DWrite: Add support for COLRv1 fonts

Fixes https://gitlab.freedesktop.org/cairo/cairo/-/issues/903
This commit is contained in:
Luca Bacci 2025-06-14 15:54:53 +02:00
parent 457ab827c9
commit 1aaa23aefb
3 changed files with 90 additions and 26 deletions

View file

@ -219,6 +219,7 @@ RefPtr<IDWriteFactory1> DWriteFactory::mFactoryInstance1;
RefPtr<IDWriteFactory2> DWriteFactory::mFactoryInstance2;
RefPtr<IDWriteFactory3> DWriteFactory::mFactoryInstance3;
RefPtr<IDWriteFactory4> DWriteFactory::mFactoryInstance4;
RefPtr<IDWriteFactory8> DWriteFactory::mFactoryInstance8;
RefPtr<IWICImagingFactory> WICImagingFactory::mFactoryInstance;
RefPtr<IDWriteFontCollection> DWriteFactory::mSystemCollection;
@ -1140,13 +1141,16 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat);
/* The list of glyph image formats this renderer is prepared to support. */
DWRITE_GLYPH_IMAGE_FORMATS supported_formats = static_cast<DWRITE_GLYPH_IMAGE_FORMATS>(
DWRITE_GLYPH_IMAGE_FORMATS_COLR |
DWRITE_GLYPH_IMAGE_FORMATS_SVG |
DWRITE_GLYPH_IMAGE_FORMATS_PNG |
DWRITE_GLYPH_IMAGE_FORMATS_JPEG |
DWRITE_GLYPH_IMAGE_FORMATS_TIFF |
DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8);
const DWRITE_GLYPH_IMAGE_FORMATS_ base_formats = (
DWRITE_GLYPH_IMAGE_FORMATS_COLR_ |
DWRITE_GLYPH_IMAGE_FORMATS_SVG_ |
DWRITE_GLYPH_IMAGE_FORMATS_PNG_ |
DWRITE_GLYPH_IMAGE_FORMATS_JPEG_ |
DWRITE_GLYPH_IMAGE_FORMATS_TIFF_ |
DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8_);
// Level of support for DWRITE_GLYPH_IMAGE_FORMATS_COLR_PAINT_TREE
DWRITE_PAINT_FEATURE_LEVEL dwrite_paint_feature_level = DWRITE_PAINT_FEATURE_LEVEL_COLR_V1;
RefPtr<IDWriteFontFace2> fontFace2;
UINT32 palette_count = 0;
@ -1157,15 +1161,35 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
if (scaled_font->base.options.palette_index < palette_count)
palette_index = scaled_font->base.options.palette_index;
hr = DWriteFactory::Instance4()->TranslateColorGlyphRun(
origin,
&run,
NULL, /* glyphRunDescription */
supported_formats,
dwrite_font_face->measuring_mode,
&matrix,
palette_index,
&run_enumerator);
if (DWriteFactory::Instance8().get()) {
hr = DWriteFactory::Instance8()->TranslateColorGlyphRun(
origin,
&run,
NULL, /* glyphRunDescription */
static_cast<DWRITE_GLYPH_IMAGE_FORMATS>
(base_formats | DWRITE_GLYPH_IMAGE_FORMATS_COLR_PAINT_TREE_),
dwrite_paint_feature_level,
dwrite_font_face->measuring_mode,
&matrix,
palette_index,
&run_enumerator);
}
else if (DWriteFactory::Instance4().get()) {
hr = DWriteFactory::Instance4()->TranslateColorGlyphRun(
origin,
&run,
NULL, /* glyphRunDescription */
static_cast<DWRITE_GLYPH_IMAGE_FORMATS>
(base_formats),
dwrite_font_face->measuring_mode,
&matrix,
palette_index,
&run_enumerator);
}
else {
// TODO
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (hr == DWRITE_E_NOCOLOR) {
/* No color glyphs */
@ -1242,11 +1266,12 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
if (FAILED(hr))
return _cairo_dwrite_error (hr, "GetCurrentRun failed");
switch (color_run->glyphImageFormat) {
case DWRITE_GLYPH_IMAGE_FORMATS_PNG:
case DWRITE_GLYPH_IMAGE_FORMATS_JPEG:
case DWRITE_GLYPH_IMAGE_FORMATS_TIFF:
case DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8:
const auto format = static_cast<DWRITE_GLYPH_IMAGE_FORMATS_>(color_run->glyphImageFormat);
switch (format) {
case DWRITE_GLYPH_IMAGE_FORMATS_PNG_:
case DWRITE_GLYPH_IMAGE_FORMATS_JPEG_:
case DWRITE_GLYPH_IMAGE_FORMATS_TIFF_:
case DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8_:
/* Bitmap glyphs */
dc4->DrawColorBitmapGlyphRun(color_run->glyphImageFormat,
origin,
@ -1255,7 +1280,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT);
break;
case DWRITE_GLYPH_IMAGE_FORMATS_SVG:
case DWRITE_GLYPH_IMAGE_FORMATS_SVG_:
/* SVG glyphs */
dc4->DrawSvgGlyphRun(origin,
&color_run->glyphRun,
@ -1265,9 +1290,9 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
dwrite_font_face->measuring_mode);
uses_foreground_color = TRUE;
break;
case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE:
case DWRITE_GLYPH_IMAGE_FORMATS_CFF:
case DWRITE_GLYPH_IMAGE_FORMATS_COLR:
case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE_:
case DWRITE_GLYPH_IMAGE_FORMATS_CFF_:
case DWRITE_GLYPH_IMAGE_FORMATS_COLR_:
/* Outline glyphs */
if (color_run->paletteIndex == 0xFFFF) {
D2D1_COLOR_F color = foreground_color_brush->GetColor();
@ -1291,7 +1316,21 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
color_run->glyphRunDescription,
color_brush,
dwrite_font_face->measuring_mode);
case DWRITE_GLYPH_IMAGE_FORMATS_NONE:
break;
case DWRITE_GLYPH_IMAGE_FORMATS_COLR_PAINT_TREE_:
{
RefPtr<ID2D1DeviceContext7> dc7;
hr = rt->QueryInterface(&dc7);
if (FAILED(hr))
return _cairo_dwrite_error (hr, "QueryInterface(&dc7) failed");
dc7->DrawPaintGlyphRun (origin,
&color_run->glyphRun,
foreground_color_brush,
palette_index,
dwrite_font_face->measuring_mode);
break;
}
case DWRITE_GLYPH_IMAGE_FORMATS_NONE_:
break;
}
}

View file

@ -125,6 +125,16 @@ public:
return mFactoryInstance4;
}
static RefPtr<IDWriteFactory8> Instance8()
{
if (!mFactoryInstance8) {
if (Instance()) {
Instance()->QueryInterface(&mFactoryInstance8);
}
}
return mFactoryInstance8;
}
static RefPtr<IDWriteFontCollection> SystemCollection()
{
if (!mSystemCollection) {
@ -169,6 +179,7 @@ private:
static RefPtr<IDWriteFactory2> mFactoryInstance2;
static RefPtr<IDWriteFactory3> mFactoryInstance3;
static RefPtr<IDWriteFactory4> mFactoryInstance4;
static RefPtr<IDWriteFactory8> mFactoryInstance8;
static RefPtr<IDWriteFontCollection> mSystemCollection;
static RefPtr<IDWriteRenderingParams> mDefaultRenderingParams;
};

View file

@ -5,6 +5,20 @@
#include <dwrite_3.h>
typedef enum DWRITE_GLYPH_IMAGE_FORMATS_ {
DWRITE_GLYPH_IMAGE_FORMATS_NONE_ = 0,
DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE_ = 1 << 0,
DWRITE_GLYPH_IMAGE_FORMATS_CFF_ = 1 << 1,
DWRITE_GLYPH_IMAGE_FORMATS_COLR_ = 1 << 2,
DWRITE_GLYPH_IMAGE_FORMATS_SVG_ = 1 << 3,
DWRITE_GLYPH_IMAGE_FORMATS_PNG_ = 1 << 4,
DWRITE_GLYPH_IMAGE_FORMATS_JPEG_ = 1 << 5,
DWRITE_GLYPH_IMAGE_FORMATS_TIFF_ = 1 << 6,
DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8_ = 1 << 7,
DWRITE_GLYPH_IMAGE_FORMATS_COLR_PAINT_TREE_ = 1 << 8
} DWRITE_GLYPH_IMAGE_FORMATS_;
DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS_)
#ifndef HAVE_IDWRITEFACTORY8
typedef enum DWRITE_PAINT_FEATURE_LEVEL {