How can I draw a svg to a SDL_Surface with nanosvg?

Started by
5 comments, last by Erik Rufelt 8 years, 3 months ago

Im trying to draw a svg to a SDL_Surface with this library:

This is my current code:

extern void nsvg_drawSVGtoSDLSurface(const char *svg_file, SDL_Surface *surface){
NSVGimage *image;
NSVGrasterizer *rast;
unsigned char *img;
int w, h;
image = nsvgParseFromFile(svg_file,"px", 96.0F);
if(image == NULL){
printf("Image not found.\n");
goto failing;
}
w = (int)image->width;
h = (int)image->height;
rast = nsvgCreateRasterizer();
if(rast == NULL){
printf("Rasterizer could not be initialized.\n");
goto failing;
}
img = malloc(w*h*4);
if(img == NULL){
printf("Image buffer could not be allocated.\n");
goto failing;
}
nsvgRasterize(rast, image, 0, 0, 1, img, w, h, w*4);
surface = SDL_CreateRGBSurfaceFrom(img, w , h, 32, 1920, 0, 0, 0, 0);
if(surface == NULL){
printf("Failed to create a surface: %s", SDL_GetError());
goto failing;
}
SDL_LockSurface(surface);
free(img);

failing:
nsvgDeleteRasterizer(rast);
nsvgDelete(image);
}

Advertisement

And what happens?

Compile error, crash, unexpected behaviour, etc?

Hello to all my stalkers.

No errors just the transparent SDLwindow.

Write the 'img' buffer to a file and open it in some image editor that supports raw files or just in a hex editor to make sure it contains somewhat proper data. If it does then the problem is in getting it onto the SDL surface, and if it doesn't then the problem is in drawing the SVG. Either way you know where to investigate.

(Also, in this case you code seems to do absolutely nothing with the SDL surface.. you create it and lock it... and.. then just exit your function? Probably some logic error there, maybe you want the surface to be a reference or have your function return a pointer to the new surface).

Was a senseless question. Anyway I removed the line that locked the sdlwindow. I tought it would fix it...

And how do I recognize if the written buffer contains proper data?

this is currently my whole code which doesnt work - has anyone improvements for it?


#include <SDL2/SDL.h>
#include <SDL2/SDL_main.h>
#include <stdio.h>

#define NANOSVG_ALL_COLOR_KEYWORDS
#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"
#include "main.h"

#define WIDTH 1280
#define HEIGTH 800

extern void drawSVGtoSDLSurface(const char *svg_file, SDL_Surface *surface, SDL_Renderer *renderer, SDL_Texture *texture){
    NSVGimage *image;
    NSVGrasterizer *rast;
    unsigned char *img;
    int w, h;
    image = nsvgParseFromFile(svg_file,"px", 96.0F);
    if(image == NULL){
        printf("Image not found.\n");
        goto failing;
    }
    w = (int)image->width;
    h = (int)image->height;
    rast = nsvgCreateRasterizer();
    if(rast == NULL){
          printf("Rasterizer could not be initialized.\n");
          goto failing;
    }
    img = malloc(w*h*4);
    if(img == NULL){
        printf("Image buffer could not be allocated.\n");
        goto failing;
    }
    nsvgRasterize(rast, image, 0, 0, 1, img, w, h, w*4);
    //surface = SDL_CreateRGBSurfaceFrom(img, w , h, 32, 1920, 0, 0, 0, 0);
    surface = img;
    texture = SDL_CreateTextureFromSurface(renderer, surface);
    if(surface == NULL){
           printf("Failed to create a surface: %s", SDL_GetError());
           goto failing;
    }
    free(img);
    SDL_FreeSurface(surface);
    failing:
    nsvgDeleteRasterizer(rast);
    nsvgDelete(image);
}

int main(int argc, char argv[]){
    if(SDL_Init(SDL_INIT_VIDEO) != 0){
        printf("Initialising SDL failed: %s", SDL_GetError());
        return -1;
    }
    SDL_Window *window;
    window=SDL_CreateWindow("WINDOW", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGTH, SDL_WINDOW_MAXIMIZED);
    if(window == NULL){
        printf("Couldn't create the window: %s", SDL_GetError());
        return -1;
    }
    SDL_Renderer *renderer;
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    SDL_Texture *tex;
    SDL_Surface *surf;
    drawSVGtoSDLSurface("../assets/textures/test.svg", surf, renderer, tex);
    while (1) {
        SDL_Event e;
        if (SDL_PollEvent(&e)) {
            if (e.type == SDL_QUIT) {
                break;
            }
        }

        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, tex, NULL, NULL);
        SDL_RenderPresent(renderer);
    }

    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyTexture(tex);
    SDL_Quit();
    return 0;
}

Try doing SDL_Texture **texture in your method signature and then *texture = SDL_CreateTexture...

You should be studying pointers and how arguments are passed and returned from your functions and learn why that is. You have similar overwriting of a passed in argument in 'surface' that you don't even need to pass to the method. These are important underlying concepts that will come up in every function you write. Even if you can get this one to work by changing a few * around it's important to learn why or the next function you write will likely have the same problem.

This topic is closed to new replies.

Advertisement