diff options
Diffstat (limited to 'libgnomecanvas')
-rw-r--r-- | libgnomecanvas/Makefile.am | 2 | ||||
-rw-r--r-- | libgnomecanvas/gnome-canvas-line.c | 1191 | ||||
-rw-r--r-- | libgnomecanvas/gnome-canvas-line.h | 143 | ||||
-rw-r--r-- | libgnomecanvas/gnome-canvas-util.c | 21 | ||||
-rw-r--r-- | libgnomecanvas/gnome-canvas-util.h | 3 | ||||
-rw-r--r-- | libgnomecanvas/libgnomecanvas.h | 1 |
6 files changed, 24 insertions, 1337 deletions
diff --git a/libgnomecanvas/Makefile.am b/libgnomecanvas/Makefile.am index 5069052309..14b44a0d07 100644 --- a/libgnomecanvas/Makefile.am +++ b/libgnomecanvas/Makefile.am @@ -25,7 +25,6 @@ libgnomecanvasinclude_HEADERS = \ gailcanvaswidgetfactory.h \ gnome-canvas-clipgroup.h \ gnome-canvas-i18n.h \ - gnome-canvas-line.h \ gnome-canvas-path-def.h \ gnome-canvas-pixbuf.h \ gnome-canvas-rect-ellipse.h \ @@ -48,7 +47,6 @@ libgnomecanvas_la_SOURCES = \ gailcanvaswidget.c \ gailcanvaswidgetfactory.c \ gnome-canvas-clipgroup.c \ - gnome-canvas-line.c \ gnome-canvas-path-def.c \ gnome-canvas-pixbuf.c \ gnome-canvas-rect-ellipse.c \ diff --git a/libgnomecanvas/gnome-canvas-line.c b/libgnomecanvas/gnome-canvas-line.c deleted file mode 100644 index 20cde8a6d9..0000000000 --- a/libgnomecanvas/gnome-canvas-line.c +++ /dev/null @@ -1,1191 +0,0 @@ -/* - * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation - * All rights reserved. - * - * This file is part of the Gnome Library. - * - * The Gnome Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The Gnome Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ - */ - -/* Line/curve item type for GnomeCanvas widget - * - * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is - * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. - * - * - * Author: Federico Mena <federico@nuclecu.unam.mx> - */ - -#include <config.h> -#include <math.h> -#include <string.h> -#include <libart_lgpl/art_vpath.h> -#include <libart_lgpl/art_svp.h> -#include <libart_lgpl/art_svp_vpath.h> -#include <libart_lgpl/art_svp_vpath_stroke.h> -#include "libgnomecanvas.h" - -#define noVERBOSE - -#define DEFAULT_SPLINE_STEPS 12 /* this is what Tk uses */ -#define NUM_ARROW_POINTS 6 /* number of points in an arrowhead */ -#define NUM_STATIC_POINTS 256 /* number of static points to use to avoid allocating arrays */ - -#define GROW_BOUNDS(bx1, by1, bx2, by2, x, y) { \ - if (x < bx1) \ - bx1 = x; \ - \ - if (x > bx2) \ - bx2 = x; \ - \ - if (y < by1) \ - by1 = y; \ - \ - if (y > by2) \ - by2 = y; \ -} - -enum { - PROP_0, - PROP_POINTS, - PROP_FILL_COLOR, - PROP_FILL_COLOR_GDK, - PROP_FILL_COLOR_RGBA, - PROP_WIDTH_PIXELS, - PROP_WIDTH_UNITS, - PROP_CAP_STYLE, - PROP_JOIN_STYLE, - PROP_FIRST_ARROWHEAD, - PROP_LAST_ARROWHEAD, - PROP_SMOOTH, - PROP_SPLINE_STEPS, - PROP_ARROW_SHAPE_A, - PROP_ARROW_SHAPE_B, - PROP_ARROW_SHAPE_C -}; - -static void gnome_canvas_line_class_init (GnomeCanvasLineClass *class); -static void gnome_canvas_line_init (GnomeCanvasLine *line); -static void gnome_canvas_line_destroy (GnomeCanvasItem *object); -static void gnome_canvas_line_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void gnome_canvas_line_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); - -static void gnome_canvas_line_update (GnomeCanvasItem *item, gdouble *affine, ArtSVP *clip_path, gint flags); -static void gnome_canvas_line_draw (GnomeCanvasItem *item, GdkDrawable *drawable, - gint x, gint y, gint width, gint height); -static GnomeCanvasItem *gnome_canvas_line_point (GnomeCanvasItem *item, gdouble x, gdouble y, - gint cx, gint cy); -static void gnome_canvas_line_bounds (GnomeCanvasItem *item, gdouble *x1, gdouble *y1, gdouble *x2, gdouble *y2); - -static GnomeCanvasItemClass *parent_class; - -GType -gnome_canvas_line_get_type (void) -{ - static GType line_type; - - if (!line_type) { - const GTypeInfo object_info = { - sizeof (GnomeCanvasLineClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gnome_canvas_line_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GnomeCanvasLine), - 0, /* n_preallocs */ - (GInstanceInitFunc) gnome_canvas_line_init, - NULL /* value_table */ - }; - - line_type = g_type_register_static (GNOME_TYPE_CANVAS_ITEM, "GnomeCanvasLine", - &object_info, 0); - } - - return line_type; -} - -static void -gnome_canvas_line_class_init (GnomeCanvasLineClass *class) -{ - GObjectClass *gobject_class; - GnomeCanvasItemClass *item_class; - - gobject_class = (GObjectClass *) class; - item_class = (GnomeCanvasItemClass *) class; - - parent_class = g_type_class_peek_parent (class); - - gobject_class->set_property = gnome_canvas_line_set_property; - gobject_class->get_property = gnome_canvas_line_get_property; - - g_object_class_install_property - (gobject_class, - PROP_POINTS, - g_param_spec_boxed ("points", NULL, NULL, - GNOME_TYPE_CANVAS_POINTS, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_FILL_COLOR, - g_param_spec_string ("fill_color", NULL, NULL, - NULL, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_FILL_COLOR_GDK, - g_param_spec_boxed ("fill_color_gdk", NULL, NULL, - GDK_TYPE_COLOR, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_FILL_COLOR_RGBA, - g_param_spec_uint ("fill_color_rgba", NULL, NULL, - 0, G_MAXUINT, 0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_WIDTH_PIXELS, - g_param_spec_uint ("width_pixels", NULL, NULL, - 0, G_MAXUINT, 0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_WIDTH_UNITS, - g_param_spec_double ("width_units", NULL, NULL, - 0.0, G_MAXDOUBLE, 0.0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_CAP_STYLE, - g_param_spec_enum ("cap_style", NULL, NULL, - G_TYPE_UINT, /* XXX */ - CAIRO_LINE_CAP_BUTT, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_JOIN_STYLE, - g_param_spec_enum ("join_style", NULL, NULL, - G_TYPE_UINT, /* XXX */ - CAIRO_LINE_JOIN_MITER, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_FIRST_ARROWHEAD, - g_param_spec_boolean ("first_arrowhead", NULL, NULL, - FALSE, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_LAST_ARROWHEAD, - g_param_spec_boolean ("last_arrowhead", NULL, NULL, - FALSE, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_SMOOTH, - g_param_spec_boolean ("smooth", NULL, NULL, - FALSE, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_SPLINE_STEPS, - g_param_spec_uint ("spline_steps", NULL, NULL, - 0, G_MAXUINT, DEFAULT_SPLINE_STEPS, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_ARROW_SHAPE_A, - g_param_spec_double ("arrow_shape_a", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_ARROW_SHAPE_B, - g_param_spec_double ("arrow_shape_b", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_ARROW_SHAPE_C, - g_param_spec_double ("arrow_shape_c", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - - item_class->destroy = gnome_canvas_line_destroy; - item_class->update = gnome_canvas_line_update; - item_class->draw = gnome_canvas_line_draw; - item_class->point = gnome_canvas_line_point; - item_class->bounds = gnome_canvas_line_bounds; -} - -static void -gnome_canvas_line_init (GnomeCanvasLine *line) -{ - line->width = 0.0; - line->cap = CAIRO_LINE_CAP_BUTT; - line->join = CAIRO_LINE_JOIN_MITER; - line->shape_a = 0.0; - line->shape_b = 0.0; - line->shape_c = 0.0; - line->spline_steps = DEFAULT_SPLINE_STEPS; -} - -static void -gnome_canvas_line_destroy (GnomeCanvasItem *object) -{ - GnomeCanvasLine *line; - - g_return_if_fail (object != NULL); - g_return_if_fail (GNOME_IS_CANVAS_LINE (object)); - - line = GNOME_CANVAS_LINE (object); - - /* remember, destroy can be run multiple times! */ - - if (line->coords) - g_free (line->coords); - line->coords = NULL; - - if (line->first_coords) - g_free (line->first_coords); - line->first_coords = NULL; - - if (line->last_coords) - g_free (line->last_coords); - line->last_coords = NULL; - - if (line->fill_svp) - art_svp_free (line->fill_svp); - line->fill_svp = NULL; - - if (line->first_svp) - art_svp_free (line->first_svp); - line->first_svp = NULL; - - if (line->last_svp) - art_svp_free (line->last_svp); - line->last_svp = NULL; - - if (GNOME_CANVAS_ITEM_CLASS (parent_class)->destroy) - GNOME_CANVAS_ITEM_CLASS (parent_class)->destroy (object); -} - -/* Computes the bounding box of the line, including its arrow points. Assumes that the number of - * points in the line is not zero. - */ -static void -get_bounds (GnomeCanvasLine *line, gdouble *bx1, gdouble *by1, gdouble *bx2, gdouble *by2) -{ - gdouble *coords; - gdouble x1, y1, x2, y2; - gdouble width; - gint i; - - if (!line->coords) { - *bx1 = *by1 = *bx2 = *by2 = 0.0; - return; - } - - /* Find bounding box of line's points */ - - x1 = x2 = line->coords[0]; - y1 = y2 = line->coords[1]; - - for (i = 1, coords = line->coords + 2; i < line->num_points; i++, coords += 2) - GROW_BOUNDS (x1, y1, x2, y2, coords[0], coords[1]); - - /* Add possible over-estimate for wide lines */ - - if (line->width_pixels) - width = line->width / line->item.canvas->pixels_per_unit; - else - width = line->width; - - x1 -= width; - y1 -= width; - x2 += width; - y2 += width; - - /* For mitered lines, make a second pass through all the points. Compute the location of - * the two miter vertex points and add them to the bounding box. - */ - - if (line->join == CAIRO_LINE_JOIN_MITER) - for (i = line->num_points, coords = line->coords; i >= 3; i--, coords += 2) { - gdouble mx1, my1, mx2, my2; - - if (gnome_canvas_get_miter_points (coords[0], coords[1], - coords[2], coords[3], - coords[4], coords[5], - width, - &mx1, &my1, &mx2, &my2)) { - GROW_BOUNDS (x1, y1, x2, y2, mx1, my1); - GROW_BOUNDS (x1, y1, x2, y2, mx2, my2); - } - } - - /* Add the arrow points, if any */ - - if (line->first_arrow && line->first_coords) - for (i = 0, coords = line->first_coords; i < NUM_ARROW_POINTS; i++, coords += 2) - GROW_BOUNDS (x1, y1, x2, y2, coords[0], coords[1]); - - if (line->last_arrow && line->last_coords) - for (i = 0, coords = line->last_coords; i < NUM_ARROW_POINTS; i++, coords += 2) - GROW_BOUNDS (x1, y1, x2, y2, coords[0], coords[1]); - - /* Done */ - - *bx1 = x1; - *by1 = y1; - *bx2 = x2; - *by2 = y2; -} - -/* Computes the bounding box of the line, in canvas coordinates. Assumes that the number of points in the polygon is - * not zero. Affine is the i2c transformation. - */ -static void -get_bounds_canvas (GnomeCanvasLine *line, gdouble *bx1, gdouble *by1, gdouble *bx2, gdouble *by2, gdouble affine[6]) -{ - /* It would be possible to tighten the bounds somewhat by transforming the individual points before - aggregating them into the bbox. But it hardly seems worth it. */ - ArtDRect bbox_world; - ArtDRect bbox_canvas; - - get_bounds (line, &bbox_world.x0, &bbox_world.y0, &bbox_world.x1, &bbox_world.y1); - - art_drect_affine_transform (&bbox_canvas, &bbox_world, affine); - /* include 1 pixel of fudge */ - *bx1 = bbox_canvas.x0 - 1; - *by1 = bbox_canvas.y0 - 1; - *bx2 = bbox_canvas.x1 + 1; - *by2 = bbox_canvas.y1 + 1; -} - -/* Recalculates the arrow polygons for the line */ -static void -reconfigure_arrows (GnomeCanvasLine *line) -{ - gdouble *poly, *coords; - gdouble dx, dy, length; - gdouble sin_theta, cos_theta, tmp; - gdouble frac_height; /* Line width as fraction of arrowhead width */ - gdouble backup; /* Distance to backup end points so the line ends in the middle of the arrowhead */ - gdouble vx, vy; /* Position of arrowhead vertex */ - gdouble shape_a, shape_b, shape_c; - gdouble width; - gint i; - - if (line->num_points == 0) - return; - - /* Set up things */ - - if (line->first_arrow) { - if (line->first_coords) { - line->coords[0] = line->first_coords[0]; - line->coords[1] = line->first_coords[1]; - } else - line->first_coords = g_new (double, 2 * NUM_ARROW_POINTS); - } else if (line->first_coords) { - line->coords[0] = line->first_coords[0]; - line->coords[1] = line->first_coords[1]; - - g_free (line->first_coords); - line->first_coords = NULL; - } - - i = 2 * (line->num_points - 1); - - if (line->last_arrow) { - if (line->last_coords) { - line->coords[i] = line->last_coords[0]; - line->coords[i + 1] = line->last_coords[1]; - } else - line->last_coords = g_new (double, 2 * NUM_ARROW_POINTS); - } else if (line->last_coords) { - line->coords[i] = line->last_coords[0]; - line->coords[i + 1] = line->last_coords[1]; - - g_free (line->last_coords); - line->last_coords = NULL; - } - - if (!line->first_arrow && !line->last_arrow) - return; - - if (line->width_pixels) - width = line->width / line->item.canvas->pixels_per_unit; - else - width = line->width; - - /* Add fudge value for better-looking results */ - - shape_a = line->shape_a; - shape_b = line->shape_b; - shape_c = line->shape_c + width / 2.0; - - if (line->width_pixels) { - shape_a /= line->item.canvas->pixels_per_unit; - shape_b /= line->item.canvas->pixels_per_unit; - shape_c /= line->item.canvas->pixels_per_unit; - } - - shape_a += 0.001; - shape_b += 0.001; - shape_c += 0.001; - - /* Compute the polygon for the first arrowhead and adjust the first point in the line so - * that the line does not stick out past the leading edge of the arrowhead. - */ - - frac_height = (line->width / 2.0) / shape_c; - backup = frac_height * shape_b + shape_a * (1.0 - frac_height) / 2.0; - - if (line->first_arrow) { - poly = line->first_coords; - poly[0] = poly[10] = line->coords[0]; - poly[1] = poly[11] = line->coords[1]; - - dx = poly[0] - line->coords[2]; - dy = poly[1] - line->coords[3]; - length = sqrt (dx * dx + dy * dy); - if (length < GNOME_CANVAS_EPSILON) - sin_theta = cos_theta = 0.0; - else { - sin_theta = dy / length; - cos_theta = dx / length; - } - - vx = poly[0] - shape_a * cos_theta; - vy = poly[1] - shape_a * sin_theta; - - tmp = shape_c * sin_theta; - - poly[2] = poly[0] - shape_b * cos_theta + tmp; - poly[8] = poly[2] - 2.0 * tmp; - - tmp = shape_c * cos_theta; - - poly[3] = poly[1] - shape_b * sin_theta - tmp; - poly[9] = poly[3] + 2.0 * tmp; - - poly[4] = poly[2] * frac_height + vx * (1.0 - frac_height); - poly[5] = poly[3] * frac_height + vy * (1.0 - frac_height); - poly[6] = poly[8] * frac_height + vx * (1.0 - frac_height); - poly[7] = poly[9] * frac_height + vy * (1.0 - frac_height); - - /* Move the first point towards the second so that the corners at the end of the - * line are inside the arrowhead. - */ - - line->coords[0] = poly[0] - backup * cos_theta; - line->coords[1] = poly[1] - backup * sin_theta; - } - - /* Same process for last arrowhead */ - - if (line->last_arrow) { - coords = line->coords + 2 * (line->num_points - 2); - poly = line->last_coords; - poly[0] = poly[10] = coords[2]; - poly[1] = poly[11] = coords[3]; - - dx = poly[0] - coords[0]; - dy = poly[1] - coords[1]; - length = sqrt (dx * dx + dy * dy); - if (length < GNOME_CANVAS_EPSILON) - sin_theta = cos_theta = 0.0; - else { - sin_theta = dy / length; - cos_theta = dx / length; - } - - vx = poly[0] - shape_a * cos_theta; - vy = poly[1] - shape_a * sin_theta; - - tmp = shape_c * sin_theta; - - poly[2] = poly[0] - shape_b * cos_theta + tmp; - poly[8] = poly[2] - 2.0 * tmp; - - tmp = shape_c * cos_theta; - - poly[3] = poly[1] - shape_b * sin_theta - tmp; - poly[9] = poly[3] + 2.0 * tmp; - - poly[4] = poly[2] * frac_height + vx * (1.0 - frac_height); - poly[5] = poly[3] * frac_height + vy * (1.0 - frac_height); - poly[6] = poly[8] * frac_height + vx * (1.0 - frac_height); - poly[7] = poly[9] * frac_height + vy * (1.0 - frac_height); - - coords[2] = poly[0] - backup * cos_theta; - coords[3] = poly[1] - backup * sin_theta; - } -} - -static void -gnome_canvas_line_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - GnomeCanvasItem *item; - GnomeCanvasLine *line; - GnomeCanvasPoints *points; - GdkColor color = { 0, 0, 0, 0, }; - GdkColor *pcolor; - gboolean color_changed; - gint have_pixel; - - g_return_if_fail (object != NULL); - g_return_if_fail (GNOME_IS_CANVAS_LINE (object)); - - item = GNOME_CANVAS_ITEM (object); - line = GNOME_CANVAS_LINE (object); - - color_changed = FALSE; - have_pixel = FALSE; - - switch (param_id) { - case PROP_POINTS: - points = g_value_get_boxed (value); - - if (line->coords) { - g_free (line->coords); - line->coords = NULL; - } - - if (!points) - line->num_points = 0; - else { - line->num_points = points->num_points; - line->coords = g_new (double, 2 * line->num_points); - memcpy (line->coords, points->coords, 2 * line->num_points * sizeof (gdouble)); - } - - /* Drop the arrowhead polygons if they exist -- they will be regenerated */ - - if (line->first_coords) { - g_free (line->first_coords); - line->first_coords = NULL; - } - - if (line->last_coords) { - g_free (line->last_coords); - line->last_coords = NULL; - } - - /* Since the line's points have changed, we need to re-generate arrowheads in - * addition to recalculating the bounds. - */ - gnome_canvas_item_request_update (item); - break; - - case PROP_FILL_COLOR: - if (g_value_get_string (value)) - gdk_color_parse (g_value_get_string (value), &color); - line->fill_rgba = ((color.red & 0xff00) << 16 | - (color.green & 0xff00) << 8 | - (color.blue & 0xff00) | - 0xff); - color_changed = TRUE; - break; - - case PROP_FILL_COLOR_GDK: - pcolor = g_value_get_boxed (value); - if (pcolor) { - GdkColormap *colormap; - color = *pcolor; - - colormap = gtk_widget_get_colormap (GTK_WIDGET (item->canvas)); - gdk_rgb_find_color (colormap, &color); - - have_pixel = TRUE; - } - - line->fill_rgba = ((color.red & 0xff00) << 16 | - (color.green & 0xff00) << 8 | - (color.blue & 0xff00) | - 0xff); - color_changed = TRUE; - break; - - case PROP_FILL_COLOR_RGBA: - line->fill_rgba = g_value_get_uint (value); - color_changed = TRUE; - break; - - case PROP_WIDTH_PIXELS: - line->width = g_value_get_uint (value); - line->width_pixels = TRUE; - gnome_canvas_item_request_update (item); - break; - - case PROP_WIDTH_UNITS: - line->width = fabs (g_value_get_double (value)); - line->width_pixels = FALSE; - gnome_canvas_item_request_update (item); - break; - - case PROP_CAP_STYLE: - line->cap = g_value_get_enum (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_JOIN_STYLE: - line->join = g_value_get_enum (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_FIRST_ARROWHEAD: - line->first_arrow = g_value_get_boolean (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_LAST_ARROWHEAD: - line->last_arrow = g_value_get_boolean (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_SMOOTH: - /* FIXME */ - break; - - case PROP_SPLINE_STEPS: - /* FIXME */ - break; - - case PROP_ARROW_SHAPE_A: - line->shape_a = fabs (g_value_get_double (value)); - gnome_canvas_item_request_update (item); - break; - - case PROP_ARROW_SHAPE_B: - line->shape_b = fabs (g_value_get_double (value)); - gnome_canvas_item_request_update (item); - break; - - case PROP_ARROW_SHAPE_C: - line->shape_c = fabs (g_value_get_double (value)); - gnome_canvas_item_request_update (item); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } - - if (color_changed) { - if (have_pixel) - line->fill_pixel = color.pixel; - else - line->fill_pixel = gnome_canvas_get_color_pixel (item->canvas, - line->fill_rgba); - - gnome_canvas_item_request_redraw_svp (item, line->fill_svp); - - if (line->first_svp) - gnome_canvas_item_request_redraw_svp (item, line->first_svp); - - if (line->last_svp) - gnome_canvas_item_request_redraw_svp (item, line->last_svp); - - } -} - -/* Returns a copy of the line's points without the endpoint adjustments for - * arrowheads. - */ -static GnomeCanvasPoints * -get_points (GnomeCanvasLine *line) -{ - GnomeCanvasPoints *points; - gint start_ofs, end_ofs; - - if (line->num_points == 0) - return NULL; - - start_ofs = end_ofs = 0; - - points = gnome_canvas_points_new (line->num_points); - - /* Invariant: if first_coords or last_coords exist, then the line's - * endpoints have been adjusted. - */ - - if (line->first_coords) { - start_ofs = 1; - - points->coords[0] = line->first_coords[0]; - points->coords[1] = line->first_coords[1]; - } - - if (line->last_coords) { - end_ofs = 1; - - points->coords[2 * (line->num_points - 1)] = line->last_coords[0]; - points->coords[2 * (line->num_points - 1) + 1] = line->last_coords[1]; - } - - memcpy (points->coords + 2 * start_ofs, - line->coords + 2 * start_ofs, - 2 * (line->num_points - (start_ofs + end_ofs)) * sizeof (gdouble)); - - return points; -} - -static void -gnome_canvas_line_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - GnomeCanvasLine *line; - - g_return_if_fail (object != NULL); - g_return_if_fail (GNOME_IS_CANVAS_LINE (object)); - - line = GNOME_CANVAS_LINE (object); - - switch (param_id) { - case PROP_POINTS: - /* get_points returns a copy */ - g_value_take_boxed (value, get_points (line)); - break; - - case PROP_FILL_COLOR: - g_value_take_string (value, - g_strdup_printf ("#%02x%02x%02x", - line->fill_rgba >> 24, - (line->fill_rgba >> 16) & 0xff, - (line->fill_rgba >> 8) & 0xff)); - break; - - case PROP_FILL_COLOR_GDK: { - GnomeCanvas *canvas = GNOME_CANVAS_ITEM (line)->canvas; - GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (canvas)); - GdkColor color; - - gdk_colormap_query_color (colormap, line->fill_pixel, &color); - g_value_set_boxed (value, &color); - break; - } - - case PROP_FILL_COLOR_RGBA: - g_value_set_uint (value, line->fill_rgba); - break; - - case PROP_WIDTH_PIXELS: - g_value_set_uint (value, line->width); - break; - - case PROP_WIDTH_UNITS: - g_value_set_double (value, line->width); - break; - - case PROP_CAP_STYLE: - g_value_set_enum (value, line->cap); - break; - - case PROP_JOIN_STYLE: - g_value_set_enum (value, line->join); - break; - - case PROP_FIRST_ARROWHEAD: - g_value_set_boolean (value, line->first_arrow); - break; - - case PROP_LAST_ARROWHEAD: - g_value_set_boolean (value, line->last_arrow); - break; - - case PROP_SMOOTH: - g_value_set_boolean (value, line->smooth); - break; - - case PROP_SPLINE_STEPS: - g_value_set_uint (value, line->spline_steps); - break; - - case PROP_ARROW_SHAPE_A: - g_value_set_double (value, line->shape_a); - break; - - case PROP_ARROW_SHAPE_B: - g_value_set_double (value, line->shape_b); - break; - - case PROP_ARROW_SHAPE_C: - g_value_set_double (value, line->shape_c); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -gnome_canvas_line_update (GnomeCanvasItem *item, gdouble *affine, ArtSVP *clip_path, gint flags) -{ - GnomeCanvasLine *line; - gdouble x1, y1, x2, y2; - - line = GNOME_CANVAS_LINE (item); - - if (parent_class->update) - (* parent_class->update) (item, affine, clip_path, flags); - - reconfigure_arrows (line); - - get_bounds_canvas (line, &x1, &y1, &x2, &y2, affine); - gnome_canvas_update_bbox (item, x1, y1, x2, y2); -} - -static void -item_to_canvas (GnomeCanvas *canvas, gdouble *item_coords, GdkPoint *canvas_coords, gint num_points, - gint *num_drawn_points, const cairo_matrix_t *matrix) -{ - gint i; - gint old_cx, old_cy; - gint cx, cy; - double x, y; - -#ifdef VERBOSE - { - gchar str[128]; - art_affine_to_string (str, i2c); - g_print ("line item_to_canvas %s\n", str); - } -#endif - - /* the first point is always drawn */ - - x = item_coords[0]; - y = item_coords[1]; - cairo_matrix_transform_point (matrix, &x, &y); - cx = floor (x + 0.5); - cy = floor (y + 0.5); - canvas_coords->x = cx - x; - canvas_coords->y = cy - y; - canvas_coords++; - old_cx = cx; - old_cy = cy; - *num_drawn_points = 1; - - for (i = 1; i < num_points; i++) { - x = item_coords[i * 2]; - y = item_coords[i * 2 + 1]; - cairo_matrix_transform_point (matrix, &x, &y); - cx = floor (x + 0.5); - cy = floor (y + 0.5); - if (old_cx != cx || old_cy != cy) { - canvas_coords->x = cx - x; - canvas_coords->y = cy - y; - old_cx = cx; - old_cy = cy; - canvas_coords++; - (*num_drawn_points)++; - } - } -} - -static void -gnome_canvas_line_draw (GnomeCanvasItem *item, GdkDrawable *drawable, - gint x, gint y, gint width, gint height) -{ - GnomeCanvasLine *line; - GdkPoint static_points[NUM_STATIC_POINTS]; - GdkPoint *points; - gint actual_num_points_drawn; - cairo_matrix_t matrix; - cairo_t *cr; - int i; - - line = GNOME_CANVAS_LINE (item); - - if (line->num_points == 0) - return; - - cr = gdk_cairo_create (drawable); - cairo_translate (cr, -x, -y); - - /* points are always centered */ - cairo_translate (cr, 0.5, 0.5); - - cairo_set_source_rgba (cr, - ((line->fill_pixel >> 24) & 0xff) / 255.0, - ((line->fill_pixel >> 16) & 0xff) / 255.0, - ((line->fill_pixel >> 8) & 0xff) / 255.0, - ((line->fill_pixel >> 0) & 0xff) / 255.0); - if (line->width_pixels) - cairo_set_line_width (cr, (gint) line->width); - else - cairo_set_line_width (cr, (gint) (line->width * line->item.canvas->pixels_per_unit + 0.5)); - if (line->first_arrow || line->last_arrow) - cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT); - else - cairo_set_line_cap (cr, line->cap); - cairo_set_line_join (cr, line->join); - - gnome_canvas_item_i2c_matrix (item, &matrix); - /* Build array of canvas pixel coordinates */ - - if (line->num_points <= NUM_STATIC_POINTS) - points = static_points; - else - points = g_new (GdkPoint, line->num_points); - - item_to_canvas (item->canvas, line->coords, points, line->num_points, - &actual_num_points_drawn, &matrix); - - cairo_move_to (cr, points[0].x, points[0].y); - for (i = 1; i < actual_num_points_drawn; i++) - cairo_line_to (cr, points[i].x, points[i].y); - cairo_stroke (cr); - - if (points != static_points) - g_free (points); - - /* Draw arrowheads */ - - points = static_points; - - if (line->first_arrow) { - item_to_canvas (item->canvas, line->first_coords, points, NUM_ARROW_POINTS, - &actual_num_points_drawn, &matrix); - cairo_move_to (cr, points[0].x, points[0].y); - for (i = 1; i < actual_num_points_drawn; i++) - cairo_line_to (cr, points[i].x, points[i].y); - cairo_fill (cr); - } - - if (line->last_arrow) { - item_to_canvas (item->canvas, line->last_coords, points, NUM_ARROW_POINTS, - &actual_num_points_drawn, &matrix); - cairo_move_to (cr, points[0].x, points[0].y); - for (i = 1; i < actual_num_points_drawn; i++) - cairo_line_to (cr, points[i].x, points[i].y); - cairo_fill (cr); - } -} - -static GnomeCanvasItem * -gnome_canvas_line_point (GnomeCanvasItem *item, gdouble x, gdouble y, - gint cx, gint cy) -{ - GnomeCanvasLine *line; - gdouble *line_points = NULL, *coords; - gdouble static_points[2 * NUM_STATIC_POINTS]; - gdouble poly[10]; - gdouble best, dist; - gdouble dx, dy; - gdouble width; - gint num_points = 0, i; - gint changed_miter_to_bevel; - -#ifdef VERBOSE - g_print ("gnome_canvas_line_point x, y = (%g, %g); cx, cy = (%d, %d)\n", x, y, cx, cy); -#endif - - line = GNOME_CANVAS_LINE (item); - - best = 1.0e36; - - /* Handle smoothed lines by generating an expanded set ot points */ - - if (line->smooth && (line->num_points > 2)) { - /* FIXME */ - } else { - num_points = line->num_points; - line_points = line->coords; - } - - /* Compute a polygon for each edge of the line and test the point against it. The effective - * width of the line is adjusted so that it will be at least one pixel thick (so that zero - * pixel-wide lines can be pickedup as well). - */ - - if (line->width_pixels) - width = line->width / item->canvas->pixels_per_unit; - else - width = line->width; - - if (width < (1.0 / item->canvas->pixels_per_unit)) - width = 1.0 / item->canvas->pixels_per_unit; - - changed_miter_to_bevel = 0; - - for (i = num_points, coords = line_points; i >= 2; i--, coords += 2) { - /* If rounding is done around the first point, then compute distance between the - * point and the first point. - */ - - if (((line->cap == CAIRO_LINE_CAP_ROUND) && (i == num_points)) - || ((line->join == CAIRO_LINE_JOIN_ROUND) && (i != num_points))) { - dx = coords[0] - x; - dy = coords[1] - y; - dist = sqrt (dx * dx + dy * dy) - width / 2.0; - if (dist < GNOME_CANVAS_EPSILON) { - best = 0.0; - goto done; - } else if (dist < best) - best = dist; - } - - /* Compute the polygonal shape corresponding to this edge, with two points for the - * first point of the edge and two points for the last point of the edge. - */ - - if (i == num_points) - gnome_canvas_get_butt_points (coords[2], coords[3], coords[0], coords[1], - width, (line->cap == CAIRO_LINE_CAP_SQUARE), - poly, poly + 1, poly + 2, poly + 3); - else if ((line->join == CAIRO_LINE_JOIN_MITER) && !changed_miter_to_bevel) { - poly[0] = poly[6]; - poly[1] = poly[7]; - poly[2] = poly[4]; - poly[3] = poly[5]; - } else { - gnome_canvas_get_butt_points (coords[2], coords[3], coords[0], coords[1], - width, FALSE, - poly, poly + 1, poly + 2, poly + 3); - - /* If this line uses beveled joints, then check the distance to a polygon - * comprising the last two points of the previous polygon and the first two - * from this polygon; this checks the wedges that fill the mitered point. - */ - - if ((line->join == CAIRO_LINE_JOIN_BEVEL) || changed_miter_to_bevel) { - poly[8] = poly[0]; - poly[9] = poly[1]; - - dist = gnome_canvas_polygon_to_point (poly, 5, x, y); - if (dist < GNOME_CANVAS_EPSILON) { - best = 0.0; - goto done; - } else if (dist < best) - best = dist; - - changed_miter_to_bevel = FALSE; - } - } - - if (i == 2) - gnome_canvas_get_butt_points (coords[0], coords[1], coords[2], coords[3], - width, (line->cap == CAIRO_LINE_CAP_SQUARE), - poly + 4, poly + 5, poly + 6, poly + 7); - else if (line->join == CAIRO_LINE_JOIN_MITER) { - if (!gnome_canvas_get_miter_points (coords[0], coords[1], - coords[2], coords[3], - coords[4], coords[5], - width, - poly + 4, poly + 5, poly + 6, poly + 7)) { - changed_miter_to_bevel = TRUE; - gnome_canvas_get_butt_points (coords[0], coords[1], coords[2], coords[3], - width, FALSE, - poly + 4, poly + 5, poly + 6, poly + 7); - } - } else - gnome_canvas_get_butt_points (coords[0], coords[1], coords[2], coords[3], - width, FALSE, - poly + 4, poly + 5, poly + 6, poly + 7); - - poly[8] = poly[0]; - poly[9] = poly[1]; - - dist = gnome_canvas_polygon_to_point (poly, 5, x, y); - if (dist < GNOME_CANVAS_EPSILON) { - best = 0.0; - goto done; - } else if (dist < best) - best = dist; - } - - /* If caps are rounded, check the distance to the cap around the final end point of the line */ - - if (line->cap == CAIRO_LINE_CAP_ROUND) { - dx = coords[0] - x; - dy = coords[1] - y; - dist = sqrt (dx * dx + dy * dy) - width / 2.0; - if (dist < GNOME_CANVAS_EPSILON) { - best = 0.0; - goto done; - } else - best = dist; - } - - /* sometimes the GnomeCanvasItem::update signal will not have - been processed between deleting the arrow points and a call - to this routine -- this can cause a segfault here */ - if ((line->first_arrow && !line->first_coords) || - (line->last_arrow && !line->last_coords)) - reconfigure_arrows (line); - - /* If there are arrowheads, check the distance to them */ - - if (line->first_arrow) { - dist = gnome_canvas_polygon_to_point (line->first_coords, NUM_ARROW_POINTS, x, y); - if (dist < GNOME_CANVAS_EPSILON) { - best = 0.0; - goto done; - } else - best = dist; - } - - if (line->last_arrow) { - dist = gnome_canvas_polygon_to_point (line->last_coords, NUM_ARROW_POINTS, x, y); - if (dist < GNOME_CANVAS_EPSILON) { - best = 0.0; - goto done; - } else - best = dist; - } - -done: - - if ((line_points != static_points) && (line_points != line->coords)) - g_free (line_points); - - return best == 0.0 ? item : NULL; -} - -static void -gnome_canvas_line_bounds (GnomeCanvasItem *item, gdouble *x1, gdouble *y1, gdouble *x2, gdouble *y2) -{ - GnomeCanvasLine *line; - - line = GNOME_CANVAS_LINE (item); - - if (line->num_points == 0) { - *x1 = *y1 = *x2 = *y2 = 0.0; - return; - } - - get_bounds (line, x1, y1, x2, y2); -} diff --git a/libgnomecanvas/gnome-canvas-line.h b/libgnomecanvas/gnome-canvas-line.h deleted file mode 100644 index 749478ff72..0000000000 --- a/libgnomecanvas/gnome-canvas-line.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation - * All rights reserved. - * - * This file is part of the Gnome Library. - * - * The Gnome Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The Gnome Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ - */ - -/* Line/curve item type for GnomeCanvas widget - * - * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is - * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. - * - * - * Author: Federico Mena <federico@nuclecu.unam.mx> - */ - -#ifndef GNOME_CANVAS_LINE_H -#define GNOME_CANVAS_LINE_H - -#include <libgnomecanvas/gnome-canvas.h> - -G_BEGIN_DECLS - -/* Line item for the canvas. This is a polyline with configurable width, cap/join styles, and arrowheads. - * If arrowheads are enabled, then three values are used to specify their shape: - * - * arrow_shape_a: Distance from tip of arrowhead to the center point. - * arrow_shape_b: Distance from tip of arrowhead to trailing point, measured along the shaft. - * arrow_shape_c: Distance of trailing point from outside edge of shaft. - * - * The following object arguments are available: - * - * name type read/write description - * ------------------------------------------------------------------------------------------ - * points GnomeCanvasPoints* RW Pointer to a GnomeCanvasPoints structure. - * This can be created by a call to - * gnome_canvas_points_new() (in gnome-canvas-util.h). - * X coordinates are in the even indices of the - * points->coords array, Y coordinates are in - * the odd indices. - * fill_color string W X color specification for line - * fill_color_gdk GdkColor* RW Pointer to an allocated GdkColor - * width_pixels uint R Width of the line in pixels. The line width - * will not be scaled when the canvas zoom factor changes. - * width_units gdouble R Width of the line in canvas units. The line width - * will be scaled when the canvas zoom factor changes. - * cap_style GdkCapStyle RW Cap ("endpoint") style for the line. - * join_style GdkJoinStyle RW Join ("vertex") style for the line. - * line_style GdkLineStyle RW Line dash style - * first_arrowhead boolean RW Specifies whether to draw an arrowhead on the - * first point of the line. - * last_arrowhead boolean RW Specifies whether to draw an arrowhead on the - * last point of the line. - * smooth boolean RW Specifies whether to smooth the line using - * parabolic splines. - * spline_steps uint RW Specifies the number of steps to use when rendering curves. - * arrow_shape_a gdouble RW First arrow shape specifier. - * arrow_shape_b gdouble RW Second arrow shape specifier. - * arrow_shape_c gdouble RW Third arrow shape specifier. - */ - -#define GNOME_TYPE_CANVAS_LINE (gnome_canvas_line_get_type ()) -#define GNOME_CANVAS_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_CANVAS_LINE, GnomeCanvasLine)) -#define GNOME_CANVAS_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_CANVAS_LINE, GnomeCanvasLineClass)) -#define GNOME_IS_CANVAS_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_CANVAS_LINE)) -#define GNOME_IS_CANVAS_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_CANVAS_LINE)) -#define GNOME_CANVAS_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_CANVAS_LINE, GnomeCanvasLineClass)) - -typedef struct _GnomeCanvasLine GnomeCanvasLine; -typedef struct _GnomeCanvasLineClass GnomeCanvasLineClass; - -struct _GnomeCanvasLine { - GnomeCanvasItem item; - - gdouble *coords; /* Array of coordinates for the line's points. X coords are in the - * even indices, Y coords are in the odd indices. If the line has - * arrowheads then the first and last points have been adjusted to - * refer to the necks of the arrowheads rather than their tips. The - * actual endpoints are stored in the first_arrow and last_arrow - * arrays, if they exist. - */ - - gdouble *first_coords; /* Array of points describing polygon for the first arrowhead */ - gdouble *last_coords; /* Array of points describing polygon for the last arrowhead */ - - GdkGC *gc; /* GC for drawing line */ - - ArtSVP *fill_svp; /* The SVP for the outline shape */ /*AA*/ - ArtSVP *first_svp; /* The SVP for the first arrow */ /*AA*/ - ArtSVP *last_svp; /* The SVP for the last arrow */ /*AA*/ - - gdouble width; /* Width of the line */ - - gdouble shape_a; /* Distance from tip of arrowhead to center */ - gdouble shape_b; /* Distance from tip of arrowhead to trailing point, measured along shaft */ - gdouble shape_c; /* Distance of trailing points from outside edge of shaft */ - - cairo_line_cap_t cap; /* Cap style for line */ - cairo_line_join_t join; /* Join style for line */ - - gulong fill_pixel; /* Color for line */ - - guint32 fill_rgba; /* RGBA color for outline */ /*AA*/ - - gint num_points; /* Number of points in the line */ - guint fill_color; /* Fill color, RGBA */ - - gint spline_steps; /* Number of steps in each spline segment */ - - guint width_pixels : 1; /* Is the width specified in pixels or units? */ - guint first_arrow : 1; /* Draw first arrowhead? */ - guint last_arrow : 1; /* Draw last arrowhead? */ - guint smooth : 1; /* Smooth line (with parabolic splines)? */ -}; - -struct _GnomeCanvasLineClass { - GnomeCanvasItemClass parent_class; -}; - -/* Standard Gtk function */ -GType gnome_canvas_line_get_type (void) G_GNUC_CONST; - -G_END_DECLS - -#endif diff --git a/libgnomecanvas/gnome-canvas-util.c b/libgnomecanvas/gnome-canvas-util.c index 8a21c548c7..bc6b1ba968 100644 --- a/libgnomecanvas/gnome-canvas-util.c +++ b/libgnomecanvas/gnome-canvas-util.c @@ -616,3 +616,24 @@ gnome_canvas_cap_gdk_to_art (GdkCapStyle gdk_cap) return ART_PATH_STROKE_CAP_BUTT; /* shut up the compiler */ } } + +/** + * gnome_canvas_cairo_create_scratch: + * + * Create a scratch #cairo_t. This is useful for measuring purposes or + * calling functions like cairo_in_fill(). + * + * Returns: A new cairo_t. Destroy with cairo_destroy() after use. + **/ +cairo_t * +gnome_canvas_cairo_create_scratch (void) +{ + cairo_surface_t *surface; + cairo_t *cr; + + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); + cr = cairo_create (surface); + cairo_surface_destroy (surface); + + return cr; +} diff --git a/libgnomecanvas/gnome-canvas-util.h b/libgnomecanvas/gnome-canvas-util.h index 1c43b65596..74e112f0fd 100644 --- a/libgnomecanvas/gnome-canvas-util.h +++ b/libgnomecanvas/gnome-canvas-util.h @@ -141,6 +141,9 @@ ArtPathStrokeJoinType gnome_canvas_join_gdk_to_art (GdkJoinStyle gdk_join); /* Convert from GDK line cap specifier to libart. */ ArtPathStrokeCapType gnome_canvas_cap_gdk_to_art (GdkCapStyle gdk_cap); +/* Create a scratch cairo_t for measuring purposes */ +cairo_t *gnome_canvas_cairo_create_scratch (void); + G_END_DECLS #endif diff --git a/libgnomecanvas/libgnomecanvas.h b/libgnomecanvas/libgnomecanvas.h index 8ddd2c541e..6dff7de8dd 100644 --- a/libgnomecanvas/libgnomecanvas.h +++ b/libgnomecanvas/libgnomecanvas.h @@ -27,7 +27,6 @@ #define LIBGNOMECANVAS_H #include <libgnomecanvas/gnome-canvas.h> -#include <libgnomecanvas/gnome-canvas-line.h> #include <libgnomecanvas/gnome-canvas-text.h> #include <libgnomecanvas/gnome-canvas-rich-text.h> #include <libgnomecanvas/gnome-canvas-pixbuf.h> |