Commit Graph

55 Commits

Author SHA1 Message Date
Simon McVittie
214f5a6f98 gskpathop: Introduce a type to represent an aligned graphene_point_t
When we allocate a graphene_point_t on the stack, there's no guarantee
that it will be aligned at an 8-byte boundary, which is an assumption
made by gsk_pathop_encode() (which wants to use the lowest 3 bits to
encode the operation). In the places where it matters, force the
points on the stack and embedded in structs to be nicely aligned.

By using a distinct type for this (a union with a suitable size and
alignment), we ensure that the compiler will warn or error whenever we
can't prove that a particular point is, in fact, suitably aligned.
We can go from a `GskAlignedPoint *` to a `graphene_point_t *`
(which is always valid, because the `GskAlignedPoint` is aligned)
via &aligned_points[0].pt, but we cannot go back the other way
(which is not always valid, because the `graphene_point_t` is not
necessarily aligned nicely) without a cast.

In practice, it seems that a graphene_point_t on x86_64 *is* usually
placed at an 8-byte boundary, but this is not the case on 32-bit
architectures or on s390x.

In many cases we can avoid needing an explicit reference to the more
complicated type by making use of a transparent union. There's already
at least one transparent union in GSK's public API, so it's presumably
portable enough to match GTK's requirements.

Increasing the alignment of GskAlignedPoint also requires adjusting how
a GskStandardContour is allocated and initialized. This data structure
allocates extra memory to hold an array of GskAlignedPoint outside the
bounds of the struct itself, and that array now needs to be aligned
suitably. Previously the array started with at next byte after the
flexible array of gskpathop, but the alignment of a gskpathop is only
4 bytes on 32-bit architectures, so depending on the number of gskpathop
in the trailing flexible array, that pointer might be an unsuitable
location to allocate a GskAlignedPoint.

Resolves: https://gitlab.gnome.org/GNOME/gtk/-/issues/6395
Signed-off-by: Simon McVittie <smcv@debian.org>
2024-07-28 17:31:41 +01:00
Matthias Clasen
ce030b1b36 gsk: Fix a minor type mismatch
Use the same types in the declaration of gsk_standard_contour_init.

Fixes: #6628
2024-04-13 22:28:48 -04:00
Benjamin Otte
06f85ee566 contour: Fix stroke bounds for rect contour
There's no tests for stroke bounds, oh no!
2024-01-09 23:27:55 +01:00
Benjamin Otte
ed8bca1548 path: Make gsk_path_to_string() work in non-US locales 2023-12-28 07:35:46 +01:00
Matthias Clasen
25acc26531 contour: Simplify add_segment for circles
We no longer need to translate path points.
2023-09-21 11:40:25 -04:00
Matthias Clasen
d849a53b98 contour: Fix get_closest_point for circles 2023-09-20 22:11:47 -04:00
Matthias Clasen
9c159cf129 path: Tweak printing a bit more
We are dealing with floats here, so using
g_ascii_dtostr isn't really the best.

Update affected tests.
2023-09-17 22:35:33 -04:00
Matthias Clasen
957d494090 contour: Make circles and rounded rects match
Make sure that we print the weights in the
same way (as floats).

Update affected tests.
2023-09-17 20:32:32 -04:00
Matthias Clasen
4d71ff6da1 contour: Fixes for circles
Make circle contours use 'foreach coordinates' for
its points. This works here, but not for general
conics. As with the other custom contours, avoid
emitting collapsed conics.
2023-09-16 08:27:18 -04:00
Matthias Clasen
6d001f79f9 contour: Fixes for rounded rects
Similar to the fixes for rect contours:
Handle all the special cases where empty curves
are omitted, and omit 'empty' curves in foreach.
2023-09-15 16:31:09 -04:00
Matthias Clasen
abebd92b19 contour: Fixes for rect contours
Handle all the special cases (zero width and/or height),
and omit 'empty' curves in foreach.
2023-09-15 16:31:09 -04:00
Matthias Clasen
de724b2a57 contour: Fix some corner cases
Adding segments of rects or rounded rects was
not working right in cases where some of the
curves are trivial. Fix that.
2023-09-15 16:31:09 -04:00
Matthias Clasen
061637f4eb contour: Small refactoring
Move some utilities out.
2023-09-15 16:31:09 -04:00
Matthias Clasen
dab1897d4e contour: Circle cosmetics 2023-09-15 16:31:09 -04:00
Matthias Clasen
ea7fd1ff5a contour: Fixup for 1-point contours
If we return a path point for a 1-point contour,
make it { n, 0, 1 }.
2023-09-04 00:55:21 +02:00
Matthias Clasen
9bd9b6f2ca contour: Make sure stroke bounds are sufficient 2023-09-03 23:04:47 +02:00
Matthias Clasen
11b219bc61 Drop tolerance from gsk_contour_foreach
There is no decomposition going on for any contours,
and the tolerance argument is entirely unused.
Decomposition and tolerance is handled entirely
in gskpath.c by its trampoline.
2023-08-28 20:52:22 -04:00
Matthias Clasen
2e24a9ece4 Make GskPathPoint public
The contents are still /*< private >*/, but we
let our tests and the debugger see them, which
helps.
2023-08-28 00:07:50 -04:00
Matthias Clasen
2a17320314 Limit rect variation in path builder
Make gsk_path_builder_add_rect always
produce a clockwise rectangle. This matches
what we do for circles and rounded rects,
which also go clockwise. Note that we
still need to allow negative widths in
the contour code, to implement reverse().
2023-08-28 00:07:50 -04:00
Matthias Clasen
0dbff14555 Allow circles with radius of zero
Not very useful, but we allow rects with
width and height of zero, so lets be consistent.
Curvature is infinite for such contours.

Tests included.
2023-08-28 00:07:50 -04:00
Matthias Clasen
6f3be310f4 contour: Simplify gsk_circle_contour_foreach
Use the same approach as the rounded rect contour.
2023-08-27 21:31:40 -04:00
Matthias Clasen
2ca9982b91 rect contour: Avoid nans in corner cases
The length of rect contours can be zero,
so we much check before we divide.
2023-08-27 19:17:02 -04:00
Matthias Clasen
02a9652af4 Use a more compact representation for circles
Print circles as M-o-o-o-o-z.
2023-08-27 14:32:21 -04:00
Matthias Clasen
0a28a5d53a Add a rectangle contour
Add a contour that optimizes some things for
rectangles. Also add rectangle detection to the
path parser, and add tests similar to what we
have for the other special contours.
2023-08-27 12:36:56 -04:00
Matthias Clasen
b5dd9dae0d rounded rect contour: Fix an oversight
The close operation takes 2 points, so our array
was one too short. Oops.
2023-08-27 10:09:32 -04:00
Matthias Clasen
ebcb518e4f Cosmetics 2023-08-27 09:50:16 -04:00
Matthias Clasen
b7ea22f168 Drop unused code
Nobody is calling gsk_contour_get_start_end, so drop
this internal API.
2023-08-27 09:39:59 -04:00
Matthias Clasen
cee043f977 Add a rounded rect contour
This special contour takes advantage of its
rounded-rect-ness for speeding up bounding
boxes and winding numbers. It falls back
to the standard contour code for everything
else.
2023-08-27 09:29:19 -04:00
Matthias Clasen
ba3a657c48 contour: Add some debug API
Add a private  way to get the class of a contour,
so we can test that roundtrips through gsk_path_parse
work as expected.
2023-08-27 09:13:32 -04:00
Matthias Clasen
5f2f116c28 circle contour: Fix a typo 2023-08-27 07:43:55 -04:00
Matthias Clasen
167b38dfa1 contour: Some reactoring
Make a default print implementation, and use it.
2023-08-26 23:42:52 -04:00
Matthias Clasen
0fce24674a path: Add a circle contour
This special contour takes advantage of the
circle definition to speed up things like
hit testing and closest point determination.
2023-08-26 23:42:52 -04:00
Matthias Clasen
99ad585252 Merge branch 'measure-speedups' into 'main'
contour: Stop doing the roundtrip test

See merge request GNOME/gtk!6342
2023-08-27 01:13:41 +00:00
Matthias Clasen
6defdb4e8a Drop unused code
we are not using any gsk_spline functions currently.
2023-08-26 11:29:09 -04:00
Matthias Clasen
c989a06718 pathmeasure: compute samples on demand
Only do the work for a curve the first time
we need it. This should greatly speed up
use cases where you only create a measure
to get the length of the path.
2023-08-26 10:23:02 -04:00
Matthias Clasen
57918813e2 contour: Stop doing the roundtrip test
Doing inverse arclength computations is
a very high overhead operation. And the
tests still pass without it.
2023-08-26 09:39:49 -04:00
Matthias Clasen
553499522c contour: Add measure API
In order to compute path lengths efficiently, we need
to cache lookup tables. This commit adds API to let
contours allocate and free such measure data, as well
as API to use the data to go length -> point and
vice versa.
2023-08-25 20:16:49 -04:00
Matthias Clasen
25e6231a88 path: Switch back to conics
Arcs were appealing, but they have a fatal flaw: we can't
split our arcs without changing the ellipse they trace.
That could be fixed by adding an extra parameter, but then
it is no longer any better than conics.

So switch back to conics, which have the advantage that they
are used elsewhere.
2023-08-25 07:33:16 -04:00
Matthias Clasen
e1faf28310 Make curvature api more flexible
Add an extra direction argument to get_curvature to
allow picking the limit on either side, for sharp turns.

Update all callers.
2023-08-24 14:32:33 -04:00
Matthias Clasen
d33ed4f9ab path: Add elliptical arcs
Add a new curve type for elliptical arcs
and use it for rounded rectangles and circles.
We use the 'E' command to represent elliptical
arcs in serialized paths.
2023-08-23 12:43:52 -04:00
Matthias Clasen
486674927a Make sure stroke bounds are big enough
Our standard 'empty path' in gtk4-node-editor
was getting its pointy corners cut off.
2023-08-21 23:59:08 -04:00
Matthias Clasen
0c39890e0f contour: Optimize bounds
Cache the bounds in the contour, and compute
the stroke bounds based on it as well.
2023-08-18 10:02:14 -04:00
Matthias Clasen
73853f1a6b contour: Add an assertion 2023-08-16 16:18:38 -04:00
Matthias Clasen
125ea90894 Rename an internal function
We want the number of ops, not the number of points.
2023-08-16 15:54:46 -04:00
Matthias Clasen
45aa8e4e00 Fix GskStandardContour to have a 'good' size
We need the size of GskStandardContour to be
at least as aligned as graphene_point_t, or
things break in hard to debug ways.
2023-08-14 15:59:45 -04:00
Matthias Clasen
a85ab3585e Revise gsk_path_point_get_tangent
Update the directions enum to allow all four
tangents to be obtained. Add an illustration
to the docs for clarity.

Update all callers.
2023-08-14 14:58:22 -04:00
Matthias Clasen
4b7e1b1233 Fix gsk_path_builder_add_segment
We were splitting the last segment, but did not
actually use the result of the split. Oops.
2023-08-13 09:40:19 -04:00
Matthias Clasen
b7544636d4 contour: Skip the move
When jumping between segments, we always
need to skip index 0, since thats the move.

This fixes the tangent checks in the
rectangle tests.
2023-08-09 15:12:58 -04:00
Matthias Clasen
6220baf230 get_closest_point: Prefer earlier points
Only switch to a later point if it is strictly
closer than the existing match. This fixes
start- vs endpoint confusion in the rectangle
tests.
2023-08-09 15:12:52 -04:00
Matthias Clasen
f707185248 Add gsk_path_builder_add_segment
With GskPathPoint, we can subset paths without
a measure object.
2023-08-09 07:01:01 -04:00