hippo-canvas r7283 - in trunk: common/hippo linux/hippo
- From: otaylor svn gnome org
- To: svn-commits-list gnome org
- Subject: hippo-canvas r7283 - in trunk: common/hippo linux/hippo
- Date: Thu, 26 Jun 2008 12:15:35 +0000 (UTC)
Author: otaylor
Date: Thu Jun 26 12:15:35 2008
New Revision: 7283
URL: http://svn.gnome.org/viewvc/hippo-canvas?rev=7283&view=rev
Log:
Optimize so that we don't repaint the entire box unnecessarily when:
- We have a box with no borders/backgrounds or custom paint
- It resizes but doesn't move
Only the children need to be repainted.
Modified:
trunk/common/hippo/hippo-canvas-box.c
trunk/common/hippo/hippo-canvas-item.c
trunk/linux/hippo/hippo-canvas-helper.c
trunk/linux/hippo/hippo-canvas-window.c
Modified: trunk/common/hippo/hippo-canvas-box.c
==============================================================================
--- trunk/common/hippo/hippo-canvas-box.c (original)
+++ trunk/common/hippo/hippo-canvas-box.c Thu Jun 26 12:15:35 2008
@@ -3179,25 +3179,28 @@
{
BoxChildPrivate *private = (BoxChildPrivate *)child;
gboolean child_moved;
- gboolean child_resized;
int old_width, old_height;
if (child->item == NULL)
return;
hippo_canvas_item_get_allocation(child->item, &old_width, &old_height);
-
+
child_moved = x != private->x || y != private->y;
- child_resized = width != old_width || height != old_height;
-
- if ((child_moved || child_resized) && (old_width != 0 || old_height != 0))
+
+ /* We handle repainting when the child moves here, the child is however
+ * responsible for repainting itself on resize (this is to allow pure-containers
+ * that don't draw anything to avoid repainting children that stay fixed when
+ * the container resizes.
+ */
+ if (child_moved && (old_width != 0 || old_height != 0))
hippo_canvas_item_emit_paint_needed(HIPPO_CANVAS_ITEM(private->box),
private->x, private->y, old_width, old_height);
private->x = x;
private->y = y;
- if ((child_moved || child_resized) && (width != 0 || height != 0))
+ if (child_moved && (width != 0 || height != 0))
hippo_canvas_item_emit_paint_needed(HIPPO_CANVAS_ITEM(private->box),
x, y, width, height);
@@ -3325,6 +3328,31 @@
}
static void
+layout_all_children_hidden(HippoCanvasBox *box)
+{
+ GSList *link;
+
+ /* If we are !visible (0 allocation) then allocate all our
+ * children to 0. This should happen in the layout algorithms
+ * below, but they are all lame about dealing with too-small
+ * allocations, so they don't "just work" for this.
+ */
+
+ for (link = box->children; link != NULL; link = link->next) {
+ HippoCanvasBoxChild *child = link->data;
+ hippo_canvas_box_child_allocate(child, 0, 0, 0, 0, FALSE);
+ }
+}
+
+static gboolean
+has_paint_signal_handlers(HippoCanvasItem *item)
+{
+ guint paint_id = g_signal_lookup("paint", HIPPO_TYPE_CANVAS_ITEM);
+
+ return g_signal_has_handler_pending(item, paint_id, 0, TRUE);
+}
+
+static void
hippo_canvas_box_allocate(HippoCanvasItem *item,
int allocated_box_width,
int allocated_box_height,
@@ -3340,23 +3368,94 @@
GSList *link;
int content_x, content_y;
gboolean has_floats;
+ gboolean size_changed;
box = HIPPO_CANVAS_BOX(item);
+ size_changed = (box->allocated_width != allocated_box_width ||
+ box->allocated_height != allocated_box_height);
+
/* If we haven't emitted request-changed then we are allowed to short-circuit
* an unchanged allocation
*/
- if (!origin_changed && !box->needs_allocate &&
- (box->allocated_width == allocated_box_width &&
- box->allocated_height == allocated_box_height))
+ if (!origin_changed && !size_changed && !box->needs_allocate)
return;
+ /* Figure out whether we need to queue a repaint */
+ if (size_changed && !origin_changed) {
+ HippoCanvasBoxClass *klass = HIPPO_CANVAS_BOX_GET_CLASS(box);
+ gboolean need_repaint = TRUE;
+
+ /* Detecting if we need to repaint the box on resize is hard; it's possible
+ * that we should just make it a property; the problem with making it a
+ * property is that we want to avoid such repaints of HippoCanvasBox,
+ * as a pure container, so we'd have to make it default off. And so then
+ * you'd have to set it before connecting to ::paint or overriding
+ * paint_below_children.
+ *
+ * The exact rule we follow here is somewhat non-scientific:
+ *
+ * - We draw borders, or background => need resize
+ * - Subclass overrides paint_below_children or paint_above_children => need resize
+ * - User connects to ::paint => resize needed
+ * (Consider this a way of customizing existing painting)
+ * - Subclass overrides paint => NO resize needed
+ * (Subclass is really doing it's own thing ... skipping borders and backgrounds.
+ * we dont' want to break this optimization for such classes)
+ */
+ if (klass->paint_below_children == NULL &&
+ klass->paint_above_children == NULL &&
+ klass->paint_background == hippo_canvas_box_paint_background &&
+ !has_paint_signal_handlers(item))
+ {
+ HippoCanvasStyle *style = hippo_canvas_context_get_style(HIPPO_CANVAS_CONTEXT(box));
+ guint32 background_color_rgba;
+ guint32 border_color_rgba;
+
+ if (box->background_color_set)
+ background_color_rgba = box->background_color_rgba;
+ else
+ background_color_rgba = hippo_canvas_style_get_background_color(style);
+
+ if (box->border_color_set)
+ border_color_rgba = box->border_color_rgba;
+ else
+ /* We just care if any have non-zero in the bottom bits, so | together */
+ border_color_rgba =
+ (hippo_canvas_style_get_border_color(style, HIPPO_CANVAS_SIDE_LEFT) |
+ hippo_canvas_style_get_border_color(style, HIPPO_CANVAS_SIDE_RIGHT) |
+ hippo_canvas_style_get_border_color(style, HIPPO_CANVAS_SIDE_TOP) |
+ hippo_canvas_style_get_border_color(style, HIPPO_CANVAS_SIDE_BOTTOM));
+
+ if (hippo_canvas_style_get_background_theme_image(style) == NULL &&
+ (background_color_rgba & 0xff) == 0 &&
+ (border_color_rgba & 0xff) == 0)
+ need_repaint = FALSE;
+ }
+
+ /* Our repaint area would be a little more accurate if we invalidated the old and new
+ * sizes separately, instead of combining them into a single box, but it's not
+ * going to be common to resize by large amounts in both directions at once.
+ */
+ if (need_repaint)
+ hippo_canvas_item_emit_paint_needed(HIPPO_CANVAS_ITEM(box), 0, 0,
+ MAX(box->allocated_width, allocated_box_width),
+ MAX(box->allocated_height, allocated_box_height));
+ }
+
box->allocated_width = allocated_box_width;
box->allocated_height = allocated_box_height;
box->needs_allocate = FALSE;
+ if (allocated_box_width <= 0 || allocated_box_height <= 0) {
+ /* Skip computation of content area in this common case (item hidden) */
+
+ layout_all_children_hidden(box);
+ return;
+ }
+
get_content_width_request(box, &requested_content_width, &natural_content_width);
-
+
get_content_area_horizontal(box, requested_content_width, natural_content_width,
allocated_box_width,
&content_x, &allocated_content_width);
@@ -3364,12 +3463,11 @@
get_content_height_request(box,
allocated_content_width,
&requested_content_height, &natural_content_height);
-
+
get_content_area_vertical(box, requested_content_height, natural_content_height,
allocated_box_height,
&content_y, &allocated_content_height);
-
if (box->debug_name != NULL) {
g_debug("box %s allocated %dx%d requested %dx%d lay out into %d,%d %dx%d",
box->debug_name, box->allocated_width, box->allocated_height,
@@ -3377,18 +3475,8 @@
content_x, content_y, allocated_content_width, allocated_content_height);
}
- if (allocated_content_width == 0 || allocated_content_height == 0) {
-
- /* If we are !visible (0 allocation) then allocate all our
- * children to 0. This should happen in the layout algorithms
- * below, but they are all lame about dealing with too-small
- * allocations, so they don't "just work" for this.
- */
-
- for (link = box->children; link != NULL; link = link->next) {
- HippoCanvasBoxChild *child = link->data;
- hippo_canvas_box_child_allocate(child, 0, 0, 0, 0, origin_changed);
- }
+ if (allocated_content_width <= 0 || allocated_content_height <= 0) {
+ layout_all_children_hidden(box);
} else {
/* Allocate fixed children their natural size and invisible
* children 0x0
Modified: trunk/common/hippo/hippo-canvas-item.c
==============================================================================
--- trunk/common/hippo/hippo-canvas-item.c (original)
+++ trunk/common/hippo/hippo-canvas-item.c Thu Jun 26 12:15:35 2008
@@ -593,6 +593,10 @@
damage_box.height = h;
}
+ /* Skip chaining signal emission up the tree if nothing to invalidate */
+ if (damage_box.width <= 0 || damage_box.height <= 0)
+ return;
+
g_signal_emit(canvas_item, signals[PAINT_NEEDED], 0,
&damage_box);
}
Modified: trunk/linux/hippo/hippo-canvas-helper.c
==============================================================================
--- trunk/linux/hippo/hippo-canvas-helper.c (original)
+++ trunk/linux/hippo/hippo-canvas-helper.c Thu Jun 26 12:15:35 2008
@@ -538,15 +538,12 @@
int border_width = GTK_CONTAINER(helper->widget)->border_width;
int child_width = allocation->width - border_width * 2;
int child_height = allocation->height - border_width * 2;
- int old_width, old_height;
gboolean border_changed;
- hippo_canvas_item_get_allocation(helper->root, &old_width, &old_height);
-
border_changed = border_width = helper->last_allocated_border;
helper->last_allocated_border = border_width;
- if (child_width != old_width || child_height != old_height || border_changed)
+ if (border_changed)
gtk_widget_queue_draw(helper->widget);
hippo_canvas_item_allocate(helper->root,
@@ -1281,7 +1278,7 @@
int window_x, window_y;
get_root_item_window_coords(helper, &window_x, &window_y);
-
+
gtk_widget_queue_draw_area(widget,
damage_box->x + window_x,
damage_box->y + window_y,
Modified: trunk/linux/hippo/hippo-canvas-window.c
==============================================================================
--- trunk/linux/hippo/hippo-canvas-window.c (original)
+++ trunk/linux/hippo/hippo-canvas-window.c Thu Jun 26 12:15:35 2008
@@ -92,6 +92,7 @@
GtkWidget *window_child;
gtk_widget_set_app_paintable(widget, TRUE);
+ gtk_widget_set_redraw_on_allocate(widget, FALSE);
gtk_widget_add_events(widget, HIPPO_CANVAS_EVENT_MASK);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]