From cb0b746f9a154289727e107723d2e14155ff1ebb Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 21 Jan 2022 15:57:16 +0300 Subject: [PATCH] dwrite: Partially implement newer TranslateColorGlyphRun() variant. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/dwrite_private.h | 5 +- dlls/dwrite/font.c | 38 ++++++++---- dlls/dwrite/main.c | 22 ++++--- dlls/dwrite/tests/font.c | 108 +++++++++++++++++++++++++++++++---- 4 files changed, 140 insertions(+), 33 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 91b2bb3241c..00fe325518f 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -315,8 +315,9 @@ extern HRESULT get_local_refkey(const WCHAR*,const FILETIME*,void**,UINT32*) DEC extern HRESULT get_filestream_from_file(IDWriteFontFile*,IDWriteFontFileStream**) DECLSPEC_HIDDEN; extern BOOL is_face_type_supported(DWRITE_FONT_FACE_TYPE) DECLSPEC_HIDDEN; extern HRESULT get_family_names_from_stream(IDWriteFontFileStream*,UINT32,DWRITE_FONT_FACE_TYPE,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; -extern HRESULT create_colorglyphenum(FLOAT,FLOAT,const DWRITE_GLYPH_RUN*,const DWRITE_GLYPH_RUN_DESCRIPTION*,DWRITE_MEASURING_MODE, - const DWRITE_MATRIX*,UINT32,IDWriteColorGlyphRunEnumerator**) DECLSPEC_HIDDEN; +extern HRESULT create_colorglyphenum(D2D1_POINT_2F origin, const DWRITE_GLYPH_RUN *run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, + DWRITE_GLYPH_IMAGE_FORMATS formats, DWRITE_MEASURING_MODE mode, const DWRITE_MATRIX *transform, UINT32 palette, + IDWriteColorGlyphRunEnumerator1 **enumerator) DECLSPEC_HIDDEN; extern BOOL lb_is_newline_char(WCHAR) DECLSPEC_HIDDEN; extern HRESULT create_system_fontfallback(IDWriteFactory7 *factory, IDWriteFontFallback1 **fallback) DECLSPEC_HIDDEN; extern void release_system_fontfallback(IDWriteFontFallback1 *fallback) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 2296c74c1e3..cbc0434b72d 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -397,8 +397,7 @@ struct dwrite_colorglyphenum IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface; LONG refcount; - FLOAT origin_x; /* original run origin */ - FLOAT origin_y; + D2D1_POINT_2F origin; /* original run origin */ IDWriteFontFace5 *fontface; /* for convenience */ DWRITE_COLOR_GLYPH_RUN1 colorrun; /* returned with GetCurrentRun() */ @@ -6431,8 +6430,8 @@ static BOOL colorglyphenum_build_color_run(struct dwrite_colorglyphenum *glyphen glyphenum->color_offsets[g] = glyphenum->offsets[g]; } - colorrun->baselineOriginX = glyphenum->origin_x + get_glyph_origin(glyphenum, first_glyph); - colorrun->baselineOriginY = glyphenum->origin_y; + colorrun->baselineOriginX = glyphenum->origin.x + get_glyph_origin(glyphenum, first_glyph); + colorrun->baselineOriginY = glyphenum->origin.y; colorrun->glyphRun.glyphCount = glyphenum->run.glyphCount; colorrun->paletteIndex = 0xffff; memset(&colorrun->runColor, 0, sizeof(colorrun->runColor)); @@ -6470,8 +6469,8 @@ static BOOL colorglyphenum_build_color_run(struct dwrite_colorglyphenum *glyphen glyphenum->palette, colorrun->paletteIndex, hr); } /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */ - colorrun->baselineOriginX = glyphenum->origin_x + get_glyph_origin(glyphenum, g); - colorrun->baselineOriginY = glyphenum->origin_y; + colorrun->baselineOriginX = glyphenum->origin.x + get_glyph_origin(glyphenum, g); + colorrun->baselineOriginY = glyphenum->origin.y; glyphenum->color_advances[index] = glyphenum->advances[g]; got_palette_index = TRUE; } @@ -6562,9 +6561,9 @@ static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl = colorglyphenum1_GetCurrentRun, }; -HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_RUN *run, - const DWRITE_GLYPH_RUN_DESCRIPTION *rundescr, DWRITE_MEASURING_MODE measuring_mode, - const DWRITE_MATRIX *transform, unsigned int palette, IDWriteColorGlyphRunEnumerator **ret) +HRESULT create_colorglyphenum(D2D1_POINT_2F origin, const DWRITE_GLYPH_RUN *run, + const DWRITE_GLYPH_RUN_DESCRIPTION *rundescr, DWRITE_GLYPH_IMAGE_FORMATS formats, DWRITE_MEASURING_MODE measuring_mode, + const DWRITE_MATRIX *transform, unsigned int palette, IDWriteColorGlyphRunEnumerator1 **ret) { struct dwrite_colorglyphenum *colorglyphenum; BOOL colorfont, has_colored_glyph; @@ -6580,13 +6579,28 @@ HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_R if (!colorfont) return DWRITE_E_NOCOLOR; + if (!(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))) + { + return DWRITE_E_NOCOLOR; + } + + if (formats & ~(DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE | DWRITE_GLYPH_IMAGE_FORMATS_CFF | DWRITE_GLYPH_IMAGE_FORMATS_COLR)) + { + FIXME("Unimplemented formats requested %#x.\n", formats); + return E_NOTIMPL; + } + if (!(colorglyphenum = calloc(1, sizeof(*colorglyphenum)))) return E_OUTOFMEMORY; colorglyphenum->IDWriteColorGlyphRunEnumerator1_iface.lpVtbl = &colorglyphenumvtbl; colorglyphenum->refcount = 1; - colorglyphenum->origin_x = originX; - colorglyphenum->origin_y = originY; + colorglyphenum->origin = origin; colorglyphenum->fontface = &fontface->IDWriteFontFace5_iface; IDWriteFontFace5_AddRef(colorglyphenum->fontface); colorglyphenum->glyphs = NULL; @@ -6648,7 +6662,7 @@ HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_R run->fontEmSize, 1.0f, transform, run->glyphIndices[i], run->isSideways); } - *ret = (IDWriteColorGlyphRunEnumerator *)&colorglyphenum->IDWriteColorGlyphRunEnumerator1_iface; + *ret = &colorglyphenum->IDWriteColorGlyphRunEnumerator1_iface; return S_OK; } diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index b21eba0c50a..ab53d5cb80d 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -1398,13 +1398,17 @@ static HRESULT WINAPI dwritefactory2_CreateFontFallbackBuilder(IDWriteFactory7 * } static HRESULT WINAPI dwritefactory2_TranslateColorGlyphRun(IDWriteFactory7 *iface, FLOAT originX, FLOAT originY, - const DWRITE_GLYPH_RUN *run, const DWRITE_GLYPH_RUN_DESCRIPTION *rundescr, DWRITE_MEASURING_MODE mode, - const DWRITE_MATRIX *transform, UINT32 palette, IDWriteColorGlyphRunEnumerator **colorlayers) + const DWRITE_GLYPH_RUN *run, const DWRITE_GLYPH_RUN_DESCRIPTION *run_desc, DWRITE_MEASURING_MODE measuring_mode, + const DWRITE_MATRIX *transform, UINT32 palette, IDWriteColorGlyphRunEnumerator **layers) { - TRACE("%p, %.8e, %.8e, %p, %p, %d, %p, %u, %p.\n", iface, originX, originY, run, rundescr, mode, - transform, palette, colorlayers); + D2D1_POINT_2F origin = { originX, originY }; - return create_colorglyphenum(originX, originY, run, rundescr, mode, transform, palette, colorlayers); + TRACE("%p, %.8e, %.8e, %p, %p, %d, %p, %u, %p.\n", iface, originX, originY, run, run_desc, measuring_mode, + transform, palette, layers); + + return create_colorglyphenum(origin, run, run_desc, DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE + | DWRITE_GLYPH_IMAGE_FORMATS_CFF | DWRITE_GLYPH_IMAGE_FORMATS_COLR, + measuring_mode, transform, palette, (IDWriteColorGlyphRunEnumerator1 **)layers); } static HRESULT WINAPI dwritefactory2_CreateCustomRenderingParams(IDWriteFactory7 *iface, FLOAT gamma, FLOAT contrast, @@ -1697,15 +1701,15 @@ static HRESULT WINAPI dwritefactory3_GetFontDownloadQueue(IDWriteFactory7 *iface return E_NOTIMPL; } -static HRESULT WINAPI dwritefactory4_TranslateColorGlyphRun(IDWriteFactory7 *iface, D2D1_POINT_2F baseline_origin, +static HRESULT WINAPI dwritefactory4_TranslateColorGlyphRun(IDWriteFactory7 *iface, D2D1_POINT_2F origin, DWRITE_GLYPH_RUN const *run, DWRITE_GLYPH_RUN_DESCRIPTION const *run_desc, DWRITE_GLYPH_IMAGE_FORMATS desired_formats, DWRITE_MEASURING_MODE measuring_mode, DWRITE_MATRIX const *transform, UINT32 palette, IDWriteColorGlyphRunEnumerator1 **layers) { - FIXME("%p, %p, %p, %u, %d, %p, %u, %p: stub\n", iface, run, run_desc, desired_formats, measuring_mode, - transform, palette, layers); + TRACE("%p, %.8e, %.8e, %p, %p, %u, %d, %p, %u, %p.\n", iface, origin.x, origin.y, run, run_desc, desired_formats, + measuring_mode, transform, palette, layers); - return E_NOTIMPL; + return create_colorglyphenum(origin, run, run_desc, desired_formats, measuring_mode, transform, palette, layers); } HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode, diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index b347a73a53e..a610491e09c 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -7671,6 +7671,7 @@ static void test_TranslateColorGlyphRun(void) const DWRITE_COLOR_GLYPH_RUN *colorrun; IDWriteFontFace2 *fontface2; IDWriteFontFace *fontface; + IDWriteFactory4 *factory4; IDWriteFactory2 *factory; DWRITE_GLYPH_RUN run; UINT32 codepoints[2]; @@ -7740,7 +7741,8 @@ static void test_TranslateColorGlyphRun(void) win_skip("IDWriteColorGlyphRunEnumerator1 is not supported.\n"); } - for (;;) { + for (;;) + { hasrun = FALSE; hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &hasrun); ok(hr == S_OK, "got 0x%08x\n", hr); @@ -7749,22 +7751,24 @@ static void test_TranslateColorGlyphRun(void) break; hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &colorrun); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(colorrun->glyphRun.fontFace != NULL, "got fontface %p\n", colorrun->glyphRun.fontFace); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(colorrun->glyphRun.fontFace == fontface, "Unexpected fontface %p.\n", colorrun->glyphRun.fontFace); ok(colorrun->glyphRun.fontEmSize == 20.0f, "got wrong font size %f\n", colorrun->glyphRun.fontEmSize); - ok(colorrun->glyphRun.glyphCount > 0, "got wrong glyph count %u\n", colorrun->glyphRun.glyphCount); + ok(colorrun->glyphRun.glyphCount == 1, "Unexpected glyph count %u.\n", colorrun->glyphRun.glyphCount); ok(colorrun->glyphRun.glyphIndices != NULL, "got null glyph indices %p\n", colorrun->glyphRun.glyphIndices); ok(colorrun->glyphRun.glyphAdvances != NULL, "got null glyph advances %p\n", colorrun->glyphRun.glyphAdvances); + ok(!colorrun->glyphRunDescription, "Unexpected description pointer.\n"); if (layers1) { hr = IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1, &colorrun1); ok(hr == S_OK, "Failed to get color runt, hr %#x.\n", hr); - ok(colorrun1->glyphRun.fontFace != NULL, "Unexpected fontface %p.\n", colorrun1->glyphRun.fontFace); - ok(colorrun1->glyphRun.fontEmSize == 20.0f, "Unexpected font size %f.\n", colorrun1->glyphRun.fontEmSize); - ok(colorrun1->glyphRun.glyphCount > 0, "Unexpected glyph count %u\n", colorrun1->glyphRun.glyphCount); - ok(colorrun1->glyphRun.glyphIndices != NULL, "Unexpected indices array.\n"); - ok(colorrun1->glyphRun.glyphAdvances != NULL, "Unexpected advances array.\n"); + ok((const DWRITE_COLOR_GLYPH_RUN *)colorrun1 == colorrun, "Unexpected pointer.\n"); + ok(colorrun1->glyphImageFormat == (DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE | DWRITE_GLYPH_IMAGE_FORMATS_COLR) || + colorrun1->glyphImageFormat == DWRITE_GLYPH_IMAGE_FORMATS_NONE, + "Unexpected glyph image format %#x.\n", colorrun1->glyphImageFormat); + ok(colorrun1->measuringMode == DWRITE_MEASURING_MODE_NATURAL, "Unexpected measuring mode %d.\n", + colorrun1->measuringMode); } } @@ -7804,6 +7808,7 @@ static void test_TranslateColorGlyphRun(void) codepoints[0] = 'A'; hr = IDWriteFontFace_GetGlyphIndices(fontface, codepoints, 1, glyphs); ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!!*glyphs, "Unexpected glyph.\n"); layers = (void*)0xdeadbeef; hr = IDWriteFactory2_TranslateColorGlyphRun(factory, 0.0f, 0.0f, &run, NULL, @@ -7822,11 +7827,94 @@ static void test_TranslateColorGlyphRun(void) layers = NULL; hr = IDWriteFactory2_TranslateColorGlyphRun(factory, 0.0f, 0.0f, &run, NULL, - DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers); + DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers); ok(hr == S_OK, "got 0x%08x\n", hr); ok(layers != NULL, "got %p\n", layers); + + hr = IDWriteColorGlyphRunEnumerator_QueryInterface(layers, &IID_IDWriteColorGlyphRunEnumerator1, (void **)&layers1); + if (SUCCEEDED(hr)) + { + for (;;) + { + hasrun = FALSE; + hr = IDWriteColorGlyphRunEnumerator1_MoveNext(layers1, &hasrun); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + if (!hasrun) + break; + + hr = IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1, &colorrun1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!colorrun1->glyphRun.fontFace, "Unexpected fontface %p.\n", colorrun1->glyphRun.fontFace); + ok(colorrun1->glyphRun.fontEmSize == 20.0f, "got wrong font size %f\n", colorrun1->glyphRun.fontEmSize); + ok(colorrun1->glyphRun.glyphCount > 0, "Unexpected glyph count %u.\n", colorrun1->glyphRun.glyphCount); + ok(!!colorrun1->glyphRun.glyphIndices, "Unexpected indices %p.\n", colorrun1->glyphRun.glyphIndices); + ok(!!colorrun1->glyphRun.glyphAdvances, "Unexpected advances %p.\n", colorrun1->glyphRun.glyphAdvances); + ok(!colorrun1->glyphRunDescription, "Unexpected description pointer.\n"); + todo_wine + ok(colorrun1->glyphImageFormat == (DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE | DWRITE_GLYPH_IMAGE_FORMATS_COLR) || + colorrun1->glyphImageFormat == DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE, "Unexpected glyph image format %#x.\n", + colorrun1->glyphImageFormat); + ok(colorrun1->measuringMode == DWRITE_MEASURING_MODE_NATURAL, "Unexpected measuring mode %d.\n", + colorrun1->measuringMode); + } + + IDWriteColorGlyphRunEnumerator1_Release(layers1); + } IDWriteColorGlyphRunEnumerator_Release(layers); + if (SUCCEEDED(IDWriteFactory2_QueryInterface(factory, &IID_IDWriteFactory4, (void **)&factory4))) + { + D2D1_POINT_2F origin; + + origin.x = origin.y = 0.0f; + hr = IDWriteFactory4_TranslateColorGlyphRun(factory4, origin, &run, NULL, + DWRITE_GLYPH_IMAGE_FORMATS_NONE, DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers1); + ok(hr == DWRITE_E_NOCOLOR, "Unexpected hr %#x.\n", hr); + + hr = IDWriteFactory4_TranslateColorGlyphRun(factory4, origin, &run, NULL, + DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE, DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers1); + ok(hr == DWRITE_E_NOCOLOR, "Unexpected hr %#x.\n", hr); + + hr = IDWriteFactory4_TranslateColorGlyphRun(factory4, origin, &run, NULL, + DWRITE_GLYPH_IMAGE_FORMATS_CFF, DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers1); + ok(hr == DWRITE_E_NOCOLOR, "Unexpected hr %#x.\n", hr); + + hr = IDWriteFactory4_TranslateColorGlyphRun(factory4, origin, &run, NULL, + DWRITE_GLYPH_IMAGE_FORMATS_COLR, DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + for (;;) + { + hasrun = FALSE; + hr = IDWriteColorGlyphRunEnumerator1_MoveNext(layers1, &hasrun); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + if (!hasrun) + break; + + hr = IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1, &colorrun1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!colorrun1->glyphRun.fontFace, "Unexpected fontface %p.\n", colorrun1->glyphRun.fontFace); + ok(colorrun1->glyphRun.fontEmSize == 20.0f, "got wrong font size %f\n", colorrun1->glyphRun.fontEmSize); + ok(colorrun1->glyphRun.glyphCount > 0, "Unexpected glyph count %u.\n", colorrun1->glyphRun.glyphCount); + ok(!!colorrun1->glyphRun.glyphIndices, "Unexpected indices %p.\n", colorrun1->glyphRun.glyphIndices); + ok(!!colorrun1->glyphRun.glyphAdvances, "Unexpected advances %p.\n", colorrun1->glyphRun.glyphAdvances); + ok(!colorrun1->glyphRunDescription, "Unexpected description pointer.\n"); + ok(colorrun1->glyphImageFormat == DWRITE_GLYPH_IMAGE_FORMATS_COLR || + colorrun1->glyphImageFormat == DWRITE_GLYPH_IMAGE_FORMATS_NONE, "Unexpected glyph image format %#x.\n", + colorrun1->glyphImageFormat); + ok(colorrun1->measuringMode == DWRITE_MEASURING_MODE_NATURAL, "Unexpected measuring mode %d.\n", + colorrun1->measuringMode); + } + + IDWriteColorGlyphRunEnumerator1_Release(layers1); + + IDWriteFactory4_Release(factory4); + } + else + win_skip("IDWriteFactory4::TranslateColorGlyphRun() is not supported.\n"); + IDWriteFontFace2_Release(fontface2); IDWriteFontFace_Release(fontface); ref = IDWriteFactory2_Release(factory);