-
Notifications
You must be signed in to change notification settings - Fork 133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is "M0,0L100,0ZL100,50L200,200ZL,0,200Z" 1 subpath or 3? #866
Comments
It's three.
Z just closes a sub-path. It doesn't start a new one.
If the subsequent subpath had no M, then both of those locations would be the same.
Is your confusion around the use of "current" in the above sentence? Remember the Z does not start a new path. So "current" refers to the first sub-path still. Update Reading your linked bug, it might be this line that is cousing confusion. | A path data segment (if there is one) must begin with a "moveto" command. This could be better worded. You should read this as "if the path data has any segments, then it must start with a "moveto" command." |
Functionally I can find nothing to determine any difference here. Markers, stroke-linejoin, and fills all work identically as simple and compound paths. The only implementation of this is within Inkscape which interprets Having read it several times I must conclude that it is 3 subpaths. Z does not start the new path but it does terminate the old one. Part of the confusion is the use of "next subpath" and "current subpath" when we're talking about
If a "closepath" is followed by any command it begins a new subpath. If it begins with a move, this new subpath begins at the point specified by the There's enough details to piece this together but it took a bit of reading between the lines. |
"M0,0ZZZZZZZZZZ" just creates a single subpath "M0,0Z", the extra Z's dont start any new subpath, they terminate an existing open path... if there's one. But it does not drops the initial point of the last processed subpath (so the last "M/m" position is preserved as the last "current point", not really the last "initial position" for the last subpath). A new subpath however is created by "M/m" or other non-"z/Z" commands: only these commands will see if there's an open path with a "current point": even if the path was closed, there's still the last value of the "current point" resulting from the last processed path. If you want to have multiple subpaths (because you want to use that path to derive other paths for superposing markers, possibly half-transparent), don't write "M1,2ZZZ" which just generates 1 subpath, but separate each Z by a relative moveto(0,0) or zero-length lineto, for example "M1,2Zh0Zh0Z" which generates 3 subpaths. |
An in fact, even the leading "M" command could be (or should be?) optional: all paths should behave as if there was an implicit "M0,0" prepended to it, and then "L1,2" would still be a valid path, equivalent to "M0,0L1,2" (both generating a single subpath). Butr may be a path like "l1,2" whose first command is relative should behave as if there was a prepended relative moveto, i.e. like "m0,0l1,2": the result would be a single relative path, that would still need to be positioned. As well all paths should have an implicit leading horizontal positive direction, as if in fact there was a "M-1,0M0.0", each moveto (absolute or relative sets a new direction if this effectively moves the current point to a different direction, otherwise the bearing direction would be undefined, caiusing path commands depending on the bearing to be non-significant and not rendered, and possibly raise some internal exception with some "debugging flags" enabled in the engine) |
"M0,0ZZZZZZZZZZ" just creates a single subpath "M0,0Z", --- Such is lossy and really should be 10 paths. We could pretty easily divide them up and without making the Z into their own paths or ignoring them in that fashion they would get lost from wrongly simplifying the structure. It also matters for somethings like the markers where we'd have far more end point markers there. But, not if we said it was an identical to a differentially expressed path. |
Philippe Verdy wrote:
This is not accurate. There is nothing in the spec that corroborates that statement. The spec states:
It doesn't distinguish close-path commands from other commands. So each extra Z should create a new sub-path and immediately close it. As proof, try the following test case in Firefox: https://jsfiddle.net/msqyx1k5/
You can see that the 20%-black mid markers stack on top of each other to make a darker triangle. Note: Chrome renders this test case incorrectly. Markers are drawn in incorrect places. But it does draw multiple markers indicating that it also thinks there should be multiple sub-paths. I'm going to file a Chrome bug for the redering issue. |
In Chrome adding z to marker mid adds in darkness to the marker, adding it to the marker-end causes the marker to disappear and to start it makes no change change in the overall marker. At a minimum this implies that Chrome is absolutely not ignoring additional z commands like they are meaningless. |
Just FFR, Chrome bug here: https://bugs.chromium.org/p/chromium/issues/detail?id=1295995 |
Here it is clearly laid out that move to establishes the new initial point and starts a subpath. This appears to be rather unambiguous.
Then 9.3.4 says closepath if followed by a moveto then the moveto identifies the start of the next subpath. But, this would have already been established by the definition of moveto that it always starts a subpath. This seems to open the question of what happens when a closepath is followed by something other than a moveto.
Now, this explanation of what closepath followed by a non-moveto command is increasingly confusing. The next subpath? So did the Z start that subpath or is it still in the subpath that started with the initial moveto. Does a subsequent
closepath
point to the previousclosepath
's destination or the previousmoveto
's destination.Keep in mind the first
closepath
destination is the same as the previousmoveto
destination. The implementations here do not make any functional difference for Chrome. Markers, stroke-linejoin, and fills do not reveal functional differences. The utility of themoveto
with compound paths is draw donut-like shapes but without moving a self-intersecting shape is drawn identically.If z does not start a new path and were seen as merely a lineto initial point when followed by non-move commands, then the language in 9.3.4 would seem to be a problem since the next subpath could start anywhere your next
moveto
says it starts, and would not start "at the same initial point as the current subpath". Also ifclosepath
doesn't actually close the path then some other language is problematic."A closed subpath must be closed with a "closepath" command, this "joins" the first and last path segments. Any other path is an open subpath." -- Would imply you could close the path then reopen it with a different lineto, unless the first Z marks the end of that subpath.
The text was updated successfully, but these errors were encountered: