[clutter] text: Make :line-wrap actually work



commit 359ed2b29fdc4f692e6cb6ff310c41ed7796139a
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Sun Sep 4 17:57:50 2011 +0100

    text: Make :line-wrap actually work
    
    When we paint a ClutterText we ask the actor for a PangoLayout that fits
    inside the actor's allocation - both width and height.
    
    Sadly, whenever a height is set on a PangoLayout, Pango will wrap its
    contents - regardless of whether the layout should actually wrap or not.
    
    This means that in certain easy to exploit cases, Clutter will paint a
    Text actor with its contents wrapping even if the :wrap property is set
    to FALSE.
    
    In order to fix this we need to encode some more cases inside the
    ::paint implementation of ClutterText, and ask the cache for a layout
    that is sized as the allocation's width, but not as its height; we also
    need to perform a clip if we detect that the PangoLayout's logical size
    is going to overflow the allocated size. This clip might cause some
    performance issue, given that clipping breaks batching in the Cogl
    journal; hopefully all clips for text are going to be screen-aligned, so
    at the end of the batch it'll just scissor them out.
    
    http://bugzilla.clutter-project.org/show_bug.cgi?id=2339

 clutter/clutter-text.c |   53 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 49 insertions(+), 4 deletions(-)
---
diff --git a/clutter/clutter-text.c b/clutter/clutter-text.c
index 4018990..7d65cb2 100644
--- a/clutter/clutter-text.c
+++ b/clutter/clutter-text.c
@@ -1975,9 +1975,37 @@ clutter_text_paint (ClutterActor *self)
   if (priv->editable && priv->single_line_mode)
     layout = clutter_text_create_layout (text, -1, -1);
   else
-    layout = clutter_text_create_layout (text,
-                                         alloc.x2 - alloc.x1,
-                                         alloc.y2 - alloc.y1);
+    {
+      /* the only time when we create the PangoLayout using the full
+       * width and height of the allocation is when we can both wrap
+       * and ellipsize
+       */
+      if (priv->wrap && priv->ellipsize)
+        {
+          layout = clutter_text_create_layout (text,
+                                               alloc.x2 - alloc.x1,
+                                               alloc.y2 - alloc.y1);
+        }
+      else
+        {
+          /* if we're not wrapping we cannot set the height of the
+           * layout, otherwise Pango will happily wrap the text to
+           * fit in the rectangle - thus making the :wrap property
+           * useless
+           *
+           * see bug:
+           *
+           *   http://bugzilla.clutter-project.org/show_bug.cgi?id=2339
+           *
+           * in order to fix this, we create a layout that would fit
+           * in the assigned width, then we clip the actor if the
+           * logical rectangle overflows the allocation.
+           */
+          layout = clutter_text_create_layout (text,
+                                               alloc.x2 - alloc.x1,
+                                               -1);
+        }
+    }
 
   if (priv->editable && priv->cursor_visible)
     clutter_text_ensure_cursor_position (text);
@@ -2027,6 +2055,24 @@ clutter_text_paint (ClutterActor *self)
           text_x = TEXT_PADDING;
         }
     }
+  else if (!priv->editable && !(priv->wrap && priv->ellipsize))
+    {
+      PangoRectangle logical_rect = { 0, };
+
+      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+
+      /* don't clip if the layout managed to fit inside our allocation */
+      if (logical_rect.width > (alloc.x2 - alloc.x1) ||
+          logical_rect.height > (alloc.y2 - alloc.y1))
+        {
+          cogl_clip_push_rectangle (0, 0,
+                                    alloc.x2 - alloc.x1,
+                                    alloc.y2 - alloc.y1);
+          clip_set = TRUE;
+        }
+
+      text_x = 0;
+    }
   else
     text_x = 0;
 
@@ -2053,7 +2099,6 @@ clutter_text_paint (ClutterActor *self)
 
   if (clip_set)
     cogl_clip_pop ();
-
 }
 
 static void



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