[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