Repository navigation
Sample gradient stops on both sides of stitching bounds - #656
Merged
Merged
Conversation
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>
This was referenced Nov 3, 2026
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.
Fixes #498
Problem
Axial and radial shadings were sampled into 16 evenly spaced color stops.
gradient_many_stops.pdfuses 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_domainkeeps 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-differentexits 0. The case now fails differently (offset), which is expected: PDFium samples shading functions into a 256-entry table att = i/256with a floor lookup, which shifts the bands by about 3 px and never reachest = 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-shadingandpdf-canvastests pass, and clippy is clean.🤖 Generated with Claude Code