[goffice] More canvas enhancements.
- From: Jean Bréfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] More canvas enhancements.
- Date: Thu, 4 Mar 2010 12:20:51 +0000 (UTC)
commit 71755a8614c9026d8ec10d6f7b522b0fc4031d6b
Author: Jean Brefort <jean brefort normalesup org>
Date: Thu Mar 4 13:17:00 2010 +0100
More canvas enhancements.
ChangeLog | 12 ++++
goffice/canvas/goc-arc.c | 58 +++++++++-------
goffice/canvas/goc-ellipse.c | 144 +++++++++++++++++++++-------------------
goffice/canvas/goc-rectangle.c | 126 +++++++++++++++++++++--------------
4 files changed, 196 insertions(+), 144 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 7da88fb..e759dbc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2010-03-04 Valek Filippov <frob gnome org>
+
+ * goffice/canvas/goc-arc.c (goc_arc_prepare_draw),
+ (goc_arc_distance), (goc_arc_draw), (goc_arc_init_style): more
+ canvas improvements.
+ * goffice/canvas/goc-ellipse.c (goc_ellipse_prepare_draw),
+ (goc_ellipse_update_bounds), (goc_ellipse_distance),
+ (goc_ellipse_draw), (goc_ellipse_class_init): ditto.
+ * goffice/canvas/goc-rectangle.c (goc_rectangle_prepare_draw),
+ (goc_rectangle_update_bounds), (goc_rectangle_distance),
+ (goc_rectangle_draw), (goc_rectangle_class_init): ditto.
+
2010-03-03 Jean Brefort <jean brefort normalesup org>
* goffice/canvas/goc-line.c (goc_line_distance): fix distance evaluation.
diff --git a/goffice/canvas/goc-arc.c b/goffice/canvas/goc-arc.c
index 1407d1f..0701f4a 100644
--- a/goffice/canvas/goc-arc.c
+++ b/goffice/canvas/goc-arc.c
@@ -231,31 +231,24 @@ goc_arc_prepare_draw (GocItem const *item, cairo_t *cr, gboolean flag)
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;
+ 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);
}
-
- return FALSE;
-
+ 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.); // together with next one gives Pie
+ if (arc->type > 0)
+ cairo_close_path (cr); // gives "Chord"
+ cairo_restore (cr);
+ return TRUE;
}
-
static void
goc_arc_update_bounds (GocItem *item)
{
@@ -295,12 +288,15 @@ goc_arc_distance (GocItem *item, double x, double y, GocItem **near_item)
cr = cairo_create (surface);
if (goc_arc_prepare_draw (item, cr, 0)){
- if (arc->type > 0 && style->fill.type != GO_STYLE_FILL_NONE){
+ // Filled OR both fill and stroke are none
+ if ((arc->type > 0 && style->fill.type != GO_STYLE_FILL_NONE) ||
+ (style->fill.type == GO_STYLE_FILL_NONE && !goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr))){
if (cairo_in_fill (cr, x, y))
res = 0;
}
- if (cairo_in_stroke (cr, x, y))
+ if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr) && cairo_in_stroke (cr, x, y)){
res = 0;
+ }
}
cairo_destroy (cr);
@@ -369,7 +365,7 @@ goc_arc_draw (GocItem const *item, cairo_t *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)){
+ if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr)) {
cairo_stroke (cr);
} else {
cairo_new_path (cr);
@@ -381,13 +377,23 @@ goc_arc_draw (GocItem const *item, cairo_t *cr)
static void
goc_arc_init_style (G_GNUC_UNUSED GocStyledItem *item, GOStyle *style)
{
- style->interesting_fields = GO_STYLE_LINE;
+ GocArc *arc = GOC_ARC(item);
+
+ style->interesting_fields = GO_STYLE_OUTLINE | GO_STYLE_FILL;
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;
+ if (arc->type > 0) {
+ if (style->fill.auto_type)
+ style->fill.type = GO_STYLE_FILL_PATTERN;
+ if (style->fill.auto_fore)
+ style->fill.pattern.fore = GO_COLOR_BLACK;
+ if (style->fill.auto_back)
+ style->fill.pattern.back = GO_COLOR_WHITE;
+ }
}
static void
diff --git a/goffice/canvas/goc-ellipse.c b/goffice/canvas/goc-ellipse.c
index acbcd8f..f824682 100644
--- a/goffice/canvas/goc-ellipse.c
+++ b/goffice/canvas/goc-ellipse.c
@@ -107,19 +107,43 @@ goc_ellipse_get_property (GObject *gobject, guint param_id,
}
}
+static gboolean
+goc_ellipse_prepare_draw (GocItem const *item, cairo_t *cr, gboolean flag)
+{
+ GocEllipse *ellipse = GOC_ELLIPSE (item);
+ double sign = (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)? -1.: 1.;
+
+ if (0 == ellipse->width && 0 == ellipse->height)
+ return FALSE;
+
+ cairo_save(cr);
+ if (1 == flag) {
+ goc_group_cairo_transform (item->parent, cr, ellipse->x + ellipse->width/2., ellipse->y + ellipse->height/2.);
+ } else {
+ cairo_translate (cr, ellipse->x + ellipse->width/2., ellipse->y + ellipse->height/2.);
+ }
+ cairo_rotate (cr, ellipse->rotation);
+ cairo_scale (cr, ellipse->width/2. * sign, ellipse->height/2.);
+ cairo_arc (cr, 0., 0., 1., 0., 2 * M_PI);
+ cairo_restore (cr);
+ return TRUE;
+}
+
static void
goc_ellipse_update_bounds (GocItem *item)
{
- GocEllipse *ellipse = GOC_ELLIPSE (item);
- GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
- /* FIXME: take rotation into account */
- double extra_width = style->line.width /2.;
- if (extra_width <= 0.)
- extra_width = .5;
- item->x0 = ellipse->x - extra_width;
- item->y0 = ellipse->y - extra_width;
- item->x1 = ellipse->x + ellipse->width + extra_width;
- item->y1 = ellipse->y + ellipse->height + extra_width;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1 , 1);
+ cr = cairo_create (surface);
+
+ if (goc_ellipse_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
@@ -127,70 +151,54 @@ goc_ellipse_distance (GocItem *item, double x, double y, GocItem **near_item)
{
GocEllipse *ellipse = GOC_ELLIPSE (item);
GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
- /* FIXME: take rotation into account */
- /* FIXME: we just consider that a point inside the ellipse is at distance 0
- even if the ellipse is not filled */
- double extra_width = (style->line.width)? style->line.width /2.: .5;
- double last = G_MAXDOUBLE, df, d2f, t, cs, sn,
- a = ellipse->width / 2, b = ellipse->height / 2,
- c = a * a - b * b;
- int i;
+ double tmp_width = 0;
+ double res = 20;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ if (0 == ellipse->width && 0 == ellipse->height)
+ return res;
+
*near_item = item;
- x = fabs (x - ellipse->x - a);
- y = fabs (y - ellipse->y - b);
- if (y < DBL_EPSILON) {
- x -= a + extra_width;
- return (x > 0.)? x: 0.;
- }
- if (x < DBL_EPSILON) {
- y -= b + extra_width;
- return (y > 0.)? y: 0.;
+ tmp_width = style->line.width;
+ if (style->line.width < 5){
+ style->line.width = 5;
}
- if (hypot (x / a, y / b) < 1.)
- return 0.;
-
- /* initial value: */
- t = atan2 (y, x);
- /* iterate using the Newton method */
- /* iterate no more than 10 times which should be largely enough
- just a security to avoid an infinite loop if something goes wrong */
- for (i = 0; i < 10; i++) {
- cs = cos (t);
- sn = sin (t);
- df = a * x * sn - b * y * cs - c * cs * sn;
- d2f = a * x * cs + b * y * sn - c * (cs * cs - sn * sn);
- t -= df / d2f;
- if ( last == df || fabs (df) < DBL_EPSILON || fabs (df) >= fabs (last))
- break;
- last = df;
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+ cr = cairo_create (surface);
+
+ if (goc_ellipse_prepare_draw (item, cr, 0)) {
+ // Filled OR both fill and stroke are none
+ if (style->fill.type != GO_STYLE_FILL_NONE ||
+ (style->fill.type == GO_STYLE_FILL_NONE && !goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr))) {
+ if (cairo_in_fill (cr, x, y))
+ res = 0;
+ }
+ if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr) && cairo_in_stroke (cr, x, y)) {
+ res = 0;
+ }
}
- /* evaluate the distance and store in df */
- df = hypot (x - a * cos (t), y - b * sin (t)) - extra_width;
- return (df > 0.)? df: 0.;
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+ style->line.width = tmp_width;
+ return res;
}
static void
goc_ellipse_draw (GocItem const *item, cairo_t *cr)
{
- GocEllipse *ellipse = GOC_ELLIPSE (item);
- double scalex = (ellipse->width > 0.)? ellipse->width / 2.: 1.e-10,
- scaley = (ellipse->height > 0.)? ellipse->height / 2.: 1.e-10;
- double sign = (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)? -1.: 1.;
- cairo_save (cr);
- goc_group_cairo_transform (item->parent, cr, ellipse->x, ellipse->y);
- cairo_translate (cr, scalex * sign, scaley);
- cairo_scale (cr, scalex, scaley);
- cairo_rotate (cr, ellipse->rotation);
- cairo_arc (cr, 0., 0., 1., 0., 2 * M_PI);
- cairo_restore (cr);
- /* Fill the shape */
- if (go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
- cairo_fill_preserve (cr);
- /* Draw the line */
- if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr))
- cairo_stroke (cr);
- else
- cairo_new_path (cr);
+ cairo_save(cr);
+ if (goc_ellipse_prepare_draw (item, cr, 1)) {
+ if (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
@@ -241,12 +249,12 @@ goc_ellipse_class_init (GocItemClass *item_klass)
_("The ellipse height"),
0., G_MAXDOUBLE, 0.,
GSF_PARAM_STATIC | G_PARAM_READWRITE));
-/* g_object_class_install_property (obj_klass, ELLIPSE_PROP_ROTATION,
+ g_object_class_install_property (obj_klass, ELLIPSE_PROP_ROTATION,
g_param_spec_double ("rotation",
_("Rotation"),
_("The rotation around top left position"),
0., 2 * M_PI, 0.,
- GSF_PARAM_STATIC | G_PARAM_READWRITE));*/
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
gsi_klass->init_style = goc_ellipse_init_style;
diff --git a/goffice/canvas/goc-rectangle.c b/goffice/canvas/goc-rectangle.c
index 6c36a8f..6732b6e 100644
--- a/goffice/canvas/goc-rectangle.c
+++ b/goffice/canvas/goc-rectangle.c
@@ -107,19 +107,41 @@ goc_rectangle_get_property (GObject *gobject, guint param_id,
}
}
+static gboolean
+goc_rectangle_prepare_draw (GocItem const *item, cairo_t *cr, gboolean flag)
+{
+ GocRectangle *rect = GOC_RECTANGLE (item);
+
+ if (0 == rect->width && 0 == rect->height)
+ return FALSE;
+
+ cairo_save(cr);
+ if (1 == flag) {
+ goc_group_cairo_transform (item->parent, cr, rect->x, rect->y);
+ } else {
+ cairo_translate (cr, rect->x, rect->y);
+ }
+ cairo_rotate (cr, rect->rotation);
+ cairo_rectangle (cr, 0., 0., (int) rect->width, (int)rect->height);
+ cairo_restore (cr);
+ return TRUE;
+}
+
static void
goc_rectangle_update_bounds (GocItem *item)
{
- GocRectangle *rect = GOC_RECTANGLE (item);
- GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
- /* FIXME: take rotation into account */
- double extra_width = style->line.width /2.;
- if (extra_width <= 0.)
- extra_width = .5;
- item->x0 = rect->x - extra_width;
- item->y0 = rect->y - extra_width;
- item->x1 = rect->x + rect->width + extra_width;
- item->y1 = rect->y + rect->height + extra_width;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1 , 1);
+ cr = cairo_create (surface);
+
+ if (goc_rectangle_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
@@ -127,51 +149,55 @@ goc_rectangle_distance (GocItem *item, double x, double y, GocItem **near_item)
{
GocRectangle *rect = GOC_RECTANGLE (item);
GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
- /* FIXME: take rotation into account */
- double extra_width = (style->line.width)? style->line.width /2.: .5;
- double dx, dy;
- if (x < rect->x - extra_width) {
- dx = rect->x - extra_width - x;
- } else if (x < rect->x + rect->width + extra_width) {
- dx = 0;
- } else {
- dx = x - extra_width - rect->x - rect->width;
+
+ double tmp_width = 0;
+ double res = 20;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ if (0 == rect->width && 0 == rect->height)
+ return res;
+
+ *near_item = item;
+ tmp_width = style->line.width;
+ if (style->line.width < 5){
+ style->line.width = 5;
}
- if (y < rect->y - extra_width) {
- dy = rect->y - extra_width - y;
- } else if (y < rect->y + rect->height + extra_width) {
- dy = 0;
- } else {
- dy = y - extra_width - rect->y - rect->height;
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+ cr = cairo_create (surface);
+
+ if (goc_rectangle_prepare_draw (item, cr, 0)) {
+ // Filled OR both fill and stroke are none
+ if (style->fill.type != GO_STYLE_FILL_NONE ||
+ (style->fill.type == GO_STYLE_FILL_NONE && !goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr))) {
+ if (cairo_in_fill (cr, x, y))
+ res = 0;
+ }
+ if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr) && cairo_in_stroke (cr, x, y)) {
+ res = 0;
+ }
}
- *near_item = item;
- return hypot (dx, dy);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+ style->line.width = tmp_width;
+ return res;
}
static void
goc_rectangle_draw (GocItem const *item, cairo_t *cr)
{
- GocRectangle *rect = GOC_RECTANGLE (item);
- double hoffs, voffs = ceil (go_styled_object_get_style (GO_STYLED_OBJECT (item))->line.width);
- if (voffs <= 0.)
- voffs = 1.;
- hoffs = ((int) voffs & 1)? .5: 0.;
- voffs = hoffs;
- if (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)
- hoffs += (int) rect->width;
- cairo_save (cr);
- goc_group_cairo_transform (item->parent, cr, hoffs + (int) rect->x, voffs + (int) rect->y);
- cairo_rotate (cr, rect->rotation);
- cairo_rectangle (cr, 0., 0., (int) rect->width, (int)rect->height);
- cairo_restore (cr);
- /* Fill the shape */
- if (go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
- cairo_fill_preserve (cr);
- /* Draw the line */
- if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr))
- cairo_stroke (cr);
- else
- cairo_new_path (cr);
+ cairo_save(cr);
+ if (goc_rectangle_prepare_draw (item, cr, 1)) {
+ if (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
@@ -222,12 +248,12 @@ goc_rectangle_class_init (GocItemClass *item_klass)
_("The rectangle height"),
0., G_MAXDOUBLE, 0.,
GSF_PARAM_STATIC | G_PARAM_READWRITE));
-/* g_object_class_install_property (obj_klass, RECT_PROP_ROTATION,
+ g_object_class_install_property (obj_klass, RECT_PROP_ROTATION,
g_param_spec_double ("rotation",
_("Rotation"),
_("The rotation around top left position"),
0., 2 * M_PI, 0.,
- GSF_PARAM_STATIC | G_PARAM_READWRITE));*/
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
gsi_klass->init_style = goc_rectangle_init_style;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]