[gtk+/wip/matthiasc/gskpango: 16/18] Make the text node do the rendering



commit 3dc257dedd0b65fd59b2b4fe67e0fcd82e7b89e3
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Aug 31 14:34:52 2017 -0400

    Make the text node do the rendering
    
    For now, this is just the fallback implementation
    using cairo.

 gsk/gskrendernode.h     |    9 ++-
 gsk/gskrendernodeimpl.c |  140 +++++++++++++++++++++++++++++++++++++----------
 gtk/gskpango.c          |  122 ++++++++++++++--------------------------
 3 files changed, 160 insertions(+), 111 deletions(-)
---
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index a550272..4c94f8d 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -176,9 +176,12 @@ GskRenderNode *         gsk_cross_fade_node_new                 (GskRenderNode
 
 GDK_AVAILABLE_IN_3_92
 GskRenderNode *         gsk_text_node_new                       (PangoFont        *font,
-                                                                 int               x,
-                                                                 int               y,
-                                                                 PangoGlyphString *glyphs);
+                                                                 PangoGlyphString *glyphs,
+                                                                 const GdkRGBA    *color,
+                                                                 int               x_offset,
+                                                                 int               y_offset,
+                                                                 double            base_x,
+                                                                 double            base_y);
 
 GDK_AVAILABLE_IN_3_90
 void                    gsk_render_node_set_scaling_filters     (GskRenderNode *node,
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index 29db76b..2d04bb3 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -3811,8 +3811,11 @@ struct _GskTextNode
 
   PangoFont *font;
   PangoGlyphString *glyphs;
-  int x;
-  int y;
+  GdkRGBA color;
+  int x_offset;
+  int y_offset;
+  double base_x;
+  double base_y;
 };
 
 static void
@@ -3824,35 +3827,80 @@ gsk_text_node_finalize (GskRenderNode *node)
   pango_glyph_string_free (self->glyphs);
 }
 
+static gboolean
+_pango_cairo_font_install (PangoFont *font,
+                           cairo_t   *cr)
+{
+  cairo_scaled_font_t *scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
+
+  if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
+    return FALSE;
+
+  cairo_set_scaled_font (cr, scaled_font);
+
+  return TRUE;
+}
+
+#ifndef STACK_BUFFER_SIZE
+#define STACK_BUFFER_SIZE (512 * sizeof (int))
+#endif
+
+#define STACK_ARRAY_LENGTH(T) (STACK_BUFFER_SIZE / sizeof(T))
+
 static void
 gsk_text_node_draw (GskRenderNode *node,
                     cairo_t       *cr)
 {
   GskTextNode *self = (GskTextNode *) node;
-  int i;
-  PangoFontDescription *desc;
-  char *s;
+  int i, count;
+  int x_position = 0;
+  cairo_glyph_t *cairo_glyphs;
+  cairo_glyph_t stack_glyphs[STACK_ARRAY_LENGTH (cairo_glyph_t)];
 
-  desc = pango_font_describe (self->font);
-  s = pango_font_description_to_string (desc);
-  g_print ("draw gyphs: font %s, x %d y %d\n", s, self->x, self->y);
-  g_free (s);
-  pango_font_description_free (desc);
+  cairo_save (cr);
 
+  cairo_translate (cr, self->x_offset, self->y_offset);
+
+  gdk_cairo_set_source_rgba (cr, &self->color);
+  if (!_pango_cairo_font_install (self->font, cr))
+    goto done;
+
+  if (self->glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_glyphs))
+    cairo_glyphs = g_new (cairo_glyph_t, self->glyphs->num_glyphs);
+  else
+    cairo_glyphs = stack_glyphs;
+
+  count = 0;
   for (i = 0; i < self->glyphs->num_glyphs; i++)
     {
-      PangoGlyphInfo *glyph = &self->glyphs->glyphs[i];
-      g_print ("  glyph %u width %d x %d y %d cs %d\n",
-               glyph->glyph,
-               glyph->geometry.width,
-               glyph->geometry.x_offset,
-               glyph->geometry.y_offset,
-               glyph->attr.is_cluster_start);
+      PangoGlyphInfo *gi = &self->glyphs->glyphs[i];
+
+      if (gi->glyph != PANGO_GLYPH_EMPTY)
+        {
+          double cx = self->base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
+          double cy = gi->geometry.y_offset == 0 ? self->base_y : self->base_y + 
(double)(gi->geometry.y_offset) / PANGO_SCALE;
+
+          if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
+            {
+              cairo_glyphs[count].index = gi->glyph;
+              cairo_glyphs[count].x = cx;
+              cairo_glyphs[count].y = cy;
+              count++;
+            }
+        }
+      x_position += gi->geometry.width;
     }
-  g_print ("\n");
+
+  cairo_show_glyphs (cr, cairo_glyphs, count);
+
+  if (cairo_glyphs != stack_glyphs)
+    g_free (cairo_glyphs);
+
+done:
+  cairo_restore (cr);
 }
 
-#define GSK_TEXT_NODE_VARIANT_TYPE "(siia(uiiii))"
+#define GSK_TEXT_NODE_VARIANT_TYPE "(sddddiidda(uiiii))"
 
 static GVariant *
 gsk_text_node_serialize (GskRenderNode *node)
@@ -3878,7 +3926,17 @@ gsk_text_node_serialize (GskRenderNode *node)
     }
 
   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(uiiii)"));
-  v = g_variant_new (GSK_TEXT_NODE_VARIANT_TYPE, s, self->x, self->y, &builder);
+  v = g_variant_new (GSK_TEXT_NODE_VARIANT_TYPE,
+                     s,
+                     self->color.red,
+                     self->color.green,
+                     self->color.blue,
+                     self->color.alpha,
+                     self->x_offset,
+                     self->y_offset,
+                     self->base_x,
+                     self->base_y,
+                     &builder);
 
   g_free (s);
   pango_font_description_free (desc);
@@ -3891,7 +3949,6 @@ gsk_text_node_deserialize (GVariant  *variant,
                            GError   **error)
 {
   PangoFont *font;
-  int x, y;
   PangoGlyphString *glyphs;
   GVariantIter iter;
   GskRenderNode *result;
@@ -3901,12 +3958,19 @@ gsk_text_node_deserialize (GVariant  *variant,
   PangoContext *context;
   int cluster_start;
   char *s;
+  GdkRGBA color;
+  int x_offset, y_offset;
+  double base_x, base_y;
   int i;
 
   if (!check_variant_type (variant, GSK_TEXT_NODE_VARIANT_TYPE, error))
     return NULL;
 
-  g_variant_get (variant, "(&siia(uiiii))", &s, &x, &y, &iter);
+  g_variant_get (variant, "(&sddddiidda(uiiii))",
+                 &color.red, &color.green, &color.blue, &color.alpha,
+                 &x_offset, &y_offset,
+                 &base_x, &base_y,
+                 &s, &iter);
 
   desc = pango_font_description_from_string (s);
   fontmap = pango_cairo_font_map_get_default ();
@@ -3923,7 +3987,9 @@ gsk_text_node_deserialize (GVariant  *variant,
       i++;
     }
 
-  result = gsk_text_node_new (font, x, y, glyphs);
+  result = gsk_text_node_new (font, glyphs, &color, /* FIXME: Avoid copying glyphs */
+                              x_offset, y_offset,
+                              base_x, base_y);
 
   pango_glyph_string_free (glyphs);
   pango_font_description_free (desc);
@@ -3945,18 +4011,34 @@ static const GskRenderNodeClass GSK_TEXT_NODE_CLASS = {
 
 GskRenderNode *
 gsk_text_node_new (PangoFont        *font,
-                   int               x,
-                   int               y,
-                   PangoGlyphString *glyphs)
+                   PangoGlyphString *glyphs,
+                   const GdkRGBA    *color,
+                   int               x_offset,
+                   int               y_offset,
+                   double            base_x,
+                   double            base_y)
 {
   GskTextNode *self;
+  PangoRectangle ink_rect;
 
   self = (GskTextNode *) gsk_render_node_new (&GSK_TEXT_NODE_CLASS, 0);
 
-  self->font = font ? g_object_ref (font) : NULL;
-  self->x = x;
-  self->y = y;
+  self->font = g_object_ref (font);
   self->glyphs = pango_glyph_string_copy (glyphs);
+  self->color = *color;
+  self->x_offset = x_offset;
+  self->y_offset = y_offset;
+  self->base_x = base_x;
+  self->base_y = base_y;
+
+  pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
+  pango_extents_to_pixels (&ink_rect, NULL);
+
+  graphene_rect_init (&self->render_node.bounds,
+                      x_offset + base_x + ink_rect.x,
+                      y_offset + base_y + ink_rect.y,
+                      ink_rect.width,
+                      ink_rect.height);
 
   return &self->render_node;
 }
diff --git a/gtk/gskpango.c b/gtk/gskpango.c
index f63179f..83376e4 100644
--- a/gtk/gskpango.c
+++ b/gtk/gskpango.c
@@ -97,20 +97,6 @@ set_color (GskPangoRenderer *crenderer,
     gdk_cairo_set_source_rgba (cr, crenderer->fg_color);
 }
 
-static gboolean
-_pango_cairo_font_install (PangoFont *font,
-                           cairo_t   *cr)
-{
-  cairo_scaled_font_t *scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
-
-  if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
-    return FALSE;
-
-  cairo_set_scaled_font (cr, scaled_font);
-
-  return TRUE;
-}
-
 static void
 gsk_pango_renderer_draw_unknown_glyph (GskPangoRenderer *crenderer,
                                        PangoFont        *font,
@@ -136,12 +122,6 @@ gsk_pango_renderer_draw_unknown_glyph (GskPangoRenderer *crenderer,
   cairo_destroy (cr);
 }
 
-#ifndef STACK_BUFFER_SIZE
-#define STACK_BUFFER_SIZE (512 * sizeof (int))
-#endif
-
-#define STACK_ARRAY_LENGTH(T) (STACK_BUFFER_SIZE / sizeof(T))
-
 static void
 gsk_pango_renderer_show_text_glyphs (PangoRenderer        *renderer,
                                      const char           *text,
@@ -155,84 +135,68 @@ gsk_pango_renderer_show_text_glyphs (PangoRenderer        *renderer,
                                      int                   y)
 {
   GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
-
-  cairo_t *cr;
-  int i, count;
-  int x_position = 0;
-  cairo_glyph_t *cairo_glyphs;
-  cairo_glyph_t stack_glyphs[STACK_ARRAY_LENGTH (cairo_glyph_t)];
   double base_x = crenderer->x_offset + (double)x / PANGO_SCALE;
   double base_y = crenderer->y_offset + (double)y / PANGO_SCALE;
+  int x_offset, y_offset;
+  cairo_scaled_font_t *scaled_font;
+  gboolean font_failed = FALSE;
+  int x_position;
+  int num_glyphs;
+  int i;
 
-  cr = gtk_snapshot_append_cairo (crenderer->snapshot, &crenderer->bounds, "Text<%dglyphs>", 
glyphs->num_glyphs);
-
-  set_color (crenderer, PANGO_RENDER_PART_FOREGROUND, cr);
-
-  if (!_pango_cairo_font_install (font, cr))
-    {
-      for (i = 0; i < glyphs->num_glyphs; i++)
-        {
-          PangoGlyphInfo *gi = &glyphs->glyphs[i];
-
-          if (gi->glyph != PANGO_GLYPH_EMPTY)
-            {
-              double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
-              double cy = gi->geometry.y_offset == 0 ?
-                          base_y :
-                          base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;
-
-              gsk_pango_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy);
-            }
-          x_position += gi->geometry.width;
-        }
-
-      goto done;
-    }
+  gtk_snapshot_get_offset (crenderer->snapshot, &x_offset, &y_offset);
 
-  if (glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_glyphs))
-    cairo_glyphs = g_new (cairo_glyph_t, glyphs->num_glyphs);
-  else
-    cairo_glyphs = stack_glyphs;
+  scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
+  if (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)
+    font_failed = TRUE;
 
-  count = 0;
+  x_position = 0;
+  num_glyphs = 0;
   for (i = 0; i < glyphs->num_glyphs; i++)
     {
       PangoGlyphInfo *gi = &glyphs->glyphs[i];
 
-      if (gi->glyph != PANGO_GLYPH_EMPTY)
+      if (gi->glyph != PANGO_GLYPH_EMPTY &&
+          (font_failed || gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
         {
           double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
-          double cy = gi->geometry.y_offset == 0 ?
-                      base_y :
-                      base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;
+          double cy = gi->geometry.y_offset == 0
+                      ? base_y
+                      : base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;
+
+          gsk_pango_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy);
 
-          if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)
-            gsk_pango_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy);
+          if (num_glyphs == 0)
+            base_x += (gi->geometry.x_offset + gi->geometry.width) / PANGO_SCALE;
           else
-            {
-              cairo_glyphs[count].index = gi->glyph;
-              cairo_glyphs[count].x = cx;
-              cairo_glyphs[count].y = cy;
-              count++;
-            }
+            glyphs->glyphs[num_glyphs - 1].geometry.width += gi->geometry.x_offset + gi->geometry.width;
+        }
+      else
+        {
+          if (i != num_glyphs)
+            glyphs->glyphs[num_glyphs] = glyphs->glyphs[i];
+          num_glyphs++;
         }
       x_position += gi->geometry.width;
     }
 
-  if (G_UNLIKELY (clusters))
-    cairo_show_text_glyphs (cr,
-                            text, text_len,
-                            cairo_glyphs, count,
-                            clusters, num_clusters,
-                            backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : 0);
-  else
-    cairo_show_glyphs (cr, cairo_glyphs, count);
+  glyphs->num_glyphs = num_glyphs;
+
+  if (glyphs->num_glyphs > 0)
+    {
+      GskRenderNode *node;
+      char name[64];
 
-  if (cairo_glyphs != stack_glyphs)
-    g_free (cairo_glyphs);
+      gtk_snapshot_offset (crenderer->snapshot, base_x, base_y);
 
-done:
-  cairo_destroy (cr);
+      node = gsk_text_node_new (font, glyphs, crenderer->fg_color, x_offset, y_offset, base_x, base_y);
+      snprintf (name, sizeof (name), "Glyphs<%d>", glyphs->num_glyphs);
+      gsk_render_node_set_name (node, name);
+      gtk_snapshot_append_node (crenderer->snapshot, node);
+      gsk_render_node_unref (node);
+
+      gtk_snapshot_offset (crenderer->snapshot, -base_x, -base_y);
+    }
 }
 
 static void


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