Skip to content

Fix Color.hex ignoring the conversion failure and not clamping components - #891

Merged
kean merged 1 commit into
mainfrom
fix/color-hex-fallback
Aug 15, 2026
Merged

kean merged 1 commit into
mainfrom
fix/color-hex-fallback

Conversation

@kean

@kean kean commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Two problems in Color.hex, which feeds Border.description and through it the identifiers of Circle and RoundedCorners:

  1. The result of getRed(_:green:blue:alpha:) was discarded. It returns false for the colors with no RGB representation — pattern colors — leaving the zero-initialized components in place, so all of them hexed to "#00000000" and shared an identifier with .clear and with each other. Two distinct border colors could be served each other's processed bytes from the disk cache, while the memory cache, which hashes the color object, kept them apart.

  2. The components were formatted unclamped. A P3 color converts to extended sRGB with components outside of 0...1, so String(format: "%02lX", lroundf(1.093 * 255)) produced "117" and the negative components produced "FFFFFFFFFFFFFFC6". P3 red hexed to "#117FFFFFFFFFFFFFFC6FFFFFFFFFFFFFFDA" on iOS.

hex is now optional and returns nil when the color has no sRGB representation, and the components are clamped to 0...1. Border.description falls back to the color's own description so that such colors stay distinct from one another instead of collapsing onto a single, already-taken value.

…ents

`hex` discarded the result of `getRed(_:green:blue:alpha:)` and formatted
the zero-initialized components, so every color with no sRGB
representation - pattern colors on both platforms - hexed to
`"#00000000"` and shared an identifier with `.clear` and with each other.
Two distinct border colors could therefore be served each other's
processed bytes from the disk cache while the memory cache, which hashes
the color object, kept them apart.

The components were also formatted unclamped. A P3 color converts to
extended sRGB with components outside of `0...1`, which produced
malformed hex on iOS, e.g. `"#117FFFFFFFFFFFFFFC6FFFFFFFFFFFFFFDA"` for
P3 red.

`hex` is now optional and the components are clamped to `0...1`.
`Border.description`, which feeds the identifiers of the processors that
draw borders, falls back to the color's own description so that the
colors with no hex stay distinct instead of collapsing onto one value.
@kean kean modified the milestone: 14.0 Aug 15, 2026
@kean
kean merged commit a17e58a into main Aug 15, 2026
5 checks passed
@kean
kean deleted the fix/color-hex-fallback branch August 16, 2026 20:20
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