From 646675f0d21abec2848ae8e25f906aa693139fbd Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 13 Dec 2011 21:22:11 +0000 Subject: Remove libart dependency. Replace unneeded arbitrary per-item affine with simple x, y coordinates. git-svn-id: http://svn.drobilla.net/lad/trunk/ganv@3867 a436a847-0d15-0410-975c-d299462d15a1 --- ganv.pc.in | 2 +- ganv/canvas-base.h | 43 ++--- src/box.c | 8 +- src/canvas-base.c | 483 ++++++++++++----------------------------------------- src/circle.c | 6 +- src/edge.c | 6 +- src/module.c | 11 +- src/node.c | 18 ++ src/text.c | 9 +- src/widget.c | 6 +- wscript | 2 - 11 files changed, 157 insertions(+), 437 deletions(-) diff --git a/ganv.pc.in b/ganv.pc.in index 4769111..7255764 100644 --- a/ganv.pc.in +++ b/ganv.pc.in @@ -6,6 +6,6 @@ includedir=@INCLUDEDIR@ Name: ganv Version: @GANV_VERSION@ Description: A Gtkmm canvas widget for graph based interfaces -Requires: gobject-2.0, libart-2.0 +Requires: gobject-2.0 Libs: -L${libdir} -l@LIB_GANV@ Cflags: -I${includedir}/ganv-@GANV_MAJOR_VERSION@ diff --git a/ganv/canvas-base.h b/ganv/canvas-base.h index 94f9580..bca4951 100644 --- a/ganv/canvas-base.h +++ b/ganv/canvas-base.h @@ -56,15 +56,13 @@ typedef struct _GanvGroupClass GanvGroupClass; /* Object flags for items */ enum { - GANV_ITEM_REALIZED = 1 << 4, - GANV_ITEM_MAPPED = 1 << 5, - GANV_ITEM_ALWAYS_REDRAW = 1 << 6, - GANV_ITEM_VISIBLE = 1 << 7, - GANV_ITEM_NEED_UPDATE = 1 << 8, - GANV_ITEM_NEED_AFFINE = 1 << 9, - GANV_ITEM_NEED_CLIP = 1 << 10, - GANV_ITEM_NEED_VIS = 1 << 11, - GANV_ITEM_AFFINE_FULL = 1 << 12 + GANV_ITEM_REALIZED = 1 << 1, + GANV_ITEM_MAPPED = 1 << 2, + GANV_ITEM_ALWAYS_REDRAW = 1 << 3, + GANV_ITEM_VISIBLE = 1 << 4, + GANV_ITEM_NEED_UPDATE = 1 << 5, + GANV_ITEM_NEED_CLIP = 1 << 6, + GANV_ITEM_NEED_VIS = 1 << 7, }; /* Update flags for items */ @@ -92,12 +90,8 @@ struct _GanvItem { /* Parent canvas group for this item (a GanvGroup) */ GanvItem* parent; - /* If NULL, assumed to be the identity tranform. If flags does not have - * AFFINE_FULL, then a two-element array containing a translation. If - * flags contains AFFINE_FULL, a six-element array containing an affine - * transformation. - */ - double* xform; + /* Position in parent-relative coordinates. */ + double x, y; /* Bounding box for this item (in canvas coordinates) */ double x1, y1, x2, y2; @@ -108,11 +102,10 @@ struct _GanvItemClass { /* Tell the item to update itself. The flags are from the update flags * defined above. The item should update its internal state from its - * queued state, and recompute and request its repaint area. The - * affine, if used, is a pointer to a 6-element array of doubles. The - * update method also recomputes the bounding box of the item. + * queued state, and recompute and request its repaint area. The update + * method also recomputes the bounding box of the item. */ - void (* update)(GanvItem* item, double* affine, int flags); + void (* update)(GanvItem* item, int flags); /* Realize an item -- create GCs, etc. */ void (* realize)(GanvItem* item); @@ -182,12 +175,6 @@ void ganv_item_set_valist(GanvItem* item, /* Move an item by the specified amount */ void ganv_item_move(GanvItem* item, double dx, double dy); -/* Apply a relative affine transformation to the item. */ -void ganv_item_affine_relative(GanvItem* item, const double affine[6]); - -/* Apply an absolute affine transformation to the item. */ -void ganv_item_affine_absolute(GanvItem* item, const double affine[6]); - /* Raise an item in the z-order of its parent group by the specified number of * positions. */ @@ -236,12 +223,12 @@ void ganv_item_i2w(GanvItem* item, double* x, double* y); /* Gets the affine transform that converts from item-relative coordinates to * world coordinates. */ -void ganv_item_i2w_affine(GanvItem* item, double affine[6]); +void ganv_item_i2w_affine(GanvItem* item, cairo_matrix_t* matrix); /* Gets the affine transform that converts from item-relative coordinates to * canvas pixel coordinates. */ -void ganv_item_i2c_affine(GanvItem* item, double affine[6]); +void ganv_item_i2c_affine(GanvItem* item, cairo_matrix_t* matrix); /* Remove the item from its parent group and make the new group its parent. The * item will be put on top of all the items in the new group. The item's @@ -486,7 +473,7 @@ void ganv_canvas_base_request_redraw(GanvCanvasBase* canvas, int x1, int y1, int /* Gets the affine transform that converts world coordinates into canvas pixel * coordinates. */ -void ganv_canvas_base_w2c_affine(GanvCanvasBase* canvas, double affine[6]); +void ganv_canvas_base_w2c_affine(GanvCanvasBase* canvas, cairo_matrix_t* matrix); /* These functions convert from a coordinate system to another. "w" is world * coordinates, "c" is canvas pixel coordinates (pixel coordinates that are diff --git a/src/box.c b/src/box.c index 38ed9a4..2390c9d 100644 --- a/src/box.c +++ b/src/box.c @@ -145,7 +145,6 @@ ganv_box_bounds_item(const GanvBoxCoords* coords, } } - static void request_redraw(GanvItem* item, const GanvBoxCoords* coords, @@ -183,9 +182,7 @@ ganv_box_bounds(GanvItem* item, } static void -ganv_box_update(GanvItem* item, - double* affine, - int flags) +ganv_box_update(GanvItem* item, int flags) { GanvBox* box = GANV_BOX(item); GanvBoxImpl* impl = box->impl; @@ -195,7 +192,7 @@ ganv_box_update(GanvItem* item, request_redraw(item, &impl->old_coords, TRUE); GanvItemClass* item_class = GANV_ITEM_CLASS(parent_class); - item_class->update(item, affine, flags); + item_class->update(item, flags); // Store old coordinates in world relative coordinates in case the // group we are in moves between now and the next update @@ -212,7 +209,6 @@ ganv_box_update(GanvItem* item, // Request redraw of new location request_redraw(item, &impl->coords, FALSE); - } static void diff --git a/src/canvas-base.c b/src/canvas-base.c index 36def3b..8a0cd4b 100644 --- a/src/canvas-base.c +++ b/src/canvas-base.c @@ -26,12 +26,6 @@ #include #include -#include "libart_lgpl/art_affine.h" -#include "libart_lgpl/art_rect.h" -#include "libart_lgpl/art_rect_uta.h" -#include "libart_lgpl/art_uta_rect.h" -#include "libart_lgpl/art_uta_ops.h" - #include "ganv/canvas-base.h" #include "./gettext.h" @@ -264,9 +258,6 @@ ganv_item_dispose(GObject* object) group_remove(GANV_GROUP(item->parent), item); } - g_free(item->xform); - item->xform = NULL; - G_OBJECT_CLASS(item_parent_class)->dispose(object); /* items should remove any reference to item->canvas after the first ::destroy */ @@ -305,10 +296,9 @@ ganv_item_unmap(GanvItem* item) /* Update handler for canvas items */ static void -ganv_item_update(GanvItem* item, double* affine, int flags) +ganv_item_update(GanvItem* item, int flags) { GTK_OBJECT_UNSET_FLAGS(item, GANV_ITEM_NEED_UPDATE); - GTK_OBJECT_UNSET_FLAGS(item, GANV_ITEM_NEED_AFFINE); GTK_OBJECT_UNSET_FLAGS(item, GANV_ITEM_NEED_CLIP); GTK_OBJECT_UNSET_FLAGS(item, GANV_ITEM_NEED_VIS); } @@ -327,33 +317,13 @@ ganv_item_update(GanvItem* item, double* affine, int flags) */ static void -ganv_item_invoke_update(GanvItem* item, double* p2cpx, int flags) +ganv_item_invoke_update(GanvItem* item, int flags) { - int child_flags; - gdouble i2cpx[6]; - - child_flags = flags; + int child_flags = flags; if (!(item->object.flags & GANV_ITEM_VISIBLE)) { child_flags &= ~GANV_CANVAS_BASE_UPDATE_IS_VISIBLE; } - /* Calculate actual item transformation matrix */ - - if (item->xform) { - if (item->object.flags & GANV_ITEM_AFFINE_FULL) { - /* Item has full affine */ - art_affine_multiply(i2cpx, item->xform, p2cpx); - } else { - /* Item has only translation */ - memcpy(i2cpx, p2cpx, 4 * sizeof(gdouble)); - i2cpx[4] = item->xform[0] * p2cpx[0] + item->xform[1] * p2cpx[2] + p2cpx[4]; - i2cpx[5] = item->xform[0] * p2cpx[1] + item->xform[1] * p2cpx[3] + p2cpx[5]; - } - } else { - /* Item has no matrix (i.e. identity) */ - memcpy(i2cpx, p2cpx, 6 * sizeof(gdouble)); - } - /* apply object flags to child flags */ child_flags &= ~GANV_CANVAS_BASE_UPDATE_REQUESTED; @@ -362,10 +332,6 @@ ganv_item_invoke_update(GanvItem* item, double* p2cpx, int flags) child_flags |= GANV_CANVAS_BASE_UPDATE_REQUESTED; } - if (item->object.flags & GANV_ITEM_NEED_AFFINE) { - child_flags |= GANV_CANVAS_BASE_UPDATE_AFFINE; - } - if (item->object.flags & GANV_ITEM_NEED_CLIP) { child_flags |= GANV_CANVAS_BASE_UPDATE_CLIP; } @@ -376,44 +342,28 @@ ganv_item_invoke_update(GanvItem* item, double* p2cpx, int flags) if (child_flags & GCI_UPDATE_MASK) { if (GANV_ITEM_GET_CLASS(item)->update) { - GANV_ITEM_GET_CLASS(item)->update(item, i2cpx, child_flags); + GANV_ITEM_GET_CLASS(item)->update(item, child_flags); } } } -/* - * This routine invokes the point method of the item. +/** + * Invoke the point method of the item. * The arguments x, y should be in the parent item local coordinates. - * - * This is potentially evil, as we are relying on matrix inversion (Lauris) */ - static double ganv_item_invoke_point(GanvItem* item, double x, double y, int cx, int cy, GanvItem** actual_item) { - /* Calculate x & y in item local coordinates */ - - if (item->xform) { - if (item->object.flags & GANV_ITEM_AFFINE_FULL) { - gdouble p2i[6], t; - /* Item has full affine */ - art_affine_invert(p2i, item->xform); - t = x * p2i[0] + y * p2i[2] + p2i[4]; - y = x * p2i[1] + y * p2i[3] + p2i[5]; - x = t; - } else { - /* Item has only translation */ - x -= item->xform[0]; - y -= item->xform[1]; - } - } + // Transform x and y to item local coordinates + x -= item->x; + y -= item->y; if (GANV_ITEM_GET_CLASS(item)->point) { return GANV_ITEM_GET_CLASS(item)->point(item, x, y, cx, cy, actual_item); } - return 1e18; + return G_MAXDOUBLE; } /** @@ -454,118 +404,23 @@ ganv_item_set_valist(GanvItem* item, const gchar* first_arg_name, va_list args) item->canvas->need_repick = TRUE; } -/** - * ganv_item_affine_relative: - * @item: A canvas item. - * @affine: An affine transformation matrix. - * - * Combines the specified affine transformation matrix with the item's current - * transformation. NULL affine is not allowed. - **/ -#define GCIAR_EPSILON 1e-6 -void -ganv_item_affine_relative(GanvItem* item, const double affine[6]) -{ - gdouble i2p[6]; - - g_return_if_fail(item != NULL); - g_return_if_fail(GANV_IS_ITEM(item)); - g_return_if_fail(affine != NULL); - - /* Calculate actual item transformation matrix */ - - if (item->xform) { - if (item->object.flags & GANV_ITEM_AFFINE_FULL) { - /* Item has full affine */ - art_affine_multiply(i2p, affine, item->xform); - } else { - /* Item has only translation */ - memcpy(i2p, affine, 6 * sizeof(gdouble)); - i2p[4] += item->xform[0]; - i2p[5] += item->xform[1]; - } - } else { - /* Item has no matrix (i.e. identity) */ - memcpy(i2p, affine, 6 * sizeof(gdouble)); - } - - ganv_item_affine_absolute(item, i2p); -} - -/** - * ganv_item_affine_absolute: - * @item: A canvas item. - * @affine: An affine transformation matrix. - * - * Makes the item's affine transformation matrix be equal to the specified - * matrix. NULL affine is treated as identity. - **/ -void -ganv_item_affine_absolute(GanvItem* item, const double i2p[6]) -{ - g_return_if_fail(item != NULL); - g_return_if_fail(GANV_IS_ITEM(item)); - - if (i2p - && (fabs(i2p[0] - 1.0) < GCI_EPSILON) - && (fabs(i2p[1] - 0.0) < GCI_EPSILON) - && (fabs(i2p[2] - 0.0) < GCI_EPSILON) - && (fabs(i2p[3] - 1.0) < GCI_EPSILON) - && (fabs(i2p[4] - 0.0) < GCI_EPSILON) - && (fabs(i2p[5] - 0.0) < GCI_EPSILON)) { - /* We are identity */ - i2p = NULL; - } - - if (i2p) { - if (item->xform && !(item->object.flags & GANV_ITEM_AFFINE_FULL)) { - /* We do not want to deal with translation-only affines */ - g_free(item->xform); - item->xform = NULL; - } - if (!item->xform) { - item->xform = g_new(gdouble, 6); - } - memcpy(item->xform, i2p, 6 * sizeof(gdouble)); - item->object.flags |= GANV_ITEM_AFFINE_FULL; - } else { - if (item->xform) { - g_free(item->xform); - item->xform = NULL; - } - } - - if (!(item->object.flags & GANV_ITEM_NEED_AFFINE)) { - /* Request update */ - item->object.flags |= GANV_ITEM_NEED_AFFINE; - ganv_item_request_update(item); - } - - item->canvas->need_repick = TRUE; -} - /** * ganv_item_move: * @item: A canvas item. * @dx: Horizontal offset. * @dy: Vertical offset. - * - * Moves a canvas item by creating an affine transformation matrix for - * translation by using the specified values. This happens in item - * local coordinate system, so if you have nontrivial transform, it - * most probably does not do, what you want. **/ void ganv_item_move(GanvItem* item, double dx, double dy) { - double translate[6]; - g_return_if_fail(item != NULL); g_return_if_fail(GANV_IS_ITEM(item)); - art_affine_translate(translate, dx, dy); + item->x += dx; + item->y += dy; - ganv_item_affine_relative(item, translate); + ganv_item_request_update(item); + item->canvas->need_repick = TRUE; } /* Convenience function to reorder items in a group's child list. This puts the @@ -884,23 +739,15 @@ ganv_item_ungrab(GanvItem* item, guint32 etime) * world coordinates. **/ void -ganv_item_i2w_affine(GanvItem* item, double affine[6]) +ganv_item_i2w_affine(GanvItem* item, cairo_matrix_t* matrix) { g_return_if_fail(GANV_IS_ITEM(item)); - g_return_if_fail(affine != NULL); - art_affine_identity(affine); + cairo_matrix_init_identity(matrix); while (item) { - if (item->xform != NULL) { - if (item->object.flags & GANV_ITEM_AFFINE_FULL) { - art_affine_multiply(affine, affine, item->xform); - } else { - affine[4] += item->xform[0]; - affine[5] += item->xform[1]; - } - } - + matrix->x0 += item->x; + matrix->y0 += item->y; item = item->parent; } } @@ -917,20 +764,15 @@ ganv_item_i2w_affine(GanvItem* item, double affine[6]) void ganv_item_w2i(GanvItem* item, double* x, double* y) { - double affine[6], inv[6]; - ArtPoint w, i; - g_return_if_fail(GANV_IS_ITEM(item)); g_return_if_fail(x != NULL); g_return_if_fail(y != NULL); - ganv_item_i2w_affine(item, affine); - art_affine_invert(inv, affine); - w.x = *x; - w.y = *y; - art_affine_point(&i, &w, inv); - *x = i.x; - *y = i.y; + cairo_matrix_t matrix; + ganv_item_i2w_affine(item, &matrix); + cairo_matrix_invert(&matrix); + + cairo_matrix_transform_point(&matrix, x, y); } /** @@ -945,19 +787,14 @@ ganv_item_w2i(GanvItem* item, double* x, double* y) void ganv_item_i2w(GanvItem* item, double* x, double* y) { - double affine[6]; - ArtPoint w, i; - g_return_if_fail(GANV_IS_ITEM(item)); g_return_if_fail(x != NULL); g_return_if_fail(y != NULL); - ganv_item_i2w_affine(item, affine); - i.x = *x; - i.y = *y; - art_affine_point(&w, &i, affine); - *x = w.x; - *y = w.y; + cairo_matrix_t matrix; + ganv_item_i2w_affine(item, &matrix); + + cairo_matrix_transform_point(&matrix, x, y); } /** @@ -969,13 +806,15 @@ ganv_item_i2w(GanvItem* item, double* x, double* y) * canvas pixel coordinates. **/ void -ganv_item_i2c_affine(GanvItem* item, double affine[6]) +ganv_item_i2c_affine(GanvItem* item, cairo_matrix_t* matrix) { - double i2w[6], w2c[6]; + cairo_matrix_t i2w; + ganv_item_i2w_affine(item, &i2w); + + cairo_matrix_t w2c; + ganv_canvas_base_w2c_affine(item->canvas, &w2c); - ganv_item_i2w_affine(item, i2w); - ganv_canvas_base_w2c_affine(item->canvas, w2c); - art_affine_multiply(affine, i2w, w2c); + cairo_matrix_multiply(matrix, &i2w, &w2c); } /* Returns whether the item is an inferior of or is equal to the parent. */ @@ -1087,94 +926,41 @@ ganv_item_grab_focus(GanvItem* item) void ganv_item_get_bounds(GanvItem* item, double* x1, double* y1, double* x2, double* y2) { - double tx1, ty1, tx2, ty2; - ArtPoint p1, p2, p3, p4; - ArtPoint q1, q2, q3, q4; - double min_x1, min_y1, min_x2, min_y2; - double max_x1, max_y1, max_x2, max_y2; + double ix1, iy1, ix2, iy2; g_return_if_fail(GANV_IS_ITEM(item)); - tx1 = ty1 = tx2 = ty2 = 0.0; + ix1 = iy1 = ix2 = iy2 = 0.0; /* Get the item's bounds in its coordinate system */ if (GANV_ITEM_GET_CLASS(item)->bounds) { - (*GANV_ITEM_GET_CLASS(item)->bounds)(item, &tx1, &ty1, &tx2, &ty2); + (*GANV_ITEM_GET_CLASS(item)->bounds)(item, &ix1, &iy1, &ix2, &iy2); } /* Make the bounds relative to the item's parent coordinate system */ - if (item->xform && (item->object.flags & GANV_ITEM_AFFINE_FULL)) { - p1.x = p2.x = tx1; - p1.y = p4.y = ty1; - p3.x = p4.x = tx2; - p2.y = p3.y = ty2; - - art_affine_point(&q1, &p1, item->xform); - art_affine_point(&q2, &p2, item->xform); - art_affine_point(&q3, &p3, item->xform); - art_affine_point(&q4, &p4, item->xform); - - if (q1.x < q2.x) { - min_x1 = q1.x; - max_x1 = q2.x; - } else { - min_x1 = q2.x; - max_x1 = q1.x; - } - - if (q1.y < q2.y) { - min_y1 = q1.y; - max_y1 = q2.y; - } else { - min_y1 = q2.y; - max_y1 = q1.y; - } - - if (q3.x < q4.x) { - min_x2 = q3.x; - max_x2 = q4.x; - } else { - min_x2 = q4.x; - max_x2 = q3.x; - } - - if (q3.y < q4.y) { - min_y2 = q3.y; - max_y2 = q4.y; - } else { - min_y2 = q4.y; - max_y2 = q3.y; - } - - tx1 = MIN(min_x1, min_x2); - ty1 = MIN(min_y1, min_y2); - tx2 = MAX(max_x1, max_x2); - ty2 = MAX(max_y1, max_y2); - } else if (item->xform) { - tx1 += item->xform[0]; - ty1 += item->xform[1]; - tx2 += item->xform[0]; - ty2 += item->xform[1]; - } + ix1 -= item->x; + iy1 -= item->y; + ix2 -= item->x; + iy2 -= item->y; /* Return the values */ if (x1) { - *x1 = tx1; + *x1 = ix1; } if (y1) { - *y1 = ty1; + *y1 = iy1; } if (x2) { - *x2 = tx2; + *x2 = ix2; } if (y2) { - *y2 = ty2; + *y2 = iy2; } } @@ -1226,7 +1012,7 @@ static void ganv_group_get_property(GObject* object, static void ganv_group_destroy(GtkObject* object); -static void ganv_group_update(GanvItem* item, double* affine, int flags); +static void ganv_group_update(GanvItem* item, int flags); static void ganv_group_realize(GanvItem* item); static void ganv_group_unrealize(GanvItem* item); static void ganv_group_map(GanvItem* item); @@ -1298,44 +1084,24 @@ ganv_group_init(GanvGroup* group) #endif } -/* Translate handler for canvas groups */ -static double* -ganv_canvas_base_ensure_translate(GanvItem* item) -{ - if (item->xform == NULL) { - GTK_OBJECT_UNSET_FLAGS(item, GANV_ITEM_AFFINE_FULL); - item->xform = g_new(double, 2); - item->xform[0] = 0.0; - item->xform[1] = 0.0; - return item->xform; - } else if (item->object.flags & GANV_ITEM_AFFINE_FULL) { - return item->xform + 4; - } else { - return item->xform; - } -} - /* Set_property handler for canvas groups */ static void ganv_group_set_property(GObject* gobject, guint param_id, const GValue* value, GParamSpec* pspec) { - GanvItem* item; - double* xlat; - g_return_if_fail(GANV_IS_GROUP(gobject)); - item = GANV_ITEM(gobject); + GanvItem* item = GANV_ITEM(gobject); switch (param_id) { case GROUP_PROP_X: - xlat = ganv_canvas_base_ensure_translate(item); - xlat[0] = g_value_get_double(value); + item->x = g_value_get_double(value); + ganv_item_request_update(item); break; case GROUP_PROP_Y: - xlat = ganv_canvas_base_ensure_translate(item); - xlat[1] = g_value_get_double(value); + item->y = g_value_get_double(value); + ganv_item_request_update(item); break; default: @@ -1357,23 +1123,11 @@ ganv_group_get_property(GObject* gobject, guint param_id, switch (param_id) { case GROUP_PROP_X: - if (item->xform == NULL) { - g_value_set_double(value, 0); - } else if (GTK_OBJECT(gobject)->flags & GANV_ITEM_AFFINE_FULL) { - g_value_set_double(value, item->xform[4]); - } else { - g_value_set_double(value, item->xform[0]); - } + g_value_set_double(value, item->x); break; case GROUP_PROP_Y: - if (item->xform == NULL) { - g_value_set_double(value, 0); - } else if (GTK_OBJECT(gobject)->flags & GANV_ITEM_AFFINE_FULL) { - g_value_set_double(value, item->xform[5]); - } else { - g_value_set_double(value, item->xform[1]); - } + g_value_set_double(value, item->y); break; default: @@ -1403,37 +1157,35 @@ ganv_group_destroy(GtkObject* object) /* Update handler for canvas groups */ static void -ganv_group_update(GanvItem* item, double* affine, int flags) +ganv_group_update(GanvItem* item, int flags) { GanvGroup* group; GList* list; GanvItem* i; - ArtDRect bbox, child_bbox; group = GANV_GROUP(item); - (*group_parent_class->update)(item, affine, flags); + (*group_parent_class->update)(item, flags); - bbox.x0 = 0; - bbox.y0 = 0; - bbox.x1 = 0; - bbox.y1 = 0; + double min_x = 0.0; + double min_y = 0.0; + double max_x = 0.0; + double max_y = 0.0; for (list = group->item_list; list; list = list->next) { i = list->data; - ganv_item_invoke_update(i, affine, flags); + ganv_item_invoke_update(i, flags); - child_bbox.x0 = i->x1; - child_bbox.y0 = i->y1; - child_bbox.x1 = i->x2; - child_bbox.y1 = i->y2; - art_drect_union(&bbox, &bbox, &child_bbox); + min_x = fmin(min_x, fmin(i->x1, i->x2)); + min_y = fmin(min_y, fmin(i->y1, i->y2)); + max_x = fmax(max_x, fmax(i->x1, i->x2)); + max_y = fmax(max_y, fmax(i->y2, i->y2)); } - item->x1 = bbox.x0; - item->y1 = bbox.y0; - item->x2 = bbox.x1; - item->y2 = bbox.y1; + item->x1 = min_x; + item->y1 = min_y; + item->x2 = max_x; + item->y2 = max_y; } /* Realize handler for canvas groups */ @@ -2191,15 +1943,7 @@ scroll_to(GanvCanvasBase* canvas, int cx, int cy) } if ((canvas->zoom_xofs != old_zoom_xofs) || (canvas->zoom_yofs != old_zoom_yofs)) { - /* This can only occur, if either canvas size or widget size changes */ - /* So I think we can request full redraw here */ - /* The reason is, that coverage UTA will be invalidated by offset change */ - /* fixme: Strictly this is not correct - we have to remove our own idle (Lauris) */ - /* More stuff - we have to mark root as needing fresh affine (Lauris) */ - if (!(canvas->root->object.flags & GANV_ITEM_NEED_AFFINE)) { - canvas->root->object.flags |= GANV_ITEM_NEED_AFFINE; - ganv_canvas_base_request_update(canvas); - } + ganv_canvas_base_request_update(canvas); gtk_widget_queue_draw(GTK_WIDGET(canvas)); } @@ -2904,17 +2648,7 @@ do_update(GanvCanvasBase* canvas) update_again: if (canvas->need_update) { - gdouble w2cpx[6]; - - /* We start updating root with w2cpx affine */ - w2cpx[0] = canvas->pixels_per_unit; - w2cpx[1] = 0.0; - w2cpx[2] = 0.0; - w2cpx[3] = canvas->pixels_per_unit; - w2cpx[4] = -canvas->scroll_x1 * canvas->pixels_per_unit; - w2cpx[5] = -canvas->scroll_y1 * canvas->pixels_per_unit; - - ganv_item_invoke_update(canvas->root, w2cpx, 0); + ganv_item_invoke_update(canvas->root, 0); canvas->need_update = FALSE; } @@ -3174,11 +2908,7 @@ ganv_canvas_base_set_pixels_per_unit(GanvCanvasBase* canvas, double n) scroll_to(canvas, x1, y1); - if (!(canvas->root->object.flags & GANV_ITEM_NEED_AFFINE)) { - canvas->root->object.flags |= GANV_ITEM_NEED_AFFINE; - ganv_canvas_base_request_update(canvas); - } - + ganv_canvas_base_request_update(canvas); canvas->need_repick = TRUE; } @@ -3368,21 +3098,18 @@ ganv_canvas_base_request_redraw(GanvCanvasBase* canvas, int x1, int y1, int x2, * pixel coordinates. **/ void -ganv_canvas_base_w2c_affine(GanvCanvasBase* canvas, double affine[6]) +ganv_canvas_base_w2c_affine(GanvCanvasBase* canvas, cairo_matrix_t* matrix) { - double zooom; - g_return_if_fail(GANV_IS_CANVAS_BASE(canvas)); - g_return_if_fail(affine != NULL); + g_return_if_fail(matrix != NULL); - zooom = canvas->pixels_per_unit; + cairo_matrix_init_translate(matrix, + -canvas->scroll_x1, + -canvas->scroll_y1); - affine[0] = zooom; - affine[1] = 0; - affine[2] = 0; - affine[3] = zooom; - affine[4] = -canvas->scroll_x1 * zooom; - affine[5] = -canvas->scroll_y1 * zooom; + cairo_matrix_scale(matrix, + canvas->pixels_per_unit, + canvas->pixels_per_unit); } /** @@ -3398,20 +3125,18 @@ ganv_canvas_base_w2c_affine(GanvCanvasBase* canvas, double affine[6]) void ganv_canvas_base_w2c(GanvCanvasBase* canvas, double wx, double wy, int* cx, int* cy) { - double affine[6]; - ArtPoint w, c; - g_return_if_fail(GANV_IS_CANVAS_BASE(canvas)); - ganv_canvas_base_w2c_affine(canvas, affine); - w.x = wx; - w.y = wy; - art_affine_point(&c, &w, affine); + cairo_matrix_t matrix; + ganv_canvas_base_w2c_affine(canvas, &matrix); + + cairo_matrix_transform_point(&matrix, &wx, &wy); + if (cx) { - *cx = floor(c.x + 0.5); + *cx = floor(wx + 0.5); } if (cy) { - *cy = floor(c.y + 0.5); + *cy = floor(wy + 0.5); } } @@ -3430,20 +3155,18 @@ ganv_canvas_base_w2c(GanvCanvasBase* canvas, double wx, double wy, int* cx, int* void ganv_canvas_base_w2c_d(GanvCanvasBase* canvas, double wx, double wy, double* cx, double* cy) { - double affine[6]; - ArtPoint w, c; - g_return_if_fail(GANV_IS_CANVAS_BASE(canvas)); - ganv_canvas_base_w2c_affine(canvas, affine); - w.x = wx; - w.y = wy; - art_affine_point(&c, &w, affine); + cairo_matrix_t matrix; + ganv_canvas_base_w2c_affine(canvas, &matrix); + + cairo_matrix_transform_point(&matrix, &wx, &wy); + if (cx) { - *cx = c.x; + *cx = wx; } if (cy) { - *cy = c.y; + *cy = wy; } } @@ -3460,21 +3183,21 @@ ganv_canvas_base_w2c_d(GanvCanvasBase* canvas, double wx, double wy, double* cx, void ganv_canvas_base_c2w(GanvCanvasBase* canvas, int cx, int cy, double* wx, double* wy) { - double affine[6], inv[6]; - ArtPoint w, c; - g_return_if_fail(GANV_IS_CANVAS_BASE(canvas)); - ganv_canvas_base_w2c_affine(canvas, affine); - art_affine_invert(inv, affine); - c.x = cx; - c.y = cy; - art_affine_point(&w, &c, inv); + cairo_matrix_t matrix; + ganv_canvas_base_w2c_affine(canvas, &matrix); + cairo_matrix_invert(&matrix); + + double x = cx; + double y = cy; + cairo_matrix_transform_point(&matrix, &x, &y); + if (wx) { - *wx = w.x; + *wx = x; } if (wy) { - *wy = w.y; + *wy = y; } } diff --git a/src/circle.c b/src/circle.c index 30237fa..cd4f09d 100644 --- a/src/circle.c +++ b/src/circle.c @@ -213,16 +213,14 @@ ganv_circle_bounds(GanvItem* item, } static void -ganv_circle_update(GanvItem* item, - double* affine, - int flags) +ganv_circle_update(GanvItem* item, int flags) { GanvCircle* circle = GANV_CIRCLE(item); GanvCircleImpl* impl = circle->impl; GanvItemClass* item_class = GANV_ITEM_CLASS(parent_class); if (item_class->update) { - (*item_class->update)(item, affine, flags); + (*item_class->update)(item, flags); } // Request redraw of old location diff --git a/src/edge.c b/src/edge.c index 37aaaf2..22a0ba9 100644 --- a/src/edge.c +++ b/src/edge.c @@ -237,15 +237,13 @@ ganv_edge_bounds(GanvItem* item, } static void -ganv_edge_update(GanvItem* item, - double* affine, - int flags) +ganv_edge_update(GanvItem* item, int flags) { GanvEdge* edge = GANV_EDGE(item); GanvEdgeImpl* impl = edge->impl; if (parent_class->update) { - (*parent_class->update)(item, affine, flags); + (*parent_class->update)(item, flags); } // Request redraw of old location diff --git a/src/module.c b/src/module.c index c9e063f..a6fe461 100644 --- a/src/module.c +++ b/src/module.c @@ -508,18 +508,21 @@ ganv_module_resize(GanvNode* self) } static void -ganv_module_update(GanvItem* item, - double* affine, - int flags) +ganv_module_update(GanvItem* item, int flags) { GanvNode* node = GANV_NODE(item); GanvModule* module = GANV_MODULE(item); + + FOREACH_PORT(module->impl->ports, p) { + ganv_item_request_update(GANV_ITEM(*p)); + } + if (module->impl->must_resize) { layout(node); } GanvItemClass* item_class = GANV_ITEM_CLASS(parent_class); - item_class->update(item, affine, flags); + item_class->update(item, flags); } static void diff --git a/src/node.c b/src/node.c index 51a0c52..96bc039 100644 --- a/src/node.c +++ b/src/node.c @@ -102,6 +102,23 @@ ganv_node_destroy(GtkObject* object) } } +static void +ganv_node_draw(GanvItem* item, + cairo_t* cr, + int cx, int cy, + int width, int height) +{ + if (GANV_ITEM_CLASS(parent_class)->draw) { + (*GANV_ITEM_CLASS(parent_class)->draw)(item, cr, cx, cy, width, height); + } + + GanvNode* node = GANV_NODE(item); + if (node->impl->label) { + GanvItem* label_item = GANV_ITEM(node->impl->label); + GANV_ITEM_GET_CLASS(label_item)->draw(label_item, cr, cx, cy, width, height); + } +} + static void ganv_node_set_property(GObject* object, guint prop_id, @@ -572,6 +589,7 @@ ganv_node_class_init(GanvNodeClass* class) item_class->realize = ganv_node_realize; item_class->event = ganv_node_default_event; + item_class->draw = ganv_node_draw; class->disconnect = ganv_node_default_disconnect; class->move = ganv_node_default_move; diff --git a/src/text.c b/src/text.c index a83daec..a20dfa0 100644 --- a/src/text.c +++ b/src/text.c @@ -231,13 +231,10 @@ ganv_text_bounds(GanvItem* item, } static void -ganv_text_update(GanvItem* item, - double* affine, - int flags) +ganv_text_update(GanvItem* item, int flags) { double x1, y1, x2, y2; ganv_text_bounds(item, &x1, &y1, &x2, &y2); - ganv_canvas_base_request_redraw(item->canvas, x1, y1, x2, y2); // I have no idea why this is necessary item->x1 = x1; @@ -245,7 +242,9 @@ ganv_text_update(GanvItem* item, item->x2 = x2; item->y2 = y2; - parent_class->update(item, affine, flags); + parent_class->update(item, flags); + + ganv_canvas_base_request_redraw(item->canvas, x1, y1, x2, y2); } static double diff --git a/src/widget.c b/src/widget.c index 2458505..6707b3b 100644 --- a/src/widget.c +++ b/src/widget.c @@ -230,7 +230,7 @@ ganv_widget_set_property(GObject* object, } if (update) { - (*GANV_ITEM_GET_CLASS(item)->update)(item, NULL, 0); + (*GANV_ITEM_GET_CLASS(item)->update)(item, 0); } if (calc_bounds) { @@ -287,14 +287,14 @@ ganv_widget_get_property(GObject* object, } static void -ganv_widget_update(GanvItem* item, double* affine, int flags) +ganv_widget_update(GanvItem* item, int flags) { GanvWidget* witem; witem = GANV_WIDGET(item); if (parent_class->update) { - (*parent_class->update)(item, affine, flags); + (*parent_class->update)(item, flags); } if (witem->widget) { diff --git a/wscript b/wscript index 90bb0b5..fb5bb69 100644 --- a/wscript +++ b/wscript @@ -50,8 +50,6 @@ def configure(conf): atleast_version='2.0.0', mandatory=True) autowaf.check_pkg(conf, 'gtkmm-2.4', uselib_store='GTKMM', atleast_version='2.10.0', mandatory=True) - autowaf.check_pkg(conf, 'libart-2.0', uselib_store='ART', - atleast_version='2.0.0', mandatory=True) if Options.options.gir: autowaf.check_pkg(conf, 'gobject-introspection-1.0', -- cgit v1.2.1