fix(transition): stop the feather leaking, give the pill its corners, add clip-path blob - #448
Merged
Merged
Conversation
… add clip-path blob Four items from #432. A feathered wipe built its mask from the exact reveal rect, whose three non-moving edges sit on the frame boundary. MaskFilter::blur softens a shape's own edge wherever it is, so all three bled feather and band tint instead of only the edge that moves. The feathered path now extends those three sides by feather * 6 + 16, comfortably past the Gaussian's reach at sigma = feather / 3, and leaves the moving edge exactly where it was. The hard-clip fast path for an unfeathered wipe is untouched. IRIS_PILL_CORNER_FRACTION was 0.2, so a pill was a barely rounded rectangle. At 1.0 the corner radius equals the smaller half-dimension, which is a true stadium -- and a circle at aspect 1.0, which iris-transition.md already documented. The doc was right and the constant was wrong. clip-path gains a blob kind. It reuses the generator the blob transition already has rather than growing a second one: blob_local_path and scaled_mask_path become pub(crate) and nothing else moves. The documented boundary holds -- mask_transition and blob_transition still do not depend on ClipPath, because a transition has no layout box to resolve a percentage against. A transition that ignores a field now says so. The applicability table is written from apply_transition's own match arms, and a field is reported only when it differs from its default, so an unset field is never flagged -- only an explicit override that does nothing. Refs #432
A mask transition with no silhouette, or one that does not resolve to a
path, falls back to a plain fade and says so on stderr under a zero exit
code -- which reads as the transition having been ignored rather than
refused. validate now names both cases before anything renders, reusing
mask_shape_to_local_path so the check and the render agree by
construction instead of by a second opinion.
origin on mask, blob, iris and zoom_blur is in frame pixels. Writing
{ "x": 0.5, "y": 0.5 } for the centre is the natural mistake, and it
places the origin half a pixel from the top-left corner with no
complaint. A warning now says which unit the field takes and what the
centre of the frame would be.
This is the fifth item of #432, which the workstream's briefing left out.
Closes #432
The generator existed and only the transition could reach it. Both documents now say clip-path has seven shapes, and that blob is the same silhouette scaled by radius around origin rather than by a transition's progress.
12 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #432. Part of #438.
The feather leaked onto three fixed edges. A feathered wipe built its mask
from the exact reveal rect, whose three non-moving edges sit on the frame
boundary, and
MaskFilter::blursoftens a shape's own edge wherever it is. Thefeathered path now extends those three sides by
feather * 6 + 16, comfortablypast the Gaussian's reach at
sigma = feather / 3, and leaves the moving edgeexactly where it was. The hard-clip fast path for an unfeathered wipe is
untouched. Reverting it paints
[255, 140, 198]— the band colour — onto pixel(640, 3), which is the issue's own report.
The pill was a rounded rectangle.
IRIS_PILL_CORNER_FRACTIONwas0.2. At1.0the corner radius equals the smaller half-dimension, which is a truestadium — and a circle at
aspect: 1.0, whichiris-transition.mdalreadydocumented. The doc was right and the constant was wrong.
clip-pathgainsblob. It reuses the generator theblobtransitionalready has rather than growing a second one:
blob_local_pathandscaled_mask_pathbecomepub(crate)and nothing else moves. The documentedboundary holds —
mask_transitionandblob_transitionstill do not depend onClipPath, because a transition has no layout box to resolve a percentageagainst.
A transition that ignores a field now says so. The applicability table is
written from
apply_transition's own match arms, and a field is reported onlywhen it differs from its default — so an unset field is never flagged, only an
explicit override that does nothing.
The fifth item, which the workstream's briefing left out
A
maskwith no silhouette, or one that does not resolve to a path, falls backto a plain fade and says so on stderr under a zero exit code — which reads as
the transition having been ignored rather than refused.
validatenames bothcases now, reusing
mask_shape_to_local_pathso the check and the render agree byconstruction rather than by a second opinion.
originonmask,blob,irisandzoom_bluris in frame pixels. Writing{ "x": 0.5, "y": 0.5 }for the centre is the natural mistake, and it places theorigin half a pixel from the top-left corner with no complaint. A warning now says
which unit the field takes and what the centre of the frame would be.
That item was missing from the brief I wrote, not from the work: the other four
each carried a reproduction and a file pointer and this one carried neither.
Tests
Nine, each reverted and watched go red. Beyond the two quoted above:
cargo test -p rustmotion-core --lib engine::transition22 passed ·engine::paint_pass101 ·-p rustmotion-core --testsall green ·-p rustmotion --lib cli::commands::validate_schema56 passed.