From c2081d28740e03d43b9dbbe9dbd5ac6484e8953a Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Mallo Date: Sat, 27 Jul 2024 12:52:51 +0200 Subject: Add SVG support for currentColor The currentColor special value for the fill and stroke attributes allows an image to follow the same foreground color of the surounding text. --- src/dicache.c | 5 +++-- src/html.cc | 5 ++++- src/image.cc | 8 +++++--- src/image.hh | 6 ++++-- src/nanosvg.h | 21 ++++++++++++--------- src/styleengine.cc | 2 +- src/svg.c | 11 ++++++++++- 7 files changed, 39 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/dicache.c b/src/dicache.c index 1419ff7a..c9f4067b 100644 --- a/src/dicache.c +++ b/src/dicache.c @@ -2,6 +2,7 @@ * File: dicache.c * * Copyright 2000-2007 Jorge Arellano Cid + * Copyright 2024 Rodrigo Arias Mallo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -353,7 +354,7 @@ void a_Dicache_close(DilloUrl *url, int version, CacheClient_t *Client) /* ------------------------------------------------------------------------- */ /** - * Generic MIME handler for GIF, JPEG and PNG. + * Generic MIME handler for GIF, JPEG, PNG and SVG. * Sets a_Dicache_callback as the cache-client, * and also sets the image decoder. * @@ -372,7 +373,7 @@ static void *Dicache_image(int ImgType, const char *MimeType, void *Ptr, if (!web->Image) { web->Image = - a_Image_new_with_dw(web->bw->render_layout, NULL, web->bgColor); + a_Image_new_with_dw(web->bw->render_layout, NULL, web->bgColor, 0); a_Image_ref(web->Image); } diff --git a/src/html.cc b/src/html.cc index a55fd2a8..4e2b73d1 100644 --- a/src/html.cc +++ b/src/html.cc @@ -2149,13 +2149,16 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, int tagsize) dw::Image *dw = new dw::Image(alt_ptr); image = - a_Image_new(html->dw->getLayout(), (void*)(dw::core::ImgRenderer*)dw, 0); + a_Image_new(html->dw->getLayout(), (void*)(dw::core::ImgRenderer*)dw, 0, 0); a_Image_ref(image); if (HT2TB(html)->getBgColor()) image->bg_color = HT2TB(html)->getBgColor()->getColor(); + if (HT2TB(html)->getFgColor()) + image->fg_color = HT2TB(html)->getFgColor()->getColor(); + DilloHtmlImage *hi = dNew(DilloHtmlImage, 1); hi->url = url; html->images->increase(); diff --git a/src/image.cc b/src/image.cc index c9862661..ae85569c 100644 --- a/src/image.cc +++ b/src/image.cc @@ -31,7 +31,8 @@ using namespace dw::core; /** * Create and initialize a new image structure. */ -DilloImage *a_Image_new(void *layout, void *img_rndr, int32_t bg_color) +DilloImage *a_Image_new(void *layout, void *img_rndr, + int32_t bg_color, int32_t fg_color) { DilloImage *Image; @@ -42,6 +43,7 @@ DilloImage *a_Image_new(void *layout, void *img_rndr, int32_t bg_color) Image->height = 0; Image->dpi = ((Layout *) layout)->dpiX(); Image->bg_color = bg_color; + Image->fg_color = fg_color; Image->ScanNumber = 0; Image->BitVec = NULL; Image->State = IMG_Empty; @@ -55,10 +57,10 @@ DilloImage *a_Image_new(void *layout, void *img_rndr, int32_t bg_color) * Create and initialize a new image structure with an image widget. */ DilloImage *a_Image_new_with_dw(void *layout, const char *alt_text, - int32_t bg_color) + int32_t bg_color, int32_t fg_color) { dw::Image *dw = new dw::Image(alt_text); - return a_Image_new(layout, (void*)(dw::core::ImgRenderer*)dw, bg_color); + return a_Image_new(layout, (void*)(dw::core::ImgRenderer*)dw, bg_color, fg_color); } /** diff --git a/src/image.hh b/src/image.hh index a5057227..2dc87ecc 100644 --- a/src/image.hh +++ b/src/image.hh @@ -66,6 +66,7 @@ struct _DilloImage { float dpi; /**< Dots per inch */ int32_t bg_color; /**< Background color */ + int32_t fg_color; /**< Foreground color */ bitvec_t *BitVec; /**< Bit vector for decoded rows */ uint_t ScanNumber; /**< Current decoding scan */ ImageState State; /**< Processing status */ @@ -77,9 +78,10 @@ struct _DilloImage { /* * Function prototypes */ -DilloImage *a_Image_new(void *layout, void *img_rndr, int32_t bg_color); +DilloImage *a_Image_new(void *layout, void *img_rndr, + int32_t bg_color, int32_t fg_color); DilloImage *a_Image_new_with_dw(void *layout, const char *alt_text, - int32_t bg_color); + int32_t bg_color, int32_t fg_color); void *a_Image_get_dw(DilloImage *Image); void a_Image_ref(DilloImage *Image); void a_Image_unref(DilloImage *Image); diff --git a/src/nanosvg.h b/src/nanosvg.h index e4bfa760..98b06bea 100644 --- a/src/nanosvg.h +++ b/src/nanosvg.h @@ -165,15 +165,16 @@ typedef struct NSVGimage { float width; // Width of the image. float height; // Height of the image. + unsigned current_color; // For "currentColor" NSVGshape* shapes; // Linked list of shapes in the image. } NSVGimage; // Parses SVG file from a file, returns SVG image as paths. -NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi); +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi, unsigned current_color); // Parses SVG file from a null terminated string, returns SVG image as paths. // Important note: changes the string. -NSVGimage* nsvgParse(char* input, const char* units, float dpi); +NSVGimage* nsvgParse(char* input, const char* units, float dpi, unsigned current_color); // Duplicates a path. NSVGpath* nsvgDuplicatePath(NSVGpath* p); @@ -616,7 +617,7 @@ static void nsvg__curveBounds(float* bounds, float* curve) } } -static NSVGparser* nsvg__createParser(void) +static NSVGparser* nsvg__createParser(unsigned current_color) { NSVGparser* p; p = (NSVGparser*)malloc(sizeof(NSVGparser)); @@ -646,6 +647,8 @@ static NSVGparser* nsvg__createParser(void) /* TODO: Let the user change the initial value */ p->attr[0].fontSize = 40.0f; + p->image->current_color = current_color; + return p; error: @@ -1810,7 +1813,7 @@ static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) nsvg__parseUrl(attr->fillGradient, value); } else if (strncmp(value, "currentColor", 12) == 0) { attr->hasFill = 1; - attr->fillColor = 0; /* TODO: Black by default */ + attr->fillColor = p->image->current_color; } else { attr->hasFill = 1; attr->fillColor = nsvg__parseColor(value); @@ -1827,7 +1830,7 @@ static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) nsvg__parseUrl(attr->strokeGradient, value); } else if (strncmp(value, "currentColor", 12) == 0) { attr->hasStroke = 1; - attr->strokeColor = 0; /* TODO: Black by default */ + attr->strokeColor = p->image->current_color; } else { attr->hasStroke = 1; attr->strokeColor = nsvg__parseColor(value); @@ -3097,12 +3100,12 @@ static void nsvg__createGradients(NSVGparser* p) } } -NSVGimage* nsvgParse(char* input, const char* units, float dpi) +NSVGimage* nsvgParse(char* input, const char* units, float dpi, unsigned current_color) { NSVGparser* p; NSVGimage* ret = 0; - p = nsvg__createParser(); + p = nsvg__createParser(current_color); if (p == NULL) { return NULL; } @@ -3124,7 +3127,7 @@ NSVGimage* nsvgParse(char* input, const char* units, float dpi) return ret; } -NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi, unsigned current_color) { FILE* fp = NULL; size_t size; @@ -3141,7 +3144,7 @@ NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) if (fread(data, 1, size, fp) != size) goto error; data[size] = '\0'; // Must be null terminated. fclose(fp); - image = nsvgParse(data, units, dpi); + image = nsvgParse(data, units, dpi, current_color); free(data); return image; diff --git a/src/styleengine.cc b/src/styleengine.cc index a2cb0c66..6aa99910 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -765,7 +765,7 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, a_Image_new(layout, (void*)attrs->backgroundImage ->getMainImgRenderer(), - 0xffffff); + 0xffffff, 0x000000); // we use the pageUrl as requester to prevent cross // domain requests as specified in domainrc diff --git a/src/svg.c b/src/svg.c index 98fe2ada..5536e9a3 100644 --- a/src/svg.c +++ b/src/svg.c @@ -31,6 +31,7 @@ typedef struct { DilloUrl *url; /* Primary Key for the dicache */ int version; /* Secondary Key for the dicache */ int bgcolor; /* Parent widget background color */ + int fgcolor; /* Parent widget foreground color */ } DilloSvg; /* @@ -71,9 +72,16 @@ static void Svg_write(DilloSvg *svg, void *Buf, uint_t BufSize) if (strstr(Buf, "") == NULL) return; + /* Use foreground as the current color, but transform to + * nanosvg color format (BGR). */ + unsigned fg_r = (svg->fgcolor >> 16) & 0xff; + unsigned fg_g = (svg->fgcolor >> 8) & 0xff; + unsigned fg_b = (svg->fgcolor >> 0) & 0xff; + unsigned curcolor = NSVG_RGB(fg_r, fg_g, fg_b); + /* NULL-terminate Buf */ char *str = dStrndup(Buf, BufSize); - NSVGimage *nimg = nsvgParse(str, "px", svg->Image->dpi); + NSVGimage *nimg = nsvgParse(str, "px", svg->Image->dpi, curcolor); dFree(str); if (nimg == NULL) { @@ -149,6 +157,7 @@ void *a_Svg_new(DilloImage *Image, DilloUrl *url, int version) svg->url = url; svg->version = version; svg->bgcolor = Image->bg_color; + svg->fgcolor = Image->fg_color; return svg; } -- cgit v1.2.3