From 3517286a9404d556c384276d63b73b588fadbcfe Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 3 Jan 2014 22:24:11 +0000 Subject: Draw and layout performance improvements. git-svn-id: http://svn.drobilla.net/lad/trunk/ganv@5248 a436a847-0d15-0410-975c-d299462d15a1 --- src/canvas-base.c | 79 ++++++++++++++++++++++--------------------------------- 1 file changed, 32 insertions(+), 47 deletions(-) (limited to 'src/canvas-base.c') diff --git a/src/canvas-base.c b/src/canvas-base.c index 8d8b8d1..e30a517 100644 --- a/src/canvas-base.c +++ b/src/canvas-base.c @@ -673,6 +673,12 @@ ganv_item_grab_focus(GanvItem* item) } } +static void +ganv_item_default_bounds(GanvItem* item, double* x1, double* y1, double* x2, double* y2) +{ + *x1 = *y1 = *x2 = *y2 = 0.0; +} + /** * ganv_item_get_bounds: * @item: A canvas item. @@ -687,20 +693,7 @@ ganv_item_grab_focus(GanvItem* item) void ganv_item_get_bounds(GanvItem* item, double* x1, double* y1, double* x2, double* y2) { - g_return_if_fail(GANV_IS_ITEM(item)); - - if (GANV_ITEM_GET_CLASS(item)->bounds) { - // Get bounds from item class - (*GANV_ITEM_GET_CLASS(item)->bounds)(item, x1, y1, x2, y2); - - // Make bounds relative to the item's parent coordinate system - *x1 -= item->x; - *y1 -= item->y; - *x2 -= item->x; - *y2 -= item->y; - } else { - *x1 = *y1 = *x2 = *y2 = 0.0; - } + GANV_ITEM_GET_CLASS(item)->bounds(item, x1, y1, x2, y2); } /** @@ -1748,46 +1741,37 @@ ganv_canvas_base_paint_rect(GanvCanvasBase* canvas, gint x0, gint y0, gint x1, g static gint ganv_canvas_base_expose(GtkWidget* widget, GdkEventExpose* event) { - GanvCanvasBase* canvas; - GdkRectangle* rects; - gint n_rects; - int i; - - canvas = GANV_CANVAS_BASE(widget); - - if (!GTK_WIDGET_DRAWABLE(widget) || (event->window != canvas->layout.bin_window)) { + GanvCanvasBase* canvas = GANV_CANVAS_BASE(widget); + if (!GTK_WIDGET_DRAWABLE(widget) || + (event->window != canvas->layout.bin_window)) { return FALSE; } -#ifdef VERBOSE - g_print("Expose\n"); -#endif - - gdk_region_get_rectangles(event->region, &rects, &n_rects); - - for (i = 0; i < n_rects; i++) { - const int x0 = rects[i].x - canvas->zoom_xofs; - const int y0 = rects[i].y - canvas->zoom_yofs; - const int x1 = rects[i].x + rects[i].width - canvas->zoom_xofs; - const int y1 = rects[i].y + rects[i].height - canvas->zoom_yofs; - - if (canvas->need_update || canvas->need_redraw) { - /* Update or drawing is scheduled, so just mark exposed area as dirty */ - ganv_canvas_base_request_redraw(canvas, x0, y0, x1, y1); - } else { - /* No pending updates, draw exposed area immediately */ - ganv_canvas_base_paint_rect(canvas, x0, y0, x1, y1); + /* Find a single bounding rectangle for all rectangles in the region. + Since drawing the root group is O(n) and thus very expensive for large + canvases, it's much faster to do a single paint than many, even though + more area may be painted that way. With a better group implementation, + it would likely be better to paint each changed rectangle separately. */ + GdkRectangle clip; + gdk_region_get_clipbox(event->region, &clip); + + const int x2 = clip.x + clip.width; + const int y2 = clip.y + clip.height; + + if (canvas->need_update || canvas->need_redraw) { + /* Update or drawing is scheduled, so just mark exposed area as dirty */ + ganv_canvas_base_request_redraw(canvas, clip.x, clip.y, x2, y2); + } else { + /* No pending updates, draw exposed area immediately */ + ganv_canvas_base_paint_rect(canvas, clip.x, clip.y, x2, y2); - /* And call expose on parent container class */ - if (GTK_WIDGET_CLASS(canvas_parent_class)->expose_event) { - (*GTK_WIDGET_CLASS(canvas_parent_class)->expose_event)( - widget, event); - } + /* And call expose on parent container class */ + if (GTK_WIDGET_CLASS(canvas_parent_class)->expose_event) { + (*GTK_WIDGET_CLASS(canvas_parent_class)->expose_event)( + widget, event); } } - g_free(rects); - return FALSE; } @@ -2515,4 +2499,5 @@ ganv_item_class_init(GanvItemClass* klass) klass->unmap = ganv_item_unmap; klass->update = ganv_item_update; klass->point = ganv_item_point; + klass->bounds = ganv_item_default_bounds; } -- cgit v1.2.1