[PATCH 2/5] dwrite: Implement GetVerticalGlyphVariants().

Nikolay Sivov nsivov at codeweavers.com
Wed Jun 10 09:21:30 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at 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);
 }
-- 
2.26.2




More information about the wine-devel mailing list