path: Add conic curves
So far this just adds the API, if you use it, you'll get lots of g_warnings(). This will be fixed in future commits.
This commit is contained in:
@@ -103,6 +103,7 @@ static gboolean
|
|||||||
gtk_path_transform_op (GskPathOperation op,
|
gtk_path_transform_op (GskPathOperation op,
|
||||||
const graphene_point_t *pts,
|
const graphene_point_t *pts,
|
||||||
gsize n_pts,
|
gsize n_pts,
|
||||||
|
float weight,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
GtkPathTransform *transform = data;
|
GtkPathTransform *transform = data;
|
||||||
@@ -135,6 +136,15 @@ gtk_path_transform_op (GskPathOperation op,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
{
|
||||||
|
graphene_point_t res[2];
|
||||||
|
gtk_path_transform_point (transform->measure, &pts[1], transform->scale, &res[0]);
|
||||||
|
gtk_path_transform_point (transform->measure, &pts[2], transform->scale, &res[1]);
|
||||||
|
gsk_path_builder_conic_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, weight);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_PATH_CLOSE:
|
case GSK_PATH_CLOSE:
|
||||||
gsk_path_builder_close (transform->builder);
|
gsk_path_builder_close (transform->builder);
|
||||||
break;
|
break;
|
||||||
@@ -160,7 +170,7 @@ gtk_path_transform (GskPathMeasure *measure,
|
|||||||
else
|
else
|
||||||
transform.scale = 1.0f;
|
transform.scale = 1.0f;
|
||||||
|
|
||||||
gsk_path_foreach (path, GSK_PATH_FOREACH_ALLOW_CURVES, gtk_path_transform_op, &transform);
|
gsk_path_foreach (path, GSK_PATH_FOREACH_ALLOW_CURVE, gtk_path_transform_op, &transform);
|
||||||
|
|
||||||
return gsk_path_builder_free_to_path (transform.builder);
|
return gsk_path_builder_free_to_path (transform.builder);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,6 +362,8 @@ gsk_path_builder_line_to
|
|||||||
gsk_path_builder_rel_line_to
|
gsk_path_builder_rel_line_to
|
||||||
gsk_path_builder_curve_to
|
gsk_path_builder_curve_to
|
||||||
gsk_path_builder_rel_curve_to
|
gsk_path_builder_rel_curve_to
|
||||||
|
gsk_path_builder_conic_to
|
||||||
|
gsk_path_builder_rel_conic_to
|
||||||
gsk_path_builder_close
|
gsk_path_builder_close
|
||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
GSK_TYPE_PATH_BUILDER
|
GSK_TYPE_PATH_BUILDER
|
||||||
|
|||||||
@@ -217,11 +217,11 @@ gsk_rect_contour_foreach (const GskContour *contour,
|
|||||||
GRAPHENE_POINT_INIT (self->x, self->y)
|
GRAPHENE_POINT_INIT (self->x, self->y)
|
||||||
};
|
};
|
||||||
|
|
||||||
return func (GSK_PATH_MOVE, &pts[0], 1, user_data)
|
return func (GSK_PATH_MOVE, &pts[0], 1, 0, user_data)
|
||||||
&& func (GSK_PATH_LINE, &pts[0], 2, user_data)
|
&& func (GSK_PATH_LINE, &pts[0], 2, 0, user_data)
|
||||||
&& func (GSK_PATH_LINE, &pts[1], 2, user_data)
|
&& func (GSK_PATH_LINE, &pts[1], 2, 0, user_data)
|
||||||
&& func (GSK_PATH_LINE, &pts[2], 2, user_data)
|
&& func (GSK_PATH_LINE, &pts[2], 2, 0, user_data)
|
||||||
&& func (GSK_PATH_CLOSE, &pts[3], 2, user_data);
|
&& func (GSK_PATH_CLOSE, &pts[3], 2, 0, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
@@ -601,7 +601,7 @@ gsk_circle_contour_curve (const graphene_point_t curve[4],
|
|||||||
{
|
{
|
||||||
ForeachWrapper *wrapper = data;
|
ForeachWrapper *wrapper = data;
|
||||||
|
|
||||||
return wrapper->func (GSK_PATH_CURVE, curve, 4, wrapper->user_data);
|
return wrapper->func (GSK_PATH_CURVE, curve, 4, 0, wrapper->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -613,7 +613,7 @@ gsk_circle_contour_foreach (const GskContour *contour,
|
|||||||
const GskCircleContour *self = (const GskCircleContour *) contour;
|
const GskCircleContour *self = (const GskCircleContour *) contour;
|
||||||
graphene_point_t start = GSK_CIRCLE_POINT_INIT (self, self->start_angle);
|
graphene_point_t start = GSK_CIRCLE_POINT_INIT (self, self->start_angle);
|
||||||
|
|
||||||
if (!func (GSK_PATH_MOVE, &start, 1, user_data))
|
if (!func (GSK_PATH_MOVE, &start, 1, 0, user_data))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!gsk_spline_decompose_arc (&self->center,
|
if (!gsk_spline_decompose_arc (&self->center,
|
||||||
@@ -627,7 +627,7 @@ gsk_circle_contour_foreach (const GskContour *contour,
|
|||||||
|
|
||||||
if (fabs (self->start_angle - self->end_angle) >= 360)
|
if (fabs (self->start_angle - self->end_angle) >= 360)
|
||||||
{
|
{
|
||||||
if (!func (GSK_PATH_CLOSE, (graphene_point_t[2]) { start, start }, 2, user_data))
|
if (!func (GSK_PATH_CLOSE, (graphene_point_t[2]) { start, start }, 2, 0, user_data))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -908,8 +908,21 @@ gsk_standard_contour_foreach (const GskContour *contour,
|
|||||||
|
|
||||||
for (i = 0; i < self->n_ops; i ++)
|
for (i = 0; i < self->n_ops; i ++)
|
||||||
{
|
{
|
||||||
if (!func (self->ops[i].op, &self->points[self->ops[i].point], n_points[self->ops[i].op], user_data))
|
if (self->ops[i].op == GSK_PATH_CONIC)
|
||||||
return FALSE;
|
{
|
||||||
|
graphene_point_t pts[3] = { self->points[self->ops[i].point],
|
||||||
|
self->points[self->ops[i].point + 1],
|
||||||
|
self->points[self->ops[i].point + 3] };
|
||||||
|
float weight = self->points[self->ops[i].point + 2].x;
|
||||||
|
|
||||||
|
if (!func (GSK_PATH_CONIC, pts, 3, weight, user_data))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!func (self->ops[i].op, &self->points[self->ops[i].point], n_points[self->ops[i].op], 0, user_data))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -959,6 +972,16 @@ gsk_standard_contour_print (const GskContour *contour,
|
|||||||
_g_string_append_point (string, &pt[3]);
|
_g_string_append_point (string, &pt[3]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
/* This is not valid SVG */
|
||||||
|
g_string_append (string, " O ");
|
||||||
|
_g_string_append_point (string, &pt[1]);
|
||||||
|
g_string_append (string, ", ");
|
||||||
|
_g_string_append_point (string, &pt[3]);
|
||||||
|
g_string_append (string, ", ");
|
||||||
|
_g_string_append_double (string, pt[2].x);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
return;
|
return;
|
||||||
@@ -1111,6 +1134,14 @@ gsk_standard_contour_init_measure (const GskContour *contour,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
{
|
||||||
|
LengthDecompose decomp = { array, { length, length, 0, 0, pt[0], i } };
|
||||||
|
gsk_spline_decompose_conic (pt, tolerance, gsk_standard_contour_measure_add_point, &decomp);
|
||||||
|
length = decomp.measure.start;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1171,6 +1202,10 @@ gsk_standard_contour_measure_get_point (GskStandardContour *self,
|
|||||||
gsk_spline_get_point_cubic (pts, progress, pos, tangent);
|
gsk_spline_get_point_cubic (pts, progress, pos, tangent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
gsk_spline_get_point_conic (pts, progress, pos, tangent);
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_PATH_MOVE:
|
case GSK_PATH_MOVE:
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
@@ -1404,6 +1439,25 @@ gsk_standard_contour_add_segment (const GskContour *contour,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
{
|
||||||
|
graphene_point_t *pts = &self->points[self->ops[start_measure->op].point];
|
||||||
|
graphene_point_t curve[4], discard[4];
|
||||||
|
|
||||||
|
gsk_spline_split_conic (pts, discard, curve, start_progress);
|
||||||
|
if (end_measure && end_measure->op == start_measure->op)
|
||||||
|
{
|
||||||
|
graphene_point_t tiny[4];
|
||||||
|
gsk_spline_split_conic (curve, tiny, discard, (end_progress - start_progress) / (1 - start_progress));
|
||||||
|
gsk_path_builder_move_to (builder, tiny[0].x, tiny[0].y);
|
||||||
|
gsk_path_builder_conic_to (builder, tiny[1].x, tiny[1].y, tiny[3].x, tiny[3].y, tiny[2].x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gsk_path_builder_move_to (builder, curve[0].x, curve[0].y);
|
||||||
|
gsk_path_builder_conic_to (builder, curve[1].x, curve[1].y, curve[3].x, curve[3].y, curve[2].x);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_PATH_MOVE:
|
case GSK_PATH_MOVE:
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
@@ -1433,6 +1487,10 @@ gsk_standard_contour_add_segment (const GskContour *contour,
|
|||||||
gsk_path_builder_curve_to (builder, pt[1].x, pt[1].y, pt[2].x, pt[2].y, pt[3].x, pt[3].y);
|
gsk_path_builder_curve_to (builder, pt[1].x, pt[1].y, pt[2].x, pt[2].y, pt[3].x, pt[3].y);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
gsk_path_builder_conic_to (builder, pt[1].x, pt[1].y, pt[3].x, pt[3].y, pt[2].x);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
return;
|
return;
|
||||||
@@ -1465,6 +1523,16 @@ gsk_standard_contour_add_segment (const GskContour *contour,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
{
|
||||||
|
graphene_point_t *pts = &self->points[self->ops[end_measure->op].point];
|
||||||
|
graphene_point_t curve[4], discard[4];
|
||||||
|
|
||||||
|
gsk_spline_split_conic (pts, curve, discard, end_progress);
|
||||||
|
gsk_path_builder_conic_to (builder, curve[1].x, curve[1].y, curve[3].x, curve[3].y, curve[2].x);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_PATH_MOVE:
|
case GSK_PATH_MOVE:
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
|
|||||||
@@ -253,6 +253,9 @@ typedef enum {
|
|||||||
* @GSK_PATH_CURVE: A curve-to operation describing a cubic Bézier curve
|
* @GSK_PATH_CURVE: A curve-to operation describing a cubic Bézier curve
|
||||||
* with 4 points describing the start point, the two control points
|
* with 4 points describing the start point, the two control points
|
||||||
* and the end point of the curve.
|
* and the end point of the curve.
|
||||||
|
* @GSK_PATH_CONIC: A weighted quadratic bezier curve with 3 points
|
||||||
|
* describing the start point, control point and end point of the
|
||||||
|
* curve. A weight for the curve will be passed, too.
|
||||||
*
|
*
|
||||||
* Path operations can be used to approximate a #GskPath.
|
* Path operations can be used to approximate a #GskPath.
|
||||||
*
|
*
|
||||||
@@ -263,6 +266,7 @@ typedef enum {
|
|||||||
GSK_PATH_CLOSE,
|
GSK_PATH_CLOSE,
|
||||||
GSK_PATH_LINE,
|
GSK_PATH_LINE,
|
||||||
GSK_PATH_CURVE,
|
GSK_PATH_CURVE,
|
||||||
|
GSK_PATH_CONIC,
|
||||||
} GskPathOperation;
|
} GskPathOperation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ static gboolean
|
|||||||
gsk_path_to_cairo_add_op (GskPathOperation op,
|
gsk_path_to_cairo_add_op (GskPathOperation op,
|
||||||
const graphene_point_t *pts,
|
const graphene_point_t *pts,
|
||||||
gsize n_pts,
|
gsize n_pts,
|
||||||
|
float weight,
|
||||||
gpointer cr)
|
gpointer cr)
|
||||||
{
|
{
|
||||||
switch (op)
|
switch (op)
|
||||||
@@ -286,6 +287,7 @@ gsk_path_to_cairo_add_op (GskPathOperation op,
|
|||||||
cairo_curve_to (cr, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
|
cairo_curve_to (cr, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -316,7 +318,7 @@ gsk_path_to_cairo (GskPath *self,
|
|||||||
g_return_if_fail (cr != NULL);
|
g_return_if_fail (cr != NULL);
|
||||||
|
|
||||||
gsk_path_foreach_with_tolerance (self,
|
gsk_path_foreach_with_tolerance (self,
|
||||||
GSK_PATH_FOREACH_ALLOW_CURVES,
|
GSK_PATH_FOREACH_ALLOW_CURVE,
|
||||||
cairo_get_tolerance (cr),
|
cairo_get_tolerance (cr),
|
||||||
gsk_path_to_cairo_add_op,
|
gsk_path_to_cairo_add_op,
|
||||||
cr);
|
cr);
|
||||||
@@ -461,6 +463,7 @@ gsk_path_foreach_trampoline_add_point (const graphene_point_t *from,
|
|||||||
trampoline->retval = trampoline->func (GSK_PATH_LINE,
|
trampoline->retval = trampoline->func (GSK_PATH_LINE,
|
||||||
(graphene_point_t[2]) { *from, *to },
|
(graphene_point_t[2]) { *from, *to },
|
||||||
2,
|
2,
|
||||||
|
0.0f,
|
||||||
trampoline->user_data);
|
trampoline->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,6 +471,7 @@ static gboolean
|
|||||||
gsk_path_foreach_trampoline (GskPathOperation op,
|
gsk_path_foreach_trampoline (GskPathOperation op,
|
||||||
const graphene_point_t *pts,
|
const graphene_point_t *pts,
|
||||||
gsize n_pts,
|
gsize n_pts,
|
||||||
|
float weight,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
GskPathForeachTrampoline *trampoline = data;
|
GskPathForeachTrampoline *trampoline = data;
|
||||||
@@ -477,11 +481,11 @@ gsk_path_foreach_trampoline (GskPathOperation op,
|
|||||||
case GSK_PATH_MOVE:
|
case GSK_PATH_MOVE:
|
||||||
case GSK_PATH_CLOSE:
|
case GSK_PATH_CLOSE:
|
||||||
case GSK_PATH_LINE:
|
case GSK_PATH_LINE:
|
||||||
return trampoline->func (op, pts, n_pts, trampoline->user_data);
|
return trampoline->func (op, pts, n_pts, weight, trampoline->user_data);
|
||||||
|
|
||||||
case GSK_PATH_CURVE:
|
case GSK_PATH_CURVE:
|
||||||
if (trampoline->flags & GSK_PATH_FOREACH_ALLOW_CURVES)
|
if (trampoline->flags & GSK_PATH_FOREACH_ALLOW_CURVE)
|
||||||
return trampoline->func (op, pts, n_pts, trampoline->user_data);
|
return trampoline->func (op, pts, n_pts, weight, trampoline->user_data);
|
||||||
|
|
||||||
gsk_spline_decompose_cubic (pts,
|
gsk_spline_decompose_cubic (pts,
|
||||||
trampoline->tolerance,
|
trampoline->tolerance,
|
||||||
@@ -489,6 +493,17 @@ gsk_path_foreach_trampoline (GskPathOperation op,
|
|||||||
trampoline);
|
trampoline);
|
||||||
return trampoline->retval;
|
return trampoline->retval;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
if (trampoline->flags & GSK_PATH_FOREACH_ALLOW_CONIC)
|
||||||
|
return trampoline->func (op, pts, n_pts, weight, trampoline->user_data);
|
||||||
|
|
||||||
|
/* XXX: decompose into curves if allowed */
|
||||||
|
gsk_spline_decompose_conic ((graphene_point_t[4]) { pts[0], pts[1], { weight, }, pts[2] },
|
||||||
|
trampoline->tolerance,
|
||||||
|
gsk_path_foreach_trampoline_add_point,
|
||||||
|
trampoline);
|
||||||
|
return trampoline->retval;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -506,7 +521,7 @@ gsk_path_foreach_with_tolerance (GskPath *self,
|
|||||||
gsize i;
|
gsize i;
|
||||||
|
|
||||||
/* If we need to massage the data, set up a trampoline here */
|
/* If we need to massage the data, set up a trampoline here */
|
||||||
if (flags != GSK_PATH_FOREACH_ALLOW_CURVES)
|
if (flags != (GSK_PATH_FOREACH_ALLOW_CURVE | GSK_PATH_FOREACH_ALLOW_CONIC))
|
||||||
{
|
{
|
||||||
trampoline = (GskPathForeachTrampoline) { flags, tolerance, func, user_data, TRUE };
|
trampoline = (GskPathForeachTrampoline) { flags, tolerance, func, user_data, TRUE };
|
||||||
func = gsk_path_foreach_trampoline;
|
func = gsk_path_foreach_trampoline;
|
||||||
@@ -631,7 +646,7 @@ parse_command (const char **p,
|
|||||||
if (*cmd == 'X')
|
if (*cmd == 'X')
|
||||||
allowed = "mM";
|
allowed = "mM";
|
||||||
else
|
else
|
||||||
allowed = "mMhHvVzZlLcCsStTqQaA";
|
allowed = "mMhHvVzZlLcCsStTqQoOaA";
|
||||||
|
|
||||||
skip_whitespace (p);
|
skip_whitespace (p);
|
||||||
s = strchr (allowed, **p);
|
s = strchr (allowed, **p);
|
||||||
@@ -1060,6 +1075,37 @@ gsk_path_parse (const char *string)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'O':
|
||||||
|
case 'o':
|
||||||
|
{
|
||||||
|
double x1, y1, x2, y2, weight;
|
||||||
|
|
||||||
|
if (parse_coordinate_pair (&p, &x1, &y1) &&
|
||||||
|
parse_coordinate_pair (&p, &x2, &y2) &&
|
||||||
|
parse_nonnegative_number (&p, &weight))
|
||||||
|
{
|
||||||
|
if (cmd == 'c')
|
||||||
|
{
|
||||||
|
x1 += x;
|
||||||
|
y1 += y;
|
||||||
|
x2 += x;
|
||||||
|
y2 += y;
|
||||||
|
}
|
||||||
|
if (strchr ("zZ", prev_cmd))
|
||||||
|
{
|
||||||
|
gsk_path_builder_move_to (builder, x, y);
|
||||||
|
path_x = x;
|
||||||
|
path_y = y;
|
||||||
|
}
|
||||||
|
gsk_path_builder_conic_to (builder, x1, y1, x2, y2, weight);
|
||||||
|
x = x2;
|
||||||
|
y = y2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'A':
|
case 'A':
|
||||||
case 'a':
|
case 'a':
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GskPathForeachFlags:
|
* GskPathForeachFlags:
|
||||||
* @GSK_PATH_FOREACH_ALLOW_CURVES: Allow emission of %GSK_PATH_CURVE
|
* @GSK_PATH_FOREACH_ALLOW_CURVE: Allow emission of %GSK_PATH_CURVE
|
||||||
|
* operations.
|
||||||
|
* @GSK_PATH_FOREACH_ALLOW_CONIC: Allow emission of %GSK_PATH_CONIC
|
||||||
* operations.
|
* operations.
|
||||||
*
|
*
|
||||||
* Flags that can be passed to gsk_path_foreach() to enable additional
|
* Flags that can be passed to gsk_path_foreach() to enable additional
|
||||||
@@ -43,7 +45,8 @@ G_BEGIN_DECLS
|
|||||||
*/
|
*/
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GSK_PATH_FOREACH_ALLOW_CURVES = (1 << 0)
|
GSK_PATH_FOREACH_ALLOW_CURVE = (1 << 0),
|
||||||
|
GSK_PATH_FOREACH_ALLOW_CONIC = (1 << 1)
|
||||||
} GskPathForeachFlags;
|
} GskPathForeachFlags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,6 +54,7 @@ typedef enum
|
|||||||
* @op: The operation to perform
|
* @op: The operation to perform
|
||||||
* @pts: The points of the operation
|
* @pts: The points of the operation
|
||||||
* @n_pts: The number of points
|
* @n_pts: The number of points
|
||||||
|
* @weight: The weight for conic curves, or unused if not a conic curve.
|
||||||
* @user_data: The user data provided with the function
|
* @user_data: The user data provided with the function
|
||||||
*
|
*
|
||||||
* Prototype of the callback to iterate throught the operations of
|
* Prototype of the callback to iterate throught the operations of
|
||||||
@@ -62,6 +66,7 @@ typedef enum
|
|||||||
typedef gboolean (* GskPathForeachFunc) (GskPathOperation op,
|
typedef gboolean (* GskPathForeachFunc) (GskPathOperation op,
|
||||||
const graphene_point_t *pts,
|
const graphene_point_t *pts,
|
||||||
gsize n_pts,
|
gsize n_pts,
|
||||||
|
float weight,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
#define GSK_TYPE_PATH (gsk_path_get_type ())
|
#define GSK_TYPE_PATH (gsk_path_get_type ())
|
||||||
|
|||||||
@@ -549,6 +549,78 @@ gsk_path_builder_rel_curve_to (GskPathBuilder *builder,
|
|||||||
builder->current_point.y + y3);
|
builder->current_point.y + y3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsk_path_builder_conic_to:
|
||||||
|
* @builder: a #GskPathBuilder
|
||||||
|
* @x1: x coordinate of control point
|
||||||
|
* @y1: y coordinate of control point
|
||||||
|
* @x2: x coordinate of the end of the curve
|
||||||
|
* @y2: y coordinate of the end of the curve
|
||||||
|
* @weight: weight of the curve
|
||||||
|
*
|
||||||
|
* Adds a [conic curve](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)
|
||||||
|
* from the current point to @x2, @y2 with the given
|
||||||
|
* @weight and @x1, @y1 as the single control point.
|
||||||
|
*
|
||||||
|
* Conic curves can be used to draw ellipses and circles.
|
||||||
|
*
|
||||||
|
* After this, @x2, @y2 will be the new current point.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gsk_path_builder_conic_to (GskPathBuilder *builder,
|
||||||
|
float x1,
|
||||||
|
float y1,
|
||||||
|
float x2,
|
||||||
|
float y2,
|
||||||
|
float weight)
|
||||||
|
{
|
||||||
|
g_return_if_fail (builder != NULL);
|
||||||
|
g_return_if_fail (weight >= 0);
|
||||||
|
|
||||||
|
builder->flags &= ~GSK_PATH_FLAT;
|
||||||
|
gsk_path_builder_append_current (builder,
|
||||||
|
GSK_PATH_CONIC,
|
||||||
|
3, (graphene_point_t[3]) {
|
||||||
|
GRAPHENE_POINT_INIT (x1, y1),
|
||||||
|
GRAPHENE_POINT_INIT (weight, 0),
|
||||||
|
GRAPHENE_POINT_INIT (x2, y2)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsk_path_builder_rel_conic_to:
|
||||||
|
* @builder: a #GskPathBuilder
|
||||||
|
* @x1: x offset of control point
|
||||||
|
* @y1: y offset of control point
|
||||||
|
* @x2: x offset of the end of the curve
|
||||||
|
* @y2: y offset of the end of the curve
|
||||||
|
* @weight: weight of the curve
|
||||||
|
*
|
||||||
|
* Adds a [conic curve](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)
|
||||||
|
* from the current point to @x2, @y2 with the given
|
||||||
|
* @weight and @x1, @y1 as the single control point.
|
||||||
|
*
|
||||||
|
* This is the relative version of gsk_path_builder_conic_to().
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gsk_path_builder_rel_conic_to (GskPathBuilder *builder,
|
||||||
|
float x1,
|
||||||
|
float y1,
|
||||||
|
float x2,
|
||||||
|
float y2,
|
||||||
|
float weight)
|
||||||
|
{
|
||||||
|
g_return_if_fail (builder != NULL);
|
||||||
|
g_return_if_fail (weight >= 0);
|
||||||
|
|
||||||
|
gsk_path_builder_conic_to (builder,
|
||||||
|
builder->current_point.x + x1,
|
||||||
|
builder->current_point.y + y1,
|
||||||
|
builder->current_point.x + x2,
|
||||||
|
builder->current_point.y + y2,
|
||||||
|
weight);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gsk_path_builder_close:
|
* gsk_path_builder_close:
|
||||||
* @builder: a #GskPathBuilder
|
* @builder: a #GskPathBuilder
|
||||||
|
|||||||
@@ -99,6 +99,20 @@ void gsk_path_builder_rel_curve_to (GskPathBuilder
|
|||||||
float x3,
|
float x3,
|
||||||
float y3);
|
float y3);
|
||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
|
void gsk_path_builder_conic_to (GskPathBuilder *builder,
|
||||||
|
float x1,
|
||||||
|
float y1,
|
||||||
|
float x2,
|
||||||
|
float y2,
|
||||||
|
float weight);
|
||||||
|
GDK_AVAILABLE_IN_ALL
|
||||||
|
void gsk_path_builder_rel_conic_to (GskPathBuilder *builder,
|
||||||
|
float x1,
|
||||||
|
float y1,
|
||||||
|
float x2,
|
||||||
|
float y2,
|
||||||
|
float weight);
|
||||||
|
GDK_AVAILABLE_IN_ALL
|
||||||
void gsk_path_builder_close (GskPathBuilder *builder);
|
void gsk_path_builder_close (GskPathBuilder *builder);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@@ -2663,7 +2663,7 @@ append_path_param (Printer *p,
|
|||||||
for (s = str; *s; s++)
|
for (s = str; *s; s++)
|
||||||
{
|
{
|
||||||
if (*s == ' ' &&
|
if (*s == ' ' &&
|
||||||
(s[1] == 'M' || s[1] == 'C' || s[1] == 'Z' || s[1] == 'L'))
|
(s[1] == 'M' || s[1] == 'C' || s[1] == 'Z' || s[1] == 'L' || s[1] == 'O'))
|
||||||
*s = '\n';
|
*s = '\n';
|
||||||
}
|
}
|
||||||
append_escaping_newlines (p->str, str);
|
append_escaping_newlines (p->str, str);
|
||||||
|
|||||||
197
gsk/gskspline.c
197
gsk/gskspline.c
@@ -25,17 +25,18 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#define MIN_PROGRESS (1/1024.f)
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
graphene_point_t last_point;
|
graphene_point_t last_point;
|
||||||
float last_progress;
|
float last_progress;
|
||||||
float tolerance;
|
|
||||||
GskSplineAddPointFunc func;
|
GskSplineAddPointFunc func;
|
||||||
gpointer user_data;
|
gpointer user_data;
|
||||||
} GskCubicDecomposition;
|
} GskSplineDecompose;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_spline_decompose_add_point (GskCubicDecomposition *decomp,
|
gsk_spline_decompose_add_point (GskSplineDecompose *decomp,
|
||||||
const graphene_point_t *pt,
|
const graphene_point_t *pt,
|
||||||
float progress)
|
float progress)
|
||||||
{
|
{
|
||||||
@@ -47,6 +48,20 @@ gsk_spline_decompose_add_point (GskCubicDecomposition *decomp,
|
|||||||
decomp->last_progress += progress;
|
decomp->last_progress += progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_spline_decompose_finish (GskSplineDecompose *decomp,
|
||||||
|
const graphene_point_t *end_point)
|
||||||
|
{
|
||||||
|
g_assert (graphene_point_equal (&decomp->last_point, end_point));
|
||||||
|
g_assert (decomp->last_progress == 1.0f || decomp->last_progress == 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GskSplineDecompose decomp;
|
||||||
|
float tolerance;
|
||||||
|
} GskCubicDecomposition;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_spline_cubic_get_coefficients (graphene_point_t coeffs[4],
|
gsk_spline_cubic_get_coefficients (graphene_point_t coeffs[4],
|
||||||
const graphene_point_t pts[4])
|
const graphene_point_t pts[4])
|
||||||
@@ -202,22 +217,22 @@ gsk_spline_cubic_too_curvy (const graphene_point_t pts[4],
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_spline_decompose_into (GskCubicDecomposition *decomp,
|
gsk_spline_cubic_decompose (GskCubicDecomposition *d,
|
||||||
const graphene_point_t pts[4],
|
const graphene_point_t pts[4],
|
||||||
float progress)
|
float progress)
|
||||||
{
|
{
|
||||||
graphene_point_t left[4], right[4];
|
graphene_point_t left[4], right[4];
|
||||||
|
|
||||||
if (!gsk_spline_cubic_too_curvy (pts, decomp->tolerance) || progress < 1 / 1024.f)
|
if (!gsk_spline_cubic_too_curvy (pts, d->tolerance) || progress < MIN_PROGRESS)
|
||||||
{
|
{
|
||||||
gsk_spline_decompose_add_point (decomp, &pts[3], progress);
|
gsk_spline_decompose_add_point (&d->decomp, &pts[3], progress);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gsk_spline_split_cubic (pts, left, right, 0.5);
|
gsk_spline_split_cubic (pts, left, right, 0.5);
|
||||||
|
|
||||||
gsk_spline_decompose_into (decomp, left, progress / 2);
|
gsk_spline_cubic_decompose (d, left, progress / 2);
|
||||||
gsk_spline_decompose_into (decomp, right, progress / 2);
|
gsk_spline_cubic_decompose (d, right, progress / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -226,12 +241,166 @@ gsk_spline_decompose_cubic (const graphene_point_t pts[4],
|
|||||||
GskSplineAddPointFunc add_point_func,
|
GskSplineAddPointFunc add_point_func,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GskCubicDecomposition decomp = { pts[0], 0.0f, tolerance, add_point_func, user_data };
|
GskCubicDecomposition decomp = { { pts[0], 0.0f, add_point_func, user_data }, tolerance };
|
||||||
|
|
||||||
gsk_spline_decompose_into (&decomp, pts, 1.0f);
|
gsk_spline_cubic_decompose (&decomp, pts, 1.0f);
|
||||||
|
|
||||||
g_assert (graphene_point_equal (&decomp.last_point, &pts[3]));
|
gsk_spline_decompose_finish (&decomp.decomp, &pts[3]);
|
||||||
g_assert (decomp.last_progress == 1.0f || decomp.last_progress == 0.0f);
|
}
|
||||||
|
|
||||||
|
/* CONIC */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
graphene_point_t num[3];
|
||||||
|
graphene_point_t denom[3];
|
||||||
|
} ConicCoefficients;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GskSplineDecompose decomp;
|
||||||
|
float tolerance;
|
||||||
|
ConicCoefficients c;
|
||||||
|
} GskConicDecomposition;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_spline_conic_get_coefficents (ConicCoefficients *c,
|
||||||
|
const graphene_point_t pts[4])
|
||||||
|
{
|
||||||
|
float w = pts[2].x;
|
||||||
|
graphene_point_t pw = GRAPHENE_POINT_INIT (w * pts[1].x, w * pts[1].y);
|
||||||
|
|
||||||
|
c->num[2] = pts[0];
|
||||||
|
c->num[1] = GRAPHENE_POINT_INIT (2 * (pw.x - pts[0].x),
|
||||||
|
2 * (pw.y - pts[0].y));
|
||||||
|
c->num[0] = GRAPHENE_POINT_INIT (pts[3].x - 2 * pw.x + pts[0].x,
|
||||||
|
pts[3].y - 2 * pw.y + pts[0].y);
|
||||||
|
|
||||||
|
c->denom[2] = GRAPHENE_POINT_INIT (1, 1);
|
||||||
|
c->denom[1] = GRAPHENE_POINT_INIT (2 * (w - 1), 2 * (w - 1));
|
||||||
|
c->denom[0] = GRAPHENE_POINT_INIT (-c->denom[1].x, -c->denom[1].y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gsk_spline_eval_quad (const graphene_point_t quad[3],
|
||||||
|
float progress,
|
||||||
|
graphene_point_t *result)
|
||||||
|
{
|
||||||
|
*result = GRAPHENE_POINT_INIT ((quad[0].x * progress + quad[1].x) * progress + quad[2].x,
|
||||||
|
(quad[0].y * progress + quad[1].y) * progress + quad[2].y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gsk_spline_eval_conic (const ConicCoefficients *c,
|
||||||
|
float progress,
|
||||||
|
graphene_point_t *result)
|
||||||
|
{
|
||||||
|
graphene_point_t num, denom;
|
||||||
|
|
||||||
|
gsk_spline_eval_quad (c->num, progress, &num);
|
||||||
|
gsk_spline_eval_quad (c->denom, progress, &denom);
|
||||||
|
*result = GRAPHENE_POINT_INIT (num.x / denom.x, num.y / denom.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_spline_get_point_conic (const graphene_point_t pts[4],
|
||||||
|
float progress,
|
||||||
|
graphene_point_t *pos,
|
||||||
|
graphene_vec2_t *tangent)
|
||||||
|
{
|
||||||
|
ConicCoefficients c;
|
||||||
|
|
||||||
|
gsk_spline_conic_get_coefficents (&c, pts);
|
||||||
|
|
||||||
|
if (pos)
|
||||||
|
gsk_spline_eval_conic (&c, progress, pos);
|
||||||
|
|
||||||
|
if (tangent)
|
||||||
|
{
|
||||||
|
graphene_point_t tmp;
|
||||||
|
float w = pts[2].x;
|
||||||
|
|
||||||
|
/* The tangent will be 0 in these corner cases, just
|
||||||
|
* treat it like a line here. */
|
||||||
|
if ((progress <= 0.f && graphene_point_equal (&pts[0], &pts[1])) ||
|
||||||
|
(progress >= 1.f && graphene_point_equal (&pts[1], &pts[3])))
|
||||||
|
{
|
||||||
|
graphene_vec2_init (tangent, pts[3].x - pts[0].x, pts[3].y - pts[0].y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsk_spline_eval_quad ((graphene_point_t[3]) {
|
||||||
|
GRAPHENE_POINT_INIT ((w - 1) * (pts[3].x - pts[0].x),
|
||||||
|
(w - 1) * (pts[3].y - pts[0].y)),
|
||||||
|
GRAPHENE_POINT_INIT (pts[3].x - pts[0].x - 2 * w * (pts[1].x - pts[0].x),
|
||||||
|
pts[3].y - pts[0].y - 2 * w * (pts[1].y - pts[0].y)),
|
||||||
|
GRAPHENE_POINT_INIT (w * (pts[1].x - pts[0].x),
|
||||||
|
w * (pts[1].y - pts[0].y))
|
||||||
|
},
|
||||||
|
progress,
|
||||||
|
&tmp);
|
||||||
|
graphene_vec2_init (tangent, tmp.x, tmp.y);
|
||||||
|
graphene_vec2_normalize (tangent, tangent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_spline_split_conic (const graphene_point_t pts[4],
|
||||||
|
graphene_point_t result1[4],
|
||||||
|
graphene_point_t result2[4],
|
||||||
|
float progress)
|
||||||
|
{
|
||||||
|
g_warning ("FIXME: Stop treating conics as lines");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* taken from Skia, including the very descriptive name */
|
||||||
|
static gboolean
|
||||||
|
gsk_spline_conic_too_curvy (const graphene_point_t *start,
|
||||||
|
const graphene_point_t *mid,
|
||||||
|
const graphene_point_t *end,
|
||||||
|
float tolerance)
|
||||||
|
{
|
||||||
|
return fabs ((start->x + end->x) * 0.5 - mid->x) > tolerance
|
||||||
|
|| fabs ((start->y + end->y) * 0.5 - mid->y) > tolerance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_spline_decompose_conic_subdivide (GskConicDecomposition *d,
|
||||||
|
const graphene_point_t *start,
|
||||||
|
float start_progress,
|
||||||
|
const graphene_point_t *end,
|
||||||
|
float end_progress)
|
||||||
|
{
|
||||||
|
graphene_point_t mid;
|
||||||
|
float mid_progress;
|
||||||
|
|
||||||
|
mid_progress = (start_progress + end_progress) / 2;
|
||||||
|
gsk_spline_eval_conic (&d->c, mid_progress, &mid);
|
||||||
|
|
||||||
|
if (end_progress - start_progress < MIN_PROGRESS ||
|
||||||
|
!gsk_spline_conic_too_curvy (start, &mid, end, d->tolerance))
|
||||||
|
{
|
||||||
|
gsk_spline_decompose_add_point (&d->decomp, end, end_progress - start_progress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsk_spline_decompose_conic_subdivide (d, start, start_progress, &mid, mid_progress);
|
||||||
|
gsk_spline_decompose_conic_subdivide (d, &mid, mid_progress, end, end_progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_spline_decompose_conic (const graphene_point_t pts[4],
|
||||||
|
float tolerance,
|
||||||
|
GskSplineAddPointFunc add_point_func,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GskConicDecomposition d = { { pts[0], 0.0f, add_point_func, user_data }, tolerance, };
|
||||||
|
|
||||||
|
gsk_spline_conic_get_coefficents (&d.c, pts);
|
||||||
|
|
||||||
|
gsk_spline_decompose_conic_subdivide (&d, &pts[0], 0.0f, &pts[3], 1.0f);
|
||||||
|
|
||||||
|
gsk_spline_decompose_finish (&d.decomp, &pts[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spline deviation from the circle in radius would be given by:
|
/* Spline deviation from the circle in radius would be given by:
|
||||||
|
|||||||
@@ -44,6 +44,19 @@ void gsk_spline_decompose_cubic (const graphene_
|
|||||||
GskSplineAddPointFunc add_point_func,
|
GskSplineAddPointFunc add_point_func,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
|
void gsk_spline_get_point_conic (const graphene_point_t pts[4],
|
||||||
|
float progress,
|
||||||
|
graphene_point_t *pos,
|
||||||
|
graphene_vec2_t *tangent);
|
||||||
|
void gsk_spline_split_conic (const graphene_point_t pts[4],
|
||||||
|
graphene_point_t result1[4],
|
||||||
|
graphene_point_t result2[4],
|
||||||
|
float progress);
|
||||||
|
void gsk_spline_decompose_conic (const graphene_point_t pts[4],
|
||||||
|
float tolerance,
|
||||||
|
GskSplineAddPointFunc add_point_func,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
typedef gboolean (* GskSplineAddCurveFunc) (const graphene_point_t curve[4],
|
typedef gboolean (* GskSplineAddCurveFunc) (const graphene_point_t curve[4],
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
gboolean gsk_spline_decompose_arc (const graphene_point_t *center,
|
gboolean gsk_spline_decompose_arc (const graphene_point_t *center,
|
||||||
|
|||||||
@@ -349,6 +349,16 @@ path_operation_print (const PathOperation *p,
|
|||||||
_g_string_append_point (string, &p->pts[3]);
|
_g_string_append_point (string, &p->pts[3]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
/* This is not valid SVG */
|
||||||
|
g_string_append (string, " O ");
|
||||||
|
_g_string_append_point (string, &p->pts[1]);
|
||||||
|
g_string_append (string, ", ");
|
||||||
|
_g_string_append_point (string, &p->pts[2]);
|
||||||
|
g_string_append (string, ", ");
|
||||||
|
_g_string_append_double (string, p->weight);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
return;
|
return;
|
||||||
@@ -379,6 +389,11 @@ path_operation_equal (const PathOperation *p1,
|
|||||||
&& graphene_point_near (&p1->pts[2], &p2->pts[2], epsilon)
|
&& graphene_point_near (&p1->pts[2], &p2->pts[2], epsilon)
|
||||||
&& graphene_point_near (&p1->pts[3], &p2->pts[3], epsilon);
|
&& graphene_point_near (&p1->pts[3], &p2->pts[3], epsilon);
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
return graphene_point_near (&p1->pts[1], &p2->pts[1], epsilon)
|
||||||
|
&& graphene_point_near (&p1->pts[2], &p2->pts[2], epsilon)
|
||||||
|
&& G_APPROX_VALUE (p1->weight, p2->weight, epsilon);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_return_val_if_reached (FALSE);
|
g_return_val_if_reached (FALSE);
|
||||||
}
|
}
|
||||||
@@ -388,6 +403,7 @@ static gboolean
|
|||||||
collect_path_operation_cb (GskPathOperation op,
|
collect_path_operation_cb (GskPathOperation op,
|
||||||
const graphene_point_t *pts,
|
const graphene_point_t *pts,
|
||||||
gsize n_pts,
|
gsize n_pts,
|
||||||
|
float weight,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_array_append_vals (user_data,
|
g_array_append_vals (user_data,
|
||||||
@@ -402,6 +418,7 @@ collect_path_operation_cb (GskPathOperation op,
|
|||||||
GRAPHENE_POINT_INIT(n_pts > 3 ? pts[3].x : 0,
|
GRAPHENE_POINT_INIT(n_pts > 3 ? pts[3].x : 0,
|
||||||
n_pts > 3 ? pts[3].y : 0)
|
n_pts > 3 ? pts[3].y : 0)
|
||||||
},
|
},
|
||||||
|
weight
|
||||||
},
|
},
|
||||||
1);
|
1);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -968,6 +985,7 @@ static gboolean
|
|||||||
rotate_path_cb (GskPathOperation op,
|
rotate_path_cb (GskPathOperation op,
|
||||||
const graphene_point_t *pts,
|
const graphene_point_t *pts,
|
||||||
gsize n_pts,
|
gsize n_pts,
|
||||||
|
float weight,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GskPathBuilder **builders = user_data;
|
GskPathBuilder **builders = user_data;
|
||||||
@@ -994,6 +1012,11 @@ rotate_path_cb (GskPathOperation op,
|
|||||||
gsk_path_builder_curve_to (builders[1], pts[1].y, -pts[1].x, pts[2].y, -pts[2].x, pts[3].y, -pts[3].x);
|
gsk_path_builder_curve_to (builders[1], pts[1].y, -pts[1].x, pts[2].y, -pts[2].x, pts[3].y, -pts[3].x);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
gsk_path_builder_conic_to (builders[0], pts[2].x, pts[2].y, pts[3].x, pts[3].y, weight);
|
||||||
|
gsk_path_builder_conic_to (builders[1], pts[2].y, -pts[2].x, pts[3].y, -pts[3].x, weight);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
Reference in New Issue
Block a user