static void so_image_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible) { GocItem *view = GOC_ITEM (GOC_GROUP (sov)->children->data); double scale = goc_canvas_get_pixels_per_unit (view->canvas); if (visible) { double x, y, width, height; double old_x1, old_y1, old_x2, old_y2, old_width, old_height; GdkPixbuf *placeholder = g_object_get_data (G_OBJECT (view), "tile"); x = MIN (coords [0], coords [2]) / scale; y = MIN (coords [1], coords [3]) / scale; width = fabs (coords [2] - coords [0]) / scale; height = fabs (coords [3] - coords [1]) / scale; goc_item_get_bounds (view, &old_x1, &old_y1, &old_x2, &old_y2); goc_item_set (view, "x", x, "y", y, "width", width, "height", height, NULL); /* regenerate the image if necessary */ old_width = fabs (old_x1 - old_x2); old_height = fabs (old_y1 - old_y2); if (placeholder != NULL && (fabs (width - old_width) > 0.5 || fabs (height - old_height) > 0.5)) { GdkPixbuf *newimage = go_pixbuf_tile (placeholder, (guint)width, (guint)height); goc_item_set (view, "pixbuf", newimage, NULL); g_object_unref (newimage); } goc_item_show (view); } else goc_item_hide (view); }
void goc_canvas_get_bounds (GocCanvas *canvas, double *x0, double *y0, double *x1, double *y1) { goc_item_get_bounds (GOC_ITEM (canvas->root), x0, y0, x1, y1); }
static void so_path_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible) { GnmSOPathView *spv = (GnmSOPathView *) sov; if (visible) { SheetObject *so = sheet_object_view_get_so (sov); GnmSOPath const *sop = GNM_SO_PATH (so); GOPath *path; double scale, x_scale, y_scale, x, y; if ((sop->path == NULL && sop->paths == NULL) || sop->width <=0. || sop->height <=0.) return; scale = goc_canvas_get_pixels_per_unit (GOC_ITEM (sov)->canvas); x_scale = fabs (coords[2] - coords[0]) / sop->width / scale; y_scale = fabs (coords[3] - coords[1]) / sop->height / scale; x = MIN (coords[0], coords[2]) / scale - sop->x_offset * x_scale; y = MIN (coords[1], coords[3]) / scale - sop->y_offset * y_scale; if (sop->path != NULL) { path = go_path_scale (sop->path, x_scale, y_scale); goc_item_set (spv->path, "x", x, "y", y, "path", path, NULL); go_path_free (path); } else { unsigned i; for (i = 0; i < sop->paths->len; i++) { path = go_path_scale ((GOPath *) g_ptr_array_index (sop->paths, i), x_scale, y_scale); goc_item_set (GOC_ITEM (g_ptr_array_index (spv->paths, i)), "x", x, "y", y, "path", path, NULL); go_path_free (path); } } if (spv->text != NULL && GOC_ITEM (spv->text)) { double x0, y0, x1, y1; if (spv->path) goc_item_get_bounds (spv->path, &x0, &y0, &x1, &y1); else { unsigned i; double mx, my, Mx, My; x0 = y0 = G_MAXDOUBLE; x1 = y1 = -G_MAXDOUBLE; for (i = 0; i < spv->paths->len; i++) { goc_item_get_bounds (GOC_ITEM (g_ptr_array_index (spv->paths, i)), &mx, &my, &Mx, &My); if (mx < x0) x0 = mx; if (my < y0) y0 = my; if (Mx > x1) x1 = Mx; if (My > y1) y1 = My; } } x1 -= x0 + sop->margin_pts.left + sop->margin_pts.right; y1 -= y0 + sop->margin_pts.top + sop->margin_pts.bottom; x0 += x1 / 2. + sop->margin_pts.left; y0 += y1 / 2. + sop->margin_pts.top; x1 = MAX (x1, DBL_MIN); y1 = MAX (y1, DBL_MIN); goc_item_set (GOC_ITEM (spv->text), "x", x0, "y", y0, "clip-height", y1, "clip-width", x1, "wrap-width", x1, NULL); } } else goc_item_hide (GOC_ITEM (sov)); }
static gboolean goc_canvas_draw (GtkWidget *widget, cairo_t *cr) { double x0, y0, x1, y1; double ax0, ay0, ax1, ay1; double clip_x1, clip_y1, clip_x2, clip_y2; GocCanvas *canvas = GOC_CANVAS (widget); GdkEventExpose *event = (GdkEventExpose *) gtk_get_current_event (); GocCanvasPrivate *priv = (GocCanvasPrivate *) canvas->priv; cairo_rectangle_list_t *l = cairo_copy_clip_rectangle_list (cr); int i, x, y; if (GOC_IS_ITEM (priv->invalidated_item) && priv->invalid_region) { /* evaluate the cairo clipped region and compare with the saved one */ cairo_region_t *region; cairo_rectangle_int_t rect[l->num_rectangles]; for (i= 0; i < l->num_rectangles; i++) { rect[i].x = l->rectangles[i].x; rect[i].y = l->rectangles[i].y; rect[i].width = l->rectangles[i].width; rect[i].height = l->rectangles[i].height; } region = cairo_region_create_rectangles (rect, l->num_rectangles); if (cairo_region_equal (priv->invalid_region, region)) { cairo_rectangle_list_destroy (l); cairo_region_destroy (region); /* looks like each time we call gtk_widget_queue_draw*, the draw event is fired twice */ if (priv->done) { priv->invalidated_item = NULL; cairo_region_destroy (priv->invalid_region); priv->invalid_region = NULL; } else { goc_item_draw (priv->invalidated_item, cr); priv->done = TRUE; } return TRUE; } cairo_region_destroy (region); } x = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas))); y = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas))); cairo_translate (cr, -x, -y); goc_item_get_bounds (GOC_ITEM (canvas->root),&x0, &y0, &x1, &y1); for (i= 0; i < l->num_rectangles; i++) { cairo_save (cr); cairo_rectangle (cr, l->rectangles[i].x, l->rectangles[i].y, l->rectangles[i].width, l->rectangles[i].height); cairo_clip (cr); clip_x1 = l->rectangles[i].x; clip_y1 = l->rectangles[i].y; clip_x2 = clip_x1 + l->rectangles[i].width; clip_y2 = clip_y1 + l->rectangles[i].height; if (canvas->direction == GOC_DIRECTION_RTL) { ax1 = (double) (canvas->width - clip_x1) / canvas->pixels_per_unit + canvas->scroll_x1; ax0 = (double) (canvas->width - clip_x2) / canvas->pixels_per_unit + canvas->scroll_x1; } else { ax0 = (double) clip_x1 / canvas->pixels_per_unit + canvas->scroll_x1; ax1 = ((double) clip_x1 + event->area.width) / canvas->pixels_per_unit + canvas->scroll_x1; } ay0 = (double) clip_y1 / canvas->pixels_per_unit + canvas->scroll_y1; ay1 = (double) clip_y2 / canvas->pixels_per_unit + canvas->scroll_y1; if (x0 <= ax1 && x1 >= ax0 && y0 <= ay1 && y1 >= ay0) { canvas->cur_event = (GdkEvent *) event; goc_item_draw_region (GOC_ITEM (canvas->root), cr, ax0, ay0, ax1, ay1); } cairo_restore (cr); } cairo_rectangle_list_destroy (l); return TRUE; }
static void cb_gnm_so_path_changed (GnmSOPath const *sop, G_GNUC_UNUSED GParamSpec *pspec, GnmSOPathView *group) { GList *ptr = GOC_GROUP (group)->children; for (; ptr && ptr->data; ptr = ptr->next) if (GOC_IS_PATH (ptr->data)) cb_gnm_so_path_style_changed (GOC_ITEM (ptr->data), sop); if (sop->text != NULL && *sop->text != 0) { /* set a font, a very bad solution, but will do until we move to GOString */ PangoFontDescription *desc = pango_font_description_from_string ("Sans 10"); GOStyle *style; if (group->text == NULL) { double x0, y0, x1, y1; if (group->path) goc_item_get_bounds (group->path, &x0, &y0, &x1, &y1); else { unsigned i; double mx, my, Mx, My; x0 = y0 = G_MAXDOUBLE; x1 = y1 = -G_MAXDOUBLE; for (i = 0; i < group->paths->len; i++) { goc_item_get_bounds (GOC_ITEM (g_ptr_array_index (group->paths, i)), &mx, &my, &Mx, &My); if (mx < x0) x0 = mx; if (my < y0) y0 = my; if (Mx > x1) x1 = Mx; if (My > y1) y1 = My; } } x1 -= x0 + sop->margin_pts.left + sop->margin_pts.right; y1 -= y0 + sop->margin_pts.top + sop->margin_pts.bottom; x0 += x1 / 2. + sop->margin_pts.left; y0 += y1 / 2. + sop->margin_pts.top; x1 = MAX (x1, DBL_MIN); y1 = MAX (y1, DBL_MIN); group->text = goc_item_new (GOC_GROUP (group), GOC_TYPE_TEXT, "anchor", GO_ANCHOR_CENTER, "clip", TRUE, "x", x0, "y", y0, "clip-height", y1, "clip-width", x1, "wrap-width", x1, "attributes", sop->markup, NULL); } style = go_styled_object_get_style (GO_STYLED_OBJECT (group->text)); go_style_set_font_desc (style, desc); goc_item_set (group->text, "text", sop->text, "attributes", sop->markup, NULL); } else if (group->text != NULL) { g_object_unref (group->text); group->text = NULL; } }