[macOS] Honor COLR/CPAL palette selection on CoreText (SKTypeface.Clone palette)#4265
Draft
mattleibow wants to merge 2 commits into
Draft
[macOS] Honor COLR/CPAL palette selection on CoreText (SKTypeface.Clone palette)#4265mattleibow wants to merge 2 commits into
mattleibow wants to merge 2 commits into
Conversation
SKTypeface.Clone(paletteIndex) and per-entry SKFontArguments.PaletteOverrides were silently ignored on macOS/iOS: the CoreText backend always rendered CPAL palette 0, while Linux (FreeType) and Windows (DirectWrite) honored the selected palette. Bump the skia submodule to the CoreText palette fix (mono/skia#270), which bakes the resolved palette into palette 0 of an in-memory copy of the font (public CoreText API only, App Store safe) so the requested colors render. Add SKColorFontPaletteRenderingTest plus a small self-contained COLRv0 test font (colr-v0-palettes.ttf, 3 palettes) that proves the rendered colors are distinct per palette index and that per-entry overrides recolor the targeted entry. COLRv0 is verified on all backends including CoreText; a COLRv1 test documents that CoreText does not paint COLRv1 (skipped on Apple platforms, asserted on FreeType/DirectWrite). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
📦 Try the packages from this PRWarning Do not run these scripts without first reviewing the code in this PR. Step 1 — Download the packages bash / macOS / Linux: curl -fsSL https://raw.githubusercontent.com/mono/SkiaSharp/main/scripts/get-skiasharp-pr.sh | bash -s -- 4265PowerShell / Windows: iex "& { $(irm https://raw.githubusercontent.com/mono/SkiaSharp/main/scripts/get-skiasharp-pr.ps1) } 4265"Step 2 — Add the local NuGet source dotnet nuget add source ~/.skiasharp/hives/pr-4265/packages --name skiasharp-pr-4265More options
Or download manually from Azure Pipelines — look for the Remove the source when you're done: dotnet nuget remove source skiasharp-pr-4265 |
Contributor
|
📖 Documentation Preview The documentation for this PR has been deployed and is available at: 🔗 View Staging Site This preview will be updated automatically when you push new commits to this PR. This comment is automatically updated by the documentation staging workflow. |
The previous test font was a hand-built 1132-byte COLRv0 font with a non-conformant OS/2 table (fsSelection=0, OS/2 v3, post 2.0). DirectWrite crashed (0xC0000005) inside sk_typeface_clone_with_arguments when cloning a non-default palette of it, hanging the Windows .NET Core test leg. Rebuild the test font from Skia's resources/fonts/colr.ttf (a font Skia exercises across every backend including DirectWrite) by extending its CPAL to three palettes. Render U+2662 (diamond, CPAL entry 0) and U+1F600 (face, CPAL entry 2) so palette swaps change two large, easy-to-detect regions: palette 0: red diamond + yellow face palette 1: blue diamond + cyan face palette 2: lime diamond + magenta face Also drop ColrV1PaletteSelectionIsUnsupportedOnCoreText: it asserted DirectWrite behavior (COLRv1 palette difference) that does not hold in this build and is not part of the CoreText COLRv0 fix being validated. Verified locally on macOS arm64 (CoreText): 9/9 pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.
Summary
SKTypeface.Clone(paletteIndex)and per-entrySKFontArguments.PaletteOverrideswere silently ignored on macOS/iOS. The CoreText backend always rendered CPAL palette 0, while Linux (FreeType) and Windows (DirectWrite) honored the selected palette. So COLR/CPAL color-font palette selection worked everywhere except Apple platforms.Root cause
CoreText exposes no public API to select a COLR/CPAL palette and always renders the font's default palette; the only color input it honors is the
CGContextfill color (mapped to the COLR foreground entry).SkTypeface_Mac::onMakeCloneforwarded only variation axes and droppedargs.getPalette()entirely.Fix
Native fix lives in the skia submodule — mono/skia#270 (this PR bumps
externals/skiato it). At clone/load time it bakes the resolved palette (selected index + per-entry overrides) into palette 0 of an in-memory copy of the font'sCPALtable and rebuilds the CTFont from those bytes, using public CoreText API only (App Store safe — a prior private-SPI attempt was reverted upstream, see flutter/flutter#158423).externals/skia→8e63d261([ports] CoreText: honor SkFontArguments COLR/CPAL palette selection skia#270)Tests (prove it works)
New
SKColorFontPaletteRenderingTest+ a small self-contained COLRv0 test font (tests/Content/fonts/colr-v0-palettes.ttf, 3 palettes × 2 entries, CC0):DifferentPaletteIndexProducesDifferentRendering/AllPalettesProduceDistinctRenderings— rendered pixels are actually different per palette index.PaletteSelectionUsesExpectedColors— each palette paints the expected colors (pal0 red/lime, pal1 blue/yellow, pal2 magenta/cyan).PaletteOverrideChangesEntryColor/NoOpPaletteOverrideMatchesBasePalette— per-entry overrides recolor the targeted entry.OutOfRangePaletteIndexFallsBackToBasePalette/SamePaletteIndexRendersIdentically— semantics match FreeType/CSS.These COLRv0 tests run and pass on all backends including CoreText.
Known limitation (COLRv1)
CoreText renders COLRv0 (layered solid colors) and honors the baked palette, but does not paint COLRv1 (gradients) at all on current macOS — it falls back to a monochrome outline regardless of palette.
ColrV1PaletteSelectionIsUnsupportedOnCoreTextdocuments this: skipped on Apple platforms, asserted to work on FreeType/DirectWrite. Full COLRv1 palette support on Apple would need Skia's own COLR engine (separate effort).Verification
macOS arm64 (macOS 26.5): 7/8 palette tests pass + 1 skipped (COLRv1 on Mac); typeface/font regression slice clean (
SKTypeface76,SKFont65,SKFontManager21 — 0 failures). CI will validate Linux/Windows/Apple.Depends on mono/skia#270 (merge that first, then re-point this submodule to the merged commit).
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com