Add quadratic curves
This commit is contained in:
@@ -246,6 +246,10 @@ build_path (GskPathOperation op,
|
||||
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
gsk_path_builder_quad_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
gsk_path_builder_cubic_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
|
||||
break;
|
||||
|
||||
@@ -122,6 +122,14 @@ gtk_path_transform_op (GskPathOperation op,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
{
|
||||
graphene_point_t res[2];
|
||||
gtk_path_transform_point (transform->measure, &pts[1], &transform->offset, transform->scale, &res[0]);
|
||||
gtk_path_transform_point (transform->measure, &pts[2], &transform->offset, transform->scale, &res[1]);
|
||||
gsk_path_builder_quad_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y);
|
||||
}
|
||||
break;
|
||||
case GSK_PATH_CUBIC:
|
||||
{
|
||||
graphene_point_t res[3];
|
||||
|
||||
@@ -982,6 +982,13 @@ gsk_standard_contour_print (const GskContour *contour,
|
||||
_g_string_append_point (string, &pt[1]);
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
g_string_append (string, " Q ");
|
||||
_g_string_append_point (string, &pt[1]);
|
||||
g_string_append (string, ", ");
|
||||
_g_string_append_point (string, &pt[2]);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
g_string_append (string, " C ");
|
||||
_g_string_append_point (string, &pt[1]);
|
||||
|
||||
220
gsk/gskcurve.c
220
gsk/gskcurve.c
@@ -218,6 +218,225 @@ static const GskCurveClass GSK_LINE_CURVE_CLASS = {
|
||||
gsk_line_curve_get_start_end_tangent
|
||||
};
|
||||
|
||||
/** QUADRATIC **/
|
||||
|
||||
static void
|
||||
gsk_quad_curve_init_from_points (GskQuadCurve *self,
|
||||
const graphene_point_t pts[3])
|
||||
{
|
||||
self->op = GSK_PATH_QUAD;
|
||||
self->has_coefficients = FALSE;
|
||||
memcpy (self->points, pts, sizeof (graphene_point_t) * 3);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_quad_curve_init (GskCurve *curve,
|
||||
gskpathop op)
|
||||
{
|
||||
GskQuadCurve *self = &curve->quad;
|
||||
|
||||
gsk_quad_curve_init_from_points (self, gsk_pathop_points (op));
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_quad_curve_init_foreach (GskCurve *curve,
|
||||
GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
float weight)
|
||||
{
|
||||
GskQuadCurve *self = &curve->quad;
|
||||
|
||||
g_assert (n_pts == 3);
|
||||
|
||||
gsk_quad_curve_init_from_points (self, pts);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_quad_curve_ensure_coefficients (const GskQuadCurve *curve)
|
||||
{
|
||||
GskQuadCurve *self = (GskQuadCurve *) curve;
|
||||
const graphene_point_t *pts = self->points;
|
||||
|
||||
if (self->has_coefficients)
|
||||
return;
|
||||
|
||||
self->coeffs[2] = pts[0];
|
||||
self->coeffs[1] = GRAPHENE_POINT_INIT (2 * (pts[1].x - pts[0].x),
|
||||
2 * (pts[1].y - pts[0].y));
|
||||
self->coeffs[0] = GRAPHENE_POINT_INIT (pts[2].x - 2 * pts[1].x + pts[0].x,
|
||||
pts[2].y - 2 * pts[1].y + pts[0].y);
|
||||
|
||||
self->has_coefficients = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_quad_curve_get_point (const GskCurve *curve,
|
||||
float t,
|
||||
graphene_point_t *pos)
|
||||
{
|
||||
GskQuadCurve *self = (GskQuadCurve *) &curve->quad;
|
||||
const graphene_point_t *c = self->coeffs;
|
||||
|
||||
gsk_quad_curve_ensure_coefficients (self);
|
||||
|
||||
*pos = GRAPHENE_POINT_INIT ((c[0].x * t + c[1].x) * t + c[2].x,
|
||||
(c[0].y * t + c[1].y) * t + c[2].y);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_quad_curve_get_tangent (const GskCurve *curve,
|
||||
float t,
|
||||
graphene_vec2_t *tangent)
|
||||
{
|
||||
GskQuadCurve *self = (GskQuadCurve *) &curve->quad;
|
||||
const graphene_point_t *c = self->coeffs;
|
||||
|
||||
gsk_quad_curve_ensure_coefficients (self);
|
||||
|
||||
graphene_vec2_init (tangent,
|
||||
2.0f * c[0].x * t + c[1].x,
|
||||
2.0f * c[0].y * t + c[1].y);
|
||||
graphene_vec2_normalize (tangent, tangent);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_quad_curve_split (const GskCurve *curve,
|
||||
float progress,
|
||||
GskCurve *start,
|
||||
GskCurve *end)
|
||||
{
|
||||
GskQuadCurve *self = (GskQuadCurve *) &curve->quad;
|
||||
const graphene_point_t *pts = self->points;
|
||||
graphene_point_t ab, bc;
|
||||
graphene_point_t final;
|
||||
|
||||
graphene_point_interpolate (&pts[0], &pts[1], progress, &ab);
|
||||
graphene_point_interpolate (&pts[1], &pts[2], progress, &bc);
|
||||
graphene_point_interpolate (&ab, &bc, progress, &final);
|
||||
|
||||
if (start)
|
||||
gsk_quad_curve_init_from_points (&start->quad, (graphene_point_t[3]) { pts[0], ab, final });
|
||||
if (end)
|
||||
gsk_quad_curve_init_from_points (&end->quad, (graphene_point_t[3]) { final, bc, pts[2] });
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_quad_curve_segment (const GskCurve *curve,
|
||||
float start,
|
||||
float end,
|
||||
GskCurve *segment)
|
||||
{
|
||||
GskCurve tmp;
|
||||
|
||||
gsk_quad_curve_split (curve, start, NULL, &tmp);
|
||||
gsk_quad_curve_split (&tmp, (end - start) / (1.0f - start), segment, NULL);
|
||||
}
|
||||
|
||||
/* taken from Skia, including the very descriptive name */
|
||||
static gboolean
|
||||
gsk_quad_curve_too_curvy (const GskQuadCurve *self,
|
||||
float tolerance)
|
||||
{
|
||||
const graphene_point_t *pts = self->points;
|
||||
float dx, dy;
|
||||
|
||||
dx = fabs (pts[1].x / 2 - (pts[0].x + pts[2].x) / 4);
|
||||
dy = fabs (pts[1].y / 2 - (pts[0].y + pts[2].y) / 4);
|
||||
|
||||
return MAX (dx, dy) > tolerance;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_quad_curve_decompose_step (const GskCurve *curve,
|
||||
float start_progress,
|
||||
float end_progress,
|
||||
float tolerance,
|
||||
GskCurveAddLineFunc add_line_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
const GskQuadCurve *self = &curve->quad;
|
||||
GskCurve left, right;
|
||||
float mid_progress;
|
||||
|
||||
if (!gsk_quad_curve_too_curvy (self, tolerance))
|
||||
return add_line_func (&self->points[0], &self->points[2], start_progress, end_progress, GSK_CURVE_LINE_REASON_STRAIGHT, user_data);
|
||||
if (end_progress - start_progress <= MIN_PROGRESS)
|
||||
return add_line_func (&self->points[0], &self->points[2], start_progress, end_progress, GSK_CURVE_LINE_REASON_SHORT, user_data);
|
||||
|
||||
gsk_quad_curve_split ((const GskCurve *) self, 0.5, &left, &right);
|
||||
mid_progress = (start_progress + end_progress) / 2;
|
||||
|
||||
return gsk_quad_curve_decompose_step (&left, start_progress, mid_progress, tolerance, add_line_func, user_data)
|
||||
&& gsk_quad_curve_decompose_step (&right, mid_progress, end_progress, tolerance, add_line_func, user_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_quad_curve_decompose (const GskCurve *curve,
|
||||
float tolerance,
|
||||
GskCurveAddLineFunc add_line_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
return gsk_quad_curve_decompose_step (curve, 0.0, 1.0, tolerance, add_line_func, user_data);
|
||||
}
|
||||
|
||||
static gskpathop
|
||||
gsk_quad_curve_pathop (const GskCurve *curve)
|
||||
{
|
||||
const GskQuadCurve *self = &curve->quad;
|
||||
|
||||
return gsk_pathop_encode (self->op, self->points);
|
||||
}
|
||||
|
||||
static const graphene_point_t *
|
||||
gsk_quad_curve_get_start_point (const GskCurve *curve)
|
||||
{
|
||||
const GskQuadCurve *self = &curve->quad;
|
||||
|
||||
return &self->points[0];
|
||||
}
|
||||
|
||||
static const graphene_point_t *
|
||||
gsk_quad_curve_get_end_point (const GskCurve *curve)
|
||||
{
|
||||
const GskQuadCurve *self = &curve->quad;
|
||||
|
||||
return &self->points[2];
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_quad_curve_get_start_tangent (const GskCurve *curve,
|
||||
graphene_vec2_t *tangent)
|
||||
{
|
||||
const GskQuadCurve *self = &curve->quad;
|
||||
|
||||
get_tangent (&self->points[0], &self->points[1], tangent);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_quad_curve_get_end_tangent (const GskCurve *curve,
|
||||
graphene_vec2_t *tangent)
|
||||
{
|
||||
const GskQuadCurve *self = &curve->quad;
|
||||
|
||||
get_tangent (&self->points[1], &self->points[2], tangent);
|
||||
}
|
||||
|
||||
static const GskCurveClass GSK_QUAD_CURVE_CLASS = {
|
||||
gsk_quad_curve_init,
|
||||
gsk_quad_curve_init_foreach,
|
||||
gsk_quad_curve_get_point,
|
||||
gsk_quad_curve_get_tangent,
|
||||
gsk_quad_curve_split,
|
||||
gsk_quad_curve_segment,
|
||||
gsk_quad_curve_decompose,
|
||||
gsk_quad_curve_pathop,
|
||||
gsk_quad_curve_get_start_point,
|
||||
gsk_quad_curve_get_end_point,
|
||||
gsk_quad_curve_get_start_tangent,
|
||||
gsk_quad_curve_get_end_tangent
|
||||
};
|
||||
|
||||
/** CUBIC **/
|
||||
|
||||
static void
|
||||
@@ -870,6 +1089,7 @@ get_class (GskPathOperation op)
|
||||
const GskCurveClass *klasses[] = {
|
||||
[GSK_PATH_CLOSE] = &GSK_LINE_CURVE_CLASS,
|
||||
[GSK_PATH_LINE] = &GSK_LINE_CURVE_CLASS,
|
||||
[GSK_PATH_QUAD] = &GSK_QUAD_CURVE_CLASS,
|
||||
[GSK_PATH_CUBIC] = &GSK_CUBIC_CURVE_CLASS,
|
||||
[GSK_PATH_CONIC] = &GSK_CONIC_CURVE_CLASS,
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@ typedef gpointer gskpathop;
|
||||
typedef union _GskCurve GskCurve;
|
||||
|
||||
typedef struct _GskLineCurve GskLineCurve;
|
||||
typedef struct _GskQuadCurve GskQuadCurve;
|
||||
typedef struct _GskCubicCurve GskCubicCurve;
|
||||
typedef struct _GskConicCurve GskConicCurve;
|
||||
|
||||
@@ -42,6 +43,17 @@ struct _GskLineCurve
|
||||
graphene_point_t points[2];
|
||||
};
|
||||
|
||||
struct _GskQuadCurve
|
||||
{
|
||||
GskPathOperation op;
|
||||
|
||||
gboolean has_coefficients;
|
||||
|
||||
graphene_point_t points[3];
|
||||
|
||||
graphene_point_t coeffs[3];
|
||||
};
|
||||
|
||||
struct _GskCubicCurve
|
||||
{
|
||||
GskPathOperation op;
|
||||
@@ -72,6 +84,7 @@ union _GskCurve
|
||||
{
|
||||
GskPathOperation op;
|
||||
GskLineCurve line;
|
||||
GskQuadCurve quad;
|
||||
GskCubicCurve cubic;
|
||||
GskConicCurve conic;
|
||||
};
|
||||
|
||||
@@ -257,6 +257,9 @@ typedef enum {
|
||||
* @GSK_PATH_CLOSE: A close operation ending the current contour with
|
||||
* a line back to the starting point. Two points describe the start
|
||||
* and end of the line.
|
||||
* @GSK_PATH_QUAD: A curve-to operation describing a quadratic Bézier curve
|
||||
* with 3 points describing the start point, the control point
|
||||
* and the end point of the curve.
|
||||
* @GSK_PATH_CUBIC: A curve-to operation describing a cubic Bézier curve
|
||||
* with 4 points describing the start point, the two control points
|
||||
* and the end point of the curve.
|
||||
@@ -272,6 +275,7 @@ typedef enum {
|
||||
GSK_PATH_MOVE,
|
||||
GSK_PATH_CLOSE,
|
||||
GSK_PATH_LINE,
|
||||
GSK_PATH_QUAD,
|
||||
GSK_PATH_CUBIC,
|
||||
GSK_PATH_CONIC,
|
||||
} GskPathOperation;
|
||||
|
||||
@@ -229,6 +229,17 @@ gsk_path_to_cairo_add_op (GskPathOperation op,
|
||||
cairo_line_to (cr, pts[1].x, pts[1].y);
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
{
|
||||
double x, y;
|
||||
cairo_get_current_point (cr, &x, &y);
|
||||
cairo_curve_to (cr,
|
||||
1/3.f * x + 2/3.f * pts[1].x, 1/3.f * y + 2/3.f * pts[1].y,
|
||||
2/3.f * pts[1].x + 1/3.f * pts[2].x, 2/3.f * pts[1].y + 1/3.f * pts[2].y,
|
||||
pts[2].x, pts[2].y);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
cairo_curve_to (cr, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
|
||||
break;
|
||||
@@ -426,6 +437,7 @@ gsk_path_foreach_trampoline (GskPathOperation op,
|
||||
case GSK_PATH_LINE:
|
||||
return trampoline->func (op, pts, n_pts, weight, trampoline->user_data);
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
case GSK_PATH_CUBIC:
|
||||
{
|
||||
GskCurve curve;
|
||||
@@ -971,7 +983,7 @@ gsk_path_parse (const char *string)
|
||||
case 'Q':
|
||||
case 'q':
|
||||
{
|
||||
double x1, y1, x2, y2, xx1, yy1, xx2, yy2;
|
||||
double x1, y1, x2, y2;
|
||||
|
||||
if (parse_coordinate_pair (&p, &x1, &y1) &&
|
||||
parse_coordinate_pair (&p, &x2, &y2))
|
||||
@@ -983,17 +995,13 @@ gsk_path_parse (const char *string)
|
||||
x2 += x;
|
||||
y2 += y;
|
||||
}
|
||||
xx1 = (x + 2.0 * x1) / 3.0;
|
||||
yy1 = (y + 2.0 * y1) / 3.0;
|
||||
xx2 = (x2 + 2.0 * x1) / 3.0;
|
||||
yy2 = (y2 + 2.0 * y1) / 3.0;
|
||||
if (_strchr ("zZ", prev_cmd))
|
||||
{
|
||||
gsk_path_builder_move_to (builder, x, y);
|
||||
path_x = x;
|
||||
path_y = y;
|
||||
}
|
||||
gsk_path_builder_cubic_to (builder, xx1, yy1, xx2, yy2, x2, y2);
|
||||
gsk_path_builder_quad_to (builder, x1, y1, x2, y2);
|
||||
prev_x1 = x1;
|
||||
prev_y1 = y1;
|
||||
x = x2;
|
||||
@@ -1007,7 +1015,7 @@ gsk_path_parse (const char *string)
|
||||
case 'T':
|
||||
case 't':
|
||||
{
|
||||
double x1, y1, x2, y2, xx1, yy1, xx2, yy2;
|
||||
double x1, y1, x2, y2;
|
||||
|
||||
if (parse_coordinate_pair (&p, &x2, &y2))
|
||||
{
|
||||
@@ -1026,17 +1034,13 @@ gsk_path_parse (const char *string)
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
}
|
||||
xx1 = (x + 2.0 * x1) / 3.0;
|
||||
yy1 = (y + 2.0 * y1) / 3.0;
|
||||
xx2 = (x2 + 2.0 * x1) / 3.0;
|
||||
yy2 = (y2 + 2.0 * y1) / 3.0;
|
||||
if (_strchr ("zZ", prev_cmd))
|
||||
{
|
||||
gsk_path_builder_move_to (builder, x, y);
|
||||
path_x = x;
|
||||
path_y = y;
|
||||
}
|
||||
gsk_path_builder_cubic_to (builder, xx1, yy1, xx2, yy2, x2, y2);
|
||||
gsk_path_builder_quad_to (builder, x1, y1, x2, y2);
|
||||
prev_x1 = x1;
|
||||
prev_y1 = y1;
|
||||
x = x2;
|
||||
|
||||
@@ -652,6 +652,67 @@ gsk_path_builder_rel_line_to (GskPathBuilder *self,
|
||||
self->current_point.y + y);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_builder_quad_to:
|
||||
* @self: 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
|
||||
*
|
||||
* Adds a [quadratic Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve)
|
||||
* from the current point to @x2, @y2 with @x1, @y1 as the control point.
|
||||
*
|
||||
* After this, @x2, @y2 will be the new current point.
|
||||
**/
|
||||
void
|
||||
gsk_path_builder_quad_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
self->flags &= ~GSK_PATH_FLAT;
|
||||
gsk_path_builder_append_current (self,
|
||||
GSK_PATH_QUAD,
|
||||
2, (graphene_point_t[2]) {
|
||||
GRAPHENE_POINT_INIT (x1, y1),
|
||||
GRAPHENE_POINT_INIT (x2, y2)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_builder_rel_quad_to:
|
||||
* @self: a #GskPathBuilder
|
||||
* @x1: x offset of control point
|
||||
* @y1: y offset of control point
|
||||
* @x3: x offset of the end of the curve
|
||||
* @y3: y offset of the end of the curve
|
||||
*
|
||||
* Adds a [quadratic Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve)
|
||||
* from the current point to @x2, @y2 with @x1, @y1 as the control point.
|
||||
* All coordinates are given relative to the current point.
|
||||
*
|
||||
* This is the relative version of gsk_path_builder_quad_to().
|
||||
**/
|
||||
void
|
||||
gsk_path_builder_rel_quad_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
gsk_path_builder_quad_to (self,
|
||||
self->current_point.x + x1,
|
||||
self->current_point.y + y1,
|
||||
self->current_point.x + x2,
|
||||
self->current_point.y + y2);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_builder_cubic_to:
|
||||
* @self: a #GskPathBuilder
|
||||
|
||||
@@ -97,6 +97,18 @@ void gsk_path_builder_rel_line_to (GskPathBuilder
|
||||
float x,
|
||||
float y);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gsk_path_builder_quad_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gsk_path_builder_rel_quad_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gsk_path_builder_cubic_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
|
||||
@@ -215,6 +215,7 @@ gsk_path_dash_foreach (GskPathOperation op,
|
||||
G_GNUC_FALLTHROUGH;
|
||||
|
||||
case GSK_PATH_LINE:
|
||||
case GSK_PATH_QUAD:
|
||||
case GSK_PATH_CUBIC:
|
||||
case GSK_PATH_CONIC:
|
||||
gsk_curve_init_foreach (&self->curve, op, pts, n_pts, weight);
|
||||
|
||||
@@ -89,6 +89,9 @@ gsk_pathop_foreach (gskpathop pop,
|
||||
case GSK_PATH_LINE:
|
||||
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 2, 0, user_data);
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 3, 0, user_data);
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 4, 0, user_data);
|
||||
|
||||
@@ -124,6 +127,10 @@ gsk_path_builder_pathop_to (GskPathBuilder *builder,
|
||||
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
gsk_path_builder_quad_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
gsk_path_builder_cubic_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
|
||||
break;
|
||||
@@ -158,6 +165,10 @@ gsk_path_builder_pathop_reverse_to (GskPathBuilder *builder,
|
||||
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
gsk_path_builder_quad_to (builder, pts[1].x, pts[1].y, pts[0].x, pts[0].y);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
gsk_path_builder_cubic_to (builder, pts[2].x, pts[2].y, pts[1].x, pts[1].y, pts[0].x, pts[0].y);
|
||||
break;
|
||||
|
||||
@@ -32,6 +32,17 @@ init_random_curve (GskCurve *curve)
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
{
|
||||
graphene_point_t p[3];
|
||||
|
||||
init_random_point (&p[0]);
|
||||
init_random_point (&p[1]);
|
||||
init_random_point (&p[2]);
|
||||
gsk_curve_init (curve, gsk_pathop_encode (GSK_PATH_QUAD, p));
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
{
|
||||
graphene_point_t p[4];
|
||||
|
||||
@@ -44,6 +44,10 @@ build_path (GskPathOperation op,
|
||||
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
gsk_path_builder_quad_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
gsk_path_builder_cubic_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
|
||||
break;
|
||||
|
||||
@@ -248,7 +248,7 @@ add_standard_contour (GskPathBuilder *builder)
|
||||
n = g_test_rand_int_range (1, 20);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
switch (g_test_rand_int_range (0, 6))
|
||||
switch (g_test_rand_int_range (0, 8))
|
||||
{
|
||||
case 0:
|
||||
gsk_path_builder_line_to (builder,
|
||||
@@ -263,6 +263,22 @@ add_standard_contour (GskPathBuilder *builder)
|
||||
break;
|
||||
|
||||
case 2:
|
||||
gsk_path_builder_quad_to (builder,
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
gsk_path_builder_rel_quad_to (builder,
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
gsk_path_builder_cubic_to (builder,
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
@@ -272,7 +288,7 @@ add_standard_contour (GskPathBuilder *builder)
|
||||
g_test_rand_double_range (-1000, 1000));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 5:
|
||||
gsk_path_builder_rel_cubic_to (builder,
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
@@ -282,7 +298,7 @@ add_standard_contour (GskPathBuilder *builder)
|
||||
g_test_rand_double_range (-1000, 1000));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 6:
|
||||
gsk_path_builder_conic_to (builder,
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
@@ -291,7 +307,7 @@ add_standard_contour (GskPathBuilder *builder)
|
||||
random_weight ());
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case 7:
|
||||
gsk_path_builder_rel_conic_to (builder,
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000),
|
||||
@@ -381,6 +397,13 @@ path_operation_print (const PathOperation *p,
|
||||
_g_string_append_point (string, &p->pts[1]);
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
g_string_append (string, " Q ");
|
||||
_g_string_append_point (string, &p->pts[1]);
|
||||
g_string_append (string, ", ");
|
||||
_g_string_append_point (string, &p->pts[2]);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
g_string_append (string, " C ");
|
||||
_g_string_append_point (string, &p->pts[1]);
|
||||
@@ -425,6 +448,10 @@ path_operation_equal (const PathOperation *p1,
|
||||
case GSK_PATH_CLOSE:
|
||||
return graphene_point_near (&p1->pts[1], &p2->pts[1], epsilon);
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
return graphene_point_near (&p1->pts[1], &p2->pts[1], epsilon)
|
||||
&& graphene_point_near (&p1->pts[2], &p2->pts[2], epsilon);
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
return graphene_point_near (&p1->pts[1], &p2->pts[1], epsilon)
|
||||
&& graphene_point_near (&p1->pts[2], &p2->pts[2], epsilon)
|
||||
@@ -1063,6 +1090,11 @@ rotate_path_cb (GskPathOperation op,
|
||||
gsk_path_builder_line_to (builders[1], pts[1].y, -pts[1].x);
|
||||
break;
|
||||
|
||||
case GSK_PATH_QUAD:
|
||||
gsk_path_builder_quad_to (builders[0], pts[1].x, pts[1].y, pts[2].x, pts[2].y);
|
||||
gsk_path_builder_quad_to (builders[1], pts[1].y, -pts[1].x, pts[2].y, -pts[2].x);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CUBIC:
|
||||
gsk_path_builder_cubic_to (builders[0], pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
|
||||
gsk_path_builder_cubic_to (builders[1], pts[1].y, -pts[1].x, pts[2].y, -pts[2].x, pts[3].y, -pts[3].x);
|
||||
|
||||
Reference in New Issue
Block a user