bug in SVG path rendering?

Post any defects you find in the released or beta versions of the ImageMagick software here. Include the ImageMagick version, OS, and any command-line required to reproduce the problem. Got a patch for a bug? Post it here.
Post Reply
agri
Posts: 4
Joined: 2014-10-11T07:46:04-07:00
Authentication code: 6789

bug in SVG path rendering?

Post by agri »

While working on an svg rendering program and using "convert" as reference I discovered a strange rendering bug.

In the specific the "path" command handles among other things
- c (bezier cubic arcs with 2 control points)
- s (bezier cubic arcs with one control point automatically computed from previous data)
- v (vertical line)
- h (horizontal line)
- l (line)

The bug is about "v" handling of previous control point data:
- with the sequence "...c...s..." the previous control point data is handled correctly.
- with "...c...h0s..." the control point from previous C command is ignored (IMO correctly)
- with "...c...l0,0s..." the control point from previous C command is ignored (IMO correctly)
- with "...c...v0s..." the control point from previous C command is instead used (IMO incorrectly)

What is very strange for me is that I don't see any difference in the handling of "v" command in respect to "h" or "l" commands to justify this behavior in the code (draw.c).

To reproduce the problem you can render

Code: Select all

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 300" version="1.1">
  <path fill="#AAA" stroke="#F00" d="m100,100c100,0,100,100,0,100s-100,50,0,50z"/>
  <path fill="#AAA" stroke="#F00" d="m300,100c100,0,100,100,0,100h0s-100,50,0,50z"/>
  <path fill="#AAA" stroke="#F00" d="m500,100c100,0,100,100,0,100v0s-100,50,0,50z"/>
</svg>
that produces
Image

As a curiosity this rendering bug is also visible on what's probably the lenna of svgs (the tiger) in the bottom part of the picture, and this is where I found the problem (while looking for why my rendering was different from convert result).

Image
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: bug in SVG path rendering?

Post by snibgo »

Interesting. I agree, the "v" has a bug.

If I render with Inkscape, my 2nd and 3rd curves look like your 2nd.

The SVG v1.1 spec http://www.w3.org/TR/SVG/paths.html says for "s":
The first control point is assumed to be the reflection of the second control point on the previous command relative to the current point. (If there is no previous command or if the previous command was not an C, c, S or s, assume the first control point is coincident with the current point.)
So the 2nd and 3rd cases for "s" should "assume the first control point is coincident with the current point".

So I think the Inkscape rendering is correct, and the 2nd curve in your IM rendering is correct, but the third (with "v") is wrong.
snibgo's IM pages: im.snibgo.com
agri
Posts: 4
Joined: 2014-10-11T07:46:04-07:00
Authentication code: 6789

Re: bug in SVG path rendering?

Post by agri »

Hmmm... this means that also MY rendering has a bug because I also reflect the control point from quadratic arcs (Qq/Tt) :(

What is strange is that the source code for handing "H" is the exact copy of the code handling "V" and yet "H" handles it correctly.

Am I missing something or draw.c is not the correct place to look in?
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: bug in SVG path rendering?

Post by snibgo »

agri wrote:What is very strange for me is that I don't see any difference in the handling of "v" command in respect to "h" or "l" commands to justify this behavior in the code (draw.c).
I could be wrong, but I think the code in draw.c is only used in a "-draw" command, such as:

Code: Select all

%IM%convert -size 600x300 xc: ^
  -fill #888 ^
  -stroke Red ^
  -draw "path 'm100,100c100,0,100,100,0,100s-100,50,0,50z'" ^
  -draw "path 'm300,100c100,0,100,100,0,100h0s-100,50,0,50z'" ^
  -draw "path 'm500,100c100,0,100,100,0,100v0s-100,50,0,50z'" ^
  p.png
I think this should give the same reslut as the SVG with Inkscape, but doesn't. I suspect a bug in the lines ...

Code: Select all

          if (strchr("CcSs",last_attribute) == (char *) NULL)
            {
              points[0]=points[2];
              points[1]=points[3];
            }
... where I think only one point should be set, not two.
snibgo's IM pages: im.snibgo.com
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: bug in SVG path rendering?

Post by snibgo »

agri wrote:While working on an svg rendering program and using "convert" as reference ...
"convert" uses one of three renderers: MSVG, RSVG or Inkscape. The slowest of these is Inkscape, but it is often more correct than the others. When they make different outputs, I have always found Inkscape to be the correct one.
snibgo's IM pages: im.snibgo.com
agri
Posts: 4
Joined: 2014-10-11T07:46:04-07:00
Authentication code: 6789

Re: bug in SVG path rendering?

Post by agri »

I think i found the bug. It's in rsvg: the code in rsvg-path.c goes

Code: Select all

    case 'h':
        /* horizontal lineto */
        if (ctx->param == 1) {
            rsvg_path_builder_line_to (&ctx->builder, ctx->params[0], ctx->cp.point.y);
            ctx->cp.point.x = ctx->rp.point.x = ctx->params[0];
            ctx->param = 0;
        }
        break;
    case 'v':
        /* vertical lineto */
        if (ctx->param == 1) {
            rsvg_path_builder_line_to (&ctx->builder, ctx->cp.point.x, ctx->params[0]);
            ctx->cp.point.y = ctx->rp.point.y = ctx->params[0];
            ctx->param = 0;
        }
        break;
As you can notice the code for "v" it sets only the "y" for "cp" (i suppose the "current point") and this is correct, but also only the "y" for "rp" (I suppose the "reference point") and this is not correct. Indeed both "h" and "v" are buggy as it's shown in this case

Code: Select all

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 300" version="1.1">
  <path fill="#AAA" stroke="#F00" d="m100,50c100,0,100,100,0,150s-100,50,0,50z"/>
  <path fill="#AAA" stroke="#F00" d="m300,50c100,0,100,100,0,150h0s-100,50,0,50z"/>
  <path fill="#AAA" stroke="#F00" d="m500,50c100,0,100,100,0,150v0s-100,50,0,50z"/>
  <path fill="#AAA" stroke="#F00" d="m700,50c100,0,100,100,0,150l0,0s-100,50,0,50z"/>
</svg>
that renders as Image

where only the last shape (l0,0) is correct because the 2nd fails to zero the y of last reference point and the 3rd fails to zero the x component.

I'll file a bug later tonight.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: bug in SVG path rendering?

Post by fmw42 »

Are you using the latest RSVG version. If not perhaps try upgrading it.
agri
Posts: 4
Joined: 2014-10-11T07:46:04-07:00
Authentication code: 6789

Re: bug in SVG path rendering?

Post by agri »

The bug is present in current git master... that's where I found it by looking at the source code.
Post Reply