Nikolay Sivov : dwrite: Implement GetGlyphOrientationTransform().

Alexandre Julliard julliard at wine.codeweavers.com
Fri May 29 05:29:48 CDT 2015


Module: wine
Branch: master
Commit: a921941a171a6194c92242a1c0b9af9aa2fe190b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a921941a171a6194c92242a1c0b9af9aa2fe190b

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Thu May 28 19:12:03 2015 +0300

dwrite: Implement GetGlyphOrientationTransform().

---

 dlls/dwrite/analyzer.c       |  66 ++++++++++++++++++--
 dlls/dwrite/tests/analyzer.c | 145 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 206 insertions(+), 5 deletions(-)

diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index b4be9f7..a1beeb3 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -1320,8 +1320,8 @@ static HRESULT WINAPI dwritetextanalyzer1_AnalyzeVerticalGlyphOrientation(IDWrit
 static HRESULT WINAPI dwritetextanalyzer1_GetGlyphOrientationTransform(IDWriteTextAnalyzer2 *iface,
     DWRITE_GLYPH_ORIENTATION_ANGLE angle, BOOL is_sideways, DWRITE_MATRIX *transform)
 {
-    FIXME("(%d %d %p): stub\n", angle, is_sideways, transform);
-    return E_NOTIMPL;
+    TRACE("(%d %d %p)\n", angle, is_sideways, transform);
+    return IDWriteTextAnalyzer2_GetGlyphOrientationTransform(iface, angle, is_sideways, 0.0, 0.0, transform);
 }
 
 static HRESULT WINAPI dwritetextanalyzer1_GetScriptProperties(IDWriteTextAnalyzer2 *iface, DWRITE_SCRIPT_ANALYSIS sa,
@@ -1425,10 +1425,66 @@ static HRESULT WINAPI dwritetextanalyzer1_GetJustifiedGlyphs(IDWriteTextAnalyzer
 }
 
 static HRESULT WINAPI dwritetextanalyzer2_GetGlyphOrientationTransform(IDWriteTextAnalyzer2 *iface,
-    DWRITE_GLYPH_ORIENTATION_ANGLE angle, BOOL is_sideways, FLOAT originX, FLOAT originY, DWRITE_MATRIX *transform)
+    DWRITE_GLYPH_ORIENTATION_ANGLE angle, BOOL is_sideways, FLOAT originX, FLOAT originY, DWRITE_MATRIX *m)
 {
-    FIXME("(%d %d %.2f %.2f %p): stub\n", angle, is_sideways, originX, originY, transform);
-    return E_NOTIMPL;
+    static const DWRITE_MATRIX transforms[] = {
+        {  1.0,  0.0,  0.0,  1.0, 0.0, 0.0 },
+        {  0.0,  1.0, -1.0,  0.0, 0.0, 0.0 },
+        { -1.0,  0.0,  0.0, -1.0, 0.0, 0.0 },
+        {  0.0, -1.0,  1.0,  0.0, 0.0, 0.0 }
+    };
+
+    TRACE("(%d %d %.2f %.2f %p)\n", angle, is_sideways, originX, originY, m);
+
+    if ((UINT32)angle > DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES) {
+        memset(m, 0, sizeof(*m));
+        return E_INVALIDARG;
+    }
+
+    /* for sideways case simply rotate 90 degrees more */
+    if (is_sideways) {
+        switch (angle) {
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES:
+            angle = DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES;
+            break;
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES:
+            angle = DWRITE_GLYPH_ORIENTATION_ANGLE_180_DEGREES;
+            break;
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_180_DEGREES:
+            angle = DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES;
+            break;
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES:
+            angle = DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES;
+            break;
+        default:
+            ;
+        }
+    }
+
+    *m = transforms[angle];
+
+    /* shift components represent transform necessary to get from original point to
+       rotated one in new coordinate system */
+    if ((originX != 0.0 || originY != 0.0) && angle != DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES) {
+        const DWRITE_MATRIX *p;
+
+        switch (angle) {
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES:
+            angle = DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES;
+            break;
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES:
+            angle = DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES;
+            break;
+        default:
+            ;
+        }
+
+        p = &transforms[angle];
+        m->dx = originX - (p->m11 * originX + p->m12 * originY);
+        m->dy = originY - (p->m21 * originX + p->m22 * originY);
+    }
+
+    return S_OK;
 }
 
 static HRESULT WINAPI dwritetextanalyzer2_GetTypographicFeatures(IDWriteTextAnalyzer2 *iface,
diff --git a/dlls/dwrite/tests/analyzer.c b/dlls/dwrite/tests/analyzer.c
index ffa4aed..15814c0 100644
--- a/dlls/dwrite/tests/analyzer.c
+++ b/dlls/dwrite/tests/analyzer.c
@@ -21,6 +21,7 @@
 #define COBJMACROS
 
 #include <assert.h>
+#include <stdio.h>
 
 #include "initguid.h"
 #include "windows.h"
@@ -1669,6 +1670,149 @@ static void test_ApplyCharacterSpacing(void)
     IDWriteTextAnalyzer1_Release(analyzer1);
 }
 
+struct orientation_transf_test {
+    DWRITE_GLYPH_ORIENTATION_ANGLE angle;
+    BOOL is_sideways;
+    DWRITE_MATRIX m;
+};
+
+static const struct orientation_transf_test ot_tests[] = {
+    { DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES,   FALSE, {  1.0,  0.0,  0.0,  1.0, 0.0, 0.0 } },
+    { DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES,  FALSE, {  0.0,  1.0, -1.0,  0.0, 0.0, 0.0 } },
+    { DWRITE_GLYPH_ORIENTATION_ANGLE_180_DEGREES, FALSE, { -1.0,  0.0,  0.0, -1.0, 0.0, 0.0 } },
+    { DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES, FALSE, {  0.0, -1.0,  1.0,  0.0, 0.0, 0.0 } },
+    { DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES,   TRUE,  {  0.0,  1.0, -1.0,  0.0, 0.0, 0.0 } },
+    { DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES,  TRUE,  { -1.0,  0.0,  0.0, -1.0, 0.0, 0.0 } },
+    { DWRITE_GLYPH_ORIENTATION_ANGLE_180_DEGREES, TRUE,  {  0.0, -1.0,  1.0,  0.0, 0.0, 0.0 } },
+    { DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES, TRUE,  {  1.0,  0.0,  0.0,  1.0, 0.0, 0.0 } }
+};
+
+static inline const char *dbgstr_matrix(const DWRITE_MATRIX *m)
+{
+    static char buff[64];
+    sprintf(buff, "{%.2f, %.2f, %.2f, %.2f, %.2f, %.2f}", m->m11, m->m12,
+        m->m21, m->m22, m->dx, m->dy);
+    return buff;
+}
+
+static void test_GetGlyphOrientationTransform(void)
+{
+    IDWriteTextAnalyzer2 *analyzer2;
+    IDWriteTextAnalyzer1 *analyzer1;
+    IDWriteTextAnalyzer *analyzer;
+    FLOAT originx, originy;
+    DWRITE_MATRIX m;
+    HRESULT hr;
+    int i;
+
+    hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IDWriteTextAnalyzer_QueryInterface(analyzer, &IID_IDWriteTextAnalyzer1, (void**)&analyzer1);
+    IDWriteTextAnalyzer_Release(analyzer);
+    if (hr != S_OK) {
+        win_skip("GetGlyphOrientationTransform() is not supported.\n");
+        return;
+    }
+
+    /* invalid angle value */
+    memset(&m, 0xcc, sizeof(m));
+    hr = IDWriteTextAnalyzer1_GetGlyphOrientationTransform(analyzer1,
+        DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES + 1, FALSE, &m);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(m.m11 == 0.0, "got %.2f\n", m.m11);
+
+    for (i = 0; i < sizeof(ot_tests)/sizeof(ot_tests[0]); i++) {
+        memset(&m, 0, sizeof(m));
+        hr = IDWriteTextAnalyzer1_GetGlyphOrientationTransform(analyzer1, ot_tests[i].angle,
+            ot_tests[i].is_sideways, &m);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!memcmp(&ot_tests[i].m, &m, sizeof(m)), "%d: wrong matrix %s\n", i, dbgstr_matrix(&m));
+    }
+
+    hr = IDWriteTextAnalyzer1_QueryInterface(analyzer1, &IID_IDWriteTextAnalyzer2, (void**)&analyzer2);
+    IDWriteTextAnalyzer1_Release(analyzer1);
+    if (hr != S_OK) {
+        win_skip("IDWriteTextAnalyzer2::GetGlyphOrientationTransform() is not supported.\n");
+        return;
+    }
+
+    /* invalid angle value */
+    memset(&m, 0xcc, sizeof(m));
+    hr = IDWriteTextAnalyzer2_GetGlyphOrientationTransform(analyzer2,
+        DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES + 1, FALSE, 0.0, 0.0, &m);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(m.m11 == 0.0, "got %.2f\n", m.m11);
+
+    originx = 50.0;
+    originy = 60.0;
+    for (i = 0; i < sizeof(ot_tests)/sizeof(ot_tests[0]); i++) {
+        DWRITE_GLYPH_ORIENTATION_ANGLE angle = DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES;
+        DWRITE_MATRIX m_exp;
+
+        memset(&m, 0, sizeof(m));
+
+        /* zero offset gives same result as a call from IDWriteTextAnalyzer1 */
+        hr = IDWriteTextAnalyzer2_GetGlyphOrientationTransform(analyzer2, ot_tests[i].angle,
+            ot_tests[i].is_sideways, 0.0, 0.0, &m);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!memcmp(&ot_tests[i].m, &m, sizeof(m)), "%d: wrong matrix %s\n", i, dbgstr_matrix(&m));
+
+        m_exp = ot_tests[i].m;
+        hr = IDWriteTextAnalyzer2_GetGlyphOrientationTransform(analyzer2, ot_tests[i].angle,
+            ot_tests[i].is_sideways, originx, originy, &m);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        /* 90 degrees more for sideways */
+        if (ot_tests[i].is_sideways) {
+            switch (ot_tests[i].angle)
+            {
+            case DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES:
+                angle = DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES;
+                break;
+            case DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES:
+                angle = DWRITE_GLYPH_ORIENTATION_ANGLE_180_DEGREES;
+                break;
+            case DWRITE_GLYPH_ORIENTATION_ANGLE_180_DEGREES:
+                angle = DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES;
+                break;
+            case DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES:
+                angle = DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES;
+                break;
+            default:
+                ;
+            }
+        }
+        else
+            angle = ot_tests[i].angle;
+
+        /* set expected offsets */
+        switch (angle)
+        {
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES:
+            break;
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES:
+            m_exp.dx = originx + originy;
+            m_exp.dy = originy - originx;
+            break;
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_180_DEGREES:
+            m_exp.dx = originx + originx;
+            m_exp.dy = originy + originy;
+            break;
+        case DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES:
+            m_exp.dx = originx - originy;
+            m_exp.dy = originy + originx;
+            break;
+        default:
+            ;
+        }
+
+        ok(!memcmp(&m_exp, &m, sizeof(m)), "%d: wrong matrix %s\n", i, dbgstr_matrix(&m));
+    }
+
+    IDWriteTextAnalyzer2_Release(analyzer2);
+}
+
 START_TEST(analyzer)
 {
     HRESULT hr;
@@ -1693,6 +1837,7 @@ START_TEST(analyzer)
     test_GetTypographicFeatures();
     test_GetGlyphPlacements();
     test_ApplyCharacterSpacing();
+    test_GetGlyphOrientationTransform();
 
     IDWriteFactory_Release(factory);
 }




More information about the wine-cvs mailing list