Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 2 ++ dlls/dwrite/font.c | 8 +++-- dlls/dwrite/opentype.c | 60 ++++++++++++++++++++++++++++++++++++ dlls/dwrite/tests/font.c | 43 ++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 3 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index a9fbb260e35..e53b4dba0bb 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -642,6 +642,8 @@ extern void opentype_layout_apply_gpos_features(struct scriptshaping_context *co extern BOOL opentype_layout_check_feature(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, struct shaping_feature *feature, unsigned int glyph_count, const UINT16 *glyphs, UINT8 *feature_applies) DECLSPEC_HIDDEN; +extern HRESULT opentype_get_vertical_glyph_variants(struct dwrite_fontface *fontface, unsigned int glyph_count, + const UINT16 *nominal_glyphs, UINT16 *glyphs) DECLSPEC_HIDDEN;
extern HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned int *scripts) DECLSPEC_HIDDEN; extern HRESULT shape_get_positions(struct scriptshaping_context *context, const unsigned int *scripts) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index ab60d4368c7..2d7a97594fc 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -1166,11 +1166,13 @@ static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFac }
static HRESULT WINAPI dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5 *iface, UINT32 glyph_count, - const UINT16 *nominal_indices, UINT16 *vertical_indices) + const UINT16 *nominal_glyphs, UINT16 *glyphs) { - FIXME("%p, %u, %p, %p: stub\n", iface, glyph_count, nominal_indices, vertical_indices); + struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface);
- return E_NOTIMPL; + TRACE("%p, %u, %p, %p.\n", iface, glyph_count, nominal_glyphs, glyphs); + + return opentype_get_vertical_glyph_variants(fontface, glyph_count, nominal_glyphs, glyphs); }
static BOOL WINAPI dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5 *iface) diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index d8bfa3f7f6d..1f0174ad72a 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -6214,3 +6214,63 @@ BOOL opentype_layout_check_feature(struct scriptshaping_context *context, unsign
return ret; } + +HRESULT opentype_get_vertical_glyph_variants(struct dwrite_fontface *fontface, unsigned int glyph_count, + const UINT16 *nominal_glyphs, UINT16 *glyphs) +{ + struct shaping_features features = { 0 }; + struct shaping_feature vert_feature = { 0 }; + struct scriptshaping_context context = { 0 }; + struct lookups lookups = { 0 }; + unsigned int i; + + memcpy(glyphs, nominal_glyphs, glyph_count * sizeof(*glyphs)); + + if (!(fontface->flags & FONTFACE_HAS_VERTICAL_VARIANTS)) + return S_OK; + + context.cache = fontface_get_shaping_cache(fontface); + context.u.subst.glyphs = glyphs; + context.u.subst.glyph_props = heap_calloc(glyph_count, sizeof(*context.u.subst.glyph_props)); + context.u.subst.max_glyph_count = glyph_count; + context.u.subst.capacity = glyph_count; + context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count); + context.table = &context.cache->gsub; + + vert_feature.tag = DWRITE_MAKE_OPENTYPE_TAG('v','e','r','t'); + vert_feature.flags = FEATURE_GLOBAL | FEATURE_GLOBAL_SEARCH; + vert_feature.max_value = 1; + vert_feature.default_value = 1; + + features.features = &vert_feature; + features.count = features.capacity = 1; + + opentype_layout_collect_lookups(&context, ~0u, ~0u, &features, context.table, &lookups); + opentype_layout_set_glyph_masks(&context, &features); + + for (i = 0; i < lookups.count; ++i) + { + const struct lookup *lookup = &lookups.lookups[i]; + + if (lookup->type != GSUB_LOOKUP_SINGLE_SUBST) + continue; + + context.cur = 0; + while (context.cur < context.glyph_count) + { + BOOL ret = FALSE; + + if (lookup_is_glyph_match(&context, context.cur, lookup->flags)) + ret = opentype_layout_apply_gsub_lookup(&context, lookup); + + if (!ret) + context.cur++; + } + } + + heap_free(context.u.subst.glyph_props); + heap_free(context.glyph_infos); + heap_free(lookups.lookups); + + return S_OK; +} diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 7c48a57eab6..f8abbf9e4b4 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -9736,6 +9736,48 @@ static void test_IsColorFont(void) ok(refcount == 0, "Factory not released, refcount %u.\n", refcount); }
+static void test_GetVerticalGlyphVariants(void) +{ + UINT16 glyphs[1], glyph_variants[1]; + IDWriteFontFace1 *fontface1; + IDWriteFontFace *fontface; + IDWriteFactory *factory; + unsigned int ch; + ULONG refcount; + HRESULT hr; + BOOL ret; + + factory = create_factory(); + + fontface = create_fontface(factory); + hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void **)&fontface1); + IDWriteFontFace_Release(fontface); + if (FAILED(hr)) + { + win_skip("GetVerticalGlyphVariants() is not supported.\n"); + IDWriteFactory_Release(factory); + return; + } + + ch = 'A'; + *glyphs = 0; + hr = IDWriteFontFace1_GetGlyphIndices(fontface1, &ch, 1, glyphs); + ok(hr == S_OK, "Failed to get glyph, hr %#x.\n", hr); + ok(!!*glyphs, "Unexpected glyph %u.\n", glyphs[0]); + + memset(glyph_variants, 0, sizeof(glyph_variants)); + hr = IDWriteFontFace1_GetVerticalGlyphVariants(fontface1, 1, glyphs, glyph_variants); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(glyphs[0] == glyph_variants[0], "Unexpected glyph.\n"); + + ret = IDWriteFontFace1_HasVerticalGlyphVariants(fontface1); + ok(!ret, "Unexpected flag.\n"); + + IDWriteFontFace1_Release(fontface1); + refcount = IDWriteFactory_Release(factory); + ok(!refcount, "Factory not released, refcount %u.\n", refcount); +} + START_TEST(font) { IDWriteFactory *factory; @@ -9805,6 +9847,7 @@ START_TEST(font) test_fontsetbuilder(); test_font_resource(); test_IsColorFont(); + test_GetVerticalGlyphVariants();
IDWriteFactory_Release(factory); }