[gegl] text: add properties to control vertical size and alignemnt



commit d82ef75eef16d46b7253b7bcb5c57170c5d07cdc
Author: Ell <ell_se yahoo com>
Date:   Tue Nov 22 14:19:31 2016 -0500

    text: add properties to control vertical size and alignemnt
    
    The "vertical_alignment" property controls whether the text is
    top-, middle-, or bottom-aligned; the text is aligned against the
    height specified by the "vertical_wrap" property.
    
    This commit also modifies the reported bounding-box of the op
    to match the actual bounding box of the text, in particular, by
    not having its top-left corner fixed at (0, 0).

 operations/external/text.c |   60 ++++++++++++++++++++++++++++++-------------
 1 files changed, 42 insertions(+), 18 deletions(-)
---
diff --git a/operations/external/text.c b/operations/external/text.c
index 8e29d83..91dff01 100644
--- a/operations/external/text.c
+++ b/operations/external/text.c
@@ -40,11 +40,19 @@ property_int  (wrap, _("Wrap width"), -1)
     description (_("Sets the width in pixels at which long lines will wrap. "
                      "Use -1 for no wrapping."))
     value_range (-1, 1000000)
+property_int  (vertical_wrap, _("Wrap height"), 0)
+    description (_("Sets the height in pixels according to which the text is "
+                   "vertically justified. Use -1 for infinite height."))
+    value_range (-1, 1000000)
 
 property_int    (alignment, _("Justification"), 0)
     value_range (0, 2)
     description (_("Alignment for multi-line text (0=Left, 1=Center, 2=Right)"))
 
+property_int    (vertical_alignment, _("Vertical justification"), 0)
+    value_range (0, 2)
+    description (_("Vertical text alignment (0=Top, 1=Middle, 2=Bottom)"))
+
 property_int (width, _("Width"), 0)
     description (_("Rendered width in pixels. (read only)"))
 property_int    (height, _("Height"), 0)
@@ -65,7 +73,9 @@ typedef struct {
   gchar         *font;
   gdouble        size;
   gint           wrap;
+  gint           vertical_wrap;
   gint           alignment;
+  gint           vertical_alignment;
   GeglRectangle  defined;
 } CachedExtent;
 
@@ -90,11 +100,10 @@ GEGL_DEFINE_DYNAMIC_OPERATION (GEGL_TYPE_OPERATION_SOURCE)
 
 
 
-static void text_layout_text (GeglOp *self,
-                              cairo_t   *cr,
-                              gdouble    rowstride,
-                              gdouble   *width,
-                              gdouble   *height)
+static void text_layout_text (GeglOp        *self,
+                              cairo_t       *cr,
+                              gdouble        rowstride,
+                              GeglRectangle *bounds)
 {
   GeglProperties           *o = GEGL_PROPERTIES (self);
   PangoFontDescription *desc;
@@ -103,6 +112,9 @@ static void text_layout_text (GeglOp *self,
   PangoAttribute *attr  = NULL;
   gchar          *string;
   gint            alignment = 0;
+  PangoRectangle  ink_rect;
+  PangoRectangle  logical_rect;
+  gint            vertical_offset = 0;
 
   /* Create a PangoLayout, set the font and text */
   layout = pango_cairo_create_layout (cr);
@@ -150,17 +162,32 @@ static void text_layout_text (GeglOp *self,
   /* Inform Pango to re-layout the text with the new transformation */
   pango_cairo_update_layout (cr, layout);
 
-  if (width && height)
+  pango_layout_get_pixel_extents (layout, &ink_rect, &logical_rect);
+  if (o->vertical_wrap >= 0)
     {
-      PangoRectangle extents;
-
-      pango_layout_get_pixel_extents (layout, &extents, NULL);
+      switch (o->vertical_alignment)
+      {
+      case 0: /* top */
+        vertical_offset = 0;
+        break;
+      case 1: /* middle */
+        vertical_offset = (o->vertical_wrap - logical_rect.height) / 2;
+        break;
+      case 2: /* bottom */
+        vertical_offset = o->vertical_wrap - logical_rect.height;
+        break;
+      }
+    }
 
-      *width  = (gdouble) (extents.x + extents.width);
-      *height = (gdouble) (extents.y + extents.height);
+  if (bounds)
+    {
+      *bounds = *GEGL_RECTANGLE (ink_rect.x,     ink_rect.y + vertical_offset,
+                                 ink_rect.width, ink_rect.height);
     }
   else
     {
+      cairo_translate (cr, 0, vertical_offset);
+
       pango_cairo_show_layout (cr, layout);
     }
 
@@ -188,7 +215,7 @@ process (GeglOperation       *operation,
                                                  result->width * 4);
   cr = cairo_create (surface);
   cairo_translate (cr, -result->x, -result->y);
-  text_layout_text (self, cr, 0, NULL, NULL);
+  text_layout_text (self, cr, 0, NULL);
 
   gegl_buffer_set (output, result, 0, babl_format ("B'aG'aR'aA u8"), data,
                    GEGL_AUTO_ROWSTRIDE);
@@ -224,17 +251,14 @@ get_bounding_box (GeglOperation *operation)
       extent->alignment != o->alignment)
     { /* get extents */
       cairo_t *cr;
-      gdouble width, height;
 
       cairo_surface_t *surface  = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
           1, 1);
       cr = cairo_create (surface);
-      text_layout_text (self, cr, 0, &width, &height);
+      text_layout_text (self, cr, 0, &extent->defined);
       cairo_destroy (cr);
       cairo_surface_destroy (surface);
 
-      extent->defined.width = width;
-      extent->defined.height = height;
       if (extent->string)
         g_free (extent->string);
       extent->string = g_strdup (o->string);
@@ -246,8 +270,8 @@ get_bounding_box (GeglOperation *operation)
       extent->alignment = o->alignment;
 
       /* store the measured size for later use */
-      o->width = width;
-      o->height = height;
+      o->width  = extent->defined.width  - extent->defined.x;
+      o->height = extent->defined.height - extent->defined.y;
 
       gegl_operation_invalidate (operation, NULL, TRUE);
     }


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