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