[goffice] Canvas enhancements from frob.
- From: Jean Bréfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Canvas enhancements from frob.
- Date: Mon, 1 Mar 2010 15:42:46 +0000 (UTC)
commit d7d765e99a5bb7d405953c951c26459d946d2f81
Author: Jean Brefort <jean brefort normalesup org>
Date: Mon Mar 1 16:44:31 2010 +0100
Canvas enhancements from frob.
ChangeLog | 17 ++
NEWS | 3 +
goffice/canvas/Makefile.am | 2 +
goffice/canvas/goc-arc.c | 468 +++++++++++++++++++++++++++++++++++++++
goffice/canvas/goc-arc.h | 51 +++++
goffice/canvas/goc-polyline.c | 132 +++++------
goffice/canvas/goffice-canvas.h | 2 +
goffice/utils/go-bezier.c | 9 +-
goffice/utils/go-bezier.h | 2 +-
po/ChangeLog | 4 +
po/POTFILES.in | 1 +
tests/Makefile.am | 5 +-
tests/shapes-demo.c | 181 +++++++++++++++
13 files changed, 801 insertions(+), 76 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b561a3b..6a1fb1f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2010-03-01 Valek Filippov <frob gnome org>
+
+ * goffice/canvas/Makefile.am: add arc support.
+ * goffice/canvas/goc-arc.c: ditto
+ * goffice/canvas/goc-arc.h: ditto
+ * goffice/canvas/goc-polyline.c (goc_polyline_prepare_draw),
+ (goc_polyline_update_bounds), (goc_polyline_distance),
+ (goc_polyline_draw): enhance polyline implementation.
+ * goffice/canvas/goffice-canvas.h: add arc support.
+ * tests/Makefile.am: new demo.
+ * tests/shapes-demo.c: ditto.
+
+2010-03-01 Jean Brefort <jean brefort normalesup org>
+ * goffice/utils/go-bezier.c (go_bezier_spline_to_cairo): add a flag to
+ support rendering in an RTL canvas.
+ * goffice/utils/go-bezier.h: ditto.
+
2010-02-26 Jean Brefort <jean brefort normalesup org>
* goffice/graph/gog-chart-map.c (make_path_cspline): correctly manage
diff --git a/NEWS b/NEWS
index 3d8da3f..b04fa1c 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,9 @@ Jean:
* Fix crash in GogGuru. [#610435]
* Fix cubic splines with invalid data. [#611163]
+Valek:
+ * Canvas improvements.
+
--------------------------------------------------------------------------
goffice 0.8.0:
diff --git a/goffice/canvas/Makefile.am b/goffice/canvas/Makefile.am
index 0083dca..993131b 100644
--- a/goffice/canvas/Makefile.am
+++ b/goffice/canvas/Makefile.am
@@ -1,6 +1,7 @@
noinst_LTLIBRARIES = libgoffice-canvas.la
libgoffice_canvas_la_SOURCES = \
+ goc-arc.c \
goc-canvas.c \
goc-circle.c \
goc-ellipse.c \
@@ -19,6 +20,7 @@ libgoffice_canvas_la_SOURCES = \
libgoffice_canvas_ladir = $(goffice_include_dir)/canvas
libgoffice_canvas_la_HEADERS = \
+ goc-arc.h \
goc-canvas.h \
goc-circle.h \
goc-ellipse.h \
diff --git a/goffice/canvas/goc-arc.c b/goffice/canvas/goc-arc.c
new file mode 100644
index 0000000..c5a36e2
--- /dev/null
+++ b/goffice/canvas/goc-arc.c
@@ -0,0 +1,468 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * goc-arc.c :
+ *
+ * Copyright (C) 2009 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include <goffice/goffice.h>
+#include <gsf/gsf-impl-utils.h>
+#include <glib/gi18n-lib.h>
+#include <math.h>
+
+/**
+ * SECTION:goc-arc
+ * @short_description: Simple elliptic arc.
+ *
+ * #GocArc implements simple elliptic arc drawing in the canvas. The arc can have
+ * arrows at the start and/or at the end.
+**/
+
+enum {
+ ARC_PROP_0,
+ ARC_PROP_XC,
+ ARC_PROP_YC,
+ ARC_PROP_XR,
+ ARC_PROP_YR,
+ ARC_PROP_ANG1,
+ ARC_PROP_ANG2,
+ ARC_PROP_ROTATION,
+ ARC_PROP_TYPE,
+ ARC_PROP_START_ARROW,
+ ARC_PROP_END_ARROW
+};
+
+enum {
+ ARC_TYPE_ARC,
+ ARC_TYPE_CHORD,
+ ARC_TYPE_PIE
+};
+
+static void
+goc_arc_set_property (GObject *gobject, guint param_id,
+ GValue const *value, GParamSpec *pspec)
+{
+ GocArc *arc = GOC_ARC (gobject);
+
+ switch (param_id) {
+ case ARC_PROP_XC:
+ arc->xc = g_value_get_double (value);
+ break;
+
+ case ARC_PROP_YC:
+ arc->yc = g_value_get_double (value);
+ break;
+
+ case ARC_PROP_XR:
+ arc->xr = g_value_get_double (value);
+ break;
+
+ case ARC_PROP_YR:
+ arc->yr = g_value_get_double (value);
+ break;
+
+ case ARC_PROP_ANG1:
+ arc->ang1 = g_value_get_double (value);
+ break;
+
+ case ARC_PROP_ANG2:
+ arc->ang2 = g_value_get_double (value);
+ break;
+
+ case ARC_PROP_ROTATION:
+ arc->rotation = g_value_get_double (value);
+ break;
+
+ case ARC_PROP_TYPE:
+ arc->type = g_value_get_int (value);
+ break;
+
+ case ARC_PROP_START_ARROW:
+ arc->start_arrow = *((GOArrow *) g_value_peek_pointer (value));
+ break;
+
+ case ARC_PROP_END_ARROW:
+ arc->end_arrow = *((GOArrow *) g_value_peek_pointer (value));
+ break;
+
+ default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
+ return; /* NOTE : RETURN */
+ }
+ goc_item_bounds_changed (GOC_ITEM (gobject));
+}
+
+static void
+goc_arc_get_property (GObject *gobject, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GocArc *arc = GOC_ARC (gobject);
+
+ switch (param_id) {
+ case ARC_PROP_XC:
+ g_value_set_double (value, arc->xc);
+ break;
+
+ case ARC_PROP_YC:
+ g_value_set_double (value, arc->yc);
+ break;
+
+ case ARC_PROP_XR:
+ g_value_set_double (value, arc->xr);
+ break;
+
+ case ARC_PROP_YR:
+ g_value_set_double (value, arc->yr);
+ break;
+
+ case ARC_PROP_ANG1:
+ g_value_set_double (value, arc->ang1);
+ break;
+
+ case ARC_PROP_ANG2:
+ g_value_set_double (value, arc->ang2);
+ break;
+
+ case ARC_PROP_ROTATION:
+ g_value_set_double (value, arc->rotation);
+ break;
+
+ case ARC_PROP_TYPE:
+ g_value_set_int (value, arc->type);
+ break;
+
+ case ARC_PROP_START_ARROW:
+ g_value_set_boxed (value, &arc->start_arrow);
+ break;
+
+ case ARC_PROP_END_ARROW:
+ g_value_set_boxed (value, &arc->end_arrow);
+ break;
+
+ default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
+ return; /* NOTE : RETURN */
+ }
+}
+
+static void
+handle_arrow_bounds (GOArrow const *arrow, GocItem *item)
+{
+ /*
+ * Do not calculate things precisely, just add enough room
+ * in all directions.
+ */
+
+ switch (arrow->typ) {
+ case GO_ARROW_NONE:
+ break;
+ case GO_ARROW_KITE: {
+ double d = hypot (arrow->b, arrow->c);
+ item->x0 -= d;
+ item->x1 += d;
+ item->y0 -= d;
+ item->y1 += d;
+ break;
+ }
+ case GO_ARROW_OVAL: {
+ double d = MAX (arrow->a, arrow->b);
+ item->x0 -= d;
+ item->x1 += d;
+ item->y0 -= d;
+ item->y1 += d;
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+goc_arc_start (GocItem const *item, double x, double y)
+{
+ GocArc *arc = GOC_ARC (item);
+ double x1, y1, s;
+
+ x1 = arc->xr * cos (atan2 (arc->xr / arc->yr * sin (arc->ang1), cos (arc->ang1)));
+ y1 = arc->yr * sin (atan2 (arc->xr / arc->yr * sin (arc->ang1), cos (arc->ang1)));
+ s = sqrt (x1 * x1 + y1 * y1);
+
+ x = arc->xc + s * cos (arc->ang1 - arc->rotation);
+ y = arc->yc - s * sin (arc->ang1 - arc->rotation);
+}
+
+static void
+goc_arc_end (GocItem const *item, double x, double y)
+{
+ GocArc *arc = GOC_ARC (item);
+ double x1, y1, s;
+
+ x1 = arc->xr * cos (atan2 (arc->xr / arc->yr * sin (arc->ang2), cos (arc->ang2)));
+ y1 = arc->yr * sin (atan2 (arc->xr / arc->yr * sin (arc->ang2), cos (arc->ang2)));
+ s = sqrt (x1 * x1 + y1 * y1);
+
+ x = arc->xc + s * cos (arc->ang2 - arc->rotation);
+ y = arc->yc - s * sin (arc->ang2 - arc->rotation);
+}
+
+static gboolean
+goc_arc_prepare_draw (GocItem const *item, cairo_t *cr, gboolean flag)
+{
+ GocArc *arc = GOC_ARC (item);
+ double sign = (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)? -1: 1;
+ double ecc = 1;
+
+ if (0 == arc->xr || 0 == arc->yr || arc->ang1 == arc->ang2)
+ return FALSE;
+
+ if (go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr) ||
+ (arc->type > 0 && go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))) { // anything with stroke or Chord/Pie with fill only
+ cairo_save (cr);
+ if (1 == flag) {
+ goc_group_cairo_transform (item->parent, cr, arc->xc, arc->yc);
+ } else {
+ cairo_translate (cr, arc->xc, arc->yc);
+ }
+ cairo_rotate (cr, arc->rotation);
+ ecc = arc->xr / arc->yr;
+ cairo_scale (cr, arc->xr * sign, arc->yr);
+ cairo_arc_negative (cr, 0., 0., 1., -atan2 (ecc * sin (arc->ang1), cos (arc->ang1)), -atan2 (ecc * sin (arc->ang2), cos (arc->ang2)));
+ if (ARC_TYPE_PIE == arc->type)
+ cairo_line_to (cr, 0., 0.);//arc->xc,arc->yc); // together with next one gives Pie
+ if (arc->type > 0)
+ cairo_close_path (cr); // <-- gives "Chord"
+ cairo_restore (cr);
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+
+static void
+goc_arc_update_bounds (GocItem *item)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, goc_canvas_get_width(item->canvas),goc_canvas_get_height(item->canvas));
+ cr = cairo_create (surface);
+
+ if (goc_arc_prepare_draw (item, cr, 0)) {
+ cairo_stroke_extents (cr, &item->x0, &item->y0, &item->x1, &item->y1);
+ }
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+}
+
+static double
+goc_arc_distance (GocItem *item, double x, double y, GocItem **near_item)
+{
+ GocArc *arc = GOC_ARC (item);
+ GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
+ double tmp_width = 0;
+ double res = 20;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ if (0 == arc->xr || 0 == arc->yr || arc->ang1 == arc->ang2)
+ return res;
+
+ *near_item = item;
+ tmp_width = style->line.width;
+ if (style->line.width < 5){
+ style->line.width = 5;
+ }
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, goc_canvas_get_width(item->canvas),goc_canvas_get_height(item->canvas));
+ cr = cairo_create (surface);
+
+ if (goc_arc_prepare_draw (item, cr, 0)){
+ if (arc->type > 0){
+ if (cairo_in_fill (cr, x, y))
+ res = 0;
+ }
+ if (cairo_in_stroke (cr, x, y))
+ res = 0;
+ }
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+ style->line.width = tmp_width;
+ return res;
+}
+
+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_KITE:
+ 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;
+
+ case GO_ARROW_OVAL:
+ cairo_save (cr);
+ cairo_translate (cr, *endx, *endy);
+ cairo_rotate (cr, phi);
+ cairo_scale (cr, arrow->a, arrow->b);
+ cairo_arc (cr, 0., 0., 1., 0., 2 * M_PI);
+ cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (style->line.color));
+ cairo_fill (cr);
+ cairo_restore (cr);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+goc_arc_draw (GocItem const *item, cairo_t *cr)
+{
+ GocArc *arc = GOC_ARC (item);
+
+ cairo_save(cr);
+ if (goc_arc_prepare_draw (item, cr, 1)) {
+ if (arc->type > 0 && go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
+ cairo_fill_preserve (cr);
+ if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr)){
+ cairo_stroke (cr);
+ } else {
+ cairo_new_path (cr);
+ }
+ }
+ cairo_restore(cr);
+}
+
+static void
+goc_arc_init_style (G_GNUC_UNUSED GocStyledItem *item, GOStyle *style)
+{
+ style->interesting_fields = GO_STYLE_LINE;
+ if (style->line.auto_dash)
+ style->line.dash_type = GO_LINE_SOLID;
+ if (style->line.auto_color)
+ style->line.color = GO_COLOR_BLACK;
+ if (style->line.auto_fore)
+ style->line.fore = 0;
+}
+
+static void
+goc_arc_class_init (GocItemClass *item_klass)
+{
+ GObjectClass *obj_klass = (GObjectClass *) item_klass;
+ GocStyledItemClass *gsi_klass = (GocStyledItemClass *) item_klass;
+
+ gsi_klass->init_style = goc_arc_init_style;
+
+ obj_klass->get_property = goc_arc_get_property;
+ obj_klass->set_property = goc_arc_set_property;
+ g_object_class_install_property (obj_klass, ARC_PROP_XC,
+ g_param_spec_double ("xc",
+ _("xc"),
+ _("The arc center x coordinate"),
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, ARC_PROP_YC,
+ g_param_spec_double ("yc",
+ _("yc"),
+ _("The arc center y coordinate"),
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, ARC_PROP_XR,
+ g_param_spec_double ("xr",
+ _("xr"),
+ _("The arc x radius"),
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, ARC_PROP_YR,
+ g_param_spec_double ("yr",
+ _("yr"),
+ _("The arc y radius"),
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, ARC_PROP_ANG1,
+ g_param_spec_double ("ang1",
+ _("ang1"),
+ _("The arc start angle"),
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, ARC_PROP_ANG2,
+ g_param_spec_double ("ang2",
+ _("ang2"),
+ _("The arc end angle"),
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, ARC_PROP_ROTATION,
+ g_param_spec_double ("rotation",
+ _("Rotation"),
+ _("The rotation around center position"),
+ 0., 2 * M_PI, 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, ARC_PROP_TYPE,
+ g_param_spec_int ("type",
+ _("Type"),
+ _("The type of arc: arc, chord or pie"),
+ 0, 2, 0,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+
+ g_object_class_install_property (obj_klass, ARC_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, ARC_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_arc_update_bounds;
+ item_klass->distance = goc_arc_distance;
+ item_klass->draw = goc_arc_draw;
+}
+
+GSF_CLASS (GocArc, goc_arc,
+ goc_arc_class_init, NULL,
+ GOC_TYPE_STYLED_ITEM)
diff --git a/goffice/canvas/goc-arc.h b/goffice/canvas/goc-arc.h
new file mode 100644
index 0000000..4422031
--- /dev/null
+++ b/goffice/canvas/goc-arc.h
@@ -0,0 +1,51 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * goc-arc.h :
+ *
+ * Copyright (C) 2009 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GOC_ARC_H
+#define GOC_ARC_H
+
+#include <goffice/goffice.h>
+
+G_BEGIN_DECLS
+
+struct _GocArc {
+ GocStyledItem base;
+
+ double rotation;
+ /* part of the ellipse: center, radiuses, angles */
+ double xc, yc, xr, yr, ang1, ang2;
+ int type;
+
+ GOArrow start_arrow, end_arrow;
+};
+
+typedef GocStyledItemClass GocArcClass;
+
+#define GOC_TYPE_ARC (goc_arc_get_type ())
+#define GOC_ARC(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOC_TYPE_ARC, GocArc))
+#define GOC_IS_ARC(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOC_TYPE_ARC))
+
+GType goc_arc_get_type (void);
+
+G_END_DECLS
+
+#endif /* GOC_ARC_H */
diff --git a/goffice/canvas/goc-polyline.c b/goffice/canvas/goc-polyline.c
index c62302a..eb65755 100644
--- a/goffice/canvas/goc-polyline.c
+++ b/goffice/canvas/goc-polyline.c
@@ -91,34 +91,49 @@ goc_polyline_get_property (GObject *gobject, guint param_id,
}
}
-static void
-goc_polyline_update_bounds (GocItem *item)
+static gboolean
+goc_polyline_prepare_draw (GocItem const *item, cairo_t *cr, gboolean flag)
{
GocPolyline *polyline = GOC_POLYLINE (item);
- GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
- double extra_width = style->line.width;
unsigned i;
- if (extra_width <= 0.)
- extra_width = 1.;
+ double sign = (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)? -1: 1;
+
if (polyline->nb_points == 0)
- return;
- /* FIXME: implement the use_spline case */
- item->x0 = item->x1 = polyline->points[0].x;
- item->y0 = item->y1 = polyline->points[0].y;
- for (i = 1; i < polyline->nb_points; i++) {
- if (polyline->points[i].x < item->x0)
- item->x0 = polyline->points[i].x;
- else if (polyline->points[i].x > item->x1)
- item->x1 = polyline->points[i].x;
- if (polyline->points[i].y < item->y0)
- item->y0 = polyline->points[i].y;
- else if (polyline->points[i].y > item->y1)
- item->y1 = polyline->points[i].y;
+ return FALSE;
+
+ if (go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr)) {
+ if (1 == flag) {
+ goc_group_cairo_transform (item->parent, cr, polyline->points[0].x, polyline->points[0].y);
+ cairo_move_to (cr, 0., 0.);
+ } else {
+ cairo_move_to (cr, polyline->points[0].x, polyline->points[0].y);
+ }
+ /* FIXME: implement the use_spline case */
+ for (i = 1; i < polyline->nb_points; i++)
+ cairo_line_to (cr, (polyline->points[i].x - polyline->points[0].x * flag) * sign,
+ polyline->points[i].y - polyline->points[0].y * flag);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+goc_polyline_update_bounds (GocItem *item)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, goc_canvas_get_width(item->canvas),goc_canvas_get_height(item->canvas));
+ cr = cairo_create (surface);
+
+ if (goc_polyline_prepare_draw (item, cr, 0)) {
+ cairo_stroke_extents (cr, &item->x0, &item->y0, &item->x1, &item->y1);
}
- item->x0 -= extra_width;
- item->y0 -= extra_width;
- item->x1 -= extra_width;
- item->y1 -= extra_width;
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
}
static double
@@ -126,63 +141,40 @@ goc_polyline_distance (GocItem *item, double x, double y, GocItem **near_item)
{
GocPolyline *polyline = GOC_POLYLINE (item);
GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
- /* FIXME: implement the use_spline case */
- double extra_width = (style->line.width)? style->line.width /2.: .5;
- double dx, dy, l, startx, starty, x_, y_, t, res;
- unsigned i;
+ double tmp_width = 0;
+ double res = 20;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ if (polyline->nb_points == 0)
+ return res;
*near_item = item;
- /* FIXME: not tested!!! */
- /* first test if the point is inside the polygon */
- startx = polyline->points[0].x;
- starty = polyline->points[0].y;
- res = hypot (polyline->points[polyline->nb_points - 1].x - x, polyline->points[polyline->nb_points - 1].y - y);
- for (i = 0; i < polyline->nb_points; i++) {
- dx = polyline->points[i].x - startx;
- dy = polyline->points[i].y - starty;
- l = hypot (dx, dy);
- x_ = x - startx;
- y_ = y - starty;
- t = (x_ * dx + y_ * dy) / l;
- y = (-x_ * dy + y_ * dx) / l;
- x_ = t;
- *near_item = item;
- if (x < 0. ) {
- t = hypot (x_, y_);
- if (t < res)
- res = t;
- } else if (t <= l) {
- if (y_ < res)
- res = y_;
- }
- startx = polyline->points[i].x;
- starty = polyline->points[i].y;
+ tmp_width = style->line.width;
+ if (style->line.width < 5) {
+ style->line.width = 5;
+ }
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, goc_canvas_get_width (item->canvas), goc_canvas_get_height (item->canvas));
+ cr = cairo_create (surface);
+
+ if (goc_polyline_prepare_draw (item,cr,0)) {
+ if (cairo_in_stroke (cr,x,y))
+ res = 0;
}
- res -= extra_width; /* no need to be more precise */
- return (res > 0.)? res: 0.;
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+ style->line.width = tmp_width;
+ return res;
}
static void
goc_polyline_draw (GocItem const *item, cairo_t *cr)
{
- GocPolyline *polyline = GOC_POLYLINE (item);
- unsigned i;
- double sign = (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)? -1: 1;
- if (polyline->nb_points == 0)
- return;
cairo_save (cr);
- goc_group_cairo_transform (item->parent, cr, polyline->points[0].x, polyline->points[0].y);
- cairo_move_to (cr, 0., 0.);
- /* FIXME: implement the use_spline case */
-
- for (i = 1; i < polyline->nb_points; i++)
- cairo_line_to (cr, (polyline->points[i].x - polyline->points[0].x) * sign,
- polyline->points[i].y - polyline->points[0].y);
-
- if (go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr))
+ if (goc_polyline_prepare_draw (item,cr,1)) {
cairo_stroke (cr);
- else
- cairo_new_path (cr);
+ }
cairo_restore (cr);
}
diff --git a/goffice/canvas/goffice-canvas.h b/goffice/canvas/goffice-canvas.h
index 14b8411..4dd3b2c 100644
--- a/goffice/canvas/goffice-canvas.h
+++ b/goffice/canvas/goffice-canvas.h
@@ -31,6 +31,7 @@ G_BEGIN_DECLS
typedef struct _GocCanvas GocCanvas;
typedef struct _GocItem GocItem;
typedef struct _GocGroup GocGroup;
+typedef struct _GocArc GocArc;
typedef struct _GocLine GocLine;
typedef struct _GocPixbuf GocPixbuf;
typedef struct _GocPolyline GocPolyline;
@@ -57,6 +58,7 @@ G_END_DECLS
#include <goffice/canvas/goc-ellipse.h>
#include <goffice/canvas/goc-graph.h>
#include <goffice/canvas/goc-group.h>
+#include <goffice/canvas/goc-arc.h>
#include <goffice/canvas/goc-line.h>
#include <goffice/canvas/goc-pixbuf.h>
#include <goffice/canvas/goc-polyline.h>
diff --git a/goffice/utils/go-bezier.c b/goffice/utils/go-bezier.c
index b02d1a3..c091b57 100644
--- a/goffice/utils/go-bezier.c
+++ b/goffice/utils/go-bezier.c
@@ -344,15 +344,16 @@ go_bezier_spline_to_path (GOBezierSpline *sp)
* Renders the spline in \a cr
**/
void
-go_bezier_spline_to_cairo (GOBezierSpline *sp, cairo_t *cr)
+go_bezier_spline_to_cairo (GOBezierSpline *sp, cairo_t *cr, gboolean horiz_flip)
{
int i, j;
+ double sign = horiz_flip? -1: 1;
cairo_new_path (cr);
- cairo_move_to (cr, sp->x[0], sp->y[0]);
+ cairo_move_to (cr, sp->x[0] * sign, sp->y[0]);
for (i = j = 1; i < sp->n; i++, j += 3)
- cairo_curve_to (cr, sp->x[j], sp->y[j], sp->x[j+1], sp->y[j+1], sp->x[j+2], sp->y[j+2]);
+ cairo_curve_to (cr, sp->x[j] * sign, sp->y[j], sp->x[j+1] * sign, sp->y[j+1], sp->x[j+2] * sign, sp->y[j+2]);
if (sp->closed) {
- cairo_curve_to (cr, sp->x[j], sp->y[j], sp->x[j+1], sp->y[j+1], sp->x[0], sp->y[0]);
+ cairo_curve_to (cr, sp->x[j] * sign, sp->y[j], sp->x[j+1] * sign, sp->y[j+1], sp->x[0] * sign, sp->y[0]);
cairo_close_path (cr);
}
}
diff --git a/goffice/utils/go-bezier.h b/goffice/utils/go-bezier.h
index 1e55cda..9e5480f 100644
--- a/goffice/utils/go-bezier.h
+++ b/goffice/utils/go-bezier.h
@@ -38,7 +38,7 @@ GOBezierSpline *go_bezier_spline_init (double const *x, double const *y, int n,
void go_bezier_spline_destroy (GOBezierSpline *sp);
GOPath *go_bezier_spline_to_path (GOBezierSpline *sp);
-void go_bezier_spline_to_cairo (GOBezierSpline *sp, cairo_t *cr);
+void go_bezier_spline_to_cairo (GOBezierSpline *sp, cairo_t *cr, gboolean horiz_flip);
G_END_DECLS
diff --git a/po/ChangeLog b/po/ChangeLog
index a4767b2..bc1de81 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,3 +1,7 @@
+2010-03-01 Jean Brefort <jean brefort normalesup org>
+
+ * POTFILES.in: updated files list.
+
2010-02-13 Morten Welinder <terra gnome org>
* Release 0.8.0
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 343b1c6..9c065ca 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -37,6 +37,7 @@ goffice/app/io-context-priv.h
goffice/app/io-context.c
goffice/app/io-context.h
goffice/app/module-plugin-defs.h
+goffice/canvas/goc-arc.c
goffice/canvas/goc-circle.c
goffice/canvas/goc-ellipse.c
goffice/canvas/goc-graph.c
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1739198..02f7b1b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,5 +1,5 @@
if WITH_GTK
-check_PROGRAMS = pie-demo go-demo
+check_PROGRAMS = pie-demo go-demo shapes-demo
endif
include $(top_srcdir)/goffice.mk
@@ -12,5 +12,8 @@ pie_demo_SOURCES = pie-demo.c
go_demo_LDADD = $(GOFFICE_PLUGIN_LIBADD)
go_demo_SOURCES = go-demo.c
+shapes_demo_LDADD = $(GOFFICE_PLUGIN_LIBADD)
+shapes_demo_SOURCES = shapes-demo.c
+
EXTRA_DIST = go-demo.ui
diff --git a/tests/shapes-demo.c b/tests/shapes-demo.c
new file mode 100644
index 0000000..b3e1867
--- /dev/null
+++ b/tests/shapes-demo.c
@@ -0,0 +1,181 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * shapes-demo.c :
+ *
+ * Copyright (C) 2003-2005 Jean Brefort (jean brefort normalesup org)
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <goffice/goffice.h>
+#include <goffice/utils/go-style.h>
+#include <goffice/utils/go-styled-object.h>
+
+
+
+static void
+change_shape (GocItem *goi)
+{
+ GocPoints *points = goc_points_new (4);
+
+ points->points[0].x = 135;
+ points->points[0].y = 150;
+ points->points[1].x = 114;
+ points->points[1].y = 160;
+ points->points[2].x = 110;
+ points->points[2].y = 180;
+ points->points[3].x = 200;
+ points->points[3].y = 200;
+
+ goc_item_set (goi, "points", points, NULL);
+
+}
+
+//
+static void
+my_test (GocCanvas *canvas, GdkEventButton *event, G_GNUC_UNUSED gpointer data) {
+ GocItem *item;
+ double x,y;
+ GOStyle *style;
+
+ g_print ("%.0f %.0f Button: %d\n", event->x, event->y, event->button);
+
+ if (event->window != gtk_layout_get_bin_window (&canvas->base))
+ return;
+
+ x = (canvas->direction == GOC_DIRECTION_RTL)?
+ canvas->scroll_x1 + (canvas->width - event->x) / canvas->pixels_per_unit:
+ canvas->scroll_x1 + event->x / canvas->pixels_per_unit;
+ y = canvas->scroll_y1 + event->y / canvas->pixels_per_unit;
+ item = goc_canvas_get_item_at (canvas, x, y);
+ if (item) {
+ style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
+ if (style->line.color == GO_COLOR_BLACK) {
+ style->line.color = GO_COLOR_RED;
+ } else {
+ style->line.color = GO_COLOR_BLACK;
+ }
+ goc_item_invalidate (item);
+ }
+ goc_canvas_scroll_to (canvas, 10, -10);
+}
+
+static void
+create_shape (GocCanvas *canvas)
+{
+ GocItem *goi;
+ double x = 180, y = 120, w = 50, h = 20;
+
+ goi = goc_item_new (goc_canvas_get_root (canvas), GOC_TYPE_RECTANGLE, NULL);
+ goc_item_set (goi, "width", w, "height", h, "x", x, "y", y, NULL);
+
+
+}
+
+
+static void
+on_quit (GtkObject *object)
+{
+ gtk_object_destroy (object);
+ gtk_main_quit ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window, *box, *hbox, *widget;
+ GocCanvas *canvas;
+ GOStyle *style;
+ /* GError *error; */
+ GocItem *goi, *goi2;
+ double xc = 80.,yc = 150., xr = 30.,yr = 60.,ang1=M_PI*0.45,ang2 = M_PI*1.75;
+ GocPoints *points = goc_points_new (5);
+
+ points->points[0].x = xc + xr * cos (atan2 (xr / yr * sin (ang1), cos (ang1)));
+ points->points[0].y = yc - yr * sin (atan2 (xr / yr * sin (ang1), cos (ang1)));
+ points->points[1].x = 10;
+ points->points[1].y = 40;
+ points->points[2].x = 23;
+ points->points[2].y = 25;
+ points->points[3].x = 120;
+ points->points[3].y = 150;
+ points->points[4].x = xc + xr * cos (atan2 (xr / yr * sin (ang2), cos (ang2)));
+ points->points[4].y = yc - yr * sin (atan2 (xr / yr * sin (ang2), cos (ang2)));
+
+ g_print("Arc: %.0f %.0f %.0f %.0f\n", points->points[0].x, points->points[0].y, points->points[4].x, points->points[4].y);
+
+ gtk_init (&argc, &argv);
+ /* Initialize libgoffice */
+ libgoffice_init ();
+ /* Initialize plugins manager */
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_resize (GTK_WINDOW (window), 300, 340);
+ gtk_window_set_title (GTK_WINDOW (window), "shapes demo");
+ g_signal_connect (window, "destroy", gtk_main_quit, NULL);
+
+ box = gtk_vbox_new (FALSE, 0);
+ hbox = gtk_hbox_new (FALSE, 0);
+ canvas =g_object_new (GOC_TYPE_CANVAS, NULL);
+ g_signal_connect_swapped (canvas, "button-press-event", G_CALLBACK (my_test), canvas);
+
+ goi = goc_item_new(goc_canvas_get_root (canvas), GOC_TYPE_POLYLINE, NULL);
+ goc_item_set (goi, "points", points, NULL);
+ style = go_styled_object_get_style (GO_STYLED_OBJECT (goi));
+ style->line.width = 1;
+ style->line.color = GO_COLOR_BLACK;
+
+ goi2 = goc_item_new (goc_canvas_get_root (canvas), GOC_TYPE_ARC,
+ "xc", xc, "yc", yc, "xr",xr, "yr", yr,
+ "ang1", ang1, "ang2", ang2, NULL);
+ style = go_styled_object_get_style (GO_STYLED_OBJECT (goi2));
+ style->line.width = 3;
+ style->line.color = GO_COLOR_YELLOW;
+
+ goi2 = goc_item_new (goc_canvas_get_root(canvas), GOC_TYPE_ARC,
+ "xc", xc, "yc", yc, "xr", xr, "yr", yr,
+ "ang1", ang1, "ang2", ang2, "rotation", M_PI / 4., NULL);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_QUIT);
+ g_signal_connect_swapped (widget, "clicked", G_CALLBACK (on_quit), window);
+ gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_NEW);
+ g_signal_connect_swapped (widget, "clicked", G_CALLBACK (create_shape), canvas);
+ gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_OPEN);
+ g_signal_connect_swapped (widget, "clicked", G_CALLBACK (change_shape), goi);
+ gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+
+ gtk_box_pack_end (GTK_BOX (box), hbox, FALSE, FALSE, 0);
+
+ widget = gtk_hseparator_new ();
+ gtk_box_pack_end (GTK_BOX (box), widget, FALSE, FALSE, 2);
+
+ gtk_box_pack_end (GTK_BOX (box), GTK_WIDGET(canvas), TRUE, TRUE, 0);
+
+ gtk_container_add (GTK_CONTAINER (window), box);
+ gtk_widget_show_all (GTK_WIDGET (window));
+
+ widget = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
+
+ gtk_main ();
+
+ /* Clean libgoffice stuff */
+ libgoffice_shutdown ();
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]