Skip to content

Sample gradient stops on both sides of stitching bounds - #656

Merged
Velli20 merged 1 commit into
mainfrom
fix-gradient-stitching-stops
Oct 31, 2026
Merged

Velli20 merged 1 commit into
mainfrom
fix-gradient-stitching-stops

Conversation

@Velli20

@Velli20 Velli20 commented Oct 31, 2026

Copy link
Copy Markdown
Owner

Fixes #498

Problem

Axial and radial shadings were sampled into 16 evenly spaced color stops. gradient_many_stops.pdf uses a stitching function with 199 linear segments, so Safe-PDF drew about three smooth bands where PDFium draws 40 sharp ones.

Change

  • Function::breakpoints() returns a stitching function's /Bounds (empty for other types).
  • ColorStops::from_function_domain keeps the 16-point even grid and adds two stops at each bound inside the shading domain: the left segment's end (sampled just below the bound) and the right segment's start. Both share a position, so each handover is a hard edge and linear segments are exact. Out-of-order bounds are skipped to keep positions sorted. Shadings without stitching get the same stops as before.
  • interpolate (the web canvas CPU rasterizer) finds the segment by binary search instead of a linear scan, now that a gradient can carry hundreds of stops.

Conformance

Mismatch on the case drops from 89% to 63% and the band pattern matches PDFium. cargo conformance verify conf2-1ca6fb38db80 --allow-different exits 0. The case now fails differently (offset), which is expected: PDFium samples shading functions into a 256-entry table at t = i/256 with a floor lookup, which shifts the bands by about 3 px and never reaches t = 1 (hence its violet rather than red extended end). Safe-PDF keeps exact sampling.

No new unit test was added, per the project's testing preference. The existing pdf-function, pdf-shading and pdf-canvas tests pass, and clippy is clean.

🤖 Generated with Claude Code

Axial and radial shadings were sampled into 16 evenly spaced color stops,
so a stitching function with more segments than that aliased into a few
smooth bands. Add a stop on each side of every stitching bound inside the
shading domain, keeping each segment's ends and a hard edge at each
handover. Find the interpolation segment by binary search now that a
gradient can carry hundreds of stops.

Fixes #498

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Velli20
Velli20 merged commit 1b5ea80 into main Oct 31, 2026
10 checks passed
@Velli20
Velli20 deleted the fix-gradient-stitching-stops branch October 31, 2026 17:56
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.

[conformance] Render differs: wrong color in fill (blend Normal)

1 participant