[PATCH] dwrite: Initial implementation of ComputeGlyphOrigins()

Nikolay Sivov nsivov at codeweavers.com
Fri Apr 7 06:06:12 CDT 2017


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/main.c       | 82 +++++++++++++++++++++++++++++++++++++++++++++---
 dlls/dwrite/tests/font.c | 65 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 143 insertions(+), 4 deletions(-)

diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 9b5de8aeea..067bc8a3ce 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -21,6 +21,7 @@
 #define COBJMACROS
 
 #include <stdarg.h>
+#include <math.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -1438,14 +1439,86 @@ static HRESULT WINAPI dwritefactory4_TranslateColorGlyphRun(IDWriteFactory4 *ifa
     return E_NOTIMPL;
 }
 
+static HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode,
+    D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform,  D2D1_POINT_2F *origins)
+{
+    IDWriteFontFace1 *fontface1 = NULL;
+    DWRITE_FONT_METRICS metrics;
+    FLOAT rtl_factor;
+    UINT32 i;
+
+    rtl_factor = run->bidiLevel & 1 ? -1.0f : 1.0f;
+
+    if (run->fontFace) {
+        IDWriteFontFace_GetMetrics(run->fontFace, &metrics);
+        IDWriteFontFace_QueryInterface(run->fontFace, &IID_IDWriteFontFace1, (void **)&fontface1);
+    }
+
+    for (i = 0; i < run->glyphCount; i++) {
+        FLOAT advance;
+
+        /* Use nominal advances if not provided by caller. */
+        if (run->glyphAdvances)
+            advance = rtl_factor * run->glyphAdvances[i];
+        else {
+            INT32 a;
+
+            advance = 0.0f;
+            switch (measuring_mode)
+            {
+            case DWRITE_MEASURING_MODE_NATURAL:
+                if (SUCCEEDED(IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, run->glyphIndices + i, &a,
+                        run->isSideways)))
+                    advance = rtl_factor * get_scaled_advance_width(a, run->fontEmSize, &metrics);
+                break;
+            case DWRITE_MEASURING_MODE_GDI_CLASSIC:
+            case DWRITE_MEASURING_MODE_GDI_NATURAL:
+                if (SUCCEEDED(IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, run->fontEmSize,
+                        1.0f, transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL,
+                        run->isSideways, 1, run->glyphIndices + i, &a)))
+                    advance = rtl_factor * floorf(a * run->fontEmSize / metrics.designUnitsPerEm + 0.5f);
+                break;
+            default:
+                ;
+            }
+        }
+
+        origins[i] = baseline_origin;
+
+        /* Apply offsets. */
+        if (run->glyphOffsets) {
+            FLOAT advanceoffset = rtl_factor * run->glyphOffsets[i].advanceOffset;
+            FLOAT ascenderoffset = -run->glyphOffsets[i].ascenderOffset;
+
+            if (run->isSideways) {
+                origins[i].x += ascenderoffset;
+                origins[i].y += advanceoffset;
+            }
+            else {
+                origins[i].x += advanceoffset;
+                origins[i].y += ascenderoffset;
+            }
+        }
+
+        if (run->isSideways)
+            baseline_origin.y += advance;
+        else
+            baseline_origin.x += advance;
+    }
+
+    if (fontface1)
+        IDWriteFontFace1_Release(fontface1);
+    return S_OK;
+}
+
 static HRESULT WINAPI dwritefactory4_ComputeGlyphOrigins_(IDWriteFactory4 *iface, DWRITE_GLYPH_RUN const *run,
     D2D1_POINT_2F baseline_origin, D2D1_POINT_2F *origins)
 {
     struct dwritefactory *This = impl_from_IDWriteFactory4(iface);
 
-    FIXME("(%p)->(%p %p): stub\n", This, run, origins);
+    TRACE("(%p)->(%p (%f,%f) %p)\n", This, run, baseline_origin.x, baseline_origin.y, origins);
 
-    return E_NOTIMPL;
+    return compute_glyph_origins(run, DWRITE_MEASURING_MODE_NATURAL, baseline_origin, NULL, origins);
 }
 
 static HRESULT WINAPI dwritefactory4_ComputeGlyphOrigins(IDWriteFactory4 *iface, DWRITE_GLYPH_RUN const *run,
@@ -1454,9 +1527,10 @@ static HRESULT WINAPI dwritefactory4_ComputeGlyphOrigins(IDWriteFactory4 *iface,
 {
     struct dwritefactory *This = impl_from_IDWriteFactory4(iface);
 
-    FIXME("(%p)->(%p %d %p %p): stub\n", This, run, measuring_mode, transform, origins);
+    TRACE("(%p)->(%p %d (%f,%f) %p %p)\n", This, run, measuring_mode, baseline_origin.x, baseline_origin.y,
+        transform, origins);
 
-    return E_NOTIMPL;
+    return compute_glyph_origins(run, measuring_mode, baseline_origin, transform, origins);
 }
 
 static const struct IDWriteFactory4Vtbl dwritefactoryvtbl = {
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 2bdc024a04..79aebe3ebe 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -6858,6 +6858,70 @@ static void test_HasKerningPairs(void)
     IDWriteFactory_Release(factory);
 }
 
+static void test_ComputeGlyphOrigins(void)
+{
+    IDWriteFactory4 *factory4;
+    IDWriteFactory *factory;
+    DWRITE_GLYPH_RUN run;
+    HRESULT hr;
+    D2D1_POINT_2F origins[2];
+    D2D1_POINT_2F baseline_origin;
+    UINT16 glyphs[2];
+    FLOAT advances[2];
+    DWRITE_MATRIX m;
+
+    factory = create_factory();
+    hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory4, (void **)&factory4);
+    IDWriteFactory_Release(factory);
+    if (FAILED(hr)) {
+        win_skip("ComputeGlyphOrigins() is not supported.\n");
+        return;
+    }
+
+    advances[0] = 10.0f;
+    advances[1] = 20.0f;
+
+    run.fontFace = NULL;
+    run.fontEmSize = 16.0f;
+    run.glyphCount = 2;
+    run.glyphIndices = glyphs;
+    run.glyphAdvances = advances;
+    run.glyphOffsets = NULL;
+    run.isSideways = FALSE;
+    run.bidiLevel = 0;
+
+    baseline_origin.x = 123.0f;
+    baseline_origin.y = 321.0f;
+
+    memset(origins, 0, sizeof(origins));
+    hr = IDWriteFactory4_ComputeGlyphOrigins_(factory4, &run, baseline_origin, origins);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(origins[0].x == 123.0f && origins[0].y == 321.0f, "origins[0] %f,%f\n", origins[0].x, origins[0].y);
+    ok(origins[1].x == 133.0f && origins[1].y == 321.0f, "origins[1] %f,%f\n", origins[1].x, origins[1].y);
+
+    memset(origins, 0, sizeof(origins));
+    hr = IDWriteFactory4_ComputeGlyphOrigins(factory4, &run, DWRITE_MEASURING_MODE_NATURAL, baseline_origin,
+        NULL, origins);
+    ok(origins[0].x == 123.0f && origins[0].y == 321.0f, "origins[0] %f,%f\n", origins[0].x, origins[0].y);
+    ok(origins[1].x == 133.0f && origins[1].y == 321.0f, "origins[1] %f,%f\n", origins[1].x, origins[1].y);
+
+    /* transform is not applied to returned origins */
+    m.m11 = 2.0f;
+    m.m12 = 0.0f;
+    m.m21 = 0.0f;
+    m.m22 = 1.0f;
+    m.dx = 0.0f;
+    m.dy = 0.0f;
+
+    memset(origins, 0, sizeof(origins));
+    hr = IDWriteFactory4_ComputeGlyphOrigins(factory4, &run, DWRITE_MEASURING_MODE_NATURAL, baseline_origin,
+        &m, origins);
+    ok(origins[0].x == 123.0f && origins[0].y == 321.0f, "origins[0] %f,%f\n", origins[0].x, origins[0].y);
+    ok(origins[1].x == 133.0f && origins[1].y == 321.0f, "origins[1] %f,%f\n", origins[1].x, origins[1].y);
+
+    IDWriteFactory4_Release(factory4);
+}
+
 START_TEST(font)
 {
     IDWriteFactory *factory;
@@ -6917,6 +6981,7 @@ START_TEST(font)
     test_font_properties();
     test_HasVerticalGlyphVariants();
     test_HasKerningPairs();
+    test_ComputeGlyphOrigins();
 
     IDWriteFactory_Release(factory);
 }
-- 
2.11.0




More information about the wine-patches mailing list