[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