WIP: path: Add conic curves
So far this just adds the API, if you use it, you'll get lots of g_warnings().
This commit is contained in:
@@ -103,6 +103,7 @@ static gboolean
|
||||
gtk_path_transform_op (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
float weight,
|
||||
gpointer data)
|
||||
{
|
||||
GtkPathTransform *transform = data;
|
||||
@@ -135,6 +136,15 @@ gtk_path_transform_op (GskPathOperation op,
|
||||
}
|
||||
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:
|
||||
gsk_path_builder_close (transform->builder);
|
||||
break;
|
||||
|
||||
@@ -296,6 +296,7 @@ gsk_path_builder_add_rect
|
||||
gsk_path_builder_move_to
|
||||
gsk_path_builder_line_to
|
||||
gsk_path_builder_curve_to
|
||||
gsk_path_builder_conic_to
|
||||
gsk_path_builder_close
|
||||
<SUBSECTION Private>
|
||||
GSK_TYPE_PATH_BUILDER
|
||||
|
||||
@@ -244,6 +244,9 @@ typedef enum {
|
||||
* @GSK_PATH_CURVE: A curve-to operation describing a cubic bezier curve
|
||||
* with 4 points describing the start point, the two control points
|
||||
* 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.
|
||||
**/
|
||||
@@ -252,6 +255,7 @@ typedef enum {
|
||||
GSK_PATH_CLOSE,
|
||||
GSK_PATH_LINE,
|
||||
GSK_PATH_CURVE,
|
||||
GSK_PATH_CONIC,
|
||||
} GskPathOperation;
|
||||
|
||||
/**
|
||||
|
||||
110
gsk/gskpath.c
110
gsk/gskpath.c
@@ -246,11 +246,11 @@ gsk_rect_contour_foreach (const GskContour *contour,
|
||||
GRAPHENE_POINT_INIT (self->x, self->y)
|
||||
};
|
||||
|
||||
return func (GSK_PATH_MOVE, &pts[0], 1, user_data)
|
||||
&& func (GSK_PATH_LINE, &pts[0], 2, user_data)
|
||||
&& func (GSK_PATH_LINE, &pts[1], 2, user_data)
|
||||
&& func (GSK_PATH_LINE, &pts[2], 2, user_data)
|
||||
&& func (GSK_PATH_CLOSE, &pts[3], 2, user_data);
|
||||
return func (GSK_PATH_MOVE, &pts[0], 1, 0, user_data)
|
||||
&& func (GSK_PATH_LINE, &pts[0], 2, 0, user_data)
|
||||
&& func (GSK_PATH_LINE, &pts[1], 2, 0, user_data)
|
||||
&& func (GSK_PATH_LINE, &pts[2], 2, 0, user_data)
|
||||
&& func (GSK_PATH_CLOSE, &pts[3], 2, 0, user_data);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
@@ -605,7 +605,7 @@ gsk_circle_contour_curve (const graphene_point_t curve[4],
|
||||
{
|
||||
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
|
||||
@@ -617,7 +617,7 @@ gsk_circle_contour_foreach (const GskContour *contour,
|
||||
const GskCircleContour *self = (const GskCircleContour *) contour;
|
||||
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;
|
||||
|
||||
if (!gsk_spline_decompose_arc (&self->center,
|
||||
@@ -631,7 +631,7 @@ gsk_circle_contour_foreach (const GskContour *contour,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -862,13 +862,25 @@ gsk_standard_contour_foreach (const GskContour *contour,
|
||||
[GSK_PATH_MOVE] = 1,
|
||||
[GSK_PATH_CLOSE] = 2,
|
||||
[GSK_PATH_LINE] = 2,
|
||||
[GSK_PATH_CURVE] = 4
|
||||
[GSK_PATH_CURVE] = 4,
|
||||
};
|
||||
|
||||
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))
|
||||
return FALSE;
|
||||
if (self->ops[i].op == GSK_PATH_CONIC)
|
||||
{
|
||||
graphene_point_t pts[2] = { self->points[self->ops[i].point],
|
||||
self->points[self->ops[i].point + 2] };
|
||||
float weight = self->points[self->ops[i].point + 1].x;
|
||||
|
||||
if (!func (GSK_PATH_CONIC, pts, 2, 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;
|
||||
@@ -918,6 +930,16 @@ gsk_standard_contour_print (const GskContour *contour,
|
||||
_g_string_append_point (string, &pt[3]);
|
||||
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_double (string, pt[2].x);
|
||||
g_string_append (string, ", ");
|
||||
_g_string_append_point (string, &pt[3]);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
return;
|
||||
@@ -1070,6 +1092,23 @@ gsk_standard_contour_init_measure (const GskContour *contour,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_PATH_CONIC:
|
||||
g_warning ("FIXME: Stop treating conics as lines");
|
||||
seg_length = graphene_point_distance (&pt[0], &pt[3], NULL, NULL);
|
||||
if (seg_length > 0)
|
||||
{
|
||||
g_array_append_vals (array,
|
||||
&(GskStandardContourMeasure) {
|
||||
length,
|
||||
length + seg_length,
|
||||
0, 1,
|
||||
pt[1],
|
||||
i,
|
||||
}, 1);
|
||||
length += seg_length;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
return NULL;
|
||||
@@ -1130,6 +1169,16 @@ gsk_standard_contour_measure_get_point (GskStandardContour *self,
|
||||
gsk_spline_get_point_cubic (pts, progress, pos, tangent);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CONIC:
|
||||
g_warning ("FIXME: Stop treating conics as lines");
|
||||
if (pos)
|
||||
graphene_point_interpolate (&pts[0], &pts[3], progress, pos);
|
||||
if (tangent)
|
||||
{
|
||||
graphene_vec2_init (tangent, pts[3].x - pts[0].x, pts[3].y - pts[0].y);
|
||||
graphene_vec2_normalize (tangent, tangent);
|
||||
}
|
||||
break;
|
||||
case GSK_PATH_MOVE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -1363,6 +1412,24 @@ gsk_standard_contour_add_segment (const GskContour *contour,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_PATH_CONIC:
|
||||
g_warning ("FIXME: Stop treating conics as lines");
|
||||
{
|
||||
graphene_point_t *pts = &self->points[self->ops[start_measure->op].point];
|
||||
graphene_point_t point;
|
||||
|
||||
graphene_point_interpolate (&pts[0], &pts[3], start_progress, &point);
|
||||
gsk_path_builder_move_to (builder, point.x, point.y);
|
||||
if (end_measure && end_measure->op == start_measure->op)
|
||||
{
|
||||
graphene_point_interpolate (&pts[0], &pts[3], end_progress, &point);
|
||||
gsk_path_builder_line_to (builder, point.x, point.y);
|
||||
return;
|
||||
}
|
||||
gsk_path_builder_line_to (builder, pts[3].x, pts[3].y);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_PATH_MOVE:
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
@@ -1392,6 +1459,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);
|
||||
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:
|
||||
g_assert_not_reached();
|
||||
return;
|
||||
@@ -1424,6 +1495,17 @@ gsk_standard_contour_add_segment (const GskContour *contour,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_PATH_CONIC:
|
||||
g_warning ("FIXME: Stop treating conics as lines");
|
||||
{
|
||||
graphene_point_t *pts = &self->points[self->ops[end_measure->op].point];
|
||||
graphene_point_t point;
|
||||
|
||||
graphene_point_interpolate (&pts[0], &pts[3], end_progress, &point);
|
||||
gsk_path_builder_line_to (builder, point.x, point.y);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_PATH_MOVE:
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
@@ -1804,6 +1886,7 @@ static gboolean
|
||||
gsk_path_to_cairo_add_op (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
float weight,
|
||||
gpointer cr)
|
||||
{
|
||||
switch (op)
|
||||
@@ -1824,6 +1907,11 @@ 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);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CONIC:
|
||||
g_warning ("FIXME: Stop treating conics as lines");
|
||||
cairo_line_to (cr, pts[3].x, pts[3].y);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
|
||||
@@ -34,6 +34,7 @@ G_BEGIN_DECLS
|
||||
* @op: The operation to perform
|
||||
* @pts: The points of the operation
|
||||
* @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
|
||||
*
|
||||
* Prototype of the callback to iterate throught the operations of
|
||||
@@ -45,6 +46,7 @@ G_BEGIN_DECLS
|
||||
typedef gboolean (* GskPathForeachFunc) (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
float weight,
|
||||
gpointer user_data);
|
||||
|
||||
#define GSK_TYPE_PATH (gsk_path_get_type ())
|
||||
|
||||
@@ -446,6 +446,41 @@ gsk_path_builder_curve_to (GskPathBuilder *builder,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
void
|
||||
gsk_path_builder_conic_to (GskPathBuilder *builder,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float weight)
|
||||
{
|
||||
g_return_if_fail (builder != NULL);
|
||||
|
||||
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_close:
|
||||
* @builder: a #GskPathBuilder
|
||||
|
||||
@@ -73,6 +73,13 @@ void gsk_path_builder_curve_to (GskPathBuilder
|
||||
float x3,
|
||||
float y3);
|
||||
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_close (GskPathBuilder *builder);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
Reference in New Issue
Block a user