Skip to content

fix(draw): make draw_start, draw_offset and svg path morph reach the frame - #444

Merged
LeadcodeDev merged 1 commit into
mainfrom
ws-b-path-drawing
Sep 29, 2026
Merged

LeadcodeDev merged 1 commit into
mainfrom
ws-b-path-drawing

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Closes #431. Part of #438.

Six items, five of them a declared property that rendered nothing.

draw_start on a finished stroke. Ignored on an svg whose stroke was
finished or static: the progress >= 1.0 branch delegated straight to resvg and
never consulted it. svg now folds draw_start, draw_progress and the new
draw_offset into one window, and takes the resvg shortcut only when that window
is the whole path — so a finished stroke can be permanently trimmed from its tail
by the same segment extraction used mid-reveal, with the cap, join and width it
already had.

arrow, connector, shape. The first two never read props.draw_start at
all; shape resolved only its own static field and ignored keyframes. All three
go through trim_path_between now.

The 8×8 dot at draw_progress: 0. Same fix, same cause line.rs already
solved: a dash of [draw_len, total_len - draw_len + 0.01] with draw_len = 0
and a hardcoded round cap paints a solid dot of diameter width. arrow and
connector copy line's PathMeasure extraction and return without painting on
an empty window.

draw_offset. A new AnimatedProperties field shifting both ends of the
reveal window, each clamped to [0, 1] — a comet that marches and shrinks at the
far end rather than wrapping, since trim_path_between has no two-segment model.
Animatable by keyframes and wiggle.

d keyframes with target. These could not go through the generic animation
system: KeyframeValue is Number | Color, so a path string cannot round-trip
through it, and adding "d" to KNOWN_MOTION_PROPERTIES would have been exactly
the accepted-but-inert field this repository keeps closing. svg.path_morph
mirrors shape.path_morph instead, with target naming an element id because a
document usually holds more than one path. An unmatched target falls back to the
untouched document rather than blanking the frame.

Structure mismatch: refused, not resampled. Resampling arbitrary SVG
topologies is a large piece of work that produces silently ugly interpolations,
and the repository's taste is the named refusal — the draw: true rejection is
the direct precedent. The check reuses interpolate_path_data's own mismatch
detection rather than reimplementing path math.

Known gaps, stated rather than left to be found

  • draw_offset has no effect on line. line.rs was read-only for this work
    — it is the module the others were imitating. Wiring it in is a follow-up.
  • path_morph.target matching is a substring scan for id="…", in both the
    render-time patcher and the validator. Enough for a plain <path id="…">, and
    it would miss a namespaced attribute or unusual whitespace. A real fix parses
    with usvg/roxmltree at both ends.

Tests

Render tests with pixel assertions throughout — every item reverted individually
and watched go red:

draw_progress_zero_paints_nothing_not_even_a_dot   got 124 lit pixels
draw_start_erases_the_head_of_an_already_finished  left: 255 right: 0
draw_offset_marches_the_drawn_window_along_...     left: 255 right: 0
draw_offset_is_a_recognized_keyframe_property      "unknown animation property 'draw_offset'"

cargo test -p rustmotion --lib cli::commands::validate_schema 47 passed. Clippy
and the full suite run at integration; a sibling workstream is still mid-flight.

…frame

Six items from #431, five of them a declared property that rendered
nothing.

draw_start was ignored on an svg whose stroke was finished or static:
the progress >= 1.0 branch delegated straight to resvg and never
consulted it. svg now folds draw_start, draw_progress and draw_offset
into one window, and takes the resvg shortcut only when that window is
the whole path -- so a finished stroke can be permanently trimmed from
its tail by the same segment extraction used mid-reveal.

arrow and connector never read props.draw_start at all, and shape
resolved only its own static field, ignoring keyframes. Both now trim
through trim_path_between.

The same change fixes the 8x8 dot they painted at draw_progress 0. Its
cause is the one line.rs already solved: a dash of
[draw_len, total_len - draw_len + 0.01] with draw_len = 0 and a round
cap paints a solid dot of diameter width. They copy line.rs's
PathMeasure extraction now, and return without painting on an empty
window.

draw_offset is a new AnimatedProperties field that shifts both ends of
the reveal window, each clamped to [0, 1] -- a comet that marches and
shrinks at the far end rather than wrapping. It is not wired into line,
which was read-only for this work.

Keyframes on d could not go through the generic animation system:
KeyframeValue is Number or Color, so a path string cannot round-trip
through it, and adding "d" to KNOWN_MOTION_PROPERTIES would have been
exactly the accepted-but-inert field this repository keeps closing.
svg.path_morph mirrors shape.path_morph instead, with target naming an
element id since a document usually holds more than one path.

A morph between paths of different command structure is refused at
validate rather than resampled. Resampling arbitrary SVG topologies is a
large, silently-ugly piece of work, and the repository's taste is the
named refusal -- the draw: true rejection is the direct precedent. The
check reuses interpolate_path_data's own mismatch detection rather than
reimplementing it.

Closes #431
@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 29, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 29, 2026
@LeadcodeDev
LeadcodeDev merged commit 9fdae7d into main Sep 29, 2026
4 checks passed
@LeadcodeDev
LeadcodeDev deleted the ws-b-path-drawing branch September 29, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Path drawing: draw_start on finished svg strokes, arrow/connector, draw_offset, svg d morph, dot at progress 0

1 participant