[lasem] svg_view: move cairo path code to lsmcairo.



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]