[lasem] svg_view: move cairo path code to lsmcairo.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [lasem] svg_view: move cairo path code to lsmcairo.
- Date: Mon, 22 Oct 2012 15:40:35 +0000 (UTC)
commit 7a2d820d38fa2f3968f7d6acf9dc3e78d0504786
Author: Emmanuel Pacaud <emmanuel gnome org>
Date: Mon Oct 22 17:40:13 2012 +0200
svg_view: move cairo path code to lsmcairo.
src/lsmcairo.c | 422 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/lsmcairo.h | 11 ++
src/lsmsvgview.c | 433 +-----------------------------------------------------
3 files changed, 439 insertions(+), 427 deletions(-)
---
diff --git a/src/lsmcairo.c b/src/lsmcairo.c
index 15d2f37..980d951 100644
--- a/src/lsmcairo.c
+++ b/src/lsmcairo.c
@@ -26,9 +26,431 @@
#include <lsmcairo.h>
#include <lsmsvgenums.h>
#include <lsmutils.h>
+#include <lsmstr.h>
#include <math.h>
#include <string.h>
+typedef struct {
+ cairo_t *cr;
+ char *ptr;
+ char last_command;
+ double last_cp_x;
+ double last_cp_y;
+ double values[7];
+} LsmSvgPathContext;
+
+/*
+ * Code for:
+ *
+ * _calc_angle
+ * _cairo_elliptical_arc
+ * _cairo_quadratic_curve_to
+ * _emit_smooth_curve
+ * _emit_smooth_quadratic_curve
+ *
+ * is adapted from the goocanvas library (goocanvasutils.c)
+ *
+ * GooCanvas. Copyright (C) 2005 Damon Chaplin.
+ */
+
+void
+lsm_cairo_quadratic_curve_to (cairo_t *cr, double x1, double y1, double x, double y)
+{
+ double x0, y0, xx1, yy1, xx2, yy2;
+
+ cairo_get_current_point (cr, &x0, &y0);
+
+ /* We need to convert the quadratic into a cubic bezier. */
+
+ xx1 = x0 + (x1 - x0) * 2.0 / 3.0;
+ yy1 = y0 + (y1 - y0) * 2.0 / 3.0;
+
+ xx2 = xx1 + (x - x0) / 3.0;
+ yy2 = yy1 + (y - y0) / 3.0;
+
+ cairo_curve_to (cr, xx1, yy1, xx2, yy2, x, y);
+}
+
+void
+lsm_cairo_rel_quadratic_curve_to (cairo_t *cr, double dx1, double dy1, double dx, double dy)
+{
+ double x0, y0;
+
+ cairo_get_current_point (cr, &x0, &y0);
+ lsm_cairo_quadratic_curve_to (cr, x0 + dx1, y0 + dy1, x0 + dx, y0 + dy);
+}
+
+static double
+_calc_angle (double ux, double uy, double vx, double vy)
+{
+ double top, u_magnitude, v_magnitude, angle_cos, angle;
+
+ top = ux * vx + uy * vy;
+ u_magnitude = sqrt (ux * ux + uy * uy);
+ v_magnitude = sqrt (vx * vx + vy * vy);
+ angle_cos = top / (u_magnitude * v_magnitude);
+
+ /* We check if the cosine is slightly out-of-bounds. */
+ if (angle_cos >= 1.0)
+ angle = 0.0;
+ if (angle_cos <= -1.0)
+ angle = M_PI;
+ else
+ angle = acos (angle_cos);
+
+ if (ux * vy - uy * vx < 0)
+ angle = - angle;
+
+ return angle;
+}
+
+void
+lsm_cairo_elliptical_arc (cairo_t *cairo, double rx, double ry, double x_axis_rotation,
+ gboolean large_arc_flag, gboolean sweep_flag, double x, double y)
+{
+ double x1, y1, x2, y2, lambda;
+ double v1, v2, angle, angle_sin, angle_cos, x11, y11;
+ double rx_squared, ry_squared, x11_squared, y11_squared, top, bottom;
+ double c, cx1, cy1, cx, cy, start_angle, angle_delta;
+
+ cairo_get_current_point (cairo, &x1, &y1);
+
+ x2 = x;
+ y2 = y;
+
+ /* If the endpoints are exactly the same, just return (see SVG spec). */
+ if (x1 == x2 && y1 == y2)
+ return;
+
+ /* If either rx or ry is 0, do a simple lineto (see SVG spec). */
+ if (rx == 0.0 || ry == 0.0)
+ {
+ cairo_line_to (cairo, x2, y2);
+ return;
+ }
+
+ /* Calculate x1' and y1' (as per SVG implementation notes). */
+ v1 = (x1 - x2) / 2.0;
+ v2 = (y1 - y2) / 2.0;
+
+ angle = x_axis_rotation * (M_PI / 180.0);
+ angle_sin = sin (angle);
+ angle_cos = cos (angle);
+
+ x11 = (angle_cos * v1) + (angle_sin * v2);
+ y11 = - (angle_sin * v1) + (angle_cos * v2);
+
+ /* Ensure rx and ry are positive and large enough. */
+ rx = rx > 0.0 ? rx : - rx;
+ ry = ry > 0.0 ? ry : - ry;
+ lambda = (x11 * x11) / (rx * rx) + (y11 * y11) / (ry * ry);
+ if (lambda > 1.0)
+ {
+ gdouble square_root = sqrt (lambda);
+ rx *= square_root;
+ ry *= square_root;
+ }
+
+ /* Calculate cx' and cy'. */
+ rx_squared = rx * rx;
+ ry_squared = ry * ry;
+ x11_squared = x11 * x11;
+ y11_squared = y11 * y11;
+
+ top = (rx_squared * ry_squared) - (rx_squared * y11_squared)
+ - (ry_squared * x11_squared);
+ if (top < 0.0)
+ {
+ c = 0.0;
+ }
+ else
+ {
+ bottom = (rx_squared * y11_squared) + (ry_squared * x11_squared);
+ c = sqrt (top / bottom);
+ }
+
+ if (large_arc_flag == sweep_flag)
+ c = - c;
+
+ cx1 = c * ((rx * y11) / ry);
+ cy1 = c * (- (ry * x11) / rx);
+
+ /* Calculate cx and cy. */
+ cx = (angle_cos * cx1) - (angle_sin * cy1) + (x1 + x2) / 2;
+ cy = (angle_sin * cx1) + (angle_cos * cy1) + (y1 + y2) / 2;
+
+ /* Calculate the start and end angles. */
+ v1 = (x11 - cx1) / rx;
+ v2 = (y11 - cy1) / ry;
+
+ start_angle = _calc_angle (1, 0, v1, v2);
+ angle_delta = _calc_angle (v1, v2, (-x11 - cx1) / rx, (-y11 - cy1) / ry);
+
+ if (sweep_flag == 0 && angle_delta > 0.0)
+ angle_delta -= 2 * M_PI;
+ else if (sweep_flag == 1 && angle_delta < 0.0)
+ angle_delta += 2 * M_PI;
+
+ /* Now draw the arc. */
+ cairo_save (cairo);
+ cairo_translate (cairo, cx, cy);
+ cairo_rotate (cairo, angle);
+ cairo_scale (cairo, rx, ry);
+
+ if (angle_delta > 0.0)
+ cairo_arc (cairo, 0.0, 0.0, 1.0,
+ start_angle, start_angle + angle_delta);
+ else
+ cairo_arc_negative (cairo, 0.0, 0.0, 1.0,
+ start_angle, start_angle + angle_delta);
+
+ cairo_restore (cairo);
+}
+
+void
+lsm_cairo_rel_elliptical_arc (cairo_t *cairo, double rx, double ry, double x_axis_rotation,
+ gboolean large_arc_flag, gboolean sweep_flag, double dx, double dy)
+{
+ double x, y;
+
+ cairo_get_current_point (cairo, &x, &y);
+
+ lsm_cairo_elliptical_arc (cairo, rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, x +dx ,y + dy);
+}
+
+void
+lsm_cairo_vertical (cairo_t *cairo, double y)
+{
+ double x0, y0;
+
+ cairo_get_current_point (cairo, &x0, &y0);
+ cairo_line_to (cairo, x0, y);
+}
+
+void
+lsm_cairo_rel_vertical (cairo_t *cairo, double dy)
+{
+ double x0, y0;
+
+ cairo_get_current_point (cairo, &x0, &y0);
+ cairo_line_to (cairo, x0, y0 + dy);
+}
+
+void
+lsm_cairo_horizontal (cairo_t *cairo, double x)
+{
+ double x0, y0;
+
+ cairo_get_current_point (cairo, &x0, &y0);
+ cairo_line_to (cairo, x, y0);
+}
+
+void
+lsm_cairo_rel_horizontal (cairo_t *cairo, double dx)
+{
+ double x0, y0;
+
+ cairo_get_current_point (cairo, &x0, &y0);
+ cairo_line_to (cairo, x0 + dx, y0);
+}
+
+static void
+_emit_function_1 (LsmSvgPathContext *ctxt,
+ void (*cairo_func) (cairo_t *, double))
+{
+ while (lsm_str_parse_double_list (&ctxt->ptr, 1, ctxt->values) == 1)
+ cairo_func (ctxt->cr, ctxt->values[0]);
+}
+
+static void
+_emit_function_2 (LsmSvgPathContext *ctxt,
+ void (*cairo_func_a) (cairo_t *, double, double),
+ void (*cairo_func_b) (cairo_t *, double, double))
+{
+
+ if (lsm_str_parse_double_list (&ctxt->ptr, 2, ctxt->values) == 2) {
+ cairo_func_a (ctxt->cr, ctxt->values[0], ctxt->values[1]);
+
+ /* Why oh why does the specification say Line is implied here ? */
+
+ while (lsm_str_parse_double_list (&ctxt->ptr, 2, ctxt->values) == 2)
+ cairo_func_b (ctxt->cr, ctxt->values[0], ctxt->values[1]);
+ }
+}
+
+static void
+_emit_function_4 (LsmSvgPathContext *ctxt,
+ void (*cairo_func) (cairo_t *, double, double, double, double))
+{
+ while (lsm_str_parse_double_list (&ctxt->ptr, 4, ctxt->values) == 4)
+ cairo_func (ctxt->cr, ctxt->values[0], ctxt->values[1], ctxt->values[2], ctxt->values[3]);
+}
+
+static void
+_emit_smooth_curve (LsmSvgPathContext *ctxt, gboolean relative)
+{
+ double x, y;
+ double x0, y0;
+
+ cairo_get_current_point (ctxt->cr, &x0, &y0);
+
+ switch (ctxt->last_command) {
+ case 'C':
+ x = 2 * x0 - ctxt->values[2];
+ y = 2 * y0 - ctxt->values[3];
+ break;
+ case 'c':
+ x = 2 * x0 - (ctxt->values[2] + x0 - ctxt->values[4]);
+ y = 2 * y0 - (ctxt->values[3] + y0 - ctxt->values[5]);
+ break;
+ case 'S':
+ x = 2 * x0 - ctxt->values[0];
+ y = 2 * y0 - ctxt->values[1];
+ break;
+ case 's':
+ x = 2 * x0 - (ctxt->values[0] + x0 - ctxt->values[2]);
+ y = 2 * y0 - (ctxt->values[1] + y0 - ctxt->values[3]);
+ break;
+ default: x = x0; y = y0; break;
+ }
+
+ while (lsm_str_parse_double_list (&ctxt->ptr, 4, ctxt->values) == 4) {
+ if (relative) {
+ cairo_get_current_point (ctxt->cr, &x0, &y0);
+ cairo_curve_to (ctxt->cr,
+ x, y,
+ x0 + ctxt->values[0], y0 + ctxt->values[1],
+ x0 + ctxt->values[2], y0 + ctxt->values[3]);
+ x = 2 * (x0 + ctxt->values[2]) - (x0 + ctxt->values[0]);
+ y = 2 * (y0 + ctxt->values[3]) - (y0 + ctxt->values[1]);
+ } else {
+ cairo_curve_to (ctxt->cr, x, y,
+ ctxt->values[0], ctxt->values[1], ctxt->values[2], ctxt->values[3]);
+ x = 2 * ctxt->values[2] - ctxt->values[0];
+ y = 2 * ctxt->values[3] - ctxt->values[1];
+ }
+ }
+}
+
+static void
+_emit_smooth_quadratic_curve (LsmSvgPathContext *ctxt, gboolean relative)
+{
+ double x, y;
+ double x0, y0;
+
+ cairo_get_current_point (ctxt->cr, &x0, &y0);
+
+ switch (ctxt->last_command) {
+ case 'Q':
+ ctxt->last_cp_x = ctxt->values[0];
+ ctxt->last_cp_y = ctxt->values[1];
+ break;
+ case 'q':
+ ctxt->last_cp_x = ctxt->values[0] + x0 - ctxt->values[2];
+ ctxt->last_cp_y = ctxt->values[1] + y0 - ctxt->values[3];
+ break;
+ case 'T':
+ case 't':
+ break;
+ default: ctxt->last_cp_x = x0; ctxt->last_cp_y = y0; break;
+ }
+
+ while (lsm_str_parse_double_list (&ctxt->ptr, 2, ctxt->values) == 2) {
+ x = 2 * x0 - ctxt->last_cp_x;
+ y = 2 * y0 - ctxt->last_cp_y;
+ if (relative) {
+ cairo_get_current_point (ctxt->cr, &x0, &y0);
+ lsm_cairo_quadratic_curve_to (ctxt->cr, x, y, x0 + ctxt->values[0], y0 + ctxt->values[1]);
+ } else {
+ lsm_cairo_quadratic_curve_to (ctxt->cr, x, y, ctxt->values[0], ctxt->values[1]);
+ }
+ ctxt->last_cp_x = x;
+ ctxt->last_cp_y = y;
+ cairo_get_current_point (ctxt->cr, &x0, &y0);
+ }
+}
+
+static void
+_emit_function_6 (LsmSvgPathContext *ctxt,
+ void (*cairo_func) (cairo_t *, double, double, double ,double, double, double))
+{
+ while (lsm_str_parse_double_list (&ctxt->ptr, 6, ctxt->values) == 6)
+ cairo_func (ctxt->cr, ctxt->values[0], ctxt->values[1], ctxt->values[2],
+ ctxt->values[3], ctxt->values[4], ctxt->values[5]);
+}
+
+static void
+_emit_function_7 (LsmSvgPathContext *ctxt,
+ void (*cairo_func) (cairo_t *, double, double, double ,gboolean, gboolean, double, double))
+{
+ while (lsm_str_parse_double_list (&ctxt->ptr, 7, ctxt->values) == 7)
+ cairo_func (ctxt->cr, ctxt->values[0], ctxt->values[1], ctxt->values[2],
+ ctxt->values[3], ctxt->values[4], ctxt->values[5],
+ ctxt->values[6]);
+}
+
+void
+lsm_cairo_emit_svg_path (cairo_t *cr, char const *path)
+{
+ LsmSvgPathContext ctxt;
+
+ g_return_if_fail (cr != NULL);
+
+ if (path == NULL)
+ return;
+
+ ctxt.cr = cr;
+ ctxt.ptr = (char *) path;
+ ctxt.last_command = '\0';
+ cairo_get_current_point (cr,
+ &ctxt.values[0],
+ &ctxt.values[1]);
+ ctxt.values[2] = ctxt.values[4] = ctxt.values[0];
+ ctxt.values[3] = ctxt.values[5] = ctxt.values[1];
+
+ lsm_str_skip_spaces (&ctxt.ptr);
+
+ while (*ctxt.ptr != '\0') {
+ char command;
+
+ command = *ctxt.ptr;
+ ctxt.ptr++;
+ lsm_str_skip_spaces (&ctxt.ptr);
+
+ if (!cairo_has_current_point (cr)) {
+ cairo_move_to (cr, 0, 0);
+ ctxt.values[2] = ctxt.values[4] = ctxt.values[0] = 0;
+ ctxt.values[3] = ctxt.values[5] = ctxt.values[1] = 0;
+ }
+
+ switch (command) {
+ case 'M': _emit_function_2 (&ctxt, cairo_move_to, cairo_line_to); break;
+ case 'm': _emit_function_2 (&ctxt, cairo_rel_move_to, cairo_rel_line_to); break;
+ case 'L': _emit_function_2 (&ctxt, cairo_line_to, cairo_line_to); break;
+ case 'l': _emit_function_2 (&ctxt, cairo_rel_line_to, cairo_rel_line_to); break;
+ case 'C': _emit_function_6 (&ctxt, cairo_curve_to); break;
+ case 'c': _emit_function_6 (&ctxt, cairo_rel_curve_to); break;
+ case 'S': _emit_smooth_curve (&ctxt, FALSE); break;
+ case 's': _emit_smooth_curve (&ctxt, TRUE); break;
+ case 'V': _emit_function_1 (&ctxt, lsm_cairo_vertical); break;
+ case 'v': _emit_function_1 (&ctxt, lsm_cairo_rel_vertical); break;
+ case 'H': _emit_function_1 (&ctxt, lsm_cairo_horizontal); break;
+ case 'h': _emit_function_1 (&ctxt, lsm_cairo_rel_horizontal); break;
+ case 'Q': _emit_function_4 (&ctxt, lsm_cairo_quadratic_curve_to); break;
+ case 'q': _emit_function_4 (&ctxt, lsm_cairo_rel_quadratic_curve_to); break;
+ case 'T': _emit_smooth_quadratic_curve (&ctxt, FALSE); break;
+ case 't': _emit_smooth_quadratic_curve (&ctxt, TRUE); break;
+ case 'A': _emit_function_7 (&ctxt, lsm_cairo_elliptical_arc); break;
+ case 'a': _emit_function_7 (&ctxt, lsm_cairo_rel_elliptical_arc); break;
+ case 'Z':
+ case 'z': cairo_close_path (cr); break;
+ default: break;
+ }
+
+ ctxt.last_command = command;
+ }
+}
+
void
lsm_cairo_box_user_to_device (cairo_t *cairo, LsmBox *to, const LsmBox *from)
{
diff --git a/src/lsmcairo.h b/src/lsmcairo.h
index 6df3363..d6f895b 100644
--- a/src/lsmcairo.h
+++ b/src/lsmcairo.h
@@ -30,6 +30,17 @@
G_BEGIN_DECLS
+void lsm_cairo_quadratic_curve_to (cairo_t *cr, double x1, double y1, double x, double y);
+void lsm_cairo_rel_quadratic_curve_to (cairo_t *cr, double dx1, double dy1, double dx, double dy);
+void lsm_cairo_elliptical_arc (cairo_t *cairo, double rx, double ry, double x_axis_rotation,
+ gboolean large_arc_flag, gboolean sweep_flag, double x, double y);
+void lsm_cairo_rel_elliptical_arc (cairo_t *cairo, double rx, double ry, double x_axis_rotation,
+ gboolean large_arc_flag, gboolean sweep_flag, double dx, double dy);
+void lsm_cairo_vertical (cairo_t *cairo, double y);
+void lsm_cairo_rel_vertical (cairo_t *cairo, double dy);
+void lsm_cairo_horizontal (cairo_t *cairo, double x);
+void lsm_cairo_rel_horizontal (cairo_t *cairo, double dx);
+void lsm_cairo_emit_svg_path (cairo_t *cr, char const *path);
void lsm_cairo_box_user_to_device (cairo_t *cairo, LsmBox *to, const LsmBox *from);
void lsm_cairo_box_device_to_user (cairo_t *cairo, LsmBox *to, const LsmBox *from);
void lsm_cairo_set_source_pixbuf (cairo_t *cairo, const GdkPixbuf *pixbuf,
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 8b22f2b..1123656 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -347,427 +347,6 @@ lsm_svg_view_create_surface_pattern (LsmSvgView *view,
return TRUE;
}
-typedef struct {
- cairo_t *cr;
- char *ptr;
- char last_command;
- double last_cp_x;
- double last_cp_y;
- double values[7];
-} LsmSvgPathContext;
-
-/*
- * Code for:
- *
- * _calc_angle
- * _cairo_elliptical_arc
- * _cairo_quadratic_curve_to
- * _emit_smooth_curve
- * _emit_smooth_quadratic_curve
- *
- * is adapted from the goocanvas library (goocanvasutils.c)
- *
- * GooCanvas. Copyright (C) 2005 Damon Chaplin.
- */
-
-static void
-_cairo_quadratic_curve_to (cairo_t *cr, double x1, double y1, double x, double y)
-{
- double x0, y0, xx1, yy1, xx2, yy2;
-
- cairo_get_current_point (cr, &x0, &y0);
-
- /* We need to convert the quadratic into a cubic bezier. */
-
- xx1 = x0 + (x1 - x0) * 2.0 / 3.0;
- yy1 = y0 + (y1 - y0) * 2.0 / 3.0;
-
- xx2 = xx1 + (x - x0) / 3.0;
- yy2 = yy1 + (y - y0) / 3.0;
-
- cairo_curve_to (cr, xx1, yy1, xx2, yy2, x, y);
-}
-
-static void
-_cairo_rel_quadratic_curve_to (cairo_t *cr, double dx1, double dy1, double dx, double dy)
-{
- double x0, y0;
-
- cairo_get_current_point (cr, &x0, &y0);
- _cairo_quadratic_curve_to (cr, x0 + dx1, y0 + dy1, x0 + dx, y0 + dy);
-}
-
-static double
-_calc_angle (double ux, double uy, double vx, double vy)
-{
- double top, u_magnitude, v_magnitude, angle_cos, angle;
-
- top = ux * vx + uy * vy;
- u_magnitude = sqrt (ux * ux + uy * uy);
- v_magnitude = sqrt (vx * vx + vy * vy);
- angle_cos = top / (u_magnitude * v_magnitude);
-
- /* We check if the cosine is slightly out-of-bounds. */
- if (angle_cos >= 1.0)
- angle = 0.0;
- if (angle_cos <= -1.0)
- angle = M_PI;
- else
- angle = acos (angle_cos);
-
- if (ux * vy - uy * vx < 0)
- angle = - angle;
-
- return angle;
-}
-
-static void
-_cairo_elliptical_arc (cairo_t *cairo, double rx, double ry, double x_axis_rotation,
- gboolean large_arc_flag, gboolean sweep_flag, double x, double y)
-{
- double x1, y1, x2, y2, lambda;
- double v1, v2, angle, angle_sin, angle_cos, x11, y11;
- double rx_squared, ry_squared, x11_squared, y11_squared, top, bottom;
- double c, cx1, cy1, cx, cy, start_angle, angle_delta;
-
- cairo_get_current_point (cairo, &x1, &y1);
-
- x2 = x;
- y2 = y;
-
- /* If the endpoints are exactly the same, just return (see SVG spec). */
- if (x1 == x2 && y1 == y2)
- return;
-
- /* If either rx or ry is 0, do a simple lineto (see SVG spec). */
- if (rx == 0.0 || ry == 0.0)
- {
- cairo_line_to (cairo, x2, y2);
- return;
- }
-
- /* Calculate x1' and y1' (as per SVG implementation notes). */
- v1 = (x1 - x2) / 2.0;
- v2 = (y1 - y2) / 2.0;
-
- angle = x_axis_rotation * (M_PI / 180.0);
- angle_sin = sin (angle);
- angle_cos = cos (angle);
-
- x11 = (angle_cos * v1) + (angle_sin * v2);
- y11 = - (angle_sin * v1) + (angle_cos * v2);
-
- /* Ensure rx and ry are positive and large enough. */
- rx = rx > 0.0 ? rx : - rx;
- ry = ry > 0.0 ? ry : - ry;
- lambda = (x11 * x11) / (rx * rx) + (y11 * y11) / (ry * ry);
- if (lambda > 1.0)
- {
- gdouble square_root = sqrt (lambda);
- rx *= square_root;
- ry *= square_root;
- }
-
- /* Calculate cx' and cy'. */
- rx_squared = rx * rx;
- ry_squared = ry * ry;
- x11_squared = x11 * x11;
- y11_squared = y11 * y11;
-
- top = (rx_squared * ry_squared) - (rx_squared * y11_squared)
- - (ry_squared * x11_squared);
- if (top < 0.0)
- {
- c = 0.0;
- }
- else
- {
- bottom = (rx_squared * y11_squared) + (ry_squared * x11_squared);
- c = sqrt (top / bottom);
- }
-
- if (large_arc_flag == sweep_flag)
- c = - c;
-
- cx1 = c * ((rx * y11) / ry);
- cy1 = c * (- (ry * x11) / rx);
-
- /* Calculate cx and cy. */
- cx = (angle_cos * cx1) - (angle_sin * cy1) + (x1 + x2) / 2;
- cy = (angle_sin * cx1) + (angle_cos * cy1) + (y1 + y2) / 2;
-
- /* Calculate the start and end angles. */
- v1 = (x11 - cx1) / rx;
- v2 = (y11 - cy1) / ry;
-
- start_angle = _calc_angle (1, 0, v1, v2);
- angle_delta = _calc_angle (v1, v2, (-x11 - cx1) / rx, (-y11 - cy1) / ry);
-
- if (sweep_flag == 0 && angle_delta > 0.0)
- angle_delta -= 2 * M_PI;
- else if (sweep_flag == 1 && angle_delta < 0.0)
- angle_delta += 2 * M_PI;
-
- /* Now draw the arc. */
- cairo_save (cairo);
- cairo_translate (cairo, cx, cy);
- cairo_rotate (cairo, angle);
- cairo_scale (cairo, rx, ry);
-
- if (angle_delta > 0.0)
- cairo_arc (cairo, 0.0, 0.0, 1.0,
- start_angle, start_angle + angle_delta);
- else
- cairo_arc_negative (cairo, 0.0, 0.0, 1.0,
- start_angle, start_angle + angle_delta);
-
- cairo_restore (cairo);
-}
-
-static void
-_cairo_rel_elliptical_arc (cairo_t *cairo, double rx, double ry, double x_axis_rotation,
- gboolean large_arc_flag, gboolean sweep_flag, double dx, double dy)
-{
- double x, y;
-
- cairo_get_current_point (cairo, &x, &y);
-
- _cairo_elliptical_arc (cairo, rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, x +dx ,y + dy);
-}
-
-static void
-_cairo_vertical (cairo_t *cairo, double y)
-{
- double x0, y0;
-
- cairo_get_current_point (cairo, &x0, &y0);
- cairo_line_to (cairo, x0, y);
-}
-
-static void
-_cairo_rel_vertical (cairo_t *cairo, double dy)
-{
- double x0, y0;
-
- cairo_get_current_point (cairo, &x0, &y0);
- cairo_line_to (cairo, x0, y0 + dy);
-}
-
-static void
-_cairo_horizontal (cairo_t *cairo, double x)
-{
- double x0, y0;
-
- cairo_get_current_point (cairo, &x0, &y0);
- cairo_line_to (cairo, x, y0);
-}
-
-static void
-_cairo_rel_horizontal (cairo_t *cairo, double dx)
-{
- double x0, y0;
-
- cairo_get_current_point (cairo, &x0, &y0);
- cairo_line_to (cairo, x0 + dx, y0);
-}
-
-static void
-_emit_function_1 (LsmSvgPathContext *ctxt,
- void (*cairo_func) (cairo_t *, double))
-{
- while (lsm_str_parse_double_list (&ctxt->ptr, 1, ctxt->values) == 1)
- cairo_func (ctxt->cr, ctxt->values[0]);
-}
-
-static void
-_emit_function_2 (LsmSvgPathContext *ctxt,
- void (*cairo_func_a) (cairo_t *, double, double),
- void (*cairo_func_b) (cairo_t *, double, double))
-{
-
- if (lsm_str_parse_double_list (&ctxt->ptr, 2, ctxt->values) == 2) {
- cairo_func_a (ctxt->cr, ctxt->values[0], ctxt->values[1]);
-
- /* Why oh why does the specification say Line is implied here ? */
-
- while (lsm_str_parse_double_list (&ctxt->ptr, 2, ctxt->values) == 2)
- cairo_func_b (ctxt->cr, ctxt->values[0], ctxt->values[1]);
- }
-}
-
-static void
-_emit_function_4 (LsmSvgPathContext *ctxt,
- void (*cairo_func) (cairo_t *, double, double, double, double))
-{
- while (lsm_str_parse_double_list (&ctxt->ptr, 4, ctxt->values) == 4)
- cairo_func (ctxt->cr, ctxt->values[0], ctxt->values[1], ctxt->values[2], ctxt->values[3]);
-}
-
-static void
-_emit_smooth_curve (LsmSvgPathContext *ctxt, gboolean relative)
-{
- double x, y;
- double x0, y0;
-
- cairo_get_current_point (ctxt->cr, &x0, &y0);
-
- switch (ctxt->last_command) {
- case 'C':
- x = 2 * x0 - ctxt->values[2];
- y = 2 * y0 - ctxt->values[3];
- break;
- case 'c':
- x = 2 * x0 - (ctxt->values[2] + x0 - ctxt->values[4]);
- y = 2 * y0 - (ctxt->values[3] + y0 - ctxt->values[5]);
- break;
- case 'S':
- x = 2 * x0 - ctxt->values[0];
- y = 2 * y0 - ctxt->values[1];
- break;
- case 's':
- x = 2 * x0 - (ctxt->values[0] + x0 - ctxt->values[2]);
- y = 2 * y0 - (ctxt->values[1] + y0 - ctxt->values[3]);
- break;
- default: x = x0; y = y0; break;
- }
-
- while (lsm_str_parse_double_list (&ctxt->ptr, 4, ctxt->values) == 4) {
- if (relative) {
- cairo_get_current_point (ctxt->cr, &x0, &y0);
- cairo_curve_to (ctxt->cr,
- x, y,
- x0 + ctxt->values[0], y0 + ctxt->values[1],
- x0 + ctxt->values[2], y0 + ctxt->values[3]);
- x = 2 * (x0 + ctxt->values[2]) - (x0 + ctxt->values[0]);
- y = 2 * (y0 + ctxt->values[3]) - (y0 + ctxt->values[1]);
- } else {
- cairo_curve_to (ctxt->cr, x, y,
- ctxt->values[0], ctxt->values[1], ctxt->values[2], ctxt->values[3]);
- x = 2 * ctxt->values[2] - ctxt->values[0];
- y = 2 * ctxt->values[3] - ctxt->values[1];
- }
- }
-}
-
-static void
-_emit_smooth_quadratic_curve (LsmSvgPathContext *ctxt, gboolean relative)
-{
- double x, y;
- double x0, y0;
-
- cairo_get_current_point (ctxt->cr, &x0, &y0);
-
- switch (ctxt->last_command) {
- case 'Q':
- ctxt->last_cp_x = ctxt->values[0];
- ctxt->last_cp_y = ctxt->values[1];
- break;
- case 'q':
- ctxt->last_cp_x = ctxt->values[0] + x0 - ctxt->values[2];
- ctxt->last_cp_y = ctxt->values[1] + y0 - ctxt->values[3];
- break;
- case 'T':
- case 't':
- break;
- default: ctxt->last_cp_x = x0; ctxt->last_cp_y = y0; break;
- }
-
- while (lsm_str_parse_double_list (&ctxt->ptr, 2, ctxt->values) == 2) {
- x = 2 * x0 - ctxt->last_cp_x;
- y = 2 * y0 - ctxt->last_cp_y;
- if (relative) {
- cairo_get_current_point (ctxt->cr, &x0, &y0);
- _cairo_quadratic_curve_to (ctxt->cr, x, y, x0 + ctxt->values[0], y0 + ctxt->values[1]);
- } else {
- _cairo_quadratic_curve_to (ctxt->cr, x, y, ctxt->values[0], ctxt->values[1]);
- }
- ctxt->last_cp_x = x;
- ctxt->last_cp_y = y;
- cairo_get_current_point (ctxt->cr, &x0, &y0);
- }
-}
-
-static void
-_emit_function_6 (LsmSvgPathContext *ctxt,
- void (*cairo_func) (cairo_t *, double, double, double ,double, double, double))
-{
- while (lsm_str_parse_double_list (&ctxt->ptr, 6, ctxt->values) == 6)
- cairo_func (ctxt->cr, ctxt->values[0], ctxt->values[1], ctxt->values[2],
- ctxt->values[3], ctxt->values[4], ctxt->values[5]);
-}
-
-static void
-_emit_function_7 (LsmSvgPathContext *ctxt,
- void (*cairo_func) (cairo_t *, double, double, double ,gboolean, gboolean, double, double))
-{
- while (lsm_str_parse_double_list (&ctxt->ptr, 7, ctxt->values) == 7)
- cairo_func (ctxt->cr, ctxt->values[0], ctxt->values[1], ctxt->values[2],
- ctxt->values[3], ctxt->values[4], ctxt->values[5],
- ctxt->values[6]);
-}
-
-static void
-_emit_svg_path (cairo_t *cr, char const *path)
-{
- LsmSvgPathContext ctxt;
-
- g_return_if_fail (cr != NULL);
-
- if (path == NULL)
- return;
-
- ctxt.cr = cr;
- ctxt.ptr = (char *) path;
- ctxt.last_command = '\0';
- cairo_get_current_point (cr,
- &ctxt.values[0],
- &ctxt.values[1]);
- ctxt.values[2] = ctxt.values[4] = ctxt.values[0];
- ctxt.values[3] = ctxt.values[5] = ctxt.values[1];
-
- lsm_str_skip_spaces (&ctxt.ptr);
-
- while (*ctxt.ptr != '\0') {
- char command;
-
- command = *ctxt.ptr;
- ctxt.ptr++;
- lsm_str_skip_spaces (&ctxt.ptr);
-
- if (!cairo_has_current_point (cr)) {
- cairo_move_to (cr, 0, 0);
- ctxt.values[2] = ctxt.values[4] = ctxt.values[0] = 0;
- ctxt.values[3] = ctxt.values[5] = ctxt.values[1] = 0;
- }
-
- switch (command) {
- case 'M': _emit_function_2 (&ctxt, cairo_move_to, cairo_line_to); break;
- case 'm': _emit_function_2 (&ctxt, cairo_rel_move_to, cairo_rel_line_to); break;
- case 'L': _emit_function_2 (&ctxt, cairo_line_to, cairo_line_to); break;
- case 'l': _emit_function_2 (&ctxt, cairo_rel_line_to, cairo_rel_line_to); break;
- case 'C': _emit_function_6 (&ctxt, cairo_curve_to); break;
- case 'c': _emit_function_6 (&ctxt, cairo_rel_curve_to); break;
- case 'S': _emit_smooth_curve (&ctxt, FALSE); break;
- case 's': _emit_smooth_curve (&ctxt, TRUE); break;
- case 'V': _emit_function_1 (&ctxt, _cairo_vertical); break;
- case 'v': _emit_function_1 (&ctxt, _cairo_rel_vertical); break;
- case 'H': _emit_function_1 (&ctxt, _cairo_horizontal); break;
- case 'h': _emit_function_1 (&ctxt, _cairo_rel_horizontal); break;
- case 'Q': _emit_function_4 (&ctxt, _cairo_quadratic_curve_to); break;
- case 'q': _emit_function_4 (&ctxt, _cairo_rel_quadratic_curve_to); break;
- case 'T': _emit_smooth_quadratic_curve (&ctxt, FALSE); break;
- case 't': _emit_smooth_quadratic_curve (&ctxt, TRUE); break;
- case 'A': _emit_function_7 (&ctxt, _cairo_elliptical_arc); break;
- case 'a': _emit_function_7 (&ctxt, _cairo_rel_elliptical_arc); break;
- case 'Z':
- case 'z': cairo_close_path (cr); break;
- default: break;
- }
-
- ctxt.last_command = command;
- }
-}
-
typedef enum {
LSM_SVG_VIEW_PAINT_OPERATION_FILL,
LSM_SVG_VIEW_PAINT_OPERATION_STROKE
@@ -1230,13 +809,13 @@ lsm_svg_view_show_rectangle (LsmSvgView *view,
cairo_move_to (cairo, x + rx, y);
cairo_line_to (cairo, x + w - rx, y);
- _cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x + w, y + ry);
+ lsm_cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x + w, y + ry);
cairo_line_to (cairo, x + w, y + h -ry);
- _cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x + w - rx, y + h);
+ lsm_cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x + w - rx, y + h);
cairo_line_to (cairo, x + rx, y + h);
- _cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x, y + h - ry);
+ lsm_cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x, y + h - ry);
cairo_line_to (cairo, x, y + ry);
- _cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x + rx, y);
+ lsm_cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x + rx, y);
cairo_close_path (cairo);
}
@@ -1288,7 +867,7 @@ lsm_svg_view_show_path (LsmSvgView *view,
g_return_if_fail (LSM_IS_SVG_VIEW (view));
- _emit_svg_path (view->dom_view.cairo, d);
+ lsm_cairo_emit_svg_path (view->dom_view.cairo, d);
process_path (view, &path_infos);
}
@@ -1304,7 +883,7 @@ lsm_svg_view_calculate_path_extents (LsmSvgView *view,
g_return_if_fail (LSM_IS_SVG_VIEW (view));
cairo_new_path (view->dom_view.cairo);
- _emit_svg_path (view->dom_view.cairo, path);
+ lsm_cairo_emit_svg_path (view->dom_view.cairo, path);
cairo_path_extents (view->dom_view.cairo, &xx1, &yy1, &xx2, &yy2);
cairo_new_path (view->dom_view.cairo);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]