[goffice] Import arcs and friends from ODF enhanced paths.
- From: Jean BrÃfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Import arcs and friends from ODF enhanced paths.
- Date: Tue, 28 Aug 2012 11:49:13 +0000 (UTC)
commit d1946540c9fb16d0aebb8ae6609c99e70e880d61
Author: Jean Brefort <jean brefort normalesup org>
Date: Tue Aug 28 13:46:24 2012 +0200
Import arcs and friends from ODF enhanced paths.
ChangeLog | 9 ++
goffice/canvas/goc-path.c | 2 +-
goffice/utils/go-path.c | 187 +++++++++++++++++++++++++++++++++++----------
3 files changed, 156 insertions(+), 42 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 3184c6e..00fa187 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2012-08-28 Jean Brefort <jean brefort normalesup org>
+
+ * goffice/canvas/goc-path.c (goc_path_prepare_draw),
+ (goc_path_draw): fixed fill rule usage.
+ * goffice/utils/go-path.c (parse_value), (emit_function_8),
+ (_path_arc), (go_path_arc_degrees), (go_path_arc_full),
+ (go_path_quadrant), (go_path_new_from_odf_enhanced_path): import arcs
+ and friends from ODF enhanced paths.
+
2012-08-27 Jean Brefort <jean brefort normalesup org>
* goffice/utils/go-path.c (skip_spaces), (skip_comma_and_spaces),
diff --git a/goffice/canvas/goc-path.c b/goffice/canvas/goc-path.c
index 0566a3c..f91f90e 100644
--- a/goffice/canvas/goc-path.c
+++ b/goffice/canvas/goc-path.c
@@ -127,7 +127,6 @@ goc_path_prepare_draw (GocItem const *item, cairo_t *cr, gboolean flag)
double rsign = sign;
cairo_save (cr);
- cairo_set_fill_rule (cr, path->fill_rule);
if (1 == flag) {
goc_group_cairo_transform (item->parent, cr, path->x , path->y);
sign = 1;
@@ -203,6 +202,7 @@ goc_path_draw (GocItem const *item, cairo_t *cr)
GocPath *path = GOC_PATH (item);
cairo_save(cr);
+ cairo_set_fill_rule (cr, path->fill_rule? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
if (goc_path_prepare_draw (item, cr, 1)) {
if (path->closed)
go_styled_object_fill (GO_STYLED_OBJECT (item), cr, TRUE);
diff --git a/goffice/utils/go-path.c b/goffice/utils/go-path.c
index f17ca67..6bb2eb2 100644
--- a/goffice/utils/go-path.c
+++ b/goffice/utils/go-path.c
@@ -543,15 +543,6 @@ go_path_arc (GOPath *path,
_ring_wedge (path, cx, cy, rx, ry, -1.0, -1.0, th0, th1, FALSE);
}
-static void
-go_path_arc_degrees (GOPath *path,
- double cx, double cy,
- double rx, double ry,
- double th0, double th1)
-{
- _ring_wedge (path, cx, cy, rx, ry, -1.0, -1.0, th0 * M_PI / 180., th1 * M_PI / 180., FALSE);
-}
-
void
go_path_arc_to (GOPath *path,
double cx, double cy,
@@ -561,15 +552,6 @@ go_path_arc_to (GOPath *path,
_ring_wedge (path, cx, cy, rx, ry, -1.0, -1.0, th0, th1, TRUE);
}
-static void
-go_path_arc_to_degrees (GOPath *path,
- double cx, double cy,
- double rx, double ry,
- double th0, double th1)
-{
- _ring_wedge (path, cx, cy, rx, ry, -1.0, -1.0, th0 * M_PI / 180., th1 * M_PI / 180., TRUE);
-}
-
void
go_path_rectangle (GOPath *path,
double x, double y,
@@ -935,7 +917,7 @@ typedef struct {
GOPath *path;
GHashTable const *variables;
double lastx, lasty;
- gboolean relative;
+ gboolean relative, clockwise, line_to, horiz;
} PathParseState;
static void
@@ -970,11 +952,8 @@ parse_value (PathParseState *state, double *x)
if (*c == '?' || *c == '$') {
char *var;
double *val;
- /* allowed codes are [?,$][a..z]?[0..9]* */
state->src++;
- if (*state->src >= 'a' && *state->src <= 'z')
- state->src++;
- while (*state->src >= '0' && *state->src <= '9')
+ while (*state->src != 0 && *state->src != ' ' && *state->src != ',')
state->src++;
var = g_strndup (c, state->src - c);
if (state->variables == NULL || ((val = g_hash_table_lookup ((GHashTable *) state->variables, var)) == NULL)) {
@@ -1125,7 +1104,7 @@ emit_function_6 (PathParseState *state,
static void
emit_function_8 (PathParseState *state,
- void (*path_func) (GOPath *, double, double, double ,double, double, double, double ,double))
+ void (*path_func) (PathParseState *, double, double, double ,double, double, double, double ,double))
{
double values[8];
@@ -1145,7 +1124,7 @@ emit_function_8 (PathParseState *state,
state->lastx = values[6];
state->lasty = values[7];
}
- path_func (state->path, values[0], values[1], values[2], values[3], values[4], values[5], state->lastx, state->lasty);
+ path_func (state, values[0], values[1], values[2], values[3], values[4], values[5], state->lastx, state->lasty);
}
}
@@ -1174,6 +1153,124 @@ emit_quadratic (PathParseState *state)
}
}
+static void
+_path_arc (PathParseState *state,
+ double cx, double cy,
+ double rx, double ry,
+ double th0, double th1)
+{
+ double th_arc, th, th_delta, t;
+ double x, y;
+ int i, n_segs;
+
+ if (state->line_to)
+ go_path_line_to (state->path, cx + rx * cos (th0), cy + ry * sin (th0));
+ else
+ go_path_move_to (state->path, cx + rx * cos (th0), cy + ry * sin (th0));
+ if (state->clockwise) {
+ while (th1 < th0)
+ th1 += 2 * M_PI;
+ } else {
+ while (th1 > th0)
+ th0 += 2 * M_PI;
+ }
+ th_arc = th1 - th0;
+ n_segs = ceil (fabs (th_arc / (M_PI * 0.5 + 0.001)));
+ th_delta = th_arc / n_segs;
+ t = (8.0 / 3.0) * sin (th_delta * 0.25) * sin (th_delta * 0.25) / sin (th_delta * 0.5);
+ th = th0;
+ for (i = 0; i < n_segs; i++) {
+ x = cx + rx * cos (th + th_delta);
+ y = cy + ry * sin (th + th_delta);
+ go_path_curve_to (state->path,
+ cx + rx * (cos (th) - t * sin (th)),
+ cy + ry * (sin (th) + t * cos (th)),
+ x + rx * t * sin (th + th_delta),
+ y - ry * t * cos (th + th_delta),
+ x, y);
+ th += th_delta;
+ }
+ state->lastx = cx + rx * sin (th1);
+ state->lasty = cy + ry * sin (th1);
+}
+
+static void
+go_path_arc_degrees (PathParseState *state)
+{
+ double values[6];
+
+ skip_spaces (state);
+
+ while (parse_values (state, 6, values)) {
+ if (state->relative) {
+ values[0] += state->lastx;
+ values[1] += state->lasty;
+ }
+ _path_arc (state, values[0], values[1], values[2], values[3],
+ values[4] * M_PI / 180., values[5] * M_PI / 180.);
+ }
+}
+
+static void
+go_path_arc_full (PathParseState *state, double x1, double y1, double x2, double y2,
+ double x3, double y3, double x4, double y4)
+{
+ double cx, cy, rx, ry, th0, th1;
+ cx = (x1 + x2) / 2.;
+ cy = (y1 + y2) / 2;
+ rx = MAX (x1, x2) - cx;
+ ry = MAX (y1, y2) - cy;
+ th0 = atan2 ((y3 - cy) / ry, (x3 - cx) / rx);
+ th1 = atan2 ((y4 - cy) / ry, (x4 - cx) / rx);
+ if (state->clockwise) {
+ /* we need th1 > th0 */
+ while (th1 < th0)
+ th1 += 2 * M_PI;
+ } else {
+ /* we need th1 > th0 */
+ while (th1 > th0)
+ th0 += 2 * M_PI;
+ }
+ _path_arc (state, cx, cy, rx, ry, th0, th1);
+}
+
+static void
+go_path_quadrant (PathParseState *state)
+{
+ double values[2], cx, cy, rx, ry, th0, th1;
+
+ skip_spaces (state);
+
+ while (parse_values (state, 2, values)) {
+ if (state->relative) {
+ values[0] += state->lastx;
+ values[1] += state->lasty;
+ }
+ /* evaluating center and radius */
+ if (state->horiz) {
+ cx = state->lastx;
+ cy = values[1];
+ rx = fabs (values[0] - cx);
+ ry = fabs (state->lasty - cy);
+ } else {
+ cx = values[0];
+ cy = state->lasty;
+ rx = fabs (state->lastx - cx);
+ ry = fabs (values[1] - cy);
+ }
+ /* now the angles */
+ th0 = atan2 (state->lasty - cy, state->lastx - cx);
+ th1 = atan2 (values[1] - cy, values[0] - cx);
+ /* and finally the direction */
+ state->clockwise = (values[1] - cy) * (state->lastx - cx) - (state->lasty - cy) * (values[0] - cx) > 0.;
+ _path_arc (state, cx, cy, rx, ry, th0, th1);
+
+ state->lastx = values[0];
+ state->lasty = values[1];
+ state->horiz = !state->horiz;
+ }
+}
+
/**
* go_path_new_from_svg:
* @src: an SVG path.
@@ -1291,18 +1388,6 @@ go_path_new_from_svg (char const *src)
return state.path;
}
-static void
-go_path_line_arc_to (GOPath *path, double x0, double x1, double x2, double x3,
- double x4, double x5, double x6, double x7)
-{
-}
-
-static void
-go_path_move_arc_to (GOPath *path, double x0, double x1, double x2, double x3,
- double x4, double x5, double x6, double x7)
-{
-}
-
/**
* go_path_new_from_odf_enhanced_path:
* @src: an ODF enhanced path.
@@ -1329,11 +1414,15 @@ go_path_new_from_odf_enhanced_path (char const *src, GHashTable const *variables
switch (*state.src) {
case 'A':
state.src++;
- emit_function_8 (&state, go_path_line_arc_to);
+ state.clockwise = FALSE;
+ state.line_to = TRUE;
+ emit_function_8 (&state, go_path_arc_full);
break;
case 'B':
state.src++;
- emit_function_8 (&state, go_path_move_arc_to);
+ state.clockwise = FALSE;
+ state.line_to = FALSE;
+ emit_function_8 (&state, go_path_arc_full);
break;
case 'C':
state.src++;
@@ -1362,23 +1451,39 @@ go_path_new_from_odf_enhanced_path (char const *src, GHashTable const *variables
break;
case 'T':
state.src++;
- emit_function_6 (&state, go_path_arc_to_degrees);
+ state.clockwise = TRUE;
+ state.line_to = TRUE;
+ go_path_arc_degrees (&state);
break;
case 'U':
state.src++;
- emit_function_6 (&state, go_path_arc_degrees);
+ state.clockwise = TRUE;
+ state.line_to = FALSE;
+ go_path_arc_degrees (&state);
break;
case 'V':
state.src++;
+ state.clockwise = TRUE;
+ state.line_to = FALSE;
+ emit_function_8 (&state, go_path_arc_full);
break;
case 'W':
state.src++;
+ state.clockwise = TRUE;
+ state.line_to = TRUE;
+ emit_function_8 (&state, go_path_arc_full);
break;
case 'X':
+ /* assuming that the horizontal/vertical alternance only applies
+ * when the additional letters are omitted */
state.src++;
+ state.horiz = TRUE;
+ go_path_quadrant (&state);
break;
case 'Y':
state.src++;
+ state.horiz = FALSE;
+ go_path_quadrant (&state);
break;
case 'Z':
state.src++;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]