[gimp] app: render the text layout directly into the layer's pixels



commit 3759b3f0d1ba128eee9d6c3195b9b891aa75b582
Author: Michael Natterer <mitch gimp org>
Date:   Wed Sep 1 23:30:40 2010 +0200

    app: render the text layout directly into the layer's pixels
    
    instead of using a mask. Enables color tags. Set the default color
    from the text object using a pango color attibute and factor out
    GimpTextLayout attribute setting into a utility function.

 app/text/gimptextlayer.c  |   97 +++++++++++++++++++++++++++++----------------
 app/text/gimptextlayout.c |   59 +++++++++++++++++----------
 2 files changed, 101 insertions(+), 55 deletions(-)
---
diff --git a/app/text/gimptextlayer.c b/app/text/gimptextlayer.c
index 779af21..4feca03 100644
--- a/app/text/gimptextlayer.c
+++ b/app/text/gimptextlayer.c
@@ -23,10 +23,12 @@
 #include <string.h>
 
 #include <gegl.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
 #include <pango/pangocairo.h>
 
 #include "libgimpbase/gimpbase.h"
 #include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpcairo-utils.h"
 
 #include "text-types.h"
 
@@ -637,66 +639,93 @@ gimp_text_layer_render_layout (GimpTextLayer  *layer,
 {
   GimpDrawable    *drawable = GIMP_DRAWABLE (layer);
   GimpItem        *item     = GIMP_ITEM (layer);
-  TileManager     *mask;
+  GimpImage       *image    = gimp_item_get_image (item);
   cairo_t         *cr;
-  cairo_surface_t *surface;
-  PixelRegion      textPR;
-  PixelRegion      maskPR;
-  const guchar    *data;
-  gint             rowstride;
+  cairo_surface_t *rgb_surface;
+  cairo_surface_t *alpha_surface;
+  PixelRegion      layerPR;
+  const guchar    *rgb_data;
+  const guchar    *alpha_data;
+  GimpImageType    layer_type;
+  gint             layer_alpha_byte;
+  gint             rgb_rowstride;
+  gint             alpha_rowstride;
   gint             width;
   gint             height;
   gpointer         pr;
 
-  gimp_drawable_fill (drawable, &layer->text->color, NULL);
+  g_return_if_fail (gimp_drawable_has_alpha (drawable));
 
   width  = gimp_item_get_width  (item);
   height = gimp_item_get_height (item);
 
-  surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
+  rgb_surface   = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
+  alpha_surface = cairo_image_surface_create (CAIRO_FORMAT_A8,    width, height);
 
-  cr = cairo_create (surface);
+  cr = cairo_create (rgb_surface);
+  gimp_text_layout_render (layout, cr, layer->text->base_dir, FALSE);
+  cairo_destroy (cr);
 
+  cr = cairo_create (alpha_surface);
   gimp_text_layout_render (layout, cr, layer->text->base_dir, FALSE);
+  cairo_destroy (cr);
 
-  mask = tile_manager_new ( width, height, 1);
-  pixel_region_init (&maskPR, mask, 0, 0, width, height, TRUE);
+  pixel_region_init (&layerPR, gimp_drawable_get_tiles (drawable),
+                     0, 0, width, height, TRUE);
 
-  cairo_surface_flush (surface);
+  layer_type       = gimp_drawable_type (drawable);
+  layer_alpha_byte = layerPR.bytes - 1;
 
-  data      = cairo_image_surface_get_data (surface);
-  rowstride = cairo_image_surface_get_stride (surface);
+  cairo_surface_flush (rgb_surface);
+  rgb_data      = cairo_image_surface_get_data (rgb_surface);
+  rgb_rowstride = cairo_image_surface_get_stride (rgb_surface);
 
-  for (pr = pixel_regions_register (1, &maskPR);
+  cairo_surface_flush (alpha_surface);
+  alpha_data      = cairo_image_surface_get_data (alpha_surface);
+  alpha_rowstride = cairo_image_surface_get_stride (alpha_surface);
+
+  for (pr = pixel_regions_register (1, &layerPR);
        pr != NULL;
        pr = pixel_regions_process (pr))
     {
-      const guchar *src  = data + maskPR.x + maskPR.y * rowstride;
-      guchar       *dest = maskPR.data;
-      gint          rows = maskPR.h;
+      const guchar *rgb_src;
+      const guchar *alpha_src;
+      guchar       *dest = layerPR.data;
+      gint          rows = layerPR.h;
+
+      rgb_src   = rgb_data   + layerPR.x * 4 + layerPR.y * rgb_rowstride;
+      alpha_src = alpha_data + layerPR.x     + layerPR.y * alpha_rowstride;
 
       while (rows--)
         {
-          memcpy (dest, src, maskPR.w);
+          const guchar *rgb   = rgb_src;
+          const guchar *alpha = alpha_src;
+          guchar       *d     = dest;
+          gint          i;
 
-          src += rowstride;
-          dest += maskPR.rowstride;
-        }
-    }
+          for (i = 0; i < layerPR.w; i++)
+            {
+              guchar color[3];
 
-  cairo_destroy (cr);
-  cairo_surface_destroy (surface);
+              GIMP_CAIRO_RGB24_GET_PIXEL (rgb, color[0], color[1], color[2]);
 
-  pixel_region_init (&textPR, gimp_drawable_get_tiles (drawable),
-                     0, 0, width, height, TRUE);
-  pixel_region_init (&maskPR, mask,
-                     0, 0, width, height, FALSE);
+              gimp_image_transform_color (image, layer_type, d,
+                                          GIMP_RGB, color);
+              d[layer_alpha_byte] = *alpha;
 
-  apply_mask_to_region (&textPR, &maskPR, OPAQUE_OPACITY);
+              rgb   += 4;
+              alpha += 1;
+              d     += layerPR.bytes;
+            }
 
-  tile_manager_unref (mask);
+          rgb_src   += rgb_rowstride;
+          alpha_src += alpha_rowstride;
+          dest      += layerPR.rowstride;
+        }
+    }
 
-  /*  no need to gimp_drawable_update() since gimp_drawable_fill()
-   *  did that for us.
-   */
+  cairo_surface_destroy (rgb_surface);
+  cairo_surface_destroy (alpha_surface);
+
+  gimp_drawable_update (drawable, 0, 0, width, height);
 }
diff --git a/app/text/gimptextlayout.c b/app/text/gimptextlayout.c
index c1968d1..f107098 100644
--- a/app/text/gimptextlayout.c
+++ b/app/text/gimptextlayout.c
@@ -49,6 +49,7 @@ struct _GimpTextLayout
 static void           gimp_text_layout_finalize   (GObject        *object);
 
 static void           gimp_text_layout_position   (GimpTextLayout *layout);
+static void           gimp_text_layout_set_attrs  (GimpTextLayout *layout);
 
 static PangoContext * gimp_text_get_pango_context (GimpText       *text,
                                                    gdouble         xres,
@@ -189,28 +190,8 @@ gimp_text_layout_new (GimpText  *text,
                             gimp_text_layout_pixel_size (text->line_spacing,
                                                          text->unit,
                                                          yres));
-  if (fabs (text->letter_spacing) > 0.1)
-    {
-      PangoAttrList  *attrs;
-      PangoAttribute *attr;
-
-      attrs = pango_layout_get_attributes (layout->layout);
-      if (attrs)
-        pango_attr_list_ref (attrs);
-      else
-        attrs = pango_attr_list_new ();
-
-      attr = pango_attr_letter_spacing_new (text->letter_spacing * PANGO_SCALE);
-
-      attr->start_index = 0;
-      attr->end_index   = -1;
-
-      pango_attr_list_insert (attrs, attr);
-
-      pango_layout_set_attributes (layout->layout, attrs);
-      pango_attr_list_unref (attrs);
-    }
 
+  gimp_text_layout_set_attrs (layout);
   gimp_text_layout_position (layout);
 
   switch (text->box_mode)
@@ -477,6 +458,42 @@ gimp_text_layout_untransform_distance (GimpTextLayout *layout,
 }
 
 static void
+gimp_text_layout_set_attrs (GimpTextLayout *layout)
+{
+  GimpText       *text = layout->text;
+  PangoAttrList  *attrs;
+  PangoAttribute *attr;
+
+  attrs = pango_layout_get_attributes (layout->layout);
+  if (attrs)
+    pango_attr_list_ref (attrs);
+  else
+    attrs = pango_attr_list_new ();
+
+  attr = pango_attr_foreground_new (text->color.r * 65535,
+                                    text->color.g * 65535,
+                                    text->color.b * 65535);
+
+  attr->start_index = 0;
+  attr->end_index   = -1;
+
+  pango_attr_list_insert (attrs, attr);
+
+  if (fabs (text->letter_spacing) > 0.1)
+    {
+      attr = pango_attr_letter_spacing_new (text->letter_spacing * PANGO_SCALE);
+
+      attr->start_index = 0;
+      attr->end_index   = -1;
+
+      pango_attr_list_insert (attrs, attr);
+    }
+
+  pango_layout_set_attributes (layout->layout, attrs);
+  pango_attr_list_unref (attrs);
+}
+
+static void
 gimp_text_layout_position (GimpTextLayout *layout)
 {
   PangoRectangle  ink;



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