Nikolay Sivov : dwrite/layout: Split run shaping between two helpers.

Alexandre Julliard julliard at winehq.org
Tue Feb 16 16:03:19 CST 2021


Module: wine
Branch: master
Commit: 2655576be965c1c2fefcd4613c4e96c740973770
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=2655576be965c1c2fefcd4613c4e96c740973770

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Feb 16 12:48:39 2021 +0300

dwrite/layout: Split run shaping between two helpers.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dwrite/layout.c | 105 ++++++++++++++++++++++++++++++++-------------------
 1 file changed, 67 insertions(+), 38 deletions(-)

diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index a24752c9bff..73fe28e222a 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -934,47 +934,57 @@ fatal:
     return hr;
 }
 
-static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular_layout_run *run)
+struct shaping_context
 {
+    IDWriteTextAnalyzer *analyzer;
+    struct regular_layout_run *run;
     DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props;
     DWRITE_SHAPING_TEXT_PROPERTIES *text_props;
-    IDWriteTextAnalyzer *analyzer;
-    struct layout_range *range;
-    UINT32 max_count;
+};
+
+static void layout_shape_clear_context(struct shaping_context *context)
+{
+    heap_free(context->glyph_props);
+    heap_free(context->text_props);
+}
+
+static HRESULT layout_shape_get_glyphs(struct dwrite_textlayout *layout, struct shaping_context *context)
+{
+    struct regular_layout_run *run = context->run;
+    unsigned int max_count;
     HRESULT hr;
 
-    range = get_layout_range_by_pos(layout, run->descr.textPosition);
-    run->descr.localeName = range->locale;
+    run->descr.localeName = get_layout_range_by_pos(layout, run->descr.textPosition)->locale;
     run->clustermap = heap_calloc(run->descr.stringLength, sizeof(*run->clustermap));
+    if (!run->clustermap)
+        return E_OUTOFMEMORY;
 
     max_count = 3 * run->descr.stringLength / 2 + 16;
     run->glyphs = heap_calloc(max_count, sizeof(*run->glyphs));
-    if (!run->clustermap || !run->glyphs)
+    if (!run->glyphs)
         return E_OUTOFMEMORY;
 
-    text_props = heap_calloc(run->descr.stringLength, sizeof(*text_props));
-    glyph_props = heap_calloc(max_count, sizeof(*glyph_props));
-    if (!text_props || !glyph_props) {
-        heap_free(text_props);
-        heap_free(glyph_props);
+    context->text_props = heap_calloc(run->descr.stringLength, sizeof(*context->text_props));
+    context->glyph_props = heap_calloc(max_count, sizeof(*context->glyph_props));
+    if (!context->text_props || !context->glyph_props)
         return E_OUTOFMEMORY;
-    }
-
-    analyzer = get_text_analyzer();
 
-    for (;;) {
-        hr = IDWriteTextAnalyzer_GetGlyphs(analyzer, run->descr.string, run->descr.stringLength, run->run.fontFace,
+    for (;;)
+    {
+        hr = IDWriteTextAnalyzer_GetGlyphs(context->analyzer, run->descr.string, run->descr.stringLength, run->run.fontFace,
                 run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName, NULL /* FIXME */, NULL,
-                NULL, 0, max_count, run->clustermap, text_props, run->glyphs, glyph_props, &run->glyphcount);
-        if (hr == E_NOT_SUFFICIENT_BUFFER) {
+                NULL, 0, max_count, run->clustermap, context->text_props, run->glyphs, context->glyph_props, &run->glyphcount);
+        if (hr == E_NOT_SUFFICIENT_BUFFER)
+        {
             heap_free(run->glyphs);
-            heap_free(glyph_props);
+            heap_free(context->glyph_props);
 
             max_count = run->glyphcount;
 
             run->glyphs = heap_calloc(max_count, sizeof(*run->glyphs));
-            glyph_props = heap_calloc(max_count, sizeof(*glyph_props));
-            if (!run->glyphs || !glyph_props) {
+            context->glyph_props = heap_calloc(max_count, sizeof(*context->glyph_props));
+            if (!run->glyphs || !context->glyph_props)
+            {
                 hr = E_OUTOFMEMORY;
                 break;
             }
@@ -985,16 +995,20 @@ static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular
         break;
     }
 
-    if (FAILED(hr)) {
-        heap_free(text_props);
-        heap_free(glyph_props);
+    if (FAILED(hr))
         WARN("%s: shaping failed, hr %#x.\n", debugstr_rundescr(&run->descr), hr);
-        return hr;
-    }
 
     run->run.glyphIndices = run->glyphs;
     run->descr.clusterMap = run->clustermap;
 
+    return hr;
+}
+
+static HRESULT layout_shape_get_positions(struct dwrite_textlayout *layout, struct shaping_context *context)
+{
+    struct regular_layout_run *run = context->run;
+    HRESULT hr;
+
     run->advances = heap_calloc(run->glyphcount, sizeof(*run->advances));
     run->offsets = heap_calloc(run->glyphcount, sizeof(*run->offsets));
     if (!run->advances || !run->offsets)
@@ -1002,20 +1016,19 @@ static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular
 
     /* Get advances and offsets. */
     if (is_layout_gdi_compatible(layout))
-        hr = IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(analyzer, run->descr.string, run->descr.clusterMap,
-                text_props, run->descr.stringLength, run->run.glyphIndices, glyph_props, run->glyphcount,
+        hr = IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap,
+                context->text_props, run->descr.stringLength, run->run.glyphIndices, context->glyph_props, run->glyphcount,
                 run->run.fontFace, run->run.fontEmSize, layout->ppdip, &layout->transform,
                 layout->measuringmode == DWRITE_MEASURING_MODE_GDI_NATURAL, run->run.isSideways, run->run.bidiLevel & 1,
                 &run->sa, run->descr.localeName, NULL, NULL, 0, run->advances, run->offsets);
     else
-        hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, run->descr.string, run->descr.clusterMap, text_props,
-                run->descr.stringLength, run->run.glyphIndices, glyph_props, run->glyphcount, run->run.fontFace,
-                run->run.fontEmSize, run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName,
-                NULL, NULL, 0, run->advances, run->offsets);
-
-    heap_free(text_props);
-    heap_free(glyph_props);
-    if (FAILED(hr)) {
+        hr = IDWriteTextAnalyzer_GetGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap,
+                context->text_props, run->descr.stringLength, run->run.glyphIndices, context->glyph_props, run->glyphcount,
+                run->run.fontFace, run->run.fontEmSize, run->run.isSideways, run->run.bidiLevel & 1, &run->sa,
+                run->descr.localeName, NULL, NULL, 0, run->advances, run->offsets);
+
+    if (FAILED(hr))
+    {
         memset(run->advances, 0, run->glyphcount * sizeof(*run->advances));
         memset(run->offsets, 0, run->glyphcount * sizeof(*run->offsets));
         WARN("%s: failed to get glyph placement info, hr %#x.\n", debugstr_rundescr(&run->descr), hr);
@@ -1024,6 +1037,22 @@ static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular
     run->run.glyphAdvances = run->advances;
     run->run.glyphOffsets = run->offsets;
 
+    return hr;
+}
+
+static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular_layout_run *run)
+{
+    struct shaping_context context = { 0 };
+    HRESULT hr;
+
+    context.analyzer = get_text_analyzer();
+    context.run = run;
+
+    if (SUCCEEDED(hr = layout_shape_get_glyphs(layout, &context)))
+        hr = layout_shape_get_positions(layout, &context);
+
+    layout_shape_clear_context(&context);
+
     /* Special treatment for runs that don't produce visual output, shaping code adds normal glyphs for them,
        with valid cluster map and potentially with non-zero advances; layout code exposes those as zero
        width clusters. */
@@ -1032,7 +1061,7 @@ static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular
     else
         run->run.glyphCount = run->glyphcount;
 
-    return S_OK;
+    return hr;
 }
 
 static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)




More information about the wine-cvs mailing list