[cairo-commit] goocanvas/src goocanvas.c, 1.21, 1.22 goocanvas.h, 1.13, 1.14 goocanvastable.c, 1.12, 1.13

Damon Chaplin commit at pdx.freedesktop.org
Tue Jun 19 04:23:07 PDT 2007


Committed by: damon

Update of /cvs/cairo/goocanvas/src
In directory kemper:/tmp/cvs-serv10052/src

Modified Files:
	goocanvas.c goocanvas.h goocanvastable.c 
Log Message:
2007-06-19  Damon Chaplin  <damon at gnome.org>

	* src/goocanvas.c: added "integer-layout" boolean property, to specify
	that all layout in the canvas (i.e. in GooCanvasTable) is done to the
	nearest integer.

	* src/goocanvastable.c: implement integer layout.

	* demo/table-demo.c: 
	* demo/mv-table-demo.c: tests for integer layout.



Index: goocanvas.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvas.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- goocanvas.c	15 May 2007 14:01:51 -0000	1.21
+++ goocanvas.c	19 Jun 2007 11:22:53 -0000	1.22
@@ -12,7 +12,6 @@
  *
  * #GooCanvas is the main widget containing a number of canvas items.
  *
- *
  * Here is a simple example:
  *
  * <informalexample><programlisting>
@@ -121,7 +120,8 @@
   PROP_RESOLUTION_X,
   PROP_RESOLUTION_Y,
   PROP_BACKGROUND_COLOR,
-  PROP_BACKGROUND_COLOR_RGB
+  PROP_BACKGROUND_COLOR_RGB,
+  PROP_INTEGER_LAYOUT
 };
 
 enum {
@@ -348,6 +348,13 @@
 						      0, G_MAXUINT, 0,
 						      G_PARAM_WRITABLE));
 
+  g_object_class_install_property (gobject_class, PROP_INTEGER_LAYOUT,
+                                   g_param_spec_boolean ("integer-layout",
+							 _("Integer Layout"),
+							 _("If all item layout is done to the nearest integer"),
+							 FALSE,
+							 G_PARAM_READWRITE));
+
   /**
    * GooCanvas::set-scroll-adjustments
    * @canvas: the canvas.
@@ -406,6 +413,7 @@
   canvas->scale_y = 1.0;
   canvas->scale = 1.0;
   canvas->need_update = TRUE;
+  canvas->need_entire_subtree_update = TRUE;
   canvas->crossing_event.type = GDK_LEAVE_NOTIFY;
   canvas->anchor = GTK_ANCHOR_NORTH_WEST;
 
@@ -635,6 +643,9 @@
     case PROP_RESOLUTION_Y:
       g_value_set_double (value, canvas->resolution_y);
       break;
+    case PROP_INTEGER_LAYOUT:
+      g_value_set_boolean (value, canvas->integer_layout);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -714,6 +725,11 @@
       color.blue  = ((rgb)       & 0xFF) * 257;
       gtk_widget_modify_base ((GtkWidget*) canvas, GTK_STATE_NORMAL, &color);
       break;
+    case PROP_INTEGER_LAYOUT:
+      canvas->integer_layout = g_value_get_boolean (value);
+      canvas->need_entire_subtree_update = TRUE;
+      goo_canvas_request_update (canvas);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1959,9 +1975,12 @@
      should ensure that they don't cause this to loop forever. */
   while (canvas->need_update)
     {
+      gboolean entire_tree = canvas->need_entire_subtree_update;
+
       canvas->need_update = FALSE;
+      canvas->need_entire_subtree_update = FALSE;
       if (canvas->root_item)
-	goo_canvas_item_update (canvas->root_item, FALSE, cr, &bounds);
+	goo_canvas_item_update (canvas->root_item, entire_tree, cr, &bounds);
     }
 
   /* Check which item is under the pointer. */

Index: goocanvas.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvas.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- goocanvas.h	15 May 2007 14:01:51 -0000	1.13
+++ goocanvas.h	19 Jun 2007 11:22:53 -0000	1.14
@@ -67,6 +67,12 @@
   /* This is TRUE if some item in the canvas needs an update. */
   guint need_update : 1;
 
+  /* This is TRUE if all items in the canvas need to be updated. */
+  guint need_entire_subtree_update : 1;
+
+  /* This is TRUE if all layout should be done to the nearest integer. */
+  guint integer_layout : 1;
+
   /* The item that the mouse is over. */
   GooCanvasItem *pointer_item;
 

Index: goocanvastable.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvastable.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- goocanvastable.c	6 Mar 2007 13:21:26 -0000	1.12
+++ goocanvastable.c	19 Jun 2007 11:22:53 -0000	1.13
@@ -40,6 +40,7 @@
  * g_object_get() and g_object_set().
  */
 #include <config.h>
+#include <math.h>
 #include <string.h>
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
@@ -135,6 +136,7 @@
 {
   gdouble requested_position[2];
   gdouble requested_size[2];
+  gdouble start_pad[2], end_pad[2];
 };
 
 /* The children array is only kept around while doing the layout.
@@ -144,6 +146,12 @@
   GooCanvasTableDimensionLayoutData *dldata[2];
   GooCanvasTableChildLayoutData *children;
 
+  /* This is TRUE if we are rounding everything to the nearest integer. */
+  gboolean integer_layout;
+
+  /* This is the border width used, possibly rounded to an integer. */
+  gdouble border_width;
+
   /* These are in the table's coordinate space. */
   gdouble natural_size[2];
   gdouble requested_size[2];
@@ -1003,6 +1011,7 @@
 static void
 goo_canvas_table_init_layout_data (GooCanvasTable *table)
 {
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) table;
   GooCanvasTableData *table_data = table->table_data;
   GooCanvasTableDimension *dimension;
   GooCanvasTableLayoutData *layout_data;
@@ -1015,11 +1024,13 @@
   layout_data = g_slice_new (GooCanvasTableLayoutData);
 
   table_data->layout_data = layout_data;
-  layout_data->dldata[VERT] = g_new (GooCanvasTableDimensionLayoutData,
-				     table_data->dimensions[VERT].size);
   layout_data->children = g_new (GooCanvasTableChildLayoutData,
 				 table_data->children->len);
   layout_data->last_width = -1;
+  layout_data->integer_layout = simple->canvas->integer_layout;
+  layout_data->border_width = table_data->border_width;
+  if (layout_data->integer_layout)
+    layout_data->border_width = floor (layout_data->border_width + 0.5);
 
   for (d = 0; d < 2; d++)
     {
@@ -1037,6 +1048,10 @@
 	  else
 	    dldata[i].spacing = dimension->default_spacing;
 
+	  /* In integer layout mode, round spacings to the nearest integer. */
+	  if (layout_data->integer_layout)
+	    dldata[i].spacing = floor (dldata[i].spacing + 0.5);
+
 	  dldata[i].need_expand = FALSE;
 	  dldata[i].need_shrink = TRUE;
 	  dldata[i].expand = FALSE;
@@ -1090,6 +1105,22 @@
       layout_data->children[i].requested_size[HORZ] = bounds.x2 - bounds.x1;
       layout_data->children[i].requested_size[VERT] = bounds.y2 - bounds.y1;
 
+      layout_data->children[i].start_pad[HORZ] = child->start_pad[HORZ];
+      layout_data->children[i].end_pad[HORZ] = child->end_pad[HORZ];
+      layout_data->children[i].start_pad[VERT] = child->start_pad[VERT];
+      layout_data->children[i].end_pad[VERT] = child->end_pad[VERT];
+
+      if (layout_data->integer_layout)
+	{
+	  layout_data->children[i].requested_size[HORZ] = ceil (layout_data->children[i].requested_size[HORZ]);
+	  layout_data->children[i].requested_size[VERT] = ceil (layout_data->children[i].requested_size[VERT]);
+
+	  layout_data->children[i].start_pad[HORZ] = floor (layout_data->children[i].start_pad[HORZ] + 0.5);
+	  layout_data->children[i].end_pad[HORZ] = floor (layout_data->children[i].end_pad[HORZ] + 0.5);
+	  layout_data->children[i].start_pad[VERT] = floor (layout_data->children[i].start_pad[VERT] + 0.5);
+	  layout_data->children[i].end_pad[VERT] = floor (layout_data->children[i].end_pad[VERT] + 0.5);
+	}
+
       /* Set the expand, shrink & empty flags in the
 	 GooCanvasTableDimensionLayoutData for the row/column, if the item
 	 only spans 1 row/column. */
@@ -1211,7 +1242,8 @@
       /* Child needs allocation & spans a single row or column. */
       if (requested_size >= 0.0 && child->size[d] == 1)
 	{
-	  requested_size += child->start_pad[d] + child->end_pad[d];
+	  requested_size += layout_data->children[i].start_pad[d]
+	    + layout_data->children[i].end_pad[d];
 	  start = child->start[d];
 	  dldata[start].requisition = MAX (dldata[start].requisition,
 					   requested_size);
@@ -1288,7 +1320,8 @@
 	     its requisition, then divide up the needed space amongst the
 	     columns it spans, favoring expandable columns if any. */
 	  space_needed = layout_data->children[i].requested_size[d]
-	    + child->start_pad[d] + child->end_pad[d];
+	    + layout_data->children[i].start_pad[d]
+	    + layout_data->children[i].end_pad[d];
 
 	  if (total_space < space_needed)
 	    {
@@ -1309,14 +1342,27 @@
 		  force_expand = TRUE;
 		}
 		    
-	      /* FIXME: Integer mode for widgets? Otherwise we may allocate
-		 fractions of pixels to widgets so there may be unwanted
-		 gaps between them. */
-	      extra = expand / n_expand;
-	      for (j = start; j <= end; j++)
+	      if (layout_data->integer_layout)
 		{
-		  if (force_expand || dldata[j].expand)
-		    dldata[j].requisition += extra;
+		  for (j = start; j <= end; j++)
+		    {
+		      if (force_expand || dldata[j].expand)
+			{
+			  extra = floor (expand / n_expand + 0.5);
+			  dldata[j].requisition += extra;
+			  expand -= extra;
+			  n_expand--;
+			}
+		    }
+		}
+	      else
+		{
+		  extra = expand / n_expand;
+		  for (j = start; j <= end; j++)
+		    {
+		      if (force_expand || dldata[j].expand)
+			dldata[j].requisition += extra;
+		    }
 		}
 	    }
 	}
@@ -1359,7 +1405,7 @@
   dimension = &table_data->dimensions[d];
   dldata = layout_data->dldata[d];
 
-  total_size = layout_data->allocated_size[d] - table_data->border_width * 2;
+  total_size = layout_data->allocated_size[d] - layout_data->border_width * 2.0;
 
   natural_size = 0;
   nexpand = 0;
@@ -1389,10 +1435,22 @@
 	  for (i = 0; i + 1 < dimension->size; i++)
 	    size_to_allocate -= dldata[i].spacing;
 	  
-	  /* FIXME: Integer mode for widgets? */
-	  size_to_allocate /= dimension->size;
-	  for (i = 0; i < dimension->size; i++)
-	    dldata[i].allocation = size_to_allocate;
+	  if (layout_data->integer_layout)
+	    {
+	      gint n_elements = dimension->size;
+	      for (i = 0; i < dimension->size; i++)
+		{
+		  dldata[i].allocation = floor (size_to_allocate / n_elements + 0.5);
+		  size_to_allocate -= dldata[i].allocation;
+		  n_elements--;
+		}
+	    }
+	  else
+	    {
+	      size_to_allocate /= dimension->size;
+	      for (i = 0; i < dimension->size; i++)
+		dldata[i].allocation = size_to_allocate;
+	    }
 	}
     }
   else
@@ -1401,12 +1459,28 @@
        */
       if ((natural_size < total_size) && (nexpand >= 1))
 	{
-	  /* FIXME: Integer mode for widgets? */
-	  extra = (total_size - natural_size) / nexpand;
-	  for (i = 0; i < dimension->size; i++)
+	  if (layout_data->integer_layout)
 	    {
-	      if (dldata[i].expand)
-		dldata[i].allocation += extra;
+	      gdouble expand = total_size - natural_size;
+	      for (i = 0; i < dimension->size; i++)
+		{
+		  if (dldata[i].expand)
+		    {
+		      extra = floor (expand / nexpand + 0.5);
+		      dldata[i].allocation += extra;
+		      expand -= extra;
+		      nexpand--;
+		    }
+		}
+	    }
+	  else
+	    {
+	      extra = (total_size - natural_size) / nexpand;
+	      for (i = 0; i < dimension->size; i++)
+		{
+		  if (dldata[i].expand)
+		    dldata[i].allocation += extra;
+		}
 	    }
 	}
 	  
@@ -1418,7 +1492,6 @@
 	  gint total_nshrink = nshrink;
 	      
 	  extra = natural_size - total_size;
-	  /* FIXME: Integer mode for widgets? */
 	  while (total_nshrink > 0 && extra > 0)
 	    {
 	      nshrink = total_nshrink;
@@ -1427,8 +1500,14 @@
 		  if (dldata[i].shrink && dldata[i].allocation > 0.0)
 		    {
 		      gdouble old_allocation = dldata[i].allocation;
-		      
-		      dldata[i].allocation = MAX (0.0, dldata[i].allocation - extra / nshrink);
+		      gdouble shrink_amount = extra / nshrink;
+		      gdouble new_allocation;
+
+		      if (layout_data->integer_layout)
+			shrink_amount = floor (shrink_amount + 0.5);
+
+		      new_allocation = old_allocation - shrink_amount;
+		      dldata[i].allocation = MAX (0.0, new_allocation);
 		      extra -= old_allocation - dldata[i].allocation;
 		      nshrink -= 1;
 		      if (dldata[i].allocation <= 0.0)
@@ -1456,13 +1535,18 @@
   dimension = &table_data->dimensions[d];
   dldata = layout_data->dldata[d];
 
-  pos = table_data->border_width;
+  pos = layout_data->border_width;
   for (i = 0; i < dimension->size; i++)
     {
       dldata[i].start = pos;
       pos += dldata[i].allocation;
       dldata[i].end = pos;
       pos += dldata[i].spacing;
+
+#if 0
+      g_print ("%s %i: %g - %g\n", d ? "Row" : "Column", i,
+	       dldata[i].start, dldata[i].end);
+#endif
     }
 }
 
@@ -1508,13 +1592,13 @@
       
       start_column = child->start[HORZ];
       end_column = child->start[HORZ] + child->size[HORZ] - 1;
-      x = columns[start_column].start + child->start_pad[HORZ];
-      max_width = columns[end_column].end - child->end_pad[HORZ] - x;
+      x = columns[start_column].start + layout_data->children[i].start_pad[HORZ];
+      max_width = columns[end_column].end - layout_data->children[i].end_pad[HORZ] - x;
 
       start_row = child->start[VERT];
       end_row = child->start[VERT] + child->size[VERT] - 1;
-      y = rows[start_row].start + child->start_pad[VERT];
-      max_height = rows[end_row].end - child->end_pad[VERT] - y;
+      y = rows[start_row].start + layout_data->children[i].start_pad[VERT];
+      max_height = rows[end_row].end - layout_data->children[i].end_pad[VERT] - y;
 
       width = max_width = MAX (0.0, max_width);
       height = max_height = MAX (0.0, max_height);
@@ -1523,12 +1607,18 @@
 	{
 	  width = MIN (max_width, requested_width);
 	  x += (max_width - width) * child->align[HORZ];
+
+	  if (layout_data->integer_layout)
+	    x = floor (x + 0.5);
 	}
 	  
       if (!(child->flags[VERT] & GOO_CANVAS_TABLE_CHILD_FILL))
 	{
 	  height = MIN (max_height, requested_height);
 	  y += (max_height - height) * child->align[VERT];
+
+	  if (layout_data->integer_layout)
+	    y = floor (y + 0.5);
 	}
 
       if (direction == GTK_TEXT_DIR_RTL)
@@ -1607,8 +1697,8 @@
 
       start_column = child->start[HORZ];
       end_column = child->start[HORZ] + child->size[HORZ] - 1;
-      x = columns[start_column].start + child->start_pad[HORZ];
-      max_width = columns[end_column].end - child->end_pad[HORZ] - x;
+      x = columns[start_column].start + layout_data->children[i].start_pad[HORZ];
+      max_width = columns[end_column].end - layout_data->children[i].end_pad[HORZ] - x;
 
       width = max_width = MAX (0.0, max_width);
 
@@ -1634,7 +1724,7 @@
       if (row < end)
 	height += rows[row].spacing;
     }
-  height += table_data->border_width * 2;
+  height += layout_data->border_width * 2.0;
 
   layout_data->natural_size[VERT] = height;
 }
@@ -1693,7 +1783,7 @@
       if (column < end)
 	width += columns[column].spacing;
     }
-  width += table_data->border_width * 2;
+  width += layout_data->border_width * 2.0;
   
   /* Save the natural size, so we know if we have to clip children. */
   layout_data->natural_size[HORZ] = width;
@@ -1720,7 +1810,7 @@
       if (row < end)
 	height += rows[row].spacing;
     }
-  height += table_data->border_width * 2;
+  height += layout_data->border_width * 2.0;
 
   /* Save the natural size, so we know if we have to clip children. */
   layout_data->natural_size[VERT] = height;
@@ -1773,6 +1863,9 @@
     allocated_width /= simple_data->transform->xx;
   layout_data->allocated_size[HORZ] = allocated_width;
 
+  if (layout_data->integer_layout)
+    layout_data->allocated_size[HORZ] = floor (layout_data->allocated_size[HORZ]);
+
   goo_canvas_table_update_requested_heights (item, cr);
 
   cairo_restore (cr);
@@ -1833,6 +1926,12 @@
       layout_data->allocated_size[VERT] = layout_data->requested_size[VERT] * height_proportion;
     }
 
+  if (layout_data->integer_layout)
+    {
+      layout_data->allocated_size[HORZ] = floor (layout_data->requested_size[HORZ]);
+      layout_data->allocated_size[VERT] = floor (layout_data->requested_size[VERT]);
+    }
+
   /* We have to remove the translation that our parent is giving us while we
      update the size requests, otherwise child items' bounds will include the
      translation which we result in incorrect bounds after allocation. */
@@ -1969,6 +2068,14 @@
 	  y = rows[start_row].start + table_child->start_pad[VERT];
 	  end_y = rows[end_row].end - table_child->end_pad[VERT];
 
+	  if (simple->canvas->integer_layout)
+	    {
+	      x = floor (x + 0.5);
+	      end_x = floor (end_x + 0.5);
+	      y = floor (y + 0.5);
+	      end_y = floor (end_y + 0.5);
+	    }
+
 	  /* Make sure it doesn't go outside the table's allocated size. */
 	  end_x = MIN (end_x, layout_data->allocated_size[HORZ]);
 	  end_y = MIN (end_y, layout_data->allocated_size[VERT]);
@@ -2100,6 +2207,14 @@
 	  start_y = rows[start_row].start + table_child->start_pad[VERT];
 	  end_y = rows[end_row].end - table_child->end_pad[VERT];
 
+	  if (simple->canvas->integer_layout)
+	    {
+	      start_x = floor (start_x + 0.5);
+	      end_x = floor (end_x + 0.5);
+	      start_y = floor (start_y + 0.5);
+	      end_y = floor (end_y + 0.5);
+	    }
+
 	  if (user_x < start_x || user_x > end_x
 	      || user_y < start_y || user_y > end_y)
 	    continue;



More information about the cairo-commit mailing list