Align path validity with SVG: only the first subpath requires a MoveTo#565
Align path validity with SVG: only the first subpath requires a MoveTo#565tomcur wants to merge 5 commits into
MoveTo#565Conversation
This matches SVG semantics: > A path data segment (if there is one) must begin with a "moveto" command. And: > If a "closepath" is followed immediately by a "moveto", then the "moveto" identifies the start point of the next subpath. If a "closepath" is followed immediately by any other command, then the next subpath starts at the same initial point as the current subpath.
|
This will likely lead to additional follow-up changes to add support for the implied MoveTo after ClosePath. I've noticed the following so far: It looks like we weren't very consistent in supporting this in the past. |
| /// A subpath of a [`BezPath`]. | ||
| /// | ||
| /// Returned by [`BezPath::subpaths`]. See | ||
| /// [`BezPath`'s documentation on elements and segments][BezPath#elements-and-segments] | ||
| /// for more information. | ||
| #[derive(Debug, Clone, Copy, PartialEq)] | ||
| pub struct Subpath<'a> { | ||
| start: Point, | ||
| elements: &'a [PathEl], | ||
| } |
There was a problem hiding this comment.
Subpaths started after a Close without a MoveTo need to know the where the previous subpath ends (or equivalently, where that subpath started). This perhaps would be the main argument in favor of not aligning with SVG, as always requiring an explicit MoveTo would allow taking &[PathEl] slices from the BezPath and having them be valid paths without further context.
Note that if we want such semantics, we may still want to update code (and improve docs) as Kurbo currently is not consistent and does different things in different places.
BezPath::segments does the SVG-aligned thing:
Lines 853 to 859 in 0c31f87
BezPath::get_seg returns None (even though BezPath::segments does return the segment):
Lines 330 to 336 in 0c31f87
BezPath::moments also does the SVG-aligned thing:
Lines 554 to 559 in 0c31f87
BezPath::current_position requires all subpaths to start with MoveTo (otherwise it treats the first element as if it were a MoveTo:
Lines 402 to 422 in 0c31f87
Shape for &'a [PathEl] similarly treats the first drawing command in case of a missing MoveTos as a MoveTo:
Lines 1444 to 1448 in 0c31f87
|
I believe things are now consistent (or at least mostly consistent). There actually is an argument for keeping the requirement that subpaths start with I can see two possible behaviors in case of missing
E.g., Skia does the latter https://api.skia.org/classSkPath.html#a27c6505cd16db954d6f0268e2de5d87f. On current |
|
I think that being able to refer to subpaths without additional context is more valuable than the flexibility of omitting some MoveTos. Plus, paths are quite a bit easier to use if they don't require as much state tracking by the consumer.
IMO that'll lead to annoying to debug issues in user code. In addition to slicing paths, we should also consider the semantics of concatenating paths. But I am not sure that any model that permits omitting MoveTo makes intuitive sense in that context. However, starting at the previous subpath's start point seems to rank rather low on expectedness, IMHO. |
In a vacuum I completely agree with this statement.
While I agree, I think following SVG's model should be the "default" unless arguments against are strong enough (which they may be in this case).
Another way to think about SVG's model is that you always continue from the current point: a |
Match SVG semantics:
And: