Merge branch 'path-convenience' into 'main'

pathpoint: Add gsk_path_get_rotation

See merge request GNOME/gtk!6284
This commit is contained in:
Matthias Clasen
2023-08-14 19:20:40 +00:00
11 changed files with 477 additions and 9 deletions

View File

@@ -36,6 +36,8 @@ content_images = [
"gtk-logo.svg",
"images/caps-dark.png",
"images/caps-light.png",
"images/directions-dark.png",
"images/directions-light.png",
"images/join-dark.png",
"images/join-light.png",
"images/path-dark.png",

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@@ -0,0 +1,327 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg1"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
sodipodi:docname="directions.svg"
inkscape:export-filename="directions-light.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="0.75989759"
inkscape:cx="353.33709"
inkscape:cy="400.71189"
inkscape:window-width="1920"
inkscape:window-height="1123"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1">
<marker
style="overflow:visible"
id="marker5"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Triangle arrow"
markerWidth="0.5"
markerHeight="0.5"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path5" />
</marker>
<marker
style="overflow:visible"
id="marker3"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Triangle arrow"
markerWidth="2"
markerHeight="2"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path3" />
</marker>
<marker
style="overflow:visible"
id="Triangle"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Triangle arrow"
markerWidth="2"
markerHeight="2"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path135" />
</marker>
<marker
style="overflow:visible"
id="marker3-8"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Triangle arrow"
markerWidth="2"
markerHeight="2"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path3-5" />
</marker>
<marker
style="overflow:visible"
id="Triangle-0"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Triangle arrow"
markerWidth="2"
markerHeight="2"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path135-9" />
</marker>
<marker
style="overflow:visible"
id="marker5-9"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Triangle arrow"
markerWidth="0.5"
markerHeight="0.5"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path5-8" />
</marker>
<marker
style="overflow:visible"
id="marker3-8-4"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Triangle arrow"
markerWidth="2"
markerHeight="2"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path3-5-4" />
</marker>
<marker
style="overflow:visible"
id="Triangle-0-7"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Triangle arrow"
markerWidth="2"
markerHeight="2"
viewBox="0 0 1 1"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path135-9-6" />
</marker>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;marker-end:url(#marker5)"
d="m 27.834229,78.180655 c 21.653076,9.584156 38.648414,3.28592 57.704513,-16.91815 26.702288,3.84691 38.178308,6.290079 51.837088,35.267113"
id="path1"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;marker-end:url(#marker5-9)"
d="m 91.839025,194.73224 c -22.098283,1.18425 -24.17615,-37.34309 2.699778,-37.47998 20.898567,-0.10644 38.726427,9.19795 51.837087,35.26711"
id="path1-8"
sodipodi:nodetypes="csc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;marker-start:url(#marker3);marker-end:url(#Triangle)"
d="M 52.087008,92.522138 119.92974,29.398044"
id="path2"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;marker-start:url(#marker3-8);marker-end:url(#Triangle-0)"
d="M 39.037646,52.780803 130.44855,67.99044"
id="path2-3"
sodipodi:nodetypes="cc"
inkscape:transform-center-x="-71.02355"
inkscape:transform-center-y="28.680447" />
<path
style="fill:none;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;marker-start:url(#marker3-8-4);marker-end:url(#Triangle-0-7)"
d="m 48.764932,157.5522 92.665618,-0.60775"
id="path2-3-1"
sodipodi:nodetypes="cc"
inkscape:transform-center-x="-74.875204"
inkscape:transform-center-y="16.143612" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
x="85.620346"
y="24.737305"
id="text4"><tspan
sodipodi:role="line"
id="tspan4"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke-width:0.2"
x="85.620346"
y="24.737305">GSK_PATH_FROM_START</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
x="125.74581"
y="152.63206"
id="text4-5"><tspan
sodipodi:role="line"
id="tspan4-7"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke-width:0.2"
x="125.74581"
y="152.63206">GSK_PATH_FROM_START</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
x="15.551258"
y="100.65614"
id="text5"><tspan
sodipodi:role="line"
id="tspan5"
style="stroke-width:0.2"
x="15.551258"
y="100.65614">GSK_PATH_TO_START</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
x="2.9303639"
y="165.83383"
id="text5-8"><tspan
sodipodi:role="line"
id="tspan5-8"
style="stroke-width:0.2"
x="2.9303639"
y="165.83383">GSK_PATH_TO_START</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
x="135.70834"
y="69.753548"
id="text6"><tspan
sodipodi:role="line"
id="tspan6"
style="stroke-width:0.2"
x="135.70834"
y="69.753548">GSK_PATH_TO_END</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
x="142.40665"
y="165.91626"
id="text6-6"><tspan
sodipodi:role="line"
id="tspan6-2"
style="stroke-width:0.2"
x="142.40665"
y="165.91626">GSK_PATH_TO_END</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
x="2.3828762"
y="48.245087"
id="text7"><tspan
sodipodi:role="line"
id="tspan7"
style="stroke-width:0.2"
x="2.3828762"
y="48.245087">GSK_PATH_FROM_END</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
x="2.4781337"
y="153.32378"
id="text7-5"><tspan
sodipodi:role="line"
id="tspan7-9"
style="stroke-width:0.2"
x="2.4781337"
y="153.32378">GSK_PATH_FROM_END</tspan></text>
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path2-8-9-7"
cx="85.343727"
cy="61.691891"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path2-8-9-7-0"
cx="93.787331"
cy="157.1212"
r="1.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -509,7 +509,8 @@ gsk_standard_contour_get_tangent (const GskContour *contour,
idx = point->idx;
t = point->t;
if (t == 0 && direction == GSK_PATH_START)
if (t == 0 && (direction == GSK_PATH_FROM_START ||
direction == GSK_PATH_TO_START))
{
/* Look at the previous segment */
if (idx > 1)
@@ -523,7 +524,8 @@ gsk_standard_contour_get_tangent (const GskContour *contour,
t = 1;
}
}
else if (t == 1 && direction == GSK_PATH_END)
else if (t == 1 && (direction == GSK_PATH_TO_END ||
direction == GSK_PATH_FROM_END))
{
/* Look at the next segment */
if (idx < self->n_ops - 1)
@@ -540,6 +542,9 @@ gsk_standard_contour_get_tangent (const GskContour *contour,
gsk_curve_init (&curve, self->ops[idx]);
gsk_curve_get_tangent (&curve, t, tangent);
if (direction == GSK_PATH_TO_START || direction == GSK_PATH_FROM_END)
graphene_vec2_negate (tangent, tangent);
}
static float

View File

@@ -292,17 +292,30 @@ typedef enum {
/**
* GskPathDirection:
* @GSK_PATH_START: The side that leads to the start of the path
* @GSK_PATH_END: The side that leads to the end of the path
* @GSK_PATH_FROM_START: The tangent in path direction of the incoming side
* of the path
* @GSK_PATH_TO_START: The tangent against path direction of the incoming side
* of the path
* @GSK_PATH_TO_END: The tangent in path direction of the outgoing side
* of the path
* @GSK_PATH_FROM_END: The tangent against path direction of the outgoing
* side of the path
*
* The values of the `GskPathDirection` enum are used to pick one
* of the two sides of the path that at a given point on the path.
* of the four tangents at a given point on the path.
*
* <picture>
* <source srcset="directions-dark.png" media="(prefers-color-scheme: dark)">
* <img alt="Path Tangents" src="directions-light.png">
* </picture>
*
* Since: 4.14
*/
typedef enum {
GSK_PATH_START,
GSK_PATH_END
GSK_PATH_FROM_START,
GSK_PATH_TO_START,
GSK_PATH_TO_END,
GSK_PATH_FROM_END,
} GskPathDirection;
/**

View File

@@ -19,12 +19,16 @@
#include "config.h"
#include <math.h>
#include "gskpathpointprivate.h"
#include "gskcontourprivate.h"
#include "gdk/gdkprivate.h"
#define RAD_TO_DEG(x) ((x) / (G_PI / 180.f))
/**
* GskPathPoint:
*
@@ -181,6 +185,10 @@ gsk_path_point_get_position (const GskPathPoint *point,
* point, and the direction coming out of it. The @direction
* argument lets you choose which one to get.
*
* If you want to orient something in the direction of the
* path, [method@Gsk.PathPoint.get_rotation] may be more
* convenient to use.
*
* Since: 4.14
*/
void
@@ -201,6 +209,40 @@ gsk_path_point_get_tangent (const GskPathPoint *point,
gsk_contour_get_tangent (contour, self, direction, tangent);
}
/**
* gsk_path_point_get_rotation:
* @point: a `GskPathPoint`
* @path: the path that @point is on
* @direction: the direction for which to return the rotation
*
* Gets the direction of the tangent at a given point.
*
* This is a convenience variant of [method@Gsk.PathPoint.get_tangent]
* that returns the angle between the tangent and the X axis. The angle
* can e.g. be used in [method@Gtk.Snapshot.rotate].
*
* Returns: the angle between the tangent and the X axis, in degrees
*
* Since: 4.14
*/
float
gsk_path_point_get_rotation (const GskPathPoint *point,
GskPath *path,
GskPathDirection direction)
{
GskRealPathPoint *self = (GskRealPathPoint *) point;
graphene_vec2_t tangent;
g_return_val_if_fail (self != NULL, 0);
g_return_val_if_fail (path != NULL, 0);
g_return_val_if_fail (self->contour < gsk_path_get_n_contours (path), 0);
gsk_path_point_get_tangent (point, path, direction, &tangent);
return RAD_TO_DEG (atan2f (graphene_vec2_get_y (&tangent),
graphene_vec2_get_x (&tangent)));
}
/**
* gsk_path_point_get_curvature:
* @point: a `GskPathPoint`

View File

@@ -67,6 +67,11 @@ void gsk_path_point_get_tangent (const GskPathPoint *poin
GskPathDirection direction,
graphene_vec2_t *tangent);
GDK_AVAILABLE_IN_4_14
float gsk_path_point_get_rotation (const GskPathPoint *point,
GskPath *path,
GskPathDirection direction);
GDK_AVAILABLE_IN_4_14
float gsk_path_point_get_curvature (const GskPathPoint *point,
GskPath *path,

View File

@@ -1151,6 +1151,9 @@ gtk_snapshot_clear_fill (GtkSnapshotState *state)
*
* The image is recorded until the next call to [method@Gtk.Snapshot.pop].
*
* If you want to fill the path with a color, [method@Gtk.Snapshot.append_fill]
* may be more convenient.
*
* Since: 4.14
*/
void
@@ -1171,6 +1174,35 @@ gtk_snapshot_push_fill (GtkSnapshot *snapshot,
state->data.fill.fill_rule = fill_rule;
}
/**
* gtk_snapshot_append_fill:
* @snapshot: a `GtkSnapshot`
* @path: The path describing the area to fill
* @fill_rule: The fill rule to use
* @color: the color to fill the path with
*
* A convenience method to fill a path with a color.
*
* See [method@Gtk.Snapshot.push_fill] if you need
* to fill a path with more complex content than
* a color.
*
* Since: 4.14
*/
void
gtk_snapshot_append_fill (GtkSnapshot *snapshot,
GskPath *path,
GskFillRule fill_rule,
const GdkRGBA *color)
{
graphene_rect_t bounds;
gsk_path_get_bounds (path, &bounds);
gtk_snapshot_push_fill (snapshot, path, fill_rule);
gtk_snapshot_append_color (snapshot, color, &bounds);
gtk_snapshot_pop (snapshot);
}
static GskRenderNode *
gtk_snapshot_collect_stroke (GtkSnapshot *snapshot,
GtkSnapshotState *state,
@@ -1222,6 +1254,9 @@ gtk_snapshot_clear_stroke (GtkSnapshotState *state)
* everything else, so uneven scaling will cause horizontal and vertical
* strokes to have different widths.
*
* If you want to stroke the path with a color, [method@Gtk.Snapshot.append_stroke]
* may be more convenient.
*
* Since: 4.14
*/
void
@@ -1265,6 +1300,35 @@ gtk_snapshot_collect_shadow (GtkSnapshot *snapshot,
return shadow_node;
}
/**
* gtk_snapshot_append_stroke:
* @snapshot: a `GtkSnapshot`
* @path: The path describing the area to fill
* @stroke: The stroke attributes
* @color: the color to fill the path with
*
* A convenience method to stroke a path with a color.
*
* See [method@Gtk.Snapshot.push_stroke] if you need
* to stroke a path with more complex content than
* a color.
*
* Since: 4.14
*/
void
gtk_snapshot_append_stroke (GtkSnapshot *snapshot,
GskPath *path,
const GskStroke *stroke,
const GdkRGBA *color)
{
graphene_rect_t bounds;
gsk_path_get_stroke_bounds (path, stroke, &bounds);
gtk_snapshot_push_stroke (snapshot, path, stroke);
gtk_snapshot_append_color (snapshot, color, &bounds);
gtk_snapshot_pop (snapshot);
}
static void
gtk_snapshot_clear_shadow (GtkSnapshotState *state)
{

View File

@@ -240,6 +240,16 @@ void gtk_snapshot_append_layout (GtkSnapshot
PangoLayout *layout,
const GdkRGBA *color);
GDK_AVAILABLE_IN_4_14
void gtk_snapshot_append_fill (GtkSnapshot *snapshot,
GskPath *path,
GskFillRule fill_rule,
const GdkRGBA *color);
GDK_AVAILABLE_IN_4_14
void gtk_snapshot_append_stroke (GtkSnapshot *snapshot,
GskPath *path,
const GskStroke *stroke,
const GdkRGBA *color);
G_END_DECLS

View File

@@ -466,8 +466,8 @@ test_path_point (void)
g_assert_true (rp->t == 1);
gsk_path_point_get_position (&point, path, &pos);
gsk_path_point_get_tangent (&point, path, GSK_PATH_START, &t1);
gsk_path_point_get_tangent (&point, path, GSK_PATH_END, &t2);
gsk_path_point_get_tangent (&point, path, GSK_PATH_TO_START, &t1);
gsk_path_point_get_tangent (&point, path, GSK_PATH_TO_END, &t2);
curvature = gsk_path_point_get_curvature (&point, path, &center);
g_assert_true (graphene_point_equal (&pos, &GRAPHENE_POINT_INIT (100, 100)));