[gtk+] label: Redo get_preferred_width/height()



commit aba0c5cc3ba1f10492c9d9013802e287067b0bf7
Author: Benjamin Otte <otte redhat com>
Date:   Sat Nov 3 15:36:22 2012 +0100

    label: Redo get_preferred_width/height()
    
    This is important for size groups mostly, but also has some small fixes.
    The label-sizing reftest as been updated accordingly.

 gtk/gtklabel.c                     |  126 +++++++++++++++---------------------
 tests/reftests/label-sizing.ref.ui |    8 +-
 2 files changed, 56 insertions(+), 78 deletions(-)
---
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 113ce57..e5b4849 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -3439,23 +3439,6 @@ gtk_label_ensure_layout (GtkLabel *label)
     }
 }
 
-static gint
-get_single_line_height (GtkWidget   *widget,
-                        PangoLayout *layout)
-{
-  PangoContext *context;
-  PangoFontMetrics *metrics;
-  gint ascent, descent;
-
-  context = pango_layout_get_context (layout);
-  metrics = get_font_metrics (context, widget);
-  ascent = pango_font_metrics_get_ascent (metrics);
-  descent = pango_font_metrics_get_descent (metrics);
-  pango_font_metrics_unref (metrics);
-
-  return ascent + descent;
-}
-
 static GtkSizeRequestMode
 gtk_label_get_request_mode (GtkWidget *widget)
 {
@@ -3512,11 +3495,12 @@ get_char_pixels (GtkWidget   *label,
 
 static void
 gtk_label_get_preferred_layout_size (GtkLabel *label,
-                                     PangoRectangle *required,
-                                     PangoRectangle *natural)
+                                     PangoRectangle *widest,
+                                     PangoRectangle *highest)
 {
   GtkLabelPrivate *priv = label->priv;
   PangoLayout *layout;
+  gint char_pixels;
 
   /* "width-chars" Hard-coded minimum width:
    *    - minimum size should be MAX (width-chars, strlen ("..."));
@@ -3537,44 +3521,44 @@ gtk_label_get_preferred_layout_size (GtkLabel *label,
   /* Start off with the pixel extents of an as-wide-as-possible layout */
   layout = gtk_label_get_measuring_layout (label, NULL, -1);
 
-  pango_layout_get_extents (layout, NULL, natural);
-  natural->x = natural->y = 0;
-
-  if (priv->wrap)
-    natural->height = get_single_line_height (GTK_WIDGET (label), layout);
+  if (priv->width_chars > -1 || priv->max_width_chars > -1)
+    char_pixels = get_char_pixels (GTK_WIDGET (label), layout);
+  else
+    char_pixels = 0;
+      
+  pango_layout_get_extents (layout, NULL, widest);
+  widest->width = MAX (widest->width, char_pixels * priv->width_chars);
+  widest->x = widest->y = 0;
 
   if (priv->ellipsize || priv->wrap)
     {
       /* a layout with width 0 will be as small as humanly possible */
-      layout = gtk_label_get_measuring_layout (label, layout, 0);
-
-      pango_layout_get_extents (layout, NULL, required);
+      layout = gtk_label_get_measuring_layout (label,
+                                               layout,
+                                               priv->width_chars > -1 ? char_pixels * priv->width_chars
+                                                                      : 0);
 
-      /* can happen when Pango decides to ellipsize text */
-      if (required->width > natural->width)
-        required->width = natural->width;
+      pango_layout_get_extents (layout, NULL, highest);
+      highest->width = MAX (highest->width, char_pixels * priv->width_chars);
+      highest->x = highest->y = 0;
 
-      required->x = required->y = 0;
-      required->height = natural->height;
+      if (priv->max_width_chars > -1 && widest->width > char_pixels * priv->max_width_chars)
+        {
+          layout = gtk_label_get_measuring_layout (label,
+                                                   layout,
+                                                   MAX (highest->width, char_pixels * priv->max_width_chars));
+          pango_layout_get_extents (layout, NULL, widest);
+          widest->width = MAX (widest->width, char_pixels * priv->width_chars);
+          widest->x = widest->y = 0;
+        }
+      g_assert (widest->width  >= highest->width);
     }
   else
     {
-      *required = *natural;
+      *highest = *widest;
     }
 
-  if (priv->width_chars > -1 || priv->max_width_chars > -1)
-    {
-      gint char_pixels;
-
-      char_pixels = get_char_pixels (GTK_WIDGET (label), layout);
-      
-      if (priv->width_chars > -1)
-        required->width = MAX (required->width, char_pixels * priv->width_chars);
-
-      if (priv->max_width_chars > -1)
-        natural->width = MIN (natural->width, priv->max_width_chars * char_pixels);
-      natural->width = MAX (natural->width, required->width);
-    }
+  g_assert (widest->height <= highest->height);
 
   g_object_unref (layout);
 }
@@ -3587,36 +3571,28 @@ gtk_label_get_preferred_size (GtkWidget      *widget,
 {
   GtkLabel      *label = GTK_LABEL (widget);
   GtkLabelPrivate  *priv = label->priv;
-  PangoRectangle required_rect;
-  PangoRectangle natural_rect;
+  PangoRectangle widest_rect;
+  PangoRectangle highest_rect;
   GtkBorder border;
 
-  gtk_label_get_preferred_layout_size (label, &required_rect, &natural_rect);
+  gtk_label_get_preferred_layout_size (label, &widest_rect, &highest_rect);
 
   /* Now that we have minimum and natural sizes in pango extents, apply a possible transform */
   if (priv->have_transform)
     {
-      PangoLayout *copy;
       PangoContext *context;
       const PangoMatrix *matrix;
 
-      copy = pango_layout_copy (priv->layout);
-      context = pango_layout_get_context (copy);
+      context = pango_layout_get_context (priv->layout);
       matrix = pango_context_get_matrix (context);
 
-      pango_layout_set_width (copy, -1);
-      pango_layout_set_ellipsize (copy, PANGO_ELLIPSIZE_NONE);
-
-      pango_layout_get_extents (copy, NULL, &natural_rect);
-      g_object_unref (copy);
-
-      pango_matrix_transform_rectangle (matrix, &required_rect);
-      pango_matrix_transform_rectangle (matrix, &natural_rect);
+      pango_matrix_transform_rectangle (matrix, &widest_rect);
+      pango_matrix_transform_rectangle (matrix, &highest_rect);
 
-      /* Bump the natural size in case of ellipsize to ensure pango has
+      /* Bump the size in case of ellipsize to ensure pango has
        * enough space in the angles (note, we could alternatively set the
        * layout to not ellipsize when we know we have been allocated our
-       * full natural size, or it may be that pango needs a fix here).
+       * full size, or it may be that pango needs a fix here).
        */
       if (priv->ellipsize && priv->angle != 0 && priv->angle != 90 && 
           priv->angle != 180 && priv->angle != 270 && priv->angle != 360)
@@ -3624,16 +3600,18 @@ gtk_label_get_preferred_size (GtkWidget      *widget,
           /* For some reason we only need this at about 110 degrees, and only
            * when gaining in height
            */
-          natural_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
-          natural_rect.width  += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+          widest_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+          widest_rect.width  += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+          highest_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+          highest_rect.width  += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
         }
     }
 
-  required_rect.width  = PANGO_PIXELS_CEIL (required_rect.width);
-  required_rect.height = PANGO_PIXELS_CEIL (required_rect.height);
+  widest_rect.width  = PANGO_PIXELS_CEIL (widest_rect.width);
+  widest_rect.height = PANGO_PIXELS_CEIL (widest_rect.height);
 
-  natural_rect.width  = PANGO_PIXELS_CEIL (natural_rect.width);
-  natural_rect.height = PANGO_PIXELS_CEIL (natural_rect.height);
+  highest_rect.width  = PANGO_PIXELS_CEIL (highest_rect.width);
+  highest_rect.height = PANGO_PIXELS_CEIL (highest_rect.height);
 
   _gtk_misc_get_padding_and_border (GTK_MISC (label), &border);
 
@@ -3650,15 +3628,15 @@ gtk_label_get_preferred_size (GtkWidget      *widget,
            */
           get_size_for_allocation (label,
                                    GTK_ORIENTATION_VERTICAL,
-                                   required_rect.height,
+                                   highest_rect.height,
                                    minimum_size, natural_size);
 
         }
       else
         {
           /* Normal desired width */
-          *minimum_size = required_rect.width;
-          *natural_size = natural_rect.width;
+          *minimum_size = highest_rect.width;
+          *natural_size = widest_rect.width;
         }
 
       *minimum_size += border.left + border.right;
@@ -3677,7 +3655,7 @@ gtk_label_get_preferred_size (GtkWidget      *widget,
            */
           get_size_for_allocation (label,
                                    GTK_ORIENTATION_HORIZONTAL,
-                                   required_rect.width,
+                                   widest_rect.width,
                                    minimum_size, natural_size);
         }
       else
@@ -3685,8 +3663,8 @@ gtk_label_get_preferred_size (GtkWidget      *widget,
           /* A vertically rotated label does w4h, so return the base
            * desired height (text length)
            */
-          *minimum_size = required_rect.height;
-          *natural_size = natural_rect.height;
+          *minimum_size = widest_rect.height;
+          *natural_size = highest_rect.height;
         }
 
       *minimum_size += border.top + border.bottom;
diff --git a/tests/reftests/label-sizing.ref.ui b/tests/reftests/label-sizing.ref.ui
index b33923d..eacaec4 100644
--- a/tests/reftests/label-sizing.ref.ui
+++ b/tests/reftests/label-sizing.ref.ui
@@ -5457,7 +5457,7 @@ ABCD</property>
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="xalign">0</property>
-                    <property name="label" translatable="yes">ABCDE   
+                    <property name="label" translatable="yes">ABCDE
 ABCD</property>
                     <property name="max_width_chars">8</property>
                     <attributes>
@@ -5476,7 +5476,7 @@ ABCD</property>
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="xalign">0</property>
-                    <property name="label" translatable="yes">ABCDE   
+                    <property name="label" translatable="yes">ABCDE
 ABCD</property>
                     <property name="max_width_chars">8</property>
                     <attributes>
@@ -6099,7 +6099,7 @@ ABCD</property>
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="xalign">0</property>
-                    <property name="label" translatable="yes">ABCDE   
+                    <property name="label" translatable="yes">ABCDE
 ABCD</property>
                     <property name="width_chars">4</property>
                     <property name="max_width_chars">8</property>
@@ -6119,7 +6119,7 @@ ABCD</property>
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="xalign">0</property>
-                    <property name="label" translatable="yes">ABCDE   
+                    <property name="label" translatable="yes">ABCDE
 ABCD</property>
                     <property name="width_chars">4</property>
                     <property name="max_width_chars">8</property>



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