Skip to content

Text Rendering: Add DirectWrite color glyph (COLR v0) rendering support#11684

Open
etvorun wants to merge 2 commits into
dotnet:mainfrom
etvorun:port/color-emoji-support
Open

Text Rendering: Add DirectWrite color glyph (COLR v0) rendering support#11684
etvorun wants to merge 2 commits into
dotnet:mainfrom
etvorun:port/color-emoji-support

Conversation

@etvorun
Copy link
Copy Markdown

@etvorun etvorun commented Jun 2, 2026

Summary

Add DirectWrite color glyph (COLR v0) rendering support to WPF and fix emoji font fallback so that emoji characters render in full color instead of monochrome outlines.

Before and after

Text like the following now renders in full color instead of monochrome outlines:

Category Example text
Faces Hello 😀😃😄😁😆 World
Gestures Great job 👍👏🙌
Animals Nature 🐶🐱🦊🐻🐼
Colored circles (U+1F7E0–1F7EB) 🟠🟡🟢🟣🟤🔴🔵🟥🟧🟨🟩🟦🟪🟫
Star / circle (U+2B50, U+2B55) ⭐⭕
Heavy equals sign (U+1F7F0) 🟰
Extended range (U+1FA00–1FAFF) 🫠🫡🫢🫣🫤🫥🫨

Before: Emoji show as monochrome outlines or empty boxes.
After: Emoji render with full COLR v0 palette colors.

What changed

Color glyph rendering

  • GlyphTypeface.IsColorFont — New property that detects whether a font has a COLR OpenType table (lazy-cached).
  • GlyphRun.TryBuildColorGlyphDrawing() — Calls IDWriteFactory2::TranslateColorGlyphRun to decompose a glyph run into per-layer sub-runs, each with a CPAL palette color. Builds a frozen DrawingGroup of GeometryDrawing layers.
  • DrawingDrawingContext / RenderDataDrawingContext — Intercept DrawGlyphRun to render color layers when available, falling through to the existing monochrome path for non-color fonts.
  • Factory.TranslateColorGlyphRun() — Managed wrapper around IDWriteFactory2::TranslateColorGlyphRun with input validation and proper COM lifetime management. Queries for IDWriteFactory2 at factory creation with graceful fallback on pre-Windows 8.1.
  • FontFace.HasColorGlyphs() — Native helper that probes for the COLR OpenType table.
  • New interop typesIDWriteColorGlyphRunEnumerator, DWRITE_COLOR_GLYPH_RUN, ColorGlyphLayer for managed/native interop.

Font fallback fixes

  • Extended emoji Unicode ranges in all three FontFamilyMap sections of GlobalUserInterface.CompositeFont from 1F900-1F9FF to 1F900-1FAFF (adds Symbols and Pictographs Extended-A coverage).
  • Added explicit Segoe UI Emoji entries for default-presentation emoji code points (U+1F7E0–1F7EB colored circles/squares, U+1F7F0 heavy equals sign, U+2B50 star, U+2B55 hollow red circle) that were previously mapped to text-priority font families.

Tests

  • Added ColorEmojiTests covering IsColorFont detection, color glyph layer decomposition, and font fallback for previously missing emoji code points.

Why

WPF renders all emoji as monochrome outlines because the glyph pipeline produces single-channel coverage bitmaps with no per-layer color support. Additionally, newer Unicode emoji ranges are not mapped to Segoe UI Emoji in the composite font, causing them to show as empty boxes.

This fix decomposes COLR v0 color glyphs via DirectWrite into individually colored geometry layers, and extends font fallback to cover all standard emoji Unicode ranges.

Limitations

  • COLR v0 only (IDWriteFactory2). COLRv1/SVG/CBDT color fonts would need IDWriteFactory4+.
  • Color layers use geometry-based rendering (no ClearType), which is acceptable for emoji at typical display sizes.

Validation

  • Verified locally that emoji render in full color with the fix applied.
  • All PresentationCore.Tests pass (976 total: 947 passed, 29 skipped for pre-existing reasons, 0 failures).

Fixes #91

Microsoft Reviewers: Open in CodeFlow

@etvorun etvorun requested review from a team and Copilot June 2, 2026 16:25
@etvorun etvorun requested a review from a team as a code owner June 2, 2026 16:25
@etvorun
Copy link
Copy Markdown
Author

etvorun commented Jun 2, 2026

Pinging participants from #91 who may be interested in reviewing this implementation:

@dotMorten (original issue author), @mikedn, @be5invis, @fdwr (DirectWrite expertise), @samhocevar (Emoji.Wpf author), @fcharlie, @pchaurasia14, @Bart-Verdonck, @alexinea, @gusmanb, @Lorymi, @virzak, @XamDR, @gusmanb

This PR adds native COLR v0 color glyph support directly in WPF's rendering pipeline via IDWriteFactory2::TranslateColorGlyphRun, along with font fallback fixes for missing emoji Unicode ranges. Feedback and review are very welcome!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds COLR v0 color glyph (emoji) rendering to WPF by decomposing DirectWrite color glyph runs into per-layer geometries, and updates the composite font fallback so newer emoji ranges select Segoe UI Emoji (enabling full-color emoji instead of monochrome/boxes).

Changes:

  • Add color-font detection (GlyphTypeface.IsColorFont) and a color-layer drawing path (GlyphRun.TryBuildColorGlyphDrawing) backed by IDWriteFactory2::TranslateColorGlyphRun.
  • Hook color-layer rendering into managed drawing contexts (DrawingDrawingContext and RenderDataDrawingContext) while preserving the existing monochrome pipeline as fallback.
  • Extend GlobalUserInterface.CompositeFont emoji mappings and add unit tests for color glyph detection/layering/fallback.
Show a summary per file
File Description
src/Microsoft.DotNet.Wpf/tests/UnitTests/PresentationCore.Tests/System/Windows/Media/ColorEmojiTests.cs Adds unit tests for color font detection, layer decomposition, and color interpretation.
src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphTypeface.cs Adds cached color-font detection via COLR table presence.
src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphRun.cs Adds translation of glyph runs into color layers and builds a DrawingGroup from per-layer geometries.
src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/RenderDataDrawingContext.cs Intercepts DrawGlyphRun to draw color-layer drawings when available.
src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/DrawingDrawingContext.cs Intercepts DrawGlyphRun to add color-layer drawings when available.
src/Microsoft.DotNet.Wpf/src/PresentationCore/PresentationCore.csproj Includes new DirectWrite interop and layer types in the build.
src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Text/TextInterface/Factory.cs QI’s IDWriteFactory2 and exposes a managed wrapper for TranslateColorGlyphRun.
src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Text/TextInterface/ColorGlyphLayer.cs Introduces a managed struct representing a translated color layer.
src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Interop/DWrite/IDWriteColorGlyphRunEnumerator.cs Adds interop for IDWriteColorGlyphRunEnumerator.
src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Interop/DWrite/DWriteColorGlyphStructs.cs Adds interop structs used by TranslateColorGlyphRun.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Fonts/GlobalUserInterface.CompositeFont Expands emoji unicode ranges and adds explicit mappings for emoji in mixed blocks.
src/Microsoft.DotNet.Wpf/src/DirectWriteForwarder/CPP/DWriteWrapper/FontFace.h Declares a native helper to probe for COLR table presence.
src/Microsoft.DotNet.Wpf/src/DirectWriteForwarder/CPP/DWriteWrapper/FontFace.cpp Implements COLR table probing via IDWriteFontFace::TryGetFontTable.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 12/13 changed files
  • Comments generated: 12

@miloush
Copy link
Copy Markdown
Contributor

miloush commented Jun 2, 2026

I think this is fine for Visual Studio but not for WPF itself. We should have a proper model for color glyph runs, not a render-time hack. If there is an interest to have this interim solution, it should at least be opt-in.

Copy link
Copy Markdown

@fdwr fdwr left a comment

Choose a reason for hiding this comment

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

Thanks ET - this is cool. Looks functionally correct, with minor feedback.

Regarding Jan's concern, is there a way to render monochromatically if desired, or is this always-on if the font has color in it? For UI controls like labels and text boxes, opting in by default makes sense, but for low level glyph rendering, there might be cases where we want to enable users to configure this. For Direct2D's DrawTextLayout, we didn't automatically enable it at the rendering layers because people could be doing custom highlight selection logic that wasn't prepared for full color yet, but we made it really easy to enable (just pass D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT). Maybe the DrawingDrawingContext (what a weird name) and RenderDataDrawingContext could have a property.

Comment thread src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphRun.cs Outdated
Comment thread src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphRun.cs Outdated
@amarinov-msft amarinov-msft added the PR metadata: Label to tag PRs, to facilitate with triage label Jun 3, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@etvorun
Copy link
Copy Markdown
Author

etvorun commented Jun 3, 2026

Thanks ET - this is cool. Looks functionally correct, with minor feedback.

Regarding Jan's concern, is there a way to render monochromatically if desired, or is this always-on if the font has color in it? For UI controls like labels and text boxes, opting in by default makes sense, but for low level glyph rendering, there might be cases where we want to enable users to configure this. For Direct2D's DrawTextLayout, we didn't automatically enable it at the rendering layers because people could be doing custom highlight selection logic that wasn't prepared for full color yet, but we made it really easy to enable (just pass D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT). Maybe the DrawingDrawingContext (what a weird name) and RenderDataDrawingContext could have a property.

This PR a port of a fix used by Visual Studio 2026 (release 18.8). We can treat it as a starting point and improve upon it. If you can recommend specific changes to this PR I can include them :)

@miloush
Copy link
Copy Markdown
Contributor

miloush commented Jun 3, 2026

The issue #91 you referenced discussed some options. Introducing TextOptions.EnableColorFont sounds like a pretty good compromise.

Copy link
Copy Markdown

@fdwr fdwr left a comment

Choose a reason for hiding this comment

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

LGTM sir 🫡. Like you say, it's a great starting point to improve upon. I'll defer to the WPF-side folks for policy decisions like whether to opt-in explicitly or opt-in by default like UWP does. (now we'll be able to use color emoji in Windows PIX which uses WPF 😉)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR metadata: Label to tag PRs, to facilitate with triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for Color Emoji support

5 participants