Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 244cdafe1b | |||
| a0d17418de | |||
| 093e6241e7 | |||
| 67b504f823 | |||
| 659bc813a4 | |||
| 293c0774b3 | |||
| 988062889b | |||
| 461922b495 | |||
| 7150a53ccb | |||
| 1e306b148e |
@@ -2857,10 +2857,7 @@ gdk_event_translate (MSG *msg,
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
/* From: https://learn.microsoft.com/en-us/windows/win32/menurc/wm-syscommand?redirectedfrom=MSDN
|
||||
* To obtain the correct result when testing the value of wParam,
|
||||
* an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator. */
|
||||
switch (msg->wParam & 0xFFF0)
|
||||
switch (msg->wParam)
|
||||
{
|
||||
case SC_MINIMIZE:
|
||||
case SC_RESTORE:
|
||||
@@ -2967,14 +2964,6 @@ gdk_event_translate (MSG *msg,
|
||||
windowpos = (WINDOWPOS *) msg->lParam;
|
||||
windowpos->cx = our_mmi.ptMaxSize.x;
|
||||
windowpos->cy = our_mmi.ptMaxSize.y;
|
||||
|
||||
if (!_gdk_win32_surface_lacks_wm_decorations (window) &&
|
||||
!(windowpos->flags & SWP_NOCLIENTSIZE) &&
|
||||
window->width == impl->next_layout.configured_width &&
|
||||
window->height == impl->next_layout.configured_height)
|
||||
{
|
||||
impl->inhibit_configure = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
impl->maximizing = FALSE;
|
||||
|
||||
@@ -1230,11 +1230,18 @@ get_effective_window_decorations (GdkSurface *window,
|
||||
|
||||
*decoration |= GDK_DECOR_MINIMIZE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (impl->hint_flags & GDK_HINT_MAX_SIZE)
|
||||
{
|
||||
*decoration = GDK_DECOR_ALL | GDK_DECOR_MAXIMIZE;
|
||||
*decoration |= GDK_DECOR_MINIMIZE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*decoration = GDK_DECOR_ALL;
|
||||
*decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
+459
-385
File diff suppressed because it is too large
Load Diff
+19
-7
@@ -57,7 +57,7 @@ void gsk_contour_get_start_end (const GskContou
|
||||
graphene_point_t *end);
|
||||
int gsk_contour_get_winding (const GskContour *self,
|
||||
const graphene_point_t *point);
|
||||
gsize gsk_contour_get_n_points (const GskContour *self);
|
||||
|
||||
gboolean gsk_contour_get_closest_point (const GskContour *self,
|
||||
const graphene_point_t *point,
|
||||
float threshold,
|
||||
@@ -75,6 +75,14 @@ void gsk_contour_get_tangent (const GskContou
|
||||
float gsk_contour_get_curvature (const GskContour *self,
|
||||
GskRealPathPoint *point,
|
||||
graphene_point_t *center);
|
||||
gpointer gsk_contour_init_measure (const GskContour *self,
|
||||
float tolerance,
|
||||
float *out_length);
|
||||
void gsk_contour_free_measure (const GskContour *self,
|
||||
gpointer data);
|
||||
int gsk_contour_point_compare (const GskContour *self,
|
||||
GskRealPathPoint *p1,
|
||||
GskRealPathPoint *p2);
|
||||
|
||||
void gsk_contour_add_segment (const GskContour *self,
|
||||
GskPathBuilder *builder,
|
||||
@@ -82,16 +90,20 @@ void gsk_contour_add_segment (const GskContou
|
||||
GskRealPathPoint *start,
|
||||
GskRealPathPoint *end);
|
||||
|
||||
|
||||
gpointer gsk_contour_init_measure (const GskContour *self,
|
||||
float tolerance,
|
||||
float *out_length);
|
||||
void gsk_contour_free_measure (const GskContour *self,
|
||||
gpointer data);
|
||||
void gsk_contour_get_point (const GskContour *self,
|
||||
gpointer measure_data,
|
||||
float offset,
|
||||
GskRealPathPoint *result);
|
||||
void gsk_contour_get_start_point (const GskContour *self,
|
||||
GskRealPathPoint *result);
|
||||
void gsk_contour_get_end_point (const GskContour *self,
|
||||
GskRealPathPoint *result);
|
||||
gboolean gsk_contour_get_previous_point (const GskContour *self,
|
||||
GskRealPathPoint *point,
|
||||
GskRealPathPoint *result);
|
||||
gboolean gsk_contour_get_next_point (const GskContour *self,
|
||||
GskRealPathPoint *point,
|
||||
GskRealPathPoint *result);
|
||||
float gsk_contour_get_distance (const GskContour *self,
|
||||
GskRealPathPoint *point,
|
||||
gpointer measure_data);
|
||||
|
||||
+38
-131
@@ -24,7 +24,7 @@
|
||||
|
||||
/* GskCurve collects all the functionality we need for Bézier segments */
|
||||
|
||||
#define MIN_PROGRESS (1/2048.f)
|
||||
#define MIN_PROGRESS (1/1024.f)
|
||||
|
||||
typedef struct _GskCurveClass GskCurveClass;
|
||||
|
||||
@@ -524,6 +524,20 @@ gsk_quad_curve_segment (const GskCurve *curve,
|
||||
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,
|
||||
@@ -536,8 +550,8 @@ gsk_quad_curve_decompose_step (const GskCurve *curve,
|
||||
GskCurve left, right;
|
||||
float mid_progress;
|
||||
|
||||
if (graphene_point_distance (&self->points[0], &self->points[2], NULL, NULL) < tolerance)
|
||||
return add_line_func (&self->points[0], &self->points[2], start_progress, end_progress, GSK_CURVE_LINE_REASON_SHORT, user_data);
|
||||
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);
|
||||
|
||||
@@ -980,6 +994,25 @@ gsk_cubic_curve_segment (const GskCurve *curve,
|
||||
gsk_cubic_curve_split (&tmp, (end - start) / (1.0f - start), segment, NULL);
|
||||
}
|
||||
|
||||
/* taken from Skia, including the very descriptive name */
|
||||
static gboolean
|
||||
gsk_cubic_curve_too_curvy (const GskCubicCurve *self,
|
||||
float tolerance)
|
||||
{
|
||||
const graphene_point_t *pts = self->points;
|
||||
graphene_point_t p;
|
||||
|
||||
graphene_point_interpolate (&pts[0], &pts[3], 1.0f / 3, &p);
|
||||
if (MAX (ABS (p.x - pts[1].x), ABS (p.y - pts[1].y)) > tolerance)
|
||||
return TRUE;
|
||||
|
||||
graphene_point_interpolate (&pts[0], &pts[3], 2.0f / 3, &p);
|
||||
if (MAX (ABS (p.x - pts[2].x), ABS (p.y - pts[2].y)) > tolerance)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_cubic_curve_decompose_step (const GskCurve *curve,
|
||||
float start_progress,
|
||||
@@ -992,8 +1025,8 @@ gsk_cubic_curve_decompose_step (const GskCurve *curve,
|
||||
GskCurve left, right;
|
||||
float mid_progress;
|
||||
|
||||
if (graphene_point_distance (&self->points[0], &self->points[3], NULL, NULL) < tolerance)
|
||||
return add_line_func (&self->points[0], &self->points[3], start_progress, end_progress, GSK_CURVE_LINE_REASON_SHORT, user_data);
|
||||
if (!gsk_cubic_curve_too_curvy (self, tolerance))
|
||||
return add_line_func (&self->points[0], &self->points[3], 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[3], start_progress, end_progress, GSK_CURVE_LINE_REASON_SHORT, user_data);
|
||||
|
||||
@@ -1495,132 +1528,6 @@ gsk_curve_get_closest_point (const GskCurve *curve,
|
||||
return find_closest_point (curve, point, threshold, 0, 1, out_dist, out_t);
|
||||
}
|
||||
|
||||
/* Legendre-Gauss values for n=24,
|
||||
* see https://pomax.github.io/bezierinfo/legendre-gauss.html
|
||||
*/
|
||||
|
||||
const double T[] = {
|
||||
-0.0640568928626056260850430826247450385909,
|
||||
0.0640568928626056260850430826247450385909,
|
||||
-0.1911188674736163091586398207570696318404,
|
||||
0.1911188674736163091586398207570696318404,
|
||||
-0.3150426796961633743867932913198102407864,
|
||||
0.3150426796961633743867932913198102407864,
|
||||
-0.4337935076260451384870842319133497124524,
|
||||
0.4337935076260451384870842319133497124524,
|
||||
-0.5454214713888395356583756172183723700107,
|
||||
0.5454214713888395356583756172183723700107,
|
||||
-0.6480936519369755692524957869107476266696,
|
||||
0.6480936519369755692524957869107476266696,
|
||||
-0.7401241915785543642438281030999784255232,
|
||||
0.7401241915785543642438281030999784255232,
|
||||
-0.8200019859739029219539498726697452080761,
|
||||
0.8200019859739029219539498726697452080761,
|
||||
-0.8864155270044010342131543419821967550873,
|
||||
0.8864155270044010342131543419821967550873,
|
||||
-0.9382745520027327585236490017087214496548,
|
||||
0.9382745520027327585236490017087214496548,
|
||||
-0.9747285559713094981983919930081690617411,
|
||||
0.9747285559713094981983919930081690617411,
|
||||
-0.9951872199970213601799974097007368118745,
|
||||
0.9951872199970213601799974097007368118745,
|
||||
};
|
||||
|
||||
const double C[] = {
|
||||
0.1279381953467521569740561652246953718517,
|
||||
0.1279381953467521569740561652246953718517,
|
||||
0.1258374563468282961213753825111836887264,
|
||||
0.1258374563468282961213753825111836887264,
|
||||
0.121670472927803391204463153476262425607,
|
||||
0.121670472927803391204463153476262425607,
|
||||
0.1155056680537256013533444839067835598622,
|
||||
0.1155056680537256013533444839067835598622,
|
||||
0.1074442701159656347825773424466062227946,
|
||||
0.1074442701159656347825773424466062227946,
|
||||
0.0976186521041138882698806644642471544279,
|
||||
0.0976186521041138882698806644642471544279,
|
||||
0.086190161531953275917185202983742667185,
|
||||
0.086190161531953275917185202983742667185,
|
||||
0.0733464814110803057340336152531165181193,
|
||||
0.0733464814110803057340336152531165181193,
|
||||
0.0592985849154367807463677585001085845412,
|
||||
0.0592985849154367807463677585001085845412,
|
||||
0.0442774388174198061686027482113382288593,
|
||||
0.0442774388174198061686027482113382288593,
|
||||
0.0285313886289336631813078159518782864491,
|
||||
0.0285313886289336631813078159518782864491,
|
||||
0.0123412297999871995468056670700372915759,
|
||||
0.0123412297999871995468056670700372915759,
|
||||
};
|
||||
|
||||
/* Compute arclength by using Gauss quadrature on
|
||||
*
|
||||
* \int_0^z \sqrt{ (dx/dt)^2 + (dy/dt)^2 } dt
|
||||
*/
|
||||
float
|
||||
gsk_curve_get_length (const GskCurve *curve)
|
||||
{
|
||||
double z = 0.5;
|
||||
double sum;
|
||||
GskCurve derivative;
|
||||
graphene_point_t d;
|
||||
|
||||
if (curve->op == GSK_PATH_LINE ||
|
||||
curve->op == GSK_PATH_CLOSE)
|
||||
return graphene_point_distance (gsk_curve_get_start_point (curve),
|
||||
gsk_curve_get_end_point (curve),
|
||||
NULL, NULL);
|
||||
|
||||
gsk_curve_get_derivative (curve, &derivative);
|
||||
|
||||
sum = 0;
|
||||
|
||||
for (unsigned int i = 0; i < G_N_ELEMENTS (T); i++)
|
||||
{
|
||||
double t = z * T[i] + z;
|
||||
gsk_curve_get_point (&derivative, t, &d);
|
||||
sum += C[i] * sqrt (d.x * d.x + d.y * d.y);
|
||||
}
|
||||
|
||||
return z * sum;
|
||||
}
|
||||
|
||||
/* Compute the inverse of the arclength using bisection,
|
||||
* to a given precision
|
||||
*/
|
||||
float
|
||||
gsk_curve_at_length (const GskCurve *curve,
|
||||
float length,
|
||||
float epsilon)
|
||||
{
|
||||
float t1, t2, t, l;
|
||||
GskCurve c1;
|
||||
//int loop_count = 0;
|
||||
|
||||
t1 = 0;
|
||||
t2 = 1;
|
||||
|
||||
while (t1 < t2)
|
||||
{
|
||||
//loop_count++;
|
||||
t = (t1 + t2) / 2;
|
||||
|
||||
gsk_curve_split (curve, t, &c1, NULL);
|
||||
|
||||
l = gsk_curve_get_length (&c1);
|
||||
if (fabs (length - l) < epsilon)
|
||||
break;
|
||||
else if (l < length)
|
||||
t1 = t;
|
||||
else
|
||||
t2 = t;
|
||||
}
|
||||
|
||||
//g_print ("loop count %d\n", loop_count);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
|
||||
@@ -153,10 +153,5 @@ gboolean gsk_curve_get_closest_point (const GskCurve
|
||||
float *out_dist,
|
||||
float *out_t);
|
||||
|
||||
float gsk_curve_get_length (const GskCurve *curve);
|
||||
float gsk_curve_at_length (const GskCurve *curve,
|
||||
float distance,
|
||||
float epsilon);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/* GSK - The GTK Scene Kit
|
||||
* Copyright 2016 Endless
|
||||
* Copyright 2016 Endless
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -42,6 +42,8 @@
|
||||
* @GSK_REPEAT_NODE: A node that repeats the child's contents
|
||||
* @GSK_CLIP_NODE: A node that clips its child to a rectangular area
|
||||
* @GSK_ROUNDED_CLIP_NODE: A node that clips its child to a rounded rectangle
|
||||
* @GSK_FILL_NODE: A node that fills a path
|
||||
* @GSK_STROKE_NODE: A node that strokes a path
|
||||
* @GSK_SHADOW_NODE: A node that draws a shadow below its child
|
||||
* @GSK_BLEND_NODE: A node that blends two children together
|
||||
* @GSK_CROSS_FADE_NODE: A node that cross-fades between two children
|
||||
@@ -51,9 +53,7 @@
|
||||
* @GSK_GL_SHADER_NODE: A node that uses OpenGL fragment shaders to render
|
||||
* @GSK_TEXTURE_SCALE_NODE: A node drawing a `GdkTexture` scaled and filtered (Since: 4.10)
|
||||
* @GSK_MASK_NODE: A node that masks one child with another (Since: 4.10)
|
||||
* @GSK_FILL_NODE: A node that fills a path
|
||||
* @GSK_STROKE_NODE: A node that strokes a path
|
||||
|
||||
|
||||
* The type of a node determines what the node is rendering.
|
||||
*/
|
||||
typedef enum {
|
||||
@@ -76,6 +76,8 @@ typedef enum {
|
||||
GSK_REPEAT_NODE,
|
||||
GSK_CLIP_NODE,
|
||||
GSK_ROUNDED_CLIP_NODE,
|
||||
GSK_FILL_NODE,
|
||||
GSK_STROKE_NODE,
|
||||
GSK_SHADOW_NODE,
|
||||
GSK_BLEND_NODE,
|
||||
GSK_CROSS_FADE_NODE,
|
||||
@@ -84,9 +86,7 @@ typedef enum {
|
||||
GSK_DEBUG_NODE,
|
||||
GSK_GL_SHADER_NODE,
|
||||
GSK_TEXTURE_SCALE_NODE,
|
||||
GSK_MASK_NODE,
|
||||
GSK_FILL_NODE,
|
||||
GSK_STROKE_NODE
|
||||
GSK_MASK_NODE
|
||||
} GskRenderNodeType;
|
||||
|
||||
/**
|
||||
|
||||
+240
-69
@@ -42,8 +42,6 @@
|
||||
* Conceptually, a path consists of zero or more contours (continous, connected
|
||||
* curves), each of which may or may not be closed. Contours are typically
|
||||
* constructed from Bézier segments.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
|
||||
struct _GskPath
|
||||
@@ -422,7 +420,6 @@ gsk_path_get_bounds (GskPath *self,
|
||||
*
|
||||
* Returns: `TRUE` if the path has bounds, `FALSE` if the path is known
|
||||
* to be empty and have no bounds.
|
||||
* Since: 4.14
|
||||
*/
|
||||
gboolean
|
||||
gsk_path_get_stroke_bounds (GskPath *self,
|
||||
@@ -493,72 +490,6 @@ gsk_path_in_fill (GskPath *self,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_get_start_point:
|
||||
* @self: a `GskPath`
|
||||
* @result: (out caller-allocates): return location for point
|
||||
*
|
||||
* Gets the start point of the path.
|
||||
*
|
||||
* An empty path has no points, so `FALSE`
|
||||
* is returned in this case.
|
||||
*
|
||||
* Returns: `TRUE` if @result was filled
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
gboolean
|
||||
gsk_path_get_start_point (GskPath *self,
|
||||
GskPathPoint *result)
|
||||
{
|
||||
GskRealPathPoint *res = (GskRealPathPoint *) result;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (result != NULL, FALSE);
|
||||
|
||||
if (self->n_contours == 0)
|
||||
return FALSE;
|
||||
|
||||
res->contour = 0;
|
||||
res->idx = 1;
|
||||
res->t = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_get_end_point:
|
||||
* @self: a `GskPath`
|
||||
* @result: (out caller-allocates): return location for point
|
||||
*
|
||||
* Gets the end point of the path.
|
||||
*
|
||||
* An empty path has no points, so `FALSE`
|
||||
* is returned in this case.
|
||||
*
|
||||
* Returns: `TRUE` if @result was filled
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
gboolean
|
||||
gsk_path_get_end_point (GskPath *self,
|
||||
GskPathPoint *result)
|
||||
{
|
||||
GskRealPathPoint *res = (GskRealPathPoint *) result;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (result != NULL, FALSE);
|
||||
|
||||
if (self->n_contours == 0)
|
||||
return FALSE;
|
||||
|
||||
res->contour = self->n_contours - 1;
|
||||
res->idx = gsk_contour_get_n_points (self->contours[self->n_contours - 1]) - 1;
|
||||
res->t = 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_get_closest_point:
|
||||
* @self: a `GskPath`
|
||||
@@ -601,6 +532,7 @@ gsk_path_get_closest_point (GskPath *self,
|
||||
{
|
||||
found = TRUE;
|
||||
res->contour = i;
|
||||
res->path = self;
|
||||
threshold = distance;
|
||||
}
|
||||
}
|
||||
@@ -608,6 +540,74 @@ gsk_path_get_closest_point (GskPath *self,
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_get_start_point:
|
||||
* @self: a `GskPath`
|
||||
* @result: (out caller-allocates): return location for point
|
||||
*
|
||||
* Gets the start point of the path.
|
||||
*
|
||||
* An empty path has no points, so `FALSE`
|
||||
* is returned in this case.
|
||||
*
|
||||
* Returns: `TRUE` if @result was filled
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
gboolean
|
||||
gsk_path_get_start_point (GskPath *self,
|
||||
GskPathPoint *result)
|
||||
{
|
||||
GskRealPathPoint *res = (GskRealPathPoint *) result;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (result != NULL, FALSE);
|
||||
|
||||
if (self->n_contours == 0)
|
||||
return FALSE;
|
||||
|
||||
gsk_contour_get_start_point (self->contours[0], res);
|
||||
|
||||
res->path = self;
|
||||
res->contour = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_get_end_point:
|
||||
* @self: a `GskPath`
|
||||
* @result: (out caller-allocates): return location for point
|
||||
*
|
||||
* Gets the end point of the path.
|
||||
*
|
||||
* An empty path has no points, so `FALSE`
|
||||
* is returned in this case.
|
||||
*
|
||||
* Returns: `TRUE` if @result was filled
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
gboolean
|
||||
gsk_path_get_end_point (GskPath *self,
|
||||
GskPathPoint *result)
|
||||
{
|
||||
GskRealPathPoint *res = (GskRealPathPoint *) result;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (result!= NULL, FALSE);
|
||||
|
||||
if (self->n_contours == 0)
|
||||
return FALSE;
|
||||
|
||||
gsk_contour_get_end_point (self->contours[self->n_contours - 1], res);
|
||||
|
||||
res->path = self;
|
||||
res->contour = self->n_contours - 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_foreach:
|
||||
* @self: a `GskPath`
|
||||
@@ -1391,3 +1391,174 @@ error:
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_builder_add_segment:
|
||||
* @self: a `GskPathBuilder`
|
||||
* @path: the `GskPath` to take the segment to
|
||||
* @start: the point on @path to start at
|
||||
* @end: the point on @path to end at
|
||||
*
|
||||
* Adds to @self the segment of @path from @start to @end.
|
||||
*
|
||||
* If @start is after @end, the path will first add the segment
|
||||
* from @start to the end of the path, and then add the segment from
|
||||
* the beginning to @end. If the path is closed, these segments will
|
||||
* be connected.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gsk_path_builder_add_segment (GskPathBuilder *self,
|
||||
GskPath *path,
|
||||
const GskPathPoint *start,
|
||||
const GskPathPoint *end)
|
||||
{
|
||||
GskRealPathPoint *s = (GskRealPathPoint *) start;
|
||||
GskRealPathPoint *e = (GskRealPathPoint *) end;
|
||||
const GskContour *contour;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (path != NULL);
|
||||
g_return_if_fail (path == s->path);
|
||||
g_return_if_fail (path == e->path);
|
||||
|
||||
contour = gsk_path_get_contour (path, s->contour);
|
||||
|
||||
if (s->contour == e->contour)
|
||||
{
|
||||
if (gsk_contour_point_compare (contour, s, e) < 0)
|
||||
{
|
||||
gsk_contour_add_segment (contour, self, TRUE, s, e);
|
||||
return;
|
||||
}
|
||||
else if (path->n_contours == 1)
|
||||
{
|
||||
gsk_contour_add_segment (contour, self, TRUE, s, NULL);
|
||||
gsk_contour_add_segment (contour, self, FALSE, NULL, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gsk_contour_add_segment (contour, self, TRUE, s, NULL);
|
||||
|
||||
for (gsize i = (s->contour + 1) % path->n_contours; i != e->contour; i = (i + 1) % path->n_contours)
|
||||
gsk_path_builder_add_contour (self, gsk_contour_dup (gsk_path_get_contour (path, i)));
|
||||
|
||||
contour = gsk_path_get_contour (path, e->contour);
|
||||
gsk_contour_add_segment (contour, self, FALSE, NULL, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_get_previous_point:
|
||||
* @self: a `GskPath`
|
||||
* @point: a point on @self
|
||||
* @result: (out caller-allocates): Return location for the result
|
||||
*
|
||||
* Gets the previous 'significant' point on @self before @point.
|
||||
*
|
||||
* The 'significant' points of a path are typically the
|
||||
* on-curve points that have been specified when the
|
||||
* path was created.
|
||||
*
|
||||
* For example, in a path with 3 Bézier segments, the
|
||||
* significant points are the start of the first segment,
|
||||
* the start point of the second segment (which coincides
|
||||
* with the end point of the first segment), the start
|
||||
* point of the third segment, and the end point of the
|
||||
* last segment.
|
||||
*
|
||||
* If @point is the start point of the path, there is no
|
||||
* prior point, and this function returns `FALSE`.
|
||||
*
|
||||
* Returns: `TRUE` if @result has been set to a point
|
||||
*/
|
||||
gboolean
|
||||
gsk_path_get_previous_point (GskPath *self,
|
||||
const GskPathPoint *point,
|
||||
GskPathPoint *result)
|
||||
{
|
||||
GskRealPathPoint *p = (GskRealPathPoint *) point;
|
||||
GskRealPathPoint *res = (GskRealPathPoint *) result;
|
||||
const GskContour *contour;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (self == p->path, FALSE);
|
||||
|
||||
contour = gsk_path_get_contour (self, p->contour);
|
||||
|
||||
if (gsk_contour_get_previous_point (contour, p, res))
|
||||
{
|
||||
res->path = self;
|
||||
res->contour = p->contour;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (p->contour > 0)
|
||||
{
|
||||
contour = gsk_path_get_contour (self, p->contour - 1);
|
||||
gsk_contour_get_end_point (contour, res);
|
||||
res->path = self;
|
||||
res->contour = p->contour - 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_get_next_point:
|
||||
* @self: a `GskPath`
|
||||
* @point: a point on @self
|
||||
* @result: (out caller-allocates): Return location for the result
|
||||
*
|
||||
* Gets the next 'significant' point on @self after @point.
|
||||
*
|
||||
* The 'significant' points of a path are typically the
|
||||
* on-curve points that have been specified when the
|
||||
* path was created.
|
||||
*
|
||||
* For example, in a path with 3 Bézier segments, the
|
||||
* significant points are the start of the first segment,
|
||||
* the start point of the second segment (which coincides
|
||||
* with the end point of the first segment), the start
|
||||
* point of the third segment, and the end point of the
|
||||
* last segment.
|
||||
*
|
||||
* If @point is the end point of the path, there is no
|
||||
* next point, and this function returns `FALSE`.
|
||||
*
|
||||
* Returns: `TRUE` if @result has been set to a point
|
||||
*/
|
||||
gboolean
|
||||
gsk_path_get_next_point (GskPath *self,
|
||||
const GskPathPoint *point,
|
||||
GskPathPoint *result)
|
||||
{
|
||||
GskRealPathPoint *p = (GskRealPathPoint *) point;
|
||||
GskRealPathPoint *res = (GskRealPathPoint *) result;
|
||||
const GskContour *contour;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (self == p->path, FALSE);
|
||||
|
||||
contour = gsk_path_get_contour (self, p->contour);
|
||||
|
||||
if (gsk_contour_get_next_point (contour, p, res))
|
||||
{
|
||||
res->path = self;
|
||||
res->contour = p->contour;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (p->contour < self->n_contours - 1)
|
||||
{
|
||||
contour = gsk_path_get_contour (self, p->contour + 1);
|
||||
gsk_contour_get_start_point (contour, res);
|
||||
res->path = self;
|
||||
res->contour = p->contour + 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+16
-8
@@ -41,8 +41,6 @@ G_BEGIN_DECLS
|
||||
* By default, [method@Gsk.Path.foreach] will only emit a path with all operations
|
||||
* flattened to straight lines to allow for maximum compatibility. The only
|
||||
* operations emitted will be `GSK_PATH_MOVE`, `GSK_PATH_LINE` and `GSK_PATH_CLOSE`.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
@@ -112,6 +110,22 @@ gboolean gsk_path_in_fill (GskPath
|
||||
const graphene_point_t *point,
|
||||
GskFillRule fill_rule);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
gboolean gsk_path_get_closest_point (GskPath *self,
|
||||
const graphene_point_t *point,
|
||||
float threshold,
|
||||
GskPathPoint *result);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
gboolean gsk_path_get_previous_point (GskPath *self,
|
||||
const GskPathPoint *point,
|
||||
GskPathPoint *result);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
gboolean gsk_path_get_next_point (GskPath *self,
|
||||
const GskPathPoint *point,
|
||||
GskPathPoint *result);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
gboolean gsk_path_get_start_point (GskPath *self,
|
||||
GskPathPoint *result);
|
||||
@@ -119,12 +133,6 @@ GDK_AVAILABLE_IN_4_14
|
||||
gboolean gsk_path_get_end_point (GskPath *self,
|
||||
GskPathPoint *result);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
gboolean gsk_path_get_closest_point (GskPath *self,
|
||||
const graphene_point_t *point,
|
||||
float threshold,
|
||||
GskPathPoint *result);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
gboolean gsk_path_foreach (GskPath *self,
|
||||
GskPathForeachFlags flags,
|
||||
|
||||
@@ -63,8 +63,6 @@
|
||||
* back with a line to the starting point.
|
||||
*
|
||||
* This is similar for how paths are drawn in Cairo.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
|
||||
struct _GskPathBuilder
|
||||
@@ -985,77 +983,3 @@ gsk_path_builder_add_layout (GskPathBuilder *self,
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_builder_add_segment:
|
||||
* @self: a `GskPathBuilder`
|
||||
* @path: the `GskPath` to take the segment to
|
||||
* @start: the point on @path to start at
|
||||
* @end: the point on @path to end at
|
||||
*
|
||||
* Adds to @self the segment of @path from @start to @end.
|
||||
*
|
||||
* If @start is equal to or after @end, the path will first add the
|
||||
* segment from @start to the end of the path, and then add the segment
|
||||
* from the beginning to @end. If the path is closed, these segments
|
||||
* will be connected.
|
||||
*
|
||||
* Note that this method always adds a path with the given start point
|
||||
* and end point. To add a closed path, use [method@Gsk.PathBuilder.add_path].
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
void
|
||||
gsk_path_builder_add_segment (GskPathBuilder *self,
|
||||
GskPath *path,
|
||||
const GskPathPoint *start,
|
||||
const GskPathPoint *end)
|
||||
{
|
||||
GskRealPathPoint *s = (GskRealPathPoint *) start;
|
||||
GskRealPathPoint *e = (GskRealPathPoint *) end;
|
||||
const GskContour *contour;
|
||||
gsize n_contours = gsk_path_get_n_contours (path);
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (path != NULL);
|
||||
g_return_if_fail (start != NULL);
|
||||
g_return_if_fail (end != NULL);
|
||||
g_return_if_fail (s->contour < n_contours);
|
||||
g_return_if_fail (e->contour < n_contours);
|
||||
|
||||
contour = gsk_path_get_contour (path, s->contour);
|
||||
|
||||
if (s->contour == e->contour)
|
||||
{
|
||||
if (gsk_path_point_compare (start, end) < 0)
|
||||
{
|
||||
gsk_contour_add_segment (contour, self, TRUE, s, e);
|
||||
goto out;
|
||||
}
|
||||
else if (n_contours == 1)
|
||||
{
|
||||
gsk_contour_add_segment (contour, self, TRUE,
|
||||
s,
|
||||
&(GskRealPathPoint) { s->contour, gsk_contour_get_n_points (contour) - 1, 1 });
|
||||
gsk_contour_add_segment (contour, self, FALSE,
|
||||
&(GskRealPathPoint) { s->contour, 1, 0 },
|
||||
e);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
gsk_contour_add_segment (contour, self, TRUE,
|
||||
s,
|
||||
&(GskRealPathPoint) { s->contour, gsk_contour_get_n_points (contour) - 1, 1 });
|
||||
|
||||
for (gsize i = (s->contour + 1) % n_contours; i != e->contour; i = (i + 1) % n_contours)
|
||||
gsk_path_builder_add_contour (self, gsk_contour_dup (gsk_path_get_contour (path, i)));
|
||||
|
||||
contour = gsk_path_get_contour (path, e->contour);
|
||||
gsk_contour_add_segment (contour, self, FALSE,
|
||||
&(GskRealPathPoint) { e->contour, 1, 0 },
|
||||
e);
|
||||
|
||||
out:
|
||||
gsk_path_builder_end_current (self);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ void gsk_path_builder_add_segment (GskPathBuilder
|
||||
GskPath *path,
|
||||
const GskPathPoint *start,
|
||||
const GskPathPoint *end);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gsk_path_builder_move_to (GskPathBuilder *self,
|
||||
float x,
|
||||
|
||||
@@ -283,6 +283,8 @@ gsk_path_measure_get_point (GskPathMeasure *self,
|
||||
contour = gsk_path_get_contour (self->path, i);
|
||||
|
||||
gsk_contour_get_point (contour, self->measures[i].contour_data, offset, res);
|
||||
|
||||
res->path = self->path;
|
||||
res->contour = i;
|
||||
|
||||
return TRUE;
|
||||
@@ -305,14 +307,12 @@ gsk_path_point_get_distance (GskPathMeasure *measure,
|
||||
const GskPathPoint *point)
|
||||
{
|
||||
GskRealPathPoint *p = (GskRealPathPoint *)point;
|
||||
const GskContour *contour;
|
||||
const GskContour *contour = gsk_path_get_contour (measure->path, p->contour);
|
||||
float contour_offset = 0;
|
||||
|
||||
g_return_val_if_fail (measure != NULL, 0);
|
||||
g_return_val_if_fail (point != NULL, 0);
|
||||
g_return_val_if_fail (p->contour < measure->n_contours, 0);
|
||||
|
||||
contour = gsk_path_get_contour (measure->path, p->contour);
|
||||
g_return_val_if_fail (measure->path == p->path, 0);
|
||||
g_return_val_if_fail (contour != NULL, 0);
|
||||
|
||||
for (gsize i = 0; i < measure->n_contours; i++)
|
||||
{
|
||||
|
||||
@@ -57,6 +57,10 @@ gboolean gsk_path_measure_get_point (GskPathMeasure
|
||||
float distance,
|
||||
GskPathPoint *result);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
float gsk_path_measure_get_distance (GskPathMeasure *self,
|
||||
const GskPathPoint *point);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPathMeasure, gsk_path_measure_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
+10
-91
@@ -41,8 +41,6 @@
|
||||
* don't a reference to the path object they are obtained from. It is the
|
||||
* callers responsibility to keep a reference to the path as long as the
|
||||
* `GskPathPoint` is used.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GskPathPoint, gsk_path_point,
|
||||
@@ -68,77 +66,6 @@ gsk_path_point_free (GskPathPoint *point)
|
||||
g_free (point);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_point_equal:
|
||||
* @point1: a `GskPathPoint`
|
||||
* @point2: another `GskPathPoint`
|
||||
*
|
||||
* Returns whether the two path points refer to the same
|
||||
* location on all paths.
|
||||
*
|
||||
* Note that the start- and endpoint of a closed contour
|
||||
* will compare nonequal according to this definition.
|
||||
* Use [method@Gsk.Path.is_closed] to find out if the
|
||||
* start- and endpoint of a concrete path refer to the
|
||||
* same location.
|
||||
*
|
||||
* Return: `TRUE` if @point1 and @point2 are equal
|
||||
*/
|
||||
gboolean
|
||||
gsk_path_point_equal (const GskPathPoint *point1,
|
||||
const GskPathPoint *point2)
|
||||
{
|
||||
const GskRealPathPoint *p1 = (const GskRealPathPoint *) point1;
|
||||
const GskRealPathPoint *p2 = (const GskRealPathPoint *) point2;
|
||||
|
||||
if (p1->contour == p2->contour)
|
||||
{
|
||||
if ((p1->idx == p2->idx && p1->t == p2->t) ||
|
||||
(p1->idx + 1 == p2->idx && p1->t == 1 && p2->t == 0) ||
|
||||
(p1->idx == p2->idx + 1 && p1->t == 0 && p2->t == 1))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_point_compare:
|
||||
* @point1: a `GskPathPoint`
|
||||
* @point2: another `GskPathPoint`
|
||||
*
|
||||
* Returns whether @point1 is before or after @point2.
|
||||
*
|
||||
* Returns: -1 if @point1 is before @point2,
|
||||
* 1 if @point1 is after @point2,
|
||||
* 0 if they are equal
|
||||
*/
|
||||
int
|
||||
gsk_path_point_compare (const GskPathPoint *point1,
|
||||
const GskPathPoint *point2)
|
||||
{
|
||||
const GskRealPathPoint *p1 = (const GskRealPathPoint *) point1;
|
||||
const GskRealPathPoint *p2 = (const GskRealPathPoint *) point2;
|
||||
|
||||
if (gsk_path_point_equal (point1, point2))
|
||||
return 0;
|
||||
|
||||
if (p1->contour < p2->contour)
|
||||
return -1;
|
||||
else if (p1->contour > p2->contour)
|
||||
return 1;
|
||||
else if (p1->idx < p2->idx)
|
||||
return -1;
|
||||
else if (p1->idx > p2->idx)
|
||||
return 1;
|
||||
else if (p1->t < p2->t)
|
||||
return -1;
|
||||
else if (p1->t > p2->t)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_point_get_position:
|
||||
* @path: a `GskPath`
|
||||
@@ -156,14 +83,11 @@ gsk_path_point_get_position (GskPath *path,
|
||||
graphene_point_t *position)
|
||||
{
|
||||
GskRealPathPoint *self = (GskRealPathPoint *) point;
|
||||
const GskContour *contour;
|
||||
const GskContour *contour = gsk_path_get_contour (path, self->contour);
|
||||
|
||||
g_return_if_fail (path != NULL);
|
||||
g_return_if_fail (point != NULL);
|
||||
g_return_if_fail (position != NULL);
|
||||
g_return_if_fail (self->contour < gsk_path_get_n_contours (path));
|
||||
g_return_if_fail (path == self->path);
|
||||
g_return_if_fail (contour != NULL);
|
||||
|
||||
contour = gsk_path_get_contour (path, self->contour),
|
||||
gsk_contour_get_position (contour, self, position);
|
||||
}
|
||||
|
||||
@@ -192,14 +116,11 @@ gsk_path_point_get_tangent (GskPath *path,
|
||||
graphene_vec2_t *tangent)
|
||||
{
|
||||
GskRealPathPoint *self = (GskRealPathPoint *) point;
|
||||
const GskContour *contour;
|
||||
const GskContour *contour = gsk_path_get_contour (path, self->contour);
|
||||
|
||||
g_return_if_fail (path != NULL);
|
||||
g_return_if_fail (point != NULL);
|
||||
g_return_if_fail (tangent != NULL);
|
||||
g_return_if_fail (self->contour < gsk_path_get_n_contours (path));
|
||||
g_return_if_fail (path == self->path);
|
||||
g_return_if_fail (contour != NULL);
|
||||
|
||||
contour = gsk_path_get_contour (path, self->contour),
|
||||
gsk_contour_get_tangent (contour, self, direction, tangent);
|
||||
}
|
||||
|
||||
@@ -207,7 +128,7 @@ gsk_path_point_get_tangent (GskPath *path,
|
||||
* gsk_path_point_get_curvature:
|
||||
* @path: a `GskPath`
|
||||
* @point: a `GskPathPoint` on @path
|
||||
* @center: (out caller-allocates) (nullable): Return location for
|
||||
* @center: (out caller-allocates): Return location for
|
||||
* the center of the osculating circle
|
||||
*
|
||||
* Calculates the curvature of the path at the point.
|
||||
@@ -227,12 +148,10 @@ gsk_path_point_get_curvature (GskPath *path,
|
||||
graphene_point_t *center)
|
||||
{
|
||||
GskRealPathPoint *self = (GskRealPathPoint *) point;
|
||||
const GskContour *contour;
|
||||
const GskContour *contour = gsk_path_get_contour (path, self->contour);
|
||||
|
||||
g_return_val_if_fail (path != NULL, 0);
|
||||
g_return_val_if_fail (point != NULL, 0);
|
||||
g_return_val_if_fail (self->contour < gsk_path_get_n_contours (path), 0);
|
||||
g_return_val_if_fail (path == self->path, 0);
|
||||
g_return_val_if_fail (contour != NULL, 0);
|
||||
|
||||
contour = gsk_path_get_contour (path, self->contour);
|
||||
return gsk_contour_get_curvature (contour, self, center);
|
||||
}
|
||||
|
||||
@@ -48,14 +48,6 @@ GskPathPoint * gsk_path_point_copy (GskPathPoint *poin
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gsk_path_point_free (GskPathPoint *point);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
gboolean gsk_path_point_equal (const GskPathPoint *point1,
|
||||
const GskPathPoint *point2);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
int gsk_path_point_compare (const GskPathPoint *point1,
|
||||
const GskPathPoint *point2);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gsk_path_point_get_position (GskPath *path,
|
||||
const GskPathPoint *point,
|
||||
|
||||
@@ -7,9 +7,15 @@ G_BEGIN_DECLS
|
||||
|
||||
struct _GskRealPathPoint
|
||||
{
|
||||
GskPath *path;
|
||||
gsize contour;
|
||||
gsize idx;
|
||||
float t;
|
||||
|
||||
union {
|
||||
struct {
|
||||
unsigned int idx;
|
||||
float t;
|
||||
} std;
|
||||
} data;
|
||||
};
|
||||
|
||||
G_STATIC_ASSERT (sizeof (GskRealPathPoint) <= sizeof (GskPathPoint));
|
||||
|
||||
+2
-20
@@ -3970,7 +3970,7 @@ gsk_repeat_node_draw (GskRenderNode *node,
|
||||
scale_x *= width / self->child_bounds.size.width;
|
||||
scale_y *= height / self->child_bounds.size.height;
|
||||
cairo_surface_set_device_scale (surface, scale_x, scale_y);
|
||||
cairo_surface_set_device_offset (surface,
|
||||
cairo_surface_set_device_offset (surface,
|
||||
- self->child_bounds.origin.x * scale_x,
|
||||
- self->child_bounds.origin.y * scale_y);
|
||||
|
||||
@@ -4141,7 +4141,7 @@ gsk_clip_node_diff (GskRenderNode *node1,
|
||||
gsk_render_node_diff_impossible (node1, node2, region);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gsk_clip_node_class_init (gpointer g_class,
|
||||
gpointer class_data)
|
||||
@@ -4372,15 +4372,6 @@ gsk_rounded_clip_node_get_clip (const GskRenderNode *node)
|
||||
/* }}} */
|
||||
/* {{{ GSK_FILL_NODE */
|
||||
|
||||
/**
|
||||
* GskFillNode:
|
||||
*
|
||||
* A render node filling the child node in the area given by [struct@Gsk.Path]
|
||||
* and [enum@Gsk.FillRule].
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
|
||||
struct _GskFillNode
|
||||
{
|
||||
GskRenderNode render_node;
|
||||
@@ -4581,15 +4572,6 @@ gsk_fill_node_get_fill_rule (const GskRenderNode *node)
|
||||
/* }}} */
|
||||
/* {{{ GSK_STROKE_NODE */
|
||||
|
||||
/**
|
||||
* GskStrokeNode:
|
||||
*
|
||||
* A render node that will stroke the child node along the given [struct@Gsk.Path]
|
||||
* using the [struct@Gsk.Stroke] attributes.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
|
||||
struct _GskStrokeNode
|
||||
{
|
||||
GskRenderNode render_node;
|
||||
|
||||
@@ -14,7 +14,7 @@ typedef struct _GskRenderNodeClass GskRenderNodeClass;
|
||||
* We don't add an "n-types" value to avoid having to handle
|
||||
* it in every single switch.
|
||||
*/
|
||||
#define GSK_RENDER_NODE_TYPE_N_TYPES (GSK_STROKE_NODE + 1)
|
||||
#define GSK_RENDER_NODE_TYPE_N_TYPES (GSK_MASK_NODE + 1)
|
||||
|
||||
extern GType gsk_render_node_types[];
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
*
|
||||
* A `GskStroke` struct collects the parameters that influence
|
||||
* the operation of stroking a path.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GskStroke, gsk_stroke, gsk_stroke_copy, gsk_stroke_free)
|
||||
|
||||
+3
-3
@@ -27,9 +27,9 @@
|
||||
* `GtkListHeader` is used by list widgets to represent the headers they
|
||||
* display.
|
||||
*
|
||||
* `GtkListHeader` objects are managed just like [class@Gtk.ListItem]
|
||||
* objects via their factory, but provide a different set of properties suitable
|
||||
* for managing the header instead of individual items.
|
||||
* The `GtkListHeader`s are managed just like [class@gtk.ListItem]s via
|
||||
* their factory, but provide a different set of properties suitable for
|
||||
* managing the header instead of individual items.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
|
||||
+3
-4
@@ -27,14 +27,13 @@
|
||||
/**
|
||||
* GtkListItem:
|
||||
*
|
||||
* `GtkListItem` is used by list widgets to represent items in a
|
||||
* [iface@Gio.ListModel].
|
||||
* `GtkListItem` is used by list widgets to represent items in a `GListModel`.
|
||||
*
|
||||
* `GtkListItem` objects are managed by the list widget (with its factory)
|
||||
* The `GtkListItem`s are managed by the list widget (with its factory)
|
||||
* and cannot be created by applications, but they need to be populated
|
||||
* by application code. This is done by calling [method@Gtk.ListItem.set_child].
|
||||
*
|
||||
* `GtkListItem` objects exist in 2 stages:
|
||||
* `GtkListItem`s exist in 2 stages:
|
||||
*
|
||||
* 1. The unbound stage where the listitem is not currently connected to
|
||||
* an item in the list. In that case, the [property@Gtk.ListItem:item]
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
/**
|
||||
* GtkOverlayLayout:
|
||||
*
|
||||
* `GtkOverlayLayout` is the layout manager used by [class@Gtk.Overlay].
|
||||
* `GtkOverlayLayout` is the layout manager used by `GtkOverlay`.
|
||||
*
|
||||
* It places widgets as overlays on top of the main child.
|
||||
*
|
||||
* This is not a reusable layout manager, since it expects its widget
|
||||
* to be a `GtkOverlay`. It is only listed here so that its layout
|
||||
* to be a `GtkOverlay`. It only listed here so that its layout
|
||||
* properties get documented.
|
||||
*/
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtk/print/gtkprintbackendprivate.h"
|
||||
#include "gtkprintbackendprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <cpdb/cpdb-frontend.h>
|
||||
#include <gtk/print/gtkprinterprivate.h>
|
||||
#include <gtk/gtkprinterprivate.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -43,4 +43,4 @@ void gtk_printer_cpdb_set_printer_obj (GtkPrinterCpdb
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_PRINTER_CPDB_H__ */
|
||||
#endif /* __GTK_PRINTER_CPDB_H__ */
|
||||
@@ -145,28 +145,6 @@ test_curve_crossing (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_bad_split (void)
|
||||
{
|
||||
GskCurve c, c1, c2;
|
||||
float t[2], l, l1, l2;
|
||||
|
||||
parse_curve (&c, "M 0 0 C 2 0 4 0 4 0");
|
||||
|
||||
l = gsk_curve_get_length (&c);
|
||||
|
||||
t[0] = 0.5;
|
||||
t[1] = gsk_curve_at_length (&c, 2, FLT_EPSILON);
|
||||
|
||||
for (unsigned int i = 0; i < G_N_ELEMENTS (t); i++)
|
||||
{
|
||||
gsk_curve_split (&c, t[i], &c1, &c2);
|
||||
l1 = gsk_curve_get_length (&c1);
|
||||
l2 = gsk_curve_get_length (&c2);
|
||||
g_print ("split at t=%g: %g == %g + %g, error %f\n", t[i], l, l1, l2, l - (l1 + l2));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@@ -176,7 +154,6 @@ main (int argc,
|
||||
g_test_add_func ("/curve/special/tangents", test_curve_tangents);
|
||||
g_test_add_func ("/curve/special/degenerate-tangents", test_curve_degenerate_tangents);
|
||||
g_test_add_func ("/curve/special/crossing", test_curve_crossing);
|
||||
g_test_add_func ("/curve/special/bad-split", test_bad_split);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
+4
-26
@@ -281,29 +281,16 @@ test_curve_decompose_into_cubic (void)
|
||||
static void
|
||||
test_curve_split (void)
|
||||
{
|
||||
for (int i = 0; i < 1000; i++)
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
GskCurve c;
|
||||
GskCurve c1, c2;
|
||||
graphene_point_t p;
|
||||
graphene_vec2_t t, t1, t2;
|
||||
float tt;
|
||||
float l, l1, l2;
|
||||
|
||||
init_random_curve (&c);
|
||||
|
||||
tt = g_test_rand_double_range (0, 1);
|
||||
|
||||
if (tt == 0 || tt == 1)
|
||||
continue;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("curve %s\nt %g\n", gsk_curve_to_string (&c), tt);
|
||||
|
||||
gsk_curve_split (&c, tt, &c1, &c2);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("c1 %s\nc2 %s\n", gsk_curve_to_string (&c1), gsk_curve_to_string (&c2));
|
||||
gsk_curve_split (&c, 0.5, &c1, &c2);
|
||||
|
||||
g_assert_true (c1.op == c.op);
|
||||
g_assert_true (c2.op == c.op);
|
||||
@@ -314,9 +301,8 @@ test_curve_split (void)
|
||||
gsk_curve_get_start_point (&c2), 0.005));
|
||||
g_assert_true (graphene_point_near (gsk_curve_get_end_point (&c),
|
||||
gsk_curve_get_end_point (&c2), 0.005));
|
||||
|
||||
gsk_curve_get_point (&c, tt, &p);
|
||||
gsk_curve_get_tangent (&c, tt, &t);
|
||||
gsk_curve_get_point (&c, 0.5, &p);
|
||||
gsk_curve_get_tangent (&c, 0.5, &t);
|
||||
g_assert_true (graphene_point_near (gsk_curve_get_end_point (&c1), &p, 0.005));
|
||||
g_assert_true (graphene_point_near (gsk_curve_get_start_point (&c2), &p, 0.005));
|
||||
|
||||
@@ -331,14 +317,6 @@ test_curve_split (void)
|
||||
gsk_curve_get_end_tangent (&c, &t1);
|
||||
gsk_curve_get_end_tangent (&c2, &t2);
|
||||
g_assert_true (graphene_vec2_near (&t1, &t2, 0.005));
|
||||
|
||||
l = gsk_curve_get_length (&c);
|
||||
l1 = gsk_curve_get_length (&c1);
|
||||
l2 = gsk_curve_get_length (&c2);
|
||||
|
||||
g_print ("l %g l1 %g l2 %g\n", l, l1, l2);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (l, l1 + l2, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,44 +20,6 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
static void
|
||||
test_basics (void)
|
||||
{
|
||||
GskPath *path;
|
||||
GskPathMeasure *measure;
|
||||
GskPathPoint point, point1;
|
||||
float epsilon = 0.001;
|
||||
float length;
|
||||
|
||||
path = gsk_path_parse ("M 0 0 L 100 0 C 100 100 200 100 200 0");
|
||||
measure = gsk_path_measure_new (path);
|
||||
|
||||
gsk_path_measure_get_point (measure, 0, &point);
|
||||
gsk_path_get_start_point (path, &point1);
|
||||
g_assert_true (gsk_path_point_equal (&point, &point1));
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gsk_path_point_get_distance (measure, &point), 0, epsilon);
|
||||
|
||||
gsk_path_measure_get_point (measure, 50, &point);
|
||||
g_assert_cmpfloat_with_epsilon (gsk_path_point_get_distance (measure, &point), 50, epsilon);
|
||||
|
||||
gsk_path_measure_get_point (measure, 100, &point);
|
||||
g_assert_cmpfloat_with_epsilon (gsk_path_point_get_distance (measure, &point), 100, epsilon);
|
||||
|
||||
gsk_path_measure_get_point (measure, 150, &point);
|
||||
g_assert_cmpfloat_with_epsilon (gsk_path_point_get_distance (measure, &point), 150, epsilon);
|
||||
|
||||
length = gsk_path_measure_get_length (measure);
|
||||
gsk_path_measure_get_point (measure, length, &point);
|
||||
gsk_path_get_end_point (path, &point1);
|
||||
g_assert_true (gsk_path_point_equal (&point, &point1));
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gsk_path_point_get_distance (measure, &point), length, epsilon);
|
||||
|
||||
gsk_path_measure_unref (measure);
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_bad_split (void)
|
||||
{
|
||||
@@ -65,7 +27,7 @@ test_bad_split (void)
|
||||
GskPathMeasure *measure, *measure1;
|
||||
GskPathBuilder *builder;
|
||||
float split, length, epsilon;
|
||||
GskPathPoint point1, point2;
|
||||
GskPathPoint point0, point1;
|
||||
|
||||
/* An example that was isolated from the /path/segment test path.c
|
||||
* It shows how uneven parametrization of cubics can lead to bad
|
||||
@@ -76,14 +38,13 @@ test_bad_split (void)
|
||||
|
||||
measure = gsk_path_measure_new (path);
|
||||
split = 2.962588;
|
||||
gsk_path_measure_get_point (measure, 0, &point0);
|
||||
gsk_path_measure_get_point (measure, split, &point1);
|
||||
length = gsk_path_measure_get_length (measure);
|
||||
epsilon = MAX (length / 256, 1.f / 1024);
|
||||
|
||||
gsk_path_get_start_point (path, &point1);
|
||||
gsk_path_measure_get_point (measure, split, &point2);
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_segment (builder, path, &point1, &point2);
|
||||
gsk_path_builder_add_segment (builder, path, &point0, &point1);;
|
||||
path1 = gsk_path_builder_free_to_path (builder);
|
||||
measure1 = gsk_path_measure_new (path1);
|
||||
|
||||
@@ -95,6 +56,40 @@ test_bad_split (void)
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_bad_in_fill (void)
|
||||
{
|
||||
GskPath *path;
|
||||
gboolean inside;
|
||||
|
||||
/* A fat Cantarell W */
|
||||
path = gsk_path_parse ("M -2 694 M 206.1748046875 704 L 390.9371337890625 704 L 551.1888427734375 99.5035400390625 L 473.0489501953125 99.5035400390625 L 649.1048583984375 704 L 828.965087890625 704 L 1028.3077392578125 10 L 857.8111572265625 10 L 710.0489501953125 621.251708984375 L 775.9720458984375 598.426513671875 L 614.5245361328125 14.0489501953125 L 430.2237548828125 14.0489501953125 L 278.6783447265625 602.230712890625 L 330.0909423828125 602.230712890625 L 195.88818359375 10 L 5.7342529296875 10 L 206.1748046875 704 Z");
|
||||
|
||||
/* The midpoint of the right foot of a fat Cantarell X */
|
||||
inside = gsk_path_in_fill (path, &GRAPHENE_POINT_INIT (552.360107, 704.000000), GSK_FILL_RULE_WINDING);
|
||||
|
||||
g_assert_false (inside);
|
||||
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
|
||||
/* Test that path_in_fill implicitly closes contours. I think this is wrong,
|
||||
* but it is what "everybody" does.
|
||||
*/
|
||||
static void
|
||||
test_unclosed_in_fill (void)
|
||||
{
|
||||
GskPath *path;
|
||||
|
||||
path = gsk_path_parse ("M 0 0 L 0 100 L 100 100 L 100 0 Z");
|
||||
g_assert_true (gsk_path_in_fill (path, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_WINDING));
|
||||
gsk_path_unref (path);
|
||||
|
||||
path = gsk_path_parse ("M 0 0 L 0 100 L 100 100 L 100 0");
|
||||
g_assert_true (gsk_path_in_fill (path, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_WINDING));
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_rect (void)
|
||||
{
|
||||
@@ -264,8 +259,9 @@ main (int argc,
|
||||
{
|
||||
gtk_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/measure/basics", test_basics);
|
||||
g_test_add_func ("/measure/bad-split", test_bad_split);
|
||||
g_test_add_func ("/measure/bad-in-fill", test_bad_in_fill);
|
||||
g_test_add_func ("/measure/unclosed-in-fill", test_unclosed_in_fill);
|
||||
g_test_add_func ("/measure/rect", test_rect);
|
||||
|
||||
return g_test_run ();
|
||||
|
||||
+347
-15
@@ -311,33 +311,191 @@ create_random_path (guint max_contours)
|
||||
return gsk_path_builder_free_to_path (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
test_roundtrip (void)
|
||||
{
|
||||
GskPath *path;
|
||||
GskPathMeasure *measure;
|
||||
float length, seg_length;
|
||||
int i;
|
||||
GskPathPoint point;
|
||||
float epsilon = 0.5;
|
||||
typedef struct {
|
||||
GskPathOperation op;
|
||||
graphene_point_t pts[4];
|
||||
float weight;
|
||||
} PathOperation;
|
||||
|
||||
path = create_random_path (10);
|
||||
static void
|
||||
test_segment_start (void)
|
||||
{
|
||||
GskPath *path, *path1;
|
||||
GskPathMeasure *measure, *measure1;
|
||||
GskPathBuilder *builder;
|
||||
float epsilon, length;
|
||||
guint i;
|
||||
GskPathPoint point0, point1;
|
||||
|
||||
path = create_random_path (G_MAXUINT);
|
||||
measure = gsk_path_measure_new (path);
|
||||
length = gsk_path_measure_get_length (measure);
|
||||
epsilon = MAX (length / 1024, G_MINFLOAT);
|
||||
gsk_path_measure_get_point (measure, 0, &point0);
|
||||
|
||||
for (i = 0; i <= 100; i++)
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
seg_length = length * i / 100.0f;
|
||||
float seg_length = length * i / 100.0f;
|
||||
|
||||
gsk_path_measure_get_point (measure, seg_length, &point);
|
||||
gsk_path_measure_get_point (measure, seg_length, &point1);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_point_get_distance (measure, &point), epsilon);
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_segment (builder, path, &point0, &point1);
|
||||
path1 = gsk_path_builder_free_to_path (builder);
|
||||
measure1 = gsk_path_measure_new (path1);
|
||||
|
||||
if (seg_length == 0)
|
||||
g_assert_cmpfloat_with_epsilon (gsk_path_measure_get_length (measure), gsk_path_measure_get_length (measure1), epsilon);
|
||||
else
|
||||
g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
|
||||
|
||||
gsk_path_measure_unref (measure1);
|
||||
gsk_path_unref (path1);
|
||||
}
|
||||
|
||||
gsk_path_measure_unref (measure);
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_segment_end (void)
|
||||
{
|
||||
GskPath *path, *path1;
|
||||
GskPathMeasure *measure, *measure1;
|
||||
GskPathBuilder *builder;
|
||||
float epsilon, length;
|
||||
guint i;
|
||||
GskPathPoint point0, point1;
|
||||
|
||||
path = create_random_path (G_MAXUINT);
|
||||
measure = gsk_path_measure_new (path);
|
||||
length = gsk_path_measure_get_length (measure);
|
||||
epsilon = MAX (length / 1024, G_MINFLOAT);
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
float seg_length = length * i / 100.0f;
|
||||
|
||||
gsk_path_measure_get_point (measure, length - seg_length, &point0);
|
||||
gsk_path_measure_get_point (measure, length, &point1);
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_segment (builder, path, &point0, &point1);
|
||||
path1 = gsk_path_builder_free_to_path (builder);
|
||||
measure1 = gsk_path_measure_new (path1);
|
||||
|
||||
if (seg_length == 0)
|
||||
g_assert_cmpfloat_with_epsilon (gsk_path_measure_get_length (measure), gsk_path_measure_get_length (measure1), epsilon);
|
||||
else
|
||||
g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
|
||||
|
||||
gsk_path_measure_unref (measure1);
|
||||
gsk_path_unref (path1);
|
||||
}
|
||||
|
||||
gsk_path_measure_unref (measure);
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_segment_chunk (void)
|
||||
{
|
||||
GskPath *path, *path1, *path2;
|
||||
GskPathMeasure *measure, *measure1, *measure2;
|
||||
GskPathBuilder *builder;
|
||||
float epsilon, length;
|
||||
guint i;
|
||||
GskPathPoint point0, point1;
|
||||
|
||||
path = create_random_path (G_MAXUINT);
|
||||
measure = gsk_path_measure_new (path);
|
||||
length = gsk_path_measure_get_length (measure);
|
||||
epsilon = MAX (length / 1024, G_MINFLOAT);
|
||||
|
||||
for (i = 0; i <= 100; i++)
|
||||
{
|
||||
float seg_start = length * i / 200.0f;
|
||||
|
||||
gsk_path_measure_get_point (measure, seg_start, &point0);
|
||||
gsk_path_measure_get_point (measure, seg_start + length / 2, &point1);
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_segment (builder, path, &point0, &point1);
|
||||
path1 = gsk_path_builder_free_to_path (builder);
|
||||
measure1 = gsk_path_measure_new (path1);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (length / 2, gsk_path_measure_get_length (measure1), epsilon);
|
||||
|
||||
gsk_path_measure_get_point (measure, seg_start + length / 2, &point0);
|
||||
gsk_path_measure_get_point (measure, seg_start, &point1);
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_segment (builder, path, &point0, &point1);
|
||||
path2 = gsk_path_builder_free_to_path (builder);
|
||||
measure2 = gsk_path_measure_new (path2);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (length / 2, gsk_path_measure_get_length (measure2), epsilon);
|
||||
|
||||
gsk_path_measure_unref (measure2);
|
||||
gsk_path_unref (path2);
|
||||
gsk_path_measure_unref (measure1);
|
||||
gsk_path_unref (path1);
|
||||
}
|
||||
|
||||
gsk_path_measure_unref (measure);
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_segment (void)
|
||||
{
|
||||
GskPath *path, *path1, *path2, *path3;
|
||||
GskPathMeasure *measure, *measure1, *measure2, *measure3;
|
||||
GskPathBuilder *builder;
|
||||
guint i;
|
||||
float split1, split2, epsilon, length;
|
||||
GskPathPoint point0, point1, point2, point3;
|
||||
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
path = create_random_path (G_MAXUINT);
|
||||
measure = gsk_path_measure_new (path);
|
||||
length = gsk_path_measure_get_length (measure);
|
||||
/* chosen high enough to stop the testsuite from failing */
|
||||
epsilon = MAX (length / 64, 1.f / 1024);
|
||||
|
||||
split1 = g_test_rand_double_range (0, length);
|
||||
split2 = g_test_rand_double_range (split1, length);
|
||||
|
||||
gsk_path_measure_get_point (measure, 0, &point0);
|
||||
gsk_path_measure_get_point (measure, split1, &point1);
|
||||
gsk_path_measure_get_point (measure, split2, &point2);
|
||||
gsk_path_measure_get_point (measure, length, &point3);
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_segment (builder, path, &point0, &point1);
|
||||
path1 = gsk_path_builder_free_to_path (builder);
|
||||
measure1 = gsk_path_measure_new (path1);
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_segment (builder, path, &point1, &point2);
|
||||
path2 = gsk_path_builder_free_to_path (builder);
|
||||
measure2 = gsk_path_measure_new (path2);
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_segment (builder, path, &point2, &point3);
|
||||
path3 = gsk_path_builder_free_to_path (builder);
|
||||
measure3 = gsk_path_measure_new (path3);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (split1, gsk_path_measure_get_length (measure1), epsilon);
|
||||
g_assert_cmpfloat_with_epsilon (split2 - split1, gsk_path_measure_get_length (measure2), epsilon);
|
||||
g_assert_cmpfloat_with_epsilon (length - split2, gsk_path_measure_get_length (measure3), epsilon);
|
||||
|
||||
gsk_path_measure_unref (measure2);
|
||||
gsk_path_measure_unref (measure1);
|
||||
gsk_path_measure_unref (measure);
|
||||
gsk_path_unref (path2);
|
||||
gsk_path_unref (path1);
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_get_point (void)
|
||||
{
|
||||
@@ -540,16 +698,190 @@ test_closest_point_for_point (void)
|
||||
}
|
||||
}
|
||||
|
||||
#define N_PATHS 3
|
||||
static void
|
||||
test_in_fill_union (void)
|
||||
{
|
||||
GskPath *path;
|
||||
GskPathMeasure *measure, *measures[N_PATHS];
|
||||
GskPathBuilder *builder;
|
||||
guint i, j, k;
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
builder = gsk_path_builder_new ();
|
||||
for (k = 0; k < N_PATHS; k++)
|
||||
{
|
||||
path = create_random_path (G_MAXUINT);
|
||||
measures[k] = gsk_path_measure_new (path);
|
||||
gsk_path_builder_add_path (builder, path);
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
path = gsk_path_builder_free_to_path (builder);
|
||||
measure = gsk_path_measure_new (path);
|
||||
gsk_path_unref (path);
|
||||
|
||||
for (j = 0; j < 100; j++)
|
||||
{
|
||||
graphene_point_t test = GRAPHENE_POINT_INIT (g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000));
|
||||
GskFillRule fill_rule;
|
||||
|
||||
for (fill_rule = GSK_FILL_RULE_WINDING; fill_rule <= GSK_FILL_RULE_EVEN_ODD; fill_rule++)
|
||||
{
|
||||
guint n_in_fill = 0;
|
||||
gboolean in_fill;
|
||||
|
||||
for (k = 0; k < N_PATHS; k++)
|
||||
{
|
||||
if (gsk_path_in_fill (gsk_path_measure_get_path (measures[k]), &test, GSK_FILL_RULE_EVEN_ODD))
|
||||
n_in_fill++;
|
||||
}
|
||||
|
||||
in_fill = gsk_path_in_fill (gsk_path_measure_get_path (measure), &test, GSK_FILL_RULE_EVEN_ODD);
|
||||
|
||||
switch (fill_rule)
|
||||
{
|
||||
case GSK_FILL_RULE_WINDING:
|
||||
if (n_in_fill == 0)
|
||||
g_assert_false (in_fill);
|
||||
else if (n_in_fill == 1)
|
||||
g_assert_true (in_fill);
|
||||
/* else we can't say anything because the winding rule doesn't give enough info */
|
||||
break;
|
||||
|
||||
case GSK_FILL_RULE_EVEN_ODD:
|
||||
g_assert_cmpint (in_fill, ==, n_in_fill & 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gsk_path_measure_unref (measure);
|
||||
for (k = 0; k < N_PATHS; k++)
|
||||
{
|
||||
gsk_path_measure_unref (measures[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef N_PATHS
|
||||
|
||||
/* This is somewhat sucky because using foreach breaks up the contours
|
||||
* (like rects and circles) and replaces everything with the standard
|
||||
* contour.
|
||||
* But at least it extensively tests the standard contour.
|
||||
*/
|
||||
static gboolean
|
||||
rotate_path_cb (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
gpointer user_data)
|
||||
{
|
||||
GskPathBuilder **builders = user_data;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case GSK_PATH_MOVE:
|
||||
gsk_path_builder_move_to (builders[0], pts[0].x, pts[0].y);
|
||||
gsk_path_builder_move_to (builders[1], pts[0].y, -pts[0].x);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CLOSE:
|
||||
gsk_path_builder_close (builders[0]);
|
||||
gsk_path_builder_close (builders[1]);
|
||||
break;
|
||||
|
||||
case GSK_PATH_LINE:
|
||||
gsk_path_builder_line_to (builders[0], pts[1].x, pts[1].y);
|
||||
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);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_in_fill_rotated (void)
|
||||
{
|
||||
GskPath *path;
|
||||
GskPathBuilder *builders[2];
|
||||
GskPathMeasure *measures[2];
|
||||
guint i, j;
|
||||
|
||||
#define N_FILL_RULES 2
|
||||
/* if this triggers, you added a new enum value to GskFillRule, so the define above needs
|
||||
* an update */
|
||||
g_assert_null (g_enum_get_value (g_type_class_ref (GSK_TYPE_FILL_RULE), N_FILL_RULES));
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
path = create_random_path (G_MAXUINT);
|
||||
builders[0] = gsk_path_builder_new ();
|
||||
builders[1] = gsk_path_builder_new ();
|
||||
/* Use -1 here because we want all the flags, even future additions */
|
||||
gsk_path_foreach (path, -1, rotate_path_cb, builders);
|
||||
gsk_path_unref (path);
|
||||
|
||||
path = gsk_path_builder_free_to_path (builders[0]);
|
||||
measures[0] = gsk_path_measure_new (path);
|
||||
gsk_path_unref (path);
|
||||
path = gsk_path_builder_free_to_path (builders[1]);
|
||||
measures[1] = gsk_path_measure_new (path);
|
||||
gsk_path_unref (path);
|
||||
|
||||
for (j = 0; j < 100; j++)
|
||||
{
|
||||
GskFillRule fill_rule = g_random_int_range (0, N_FILL_RULES);
|
||||
float x = g_test_rand_double_range (-1000, 1000);
|
||||
float y = g_test_rand_double_range (-1000, 1000);
|
||||
|
||||
g_assert_cmpint (gsk_path_in_fill (gsk_path_measure_get_path (measures[0]), &GRAPHENE_POINT_INIT (x, y), fill_rule),
|
||||
==,
|
||||
gsk_path_in_fill (gsk_path_measure_get_path (measures[1]), &GRAPHENE_POINT_INIT (y, -x), fill_rule));
|
||||
g_assert_cmpint (gsk_path_in_fill (gsk_path_measure_get_path (measures[0]), &GRAPHENE_POINT_INIT (y, x), fill_rule),
|
||||
==,
|
||||
gsk_path_in_fill (gsk_path_measure_get_path (measures[1]), &GRAPHENE_POINT_INIT (x, -y), fill_rule));
|
||||
}
|
||||
|
||||
gsk_path_measure_unref (measures[0]);
|
||||
gsk_path_measure_unref (measures[1]);
|
||||
}
|
||||
#undef N_FILL_RULES
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
gtk_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/measure/roundtrip", test_roundtrip);
|
||||
g_test_add_func ("/measure/segment_start", test_segment_start);
|
||||
g_test_add_func ("/measure/segment_end", test_segment_end);
|
||||
g_test_add_func ("/measure/segment_chunk", test_segment_chunk);
|
||||
g_test_add_func ("/measure/segment", test_segment);
|
||||
g_test_add_func ("/measure/get_point", test_get_point);
|
||||
g_test_add_func ("/measure/closest_point", test_closest_point);
|
||||
g_test_add_func ("/measure/closest_point_for_point", test_closest_point_for_point);
|
||||
g_test_add_func ("/measure/in-fill-union", test_in_fill_union);
|
||||
g_test_add_func ("/measure/in-fill-rotated", test_in_fill_rotated);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
@@ -485,12 +485,6 @@ test_path_segments (void)
|
||||
{ 50, 0 },
|
||||
{ 50, 50 },
|
||||
"M 50 0 L 100 0 L 50 50"
|
||||
},
|
||||
{
|
||||
"M 0 0 L 100 0 L 50 50 Z",
|
||||
{ 100, 0 },
|
||||
{ 100, 0 },
|
||||
"M 100 0 L 50 50 L 0 0 L 100 0"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -518,40 +512,6 @@ test_path_segments (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_bad_in_fill (void)
|
||||
{
|
||||
GskPath *path;
|
||||
gboolean inside;
|
||||
|
||||
/* A fat Cantarell W */
|
||||
path = gsk_path_parse ("M -2 694 M 206.1748046875 704 L 390.9371337890625 704 L 551.1888427734375 99.5035400390625 L 473.0489501953125 99.5035400390625 L 649.1048583984375 704 L 828.965087890625 704 L 1028.3077392578125 10 L 857.8111572265625 10 L 710.0489501953125 621.251708984375 L 775.9720458984375 598.426513671875 L 614.5245361328125 14.0489501953125 L 430.2237548828125 14.0489501953125 L 278.6783447265625 602.230712890625 L 330.0909423828125 602.230712890625 L 195.88818359375 10 L 5.7342529296875 10 L 206.1748046875 704 Z");
|
||||
|
||||
/* The midpoint of the right foot of a fat Cantarell X */
|
||||
inside = gsk_path_in_fill (path, &GRAPHENE_POINT_INIT (552.360107, 704.000000), GSK_FILL_RULE_WINDING);
|
||||
|
||||
g_assert_false (inside);
|
||||
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
|
||||
/* Test that path_in_fill implicitly closes contours. I think this is wrong,
|
||||
* but it is what "everybody" does.
|
||||
*/
|
||||
static void
|
||||
test_unclosed_in_fill (void)
|
||||
{
|
||||
GskPath *path;
|
||||
|
||||
path = gsk_path_parse ("M 0 0 L 0 100 L 100 100 L 100 0 Z");
|
||||
g_assert_true (gsk_path_in_fill (path, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_WINDING));
|
||||
gsk_path_unref (path);
|
||||
|
||||
path = gsk_path_parse ("M 0 0 L 0 100 L 100 100 L 100 0");
|
||||
g_assert_true (gsk_path_in_fill (path, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_WINDING));
|
||||
gsk_path_unref (path);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@@ -563,8 +523,6 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/path/foreach", test_foreach);
|
||||
g_test_add_func ("/path/point", test_path_point);
|
||||
g_test_add_func ("/path/segments", test_path_segments);
|
||||
g_test_add_func ("/measure/bad-in-fill", test_bad_in_fill);
|
||||
g_test_add_func ("/measure/unclosed-in-fill", test_unclosed_in_fill);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
@@ -582,166 +582,6 @@ test_parse (void)
|
||||
}
|
||||
}
|
||||
|
||||
#define N_PATHS 3
|
||||
static void
|
||||
test_in_fill_union (void)
|
||||
{
|
||||
GskPath *path, *paths[N_PATHS];
|
||||
GskPathBuilder *builder;
|
||||
guint i, j, k;
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
builder = gsk_path_builder_new ();
|
||||
|
||||
for (k = 0; k < N_PATHS; k++)
|
||||
{
|
||||
paths[k] = create_random_path (G_MAXUINT);
|
||||
gsk_path_builder_add_path (builder, paths[k]);
|
||||
}
|
||||
|
||||
path = gsk_path_builder_free_to_path (builder);
|
||||
|
||||
for (j = 0; j < 100; j++)
|
||||
{
|
||||
graphene_point_t test = GRAPHENE_POINT_INIT (g_test_rand_double_range (-1000, 1000),
|
||||
g_test_rand_double_range (-1000, 1000));
|
||||
GskFillRule fill_rule;
|
||||
|
||||
for (fill_rule = GSK_FILL_RULE_WINDING; fill_rule <= GSK_FILL_RULE_EVEN_ODD; fill_rule++)
|
||||
{
|
||||
guint n_in_fill = 0;
|
||||
gboolean in_fill;
|
||||
|
||||
for (k = 0; k < N_PATHS; k++)
|
||||
{
|
||||
if (gsk_path_in_fill (paths[k], &test, GSK_FILL_RULE_EVEN_ODD))
|
||||
n_in_fill++;
|
||||
}
|
||||
|
||||
in_fill = gsk_path_in_fill (path, &test, GSK_FILL_RULE_EVEN_ODD);
|
||||
switch (fill_rule)
|
||||
{
|
||||
case GSK_FILL_RULE_WINDING:
|
||||
if (n_in_fill == 0)
|
||||
g_assert_false (in_fill);
|
||||
else if (n_in_fill == 1)
|
||||
g_assert_true (in_fill);
|
||||
/* else we can't say anything because the winding rule doesn't give enough info */
|
||||
break;
|
||||
|
||||
case GSK_FILL_RULE_EVEN_ODD:
|
||||
g_assert_cmpint (in_fill, ==, n_in_fill & 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gsk_path_unref (path);
|
||||
|
||||
for (k = 0; k < N_PATHS; k++)
|
||||
gsk_path_unref (paths[k]);
|
||||
}
|
||||
}
|
||||
#undef N_PATHS
|
||||
|
||||
/* This is somewhat sucky because using foreach breaks up the contours
|
||||
* (like rects and circles) and replaces everything with the standard
|
||||
* contour.
|
||||
* But at least it extensively tests the standard contour.
|
||||
*/
|
||||
static gboolean
|
||||
rotate_path_cb (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
gpointer user_data)
|
||||
{
|
||||
GskPathBuilder **builders = user_data;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case GSK_PATH_MOVE:
|
||||
gsk_path_builder_move_to (builders[0], pts[0].x, pts[0].y);
|
||||
gsk_path_builder_move_to (builders[1], pts[0].y, -pts[0].x);
|
||||
break;
|
||||
|
||||
case GSK_PATH_CLOSE:
|
||||
gsk_path_builder_close (builders[0]);
|
||||
gsk_path_builder_close (builders[1]);
|
||||
break;
|
||||
|
||||
case GSK_PATH_LINE:
|
||||
gsk_path_builder_line_to (builders[0], pts[1].x, pts[1].y);
|
||||
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);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_in_fill_rotated (void)
|
||||
{
|
||||
GskPath *path;
|
||||
GskPathBuilder *builders[2];
|
||||
GskPath *paths[2];
|
||||
guint i, j;
|
||||
|
||||
#define N_FILL_RULES 2
|
||||
/* if this triggers, you added a new enum value to GskFillRule, so the define above needs
|
||||
* an update */
|
||||
g_assert_null (g_enum_get_value (g_type_class_ref (GSK_TYPE_FILL_RULE), N_FILL_RULES));
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
path = create_random_path (G_MAXUINT);
|
||||
builders[0] = gsk_path_builder_new ();
|
||||
builders[1] = gsk_path_builder_new ();
|
||||
/* Use -1 here because we want all the flags, even future additions */
|
||||
gsk_path_foreach (path, -1, rotate_path_cb, builders);
|
||||
gsk_path_unref (path);
|
||||
|
||||
paths[0] = gsk_path_builder_free_to_path (builders[0]);
|
||||
paths[1] = gsk_path_builder_free_to_path (builders[1]);
|
||||
|
||||
for (j = 0; j < 100; j++)
|
||||
{
|
||||
GskFillRule fill_rule = g_random_int_range (0, N_FILL_RULES);
|
||||
float x = g_test_rand_double_range (-1000, 1000);
|
||||
float y = g_test_rand_double_range (-1000, 1000);
|
||||
|
||||
g_assert_cmpint (gsk_path_in_fill (paths[0], &GRAPHENE_POINT_INIT (x, y), fill_rule),
|
||||
==,
|
||||
gsk_path_in_fill (paths[1], &GRAPHENE_POINT_INIT (y, -x), fill_rule));
|
||||
g_assert_cmpint (gsk_path_in_fill (paths[0], &GRAPHENE_POINT_INIT (y, x), fill_rule),
|
||||
==,
|
||||
gsk_path_in_fill (paths[1], &GRAPHENE_POINT_INIT (x, -y), fill_rule));
|
||||
}
|
||||
|
||||
gsk_path_unref (paths[0]);
|
||||
gsk_path_unref (paths[1]);
|
||||
}
|
||||
#undef N_FILL_RULES
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@@ -750,8 +590,6 @@ main (int argc,
|
||||
|
||||
g_test_add_func ("/path/create", test_create);
|
||||
g_test_add_func ("/path/parse", test_parse);
|
||||
g_test_add_func ("/path/in-fill-union", test_in_fill_union);
|
||||
g_test_add_func ("/path/in-fill-rotated", test_in_fill_rotated);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ test_calendar_set_day (void)
|
||||
|
||||
cal = gtk_calendar_new ();
|
||||
|
||||
tz = g_time_zone_new_identifier ("Europe/Brussels");
|
||||
tz = g_time_zone_new_identifier ("MET");
|
||||
g_assert_nonnull (tz);
|
||||
dt = g_date_time_new (tz, 1970, 3, 1, 0, 0, 0);
|
||||
g_assert_nonnull (dt);
|
||||
|
||||
Reference in New Issue
Block a user