Hi,
Can someone quickly remind me what the problem is with the current SVG 'z' syntax to close a path?
Thanks,
Tav
On 9-9-2012 12:15, Tavmjong Bah wrote:
Hi,
Can someone quickly remind me what the problem is with the current SVG 'z' syntax to close a path?
I believe the 'problem' is that 'z' is not only a flag to tell the path is closed, it is also used to actually close the path with a straight line segment if the start and end points don't align. In our implementation (2geom), this implicit closing line segment is always there, also if the start and end points are equal. For new 2geom programmers, this can be confusing as the path length given by 2geom may not be the number of segments one sees in Inkscape. One always has to check for 'degenerate' (zero length) path segments.
Ciao, Johan
On 09-09-12 14:13, Johan Engelen wrote:
On 9-9-2012 12:15, Tavmjong Bah wrote:
Hi,
Can someone quickly remind me what the problem is with the current SVG 'z' syntax to close a path?
I believe the 'problem' is that 'z' is not only a flag to tell the path is closed, it is also used to actually close the path with a straight line segment if the start and end points don't align. In our implementation (2geom), this implicit closing line segment is always there, also if the start and end points are equal. For new 2geom programmers, this can be confusing as the path length given by 2geom may not be the number of segments one sees in Inkscape. One always has to check for 'degenerate' (zero length) path segments.
Additionally, it leads to some funky problems in Inkscape's UI. Essentially, if a closed path starts and "ends" with a cubic Bézier, we try to hide the fact that there is actually another (zero-length) line segment in between. However, if you then use relative coordinates, or do other things that might lead to small numerical differences between the start and "end" node, then you suddenly do see the extra closing line segment (even though the structure of the path has not changed).
On 10/09/2012 09:24, Jasper van de Gronde wrote:
On 09-09-12 14:13, Johan Engelen wrote:
On 9-9-2012 12:15, Tavmjong Bah wrote:
Hi,
Can someone quickly remind me what the problem is with the current SVG 'z' syntax to close a path?
I believe the 'problem' is that 'z' is not only a flag to tell the path is closed, it is also used to actually close the path with a straight line segment if the start and end points don't align. In our implementation (2geom), this implicit closing line segment is always there, also if the start and end points are equal. For new 2geom programmers, this can be confusing as the path length given by 2geom may not be the number of segments one sees in Inkscape. One always has to check for 'degenerate' (zero length) path segments.
Additionally, it leads to some funky problems in Inkscape's UI. Essentially, if a closed path starts and "ends" with a cubic Bézier, we try to hide the fact that there is actually another (zero-length) line segment in between. However, if you then use relative coordinates, or do other things that might lead to small numerical differences between the start and "end" node, then you suddenly do see the extra closing line segment (even though the structure of the path has not changed).
Related side-effect (AFAIU): mid-markers may differ for closed shapes
- Closed shapes with straight line segments only (e.g. polygons/stars) no longer render an additional mid-marker at the start-/ end-node with current (optimized) path data - see bug #403445 [1].
- Circle/ellipses render an unexpected mid-marker at the start-/ end-node, and 'orient="auto"' causes it to be misaligned wrt the outline of the shape.
- Objects based e.g. on rectangles with rounded corners may produce arbitrary results (depending on the type of last path segment - see bug #623739 [2]).
~suv
[1] https://bugs.launchpad.net/inkscape/+bug/403445 [2] https://bugs.launchpad.net/inkscape/+bug/623739
On 10-9-2012 10:33, ~suv wrote:
On 10/09/2012 09:24, Jasper van de Gronde wrote:
On 09-09-12 14:13, Johan Engelen wrote:
On 9-9-2012 12:15, Tavmjong Bah wrote:
Hi,
Can someone quickly remind me what the problem is with the current SVG 'z' syntax to close a path?
I believe the 'problem' is that 'z' is not only a flag to tell the path is closed, it is also used to actually close the path with a straight line segment if the start and end points don't align. In our implementation (2geom), this implicit closing line segment is always there, also if the start and end points are equal. For new 2geom programmers, this can be confusing as the path length given by 2geom may not be the number of segments one sees in Inkscape. One always has to check for 'degenerate' (zero length) path segments.
Additionally, it leads to some funky problems in Inkscape's UI. Essentially, if a closed path starts and "ends" with a cubic Bézier, we try to hide the fact that there is actually another (zero-length) line segment in between. However, if you then use relative coordinates, or do other things that might lead to small numerical differences between the start and "end" node, then you suddenly do see the extra closing line segment (even though the structure of the path has not changed).
Related side-effect (AFAIU): mid-markers may differ for closed shapes
- Closed shapes with straight line segments only (e.g. polygons/stars)
no longer render an additional mid-marker at the start-/ end-node with current (optimized) path data - see bug #403445 [1].
- Circle/ellipses render an unexpected mid-marker at the start-/
end-node, and 'orient="auto"' causes it to be misaligned wrt the outline of the shape.
- Objects based e.g. on rectangles with rounded corners may produce
arbitrary results (depending on the type of last path segment - see bug #623739 [2]).
~suv
[1] https://bugs.launchpad.net/inkscape/+bug/403445 [2] https://bugs.launchpad.net/inkscape/+bug/623739
Ah, I remember now the problems when working on markers indeed! Good catch suv. Where to put markers on closed paths is ill-defined in the SVG spec (last time I checked is a while ago). See the markers.svg testcase in our testsuite.
What would help is to explicitly state in the SVG spec the behavior for closed paths with equal endpoints and closed paths with not equal endpoints (and hence 'z' implies an extra segment). I think changing the path spec is more work.
Ciao, Johan
On 10-9-2012 9:24, Jasper van de Gronde wrote:
On 09-09-12 14:13, Johan Engelen wrote:
On 9-9-2012 12:15, Tavmjong Bah wrote:
Hi,
Can someone quickly remind me what the problem is with the current SVG 'z' syntax to close a path?
I believe the 'problem' is that 'z' is not only a flag to tell the path is closed, it is also used to actually close the path with a straight line segment if the start and end points don't align. In our implementation (2geom), this implicit closing line segment is always there, also if the start and end points are equal. For new 2geom programmers, this can be confusing as the path length given by 2geom may not be the number of segments one sees in Inkscape. One always has to check for 'degenerate' (zero length) path segments.
Additionally, it leads to some funky problems in Inkscape's UI. Essentially, if a closed path starts and "ends" with a cubic Bézier, we try to hide the fact that there is actually another (zero-length) line segment in between. However, if you then use relative coordinates, or do other things that might lead to small numerical differences between the start and "end" node, then you suddenly do see the extra closing line segment (even though the structure of the path has not changed).
Indeed, but I think these are Inkscape issues that not necessarily SVG induced ;)
Ciao, Johan
On 10-09-12 13:50, Johan Engelen wrote:
On 10-9-2012 9:24, Jasper van de Gronde wrote:
On 09-09-12 14:13, Johan Engelen wrote:
On 9-9-2012 12:15, Tavmjong Bah wrote:
Hi,
Can someone quickly remind me what the problem is with the current SVG 'z' syntax to close a path?
...
Additionally, it leads to some funky problems in Inkscape's UI. Essentially, if a closed path starts and "ends" with a cubic Bézier, we try to hide the fact that there is actually another (zero-length) line segment in between. However, if you then use relative coordinates, or do other things that might lead to small numerical differences between the start and "end" node, then you suddenly do see the extra closing line segment (even though the structure of the path has not changed).
Indeed, but I think these are Inkscape issues that not necessarily SVG induced ;)
Not really, the way 'z' is interpreted now, Inkscape either has to rely on exact(!) coincidence of the start and end node to hide the fact that there really is another segment, or now and then show an, that users cannot get rid of (and complicates selecting nodes and so on).
(Good of ~suv to think of markers btw, that's even more serious.)
2012/9/10 Jasper van de Gronde <th.v.d.gronde@...528...>:
Not really, the way 'z' is interpreted now, Inkscape either has to rely on exact(!) coincidence of the start and end node to hide the fact that there really is another segment, or now and then show an, that users cannot get rid of (and complicates selecting nodes and so on).
I previously wrote this in an accidentally off-list response: the workaround to this problem is to always write out the moveto command that starts a new subpath and the last point of the last segment in absolute coordinates. This way the start and end nodes will always coincide exactly.
A better solution would be to allow 'z' not only as a segment, but also in place of the last coordinate. For example: d="M 1,1 ... C 4,3 2,2 z" would be equivalent to "M 1,1 ... C 4,3 2,2 1,1 z".
Regards, Krzysztof
On 10-09-12 17:19, Krzysztof Kosiński wrote:
2012/9/10 Jasper van de Gronde <th.v.d.gronde@...528...>:
Not really, the way 'z' is interpreted now, Inkscape either has to rely on exact(!) coincidence of the start and end node to hide the fact that there really is another segment, or now and then show an, that users cannot get rid of (and complicates selecting nodes and so on).
I previously wrote this in an accidentally off-list response: the workaround to this problem is to always write out the moveto command that starts a new subpath and the last point of the last segment in absolute coordinates. This way the start and end nodes will always coincide exactly.
There are more esoteric things that can cause slight numerical problems, but that suggestion would indeed solve the vast majority of cases. If anyone wants to beat me to it, in src/svg/path-string.h, around line 133 you should change the closePath method to this:
PathString &closePath() { commonbase += _abs_state.str; _abs_state.str.clear(); _rel_state = _abs_state; _abs_state.appendOp('Z'); _rel_state.appendOp('z'); _rel_state.switches++; _current_point = _initial_point; return *this; }
The path string code basically always tries using both relative and absolute coordinates, and the above says that if we close the path, that we always want to use absolute coordinates for the previous segment. This is obviously suboptimal, but only impacts closed (sub)paths, and is still optimal within the constraint of wanting the last segment before the close path command to use absolute coordinates.
But still, the point is that SVG does have somewhat the ambition of being an "editable" format, thus making it highly desirable to not force such hacks on to an editor.
A better solution would be to allow 'z' not only as a segment, but also in place of the last coordinate. For example: d="M 1,1 ... C 4,3 2,2 z" would be equivalent to "M 1,1 ... C 4,3 2,2 1,1 z".
Indeed. Or, alternatively, one could regard z as being a "lineto" with an implicit end coordinate, and then add similar commands (w, x, y, for example) corresponding to quadratic, cubic and elliptic segments.
On 2012-09-10 17:19, Krzysztof Kosiński wrote:
2012/9/10 Jasper van de Gronde <th.v.d.gronde@...528...>:
Not really, the way 'z' is interpreted now, Inkscape either has to rely on exact(!) coincidence of the start and end node to hide the fact that there really is another segment, or now and then show an, that users cannot get rid of (and complicates selecting nodes and so on).
I previously wrote this in an accidentally off-list response: the workaround to this problem is to always write out the moveto command that starts a new subpath and the last point of the last segment in absolute coordinates. This way the start and end nodes will always coincide exactly.
I've checked in a change that accomplishes this. It does not try to be "smart" about it, so it simply always ensures the last segment before a close-path is absolute. It would be quite easy to add a check to see whether the current point equals the initial point, but of course then the question again becomes whether this should be an exact check or not, and if not, what the tolerance would have to be, etc., etc. On the other hand, the current choice should have a pretty small impact, and is extremely simple.
participants (5)
-
Jasper van de Gronde
-
Johan Engelen
-
Krzysztof Kosiński
-
Tavmjong Bah
-
~suv