nanosvg
nanosvg copied to clipboard
Adds basic text parsing
Began work on basic text parsing, would you consider adding an improved version of this to NanoSVG..
Tabs replaced by spaces, formatting garbled. Tabs are annoying )
@lieff editor was set spaces, removed! Thanks!
Good work, If it could parse the Text
field, we can extract the those information, and draw the text in some native API. For example, all the non Text
elements can be rendered by the current implementation, and the text element can be drawn by the DrawText function from the wxWidgets
library.
@jamislike can you merge the work in year 2017 with the current head maser?
It looks like some code and structure are changed from the years.
Thanks.
2022-04-05.zip I have manually merged your work with the recent master, but I'm not sure this is OK, can you have a look at this patch file(in the attachment zip file)? Thanks.
In the patch file, I have add a comment:
@@ -1019,12 +1095,18 @@ static void nsvg__addShape(NSVGparser* p)
// Set flags
shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00);
+// should to be fixed!!!
// Add to tail
- if (p->image->shapes == NULL)
+ prev = NULL;
+ cur = p->image->shapes;
+ while (cur != NULL) {
+ prev = cur;
+ cur = cur->next;
+ }
+ if (prev == NULL)
p->image->shapes = shape;
else
- p->shapesTail->next = shape;
- p->shapesTail = shape;
+ prev->next = shape;
return;
I'm not sure what does the shapesTail
used for, since in your work, this is not used, I think this should be fixed.
I got a shape
like below: (I show this from the GDB debugger command line)
$2 = {id = "text35", '\000' <repeats 249 times>, fill = {type = 1 '\001', {color = 4278190080, gradient = 0xff000000}}, stroke = {type = 0 '\000', {color = 0, gradient = 0x0}}, opacity = 1, strokeWidth = 0.999998748, strokeDashOffset = 0, strokeDashArray = {0, 0, 0, 0, 0, 0, 0, 0}, strokeDashCount = 0 '\000', strokeLineJoin = 0 '\000', strokeLineCap = 0 '\000', miterLimit = 4, fillRule = 0 '\000', flags = 1 '\001', bounds = {0, 0, 0, 0}, paths = 0x0, group = 0x6a37b40, next = 0x0, fontFamily = "sans-serif", '\000' <repeats 53 times>, fontWeight = "sans-serif", '\000' <repeats 53 times>, fontSize = 13.2292004, isText = 1 '\001', textData = "abc", '\000' <repeats 252 times>}
When I try to parse a text field in svg file like below:
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:13.2292px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="74.839287"
y="66.523811"
id="text35"><tspan
sodipodi:role="line"
id="tspan33"
x="74.839287"
y="66.523811"
style="stroke-width:0.264583px">abc</tspan></text>
The svg file is generated by inkscape software.
It looks like the "x" and "y" coordinates is missing from the shape, are there any way to record them? Thanks.
I debugged this code for a while, and I see that in this function:
static void nsvg__parseText(NSVGparser* p, const char** attr)
{
float x = 0.0f;
float y = 0.0f;
float r = 0.0f;
float xform[6];
int i;
for (i = 0; attr[i]; i += 2) {
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
if (strcmp(attr[i], "transform") == 0)
{
nsvg__parseTransform(xform, attr[i+1]);
x = nsvg__parseCoordinate(p, attr[i+1], xform[4], 0);
y = nsvg__parseCoordinate(p, attr[i+1], xform[5], 0);
}
if (strcmp(attr[i], "font-size") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)) );
}
}
p->isText = 1;
nsvg__addShape(p);
}
The x
and y
value are correctly get, but those two variables are local variables, and I see there is no code to use them.
So, they never get saved in the shape
structure.
I have see a pull request here:
With the commits in the pull request, it has to handle the x
and 'y` in the attribute. And when adding the shape, it has such result:
[debug]> p shape->bounds
[debug]$1 = {74.8392868, 66.5238113, 74.8392868, 66.5238113}
So, the x,y coordinates of the text elements were stored in the bounds
field, so we may later to use this information to draw the text on the screen(use our own API, not the rasterization function in nanosvg, but some DrawText
like function in wxWidgets
library.).
Here is the result of my research, I extract the text elements by the nanosvg and this pull request, and draw the text elements on the rendered image. See the image below. With a comparing of the original svg image in Inkscape tool and the svg viewer window by wxWidgets.
FYI: I create a very simple project which uses wxWidgets to draw the text, see here: asmwarrior/SvgPanel: a wxPanel which can show svg image and simple text labels