Nikolay Sivov : dwrite: Set baseline origin Y for reported runs.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Jun 23 09:17:14 CDT 2015


Module: wine
Branch: master
Commit: 643125e50f620137c30576a219d6e497f4d1a047
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=643125e50f620137c30576a219d6e497f4d1a047

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Jun 22 11:56:25 2015 +0300

dwrite: Set baseline origin Y for reported runs.

---

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

diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index ba31ec6..25e8eac 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -181,6 +181,7 @@ struct layout_effective_run {
     FLOAT origin_x;         /* baseline X position */
     FLOAT origin_y;         /* baseline Y position */
     UINT16 *clustermap;     /* effective clustermap, allocated separately, is not reused from nominal map */
+    UINT32 line;
 };
 
 struct layout_effective_inline {
@@ -191,6 +192,7 @@ struct layout_effective_inline {
     FLOAT origin_y;
     BOOL  is_sideways;
     BOOL  is_rtl;
+    UINT32 line;
 };
 
 struct layout_strikethrough {
@@ -906,7 +908,7 @@ static inline IUnknown *layout_get_effect_from_pos(struct dwrite_textlayout *lay
 /* Effective run is built from consecutive clusters of a single nominal run, 'first_cluster' is 0 based cluster index,
    'cluster_count' indicates how many clusters to add, including first one. */
 static HRESULT layout_add_effective_run(struct dwrite_textlayout *layout, const struct layout_run *r, UINT32 first_cluster,
-    UINT32 cluster_count, FLOAT origin_x, BOOL strikethrough)
+    UINT32 cluster_count, UINT32 line, FLOAT origin_x, BOOL strikethrough)
 {
     UINT32 i, start, length, last_cluster;
     struct layout_effective_run *run;
@@ -926,6 +928,7 @@ static HRESULT layout_add_effective_run(struct dwrite_textlayout *layout, const
            different ranges which differ in reading direction). */
         inlineobject->is_sideways = FALSE;
         inlineobject->is_rtl = FALSE;
+        inlineobject->line = line;
 
         /* effect assigned from start position and on is used for inline objects */
         inlineobject->effect = layout_get_effect_from_pos(layout, layout->clusters[first_cluster].position);
@@ -954,7 +957,8 @@ static HRESULT layout_add_effective_run(struct dwrite_textlayout *layout, const
     run->start = start = layout->clusters[first_cluster].position;
     run->length = length;
     run->origin_x = origin_x;
-    run->origin_y = 0.0; /* FIXME: set after line is built */
+    run->origin_y = 0.0; /* set after line is built */
+    run->line = line;
 
     if (r->u.regular.run.glyphCount) {
         /* trim from the left */
@@ -1039,11 +1043,41 @@ static inline BOOL layout_get_strikethrough_from_pos(struct dwrite_textlayout *l
     return ((struct layout_range_bool*)h)->value;
 }
 
+static inline struct layout_effective_run *layout_get_next_erun(struct dwrite_textlayout *layout,
+    const struct layout_effective_run *cur)
+{
+    struct list *e;
+
+    if (!cur)
+        e = list_head(&layout->eruns);
+    else
+        e = list_next(&layout->eruns, &cur->entry);
+    if (!e)
+        return NULL;
+    return LIST_ENTRY(e, struct layout_effective_run, entry);
+}
+
+static inline struct layout_effective_inline *layout_get_next_inline_run(struct dwrite_textlayout *layout,
+    const struct layout_effective_inline *cur)
+{
+    struct list *e;
+
+    if (!cur)
+        e = list_head(&layout->inlineobjects);
+    else
+        e = list_next(&layout->inlineobjects, &cur->entry);
+    if (!e)
+        return NULL;
+    return LIST_ENTRY(e, struct layout_effective_inline, entry);
+}
+
 static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
 {
-    DWRITE_LINE_METRICS metrics;
+    struct layout_effective_inline *inrun;
+    struct layout_effective_run *erun;
     const struct layout_run *run;
-    FLOAT width, origin_x;
+    DWRITE_LINE_METRICS metrics;
+    FLOAT width, origin_x, origin_y;
     UINT32 i, start, line, textpos;
     HRESULT hr;
     BOOL s[2];
@@ -1070,7 +1104,7 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
         /* switched to next nominal run, at this point all previous pending clusters are already
            checked for layout line overflow, so new effective run will fit in current line */
         if (run != layout->clusters[i].run || s[0] != s[1]) {
-            hr = layout_add_effective_run(layout, run, start, i - start, origin_x, s[0]);
+            hr = layout_add_effective_run(layout, run, start, i - start, line, origin_x, s[0]);
             if (FAILED(hr))
                 return hr;
             origin_x += get_cluster_range_width(layout, start, i);
@@ -1096,7 +1130,7 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
                 last_cluster = i ? i - 1 : i;
 
             if (i >= start) {
-                hr = layout_add_effective_run(layout, run, start, i - start + 1, origin_x, s[0]);
+                hr = layout_add_effective_run(layout, run, start, i - start + 1, line, origin_x, s[0]);
                 if (FAILED(hr))
                     return hr;
                 /* we don't need to update origin for next run as we're going to wrap */
@@ -1165,6 +1199,33 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
     }
 
     layout->line_count = line;
+
+    /* Now all line info is here, update effective runs positions in flow direction */
+    erun = layout_get_next_erun(layout, NULL);
+    inrun = layout_get_next_inline_run(layout, NULL);
+
+    origin_y = 0.0;
+    for (line = 0; line < layout->line_count; line++) {
+
+        origin_y += layout->lines[line].baseline;
+
+        /* For all runs on this line */
+        while (erun && erun->line == line) {
+            erun->origin_y = origin_y;
+            erun = layout_get_next_erun(layout, erun);
+            if (!erun)
+                break;
+        }
+
+        /* Same for inline runs */
+        while (inrun && inrun->line == line) {
+            inrun->origin_y = origin_y;
+            inrun = layout_get_next_inline_run(layout, inrun);
+            if (!inrun)
+                break;
+        }
+    }
+
     layout->recompute &= ~RECOMPUTE_EFFECTIVE_RUNS;
     return hr;
 }




More information about the wine-cvs mailing list