SVG: write translucent paints as color plus opacity instead of rgba() - #386
Merged
Conversation
SVG 1.1 does not allow a function like rgba() where a <color> is expected, so renderers implementing SVG 1.1 rather than CSS Color 4 discard the value and fall back to the initial fill, black. Split the alpha off into a separate fill-opacity/stroke-opacity/stop-opacity property and write the color as plain hex, which both SVG 1.1 renderers and browsers understand. The alpha is never written twice: splitAlpha un-premultiplies the color and returns an opaque one, so the value in the *-opacity property is the only place the alpha appears. This was the hazard that made 7d6baa9 remove the previous fix for this (tdewolff#263). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
aldernero
force-pushed
the
svg-rgba-opacity
branch
from
August 3, 2026 03:40
079e523 to
c2750c7
Compare
Owner
|
Fantastic, thank you for the PR! |
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 #385.
The SVG renderer wrote translucent paints as
fill:rgba(58,130,246,.69803922). SVG 1.1 does not allow a function where a<color>is expected, so renderers implementing SVG 1.1 rather than CSS Color 4 discard the declaration and fall back to the initialfill— black. Browsers accept it, so it only shows up outside a browser (Inkscape, librsvg, most print/CAD toolchains).Fix
splitAlphaun-premultiplies a color into an opaque#rrggbbplus an opacity in[0,1].writePaintreturns both, and each call site writes the opacity to the matching property —fill-opacity,stroke-opacity, orstop-opacity— only when it is not1.0. Output for the issue's reproducer:Covered: path fill and stroke in both attribute and
styleform, the explicitly-drawn stroke path (strokeUnsupported), text fill inRenderTextand all three branches ofwriteFontStyle, and linear/radial gradient stops (stop-colorhad the same problem).Not writing the alpha twice
#263 fixed this in Dec 2023 and 7d6baa9 removed it in Jul 2024 as a drive-by while working on #307. I could not find a recorded failure case, but the obvious hazard is emitting the alpha in both
rgba()andfill-opacity, which darkens the result. That cannot happen here:splitAlphareturns a color withA = 255, so the alpha exists in exactly one place.TestSplitAlphapins that, and every case inTestPaintOpacityadditionally assertsrgba(never appears in the output, so this cannot regress a third time.The SVG parser in
svg.goalready handlesfill-opacity,stroke-opacityandstop-opacity, so round-tripping is unaffected.Verification
inkscape out.svg -o out.pngon the reproducer from the issue now samplessrgba(57,130,248,0.698039)inside the square, instead of solid black.go test ./renderers/svg/ ./renderers/pdf/ .passes.One leftover:
examples/go-chart/output.svgis a committed render that still contains onergba(...)from before this change. I left it alone rather than regenerate the example's four output files in this PR — happy to add that if you'd prefer.🤖 Generated with Claude Code