[goffice] Canvas: lines can have arrows in either end.
- From: Morten Welinder <mortenw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [goffice] Canvas: lines can have arrows in either end.
- Date: Wed, 14 Oct 2009 18:19:16 +0000 (UTC)
commit bdb0c406fdbe4bbbc53e2747508e531cdf2d135f
Author: Morten Welinder <terra gnome org>
Date: Wed Oct 14 14:18:59 2009 -0400
Canvas: lines can have arrows in either end.
ChangeLog | 8 ++
NEWS | 3 +
goffice/canvas/goc-line.c | 176 ++++++++++++++++++++++++---------------------
goffice/canvas/goc-line.h | 4 +-
4 files changed, 108 insertions(+), 83 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 26327c5..f1f1b6d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2009-10-14 Morten Welinder <terra gnome org>
+ * goffice/canvas/goc-line.c (goc_line_class_init): Change to
+ GOArrow for arrow properties.
+
+ * goffice/canvas/goc-line.h (struct _GocLine): Have an arrow at
+ both ends.
+
+ * goffice/canvas/goc-line.c (goc_line_draw): Draw point arrows.
+
* goffice/utils/go-line.c (go_arrow_init, go_arrow_get_type,
go_arrow_clear, go_arrow_dup): New functions.
diff --git a/NEWS b/NEWS
index 0a2f38d..122069f 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ Jean:
* Fix bounds update of GocItem. [#598091]
* Prepare for GSEAL_ENABLE.
+Morten:
+ * Canvas improvements for arrows.
+
--------------------------------------------------------------------------
goffice 0.7.14:
diff --git a/goffice/canvas/goc-line.c b/goffice/canvas/goc-line.c
index c3b4549..8ced147 100644
--- a/goffice/canvas/goc-line.c
+++ b/goffice/canvas/goc-line.c
@@ -30,7 +30,7 @@
* @short_description: Simple line.
*
* #GocLine implements simple line drawing in the canvas. The line can have
- * an arrowhead at its end.
+ * arrows at the start and/or at the end.
**/
enum {
@@ -39,10 +39,8 @@ enum {
LINE_PROP_Y0,
LINE_PROP_X1,
LINE_PROP_Y1,
- LINE_PROP_ARROWHEAD,
- LINE_PROP_ARROW_SHAPE_A,
- LINE_PROP_ARROW_SHAPE_B,
- LINE_PROP_ARROW_SHAPE_C
+ LINE_PROP_START_ARROW,
+ LINE_PROP_END_ARROW
};
static void
@@ -68,20 +66,12 @@ goc_line_set_property (GObject *gobject, guint param_id,
line->endy = g_value_get_double (value);
break;
- case LINE_PROP_ARROWHEAD:
- line->arrowhead = g_value_get_boolean (value);
+ case LINE_PROP_START_ARROW:
+ line->start_arrow = *((GOArrow *)g_value_peek_pointer (value));
break;
- case LINE_PROP_ARROW_SHAPE_A:
- line->headA = g_value_get_double (value);
- break;
-
- case LINE_PROP_ARROW_SHAPE_B:
- line->headB = g_value_get_double (value);
- break;
-
- case LINE_PROP_ARROW_SHAPE_C:
- line->headC = g_value_get_double (value);
+ case LINE_PROP_END_ARROW:
+ line->end_arrow = *((GOArrow *)g_value_peek_pointer (value));
break;
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
@@ -113,20 +103,12 @@ goc_line_get_property (GObject *gobject, guint param_id,
g_value_set_double (value, line->endy);
break;
- case LINE_PROP_ARROWHEAD:
- g_value_set_boolean (value, line->arrowhead);
- break;
-
- case LINE_PROP_ARROW_SHAPE_A:
- g_value_set_double (value, line->headA);
- break;
-
- case LINE_PROP_ARROW_SHAPE_B:
- g_value_set_double (value, line->headB);
+ case LINE_PROP_START_ARROW:
+ g_value_set_boxed (value, &line->start_arrow);
break;
- case LINE_PROP_ARROW_SHAPE_C:
- g_value_set_double (value, line->headC);
+ case LINE_PROP_END_ARROW:
+ g_value_set_boxed (value, &line->end_arrow);
break;
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
@@ -158,9 +140,20 @@ goc_line_update_bounds (GocItem *item)
item->y0 = line->endy - extra_width;
item->y1 = line->starty + extra_width;
}
- if (line->arrowhead) {
- /* do not calculate things precisely, just add enough room in all directions */
- double d = hypot (line->headB, line->headC);
+ if (line->start_arrow.typ) {
+ /*
+ * Do not calculate things precisely, just add enough room
+ * in all directions.
+ */
+ double d = hypot (line->start_arrow.b, line->start_arrow.c);
+ item->x0 -= d;
+ item->x1 += d;
+ item->y0 -= d;
+ item->y1 += d;
+ }
+ if (line->end_arrow.typ) {
+ /* See above. */
+ double d = hypot (line->end_arrow.b, line->end_arrow.c);
item->x0 -= d;
item->x1 += d;
item->y0 -= d;
@@ -193,44 +186,77 @@ goc_line_distance (GocItem *item, double x, double y, GocItem **near_item)
return (t > 0.)? t: 0.;
}
-static void goc_line_draw (GocItem const *item, cairo_t *cr)
+static void
+draw_arrow (GOArrow const *arrow, cairo_t *cr, GOStyle *style,
+ double *endx, double *endy, double phi)
+{
+ double l, w;
+
+ if (arrow->typ == GO_ARROW_NONE)
+ return;
+
+ l = hypot (*endx, *endy);
+ w = style->line.width ? style->line.width / 2.0 : 0.5;
+
+ switch (arrow->typ) {
+ case GO_ARROW_TRIANGLE:
+ cairo_save (cr);
+ cairo_translate (cr, (int) *endx, (int) *endy);
+ cairo_rotate (cr, phi);
+ cairo_move_to (cr, -arrow->a, w);
+ cairo_line_to (cr, -arrow->b, w + arrow->c);
+ cairo_line_to (cr, 0., 0.);
+ cairo_line_to (cr, -arrow->b, -w - arrow->c);
+ cairo_line_to (cr, -arrow->a, -w);
+ cairo_close_path (cr);
+ cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (style->line.color));
+ cairo_fill (cr);
+ cairo_restore (cr);
+ if (l > 0.) {
+ (*endx) -= arrow->a * *endx / l;
+ (*endy) -= arrow->a * *endy / l;
+ } else
+ *endx = *endy = 0.;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+goc_line_draw (GocItem const *item, cairo_t *cr)
{
GocLine *line = GOC_LINE (item);
+ GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
double sign = (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)? -1: 1;
double endx = (line->endx - line->startx) * sign, endy = line->endy - line->starty;
- double hoffs, voffs = ceil (go_styled_object_get_style (GO_STYLED_OBJECT (item))->line.width);
+ double hoffs, voffs = ceil (style->line.width);
+ double startx = 0, starty = 0;
+ double phi;
+
if (line->startx == line->endx && line->starty == line->endy)
return;
+
if (voffs <= 0.)
voffs = 1.;
+
hoffs = ((int) voffs & 1)? .5: 0.;
voffs = (line->starty == line->endy)? hoffs: 0.;
if (line->startx != line->endx)
hoffs = 0.;
+
cairo_save (cr);
- goc_group_cairo_transform (item->parent, cr, hoffs + (int) line->startx, voffs + (int) line->starty);
- if (line->arrowhead) {
- GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
- double l = hypot (endx, endy), w = (style->line.width)? style->line.width / 2.: .5;
- /* display the arrow head */
- cairo_save (cr);
- cairo_translate (cr, (int) endx, (int) endy);
- cairo_rotate (cr, atan2 (endy, endx));
- cairo_move_to (cr, -line->headA, w);
- cairo_line_to (cr, -line->headB, w + line->headC);
- cairo_line_to (cr, 0., 0.);
- cairo_line_to (cr, -line->headB, -w - line->headC);
- cairo_line_to (cr, -line->headA, -w);
- cairo_close_path (cr);
- cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (style->line.color));
- cairo_fill (cr);
- cairo_restore (cr);
- if (l > 0.) {
- endx -= line->headA * endx / l;
- endy -= line->headA * endy / l;
- } else
- endx = endy = 0.;
- }
+ goc_group_cairo_transform (item->parent, cr,
+ hoffs + (int) line->startx,
+ voffs + (int) line->starty);
+
+ phi = atan2 (endy, endx);
+ draw_arrow (&line->start_arrow, cr, style,
+ &startx, &starty, phi + M_PI);
+ draw_arrow (&line->end_arrow, cr, style,
+ &endx, &endy, phi);
+
if ((endx != 0. || endy!= 0.) && go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr)) {
/* try to avoid horizontal and vertical lines between two pixels */
cairo_move_to (cr, 0., 0.);
@@ -288,30 +314,18 @@ goc_line_class_init (GocItemClass *item_klass)
_("The line end y coordinate"),
-G_MAXDOUBLE, G_MAXDOUBLE, 0.,
GSF_PARAM_STATIC | G_PARAM_READWRITE));
- g_object_class_install_property (obj_klass, LINE_PROP_ARROWHEAD,
- g_param_spec_boolean ("arrowhead",
- _("Arrow head"),
- _("Whether to add an arrow head at the end of the line"),
- FALSE,
- GSF_PARAM_STATIC | G_PARAM_READWRITE));
- g_object_class_install_property (obj_klass, LINE_PROP_ARROW_SHAPE_A,
- g_param_spec_double ("arrow-shape-a",
- _("Arrow head shape A"),
- _("The distance from tip of arrow head to center"),
- 0, G_MAXDOUBLE, 0.,
- GSF_PARAM_STATIC | G_PARAM_READWRITE));
- g_object_class_install_property (obj_klass, LINE_PROP_ARROW_SHAPE_B,
- g_param_spec_double ("arrow-shape-b",
- _("Arrow head shape B"),
- _("The distance from tip of arrow head to trailing point, measured along shaft"),
- 0, G_MAXDOUBLE, 0.,
- GSF_PARAM_STATIC | G_PARAM_READWRITE));
- g_object_class_install_property (obj_klass, LINE_PROP_ARROW_SHAPE_C,
- g_param_spec_double ("arrow-shape-c",
- _("Arrow head shape C"),
- _("The distance of trailing points from outside edge of shaft"),
- 0, G_MAXDOUBLE, 0.,
- GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, LINE_PROP_START_ARROW,
+ g_param_spec_boxed ("start-arrow",
+ _("Start Arrow"),
+ _("Arrow for line's start"),
+ GO_ARROW_TYPE,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, LINE_PROP_END_ARROW,
+ g_param_spec_boxed ("end-arrow",
+ _("End Arrow"),
+ _("Arrow for line's end"),
+ GO_ARROW_TYPE,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
item_klass->update_bounds = goc_line_update_bounds;
item_klass->distance = goc_line_distance;
diff --git a/goffice/canvas/goc-line.h b/goffice/canvas/goc-line.h
index 085920c..395dc4f 100644
--- a/goffice/canvas/goc-line.h
+++ b/goffice/canvas/goc-line.h
@@ -32,8 +32,8 @@ struct _GocLine {
/* using these to avoid confusion with x0 and others in GocItem */
double startx, starty, endx, endy;
- gboolean arrowhead;
- double headA, headB, headC;
+
+ GOArrow start_arrow, end_arrow;
};
typedef GocStyledItemClass GocLineClass;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]