Delphi SVG library originally by Martin Walter
ekot1 / delphisvg Goto Github PK
View Code? Open in Web Editor NEWDelphi SVG library
License: Other
Delphi SVG library
License: Other
Delphi SVG library originally by Martin Walter
Many of small and simple SVG files has incorrect draw result.
The SVG content loading and parsing is fine, but PaintTo
method incorrectly overlap pixels.
Instead of draw each of z
-ended segments separately - all segments draw with the same common pixels overlap as one shape.
Two arrows draw 2 times
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3z
M9 3L5 6.99h3V14h2V6.99h3L9 3z
m7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z
M9 3L5 6.99h3V14h2V6.99h3L9 3z"/>
</svg>
Sharping the rounded corners by different z
-separated segments.
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z
m0 16H3V5h10v4h8v10z m2-16H1v18h22V3z m-2 16H3V5h10v4h8v10z"/>
</svg>
Is it possible install on Delphi 7?
The current implementation of Delphi SVG library has an issue with floating-point-constant
parsing logic. Here is an example of fingerprint
system icon from Google material design:
The correct BNF notation provided in the SVG 1.1 spec for floating numbers is:
number:
sign? integer-constant
| sign? floating-point-constant
flag:
"0" | "1"
comma-wsp:
(wsp+ comma? wsp*) | (comma wsp*)
comma:
","
integer-constant:
digit-sequence
floating-point-constant:
fractional-constant exponent?
| digit-sequence exponent
fractional-constant:
digit-sequence? "." digit-sequence
| digit-sequence "."
exponent:
( "e" | "E" ) sign? digit-sequence
sign:
"+" | "-"
digit-sequence:
digit
| digit digit-sequence
digit:
"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
wsp:
(#x20 | #x9 | #xD | #xA)
SVG 2.0 spec still not stabilized
Hi.
SvgViewer can't show svg with style classes.
Sample svg (remove the extension .txt):
bin-1.svg.txt
Trying to change color of the text element (id=text5040) from #000000 to #0000FF.
Nothing happens, color still black.
Code:
procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then begin SVGImage1.LoadFromFile(OpenDialog1.FileName); SVGImage1.SVG.FindByID('text5040').Style.AddStyle('fill', '#0000FF'); end; end;
SVG text element: (it could be path, rectangle etc)
<text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="659.09045" y="657.46405" id="text5040">Some text</text>
Loading of some SVG files on 64-bit platform compiled code can randomly drop the next exception:
Exception class $C0000090 with message 'c0000090 FLOAT_INVALID_OPERATION'
Random crushes for the same files show that issues is related to some not initialized memory usage. Deeper investigation reveals that Result
variable is not properly initialized with zeros in some of GetBounds
calculations.
For example in SVGPath.pas:
function TSVGPathMove.GetBounds: TRectF;
begin
Result.Width := 0;
Result.Height := 0;
end;
The code above assumes that Left
and Top
properties in Result
rectangle record are initialized with zeroes, which is not true, especially on 64-bit platforms - it could be any memory garbage.
Hi, thanks for your work.
This is simplified SVG version of standart 24px assignment_turned_in
icon from two-tone material design system icon theme.
Note: the floats parsing still has issues, so I add spaces to highlight more important rendering issue.
It's better to analyse difference on 10x scale like this in SVGViewer.exe
:
FSVG.PaintTo(PaintBox1.Canvas.Handle,
MakeRect(0.0, 0.0, FSVG.Width * 10, FSVG.Height * 10), nil, 0);
This version has a correct rendering on browsers, but has an issues in library:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path opacity=".3" d="M 5 19 h 14 V 5 H 5 v 14 z m 2.41 -7.41 L 10 14.17 l 6.59 -6.59 L 18 9 l -8 8 -4 -4 1.41 -1.41 z"/>
<path d="M 18 9 l -1.41 -1.42 L 10 14.17 l -2.59 -2.58 L 6 13 l 4 4 z m 1 -6 h -4.18 C 14.4 1.84 13.3 1 12 1 c -1.3 0 -2.4 .84 -2.82 2 H 5 c -.14 0 -.27 .01 -.4 .04 -.39 .08 -.74 .28 -1.01 .55 -.18 .18 -.33 .4 -.43 .64 S 3 4.72 3 5 v 14 c 0 .27 .06 .54 .16 .78 s .25 .45 .43 .64 c .27 .27 .62 .47 1.01 .55 .13 .02 .26 .03 .4 .03 h 14 c 1.1 0 2 -.9 2 -2 V 5 c 0 -1.1 -.9 -2 -2 -2 z m -7 -.25 c .41 0 .75 .34 .75 .75 s -.34 .75 -.75 .75 -.75 -.34 -.75 -.75 .34 -.75 .75 -.75 z M 19 19 H 5 V 5 h 14 v 14 z"/>
</svg>
This version has a correct rendering in this library, but incorrectly render in browsers:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path opacity=".3" d="M 5 19 h 14 V 5 H 5 v 14 z m 2.41 -7.41 L 10 14.17 l 6.59 -6.59 L 18 9 l -8 8 -4 -4 1.41 -1.41 z"/>
<path d="M 18 9 l -1.41 -1.42 L 10 14.17 l -2.59 -2.58 L 6 13 l 4 4 z m 9 -14 h -4.18 C 14.4 1.84 13.3 1 12 1 c -1.3 0 -2.4 .84 -2.82 2 H 5 c -.14 0 -.27 .01 -.4 .04 -.39 .08 -.74 .28 -1.01 .55 -.18 .18 -.33 .4 -.43 .64 S 3 4.72 3 5 v 14 c 0 .27 .06 .54 .16 .78 s .25 .45 .43 .64 c .27 .27 .62 .47 1.01 .55 .13 .02 .26 .03 .4 .03 h 14 c 1.1 0 2 -.9 2 -2 V 5 c 0 -1.1 -.9 -2 -2 -2 z m -7 -.25 c .41 0 .75 .34 .75 .75 s -.34 .75 -.75 .75 -.75 -.34 -.75 -.75 .34 -.75 .75 -.75 z M 19 19 H 5 V 5 h 14 v 14 z"/>
</svg>
The difference is only in seconds path in m
command after first z
Correct in browsers ... z m 1 -6 ...
, correct in library ... z m 9 -14 ...
.
Somehow library incorrectly calc relative move position after z
command.
SVG file example (www.mapbox.com, "Streets" map style):
za-national-3.zip
Can be fixed something like that (SVG.pas):
1.
procedure TSVGPolyLine.ReadIn(const Node: IXMLNode);
var
S: string;
begin
inherited;
LoadString(Node, 'points', S);
S := StringReplace(AddCommaBeforePoint(S), ',', ' ', [rfReplaceAll]);
{...}
end;
2.
procedure TSVGPath.ReadIn(const Node: IXMLNode);
var
S: string;
SL: TStrings;
C: Integer;
Element: TSVGPathElement;
LastElement: TSVGPathElement;
begin
inherited;
LoadString(Node, 'd', S);
S := StringReplace(AddCommaBeforePoint(S), ',', ' ', [rfReplaceAll]);
{...}
end;
//'M5,17.5a.5.5,0,0,1-.46-.31l-4-10a.5.5,0,0,1,.23-.62l11-6a.5.5,0,0,1,.48,0l11,6a.5.5,0,0,1,.23.62l-4,10a.5.5,0,0,1-.46.31Z'
//"a.5.5,0,0,1-.46-.31" - 6 values parsed (must be 7).
//"a.5.5,0,0,1-.46-.31" => "a.5,.5,0,0,1-.46-.31"
function AddCommaBeforePoint(const AStr: UnicodeString): UnicodeString;
var s: UnicodeString; DecimalFound: boolean; ch: WideChar; i: integer;
begin
DecimalFound:=false;
for i:=1 to length(AStr) do
begin
ch:=AStr[i];
case ch of
' ','-',',','a'..'z','A'..'Z': DecimalFound:=false;
'.': begin if DecimalFound then s:=s+','; DecimalFound:=true; end;
end;
s:=s+ch;
end;
Result:=s;
end;
When you apply multiple transformations you pre-multiply the new one with the old one. See for example CalcRootMatrix where it is done correctly. However in TSVGMatrix.CalcMatrix it is done the wrong way (post-multiply the new matrix).
You need to change:
CompleteMatrix := CompleteMatrix * NewMatrix;
to
CompleteMatrix := NewMatrix * CompleteMatrix;
and
LMatrix := LMatrix * NewMatrix;
to
LMatrix := NewMatrix * LMatrix;
Hi,
I use your SvgViewer for testing.
I made a .svg with inkscape v0.92.3 - it breaks the load by
Element "text" enthält keinen einzelnen Textknoten
Trace:
:768dc54f KERNELBASE.RaiseException + 0x58
Xml.XMLDoc.XMLDocError('Element "%s" enthält keinen einzelnen Textknoten',(...))
Xml.XMLDoc.TXMLNode.CheckTextNode
Xml.XMLDoc.TXMLNode.GetText
SVG.TSVGCustomText.ReadTextNodes(TXMLNode($328C500) as IXMLNode)
SVG.TSVGText.ReadIn(TXMLNode($328C500) as IXMLNode)
SVG.TSVGBasic.ReadChildren(TXMLNode($334D740) as IXMLNode)
SVG.TSVGContainer.ReadIn(TXMLNode($334D740) as IXMLNode)
SVG.TSVGBasic.ReadChildren(TXMLNode($334FA50) as IXMLNode)
SVG.TSVG.ReadIn(TXMLNode($334FA50) as IXMLNode)
SVG.TSVG.LoadFromText(''#$D#$A'<svg'#$D#$A' xmlns:osb="http: ................
Attached a simple sample (remove the extension .txt)
inkscape.svg.txt
How to Solve?
I had issues with text position in my SVG file using inches unit.
I saw some mistakes in GetFactor function, it looks like factors are based on millimeters, ex :
suIN: Result := 25.4; ( factor between mm and inches)
must be :
suIN: Result := 96; ( factor between pixels and inches)
others unit factors are wrong (suPT must be 1.33, suEM must be 16...) https://www.w3schools.com/cssref/css_units.asp
Hi, if anyone is still using this project, I suggest to look at https://github.com/EtheaDev/SVGIconImageList
where the library of Martin Walter ha been fixed and enhanced in many aspect...
Hello, what is the licence of your code?
picture format is not recgnizing
Hello,
does this lib support fmx MacOS, linux, android, IOS?
The two attached graphics cause errors or cause the app to freeze completely.
svg_error_maps.zip
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.