[gtk+/extended-layout-jhs: 6/64] Implement height for width for GtkLabel.



commit b5043723672dae25be1cb6aeba7ef322004cd900
Author: Mathias Hasselmann <mathias hasselmann gmx de>
Date:   Wed Jun 20 08:31:46 2007 +0000

    Implement height for width for GtkLabel.
    
    2007-06-20  Mathias Hasselmann  <mathias hasselmann gmx de>
    
    	* gtk/gtklabel.c, tests/autotestextendedlayout.c:
    	Implement height for width for GtkLabel.
    
    svn path=/branches/extended-layout/; revision=18203

 ChangeLog.gtk-extended-layout  |    7 +-
 gtk/gtklabel.c                 |   35 +++++-
 tests/autotestextendedlayout.c |  240 +++++++++++++++++++++++++++++++---------
 3 files changed, 220 insertions(+), 62 deletions(-)
---
diff --git a/ChangeLog.gtk-extended-layout b/ChangeLog.gtk-extended-layout
index 300e5e1..bda6570 100644
--- a/ChangeLog.gtk-extended-layout
+++ b/ChangeLog.gtk-extended-layout
@@ -1,5 +1,10 @@
 2007-06-20  Mathias Hasselmann  <mathias hasselmann gmx de>
 
+	* gtk/gtklabel.c, tests/autotestextendedlayout.c: 
+	Implement height for width for GtkLabel.
+
+2007-06-20  Mathias Hasselmann  <mathias hasselmann gmx de>
+
 	* tests/autotestextendedlayout.c: Correct some assumptions,
 	write baseline values to console.
 
@@ -24,7 +29,7 @@
 
 2007-05-29  Mathias Hasselmann  <mathias hasselmann gmx de>
 
-	* testextendedlayout.c: Create initial heigth-for-width test.
+	* testextendedlayout.c: Create initial height-for-width test.
 
 2007-05-29  Mathias Hasselmann  <mathias hasselmann gmx de>
 
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index edf4a99..c55ceaa 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -4230,17 +4230,40 @@ gtk_label_do_popup (GtkLabel       *label,
 static GtkExtendedLayoutFeatures
 gtk_label_extended_layout_get_features (GtkExtendedLayout *layout)
 {
-  return GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH
-       | GTK_EXTENDED_LAYOUT_NATURAL_SIZE
-       | GTK_EXTENDED_LAYOUT_BASELINES;
+  GtkLabel *label;
+
+  label = GTK_LABEL (layout);
+
+  if (label->wrap)
+    return
+      GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH |
+      GTK_EXTENDED_LAYOUT_NATURAL_SIZE |
+      GTK_EXTENDED_LAYOUT_BASELINES;
+
+  return 
+    GTK_EXTENDED_LAYOUT_NATURAL_SIZE |
+    GTK_EXTENDED_LAYOUT_BASELINES;
 }
 
 static gint
 gtk_label_extended_layout_get_height_for_width (GtkExtendedLayout *layout,
                                                 gint               width)
 {
-  g_return_val_if_fail (GTK_IS_LABEL (layout), -1);
-  return -1;
+  PangoLayout *tmp;
+  GtkLabel *label;
+  gint height;
+
+  label = GTK_LABEL (layout);
+
+  g_return_val_if_fail (label->wrap, -1);
+
+  gtk_label_ensure_layout (label);
+  tmp = pango_layout_copy (label->layout);
+  pango_layout_set_width (tmp, PANGO_SCALE * width);
+  pango_layout_get_pixel_size (tmp, NULL, &height);
+  g_object_unref (tmp);
+
+  return height;
 }
 
 static void
@@ -4248,6 +4271,7 @@ gtk_label_extended_layout_get_natural_size (GtkExtendedLayout *layout,
                                             GtkRequisition    *requisition)
 {
   g_return_if_fail (GTK_IS_LABEL (layout));
+  g_return_if_reached ();
 }
 
 static gint
@@ -4259,7 +4283,6 @@ gtk_label_extended_layout_get_baselines (GtkExtendedLayout  *layout,
   GSList *lines;
 
   label = GTK_LABEL (layout);
-
   gtk_label_ensure_layout (label);
   lines = pango_layout_get_lines_readonly (label->layout);
   num_lines = g_slist_length (lines);
diff --git a/tests/autotestextendedlayout.c b/tests/autotestextendedlayout.c
index f10911e..797b651 100644
--- a/tests/autotestextendedlayout.c
+++ b/tests/autotestextendedlayout.c
@@ -1,21 +1,36 @@
 #include <config.h>
-#include <string.h>
+#include <stdlib.h>
 #include <glib/gprintf.h>
 #include <gtk/gtk.h>
 
-#define test(condition) \
-        log_test((condition), G_STRFUNC, #condition)
-#define testf(condition, format, ...) \
-        log_test((condition), G_STRFUNC, \
-                 #condition " (" format ")", __VA_ARGS__)
-#define testi(expected, number) G_STMT_START { \
-          const gint i = (expected), j = (number); \
-          log_test(i == j, G_STRFUNC, #number " is " #expected \
-                                      " (actual number %d)", j); \
-        } G_STMT_END
+/*****************************************************************************/
 
+#define log_test(condition) \
+  log_test_impl(G_STRFUNC, (condition), #condition)
+#define log_testf(condition, format, ...) \
+  log_test_impl(G_STRFUNC, (condition), #condition " (" format ")", __VA_ARGS__)
+#define log_testi(expected, number) G_STMT_START { \
+    const gint i = (expected), j = (number); \
+    log_test_impl(G_STRFUNC, i == j, \
+                  #number " is " #expected " (actual number %d)", j); \
+  } G_STMT_END
+
+#define log_info(format, ...) \
+  g_print ("INFO: %s: " format "\n", G_STRFUNC, __VA_ARGS__);
 #define log_int_array(values, length) \
-        log_int_array_impl (G_STRFUNC, #values, (values), (length))
+  log_int_array_impl (G_STRFUNC, #values, (values), (length))
+#define log_int(value) \
+  log_info (#value " is %d\n", (value));
+
+/*****************************************************************************/
+
+static const gchar lorem_ipsum[] =
+  "<span weight=\"bold\" size=\"xx-large\">"
+  "Lorem ipsum</span> dolor sit amet, consectetuer "
+  "adipiscing elit. Aliquam sed erat. Proin lectus "
+  "orci, venenatis pharetra, egestas id, tincidunt "
+  "vel, eros. Integer fringilla. Aenean justo ipsum, "        
+  "luctus ut, volutpat laoreet, vehicula in, libero.";
 
 static int num_failures = 0;
 static int num_warnings = 0;
@@ -24,6 +39,8 @@ static int num_criticals = 0;
 
 static GLogFunc default_log_handler;
 
+/*****************************************************************************/
+
 static void
 log_int_array_impl (const gchar *function,
                     const gchar *var_name,
@@ -51,9 +68,9 @@ log_int_array_impl (const gchar *function,
 }
 
 static void
-log_test (gboolean     passed, 
-          const gchar *function,
-          const gchar *test_name, ...)
+log_test_impl (const gchar *function,
+               gboolean     passed, 
+               const gchar *test_name, ...)
 {
   va_list args;
   char *str;
@@ -87,92 +104,205 @@ log_override_cb (const gchar   *log_domain,
   (* default_log_handler) (log_domain, log_level, message, user_data);
 }
 
+/*****************************************************************************/
+
 static void
-test_label (void)
+gtk_label_test_baselines (void)
 {
-  GtkExtendedLayoutFeatures features;
-  GtkExtendedLayoutIface *iface;
   GtkExtendedLayout *layout;
   GtkWidget *widget;
   GtkLabel *label;
 
-  gint *baselines;
   gint num_baselines;
+  gint *baselines;
 
   widget = g_object_ref_sink (gtk_label_new (NULL));
-  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (widget);
   layout = GTK_EXTENDED_LAYOUT (widget);
   label = GTK_LABEL (widget);
 
-  /* basic properties */
-
-  test (GTK_IS_EXTENDED_LAYOUT (label));
-  features = gtk_extended_layout_get_features (layout);
-
-  test (NULL != iface->get_features);
-  test (NULL != iface->get_height_for_width);
-  test (NULL == iface->get_width_for_height);
-  test (NULL != iface->get_natural_size);
-  test (NULL != iface->get_baselines);
-
-  test (0 != (features & GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH));
-  test (0 == (features & GTK_EXTENDED_LAYOUT_WIDTH_FOR_HEIGHT));
-  test (0 != (features & GTK_EXTENDED_LAYOUT_NATURAL_SIZE));
-  test (0 != (features & GTK_EXTENDED_LAYOUT_BASELINES));
-
-  /* baseline support */
-
   baselines = NULL;
   gtk_label_set_text (label, NULL);
   num_baselines = gtk_extended_layout_get_baselines (layout, &baselines);
   log_int_array (baselines, num_baselines);
-  testi (1, num_baselines);
-  test (NULL != baselines); 
+  log_testi (1, num_baselines);
+  log_test (NULL != baselines); 
   g_free (baselines);
 
   baselines = NULL;
   gtk_label_set_text (label, "");
   num_baselines = gtk_extended_layout_get_baselines (layout, &baselines);
   log_int_array (baselines, num_baselines);
-  testi (1, num_baselines);
-  test (NULL != baselines); 
+  log_testi (1, num_baselines);
+  log_test (NULL != baselines); 
   g_free (baselines);
 
   baselines = NULL;
   gtk_label_set_text (label, "First Line");
   num_baselines = gtk_extended_layout_get_baselines (layout, &baselines);
   log_int_array (baselines, num_baselines);
-  testi (1, num_baselines);
-  test (NULL != baselines); 
+  log_testi (1, num_baselines);
+  log_test (NULL != baselines); 
   g_free (baselines);
 
   baselines = NULL;
   gtk_label_set_text (label, "First Line\n");
   num_baselines = gtk_extended_layout_get_baselines (layout, &baselines);
   log_int_array (baselines, num_baselines);
-  testi (2, num_baselines);
-  test (NULL != baselines); 
+  log_testi (2, num_baselines);
+  log_test (NULL != baselines); 
   g_free (baselines);
 
   baselines = NULL;
   gtk_label_set_text (label, "First Line\nSecond Line");
   num_baselines = gtk_extended_layout_get_baselines (layout, &baselines);
   log_int_array (baselines, num_baselines);
-  testi (2, num_baselines);
-  test (NULL != baselines); 
+  log_testi (2, num_baselines);
+  log_test (NULL != baselines); 
   g_free (baselines);
 
   baselines = NULL;
   gtk_label_set_markup (label, "First Line\n<big>Second Line</big>\nThird Line");
   num_baselines = gtk_extended_layout_get_baselines (layout, &baselines);
   log_int_array (baselines, num_baselines);
-  testi (3, num_baselines);
-  test (NULL != baselines); 
+  log_testi (3, num_baselines);
+  log_test (NULL != baselines); 
   g_free (baselines);
 
   g_object_unref (widget);
 }
 
+static void
+gtk_label_test_height_for_width (void)
+{
+  GtkExtendedLayout *layout;
+  GtkWidget *widget;
+  GtkLabel *label;
+
+  PangoLayout *ref;
+  gint i, cx, cy, rcx, rcy;
+  double cy_min, cy_max;
+
+  widget = g_object_ref_sink (gtk_label_new (NULL));
+  layout = GTK_EXTENDED_LAYOUT (widget);
+  label = GTK_LABEL (widget);
+
+  gtk_label_set_markup (label, lorem_ipsum);
+  gtk_label_set_line_wrap_mode (label, PANGO_WRAP_CHAR);
+  gtk_label_set_line_wrap (label, TRUE);
+
+  ref = pango_layout_copy (gtk_label_get_layout (label));
+  pango_layout_set_width (ref, -1);
+  pango_layout_get_pixel_size (ref, &rcx, &rcy);
+  g_object_unref (ref);
+
+  log_info ("preferred layout size: %d \303\227 %d", rcx, rcy);
+
+  for (i = 5; i >= 1; --i)
+    {
+      cy = gtk_extended_layout_get_height_for_width (layout, cx = rcx * i);
+      log_info ("scale is %d, so width is %d. results in height of %d.", i, cx, cy);
+      log_testi (rcy, cy);
+    }
+
+  cy_min = rcy;
+  cy_max = rcy * 2.5;
+
+  for (i = 2, cx = rcx / 2; cx >= rcy; ++i, cx = rcx / i, cy_min = cy, cy_max += rcy)
+    {
+      cy = gtk_extended_layout_get_height_for_width (layout, cx);
+      log_info ("scale is 1/%d, so width is %d. results in height of %d.", i, cx, cy);
+      log_testf (cy_min <= cy && cy <= cy_max, "%f <= %d <= %f", cy_min, cy, cy_max);
+    }
+
+  g_object_unref (widget);
+}
+
+static void
+gtk_label_test_extended_layout (void)
+{
+  GtkExtendedLayoutFeatures features;
+  GtkExtendedLayoutIface *iface;
+  GtkExtendedLayout *layout;
+  GtkWidget *widget;
+  GtkLabel *label;
+
+  widget = g_object_ref_sink (gtk_label_new (NULL));
+  layout = GTK_EXTENDED_LAYOUT (widget);
+  label = GTK_LABEL (widget);
+
+  /* vtable */
+
+  log_test (GTK_IS_EXTENDED_LAYOUT (label));
+  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (label);
+
+  log_test (NULL != iface->get_features);
+  log_test (NULL != iface->get_height_for_width);
+  log_test (NULL == iface->get_width_for_height);
+  log_test (NULL != iface->get_natural_size);
+  log_test (NULL != iface->get_baselines);
+
+  /* feature set */
+
+  features = gtk_extended_layout_get_features (layout);
+
+  log_test (0 == (features & GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH));
+  log_test (0 == (features & GTK_EXTENDED_LAYOUT_WIDTH_FOR_HEIGHT));
+  log_test (0 != (features & GTK_EXTENDED_LAYOUT_NATURAL_SIZE));
+  log_test (0 != (features & GTK_EXTENDED_LAYOUT_BASELINES));
+
+  gtk_label_set_line_wrap (label, TRUE);
+  features = gtk_extended_layout_get_features (layout);
+
+  log_test (0 != (features & GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH));
+  log_test (0 == (features & GTK_EXTENDED_LAYOUT_WIDTH_FOR_HEIGHT));
+  log_test (0 != (features & GTK_EXTENDED_LAYOUT_NATURAL_SIZE));
+  log_test (0 != (features & GTK_EXTENDED_LAYOUT_BASELINES));
+
+  g_object_unref (widget);
+
+  /* baseline support */
+
+  gtk_label_test_baselines ();
+  gtk_label_test_height_for_width ();
+
+  /* height for width */
+/*
+  PangoLayout *tmp;
+
+  log_info ("requisition: %d, %d", req.width, req.height);
+
+  for (i = -5; i < 6; ++i)
+    {
+      const gint e = i < 4 ? 1 : 2;
+
+      const gdouble sy_lower =
+        i + 1 < 0 ? (abs(i + 1) + 1) : 
+        i + 1 > 0 ? 1.0 / (abs(i + 1) + 1) : 1;
+      const gdouble sy_upper = 
+        i - e < 0 ? (abs(i - e) + 1) :
+        i - e > 0 ? 1.0 / (abs(i - e) + 1) : 1;
+
+      double sy;
+
+      width =
+        i < 0 ? req.width / (abs(i) + 1) :
+        i > 0 ? req.width * (abs(i) + 1) :
+        req.width;
+
+      height = gtk_extended_layout_get_height_for_width (layout, width);
+      sy = (double)height / req.height;
+
+      log_info ("scale is %s%d, so width is %d, height is %d",
+                i < 0 ? "1/" : "", abs(i) + 1, width, height);
+
+      log_testf (sy_lower <= sy && sy <= sy_upper,
+             "%f <= %f <= %f", sy_lower, sy, sy_upper);
+    }
+*/
+}
+
+/*****************************************************************************/
+
 int
 main(int argc, char **argv)
 {
@@ -180,12 +310,12 @@ main(int argc, char **argv)
 
   gtk_init (&argc, &argv);
 
-  test_label ();
+  gtk_label_test_extended_layout ();
 
-  testi (0, num_warnings);
-  testi (0, num_errors);
-  testi (0, num_criticals);
-  testi (0, num_failures);
+  log_testi (0, num_warnings);
+  log_testi (0, num_errors);
+  log_testi (0, num_criticals);
+  log_testi (0, num_failures);
   
   return MAX(0, num_failures - 1);
 }



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