[PATCH 1/2] dwrite: Advances and offsets are optional for IDWriteGlyphRunAnalysis

Nikolay Sivov nsivov at codeweavers.com
Tue Aug 4 03:16:10 CDT 2015


---
-------------- next part --------------
>From c25ade69962242856bd0fe2d5aeaaeb4c02297ff Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue, 4 Aug 2015 10:20:05 +0300
Subject: [PATCH 1/2] dwrite: Advances and offsets are optional for
 IDWriteGlyphRunAnalysis

---
 dlls/dwrite/analyzer.c       |  5 ----
 dlls/dwrite/dwrite_private.h |  7 ++++-
 dlls/dwrite/font.c           | 70 ++++++++++++++++++++++++++++++++++++--------
 dlls/dwrite/main.c           |  2 +-
 dlls/dwrite/tests/font.c     | 69 ++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 133 insertions(+), 20 deletions(-)

diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index eedb41d..448a212 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -1016,11 +1016,6 @@ done:
     return hr;
 }
 
-static inline FLOAT get_scaled_advance_width(INT32 advance, FLOAT emSize, const DWRITE_FONT_METRICS *metrics)
-{
-    return (FLOAT)advance * emSize / (FLOAT)metrics->designUnitsPerEm;
-}
-
 static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2 *iface,
     WCHAR const* text, UINT16 const* clustermap, DWRITE_SHAPING_TEXT_PROPERTIES* props,
     UINT32 text_len, UINT16 const* glyphs, DWRITE_SHAPING_GLYPH_PROPERTIES const* glyph_props,
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index b0168ae..75098cf 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -104,6 +104,11 @@ static inline unsigned short get_table_entry(const unsigned short *table, WCHAR
     return table[table[table[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0xf)];
 }
 
+static inline FLOAT get_scaled_advance_width(INT32 advance, FLOAT emSize, const DWRITE_FONT_METRICS *metrics)
+{
+    return (FLOAT)advance * emSize / (FLOAT)metrics->designUnitsPerEm;
+}
+
 extern HRESULT convert_fontface_to_logfont(IDWriteFontFace*, LOGFONTW*) DECLSPEC_HIDDEN;
 extern HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD,const WCHAR *locale,BOOL,IDWriteNumberSubstitution**) DECLSPEC_HIDDEN;
 extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
@@ -124,7 +129,7 @@ extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *refer
 extern HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface) DECLSPEC_HIDDEN;
 extern HRESULT create_fontface(DWRITE_FONT_FACE_TYPE,UINT32,IDWriteFontFile* const*,UINT32,DWRITE_FONT_SIMULATIONS,IDWriteFontFace2**) DECLSPEC_HIDDEN;
 extern HRESULT create_font_collection(IDWriteFactory2*,IDWriteFontFileEnumerator*,BOOL,IDWriteFontCollection**) DECLSPEC_HIDDEN;
-extern HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE,DWRITE_GLYPH_RUN const*,FLOAT,FLOAT,FLOAT,IDWriteGlyphRunAnalysis**) DECLSPEC_HIDDEN;
+extern HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE,DWRITE_MEASURING_MODE,DWRITE_GLYPH_RUN const*,FLOAT,FLOAT,FLOAT,IDWriteGlyphRunAnalysis**) DECLSPEC_HIDDEN;
 extern BOOL    is_system_collection(IDWriteFontCollection*) DECLSPEC_HIDDEN;
 extern HRESULT get_local_refkey(const WCHAR*,const FILETIME*,void**,UINT32*) DECLSPEC_HIDDEN;
 extern HRESULT get_filestream_from_file(IDWriteFontFile*,IDWriteFontFileStream**) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index d72f8a6..707ef6d 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -2946,16 +2946,19 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
     origin_x = 0.0;
     is_rtl = analysis->run.bidiLevel & 1;
     for (i = 0; i < analysis->run.glyphCount; i++) {
-        const DWRITE_GLYPH_OFFSET *offset = &analysis->offsets[i];
+        const DWRITE_GLYPH_OFFSET *offset = analysis->offsets ? &analysis->offsets[i] : NULL;
         FLOAT advance = analysis->advances[i];
         RECT bbox;
 
         freetype_get_glyph_bbox(fontface2, analysis->run.fontEmSize * analysis->ppdip, analysis->run.glyphIndices[i], nohint, &bbox);
 
         if (is_rtl)
-            OffsetRect(&bbox, origin_x - offset->advanceOffset - advance, -offset->ascenderOffset);
+            OffsetRect(&bbox, origin_x - advance, 0);
         else
-            OffsetRect(&bbox, origin_x + offset->advanceOffset, offset->ascenderOffset);
+            OffsetRect(&bbox, origin_x, 0);
+
+        if (offset)
+            OffsetRect(&bbox, is_rtl ? -offset->advanceOffset : offset->advanceOffset, is_rtl ? -offset->ascenderOffset : offset->ascenderOffset);
 
         UnionRect(&analysis->bounds, &analysis->bounds, &bbox);
         origin_x += is_rtl ? -advance : advance;
@@ -3026,7 +3029,7 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
     origin_x = 0.0;
     is_rtl = analysis->run.bidiLevel & 1;
     for (i = 0; i < analysis->run.glyphCount; i++) {
-        const DWRITE_GLYPH_OFFSET *offset = &analysis->offsets[i];
+        const DWRITE_GLYPH_OFFSET *offset = analysis->offsets ? &analysis->offsets[i] : NULL;
         FLOAT advance = analysis->advances[i];
         int pitch, x, y, width, height;
         BYTE *glyph, *src, *dst;
@@ -3047,9 +3050,12 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
         freetype_get_glyph_bitmap(fontface2, analysis->run.fontEmSize * analysis->ppdip, analysis->run.glyphIndices[i], &bbox, glyph);
 
         if (is_rtl)
-            OffsetRect(&bbox, origin_x - offset->advanceOffset - advance, -offset->ascenderOffset);
+            OffsetRect(&bbox, origin_x - advance, 0);
         else
-            OffsetRect(&bbox, origin_x + offset->advanceOffset, offset->ascenderOffset);
+            OffsetRect(&bbox, origin_x, 0);
+
+        if (offset)
+            OffsetRect(&bbox, is_rtl ? -offset->advanceOffset : offset->advanceOffset, is_rtl ? -offset->ascenderOffset : offset->ascenderOffset);
 
         OffsetRect(&bbox, analysis->originX, analysis->originY);
 
@@ -3193,8 +3199,8 @@ static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl = {
     glyphrunanalysis_GetAlphaBlendParams
 };
 
-HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_GLYPH_RUN const *run, FLOAT ppdip,
-    FLOAT originX, FLOAT originY, IDWriteGlyphRunAnalysis **ret)
+HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode, DWRITE_GLYPH_RUN const *run,
+    FLOAT ppdip, FLOAT originX, FLOAT originY, IDWriteGlyphRunAnalysis **ret)
 {
     struct dwrite_glyphrunanalysis *analysis;
 
@@ -3221,8 +3227,8 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_GLY
     IDWriteFontFace_AddRef(analysis->run.fontFace);
     analysis->glyphs = heap_alloc(run->glyphCount*sizeof(*run->glyphIndices));
     analysis->advances = heap_alloc(run->glyphCount*sizeof(*run->glyphAdvances));
-    analysis->offsets = heap_alloc(run->glyphCount*sizeof(*run->glyphOffsets));
-    if (!analysis->glyphs || !analysis->advances || !analysis->offsets) {
+    analysis->offsets = run->glyphOffsets ? heap_alloc(run->glyphCount*sizeof(*run->glyphOffsets)) : NULL;
+    if (!analysis->glyphs || !analysis->advances || (!analysis->offsets && run->glyphOffsets)) {
         heap_free(analysis->glyphs);
         heap_free(analysis->advances);
         heap_free(analysis->offsets);
@@ -3240,8 +3246,48 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_GLY
     analysis->run.glyphOffsets = analysis->offsets;
 
     memcpy(analysis->glyphs, run->glyphIndices, run->glyphCount*sizeof(*run->glyphIndices));
-    memcpy(analysis->advances, run->glyphAdvances, run->glyphCount*sizeof(*run->glyphAdvances));
-    memcpy(analysis->offsets, run->glyphOffsets, run->glyphCount*sizeof(*run->glyphOffsets));
+
+    if (run->glyphAdvances)
+        memcpy(analysis->advances, run->glyphAdvances, run->glyphCount*sizeof(*run->glyphAdvances));
+    else {
+        DWRITE_FONT_METRICS metrics;
+        IDWriteFontFace1 *fontface1;
+        UINT32 i;
+
+        IDWriteFontFace_GetMetrics(run->fontFace, &metrics);
+        IDWriteFontFace_QueryInterface(run->fontFace, &IID_IDWriteFontFace1, (void**)&fontface1);
+
+        for (i = 0; i < run->glyphCount; i++) {
+            HRESULT hr;
+            INT32 a;
+
+            switch (measuring_mode)
+            {
+            case DWRITE_MEASURING_MODE_NATURAL:
+                hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, run->glyphIndices + i, &a, run->isSideways);
+                if (FAILED(hr))
+                    a = 0;
+                analysis->advances[i] = get_scaled_advance_width(a, run->fontEmSize, &metrics);
+                break;
+            case DWRITE_MEASURING_MODE_GDI_CLASSIC:
+            case DWRITE_MEASURING_MODE_GDI_NATURAL:
+                hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, run->fontEmSize, ppdip, NULL /* FIXME */,
+                    measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, run->isSideways, 1, run->glyphIndices + i, &a);
+                if (FAILED(hr))
+                    analysis->advances[i] = 0.0;
+                else
+                    analysis->advances[i] = floorf(a * run->fontEmSize * ppdip / metrics.designUnitsPerEm + 0.5f) / ppdip;
+                break;
+            default:
+                ;
+            }
+        }
+
+        IDWriteFontFace1_Release(fontface1);
+    }
+
+    if (run->glyphOffsets)
+        memcpy(analysis->offsets, run->glyphOffsets, run->glyphCount*sizeof(*run->glyphOffsets));
 
     *ret = &analysis->IDWriteGlyphRunAnalysis_iface;
     return S_OK;
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 5a8c026..5673bba 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1079,7 +1079,7 @@ static HRESULT WINAPI dwritefactory_CreateGlyphRunAnalysis(IDWriteFactory2 *ifac
     TRACE("(%p)->(%p %.2f %p %d %d %.2f %.2f %p)\n", This, run, ppdip, transform, rendering_mode,
         measuring_mode, originX, originY, analysis);
 
-    return create_glyphrunanalysis(rendering_mode, run, ppdip, originX, originY, analysis);
+    return create_glyphrunanalysis(rendering_mode, measuring_mode, run, ppdip, originX, originY, analysis);
 }
 
 static HRESULT WINAPI dwritefactory1_GetEudcFontCollection(IDWriteFactory2 *iface, IDWriteFontCollection **collection,
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index c132159..0eca7f4 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -3431,7 +3431,7 @@ static void test_CreateGlyphRunAnalysis(void)
     IDWriteFactory *factory;
     DWRITE_GLYPH_RUN run;
     IDWriteFontFace *face;
-    UINT16 glyph;
+    UINT16 glyph, glyphs[10];
     FLOAT advance;
     HRESULT hr;
     UINT32 ch;
@@ -3578,6 +3578,73 @@ static void test_CreateGlyphRunAnalysis(void)
         IDWriteGlyphRunAnalysis_Release(analysis);
     }
 
+    /* without offsets */
+    run.fontFace = face;
+    run.fontEmSize = 24.0;
+    run.glyphCount = 1;
+    run.glyphIndices = &glyph;
+    run.glyphAdvances = &advance;
+    run.glyphOffsets = NULL;
+    run.isSideways = FALSE;
+    run.bidiLevel = 0;
+
+    hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
+        DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
+        0.0, 0.0, &analysis);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    SetRectEmpty(&rect);
+    hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(!IsRectEmpty(&rect), "got empty bounds\n");
+
+    IDWriteGlyphRunAnalysis_Release(analysis);
+
+    /* without explicit advances */
+    run.fontFace = face;
+    run.fontEmSize = 24.0;
+    run.glyphCount = 1;
+    run.glyphIndices = &glyph;
+    run.glyphAdvances = NULL;
+    run.glyphOffsets = NULL;
+    run.isSideways = FALSE;
+    run.bidiLevel = 0;
+
+    hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
+        DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
+        0.0, 0.0, &analysis);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    SetRectEmpty(&rect);
+    hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(!IsRectEmpty(&rect), "got empty bounds\n");
+
+    IDWriteGlyphRunAnalysis_Release(analysis);
+
+    glyphs[0] = glyphs[1] = glyph;
+    run.fontFace = face;
+    run.fontEmSize = 24.0;
+    run.glyphCount = 2;
+    run.glyphIndices = glyphs;
+    run.glyphAdvances = NULL;
+    run.glyphOffsets = NULL;
+    run.isSideways = FALSE;
+    run.bidiLevel = 0;
+
+    hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
+        DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
+        0.0, 0.0, &analysis);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    SetRectEmpty(&rect2);
+    hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect2);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(!IsRectEmpty(&rect2), "got empty bounds\n");
+    ok(!EqualRect(&rect, &rect2), "got wrong rect2\n");
+
+    IDWriteGlyphRunAnalysis_Release(analysis);
+
     IDWriteFontFace_Release(face);
     IDWriteFactory_Release(factory);
 }
-- 
2.1.4



More information about the wine-patches mailing list