Painter: currentColor support in SVG; ide: Improved/simplified SVG view

This commit is contained in:
Mirek Fidler 2025-04-23 23:09:29 +02:00
parent f43662f23c
commit b900d5e1ea
6 changed files with 71 additions and 62 deletions

View file

@ -460,15 +460,15 @@ protected:
virtual void BeginOnPathOp(double q, bool abs);
};
bool RenderSVG(Painter& p, const char *svg, Event<String, String&> resloader);
bool RenderSVG(Painter& p, const char *svg);
bool RenderSVG(Painter& p, const char *svg, Event<String, String&> resloader, Color ink = SBlack());
bool RenderSVG(Painter& p, const char *svg, Color ink = SBlack());
void GetSVGDimensions(const char *svg, Sizef& sz, Rectf& viewbox);
Rectf GetSVGBoundingBox(const char *svg);
Rectf GetSVGPathBoundingBox(const char *path);
Image RenderSVGImage(Size sz, const char *svg, Event<String, String&> resloader);
Image RenderSVGImage(Size sz, const char *svg);
Image RenderSVGImage(Size sz, const char *svg, Event<String, String&> resloader, Color ink = SBlack());
Image RenderSVGImage(Size sz, const char *svg, Color ink = SBlack());
bool IsSVG(const char *svg);

View file

@ -101,11 +101,12 @@ struct SvgParser {
BoundsPainter bp;
VectorMap<String, const XmlNode*> idmap;
VectorMap<String, String> classes;
Color currentColor = SBlack();
void Reset();
static Color GetTextColor(const String& color);
static Color GetColor(const String& text);
Color GetTextColor(const String& color);
Color GetColor(const String& text);
void ProcessValue(const String& key, const String& value);
void Style(const char *style);

View file

@ -1,5 +1,4 @@
#include "Painter.h"
#include "Painter.h"
#define LLOG(x)
@ -543,11 +542,12 @@ SvgParser::SvgParser(Painter& sw)
Reset();
}
bool ParseSVG(Painter& p, const char *svg, Event<String, String&> resloader, Rectf *boundingbox)
bool ParseSVG(Painter& p, const char *svg, Event<String, String&> resloader, Rectf *boundingbox, Color ink)
{
SvgParser sp(p);
sp.bp.compute_svg_boundingbox = boundingbox;
sp.resloader = resloader;
sp.currentColor = ink;
if(!sp.Parse(svg))
return false;
if(boundingbox)
@ -555,14 +555,14 @@ bool ParseSVG(Painter& p, const char *svg, Event<String, String&> resloader, Rec
return true;
}
bool RenderSVG(Painter& p, const char *svg, Event<String, String&> resloader)
bool RenderSVG(Painter& p, const char *svg, Event<String, String&> resloader, Color ink)
{
return ParseSVG(p, svg, resloader, NULL);
return ParseSVG(p, svg, resloader, NULL, ink);
}
bool RenderSVG(Painter& p, const char *svg)
bool RenderSVG(Painter& p, const char *svg, Color ink)
{
return RenderSVG(p, svg, Event<String, String&>());
return RenderSVG(p, svg, Event<String, String&>(), ink);
}
void GetSVGDimensions(const char *svg, Sizef& sz, Rectf& viewbox)
@ -585,12 +585,12 @@ Rectf GetSVGBoundingBox(const char *svg)
{
NilPainter nil;
Rectf bb;
if(!ParseSVG(nil, svg, Event<String, String&>(), &bb))
if(!ParseSVG(nil, svg, Event<String, String&>(), &bb, Black()))
return Null;
return bb;
}
Image RenderSVGImage(Size sz, const char *svg, Event<String, String&> resloader)
Image RenderSVGImage(Size sz, const char *svg, Event<String, String&> resloader, Color ink)
{
Rectf f = GetSVGBoundingBox(svg);
Sizef iszf = GetFitSize(f.GetSize(), Sizef(sz.cx, sz.cy) - 10.0);
@ -602,13 +602,13 @@ Image RenderSVGImage(Size sz, const char *svg, Event<String, String&> resloader)
sw.Clear(White());
sw.Scale(min(isz.cx / f.GetWidth(), isz.cy / f.GetHeight()));
sw.Translate(-f.left, -f.top);
RenderSVG(sw, svg, resloader);
RenderSVG(sw, svg, resloader, ink);
return Image(ib);
}
Image RenderSVGImage(Size sz, const char *svg)
Image RenderSVGImage(Size sz, const char *svg, Color ink)
{
return RenderSVGImage(sz, svg, Event<String, String&>());
return RenderSVGImage(sz, svg, Event<String, String&>(), ink);
}
bool IsSVG(const char *svg)

View file

@ -149,6 +149,8 @@ Color SvgParser::GetTextColor(const String& color) {
{"whitesmoke", 245, 245, 245},
{"yellow", 255, 255, 0},
{"yellowgreen", 154, 205, 50},
{"currentcolor", 0, 0, 0},
};
static VectorMap<String, Color> map;
@ -157,6 +159,11 @@ Color SvgParser::GetTextColor(const String& color) {
map.Add(colors[i].name, Color(colors[i].r, colors[i].g, colors[i].b));
}
String lc = ToLower(color);
if(lc == "currentcolor")
return currentColor;
return map.Get(color, map.Get(ToLower(color), Null));
}

View file

@ -5,50 +5,55 @@ topic "SVG support";
[0 $$4,0#96390100711032703541132217272105:end]
[i448;a25;kKO9; $$5,0#37138531426314131252341829483380:structitem]
[ $$0,0#00000000000000000000000000000000:Default]
[{_}%EN-US
[ {{10000@(113.42.0) [s0; [*@(229)4 SVG support]]}}&]
[s4;%- &]
[s2;:Upp`:`:RenderSVG`(Upp`:`:Painter`&`,const char`*`,Event`):%- [@(0.0.255) bool]
[{_}
[ {{10000@(113.42.0) [s0;%% [*@(229)4 SVG support]]}}&]
[s4; &]
[s2;:Upp`:`:RenderSVG`(Painter`&`,const char`*`,Event`,Color`): [@(0.0.255) bool]
[* RenderSVG](Painter[@(0.0.255) `&] [*@3 p], [@(0.0.255) const] [@(0.0.255) char]
[@(0.0.255) `*][*@3 svg], Event<String, String[@(0.0.255) `&]> [*@3 resloader])&]
[s2;:RenderSVG`(Painter`&`,const char`*`): [@(0.0.255) bool]_[* RenderSVG]([_^Painter^ Pain
ter][@(0.0.255) `&]_[*@3 p], [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 svg])&]
[s3; Renders [*@3 svg ]to Painter [*@3 p]. Use [*@3 resloader] to provide
resources like images, first String of callback is resource name
(filename), the data is to be returned in second parameter. Return
empty String if resource not found..&]
[s4;%- &]
[s1; &]
[s2;:GetSVGDimensions`(const char`*`,Sizef`&`,Rectf`&`): [@(0.0.255) void]_[* GetSVGDimen
sions]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 svg], [_^Sizef^ Sizef][@(0.0.255) `&]_[*@3 s
z], [_^Rectf^ Rectf][@(0.0.255) `&]_[*@3 viewbox])&]
[s3; Returns size and viewbox attributes of SVG.&]
[@(0.0.255) `*][*@3 svg], Event<String, String[@(0.0.255) `&]> [*@3 resloader],
Color ink [@(0.0.255) `=] [*@3 SBlack]())&]
[s2;:Upp`:`:RenderSVG`(Painter`&`,const char`*`,Color`): [@(0.0.255) bool]
[* RenderSVG](Painter[@(0.0.255) `&] [*@3 p], [@(0.0.255) const] [@(0.0.255) char]
[@(0.0.255) `*][*@3 svg], Color ink [@(0.0.255) `=] [*@3 SBlack]())&]
[s3; [%% Renders ][%%*@3 svg ][%% to Painter ][%%*@3 p][%% . Use ][%%*@3 resloader][%%
to provide resources like images, first String of callback is
resource name (filename), the data is to be returned in second
parameter. Return empty String if resource is not found. ][*@3 ink]
is used for SVG currentColor.&]
[s4; &]
[s1; &]
[s2;:GetSVGBoundingBox`(const char`*`): [_^Rectf^ Rectf]_[* GetSVGBoundingBox]([@(0.0.255) c
[s2;:GetSVGDimensions`(const char`*`,Sizef`&`,Rectf`&`):%% [@(0.0.255) void]_[* GetSVGDim
ensions]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 svg], [_^Sizef^ Sizef][@(0.0.255) `&]_
[*@3 sz], [_^Rectf^ Rectf][@(0.0.255) `&]_[*@3 viewbox])&]
[s3;%% Returns size and viewbox attributes of SVG.&]
[s4; &]
[s1;%% &]
[s2;:GetSVGBoundingBox`(const char`*`):%% [_^Rectf^ Rectf]_[* GetSVGBoundingBox]([@(0.0.255) c
onst]_[@(0.0.255) char]_`*[*@3 svg])&]
[s3; Computes the complete bounding box of SVG.&]
[s4; &]
[s1;%- &]
[s2;:Upp`:`:GetSVGPathBoundingBox`(const char`*`):%- [_^Upp`:`:Rectf^ Rectf]_[* GetSVGPat
hBoundingBox]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 path])&]
[s3; Returns the bounding box of [%-*@3 SVG] path stored in path element
format.&]
[s4; &]
[s1;%- &]
[s2;:Upp`:`:RenderSVGImage`(Upp`:`:Size`,const char`*`,Event`):%- Image
[s3;%% Computes the complete bounding box of SVG.&]
[s4;%% &]
[s1; &]
[s2;:Upp`:`:GetSVGPathBoundingBox`(const char`*`): [_^Upp`:`:Rectf^ Rectf]_[* GetSVGPathB
oundingBox]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 path])&]
[s3;%% Returns the bounding box of [%-*@3 SVG] path stored in path
element format.&]
[s4;%% &]
[s1; &]
[s2;:Upp`:`:RenderSVGImage`(Size`,const char`*`,Event`,Color`): Image
[* RenderSVGImage](Size [*@3 sz], [@(0.0.255) const] [@(0.0.255) char]
[@(0.0.255) `*][*@3 svg], Event<String, String[@(0.0.255) `&]> [*@3 resloader])&]
[s2;:RenderSVGImage`(Size`,const char`*`): [_^Image^ Image]_[* RenderSVGImage]([_^Size^ Siz
e]_[*@3 sz], [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 svg])&]
[s3; Renders SVG into Image. This function basically ignores dimensions
[@(0.0.255) `*][*@3 svg], Event<String, String[@(0.0.255) `&]> [*@3 resloader],
Color ink [@(0.0.255) `=] [*@3 SBlack]())&]
[s2;:Upp`:`:RenderSVGImage`(Size`,const char`*`,Color`): Image [* RenderSVGImage](Size
[*@3 sz], [@(0.0.255) const] [@(0.0.255) char] [@(0.0.255) `*][*@3 svg],
Color [*@3 ink ][@(0.0.255) `=] [*@3 SBlack]())&]
[s3; [%% Renders SVG into Image. This function basically ignores dimensions
specified in SVG and uses computed bounding box. It is then scaled
into [*@3 sz] at maximum size preserving aspect ratio. Use [*@3 resloader]
to provide resources like images.&]
[s4; &]
[s1;%- &]
[s2;:Upp`:`:IsSVG`(const char`*`):%- [@(0.0.255) bool]_[* IsSVG]([@(0.0.255) const]_[@(0.0.255) c
into ][%%*@3 sz][%% at maximum size preserving aspect ratio. Use
][%%*@3 resloader][%% to provide resources like images. ][*@3 ink]
is used for SVG currentColor.&]
[s4;%% &]
[s1; &]
[s2;:Upp`:`:IsSVG`(const char`*`): [@(0.0.255) bool]_[* IsSVG]([@(0.0.255) const]_[@(0.0.255) c
har]_`*[*@3 svg])&]
[s3; Returns true if [%-*@3 svg] likely contains SVG image.&]
[s4; &]
[s0; ]]
[s3;%% Returns true if [%-*@3 svg] likely contains SVG image.&]
[s4;%% ]]

View file

@ -44,13 +44,9 @@ struct ImageViewModule : public IdeModule {
if(IsImgFile(path)) {
if(ToLower(path).EndsWith(".svg"))
{
String svg = LoadFile(path);
Sizef sz = GetSVGBoundingBox(svg).GetSize();
while(max(sz.cx, sz.cy) < 500)
sz *= 2;
IdeImgView *d = new IdeImgView;
d->filename = path;
d->img = RenderSVGImage(sz, svg);
d->img = RenderSVGImage(Size(512, 512), LoadFile(path));
return d;
}
FileIn in(path);