[cairo] Q: gtk_main() and svg_cairo_parse()
Michael N. Filippov
michael at idisys.iae.nsk.su
Mon Oct 3 22:26:45 PDT 2005
Michael N. Filippov wrote:
> Hello!
>
> I tried to compile a very simple code (based on libsvg.cairo from
> cairo-demo/cairo_snippets, see below) with libcairo2-dev_1.0.0-3,
> libsvg-cairo1-dev_0.1.6-5 and libgtk2.0-dev_2.6.10-1 (also tried 2.8.3)
> and noticed that if gtk_main() is called before svg_cairo_parse() then
> the PNG picture looks bad (no shadows, yellow border is below the window
> etc). But if gtk_init() is called after svg_cairo_parse(), everything is
> fine. Did I miss something about API, environment variables or something
> else? Any help would be greatly appreciated.
>
> Thanks in advance,
>
> Michael
>
>
> #include <gtk/gtk.h>
> #include <svg-cairo.h>
>
> int main(int argc, char* argv[])
> {
> double IMAGE_WIDTH = 256;
> double IMAGE_HEIGHT = 256;
> cairo_surface_t* surface = cairo_image_surface_create(
> CAIRO_FORMAT_ARGB32, IMAGE_WIDTH, IMAGE_HEIGHT);
> cairo_t* cr = cairo_create(surface);
> cairo_scale(cr, IMAGE_WIDTH, IMAGE_HEIGHT);
> svg_cairo_t* svgc;
> svg_cairo_create(&svgc);
> gtk_init(&argc, &argv); // 1) doesn't work
> svg_cairo_parse(svgc, "data/home.svg");
> // gtk_init(&argc, &argv); // 2) works
> unsigned w, h;
> svg_cairo_get_size(svgc, &w, &h);
> cairo_scale(cr, 1.0 / w, 1.0 / h);
> svg_cairo_render(svgc, cr);
> svg_cairo_destroy(svgc);
> cairo_surface_write_to_png(surface, "out.png");
> cairo_destroy(cr);
> cairo_surface_destroy(surface);
> return 0;
> }
> _______________________________________________
> cairo mailing list
> cairo at cairographics.org
> http://cairographics.org/cgi-bin/mailman/listinfo/cairo
Hello again!
Seems I found the problem (solution attached): it's a bug in
_svg_ascii_strtod() (libsvg-0.1.4/src/svg_ascii.c).
Example:
>~/work/svg/test$ LC_ALL=C ./main
decimal_point: '.'
Result: _svg_ascii_strtod("0,123.456", NULL) = 0
>~/work/svg/test$ LC_ALL=ru_RU.KOI8-R ./main
decimal_point: ','
Result: _svg_ascii_strtod("0,123.456", NULL) = 0,123
Details:
if input parameter nptr == 0,123.456 and current locale decimal_point ==
",",
then after /* Skip leading space */ decimal_point_pos == NULL, stdlib
strtod("0,123.456") is called and result is 0.123 (should be 0).
Solution:
Own strtod function for SVG numbers (I think it is much better than hack
to use locale dependent std::strtod).
According to http://www.w3.org/TR/2003/REC-SVG11-20030114/paths.html:
number:
sign? integer-constant
| sign? floating-point-constant
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"
So the new procedure is very simple (see below). I had to add couple of
if's to make it fully compatible with std::strtod(). Attached main.c
contains this procedure and code to compare results with std::strtod().
double
_svg_ascii_strtod (const char *nptr,
const char **endptr)
{
const char *p = nptr;
const char *end = p;
double value = 0;
int sign = 1;
double factor;
int exp;
while (_svg_ascii_isspace (*p))
p++;
switch (*p)
{
case '-':
sign = -1;
/* FALLTHRU */
case '+':
++p;
}
while (_svg_ascii_isdigit (*p))
{
value = value * 10 + (*p - '0');
end = ++p;
}
if (*p == '.')
{
++p;
if (end != nptr) /* digits. */
end = p;
else
{
if (!_svg_ascii_isdigit (*p))
goto exit;
}
factor = 1;
while (_svg_ascii_isdigit (*p))
{
factor *= 0.1;
value += (*p - '0') * factor;
end = ++p;
}
}
if (end != nptr && (*p == 'e' || *p == 'E'))
{
++p;
factor = 10;
switch (*p)
{
case '-':
factor = 0.1;
/* FALLTHRU */
case '+':
++p;
}
exp = 0;
while (_svg_ascii_isdigit (*p))
{
exp = exp * 10 + (*p - '0');
end = ++p;
}
if (value != 0) /* 0e1000 */
{
while (1)
{
if (exp & 1)
value *= factor;
if ((exp >>= 1) == 0)
break;
factor *= factor;
}
}
}
exit:
if (endptr)
*endptr = end;
if (end == nptr) /* "-a" gives 0 */
return 0;
return value * sign;
}
Best regards,
Michael
-------------- next part --------------
A non-text attachment was scrubbed...
Name: bad.png
Type: image/png
Size: 12491 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20051004/8c15b364/bad-0001.png
-------------- next part --------------
A non-text attachment was scrubbed...
Name: good.png
Type: image/png
Size: 13059 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20051004/8c15b364/good-0001.png
-------------- next part --------------
A non-text attachment was scrubbed...
Name: main.c.gz
Type: application/x-gzip
Size: 1597 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20051004/8c15b364/main.c-0001.bin
More information about the cairo
mailing list