diff options
Diffstat (limited to 'svg.c')
| -rw-r--r-- | svg.c | 80 | 
1 files changed, 47 insertions, 33 deletions
| @@ -9,47 +9,60 @@  #include "log.h"  #include "stride.h" -pixman_image_t * +struct NSVGimage *svg_image = NULL; +struct NSVGrasterizer *rast = NULL; + +bool  svg_load(FILE *fp, const char *path)  { -    pixman_image_t *pix = NULL; -    uint8_t *data = NULL; -    int width, height, stride; -    bool ok = false; -    struct NSVGimage *image = NULL; -    struct NSVGrasterizer *rast = NULL; - -    image = nsvgParseFromFile(path, "px", 96); -    width = image->width; -    height = image->height; -    if (width == 0 || height == 0) { +    svg_image = nsvgParseFromFile(path, "px", 96); +    if (svg_image == NULL) +        return false; +    if (svg_image->width == 0 || svg_image->height == 0) {          LOG_DBG("%s: width and/or heigth is zero, not a SVG?", path); -        nsvgDelete(image); -        return NULL; +        nsvgDelete(svg_image); +        svg_image = NULL; +        return false;      } -    stride = stride_for_format_and_width(PIXMAN_a8b8g8r8, image->width); +    rast = nsvgCreateRasterizer(); +    if (rast == NULL) +        return false; +    return true; +} + +pixman_image_t * +svg_render(const int width, const int height) +{ +    pixman_image_t *pix = NULL; +    uint8_t *data = NULL; +    int stride = stride_for_format_and_width(PIXMAN_a8b8g8r8, width);      if (!(data = calloc(1, height * stride))) -        goto out; +        return NULL; + +    double sx = width / (double)svg_image->width; +    double sy = height / (double)svg_image->height; -    if (!(rast = nsvgCreateRasterizer())) -        goto out; +    float s = sx > sy ? sy : sx; -    nsvgRasterize(rast, image, 0, 0, 1, data, width, height, stride); +    float tx = (width - svg_image->width * s) / 2; +    float ty = (height - svg_image->height * s) / 2; -    ok = NULL != (pix = pixman_image_create_bits_no_clear( -            PIXMAN_a8b8g8r8, width, height, (uint32_t *)data, stride)); +    nsvgRasterize(rast, svg_image, tx, ty, s, data, width, height, stride); -    if (!ok) { -        LOG_ERR("%s: failed to instanciate pixman image", path); -        goto out; +    pix = pixman_image_create_bits_no_clear(PIXMAN_a8b8g8r8, width, +        height, (uint32_t *)data, stride); +    if (pix == NULL) { +        LOG_ERR("failed to render svg image"); +        free(data); +        return NULL;      }      /* Copied from fuzzel */      /* Nanosvg produces non-premultiplied ABGR, while pixman expects       * premultiplied */      for (uint32_t *abgr = (uint32_t *)data; -         abgr < (uint32_t *)(data + (size_t)image->width * (size_t)image->height * 4); +         abgr < (uint32_t *)(data + (size_t)width * (size_t)height * 4);           abgr++) {          uint8_t alpha = (*abgr >> 24) & 0xff;          uint8_t blue = (*abgr >> 16) & 0xff; @@ -70,13 +83,14 @@ svg_load(FILE *fp, const char *path)          *abgr = (uint32_t)alpha << 24 | blue << 16 | green << 8 | red;      } -out: -    if (image) -        nsvgDelete(image); -    if (rast) -        nsvgDeleteRasterizer(rast); - -    if (!ok) -        free(data);      return pix;  } + +void +svg_free() +{ +    if (svg_image != NULL) +        nsvgDelete(svg_image); +    if (rast != NULL) +        nsvgDeleteRasterizer(rast); +} | 
