Skip to content

feat: add outline raster component#11

Merged
AsPulse merged 2 commits into
mainfrom
feat/outline-component
May 25, 2026
Merged

feat: add outline raster component#11
AsPulse merged 2 commits into
mainfrom
feat/outline-component

Conversation

@AsPulse
Copy link
Copy Markdown
Member

@AsPulse AsPulse commented May 25, 2026

Adds an Outline raster effect that wraps a RasterComponent and paints a solid-colored ring around the outside of the child's alpha shape. Mirrors DropShadow in shape: it owns a width (logical units) and a color, expands paint_bounds so the stroke isn't clipped, leaves layout_box untouched, and routes the child render through ctx.render(...) so the inner subtree is memoized independently.

  • tellur-renderer::outline (new): Outline { width, color, child }. paint_bounds widens the child rect by width on all sides; layout is pass-through. render rasterizes the child once, dilates the alpha channel by width, subtracts the original alpha to leave only the ring, applies color, and composites outline then child source-over.
  • Dilation uses an axis-aligned ellipse SE rather than a separable square (Chebyshev) SE. A square SE is cheaper but flattens curved tips — the top/bottom of a circle becomes a horizontal cap — which is visually distracting on rounded shapes. The ellipse keeps the contour following the original alpha, including under anisotropic pixel ratios.
  • Dilation radii along x and y are computed independently as round(width * sx) / round(width * sy), so the output image is exactly the size of paint_bounds * (sx, sy). Using max(sx, sy) (matching the existing DropShadow pattern) would have pushed the outline past the buffer edge under anisotropic ratios and gotten silently clipped by composite_at.
  • make_outline's ring = saturating_sub(dilated, original), so pixels fully inside the child contribute zero and only the outside band carries color. color.a multiplies through, matching DropShadow's convention.
  • Example: timeline_to_mp4's BouncingDot is now Circle → Outline (white, 4px) → DropShadow, so the shadow falls behind the combined stroked shape. Added an unquantized first track (raw t) ahead of the 60/30/24/16 fps tracks so the smooth motion is the explicit baseline.
  • Outline is registered on tellur-renderer::lib and re-exported alongside DropShadow. CachingRenderContext picks it up automatically — in the example the entire Outline subtree is one miss + 1199 hits across the timeline.

@AsPulse AsPulse merged commit 5f0e5c6 into main May 25, 2026
14 checks passed
@AsPulse AsPulse deleted the feat/outline-component branch May 25, 2026 17:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant