Skip to content

SVG: read hsl() and hsla() colors - #2171

Merged
andersonhc merged 6 commits into
py-pdf:masterfrom
RavSinghChandan:svg-hsl-colors
Nov 13, 2026
Merged

andersonhc merged 6 commits into
py-pdf:masterfrom
RavSinghChandan:svg-hsl-colors

Conversation

@RavSinghChandan

Copy link
Copy Markdown

fill="hsl(120, 100%, 25%)" fails with ValueError: unsupported color specification hsl(120, 100%, 25%). hsl() is a common way to write colors in stylesheets, and Mermaid computes the colors of its themes as hsl(...) strings.

svgcolor() now reads hsl() and hsla(), with commas or space-separated with an optional / A, as in CSS Color 4: the hue may have an angle unit (deg, grad, rad, turn), a saturation or lightness without % is a percentage, and the alpha is a number from 0 to 1 or a percentage. The channels are rounded to 8 bits as browsers do, so hsl(120, 100%, 25%) is #008000.

Added four cases to test_svg_attribute_conversion: hsl(), hsl() space-separated with a turn hue and an alpha, an uppercase hsla() stroke and an invalid hsl(). The first three fail on master. The SVG tests, black, pylint and mypy pass

@andersonhc andersonhc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small things I noticed:

  • Could we preserve the floating-point RGB values instead of rounding to 8 bits? DeviceRGB supports them, and Python’s rounding gives some unexpected results: hsl(0 0% 30%) becomes #4c4c4c rather than #4d4d4d, while very dark colors can become black.
  • The changelog entry landed under the released 2.9.0 section. Could you move it to the unreleased 2.9.1 section?

DeviceRGB takes fractions, so rounding to 8 bits only lost precision:
hsl(0 0% 30%) was #4c4c4c instead of 0.3 gray.
@RavSinghChandan

Copy link
Copy Markdown
Author

Done: the RGB values are no longer rounded, so hsl(0 0% 30%) is 0.3 gray (now a test case), and the changelog entry is under 2.9.1. I also merged master.

@andersonhc

Copy link
Copy Markdown
Collaborator

Done: the RGB values are no longer rounded, so hsl(0 0% 30%) is 0.3 gray (now a test case), and the changelog entry is under 2.9.1. I also merged master.

Thanks for addressing both points!

I found one remaining edge case with the cache: for a -> b -> a, where only a has stops, defining a first caches b without stops, so shapes using b lose their gradient. Reversing the definitions makes both gradients resolve.

Could we avoid caching incomplete results for cycle members and add a test with stops in the cycle, checking both definition orders?

@andersonhc
andersonhc merged commit 2c50cc2 into py-pdf:master Nov 13, 2026
23 checks passed
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.

2 participants