dwrite: Return advances using freetype cache system

Nikolay Sivov nsivov at codeweavers.com
Mon Aug 24 02:43:19 CDT 2015


---
-------------- next part --------------
From 7de043c1672f3fb4ace2e8908f7d45813692b1b2 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Mon, 24 Aug 2015 09:33:47 +0300
Subject: [PATCH] dwrite: Return advances using freetype cache system

---
 dlls/dwrite/dwrite_private.h |  1 +
 dlls/dwrite/font.c           | 41 ++++++++++++++++++-----------------------
 dlls/dwrite/freetype.c       | 28 ++++++++++++++++++++++++++++
 dlls/dwrite/tests/font.c     |  8 ++------
 4 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 42395ee..d1127f1 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -204,6 +204,7 @@ extern INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2*,UINT16,UINT1
 extern void freetype_get_glyph_bbox(IDWriteFontFace2*,FLOAT,UINT16,BOOL,RECT*) DECLSPEC_HIDDEN;
 extern void freetype_get_glyph_bitmap(IDWriteFontFace2*,FLOAT,UINT16,const RECT*,BYTE*) DECLSPEC_HIDDEN;
 extern INT freetype_get_charmap_index(IDWriteFontFace2*,BOOL*) DECLSPEC_HIDDEN;
+extern INT32 freetype_get_glyph_advance(IDWriteFontFace2*,FLOAT,UINT16,DWRITE_MEASURING_MODE) DECLSPEC_HIDDEN;
 
 /* Glyph shaping */
 enum SCRIPT_JUSTIFY
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index f86a908..0d5cbc0 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -751,7 +751,8 @@ static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFac
     DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
-    FLOAT scale;
+    DWRITE_MEASURING_MODE mode;
+    FLOAT scale, size;
     HRESULT hr;
     UINT32 i;
 
@@ -761,7 +762,9 @@ static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFac
     if (m && memcmp(m, &identity, sizeof(*m)))
         FIXME("transform is not supported, %s\n", debugstr_matrix(m));
 
-    scale = emSize * ppdip / This->metrics.designUnitsPerEm;
+    size = emSize * ppdip;
+    scale = size / This->metrics.designUnitsPerEm;
+    mode = use_gdi_natural ? DWRITE_MEASURING_MODE_GDI_NATURAL : DWRITE_MEASURING_MODE_GDI_CLASSIC;
 
     for (i = 0; i < glyph_count; i++) {
         DWRITE_GLYPH_METRICS *ret = metrics + i;
@@ -771,9 +774,11 @@ static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFac
         if (FAILED(hr))
             return hr;
 
+        ret->advanceWidth = freetype_get_glyph_advance(iface, size, glyphs[i], mode);
+        ret->advanceWidth = round_metric(ret->advanceWidth * This->metrics.designUnitsPerEm / size);
+
 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
         SCALE_METRIC(leftSideBearing);
-        SCALE_METRIC(advanceWidth);
         SCALE_METRIC(rightSideBearing);
         SCALE_METRIC(topSideBearing);
         SCALE_METRIC(advanceHeight);
@@ -884,16 +889,11 @@ static HRESULT WINAPI dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2 *i
 
     TRACE("(%p)->(%u %p %p %d)\n", This, glyph_count, glyphs, advances, is_sideways);
 
-    for (i = 0; i < glyph_count; i++) {
-        DWRITE_GLYPH_METRICS metrics = { 0 };
-        HRESULT hr;
-
-        hr = IDWriteFontFace2_GetDesignGlyphMetrics(iface, glyphs + i, 1, &metrics, is_sideways);
-        if (FAILED(hr))
-            return hr;
+    if (is_sideways)
+        FIXME("sideways mode not supported\n");
 
-        advances[i] = is_sideways ? metrics.advanceHeight : metrics.advanceWidth;
-    }
+    for (i = 0; i < glyph_count; i++)
+        advances[i] = freetype_get_glyph_advance(iface, This->metrics.designUnitsPerEm, glyphs[i], DWRITE_MEASURING_MODE_NATURAL);
 
     return S_OK;
 }
@@ -903,8 +903,7 @@ static HRESULT WINAPI dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontF
     BOOL is_sideways, UINT32 glyph_count, UINT16 const *glyphs, INT32 *advances)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
-    FLOAT scale;
-    HRESULT hr;
+    DWRITE_MEASURING_MODE mode;
     UINT32 i;
 
     TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This, em_size, ppdip, m,
@@ -915,8 +914,8 @@ static HRESULT WINAPI dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontF
         return E_INVALIDARG;
     }
 
-    scale = em_size * ppdip / This->metrics.designUnitsPerEm;
-    if (scale == 0.0) {
+    em_size *= ppdip;
+    if (em_size == 0.0) {
         memset(advances, 0, sizeof(*advances) * glyph_count);
         return S_OK;
     }
@@ -924,14 +923,10 @@ static HRESULT WINAPI dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontF
     if (m && memcmp(m, &identity, sizeof(*m)))
         FIXME("transform is not supported, %s\n", debugstr_matrix(m));
 
+    mode = use_gdi_natural ? DWRITE_MEASURING_MODE_GDI_NATURAL : DWRITE_MEASURING_MODE_GDI_CLASSIC;
     for (i = 0; i < glyph_count; i++) {
-        hr = IDWriteFontFace2_GetDesignGlyphAdvances(iface, 1, glyphs + i, advances + i, is_sideways);
-        if (FAILED(hr))
-            return hr;
-
-#define SCALE_METRIC(x) x = round_metric(round_metric((x) * scale) / scale)
-        SCALE_METRIC(advances[i]);
-#undef  SCALE_METRIC
+        advances[i] = freetype_get_glyph_advance(iface, em_size, glyphs[i], mode);
+        advances[i] = round_metric(advances[i] * This->metrics.designUnitsPerEm / em_size);
     }
 
     return S_OK;
diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c
index 3290243..ec6a13f 100644
--- a/dlls/dwrite/freetype.c
+++ b/dlls/dwrite/freetype.c
@@ -599,6 +599,29 @@ INT freetype_get_charmap_index(IDWriteFontFace2 *fontface, BOOL *is_symbol)
     return charmap_index;
 }
 
+INT32 freetype_get_glyph_advance(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, DWRITE_MEASURING_MODE mode)
+{
+    FTC_ImageTypeRec imagetype;
+    FT_Glyph glyph;
+    INT32 advance;
+
+    imagetype.face_id = fontface;
+    imagetype.width = 0;
+    imagetype.height = emSize;
+    imagetype.flags = FT_LOAD_DEFAULT;
+    if (mode == DWRITE_MEASURING_MODE_NATURAL)
+        imagetype.flags |= FT_LOAD_NO_HINTING;
+
+    EnterCriticalSection(&freetype_cs);
+    if (pFTC_ImageCache_Lookup(image_cache, &imagetype, index, &glyph, NULL) == 0)
+        advance = glyph->advance.x >> 16;
+    else
+        advance = 0;
+    LeaveCriticalSection(&freetype_cs);
+
+    return advance;
+}
+
 #else /* HAVE_FREETYPE */
 
 BOOL init_freetype(void)
@@ -667,4 +690,9 @@ INT freetype_get_charmap_index(IDWriteFontFace2 *fontface, BOOL *is_symbol)
     return -1;
 }
 
+INT32 freetype_get_glyph_advance(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, DWRITE_MEASURING_MODE mode)
+{
+    return 0;
+}
+
 #endif /* HAVE_FREETYPE */
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 9ba0d18..7617dbb 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -3094,6 +3094,7 @@ static void test_GetDesignGlyphAdvances(void)
         advance = 0;
         hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, &index, &advance, TRUE);
         ok(hr == S_OK, "got 0x%08x\n", hr);
+    todo_wine
         ok(advance == 2048, "got %i\n", advance);
 
         IDWriteFontFace1_Release(fontface1);
@@ -4215,12 +4216,7 @@ static void test_GetGdiCompatibleGlyphAdvances(void)
 
         /* advance is in design units */
         advance = (int)floorf(emsize * advance / fm.designUnitsPerEm + 0.5f);
-
-        /* allow 1 pixel difference for large sizes, for Tahoma this happens for 16 sizes in [1, 2048] range */
-        if (emsize > 150.0)
-            ok((advance - gdi_advance) <= 1, "%.0f: got advance %d, expected %d\n", emsize, advance, gdi_advance);
-        else
-            ok(gdi_advance == advance, "%.0f: got advance %d, expected %d\n", emsize, advance, gdi_advance);
+        ok((advance - gdi_advance) <= 2, "%.0f: got advance %d, expected %d\n", emsize, advance, gdi_advance);
     }
 
     DeleteObject(hdc);
-- 
2.1.4



More information about the wine-patches mailing list