mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 02:40:11 +00:00
Merge branch 'path-builder-simplify' into 'main'
pathbuilder: Simplify degenerate curves See merge request GNOME/gtk!6402
This commit is contained in:
commit
5a0b65c611
@ -112,4 +112,32 @@ gsk_bounding_box_union (const GskBoundingBox *a,
|
|||||||
gsk_bounding_box_init (res, &min, &max);
|
gsk_bounding_box_init (res, &min, &max);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_END_DECLS
|
static inline void
|
||||||
|
gsk_bounding_box_get_corner (const GskBoundingBox *b,
|
||||||
|
GskCorner c,
|
||||||
|
graphene_point_t *p)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case GSK_CORNER_TOP_LEFT:
|
||||||
|
*p = b->min;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_CORNER_TOP_RIGHT:
|
||||||
|
p->x = b->max.x;
|
||||||
|
p->y = b->min.y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_CORNER_BOTTOM_RIGHT:
|
||||||
|
*p = b->max;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_CORNER_BOTTOM_LEFT:
|
||||||
|
p->x = b->min.x;
|
||||||
|
p->y = b->max.y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2581,6 +2581,57 @@ gsk_curve_get_curvature_points (const GskCurve *curve,
|
|||||||
return filter_allowable (t, n);
|
return filter_allowable (t, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find cusps inside the open interval from 0 to 1.
|
||||||
|
*
|
||||||
|
* According to Stone & deRose, A Geometric Characterization
|
||||||
|
* of Parametric Cubic curves, a necessary and sufficient
|
||||||
|
* condition is that the first derivative vanishes.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
gsk_curve_get_cusps (const GskCurve *curve,
|
||||||
|
float t[2])
|
||||||
|
{
|
||||||
|
const graphene_point_t *pts = curve->cubic.points;
|
||||||
|
graphene_point_t p[3];
|
||||||
|
float ax, bx, cx;
|
||||||
|
float ay, by, cy;
|
||||||
|
float tx[3];
|
||||||
|
int nx;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
if (curve->op != GSK_PATH_CUBIC)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
p[0].x = 3 * (pts[1].x - pts[0].x);
|
||||||
|
p[0].y = 3 * (pts[1].y - pts[0].y);
|
||||||
|
p[1].x = 3 * (pts[2].x - pts[1].x);
|
||||||
|
p[1].y = 3 * (pts[2].y - pts[1].y);
|
||||||
|
p[2].x = 3 * (pts[3].x - pts[2].x);
|
||||||
|
p[2].y = 3 * (pts[3].y - pts[2].y);
|
||||||
|
|
||||||
|
ax = p[0].x - 2 * p[1].x + p[2].x;
|
||||||
|
bx = - 2 * p[0].x + 2 * p[1].x;
|
||||||
|
cx = p[0].x;
|
||||||
|
|
||||||
|
nx = solve_quadratic (ax, bx, cx, tx);
|
||||||
|
nx = filter_allowable (tx, nx);
|
||||||
|
|
||||||
|
ay = p[0].y - 2 * p[1].y + p[2].y;
|
||||||
|
by = - 2 * p[0].y + 2 * p[1].y;
|
||||||
|
cy = p[0].y;
|
||||||
|
|
||||||
|
for (int i = 0; i < nx; i++)
|
||||||
|
{
|
||||||
|
float ti = tx[i];
|
||||||
|
|
||||||
|
if (0 < ti && ti < 1 &&
|
||||||
|
fabsf (ay * ti * ti + by * ti + cy) < 0.001)
|
||||||
|
t[n++] = ti;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* vim:set foldmethod=marker expandtab: */
|
/* vim:set foldmethod=marker expandtab: */
|
||||||
|
@ -181,9 +181,12 @@ float gsk_curve_at_length (const GskCurve
|
|||||||
float distance,
|
float distance,
|
||||||
float epsilon);
|
float epsilon);
|
||||||
|
|
||||||
int gsk_curve_get_curvature_points (const GskCurve * curve,
|
int gsk_curve_get_curvature_points (const GskCurve *curve,
|
||||||
float t[3]);
|
float t[3]);
|
||||||
|
|
||||||
|
int gsk_curve_get_cusps (const GskCurve *curve,
|
||||||
|
float t[2]);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "gskpathbuilder.h"
|
#include "gskpathbuilder.h"
|
||||||
|
|
||||||
#include "gskpathprivate.h"
|
#include "gskpathprivate.h"
|
||||||
|
#include "gskcurveprivate.h"
|
||||||
#include "gskpathpointprivate.h"
|
#include "gskpathpointprivate.h"
|
||||||
#include "gskcontourprivate.h"
|
#include "gskcontourprivate.h"
|
||||||
|
|
||||||
@ -67,6 +68,9 @@
|
|||||||
*
|
*
|
||||||
* This is similar to how paths are drawn in Cairo.
|
* This is similar to how paths are drawn in Cairo.
|
||||||
*
|
*
|
||||||
|
* Note that `GskPathBuilder` will reduce the degree of added Bézier
|
||||||
|
* curves as much as possible, to simplify rendering.
|
||||||
|
*
|
||||||
* Since: 4.14
|
* Since: 4.14
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -624,6 +628,40 @@ gsk_path_builder_rel_line_to (GskPathBuilder *self,
|
|||||||
self->current_point.y + y);
|
self->current_point.y + y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
closest_point (const graphene_point_t *p,
|
||||||
|
const graphene_point_t *a,
|
||||||
|
const graphene_point_t *b,
|
||||||
|
graphene_point_t *q)
|
||||||
|
{
|
||||||
|
graphene_vec2_t n;
|
||||||
|
graphene_vec2_t ap;
|
||||||
|
float t;
|
||||||
|
|
||||||
|
graphene_vec2_init (&n, b->x - a->x, b->y - a->y);
|
||||||
|
graphene_vec2_init (&ap, p->x - a->x, p->y - a->y);
|
||||||
|
|
||||||
|
t = graphene_vec2_dot (&ap, &n) / graphene_vec2_dot (&n, &n);
|
||||||
|
|
||||||
|
q->x = a->x + t * (b->x - a->x);
|
||||||
|
q->y = a->y + t * (b->y - a->y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
collinear (const graphene_point_t *p,
|
||||||
|
const graphene_point_t *a,
|
||||||
|
const graphene_point_t *b)
|
||||||
|
{
|
||||||
|
graphene_point_t q;
|
||||||
|
|
||||||
|
if (graphene_point_equal (a, b))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
closest_point (p, a, b, &q);
|
||||||
|
|
||||||
|
return graphene_point_near (p, &q, 0.001);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gsk_path_builder_quad_to:
|
* gsk_path_builder_quad_to:
|
||||||
* @self: a #GskPathBuilder
|
* @self: a #GskPathBuilder
|
||||||
@ -651,22 +689,49 @@ gsk_path_builder_quad_to (GskPathBuilder *self,
|
|||||||
float x2,
|
float x2,
|
||||||
float y2)
|
float y2)
|
||||||
{
|
{
|
||||||
|
graphene_point_t p0 = self->current_point;
|
||||||
|
graphene_point_t p1 = GRAPHENE_POINT_INIT (x1, y1);
|
||||||
|
graphene_point_t p2 = GRAPHENE_POINT_INIT (x2, y2);
|
||||||
|
|
||||||
g_return_if_fail (self != NULL);
|
g_return_if_fail (self != NULL);
|
||||||
|
|
||||||
/* skip the quad if it collapses to a point */
|
if (collinear (&p0, &p1, &p2))
|
||||||
if (graphene_point_equal (&self->current_point,
|
{
|
||||||
&GRAPHENE_POINT_INIT (x1, y1)) &&
|
GskBoundingBox bb;
|
||||||
graphene_point_equal (&GRAPHENE_POINT_INIT (x1, y1),
|
|
||||||
&GRAPHENE_POINT_INIT (x2, y2)))
|
/* We simplify degenerate quads to one or two lines */
|
||||||
return;
|
if (!gsk_bounding_box_contains_point (gsk_bounding_box_init (&bb, &p0, &p2), &p1))
|
||||||
|
{
|
||||||
|
GskCurve c;
|
||||||
|
|
||||||
|
gsk_curve_init_foreach (&c, GSK_PATH_QUAD,
|
||||||
|
(const graphene_point_t []) { p0, p1, p2 },
|
||||||
|
3, 0.f);
|
||||||
|
gsk_curve_get_tight_bounds (&c, &bb);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
graphene_point_t q;
|
||||||
|
|
||||||
|
gsk_bounding_box_get_corner (&bb, i, &q);
|
||||||
|
if (graphene_point_equal (&p0, &q) ||
|
||||||
|
graphene_point_equal (&p2, &q))
|
||||||
|
{
|
||||||
|
gsk_bounding_box_get_corner (&bb, (i + 2) % 4, &q);
|
||||||
|
gsk_path_builder_line_to (self, q.x, q.y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gsk_path_builder_line_to (self, x2, y2);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self->flags &= ~GSK_PATH_FLAT;
|
self->flags &= ~GSK_PATH_FLAT;
|
||||||
gsk_path_builder_append_current (self,
|
gsk_path_builder_append_current (self,
|
||||||
GSK_PATH_QUAD,
|
GSK_PATH_QUAD,
|
||||||
2, (graphene_point_t[2]) {
|
2, (graphene_point_t[2]) { p1, p2 });
|
||||||
GRAPHENE_POINT_INIT (x1, y1),
|
|
||||||
GRAPHENE_POINT_INIT (x2, y2)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -702,6 +767,38 @@ gsk_path_builder_rel_quad_to (GskPathBuilder *self,
|
|||||||
self->current_point.y + y2);
|
self->current_point.y + y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
point_is_between (const graphene_point_t *q,
|
||||||
|
const graphene_point_t *p0,
|
||||||
|
const graphene_point_t *p1)
|
||||||
|
{
|
||||||
|
return collinear (p0, p1, q) &&
|
||||||
|
fabsf (graphene_point_distance (p0, q, NULL, NULL) + graphene_point_distance (p1, q, NULL, NULL) - graphene_point_distance (p0, p1, NULL, NULL)) < 0.001;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
bounding_box_corner_between (const GskBoundingBox *bb,
|
||||||
|
const graphene_point_t *p0,
|
||||||
|
const graphene_point_t *p1,
|
||||||
|
graphene_point_t *p)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
graphene_point_t q;
|
||||||
|
|
||||||
|
gsk_bounding_box_get_corner (bb, i, &q);
|
||||||
|
|
||||||
|
if (point_is_between (&q, p0, p1))
|
||||||
|
{
|
||||||
|
*p = q;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gsk_path_builder_cubic_to:
|
* gsk_path_builder_cubic_to:
|
||||||
* @self: a `GskPathBuilder`
|
* @self: a `GskPathBuilder`
|
||||||
@ -734,25 +831,136 @@ gsk_path_builder_cubic_to (GskPathBuilder *self,
|
|||||||
float x3,
|
float x3,
|
||||||
float y3)
|
float y3)
|
||||||
{
|
{
|
||||||
|
graphene_point_t p0 = self->current_point;
|
||||||
|
graphene_point_t p1 = GRAPHENE_POINT_INIT (x1, y1);
|
||||||
|
graphene_point_t p2 = GRAPHENE_POINT_INIT (x2, y2);
|
||||||
|
graphene_point_t p3 = GRAPHENE_POINT_INIT (x3, y3);
|
||||||
|
graphene_point_t p, q;
|
||||||
|
gboolean p01, p12, p23;
|
||||||
|
|
||||||
g_return_if_fail (self != NULL);
|
g_return_if_fail (self != NULL);
|
||||||
|
|
||||||
/* skip the cubic if it collapses to a point */
|
p01 = graphene_point_equal (&p0, &p1);
|
||||||
if (graphene_point_equal (&self->current_point,
|
p12 = graphene_point_equal (&p1, &p2);
|
||||||
&GRAPHENE_POINT_INIT (x1, y1)) &&
|
p23 = graphene_point_equal (&p2, &p3);
|
||||||
graphene_point_equal (&GRAPHENE_POINT_INIT (x1, y1),
|
|
||||||
&GRAPHENE_POINT_INIT (x2, y2)) &&
|
if (p01 && p12 && p23)
|
||||||
graphene_point_equal (&GRAPHENE_POINT_INIT (x2, y2),
|
|
||||||
&GRAPHENE_POINT_INIT (x3, y3)))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ((p01 && p23) || (p12 && (p01 || p23)))
|
||||||
|
{
|
||||||
|
gsk_path_builder_line_to (self, x3, y3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collinear (&p0, &p1, &p2) &&
|
||||||
|
collinear (&p1, &p2, &p3) &&
|
||||||
|
(!p12 || collinear (&p0, &p1, &p3)))
|
||||||
|
{
|
||||||
|
GskBoundingBox bb;
|
||||||
|
gboolean p1in, p2in;
|
||||||
|
|
||||||
|
gsk_bounding_box_init (&bb, &p0, &p3);
|
||||||
|
p1in = gsk_bounding_box_contains_point (&bb, &p1);
|
||||||
|
p2in = gsk_bounding_box_contains_point (&bb, &p2);
|
||||||
|
if (p1in && p2in)
|
||||||
|
{
|
||||||
|
gsk_path_builder_line_to (self, x3, y3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GskCurve c;
|
||||||
|
|
||||||
|
gsk_curve_init_foreach (&c,
|
||||||
|
GSK_PATH_CUBIC,
|
||||||
|
(const graphene_point_t[]) { p0, p1, p2, p3 },
|
||||||
|
4,
|
||||||
|
0.f);
|
||||||
|
gsk_curve_get_tight_bounds (&c, &bb);
|
||||||
|
if (!p1in)
|
||||||
|
{
|
||||||
|
/* Find the intersection of bb with p0 - p1.
|
||||||
|
* It must be a corner
|
||||||
|
*/
|
||||||
|
bounding_box_corner_between (&bb, &p0, &p1, &p);
|
||||||
|
gsk_path_builder_line_to (self, p.x, p.y);
|
||||||
|
}
|
||||||
|
if (!p2in)
|
||||||
|
{
|
||||||
|
/* Find the intersection of bb with p2 - p3. */
|
||||||
|
bounding_box_corner_between (&bb, &p3, &p2, &p);
|
||||||
|
gsk_path_builder_line_to (self, p.x, p.y);
|
||||||
|
}
|
||||||
|
gsk_path_builder_line_to (self, x3, y3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reduce to a quadratic if possible */
|
||||||
|
graphene_point_interpolate (&p0, &p1, 1.5, &p);
|
||||||
|
graphene_point_interpolate (&p3, &p2, 1.5, &q);
|
||||||
|
if (graphene_point_near (&p, &q, 0.001))
|
||||||
|
{
|
||||||
|
gsk_path_builder_quad_to (self, p.x, p.y, x3, y3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self->flags &= ~GSK_PATH_FLAT;
|
self->flags &= ~GSK_PATH_FLAT;
|
||||||
|
|
||||||
|
/* At this point, we are dealing with a cubic that can't be reduced to
|
||||||
|
* lines or quadratics. Check for cusps.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
GskCurve c, c1, c2, c3, c4;
|
||||||
|
float t[2];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
gsk_curve_init_foreach (&c,
|
||||||
|
GSK_PATH_CUBIC,
|
||||||
|
(const graphene_point_t[]) { p0, p1, p2, p3 },
|
||||||
|
4,
|
||||||
|
0.f);
|
||||||
|
|
||||||
|
n = gsk_curve_get_cusps (&c, t);
|
||||||
|
if (n == 1)
|
||||||
|
{
|
||||||
|
gsk_curve_split (&c, t[0], &c1, &c2);
|
||||||
|
gsk_path_builder_append_current (self,
|
||||||
|
GSK_PATH_CUBIC,
|
||||||
|
3, &c1.cubic.points[1]);
|
||||||
|
gsk_path_builder_append_current (self,
|
||||||
|
GSK_PATH_CUBIC,
|
||||||
|
3, &c2.cubic.points[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (n == 2)
|
||||||
|
{
|
||||||
|
if (t[1] < t[0])
|
||||||
|
{
|
||||||
|
float s = t[0];
|
||||||
|
t[0] = t[1];
|
||||||
|
t[1] = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsk_curve_split (&c, t[0], &c1, &c2);
|
||||||
|
gsk_curve_split (&c2, (t[1] - t[0]) / (1 - t[0]), &c3, &c4);
|
||||||
|
gsk_path_builder_append_current (self,
|
||||||
|
GSK_PATH_CUBIC,
|
||||||
|
3, &c1.cubic.points[1]);
|
||||||
|
gsk_path_builder_append_current (self,
|
||||||
|
GSK_PATH_CUBIC,
|
||||||
|
3, &c3.cubic.points[1]);
|
||||||
|
gsk_path_builder_append_current (self,
|
||||||
|
GSK_PATH_CUBIC,
|
||||||
|
3, &c4.cubic.points[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gsk_path_builder_append_current (self,
|
gsk_path_builder_append_current (self,
|
||||||
GSK_PATH_CUBIC,
|
GSK_PATH_CUBIC,
|
||||||
3, (graphene_point_t[3]) {
|
3, (graphene_point_t[3]) { p1, p2, p3 });
|
||||||
GRAPHENE_POINT_INIT (x1, y1),
|
|
||||||
GRAPHENE_POINT_INIT (x2, y2),
|
|
||||||
GRAPHENE_POINT_INIT (x3, y3)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -831,15 +1039,53 @@ gsk_path_builder_conic_to (GskPathBuilder *self,
|
|||||||
float y2,
|
float y2,
|
||||||
float weight)
|
float weight)
|
||||||
{
|
{
|
||||||
|
graphene_point_t p0 = self->current_point;
|
||||||
|
graphene_point_t p1 = GRAPHENE_POINT_INIT (x1, y1);
|
||||||
|
graphene_point_t p2 = GRAPHENE_POINT_INIT (x2, y2);
|
||||||
|
|
||||||
g_return_if_fail (self != NULL);
|
g_return_if_fail (self != NULL);
|
||||||
g_return_if_fail (weight > 0);
|
g_return_if_fail (weight > 0);
|
||||||
|
|
||||||
/* skip the conic if it collapses to a point */
|
if (weight == 1)
|
||||||
if (graphene_point_equal (&self->current_point,
|
{
|
||||||
&GRAPHENE_POINT_INIT (x1, y1)) &&
|
gsk_path_builder_quad_to (self, x1, y1, x2, y2);
|
||||||
graphene_point_equal (&GRAPHENE_POINT_INIT (x1, y1),
|
return;
|
||||||
&GRAPHENE_POINT_INIT (x2, y2)))
|
}
|
||||||
return;
|
|
||||||
|
if (collinear (&p0, &p1, &p2))
|
||||||
|
{
|
||||||
|
GskBoundingBox bb;
|
||||||
|
|
||||||
|
/* We simplify degenerate quads to one or two lines
|
||||||
|
* (two lines are needed if there's a cusp).
|
||||||
|
*/
|
||||||
|
if (!gsk_bounding_box_contains_point (gsk_bounding_box_init (&bb, &p0, &p2), &p1))
|
||||||
|
{
|
||||||
|
GskCurve c;
|
||||||
|
|
||||||
|
gsk_curve_init_foreach (&c, GSK_PATH_CONIC,
|
||||||
|
(const graphene_point_t []) { p0, p1, p2 },
|
||||||
|
3, weight);
|
||||||
|
gsk_curve_get_tight_bounds (&c, &bb);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
graphene_point_t q;
|
||||||
|
|
||||||
|
gsk_bounding_box_get_corner (&bb, i, &q);
|
||||||
|
if (graphene_point_equal (&p0, &q) ||
|
||||||
|
graphene_point_equal (&p2, &q))
|
||||||
|
{
|
||||||
|
gsk_bounding_box_get_corner (&bb, (i + 2) % 4, &q);
|
||||||
|
gsk_path_builder_line_to (self, q.x, q.y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gsk_path_builder_line_to (self, x2, y2);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self->flags &= ~GSK_PATH_FLAT;
|
self->flags &= ~GSK_PATH_FLAT;
|
||||||
gsk_path_builder_append_current (self,
|
gsk_path_builder_append_current (self,
|
||||||
|
@ -4364,16 +4364,16 @@ gtk_window_realize (GtkWidget *widget)
|
|||||||
{
|
{
|
||||||
gtk_window_enable_csd (window);
|
gtk_window_enable_csd (window);
|
||||||
|
|
||||||
if (priv->title_box == NULL)
|
if (priv->title_box == NULL)
|
||||||
{
|
{
|
||||||
priv->title_box = gtk_header_bar_new ();
|
priv->title_box = gtk_header_bar_new ();
|
||||||
gtk_widget_add_css_class (priv->title_box, "titlebar");
|
gtk_widget_add_css_class (priv->title_box, "titlebar");
|
||||||
gtk_widget_add_css_class (priv->title_box, "default-decoration");
|
gtk_widget_add_css_class (priv->title_box, "default-decoration");
|
||||||
|
|
||||||
gtk_widget_insert_before (priv->title_box, widget, NULL);
|
gtk_widget_insert_before (priv->title_box, widget, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_window_actions (window);
|
update_window_actions (window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
fill {
|
fill {
|
||||||
path: "M 0 0 O 10 10 20 20 5";
|
path: "M 0 0 O 10 0 20 20 5";
|
||||||
fill-rule: even-odd;
|
fill-rule: even-odd;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,6 @@ fill {
|
|||||||
color: rgb(255,0,204);
|
color: rgb(255,0,204);
|
||||||
}
|
}
|
||||||
path: "\
|
path: "\
|
||||||
M 0 0 O 10 10, 20 20, 5";
|
M 0 0 O 10 0, 20 20, 5";
|
||||||
fill-rule: even-odd;
|
fill-rule: even-odd;
|
||||||
}
|
}
|
||||||
|
@ -426,10 +426,23 @@ test_foreach (void)
|
|||||||
path2 = gsk_path_builder_free_to_path (builder);
|
path2 = gsk_path_builder_free_to_path (builder);
|
||||||
s2 = gsk_path_to_string (path2);
|
s2 = gsk_path_to_string (path2);
|
||||||
|
|
||||||
g_assert_cmpstr (sp, ==, s2);
|
/* We still end up with quads here, since GskPathBuilder aggressively reduces
|
||||||
|
* curves degrees.
|
||||||
|
*/
|
||||||
|
g_assert_cmpstr (s, ==, s2);
|
||||||
|
|
||||||
gsk_path_unref (path2);
|
gsk_path_unref (path2);
|
||||||
g_free (s2);
|
g_free (s2);
|
||||||
|
|
||||||
|
path2 = gsk_path_parse (sp);
|
||||||
|
s2 = gsk_path_to_string (path2);
|
||||||
|
|
||||||
|
g_assert_cmpstr (s, ==, s2);
|
||||||
|
|
||||||
|
gsk_path_unref (path2);
|
||||||
|
g_free (s2);
|
||||||
|
|
||||||
|
gsk_path_unref (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user