[pango/line-breaker: 10/18] Implement rendering for PangoLine




commit f94613e1af6373b287f57be939f9e525700ba96c
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jan 14 22:11:15 2022 -0500

    Implement rendering for PangoLine

 pango/pango-renderer.c    | 174 +++++++++++++++++++++++++++++++++++-----------
 pango/pango-renderer.h    |  12 ++++
 pango/pangocairo-render.c |  78 +++++++++++++++++++++
 pango/pangocairo.h        |   7 ++
 4 files changed, 232 insertions(+), 39 deletions(-)
---
diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c
index 311c28cd..4f223228 100644
--- a/pango/pango-renderer.c
+++ b/pango/pango-renderer.c
@@ -25,6 +25,7 @@
 #include "pango-renderer.h"
 #include "pango-impl-utils.h"
 #include "pango-layout-private.h"
+#include "pango-line-private.h"
 
 #define N_RENDER_PARTS 5
 
@@ -549,6 +550,11 @@ draw_shaped_glyphs (PangoRenderer    *renderer,
     }
 }
 
+static void pango_renderer_draw_runs (PangoRenderer *renderer,
+                                      GSList        *runs,
+                                      const char    *text,
+                                      int            x,
+                                      int            y);
 
 /**
  * pango_renderer_draw_layout_line:
@@ -573,12 +579,7 @@ pango_renderer_draw_layout_line (PangoRenderer   *renderer,
                                  int              x,
                                  int              y)
 {
-  int x_off = 0;
-  int glyph_string_width;
   LineState state = { 0, };
-  GSList *l;
-  gboolean got_overall = FALSE;
-  PangoRectangle overall_rect;
   const char *text;
 
   g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
@@ -604,7 +605,120 @@ pango_renderer_draw_layout_line (PangoRenderer   *renderer,
 
   text = G_LIKELY (line->layout) ? pango_layout_get_text (line->layout) : NULL;
 
-  for (l = line->runs; l; l = l->next)
+  pango_renderer_draw_runs (renderer, line->runs, text, x, y);
+
+  /* Finish off any remaining underlines */
+  draw_underline (renderer, &state);
+  draw_overline (renderer, &state);
+  draw_strikethrough (renderer, &state);
+
+  renderer->priv->line_state = NULL;
+  renderer->priv->line = NULL;
+
+  pango_renderer_deactivate (renderer);
+}
+
+/**
+ * pango_renderer_draw_line:
+ * @renderer: a `PangoRenderer`
+ * @line: a `PangoLine`
+ * @x: X position of left edge of baseline, in user space coordinates
+ *   in Pango units.
+ * @y: Y position of left edge of baseline, in user space coordinates
+ *   in Pango units.
+ *
+ * Draws @line with the specified `PangoRenderer`.
+ *
+ * This draws the glyph items that make up the line, as well as
+ * shapes, backgrounds and lines that are specified by the attributes
+ * of those items.
+ */
+void
+pango_renderer_draw_line (PangoRenderer *renderer,
+                          PangoLine     *line,
+                          int             x,
+                          int             y)
+{
+  LineState state = { 0, };
+
+  g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+
+  pango_renderer_activate (renderer);
+
+  renderer->priv->line = NULL;
+  renderer->priv->line_state = &state;
+
+  state.underline = PANGO_UNDERLINE_NONE;
+  state.overline = PANGO_OVERLINE_NONE;
+  state.strikethrough = FALSE;
+
+  pango_renderer_draw_runs (renderer, line->runs, line->data->text, x, y);
+
+  /* Finish off any remaining underlines */
+  draw_underline (renderer, &state);
+  draw_overline (renderer, &state);
+  draw_strikethrough (renderer, &state);
+
+  renderer->priv->line_state = NULL;
+  renderer->priv->line = NULL;
+
+  pango_renderer_deactivate (renderer);
+}
+
+/**
+ * pango_renderer_draw_lines:
+ * @renderer: a `PangoRenderer`
+ * @lines: a `PangoLines` object
+ * @x: X position of left edge of baseline, in user space coordinates
+ *   in Pango units.
+ * @y: Y position of left edge of baseline, in user space coordinates
+ *   in Pango units.
+ *
+ * Draws @lines with the specified `PangoRenderer`.
+ */
+void
+pango_renderer_draw_lines (PangoRenderer *renderer,
+                           PangoLines    *lines,
+                           int            x,
+                           int            y)
+{
+  int n;
+  PangoLine *line;
+  int line_x, line_y;
+
+  g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+
+  pango_renderer_activate (renderer);
+
+  n = 0;
+  while (pango_lines_get_line (lines, n, &line, &line_x, &line_y))
+    {
+      PangoRectangle ext;
+
+      pango_line_get_extents (line, &ext);
+
+      pango_renderer_draw_line (renderer, line, x + line_x + ext.x, y + line_y - ext.y);
+
+      n++;
+    }
+
+  pango_renderer_deactivate (renderer);
+}
+
+static void
+pango_renderer_draw_runs (PangoRenderer *renderer,
+                          GSList        *runs,
+                          const char    *text,
+                          int            x,
+                          int            y)
+{
+  GSList *l;
+  int x_off = 0;
+  int glyph_string_width;
+  gboolean got_overall = FALSE;
+  PangoRectangle overall_rect;
+
+  for (l = runs; l; l = l->next)
     {
       PangoFontMetrics *metrics;
       PangoLayoutRun *run = l->data;
@@ -641,15 +755,14 @@ pango_renderer_draw_layout_line (PangoRenderer   *renderer,
               logical = &logical_rect;
             }
           if (G_UNLIKELY (ink || logical))
-            pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
-                                        ink, logical);
+            pango_glyph_string_extents (run->glyphs, run->item->analysis.font, ink, logical);
           if (logical)
             glyph_string_width = logical_rect.width;
           else
             glyph_string_width = pango_glyph_string_get_width (run->glyphs);
         }
 
-      state.logical_rect_end = x + x_off + glyph_string_width;
+      renderer->priv->line_state->logical_rect_end = x + x_off + glyph_string_width;
 
       x_off += run->start_x_offset;
       y_off = run->y_offset;
@@ -665,12 +778,13 @@ pango_renderer_draw_layout_line (PangoRenderer   *renderer,
           y_off += adjustment;
         }
 
-
       if (renderer->priv->color_set[PANGO_RENDER_PART_BACKGROUND])
         {
           if (!got_overall)
             {
+#ifdef EXTENTS
               pango_layout_line_get_extents (line, NULL, &overall_rect);
+#endif
               got_overall = TRUE;
             }
 
@@ -683,16 +797,9 @@ pango_renderer_draw_layout_line (PangoRenderer   *renderer,
         }
 
       if (shape_attr)
-        {
-          draw_shaped_glyphs (renderer, run->glyphs, shape_attr, x + x_off, y - y_off);
-        }
+        draw_shaped_glyphs (renderer, run->glyphs, shape_attr, x + x_off, y - y_off);
       else
-        {
-          pango_renderer_draw_glyph_item (renderer,
-                                          text,
-                                          run,
-                                          x + x_off, y - y_off);
-        }
+        pango_renderer_draw_glyph_item (renderer, text, run, x + x_off, y - y_off);
 
       if (renderer->underline != PANGO_UNDERLINE_NONE ||
           renderer->priv->overline != PANGO_OVERLINE_NONE ||
@@ -702,17 +809,17 @@ pango_renderer_draw_layout_line (PangoRenderer   *renderer,
                                             run->item->analysis.language);
 
           if (renderer->underline != PANGO_UNDERLINE_NONE)
-            add_underline (renderer, &state,metrics,
+            add_underline (renderer, renderer->priv->line_state, metrics,
                            x + x_off, y - y_off,
                            ink, logical);
 
           if (renderer->priv->overline != PANGO_OVERLINE_NONE)
-            add_overline (renderer, &state,metrics,
+            add_overline (renderer, renderer->priv->line_state, metrics,
                            x + x_off, y - y_off,
                            ink, logical);
 
           if (renderer->strikethrough)
-            add_strikethrough (renderer, &state, metrics,
+            add_strikethrough (renderer, renderer->priv->line_state, metrics,
                                x + x_off, y - y_off,
                                ink, logical, run->glyphs->num_glyphs);
 
@@ -720,30 +827,19 @@ pango_renderer_draw_layout_line (PangoRenderer   *renderer,
         }
 
       if (renderer->underline == PANGO_UNDERLINE_NONE &&
-          state.underline != PANGO_UNDERLINE_NONE)
-        draw_underline (renderer, &state);
+          renderer->priv->line_state->underline != PANGO_UNDERLINE_NONE)
+        draw_underline (renderer, renderer->priv->line_state);
 
       if (renderer->priv->overline == PANGO_OVERLINE_NONE &&
-          state.overline != PANGO_OVERLINE_NONE)
-        draw_overline (renderer, &state);
+          renderer->priv->line_state->overline != PANGO_OVERLINE_NONE)
+        draw_overline (renderer, renderer->priv->line_state);
 
-      if (!renderer->strikethrough && state.strikethrough)
-        draw_strikethrough (renderer, &state);
+      if (!renderer->strikethrough && renderer->priv->line_state->strikethrough)
+        draw_strikethrough (renderer, renderer->priv->line_state);
 
       x_off += glyph_string_width;
       x_off += run->end_x_offset;
     }
-
-  /* Finish off any remaining underlines
-   */
-  draw_underline (renderer, &state);
-  draw_overline (renderer, &state);
-  draw_strikethrough (renderer, &state);
-
-  renderer->priv->line_state = NULL;
-  renderer->priv->line = NULL;
-
-  pango_renderer_deactivate (renderer);
 }
 
 /**
diff --git a/pango/pango-renderer.h b/pango/pango-renderer.h
index 16a1bbd4..d3c16944 100644
--- a/pango/pango-renderer.h
+++ b/pango/pango-renderer.h
@@ -22,6 +22,8 @@
 #define __PANGO_RENDERER_H_
 
 #include <pango/pango-layout.h>
+#include <pango/pango-line.h>
+#include <pango/pango-lines.h>
 
 G_BEGIN_DECLS
 
@@ -207,6 +209,16 @@ void pango_renderer_draw_layout_line     (PangoRenderer    *renderer,
                                           PangoLayoutLine  *line,
                                           int               x,
                                           int               y);
+PANGO_AVAILABLE_IN_ALL
+void pango_renderer_draw_line            (PangoRenderer    *renderer,
+                                          PangoLine        *line,
+                                          int               x,
+                                          int               y);
+PANGO_AVAILABLE_IN_ALL
+void pango_renderer_draw_lines           (PangoRenderer    *renderer,
+                                          PangoLines       *lines,
+                                          int               x,
+                                          int               y);
 PANGO_AVAILABLE_IN_1_8
 void pango_renderer_draw_glyphs          (PangoRenderer    *renderer,
                                           PangoFont        *font,
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
index 2c552ba1..9d139748 100644
--- a/pango/pangocairo-render.c
+++ b/pango/pangocairo-render.c
@@ -992,6 +992,44 @@ _pango_cairo_do_layout_line (cairo_t          *cr,
   release_renderer (crenderer);
 }
 
+static void
+_pango_cairo_do_line (cairo_t   *cr,
+                      PangoLine *line,
+                      gboolean   do_path)
+{
+  PangoCairoRenderer *crenderer = acquire_renderer ();
+  PangoRenderer *renderer = (PangoRenderer *) crenderer;
+
+  crenderer->cr = cr;
+  crenderer->do_path = do_path;
+  save_current_point (crenderer);
+
+  pango_renderer_draw_line (renderer, line, 0, 0);
+
+  restore_current_point (crenderer);
+
+  release_renderer (crenderer);
+}
+
+static void
+_pango_cairo_do_lines (cairo_t    *cr,
+                       PangoLines *lines,
+                       gboolean    do_path)
+{
+  PangoCairoRenderer *crenderer = acquire_renderer ();
+  PangoRenderer *renderer = (PangoRenderer *) crenderer;
+
+  crenderer->cr = cr;
+  crenderer->do_path = do_path;
+  save_current_point (crenderer);
+
+  pango_renderer_draw_lines (renderer, lines, 0, 0);
+
+  restore_current_point (crenderer);
+
+  release_renderer (crenderer);
+}
+
 static void
 _pango_cairo_do_layout (cairo_t     *cr,
                        PangoLayout *layout,
@@ -1117,6 +1155,46 @@ pango_cairo_show_layout_line (cairo_t          *cr,
   _pango_cairo_do_layout_line (cr, line, FALSE);
 }
 
+/**
+ * pango_cairo_show_line:
+ * @cr: a Cairo context
+ * @line: a `PangoLine`
+ *
+ * Draws a `PangoLine` in the specified cairo context.
+ *
+ * The origin of the glyphs (the left edge of the line) will
+ * be drawn at the current point of the cairo context.
+ */
+void
+pango_cairo_show_line (cairo_t   *cr,
+                       PangoLine *line)
+{
+  g_return_if_fail (cr != NULL);
+  g_return_if_fail (line != NULL);
+
+  _pango_cairo_do_line (cr, line, FALSE);
+}
+
+/**
+ * pango_cairo_show_lines:
+ * @cr: a Cairo context
+ * @lines: a `PangoLines` object
+ *
+ * Draws a `PangoLines` object in the specified cairo context.
+ *
+ * The top-left corner of the `PangoLines` will be drawn
+ * at the current point of the cairo context.
+ */
+void
+pango_cairo_show_lines (cairo_t    *cr,
+                        PangoLines *lines)
+{
+  g_return_if_fail (cr != NULL);
+  g_return_if_fail (lines != NULL);
+
+  _pango_cairo_do_lines (cr, lines, FALSE);
+}
+
 /**
  * pango_cairo_show_layout:
  * @cr: a Cairo context
diff --git a/pango/pangocairo.h b/pango/pangocairo.h
index 7e860554..1f9f4926 100644
--- a/pango/pangocairo.h
+++ b/pango/pangocairo.h
@@ -183,6 +183,12 @@ void pango_cairo_show_glyph_item   (cairo_t          *cr,
 PANGO_AVAILABLE_IN_1_10
 void pango_cairo_show_layout_line  (cairo_t          *cr,
                                    PangoLayoutLine  *line);
+PANGO_AVAILABLE_IN_ALL
+void pango_cairo_show_line         (cairo_t          *cr,
+                                    PangoLine        *line);
+PANGO_AVAILABLE_IN_ALL
+void pango_cairo_show_lines        (cairo_t          *cr,
+                                    PangoLines       *lines);
 PANGO_AVAILABLE_IN_1_10
 void pango_cairo_show_layout       (cairo_t          *cr,
                                    PangoLayout      *layout);
@@ -194,6 +200,7 @@ void pango_cairo_show_error_underline (cairo_t       *cr,
                                       double         width,
                                       double         height);
 
+
 /*
  * Rendering to a path
  */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]