Compare commits

..

10 Commits

Author SHA1 Message Date
Matthias Clasen c1e6e8e2a7 Add more fill and stroke node tests 2023-08-26 00:48:31 -04:00
Matthias Clasen 61756ab39d Document node format for stroke and fill nodes 2023-08-26 00:48:31 -04:00
Matthias Clasen ca188b41ae post-release version bump 2023-08-25 22:29:09 -04:00
Matthias Clasen 01b9997590 4.13.0 2023-08-25 22:21:27 -04:00
Matthias Clasen 677e19042d Docs: Cosmetics 2023-08-25 22:21:27 -04:00
Matthias Clasen bd79f61cc5 pathpoint: Update the docs
We have gained some more ways of getting points.
2023-08-25 22:03:42 -04:00
Matthias Clasen 361cdecfe4 Merge branch 'path-measure-reredone' into 'main'
Add GskPathMeasure

See merge request GNOME/gtk!6326
2023-08-26 01:05:19 +00:00
Benjamin Otte 81821978ae Merge branch 'wip/otte/for-main' into 'main'
gltexture: Restore previous GL context

See merge request GNOME/gtk!6335
2023-08-25 21:44:17 +00:00
Benjamin Otte ae7ec40cf2 rendernodeparser: Generate better default child
... for fill and stroke nodes.

It's most likely we want the path bounds (or path stroke bounds),
so make the parser use those by default.
2023-08-25 21:12:12 +02:00
Benjamin Otte 8aaecc3416 gltexture: Restore previous GL context
Texture downloads can be initiated due to the weirdest reasons - and if
they cause a GL context to be changed, it'd be basically unpredictable
when the GL context changes.

An example is the Cairo renderer - if it needs to draw a GL texture, it
will download it.

Now that no longer changes the GL context.
2023-08-24 05:00:29 +02:00
24 changed files with 323 additions and 250 deletions
+76 -1
View File
@@ -1,6 +1,81 @@
Overview of Changes in 4.13.0, xx-xx-xxxx
Overview of Changes in 4.13.1, xx-xx-xxxx
=========================================
Overview of Changes in 4.13.0, 25-08-2023
=========================================
* GskPath, GskPathBuilder, GskPathMeasure:
Data types and APIs for path rendering. These APIs are still
considered experimental, and may change until 4.14. Please try
them out and give us feedback. Documentation can be found
here: https://docs.gtk.org/gsk4/paths.html
* GtkGridView:
- Fix a crash when scrolling
* GtkColumnView:
- Fix a refcounting issue in the new scroll_to api
* GtkTreeView
- Fix style classes for sort arrows
* GtkEntry:
- Improve tracking of user changes (for undo)
* GtkNotebook:
- Fix a critical when switching pages
* GtkColor/FontDialogButton:
- Make these widgets activatable
* GtkMenuButton:
- Fix problems with focus handling
- Fix problems with DND
- Make flags a settable property
* GtkShortcutsWindow:
- Add API to build shortcuts windows programmatically
* Printing
- Fix the cpdb backend build
* MacOS:
- Make file filters work again
* GSK:
- Fix issues with color matrix nodes
* Wayland:
- Fix a crash with compositors other than gnome-shell
* Deprecations:
- Remaining GtkTreeModel-related types
* Demos:
- Add a few path demos to gtk4-demo
* Tools:
- gtk4-path-tool provides a commandline interface for paths
* Translation updates:
Basque
Catalan
Finnish
Galician
Georgian
German
Greek
Indonesian
Kazakh
Persian
Polish
Romanian
Spanish
Swedish
Turkish
Ukrainian
Overview of Changes in 4.12.0, 05-08-2023
=========================================
+15 -14
View File
@@ -104,19 +104,20 @@ gtk_path_transform_point (GskPathMeasure *measure,
}
static gboolean
gtk_path_transform_op (const graphene_point_t *start,
const graphene_point_t *end,
const GskPathControl *control,
gtk_path_transform_op (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
GtkPathTransform *transform = data;
switch (control->op)
switch (op)
{
case GSK_PATH_MOVE:
{
graphene_point_t res;
gtk_path_transform_point (transform->measure, end, &transform->offset, transform->scale, &res);
gtk_path_transform_point (transform->measure, &pts[0], &transform->offset, transform->scale, &res);
gsk_path_builder_move_to (transform->builder, res.x, res.y);
}
break;
@@ -124,7 +125,7 @@ gtk_path_transform_op (const graphene_point_t *start,
case GSK_PATH_LINE:
{
graphene_point_t res;
gtk_path_transform_point (transform->measure, end, &transform->offset, transform->scale, &res);
gtk_path_transform_point (transform->measure, &pts[1], &transform->offset, transform->scale, &res);
gsk_path_builder_line_to (transform->builder, res.x, res.y);
}
break;
@@ -132,8 +133,8 @@ gtk_path_transform_op (const graphene_point_t *start,
case GSK_PATH_QUAD:
{
graphene_point_t res[2];
gtk_path_transform_point (transform->measure, &control->quad.control, &transform->offset, transform->scale, &res[0]);
gtk_path_transform_point (transform->measure, end, &transform->offset, transform->scale, &res[1]);
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;
@@ -141,9 +142,9 @@ gtk_path_transform_op (const graphene_point_t *start,
case GSK_PATH_CUBIC:
{
graphene_point_t res[3];
gtk_path_transform_point (transform->measure, &control->cubic.control1, &transform->offset, transform->scale, &res[0]);
gtk_path_transform_point (transform->measure, &control->cubic.control2, &transform->offset, transform->scale, &res[1]);
gtk_path_transform_point (transform->measure, end, &transform->offset, transform->scale, &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]);
gtk_path_transform_point (transform->measure, &pts[3], &transform->offset, transform->scale, &res[2]);
gsk_path_builder_cubic_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, res[2].x, res[2].y);
}
break;
@@ -151,9 +152,9 @@ gtk_path_transform_op (const graphene_point_t *start,
case GSK_PATH_CONIC:
{
graphene_point_t res[2];
gtk_path_transform_point (transform->measure, &control->conic.control, &transform->offset, transform->scale, &res[0]);
gtk_path_transform_point (transform->measure, end, &transform->offset, transform->scale, &res[1]);
gsk_path_builder_conic_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, control->conic.weight);
gtk_path_transform_point (transform->measure, &pts[1], &transform->offset, transform->scale, &res[0]);
gtk_path_transform_point (transform->measure, &pts[3], &transform->offset, transform->scale, &res[1]);
gsk_path_builder_conic_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, weight);
}
break;
+29
View File
@@ -147,6 +147,18 @@ Creates a node like `gsk_cross_fade_node_new()` with the given properties.
Creates a node like `gsk_debug_node_new()` with the given properties.
### fill
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| child | `<node>` | *see below* | always |
| path | `<string>` | "" | always |
| fill-rule| `<fill-rule>` | winding | always |
Creates a node like `gsk_fill_node_new()` with the given properties.
The default child node is created with the bounds of the path.
### glshader
| property | syntax | default | printed |
@@ -289,6 +301,23 @@ Creates a node like `gsk_rounded_clip_node_new()` with the given properties.
Creates a node like `gsk_shadow_node_new()` with the given properties.
### stroke
| property | syntax | default | printed |
| ----------- | ------------------ | ----------------- | ----------- |
| child | `<node>` | *see below* | always |
| path | `<string>` | "" | always |
| line-width | `<number>` | 0 | non-default |
| line-cap | `<line-cap>` | butt | always |
| line-join | `<line-join>` | miter | always |
| miter-limit | `<number>` | 4 | non-default |
| dash | `<number>{+}|none` | none | non-default |
| dash-offset | `<number>` | 0 | non-default |
Creates a node like `gsk_stroke_node_new()` with the given properties.
The default child node is created with the stroke bounds of the path.
### text
| property | syntax | default | printed |
+7 -1
View File
@@ -95,10 +95,11 @@ static gboolean
gdk_gl_texture_invoke_callback (gpointer data)
{
InvokeData *invoke = data;
GdkGLContext *context;
GdkGLContext *context, *previous;
context = gdk_display_get_gl_context (gdk_gl_context_get_display (invoke->self->context));
previous = gdk_gl_context_get_current ();
gdk_gl_context_make_current (context);
if (invoke->self->sync && context != invoke->self->context)
@@ -110,6 +111,11 @@ gdk_gl_texture_invoke_callback (gpointer data)
g_atomic_int_set (&invoke->spinlock, 1);
if (previous)
gdk_gl_context_make_current (previous);
else
gdk_gl_context_clear_current ();
return FALSE;
}
+14 -56
View File
@@ -381,10 +381,7 @@ gsk_line_curve_decompose_curve (const GskCurve *curve,
{
const GskLineCurve *self = &curve->line;
return add_curve_func (&self->points[0],
&self->points[1],
&(GskPathControl) { .op = GSK_PATH_LINE },
user_data);
return add_curve_func (GSK_PATH_LINE, self->points, 2, 0.f, user_data);
}
static void
@@ -708,10 +705,9 @@ gsk_curve_add_line_cb (const graphene_point_t *from,
gpointer user_data)
{
AddLineData *data = user_data;
graphene_point_t p[2] = { *from, *to };
return data->add_curve (from, to,
&(GskPathControl) { .op = GSK_PATH_LINE },
data->user_data);
return data->add_curve (GSK_PATH_LINE, p, 2, 0.f, data->user_data);
}
static gboolean
@@ -724,30 +720,13 @@ gsk_quad_curve_decompose_curve (const GskCurve *curve,
const GskQuadCurve *self = &curve->quad;
if (flags & GSK_PATH_FOREACH_ALLOW_QUAD)
return add_curve_func (&self->points[0],
&self->points[2],
&(GskPathControl) {
.op = GSK_PATH_QUAD,
.quad = (GskQuadControl) {
.control = self->points[1],
},
},
user_data);
return add_curve_func (GSK_PATH_QUAD, self->points, 3, 0.f, user_data);
else if (flags & GSK_PATH_FOREACH_ALLOW_CUBIC)
{
GskCurve c;
gsk_curve_elevate (curve, &c);
return add_curve_func (&c.cubic.points[0],
&c.cubic.points[3],
&(GskPathControl) {
.op = GSK_PATH_CUBIC,
.cubic = (GskCubicControl) {
.control1 = c.cubic.points[1],
.control2 = c.cubic.points[2],
},
},
user_data);
return add_curve_func (GSK_PATH_CUBIC, c.cubic.points, 4, 0.f, user_data);
}
else
{
@@ -1201,16 +1180,7 @@ gsk_cubic_curve_decompose_curve (const GskCurve *curve,
const GskCubicCurve *self = &curve->cubic;
if (flags & GSK_PATH_FOREACH_ALLOW_CUBIC)
return add_curve_func (&self->points[0],
&self->points[3],
&(GskPathControl) {
.op = GSK_PATH_CUBIC,
.cubic = (GskCubicControl) {
.control1 = self->points[1],
.control2 = self->points[2],
},
},
user_data);
return add_curve_func (GSK_PATH_CUBIC, self->points, 4, 0.f, user_data);
/* FIXME: Quadratic or arc approximation */
return gsk_cubic_curve_decompose (curve,
@@ -1884,16 +1854,7 @@ gsk_conic_curve_decompose_or_add (const GskCurve *curve,
gpointer user_data)
{
if (gsk_conic_is_close_to_cubic (curve, cubic, tolerance))
return add_curve_func (&cubic->cubic.points[0],
&cubic->cubic.points[3],
&(GskPathControl) {
.op = GSK_PATH_CUBIC,
.cubic = (GskCubicControl) {
.control1 = cubic->cubic.points[1],
.control2 = cubic->cubic.points[2],
},
},
user_data);
return add_curve_func (GSK_PATH_CUBIC, cubic->cubic.points, 4, 0.f, user_data);
else
{
GskCurve c1, c2;
@@ -1920,16 +1881,13 @@ gsk_conic_curve_decompose_curve (const GskCurve *curve,
GskCurve c;
if (flags & GSK_PATH_FOREACH_ALLOW_CONIC)
return add_curve_func (&self->points[0],
&self->points[3],
&(GskPathControl) {
.op = GSK_PATH_CONIC,
.conic = (GskConicControl) {
.control = self->points[1],
.weight = self->points[2].x
},
},
user_data);
return add_curve_func (GSK_PATH_CONIC,
(const graphene_point_t[3]) { self->points[0],
self->points[1],
self->points[3] },
3,
self->points[2].x,
user_data);
if (flags & GSK_PATH_FOREACH_ALLOW_CUBIC)
{
+4 -3
View File
@@ -102,9 +102,10 @@ typedef gboolean (* GskCurveAddLineFunc) (const graphene_point_t *from,
GskCurveLineReason reason,
gpointer user_data);
typedef gboolean (* GskCurveAddCurveFunc) (const graphene_point_t *start,
const graphene_point_t *end,
const GskPathControl *control,
typedef gboolean (* GskCurveAddCurveFunc) (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer user_data);
void gsk_curve_init (GskCurve *curve,
+41 -54
View File
@@ -177,7 +177,7 @@ gsk_path_get_flags (const GskPath *self)
* Converts @self into a human-readable string representation suitable
* for printing.
*
* The string is compatible with
* The string is compatible with (a superset of)
* [SVG path syntax](https://www.w3.org/TR/SVG11/paths.html#PathData),
* see [func@Gsk.Path.parse] for a summary of the syntax.
*
@@ -231,15 +231,16 @@ gsk_path_to_string (GskPath *self)
}
static gboolean
gsk_path_to_cairo_add_op (const graphene_point_t *start,
const graphene_point_t *end,
const GskPathControl *control,
gsk_path_to_cairo_add_op (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer cr)
{
switch (control->op)
switch (op)
{
case GSK_PATH_MOVE:
cairo_move_to (cr, end->x, end->y);
cairo_move_to (cr, pts[0].x, pts[0].y);
break;
case GSK_PATH_CLOSE:
@@ -247,13 +248,11 @@ gsk_path_to_cairo_add_op (const graphene_point_t *start,
break;
case GSK_PATH_LINE:
cairo_line_to (cr, end->x, end->y);
cairo_line_to (cr, pts[1].x, pts[1].y);
break;
case GSK_PATH_CUBIC:
cairo_curve_to (cr, control->cubic.control1.x, control->cubic.control1.y,
control->cubic.control2.x, control->cubic.control2.y,
end->x, end->y);
cairo_curve_to (cr, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
break;
case GSK_PATH_QUAD:
@@ -422,6 +421,7 @@ 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
@@ -669,65 +669,64 @@ gsk_path_foreach_trampoline_add_line (const graphene_point_t *from,
{
GskPathForeachTrampoline *trampoline = data;
return trampoline->func (from, to,
&(GskPathControl) { GSK_PATH_LINE, },
return trampoline->func (GSK_PATH_LINE,
(graphene_point_t[2]) { *from, *to },
2,
0.f,
trampoline->user_data);
}
static gboolean
gsk_path_foreach_trampoline_add_curve (const graphene_point_t *start,
const graphene_point_t *end,
const GskPathControl *control,
gsk_path_foreach_trampoline_add_curve (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
GskPathForeachTrampoline *trampoline = data;
return trampoline->func (start, end, control, trampoline->user_data);
return trampoline->func (op, pts, n_pts, weight, trampoline->user_data);
}
static gboolean
gsk_path_foreach_trampoline (const graphene_point_t *start,
const graphene_point_t *end,
const GskPathControl *control,
gsk_path_foreach_trampoline (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
GskPathForeachTrampoline *trampoline = data;
switch (control->op)
switch (op)
{
case GSK_PATH_MOVE:
case GSK_PATH_CLOSE:
case GSK_PATH_LINE:
return trampoline->func (start, end, control, trampoline->user_data);
return trampoline->func (op, pts, n_pts, weight, trampoline->user_data);
case GSK_PATH_QUAD:
{
GskCurve curve;
if (trampoline->flags & GSK_PATH_FOREACH_ALLOW_QUAD)
return trampoline->func (start, end, control, trampoline->user_data);
return trampoline->func (op, pts, n_pts, weight, trampoline->user_data);
else if (trampoline->flags & GSK_PATH_FOREACH_ALLOW_CUBIC)
{
return trampoline->func (start,
end,
&(GskPathControl) {
.op = GSK_PATH_CUBIC,
.cubic = (GskCubicControl) {
.control1 = GRAPHENE_POINT_INIT ((start->x + 2 * control->quad.control.x) / 3,
(start->y + 2 * control->quad.control.y) / 3),
.control2 = GRAPHENE_POINT_INIT ((end->x + 2 * control->quad.control.x) / 3,
(end->y + 2 * control->quad.control.y) / 3),
},
return trampoline->func (GSK_PATH_CUBIC,
(graphene_point_t[4]) {
pts[0],
GRAPHENE_POINT_INIT ((pts[0].x + 2 * pts[1].x) / 3,
(pts[0].y + 2 * pts[1].y) / 3),
GRAPHENE_POINT_INIT ((pts[2].x + 2 * pts[1].x) / 3,
(pts[2].y + 2 * pts[1].y) / 3),
pts[2],
},
4,
weight,
trampoline->user_data);
}
gsk_curve_init (&curve, gsk_pathop_encode (GSK_PATH_QUAD,
(graphene_point_t[3]) {
*start,
control->quad.control,
*end,
} ));
gsk_curve_init (&curve, gsk_pathop_encode (GSK_PATH_QUAD, pts));
return gsk_curve_decompose (&curve,
trampoline->tolerance,
gsk_path_foreach_trampoline_add_line,
@@ -739,15 +738,9 @@ gsk_path_foreach_trampoline (const graphene_point_t *start,
GskCurve curve;
if (trampoline->flags & GSK_PATH_FOREACH_ALLOW_CUBIC)
return trampoline->func (start, end, control, trampoline->user_data);
return trampoline->func (op, pts, n_pts, weight, trampoline->user_data);
gsk_curve_init (&curve, gsk_pathop_encode (GSK_PATH_CUBIC,
(const graphene_point_t[4]) {
*start,
control->cubic.control1,
control->cubic.control2,
*end,
}));
gsk_curve_init (&curve, gsk_pathop_encode (GSK_PATH_CUBIC, pts));
if (trampoline->flags & (GSK_PATH_FOREACH_ALLOW_QUAD|GSK_PATH_FOREACH_ALLOW_CONIC))
return gsk_curve_decompose_curve (&curve,
trampoline->flags,
@@ -766,15 +759,9 @@ gsk_path_foreach_trampoline (const graphene_point_t *start,
GskCurve curve;
if (trampoline->flags & GSK_PATH_FOREACH_ALLOW_CONIC)
return trampoline->func (start, end, control, trampoline->user_data);
return trampoline->func (op, pts, n_pts, weight, trampoline->user_data);
gsk_curve_init (&curve, gsk_pathop_encode (GSK_PATH_CONIC,
(graphene_point_t[4]) {
*start,
control->conic.control,
{ control->conic.weight, 0.f },
*end
} ));
gsk_curve_init (&curve, gsk_pathop_encode (GSK_PATH_CONIC, (graphene_point_t[4]) { pts[0], pts[1], { weight, 0.f }, pts[2] } ));
if (trampoline->flags & (GSK_PATH_FOREACH_ALLOW_QUAD|GSK_PATH_FOREACH_ALLOW_CUBIC))
return gsk_curve_decompose_curve (&curve,
trampoline->flags,
+12 -40
View File
@@ -53,50 +53,21 @@ typedef enum
GSK_PATH_FOREACH_ALLOW_CONIC = (1 << 2),
} GskPathForeachFlags;
typedef struct _GskQuadControl GskQuadControl;
struct _GskQuadControl
{
graphene_point_t control;
};
typedef struct _GskCubicControl GskCubicControl;
struct _GskCubicControl
{
graphene_point_t control1;
graphene_point_t control2;
};
typedef struct _GskConicControl GskConicControl;
struct _GskConicControl
{
graphene_point_t control;
float weight;
};
typedef struct _GskPathControl GskPathControl;
struct _GskPathControl
{
GskPathOperation op;
union {
GskQuadControl quad;
GskCubicControl cubic;
GskConicControl conic;
};
};
/**
* GskPathForeachFunc:
* @start: The start point of the operation
* @end: The end point of the operation
* @control: The control data for the operation
* @op: The operation
* @pts: The points of the operation
* @n_pts: The number of points
* @weight: The weight for conic curves, or unused if not a conic curve
* @user_data: The user data provided with the function
*
* Prototype of the callback to iterate through the operations of
* a path.
*
* For each operation, the callback is given the @op itself, the start-
* and endpoint, and the control data, depending on the kind of operation.
* For each operation, the callback is given the @op itself, the points
* that the operation is applied to in @pts, and a @weight for conic
* curves. The @n_pts argument is somewhat redundant, since the number
* of points can be inferred from the operation.
*
* Each contour of the path starts with a @GSK_PATH_MOVE operation.
* Closed contours end with a @GSK_PATH_CLOSE operation.
@@ -104,9 +75,10 @@ struct _GskPathControl
* Returns: %TRUE to continue iterating the path, %FALSE to
* immediately abort and not call the function again.
*/
typedef gboolean (* GskPathForeachFunc) (const graphene_point_t *start,
const graphene_point_t *end,
const GskPathControl *control,
typedef gboolean (* GskPathForeachFunc) (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer user_data);
#define GSK_TYPE_PATH (gsk_path_get_type ())
+20 -15
View File
@@ -64,7 +64,7 @@
* [method@Gsk.PathBuilder.close] to close the path by connecting it
* back with a line to the starting point.
*
* This is similar for how paths are drawn in Cairo.
* This is similar to how paths are drawn in Cairo.
*
* Since: 4.14
*/
@@ -240,7 +240,7 @@ gsk_path_builder_unref (GskPathBuilder *self)
* @self: a `GskPathBuilder`
*
* Creates a new `GskPath` from the current state of the
* given builder, and frees the @builder instance.
* given builder, and unrefs the @builder instance.
*
* Returns: (transfer full): the newly created `GskPath`
* with all the contours added to the builder
@@ -310,12 +310,14 @@ gsk_path_builder_add_contour (GskPathBuilder *self,
* gsk_path_builder_get_current_point:
* @self: a `GskPathBuilder`
*
* Gets the current point. The current point is used for relative
* drawing commands and updated after every operation.
* Gets the current point.
*
* When the builder is created, the default current point is set to (0, 0).
* Note that this is different from cairo, which starts out without
* a current point.
* The current point is used for relative drawing commands and
* updated after every operation.
*
* When the builder is created, the default current point is set
* to `0, 0`. Note that this is different from cairo, which starts
* out without a current point.
*
* Returns: (transfer none): The current point
*
@@ -828,7 +830,9 @@ gsk_path_builder_cubic_to (GskPathBuilder *self,
*
* Adds a [cubic Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve)
* from the current point to @x3, @y3 with @x1, @y1 and @x2, @y2 as the control
* points. All coordinates are given relative to the current point.
* points.
*
* All coordinates are given relative to the current point.
*
* This is the relative version of [method@Gsk.PathBuilder.cubic_to].
*
@@ -865,7 +869,7 @@ gsk_path_builder_rel_cubic_to (GskPathBuilder *self,
*
* Adds a [conic curve](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)
* from the current point to @x2, @y2 with the given @weight and @x1, @y1 as the
* single control point.
* control point.
*
* The weight determines how strongly the curve is pulled towards the control point.
* A conic with weight 1 is identical to a quadratic Bézier curve with the same points.
@@ -914,7 +918,9 @@ gsk_path_builder_conic_to (GskPathBuilder *self,
*
* Adds a [conic curve](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)
* from the current point to @x2, @y2 with the given @weight and @x1, @y1 as the
* single control point.
* control point.
*
* All coordinates are given relative to the current point.
*
* This is the relative version of [method@Gsk.PathBuilder.conic_to].
*
@@ -985,8 +991,9 @@ gsk_path_builder_arc_to (GskPathBuilder *self,
* @y2: y coordinate of second control point
*
* Adds an elliptical arc from the current point to @x3, @y3
* with @x1, @y1 determining the tangent directions. All coordinates
* are given relative to the current point.
* with @x1, @y1 determining the tangent directions.
*
* All coordinates are given relative to the current point.
*
* This is the relative version of [method@Gsk.PathBuilder.arc_to].
*
@@ -1332,7 +1339,6 @@ angle_between_points (const graphene_point_t *c,
* the circle with the given radius touches the line from
* @x1, @y1 to @x2, @y2.
*
*
* Since: 4.14
*/
void
@@ -1417,8 +1423,7 @@ gsk_path_builder_rel_html_arc_to (GskPathBuilder *self,
* @self: a #GskPathBuilder
* @layout: the pango layout to add
*
* Adds the outlines for the glyphs in @layout to
* the builder.
* Adds the outlines for the glyphs in @layout to the builder.
*
* Since: 4.14
*/
+2 -1
View File
@@ -69,7 +69,8 @@ G_DEFINE_BOXED_TYPE (GskPathMeasure, gsk_path_measure,
* gsk_path_measure_new:
* @path: the path to measure
*
* Creates a measure object for the given @path.
* Creates a measure object for the given @path with the
* default tolerance.
*
* Returns: a new `GskPathMeasure` representing @path
*
+8 -35
View File
@@ -89,50 +89,23 @@ gsk_pathop_foreach (gskpathop pop,
switch (gsk_pathop_op (pop))
{
case GSK_PATH_MOVE:
return func (&GRAPHENE_POINT_INIT (0, 0),
&gsk_pathop_points (pop)[0],
&(GskPathControl) { .op = gsk_pathop_op (pop), },
user_data);
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 1, 0, user_data);
case GSK_PATH_CLOSE:
case GSK_PATH_LINE:
return func (&gsk_pathop_points (pop)[0],
&gsk_pathop_points (pop)[1],
&(GskPathControl) { .op = gsk_pathop_op (pop), },
user_data);
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 2, 0, user_data);
case GSK_PATH_QUAD:
return func (&gsk_pathop_points (pop)[0],
&gsk_pathop_points (pop)[2],
&(GskPathControl) {
.op = gsk_pathop_op (pop),
.quad = (GskQuadControl) { gsk_pathop_points (pop)[1] }
},
user_data);
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 3, 0, user_data);
case GSK_PATH_CUBIC:
return func (&gsk_pathop_points (pop)[0],
&gsk_pathop_points (pop)[3],
&(GskPathControl) {
.op = gsk_pathop_op (pop),
.cubic = (GskCubicControl) {
.control1 = gsk_pathop_points (pop)[1],
.control2 = gsk_pathop_points (pop)[2]
},
},
user_data);
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 4, 0, user_data);
case GSK_PATH_CONIC:
return func (&gsk_pathop_points (pop)[0],
&gsk_pathop_points (pop)[3],
&(GskPathControl) {
.op = gsk_pathop_op (pop),
.conic = (GskConicControl) {
.control = gsk_pathop_points (pop)[1],
.weight = gsk_pathop_points (pop)[2].x
},
},
user_data);
{
const graphene_point_t *pts = gsk_pathop_points (pop);
return func (gsk_pathop_op (pop), (graphene_point_t[3]) { pts[0], pts[1], pts[3] }, 3, pts[2].x, user_data);
}
default:
g_assert_not_reached ();
+9 -3
View File
@@ -34,10 +34,12 @@
*
* `GskPathPoint` is an opaque type representing a point on a path.
*
* It can be queried for properties of the path at that point, such as its
* tangent or its curvature.
* It can be queried for properties of the path at that point, such as
* its tangent or its curvature.
*
* To obtain a `GskPathPoint`, use [method@Gsk.Path.get_closest_point].
* To obtain a `GskPathPoint`, use [method@Gsk.Path.get_closest_point],
* [method@Gsk.Path.get_start_point], [method@Gsk.Path.get_end_point]
* or [method@Gsk.PathMeasure.get_point].
*
* Note that `GskPathPoint` structs are meant to be stack-allocated, and
* don't a reference to the path object they are obtained from. It is the
@@ -85,6 +87,8 @@ gsk_path_point_free (GskPathPoint *point)
* same location.
*
* Return: `TRUE` if @point1 and @point2 are equal
*
* Since: 4.14
*/
gboolean
gsk_path_point_equal (const GskPathPoint *point1,
@@ -114,6 +118,8 @@ gsk_path_point_equal (const GskPathPoint *point1,
* Returns: -1 if @point1 is before @point2,
* 1 if @point1 is after @point2,
* 0 if they are equal
*
* Since: 4.14
*/
int
gsk_path_point_compare (const GskPathPoint *point1,
+20 -5
View File
@@ -1172,10 +1172,16 @@ create_default_texture (void)
return texture;
}
static GskRenderNode *
create_default_render_node_with_bounds (const graphene_rect_t *rect)
{
return gsk_color_node_new (&GDK_RGBA("FF00CC"), rect);
}
static GskRenderNode *
create_default_render_node (void)
{
return gsk_color_node_new (&GDK_RGBA("FF00CC"), &GRAPHENE_RECT_INIT (0, 0, 50, 50));
return create_default_render_node_with_bounds (&GRAPHENE_RECT_INIT (0, 0, 50, 50));
}
static GskPath *
@@ -2254,10 +2260,14 @@ parse_fill_node (GtkCssParser *parser,
GskRenderNode *result;
parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
if (path == NULL)
path = create_default_path ();
if (child == NULL)
{
graphene_rect_t bounds;
gsk_path_get_bounds (path, &bounds);
child = create_default_render_node_with_bounds (&bounds);
}
result = gsk_fill_node_new (child, path, rule);
@@ -2311,8 +2321,6 @@ parse_stroke_node (GtkCssParser *parser,
GskRenderNode *result;
parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
if (path == NULL)
path = create_default_path ();
@@ -2327,6 +2335,13 @@ parse_stroke_node (GtkCssParser *parser,
}
gsk_stroke_set_dash_offset (stroke, dash_offset);
if (child == NULL)
{
graphene_rect_t bounds;
gsk_path_get_stroke_bounds (path, stroke, &bounds);
child = create_default_render_node_with_bounds (&bounds);
}
result = gsk_stroke_node_new (child, path, stroke);
gsk_path_unref (path);
+1 -1
View File
@@ -368,7 +368,7 @@ gsk_stroke_get_miter_limit (const GskStroke *self)
* gsk_stroke_set_dash:
* @self: a `GskStroke`
* @dash: (array length=n_dash) (transfer none) (nullable):
* the array of dashes
* the array of dashes
* @n_dash: number of elements in @dash
*
* Sets the dash pattern to use by this stroke.
+1 -1
View File
@@ -1,5 +1,5 @@
project('gtk', 'c',
version: '4.13.0',
version: '4.13.1',
default_options: [
'buildtype=debugoptimized',
'warning_level=1',
+2
View File
@@ -295,6 +295,8 @@ node_parser_tests = [
'empty-transform.ref.node',
'fill.node',
'fill.ref.node',
'fill2.node',
'fill2.ref.node',
'glshader.node',
'glshader.ref.node',
'glshader.errors',
+1 -1
View File
@@ -1,6 +1,6 @@
fill {
child: color {
bounds: 0 0 50 50;
bounds: 1.22359 0 47.5528 45.2254;
color: rgb(255,0,204);
}
path: "\
@@ -1,6 +1,6 @@
stroke {
child: color {
bounds: 0 0 50 50;
bounds: -2.77641 -4 55.5528 53.2254;
color: rgb(255,0,204);
}
path: "\
+4
View File
@@ -0,0 +1,4 @@
fill {
path: "M 0 0 O 10 10 20 20 5";
fill-rule: even-odd;
}
+9
View File
@@ -0,0 +1,9 @@
fill {
child: color {
bounds: 0 0 20 20;
color: rgb(255,0,204);
}
path: "\
M 0 0 O 10 10, 20 20, 5";
fill-rule: even-odd;
}
+10
View File
@@ -0,0 +1,10 @@
stroke {
child: color { bounds: 0 0 100 100; color: red; }
path: "M 10, 10 L 90, 90 M 90, 10 L 10, 90";
line-width: 2.5;
line-cap: butt;
line-join: miter;
miter-limit: 3.1;
dash: 0 1 4.5 10;
dash-offset: 2.1;
}
+17
View File
@@ -0,0 +1,17 @@
stroke {
child: color {
bounds: 0 0 100 100;
color: rgb(255,0,0);
}
path: "\
M 10 10\
L 90 90\
M 90 10\
L 10 90";
line-width: 2.5;
line-cap: butt;
line-join: miter;
miter-limit: 3.1;
dash: 0 1 4.5 10;
dash-offset: 2.1;
}
+15 -14
View File
@@ -25,17 +25,18 @@
#include <glib/gi18n-lib.h>
static gboolean
foreach_cb (const graphene_point_t *start,
const graphene_point_t *end,
const GskPathControl *control,
foreach_cb (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer user_data)
{
GskPathBuilder *builder = user_data;
switch (control->op)
switch (op)
{
case GSK_PATH_MOVE:
gsk_path_builder_move_to (builder, end->x, end->y);
gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
break;
case GSK_PATH_CLOSE:
@@ -43,24 +44,24 @@ foreach_cb (const graphene_point_t *start,
break;
case GSK_PATH_LINE:
gsk_path_builder_line_to (builder, end->x, end->y);
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
break;
case GSK_PATH_QUAD:
gsk_path_builder_quad_to (builder, control->quad.control.x, control->quad.control.y,
end->x, end->y);
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, control->cubic.control1.x, control->cubic.control1.y,
control->cubic.control2.x, control->cubic.control2.y,
end->x, end->y);
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;
case GSK_PATH_CONIC:
gsk_path_builder_conic_to (builder, control->conic.control.x, control->conic.control.y,
end->x, end->y,
control->conic.weight);
gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y,
pts[2].x, pts[2].y,
weight);
break;
default:
+5 -4
View File
@@ -35,16 +35,17 @@ typedef struct
} Statistics;
static gboolean
stats_cb (const graphene_point_t *start,
const graphene_point_t *end,
const GskPathControl *control,
stats_cb (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer user_data)
{
Statistics *stats = user_data;
stats->ops++;
switch (control->op)
switch (op)
{
case GSK_PATH_MOVE:
stats->contours++;