From 2c82e26dcb23240d50cf5926d9777ebfb53894e0 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Sun, 27 Oct 2024 03:04:55 +0100 Subject: [PATCH] when importing svg images with a svg->png filter (like rsvg-convert) keep source svg data in the image_data attribute instead of the rasterized data. This will make these images scalable and schematics will be smaller (if using small vector SVGs) --- src/draw.c | 95 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 17 deletions(-) diff --git a/src/draw.c b/src/draw.c index 0ccc525a..91e4e01c 100644 --- a/src/draw.c +++ b/src/draw.c @@ -4221,6 +4221,32 @@ int edit_image(int what, xRect *r) return 1; } +/* + * The memmem() function finds the start of the first occurrence of the + * substring 'needle' of length 'nlen' in the memory area 'haystack' of + * length 'hlen'. + * + * The return value is a pointer to the beginning of the sub-string, or + * NULL if the substring is not found. + */ +static void *my_memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen) +{ + int needle_first; + const char *p = haystack; + size_t plen = hlen; + + if (!nlen) return NULL; + needle_first = *(unsigned char *)needle; + + while (plen >= nlen && (p = memchr(p, needle_first, plen - nlen + 1))) + { + if (!memcmp(p, needle, nlen)) return (void *)p; + p++; + plen = hlen - (p - (char *)haystack); + } + return NULL; +} + /* returns a cairo surface. * `filename` should be a png or jpeg image or anything else that can be converted to png * or jpeg via a `filter` pipeline. (example: filter="gm convert - png:-") @@ -4235,6 +4261,7 @@ static cairo_surface_t *get_surface_from_file(const char *filename, const char * char *filedata = NULL; FILE *fd; struct stat buf; + int svg = 0; cairo_surface_t *surface = NULL; if(filename[0]) { @@ -4264,15 +4291,19 @@ static cairo_surface_t *get_surface_from_file(const char *filename, const char * return NULL; } } + if(my_memmem(filedata, filesize, "only_probes) return 0; xx1 = *x1; yy1 = *y1; /* image anchor point */ @@ -4377,26 +4435,28 @@ int draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, set_rect_extraptr(1, r); /* create r->extraptr pointing to a xEmb_image struct */ emb_ptr = r->extraptr; my_strncpy(filename, get_tok_value(r->prop_ptr, "image", 0), S(filename)); + my_strdup(_ALLOC_ID_, &filter, get_tok_value(r->prop_ptr, "filter", 0)); /******* read image from in-memory buffer ... *******/ if(emb_ptr && emb_ptr->image) { /* nothing to do, image is already created */ /******* ... or read PNG from image_data attribute *******/ } else if( (attr = get_tok_value(r->prop_ptr, "image_data", 0))[0] && (attr_len = strlen(attr)) > 5) { - emb_ptr->image = get_surface_from_b64data(attr, attr_len); + emb_ptr->image = get_surface_from_b64data(attr, attr_len, filter); if(!emb_ptr->image) { + my_free(_ALLOC_ID_, &filter); return 0; } /******* ... or read PNG from file (image attribute) *******/ - } else if(1 || filename[0]) { + } else if(filename[0]) { unsigned char *buffer = NULL; size_t size = 0; - char *filter = NULL; char *encoded_data = NULL; size_t olength; - my_strdup(_ALLOC_ID_, &filter, get_tok_value(r->prop_ptr, "filter", 0)); + /* if filename is a SVG file buffer will be the plain svg file content, not the filtered data */ emb_ptr->image = get_surface_from_file(filename, filter, &buffer, &size); if(!emb_ptr->image) { + my_free(_ALLOC_ID_, &filter); return 0; } /* put base64 encoded data to rect image_data attribute */ @@ -4472,6 +4532,7 @@ int draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, cairo_restore(xctx->cairo_ctx); cairo_restore(xctx->cairo_save_ctx); } + my_free(_ALLOC_ID_, &filter); #endif return 1; }