[cairo-commit] goocanvas/src goocanvasgroup.c, 1.19, 1.20 goocanvasitemsimple.c, 1.21, 1.22 goocanvasrect.c, 1.10, 1.11 goocanvastable.c, 1.7, 1.8 goocanvastable.h, 1.5, 1.6

Damon Chaplin commit at pdx.freedesktop.org
Tue Feb 20 14:54:52 PST 2007


Committed by: damon

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

Modified Files:
	goocanvasgroup.c goocanvasitemsimple.c goocanvasrect.c 
	goocanvastable.c goocanvastable.h 
Log Message:
2007-02-20  Damon Chaplin  <damon at gnome.org>

	* src/goocanvastable.c (goo_canvas_table_get_item_at) 
	(goo_canvas_table_paint): if the table was shrunk below its requested
	size, clip the children if appropriate.

	* src/goocanvastable.c (goo_canvas_table_get_item_at) 
	(goo_canvas_table_paint): 
	* src/goocanvasgroup.c (goo_canvas_group_get_item_at) 
	(goo_canvas_group_paint): check the bounds and handle the clip path.

	* demo/table-demo.c (create_demo_table): added parameters and created
	a second table of shapes, this time with the items shrunk and clipped.



Index: goocanvasgroup.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasgroup.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- goocanvasgroup.c	17 Feb 2007 13:48:37 -0000	1.19
+++ goocanvasgroup.c	20 Feb 2007 22:54:46 -0000	1.20
@@ -411,6 +411,11 @@
   if (simple->need_update)
     goo_canvas_item_ensure_updated (item);
 
+  /* Skip the item if the point isn't in the item's bounds. */
+  if (simple->bounds.x1 > x || simple->bounds.x2 < x
+      || simple->bounds.y1 > y || simple->bounds.y2 < y)
+    return NULL;
+
   if (simple_data->visibility <= GOO_CANVAS_ITEM_INVISIBLE
       || (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
 	  && simple->canvas->scale < simple_data->visibility_threshold))
@@ -429,6 +434,21 @@
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  /* If the group has a clip path, check if the point is inside it. */
+  if (simple_data->clip_path_commands)
+    {
+      double user_x = x, user_y = y;
+
+      cairo_device_to_user (cr, &user_x, &user_y);
+      goo_canvas_create_path (simple_data->clip_path_commands, cr);
+      cairo_set_fill_rule (cr, simple_data->clip_fill_rule);
+      if (!cairo_in_fill (cr, user_x, user_y))
+	{
+	  cairo_restore (cr);
+	  return NULL;
+	}
+    }
+
   for (i = group->items->len - 1; i >= 0; i--)
     {
       GooCanvasItem *child = group->items->pdata[i];
@@ -455,6 +475,11 @@
   GooCanvasGroup *group = (GooCanvasGroup*) item;
   gint i;
 
+  /* Skip the item if the bounds don't intersect the expose rectangle. */
+  if (simple->bounds.x1 > bounds->x2 || simple->bounds.x2 < bounds->x1
+      || simple->bounds.y1 > bounds->y2 || simple->bounds.y2 < bounds->y1)
+    return;
+
   /* Check if the item should be visible. */
   if (simple_data->visibility <= GOO_CANVAS_ITEM_INVISIBLE
       || (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
@@ -466,6 +491,14 @@
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  /* Clip with the group's clip path, if it is set. */
+  if (simple_data->clip_path_commands)
+    {
+      goo_canvas_create_path (simple_data->clip_path_commands, cr);
+      cairo_set_fill_rule (cr, simple_data->clip_fill_rule);
+      cairo_clip (cr);
+    }
+
   for (i = 0; i < group->items->len; i++)
     {
       GooCanvasItem *child = group->items->pdata[i];

Index: goocanvasitemsimple.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasitemsimple.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- goocanvasitemsimple.c	17 Feb 2007 13:48:37 -0000	1.21
+++ goocanvasitemsimple.c	20 Feb 2007 22:54:46 -0000	1.22
@@ -970,6 +970,7 @@
   matrix.x0 = matrix.y0 = 0.0;
   cairo_set_matrix (cr, &matrix);
 
+  /* If the item has a clip path, check if the point is inside it. */
   if (simple_data->clip_path_commands)
     {
       goo_canvas_create_path (simple_data->clip_path_commands, cr);
@@ -1270,6 +1271,7 @@
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  /* Clip with the item's clip path, if it is set. */
   if (simple_data->clip_path_commands)
     {
       goo_canvas_create_path (simple_data->clip_path_commands, cr);

Index: goocanvasrect.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasrect.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- goocanvasrect.c	17 Feb 2007 13:48:37 -0000	1.10
+++ goocanvasrect.c	20 Feb 2007 22:54:46 -0000	1.11
@@ -383,11 +383,8 @@
   else
     {
       /* Draw the plain rectangle. */
-      cairo_move_to (cr, rect_data->x, rect_data->y);
-      cairo_line_to (cr, rect_data->x, rect_data->y + rect_data->height);
-      cairo_line_to (cr, rect_data->x + rect_data->width,
-		     rect_data->y + rect_data->height);
-      cairo_line_to (cr, rect_data->x + rect_data->width, rect_data->y);
+      cairo_rectangle (cr, rect_data->x, rect_data->y,
+		       rect_data->width, rect_data->height);
       cairo_close_path (cr);
     }
 }

Index: goocanvastable.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvastable.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- goocanvastable.c	20 Feb 2007 14:22:03 -0000	1.7
+++ goocanvastable.c	20 Feb 2007 22:54:46 -0000	1.8
@@ -121,7 +121,7 @@
   gdouble requested_size[2];
 };
 
-/* This is only meant to be kept around while doing the layout.
+/* The children array is only kept around while doing the layout.
    It gets freed in goo_canvas_table_allocate_area(). */
 struct _GooCanvasTableLayoutData
 {
@@ -129,6 +129,7 @@
   GooCanvasTableChildLayoutData *children;
 
   /* These are in the table's coordinate space. */
+  gdouble natural_size[2];
   gdouble requested_size[2];
   gdouble allocated_size[2];
 };
@@ -985,7 +986,7 @@
   GooCanvasTableDimensionLayoutData *dldata;
   gint d, i;
 
-  /* Free any previous data, just in case it hasn't been freed. */
+  /* Free any previous data. */
   goo_canvas_table_free_layout_data (table->table_data);
 
   layout_data = g_slice_new (GooCanvasTableLayoutData);
@@ -1258,7 +1259,9 @@
 		      force_expand = TRUE;
 		    }
 		    
-		  /* FIXME: Integer mode for widgets? */
+		  /* 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++)
 		    {
@@ -1331,6 +1334,10 @@
   width += table_data->border_width * 2;
   height += table_data->border_width * 2;
 
+  /* Save the natural size, so we know if we have to clip children. */
+  layout_data->natural_size[HORZ] = width;
+  layout_data->natural_size[VERT] = height;
+
   /* If the width or height has been set, that overrides the calculations. */
   if (table_data->width > 0.0)
     width = table_data->width;
@@ -1682,7 +1689,9 @@
   goo_canvas_table_size_allocate_pass2 (table);
   goo_canvas_table_size_allocate_pass3 (table, cr, x_offset, y_offset);
 
-  goo_canvas_table_free_layout_data (table_data);
+  /* We free the children array but keep the dimension data. */
+  g_free (layout_data->children);
+  layout_data->children = NULL;
 
   cairo_restore (cr);
 }
@@ -1725,10 +1734,20 @@
   GooCanvasGroup *group = (GooCanvasGroup*) item;
   GooCanvasTable *table = (GooCanvasTable*) item;
   GooCanvasTableData *table_data = table->table_data;
+  GooCanvasTableLayoutData *layout_data = table_data->layout_data;
+  GooCanvasTableDimensionLayoutData *rows = layout_data->dldata[VERT];
+  GooCanvasTableDimensionLayoutData *columns = layout_data->dldata[HORZ];
   GArray *children = table_data->children;
   GooCanvasTableChild *table_child;
   GooCanvasItem *child;
-  gint i;
+  gboolean check_clip = FALSE, clip;
+  gint start_column, end_column, start_row, end_row, i, j;
+  gdouble x, y, max_width, max_height;
+
+  /* Skip the item if the bounds don't intersect the expose rectangle. */
+  if (simple->bounds.x1 > bounds->x2 || simple->bounds.x2 < bounds->x1
+      || simple->bounds.y1 > bounds->y2 || simple->bounds.y2 < bounds->y1)
+    return;
 
   /* Check if the item should be visible. */
   if (simple_data->visibility <= GOO_CANVAS_ITEM_INVISIBLE
@@ -1741,19 +1760,71 @@
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  /* Clip with the table's clip path, if it is set. */
+  if (simple_data->clip_path_commands)
+    {
+      goo_canvas_create_path (simple_data->clip_path_commands, cr);
+      cairo_set_fill_rule (cr, simple_data->clip_fill_rule);
+      cairo_clip (cr);
+    }
+
+  /* Check if the table was allocated less space than it requested, in which
+     case we may need to clip children. */
+  if (layout_data->allocated_size[HORZ] < layout_data->natural_size[HORZ]
+      || layout_data->allocated_size[VERT] < layout_data->natural_size[VERT])
+    check_clip = TRUE;
+
   for (i = 0; i < group->items->len; i++)
     {
       child = group->items->pdata[i];
 
       table_child = &g_array_index (children, GooCanvasTableChild, i);
+      clip = FALSE;
+
+      /* Clip the child to make sure it doesn't go outside its area. */
+      if (check_clip)
+	{
+	  /* Calculate the position of the child and how much space it has. */
+	  start_column = table_child->start[HORZ];
+	  end_column = table_child->start[HORZ] + table_child->size[HORZ] - 1;
+	  x = columns[start_column].start + table_child->start_pad[HORZ];
+	  max_width = columns[end_column].end - table_child->end_pad[HORZ] - x;
+
+	  start_row = table_child->start[VERT];
+	  end_row = table_child->start[VERT] + table_child->size[VERT] - 1;
+	  y = rows[start_row].start + table_child->start_pad[VERT];
+	  max_height = rows[end_row].end - table_child->end_pad[VERT] - y;
+
+	  /* Only try to paint the child if it has some allocated space. */
+	  if (max_width <= 0.0 || max_height <= 0.0)
+	    continue;
+
+	  /* Check if any of the rows/columns the child is in can shrink. */
+	  for (j = start_column; j <= end_column; j++)
+	    if (columns[j].shrink)
+	      clip = TRUE;
+
+	  for (j = start_row; j <= end_row; j++)
+	    if (rows[j].shrink)
+	      clip = TRUE;
+			 
+	  /* Only clip the child if it may have been shrunk. */
+	  if (clip)
+	    {
+	      cairo_save (cr);
+	      cairo_rectangle (cr, x, y, max_width, max_height);
+	      cairo_clip (cr);
+	    }
+	}
+
       cairo_translate (cr, table_child->position[HORZ],
 		       table_child->position[VERT]);
-
-      /* FIXME: Clip the child to make sure it doesn't go outside its area? */
       goo_canvas_item_paint (child, cr, bounds, scale);
-
       cairo_translate (cr, -table_child->position[HORZ],
 		       -table_child->position[VERT]);
+
+      if (clip)
+	cairo_restore (cr);
     }
   cairo_restore (cr);
 }
@@ -1772,16 +1843,26 @@
   GooCanvasGroup *group = (GooCanvasGroup*) item;
   GooCanvasTable *table = (GooCanvasTable*) item;
   GooCanvasTableData *table_data = table->table_data;
+  GooCanvasTableLayoutData *layout_data = table_data->layout_data;
+  GooCanvasTableDimensionLayoutData *rows = layout_data->dldata[VERT];
+  GooCanvasTableDimensionLayoutData *columns = layout_data->dldata[HORZ];
   GArray *children = table_data->children;
   GooCanvasTableChild *table_child;
   GooCanvasItem *child;
   GooCanvasItem *found_item = NULL;
-  gboolean visible = parent_visible;
-  int i;
+  gboolean visible = parent_visible, check_clip = FALSE;
+  double user_x = x, user_y = y;
+  gint start_column, end_column, start_row, end_row, i;
+  gdouble start_x, end_x, start_y, end_y;
 
   if (simple->need_update)
     goo_canvas_item_ensure_updated (item);
 
+  /* Skip the item if the point isn't in the item's bounds. */
+  if (simple->bounds.x1 > x || simple->bounds.x2 < x
+      || simple->bounds.y1 > y || simple->bounds.y2 < y)
+    return NULL;
+
   if (simple_data->visibility <= GOO_CANVAS_ITEM_INVISIBLE
       || (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
 	  && simple->canvas->scale < simple_data->visibility_threshold))
@@ -1800,11 +1881,52 @@
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  cairo_device_to_user (cr, &user_x, &user_y);
+
+  /* If the table has a clip path, check if the point is inside it. */
+  if (simple_data->clip_path_commands)
+    {
+      goo_canvas_create_path (simple_data->clip_path_commands, cr);
+      cairo_set_fill_rule (cr, simple_data->clip_fill_rule);
+      if (!cairo_in_fill (cr, user_x, user_y))
+	{
+	  cairo_restore (cr);
+	  return NULL;
+	}
+    }
+
+  /* Check if the table was allocated less space than it requested, in which
+     case we may need to clip children. */
+  if (layout_data->allocated_size[HORZ] < layout_data->natural_size[HORZ]
+      || layout_data->allocated_size[VERT] < layout_data->natural_size[VERT])
+    check_clip = TRUE;
+
   for (i = group->items->len - 1; i >= 0; i--)
     {
       child = group->items->pdata[i];
 
       table_child = &g_array_index (children, GooCanvasTableChild, i);
+
+      /* If the child may have been clipped, check the point is in the child's
+	 allocated area. */
+      if (check_clip)
+	{
+	  /* Calculate the position of the child and how much space it has. */
+	  start_column = table_child->start[HORZ];
+	  end_column = table_child->start[HORZ] + table_child->size[HORZ] - 1;
+	  start_x = columns[start_column].start + table_child->start_pad[HORZ];
+	  end_x = columns[end_column].end - table_child->end_pad[HORZ];
+
+	  start_row = table_child->start[VERT];
+	  end_row = table_child->start[VERT] + table_child->size[VERT] - 1;
+	  start_y = rows[start_row].start + table_child->start_pad[VERT];
+	  end_y = rows[end_row].end - table_child->end_pad[VERT];
+
+	  if (user_x < start_x || user_x > end_x
+	      || user_y < start_y || user_y > end_y)
+	    continue;
+	}
+
       cairo_translate (cr, table_child->position[HORZ],
 		       table_child->position[VERT]);
 

Index: goocanvastable.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvastable.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- goocanvastable.h	20 Feb 2007 14:22:03 -0000	1.5
+++ goocanvastable.h	20 Feb 2007 22:54:46 -0000	1.6
@@ -44,8 +44,6 @@
   /* An array of GooCanvasTableChild. */
   GArray *children;
 
-  /* This is only meant to be kept around while doing the layout.
-     It gets freed in goo_canvas_table_allocate_area(). */
   GooCanvasTableLayoutData *layout_data;
 };
 



More information about the cairo-commit mailing list