diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index b4be9f7cc1a..a1beeb33d72 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 ffa4aed460c..15814c0d91a 100644 --- a/dlls/dwrite/tests/analyzer.c +++ b/dlls/dwrite/tests/analyzer.c @@ -21,6 +21,7 @@ #define COBJMACROS #include +#include #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); }