[pango/line-breaker: 9/16] Implement rendering for PangoLine




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

    Implement rendering for PangoLine

 pango/pango-renderer.c    | 226 +++++++++++++++++++++++++++++++++-------------
 pango/pango-renderer.h    |  15 +++
 pango/pangocairo-render.c |  97 ++++++++++++++++++--
 pango/pangocairo.h        |   7 ++
 4 files changed, 274 insertions(+), 71 deletions(-)
---
diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c
index 311c28cd..47ae606b 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
 
@@ -56,6 +57,8 @@ struct _LineState
 
 struct _PangoRendererPrivate
 {
+  PangoContext *context;
+
   PangoColor color[N_RENDER_PARTS];
   gboolean color_set[N_RENDER_PARTS];
   guint16 alpha[N_RENDER_PARTS];
@@ -146,6 +149,20 @@ pango_renderer_finalize (GObject *gobject)
   G_OBJECT_CLASS (pango_renderer_parent_class)->finalize (gobject);
 }
 
+static void
+pango_renderer_activate_with_context (PangoRenderer *renderer,
+                                      PangoContext  *context)
+{
+  /* We only change the matrix if the renderer isn't already active. */
+  if (!renderer->active_count)
+    {
+      pango_renderer_set_matrix (renderer, context ? pango_context_get_matrix (context) : NULL);
+      renderer->priv->context = context;
+    }
+
+  pango_renderer_activate (renderer);
+}
+
 /**
  * pango_renderer_draw_layout:
  * @renderer: a `PangoRenderer`
@@ -173,17 +190,7 @@ pango_renderer_draw_layout (PangoRenderer *renderer,
   g_return_if_fail (PANGO_IS_RENDERER (renderer));
   g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  /* We only change the matrix if the renderer isn't already
-   * active.
-   */
-  if (!renderer->active_count)
-    {
-      PangoContext *context = pango_layout_get_context (layout);
-      pango_renderer_set_matrix (renderer,
-                                 pango_context_get_matrix (context));
-    }
-
-  pango_renderer_activate (renderer);
+  pango_renderer_activate_with_context (renderer, pango_layout_get_context (layout));
 
   _pango_layout_get_iter (layout, &iter);
 
@@ -549,6 +556,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,27 +585,13 @@ 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));
 
-  /* We only change the matrix if the renderer isn't already
-   * active.
-   */
-  if (!renderer->active_count)
-    pango_renderer_set_matrix (renderer,
-                               G_LIKELY (line->layout) ?
-                               pango_context_get_matrix
-                               (pango_layout_get_context (line->layout)) :
-                               NULL);
-
-  pango_renderer_activate (renderer);
+  pango_renderer_activate_with_context (renderer,
+                                        line->layout ? pango_layout_get_context (line->layout) : NULL);
 
   renderer->priv->line = line;
   renderer->priv->line_state = &state;
@@ -604,7 +602,117 @@ 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_with_context (renderer, line->context);
+
+  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));
+
+  n = 0;
+  while (pango_lines_get_line (lines, n, &line, &line_x, &line_y))
+    {
+      if (n == 0)
+        pango_renderer_activate_with_context (renderer, line->context);
+
+      pango_renderer_draw_line (renderer, line, x + line_x, y + line_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 +749,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 +772,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 +791,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 +803,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 +821,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);
 }
 
 /**
@@ -1645,3 +1735,17 @@ pango_renderer_get_layout_line (PangoRenderer *renderer)
 {
   return renderer->priv->line;
 }
+
+/**
+ * pango_renderer_get_context:
+ * @renderer: a `PangoRenderer`
+ *
+ * Gets the current context in which @renderer operates.
+ *
+ * Returns: (nullable) (transfer none): the `PangoContext`
+ */
+PangoContext *
+pango_renderer_get_context (PangoRenderer *renderer)
+{
+  return renderer->priv->context;
+}
diff --git a/pango/pango-renderer.h b/pango/pango-renderer.h
index 16a1bbd4..61f18a72 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,
@@ -284,6 +296,9 @@ PangoLayout       *pango_renderer_get_layout      (PangoRenderer     *renderer);
 PANGO_AVAILABLE_IN_1_20
 PangoLayoutLine   *pango_renderer_get_layout_line (PangoRenderer     *renderer);
 
+PANGO_AVAILABLE_IN_ALL
+PangoContext *     pango_renderer_get_context     (PangoRenderer     *renderer);
+
 G_END_DECLS
 
 #endif /* __PANGO_RENDERER_H_ */
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
index 2c552ba1..50a483d4 100644
--- a/pango/pangocairo-render.c
+++ b/pango/pangocairo-render.c
@@ -772,24 +772,23 @@ pango_cairo_renderer_draw_error_underline (PangoRenderer *renderer,
 
 static void
 pango_cairo_renderer_draw_shape (PangoRenderer  *renderer,
-                                PangoAttrShape *attr,
-                                int             x,
-                                int             y)
+                                 PangoAttrShape *attr,
+                                 int             x,
+                                 int             y)
 {
   PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer);
   cairo_t *cr = crenderer->cr;
-  PangoLayout *layout;
+  PangoContext *context;
   PangoCairoShapeRendererFunc shape_renderer;
-  gpointer                    shape_renderer_data;
+  gpointer shape_renderer_data;
   double base_x, base_y;
 
-  layout = pango_renderer_get_layout (renderer);
+  context = pango_renderer_get_context (renderer);
 
-  if (!layout)
-       return;
+  if (!context)
+    return;
 
-  shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (layout),
-                                                          &shape_renderer_data);
+  shape_renderer = pango_cairo_context_get_shape_renderer (context, &shape_renderer_data);
 
   if (!shape_renderer)
     return;
@@ -992,6 +991,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 +1154,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]