Compare commits

...

369 Commits

Author SHA1 Message Date
Matthias Clasen
027461b209 path-tool: Add a dash command
This is the obvious wrapper around gsk_path_dash.
2023-08-29 00:42:30 -04:00
Matthias Clasen
ff17fd0e82 gsk: Add tests for gsk_path_dash 2023-08-29 00:42:30 -04:00
Matthias Clasen
dea4d52d1a Add gsk_path_dash
This is a function like gsk_path_foreach, but
it provides a dashed version of the path instead
of the original.
2023-08-29 00:42:30 -04:00
Matthias Clasen
f7e248c7fe curve: Add a vfunc for get_at_length
We can do this precisely for lines, so lets do it.
2023-08-28 23:28:08 -04:00
Matthias Clasen
37db270d19 Merge branch 'contour-foreach' into 'main'
Drop tolerance from gsk_contour_foreach

See merge request GNOME/gtk!6361
2023-08-29 01:58:39 +00:00
Matthias Clasen
f3312f677b measure: Cosmetics 2023-08-28 21:14:28 -04:00
Matthias Clasen
05547d98d6 path: Cosmetics
Reorganize this source file into sections.
2023-08-28 21:13:58 -04: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
5721c3cb8f demos: Drop an unused variable 2023-08-28 20:50:38 -04:00
Fran Dieguez
f90ca697af Update Galician translation 2023-08-28 22:36:51 +00:00
Matthias Clasen
e81aa18c82 Merge branch 'closest-point-distance' into 'main'
Change gsk_path_get_closest_point to return distance

See merge request GNOME/gtk!6357
2023-08-28 15:53:51 +00:00
Matthias Clasen
827bbc0cc1 Change gsk_path_get_closest_point to return distance
We already compute it, so lets return it.
Bindings seems fine with this change - they
already return (success, point) as a tuple
anyway.
2023-08-28 11:22:30 -04:00
Matthias Clasen
7095a67910 Merge branch 'matthiasc/for-main' into 'main'
path-tool: Add a reverse command

See merge request GNOME/gtk!6356
2023-08-28 04:38:42 +00:00
Matthias Clasen
dcbca3f0d7 path-tool: Add a reverse command
It does what it says.
2023-08-28 00:27:29 -04:00
Matthias Clasen
702d7c238a Merge branch 'matthiasc/for-main' into 'main'
contour: Simplify gsk_circle_contour_foreach

See merge request GNOME/gtk!6355
2023-08-28 04:18:48 +00:00
Matthias Clasen
5a3ed65ad8 Improve precondition checks for path points
Add a helper function for checking that a
path point is valid for a path, and use it.
2023-08-28 00:07:50 -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
c5d89d00f1 Merge branch 'zbrown/tooltips' into 'main'
tooltip: don't cross native boundaries

Closes #1234, #5998, gnome-calendar#1038, and nautilus#3063

See merge request GNOME/gtk!6346
2023-08-28 03:25:44 +00: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
0ea6b70d55 Merge branch 'matthiasc/for-main' into 'main'
gtk-demo: Add a few path benchmarks

See merge request GNOME/gtk!6353
2023-08-27 23:45:59 +00: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
a40282b2fb Add gsk_path_point_print
Another private debug API.
2023-08-27 19:06:39 -04:00
Matthias Clasen
ad9fb1e101 Improve quad and conic decomposition
If the control point is equal to either
start or end, just emit a line. This improves
the rendering of rounded rectangles with such
corners.
2023-08-27 16:57:03 -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
6f823d2d0d gtk-demo: Add a few path benchmarks
The Tiger and Graph examples in the fishbowl test
path handling.
2023-08-27 12:59:10 -04:00
Matthias Clasen
a5c9cd5657 Merge branch 'rectangle-contour' into 'main'
Add a rectangle contour

See merge request GNOME/gtk!6351
2023-08-27 16:46:12 +00:00
Matthias Clasen
21ab5b6fa3 Merge branch 'matthiasc/for-main' into 'main'
Add a test for rectangle segments

See merge request GNOME/gtk!6352
2023-08-27 16:45:58 +00:00
Benjamin Otte
2582fd45e4 demos: Add cute maze demo 2023-08-27 12:45:25 -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
ddd4855bbc Add a test for rectangle segments 2023-08-27 12:36:30 -04:00
Matthias Clasen
204216e3d5 Merge branch 'matthiasc/for-main' into 'main'
Drop unused code

See merge request GNOME/gtk!6350
2023-08-27 16:19:16 +00:00
Matthias Clasen
1e6a124665 Correct the docs of gsk_path_builder_add_rect
The path does *not* always go clockwise!
2023-08-27 12:18:36 -04:00
Matthias Clasen
78c5aff956 Test special contours harder
Check that the start- and endpoint work
as expected and verify that their winding
numbers match the ones of the standard contour,
and are negated when the contour is reversed.
2023-08-27 11:47:40 -04:00
Matthias Clasen
8d1844135b path: Add a comment 2023-08-27 10:10:08 -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
f0b3381660 Merge branch 'rounded-rect-contour' into 'main'
path: Add a rounded rect contour

See merge request GNOME/gtk!6347
2023-08-27 13:36:53 +00:00
Matthias Clasen
0796c72049 Add roundtrip tests for rounded rect contours
These should survive roundtrips through the
path parser as well now.
2023-08-27 09:31:17 -04:00
Matthias Clasen
822e988efe path: Recognize rounded rects when parsing
We can look out for M-L-O-L-O-L-O-L-O-Z patterns
with matching numbers.
2023-08-27 09:31:17 -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
b420540b15 Merge branch 'matthiasc/for-main' into 'main'
Simplify the path spinner demo

See merge request GNOME/gtk!6349
2023-08-27 13:27:50 +00:00
Matthias Clasen
031c0ec3e5 pathpoint: Add some debug API
Add a private gsk_path_point_to_string that
can be called in the debugger if you want
to see the contents of a GskPathPoint and
are too lazy to cast it to GskRealPathPoint
yourself.
2023-08-27 09:14:47 -04:00
Matthias Clasen
43b6822eb0 Add roundtrip tests for special contours
So far, we only have a circle contour.
Check that it survives a roundtrip through
gsk_path_to_string and gsk_path_parse.
2023-08-27 09:14:03 -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
1db75e521d Simplify the path spinner demo
The transforms were obscuring a simple
calculation here.
2023-08-27 07:43:55 -04:00
Matthias Clasen
2297a353b8 Merge branch 'circle-contour' into 'main'
path: Add a circle contour

See merge request GNOME/gtk!6345
2023-08-27 11:12:51 +00:00
Matthias Clasen
80903e5f44 Merge branch 'bilelmoussaoui/gi' into 'main'
gi: Add missing since annotation

See merge request GNOME/gtk!6348
2023-08-27 11:05:31 +00:00
Bilal Elmoussaoui
7342ce5bca gi: Add missing since annotation 2023-08-27 08:17:00 +00: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
ead88c36ec path: Add circle tests 2023-08-26 23:42:52 -04:00
Matthias Clasen
b8a3d7fa00 path: Recognize circles when parsing
We can look out for the tell-tale
M-O-O-O-O-Z and turn it into a circle
contour.
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
Zander Brown
739084e9bc tooltip: don't cross native boundaries
When walking the tree looking for tooltips we shouldn't cross from, say,
a popover to it's parent window

Fix: https://gitlab.gnome.org/GNOME/gtk/-/issues/1234
Fix: https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/1038
Fix: https://gitlab.gnome.org/GNOME/gtk/-/issues/5998
Fix: https://gitlab.gnome.org/GNOME/nautilus/-/issues/3063
See: https://gitlab.gnome.org/GNOME/console/-/issues/318
2023-08-27 02:36:51 +01: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
949b6692ac Merge branch 'matthiasc/for-main' into 'main'
Drop unused code

See merge request GNOME/gtk!6344
2023-08-26 16:46:49 +00:00
Piotr Drąg
eb0479d8ed Update POTFILES.in and POTFILES.skip 2023-08-26 17:52:22 +02: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
9fdad6d4ee Make randomized path tests less precise
Bump the epsilon in test_split to make these
tests survive longer. They still fail eventually,
unfortunately.
2023-08-26 11:23:02 -04:00
Matthias Clasen
b6e285844f Make curve tests pass 2023-08-26 11:22:58 -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
1c8bd8658d curve: Cosmetics 2023-08-26 10:23:02 -04:00
Matthias Clasen
ab50cba4e9 curve: Reduce the order of our approximation
Use 24 samples instead of 32.
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
a4df8d8818 Merge branch 'path-node-tests' into 'main'
css: Replace border rendering code with GskPath

See merge request GNOME/gtk!6341
2023-08-26 12:13:04 +00:00
Matthias Clasen
4b00cfc1ce Merge branch 'macos_ci' into 'main'
Disable macOS CI for forks

See merge request GNOME/gtk!6337
2023-08-26 11:43:57 +00:00
Matthias Clasen
889688c978 Add more fill and stroke node tests 2023-08-26 07:39:23 -04:00
Matthias Clasen
0bf1ae033d Document node format for stroke and fill nodes 2023-08-26 07:39:23 -04:00
Jordi Mas
994afcaeed Update Catalan translation 2023-08-26 09:50:31 +02:00
Matthias Clasen
b69cc832ef Merge branch 'path-tool-restrict' into 'main'
path-tool: Add a restrict command

See merge request GNOME/gtk!6340
2023-08-26 04:24:06 +00:00
Matthias Clasen
ca188b41ae post-release version bump 2023-08-25 22:29:09 -04:00
Matthias Clasen
81c8d1dd28 path-tool: Add length to info output
This requires GskPathMeasure.
2023-08-25 22:26:54 -04:00
Matthias Clasen
32d00ca9ed path-tool: Add a restrict command
This lets you subset a path between two given lengths.
2023-08-25 22:26:54 -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
Matthias Clasen
581ad5fc04 Make curve tests more robust
Add a few fudge factors that let these
tests survive extended runs.
2023-08-25 20:23:08 -04:00
Matthias Clasen
ff40dcffec Make the measure tests waste less time
No need to produce multiple contours, when
the test is just about splitting a single
curve.
2023-08-25 20:23:08 -04:00
Matthias Clasen
eb2fa4195a Make the measure tests run in ci
Marking them as slow has the unintended
side-effect of keeping them from running.
2023-08-25 20:23:08 -04:00
Benjamin Otte
e2d2b57f0e demos: Add a text-on-path demo 2023-08-25 20:23:08 -04:00
Matthias Clasen
6c1a128ea3 Make the map demo more interesting
Add marching arrows to it.

With this, it can also serve as a performance
test for rendering medium complexity paths.
2023-08-25 20:23:08 -04:00
Matthias Clasen
cfaa31eeb8 Expand docs for GskPathMeasure 2023-08-25 20:23:08 -04:00
Matthias Clasen
2097b15f9c Add randomized measure tests
Test that lengths behave as expected when
we split paths, do roundtrips through points,
and subset paths.
2023-08-25 20:16:49 -04:00
Matthias Clasen
46a8f57735 Add tests for path length 2023-08-25 20:16:49 -04:00
Matthias Clasen
2e5639a077 Add a circle test 2023-08-25 20:16:49 -04:00
Matthias Clasen
007cfeac94 Add GskPathMeasure
GskPathMeasure is the public API for path lengths.
2023-08-25 20:16: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
René de Hesselle
2782daadb4 ci: Do not create macOS jobs for forks
The runner is not available in forks (on purpose / for security
reasons), so jobs created there will be stuck indefinitely until they
timeout and fail the pipeline, which is undesireable.

That also means that the initial goal to enable macOS jobs for all MRs
is out of reach: if you are an external contributor (read: non-project
member), your MR pipelines run in your fork, therefore have no access
to the runner.
2023-08-26 01:56:59 +02: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
Matthias Clasen
787b1a661e curve: Add tests for length
Add some tests for gsk_curve_get_length.
2023-08-25 16:13:36 -04:00
Matthias Clasen
04e6fc3f74 curve: Add length computation
Add api to go t<>length.

The code here is inspired by
https://pomax.github.io/bezierinfo/#arclength
2023-08-25 16:13:36 -04:00
Benjamin Otte
54d2f0063a Merge branch 'replay' into 'main'
Node replay tests

See merge request GNOME/gtk!6299
2023-08-25 19:45:34 +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
Matthias Clasen
d586a5c67c Merge branch 'fix-gears-demo' into 'main'
demo: Fix a bug without GL

Closes #6059

See merge request GNOME/gtk!6333
2023-08-25 14:34:13 +00:00
Matthias Clasen
c97dc6e903 Merge branch 'conics-revisited' into 'main'
path: Switch back to conics

See merge request GNOME/gtk!6332
2023-08-25 14:26:33 +00:00
Matthias Clasen
eec90d1026 pathbuilder: Add rel-variants for arc-to
Add rel-variants for all our arc-to APIs. This is
a pretty harmless addition, and it is more consistent
to have these for all ..._to functions.
2023-08-25 09:45:45 -04:00
Matthias Clasen
f4fb4d04e5 Some pathbuilder doc clarifications
Mention the end point of the html arc-to call.
2023-08-25 09:37:07 -04:00
Matthias Clasen
3283157352 Bring arc_to back as convenience API
It is our main use of conics, so make it an API,
and use it internally.
2023-08-25 09:31:19 -04:00
Sergey Bugaev
d07a6b8566 snapshot, gsktransform: Mention that rotation happens around (0, 0)
...and not around the center of the render node, as one could expect
given that the render node syntax for rotation, transform: rotate(90);,
happens to match the CSS syntax for the same thing, and CSS does rotate
around the center by default.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2023-08-25 15:54:05 +03:00
Sergey Bugaev
4e8e59cd58 snapshot: Fix push_repeat () with empty child bounds
The logic would confuse empty child bounds (in which case nothing should
get rendered) with NULL child bounds (in which case the child node's own
bounds should get used). In fact, if the child bounds are empty, we can
discard the descendant render nodes completely, getting a nice little
optimization.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2023-08-25 15:54:05 +03:00
Sergey Bugaev
9f811ccee5 testsuite: Add color-matrix-merge testcase
This tests the merging of nested color matrix nodes feature of
GtkSnapshot, which was broken before commit 082fdfdb24.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2023-08-25 15:54:05 +03:00
Sergey Bugaev
6cd6da050b testsuite: Add render node replay tests
This takes a render node tree and "replays" it by using the GtkSnapshot
machinery. We don't necesserily expect to get back an exactly equal
render node tree back, since GtkSnapshot applies various small
optimizations where possible, but the original and the replayed nodes
should render to identical textures.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2023-08-25 15:54:05 +03:00
Matthias Clasen
a906dbea35 demo: Fix a bug without GL
The gears widget was just not unrealizing properly
when GL is not available. Fix that.

Fixes: #6059
2023-08-25 08:37:22 -04:00
Matthias Clasen
5bc82f4141 Change curve derivative api
We don't need to have the derivative as a curve,
it is enough for us to compute values of the
derivative at a given t, which we can also do
for conics.
2023-08-25 07:33:16 -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
650e4b1920 Merge branch 'matthiasc/for-main' into 'main'
path docs: Clarify curvature

See merge request GNOME/gtk!6331
2023-08-24 19:55:36 +00:00
Matthias Clasen
5dc0cbc20f Expand the path docs a bit 2023-08-24 15:00:14 -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
854c695153 pathpoint docs: Fix a link
Links gsk->gtk must be done manually, since we
don't have a dependency.
2023-08-24 13:41:39 -04:00
Matthias Clasen
ebd4ceca15 path docs: Clarify curvature
The curvature of lines is zero, not infinite.
2023-08-24 11:15:51 -04:00
Matthias Clasen
d873643407 path docs: Add another illustration 2023-08-24 11:09:28 -04:00
Matthias Clasen
8a789d0234 path docs: Cosmetics 2023-08-24 10:54:23 -04:00
Emmanuele Bassi
286b4cbc72 Merge branch 'macos_ci' into 'main'
interim solution for macOS CI

See merge request GNOME/gtk!6274
2023-08-24 14:10:03 +00:00
René de Hesselle
b4428029af Change workflow to enable MR pipelines
This makes it possible to have macOS CI run for everything inside the
main repository and for merge requests.
2023-08-24 15:30:03 +02:00
René de Hesselle
9aeb5be8ad gdk: Use subpixel_layout on macOS 2023-08-24 15:30:03 +02:00
René de Hesselle
007dd55a71 Re-enable macOS CI on new self-hosted runner 2023-08-24 15:30:03 +02:00
Matthias Clasen
7a05e40ce7 Merge branch 'matthiasc/for-main' into 'main'
Add some more arc tests

See merge request GNOME/gtk!6330
2023-08-24 12:20:13 +00:00
Matthias Clasen
8d0654db6b Add some more arc tests 2023-08-24 07:40:05 -04:00
Matthias Clasen
63d5615fe7 Merge branch 'dboles/issue6001-ShortcutsWindow-programmatic' into 'main'
Add API to programmatically build ShortcutsWindow

Closes #6001

See merge request GNOME/gtk!6249
2023-08-24 10:40:34 +00:00
Matthias Clasen
37d18816be menubutton: Don't assume the root is a window
The only thing this assumption does is cause
criticals, so remove it.

Fixes: #6055
2023-08-24 06:30:55 -04:00
Matthias Clasen
f1de7a524c Merge branch 'matthiasc/for-main' into 'main'
demo cosmetics

See merge request GNOME/gtk!6329
2023-08-24 10:17:44 +00:00
Fran Dieguez
644692a2e0 Update Galician translation 2023-08-24 06:19:48 +00:00
Matthias Clasen
da2e8b78c2 Merge branch 'matthiasc/for-main' into 'main'
demo cosmetics

See merge request GNOME/gtk!6329
2023-08-24 03:47:00 +00:00
Matthias Clasen
0b5a6ecbff demos: Cosmetics 2023-08-23 23:20:17 -04:00
Matthias Clasen
9a6aac0459 path spinner demo: Don't crash 2023-08-23 23:18:59 -04: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
Matthias Clasen
d3f9b3e28a Merge branch 'matthiasc/for-main' into 'main'
arc: Fix the derivative

See merge request GNOME/gtk!6328
2023-08-24 02:45:58 +00:00
Matthias Clasen
4229a37e90 arc: Fix the derivative
Scale the derivative such that computing the arc length
of a unit quarter circle wil produce the expected result
of PI/2.
2023-08-23 22:18:52 -04:00
Matthias Clasen
12297fd88a arc curve: Simplify derivative 2023-08-23 22:11:22 -04:00
Matthias Clasen
7943610066 curve: Fix arc decomposition 2023-08-23 22:11:15 -04:00
Matthias Clasen
e19246d2db tests: Include arcs in curve tests 2023-08-23 22:10:51 -04:00
Matthias Clasen
e70117bd9f Merge branch 'mcatanzaro/#6056' into 'main'
notebook: fix critical when switching page

Closes #6056

See merge request GNOME/gtk!6327
2023-08-24 01:09:19 +00:00
Michael Catanzaro
20c4e24b74 notebook: fix critical when switching page
It's expected that gtk_widget_get_root() will return NULL if the widget
tree does not contain a root widget. I don't know what that means or why
it happens, but it's true in gnome-control-center's network panel when
displaying the OpenVPN configuration dialog. We need to handle it.

Fixes #6056
2023-08-23 15:51:08 -05:00
Matthias Clasen
3c5efbc77e Merge branch 'wip/matthiasc/arcs' into 'main'
path: Add arcs

See merge request GNOME/gtk!6313
2023-08-23 19:17:01 +00:00
Matthias Clasen
f6c2b6bb88 Make foreach work efficiently with arcs 2023-08-23 14:51:31 -04:00
Matthias Clasen
4ab03e79b7 Drop some unnecessary code
We tell path_foreach to split into lines or cubics,
so no point in having code to handle quads and arcs.
2023-08-23 14:33:25 -04:00
Matthias Clasen
7a12abdea3 Incorporate review feedback 2023-08-23 14:16:43 -04:00
Matthias Clasen
36ca1f10dc Add an arc demo
Make a circular spinner to see how well arcs
do for circles.
2023-08-23 13:45:12 -04:00
Matthias Clasen
07a92c1690 Merge branch 'matthiasc/for-main' into 'main'
docs: Fix gsk->gtk links

See merge request GNOME/gtk!6324
2023-08-23 16:45:26 +00:00
Matthias Clasen
0f7b9e686c Add a rounded rect test
This checks that our path-in-fill computations
agree with rounded_rect_contains_point. Sadly,
they don't do that, 100%.
2023-08-23 12:43:52 -04:00
Matthias Clasen
71584107b0 Add gsk_path_builder_html_arc_to
This one draws circular arcs with a given radius.
2023-08-23 12:43:52 -04:00
Matthias Clasen
88c0ace644 Make gsk_path_builder_svg_arc_to public
This is useful to port SVG paths using this syntax.
2023-08-23 12:43:52 -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
a63af177a4 docs: Fix gsk->gtk links
gi-docgen can't handle these, since we don't have
a dependency.
2023-08-23 11:38:13 -04:00
Piotr Drąg
43c8e136b5 Update Polish translation 2023-08-23 16:43:05 +02:00
Matthias Clasen
efd597c6ed Merge branch 'default-get-current-image' into 'main'
Implement gdk_paintable_default_get_current_image ()

See merge request GNOME/gtk!6303
2023-08-23 10:53:12 +00:00
Fran Dieguez
024a753a6a Update Galician translation 2023-08-23 07:24:01 +00:00
Danial Behzadi
e1dd3fb801 Update Persian translation 2023-08-23 00:18:33 +00:00
Ekaterine Papava
82011569ce Update Georgian translation 2023-08-22 21:14:18 +00:00
Sabri Ünal
747c9c4f94 Update Turkish translation 2023-08-22 20:18:57 +00:00
Matthias Clasen
7d7a090875 Merge branch 'wip/smcv/i387' into 'main'
tests: Accept slightly different numeric results

Closes #6051

See merge request GNOME/gtk!6320
2023-08-22 17:34:10 +00:00
Simon McVittie
0f125aad90 tests: Accept slightly different numeric results
FLT_EPSILON is the distance between 1.0 and the next distinct floating
point number, and doesn't necessarily have anything to do with the
precision we can expect from a series of floating-point calculations.
Experimentally, 1e-6 is achievable, even on platforms with unusual
floating point implementations like i387.

Resolves: https://gitlab.gnome.org/GNOME/gtk/-/issues/6051
Bug-Debian: https://bugs.debian.org/1050076
Signed-off-by: Simon McVittie <smcv@debian.org>
2023-08-22 17:24:17 +01:00
Matthias Clasen
a7d5796750 Merge branch 'path-tool-tweak' into 'main'
path-tool: Reorganize options

See merge request GNOME/gtk!6323
2023-08-22 16:19:19 +00:00
Matthias Clasen
79e132ab7b path-tool: Reorganize options
Put fill and stroke options into their own group.
This helps produce understandable --help output.
2023-08-22 09:56:43 -04:00
Danial Behzadi
85957b5d3e Update Persian translation 2023-08-22 13:39:46 +00:00
Matthias Clasen
373972b8ca Merge branch 'fix-wayland-crash' into 'main'
wayland: Don't assume the shell protocol

Closes #6048

See merge request GNOME/gtk!6322
2023-08-22 13:13:51 +00:00
Matthias Clasen
30e6d70b14 Merge branch 'matthiasc/for-main' into 'main'
docs: Tweaks

See merge request GNOME/gtk!6321
2023-08-22 13:07:42 +00:00
Matthias Clasen
c78b34649b wayland: Don't assume the shell protocol
The gtk_shell proxy will be NULL if the compositor
is not gnome-shell. Handle that without crashing.

Fixes: #6048
2023-08-22 08:27:23 -04:00
Matthias Clasen
b3fe68ca95 docs: Tweaks 2023-08-22 07:56:27 -04:00
Daniel Mustieles
417888f847 Updated Spanish translation 2023-08-22 13:25:53 +02:00
Benjamin Otte
de8fdd822c Merge branch 'wip/otte/for-main' into 'main'
widget: Remove unused headers from gtkwidget.h

See merge request GNOME/gtk!6319
2023-08-22 07:38:57 +00:00
Matthias Clasen
ee8e6ac546 Merge branch 'matthiasc/for-main' into 'main'
Make sure stroke bounds are big enough

See merge request GNOME/gtk!6318
2023-08-22 05:36:16 +00: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
acf9612ed8 docs: Start a section on paths 2023-08-21 23:59:08 -04:00
Matthias Clasen
8c664b669c Merge branch 'matthiasc/for-main' into 'main'
docs: Drop a nonexisting enum value

See merge request GNOME/gtk!6317
2023-08-22 03:47:30 +00:00
Matthias Clasen
b367bf83b4 docs: Tweaks 2023-08-21 22:40:22 -04:00
Matthias Clasen
b84f60877d docs: Drop a nonexisting enum value 2023-08-21 21:52:53 -04:00
Matthias Clasen
8a84024a54 Merge branch 'bilelmoussaoui/gi' into 'main'
gi: Fix missing namespace

See merge request GNOME/gtk!6316
2023-08-22 00:47:05 +00:00
Bilal Elmoussaoui
56cb614f79 gi: Fix missing namespace 2023-08-21 21:11:12 +00:00
Matthias Clasen
957d8845fd Merge branch 'kabus/x11-clipboard-leak' into 'main'
gdk/x11/clipboard: Fix Slist leak

See merge request GNOME/gtk!6314
2023-08-21 20:39:29 +00:00
Georges Basile Stavracas Neto
231c0ad77f Merge branch 'gbsneto/windows-ci-linker' into 'main'
ci: Limit parallel linking on Windows CI

See merge request GNOME/gtk!6315
2023-08-21 18:53:53 +00:00
Matthias Clasen
da635d6392 Merge branch '5777_texthistory_restore_modified_flag_on_redo' into 'main'
gtktexthistory: restore 'modified' flag on redo

Closes #5777

See merge request GNOME/gtk!6302
2023-08-21 18:41:28 +00:00
Matthias Clasen
b8a103b993 Merge branch 'matthiasc/for-main' into 'main'
curve: Add a get_crossing vfunc

See merge request GNOME/gtk!6312
2023-08-21 18:35:01 +00:00
Georges Basile Stavracas Neto
162759f34b ci: Limit parallel linking on Windows CI
Linking on Windows can easily run out of memory, and limiting it
to a single link operation (i.e. disabling parallelization) should
be enough to avoid this problem.
2023-08-21 15:29:51 -03:00
Khalid Abu Shawarib
79fa785dbc gdk/x11/clipboard: Fix Slist leak 2023-08-21 20:32:42 +03:00
Anders Jonsson
2a03e50030 Update Swedish translation 2023-08-21 15:55:55 +00:00
Matthias Clasen
fb0f5b5c14 curve: Add a get_crossing vfunc 2023-08-21 11:29:14 -04:00
Matthias Clasen
cd7726bb31 Merge branch 'matthiasc/for-main' into 'main'
docs: Add more illustrations

See merge request GNOME/gtk!6311
2023-08-21 05:49:23 +00:00
Matthias Clasen
2b4e577b53 docs: Add more illustrations
Add illustrations to the various curve_to methods
of GskPathBuilder.
2023-08-20 22:28:06 -07:00
Matthias Clasen
1ed695931f Merge branch 'matthiasc/for-main' into 'main'
path: Don't accept 'O' as path command

See merge request GNOME/gtk!6305
2023-08-21 04:15:27 +00:00
Matthias Clasen
51a44ddd1d Merge branch 'bilelmoussaoui/gi-docgen-links' into 'main'
docs: Stop using C symbols as links

See merge request GNOME/gtk!6310
2023-08-21 04:14:57 +00:00
Benjamin Otte
29cdac18e8 rendernodeparser: Handle dashing in strokes
That part of the original MR got lost while refactoring.

Put it back.
2023-08-21 05:23:44 +02:00
Benjamin Otte
418f6b35af gsk: Add gsk_rect_to_float()
... and use it.
2023-08-21 05:23:42 +02:00
Benjamin Otte
96a6e05f0b build: Add -Woverride-init
That's a gcc warning (clang has the equivalent -Winitializer-overrides,
but that one is included in -Wall) that complains about things like:

  VkOffset3D offset = { .x = pt.x, .x = pt.y, .y = 0 };

So you don't have to spend a few hours trying to understand what's going
on before realizing your copy/paste skills are substandard.
2023-08-21 05:20:31 +02:00
Benjamin Otte
d665d2fb89 vulkan: Add nonuniformEXT() where needed
The magical term to know about (because the GLSL compiler or the
validation layers sure as hell don't) is:

  "dynamically uniform expression"

because if you don't have that when indexing a texture or buffer array,
you need to add nonuniformEXT() around the index variable.

Fixes the close icon on AMD having glitches of the previous icon visible
in some pixels.
2023-08-21 05:19:44 +02:00
Benjamin Otte
8862666b5a build: GSK doesn't depend on gdk-pixbuf 2023-08-21 05:19:37 +02:00
Benjamin Otte
3adf02445f build: Don't use configure_file() when custom_target() works
These two files don't need to be built when configuring, they are only
needed during build.
2023-08-21 05:19:37 +02:00
Benjamin Otte
bfdd325d36 widget: Remove unused headers from gtkwidget.h
... and put them back in places where they are needed.
2023-08-21 05:19:37 +02:00
Jürgen Benvenuti
ac76cadf32 Update German translation
(cherry picked from commit f237c85c8f)
2023-08-20 17:47:37 +00:00
Bilal Elmoussaoui
5516ff6a02 docs: Stop using C symbols as links
They are much harder for the bindings to figure out the type back from it and usually just break
2023-08-20 10:59:49 +02:00
Baurzhan Muftakhidinov
f2578fcfb9 Update Kazakh translation 2023-08-19 18:04:04 +00:00
Piotr Drąg
4da80520b8 Update Polish translation 2023-08-19 17:18:25 +02:00
Matthias Clasen
b12a27083d path: Drop special contour parsing
This is not used currently, since we don't
have custom contours.
2023-08-18 18:06:44 -04:00
Matthias Clasen
07ec266a00 curve: Add a get_derivative vfunc 2023-08-18 13:46:42 -04:00
Sabri Ünal
965b3025d9 Update Turkish translation 2023-08-18 17:35:14 +00:00
Matthias Clasen
88e74ca21e path: Don't accept 'O' as path command
We don't have conics atm.
2023-08-18 13:19:48 -04:00
Matthias Clasen
148da12cfc Cosmetics 2023-08-18 13:19:33 -04:00
Matthias Clasen
3ded6ada0c Merge branch 'matthiasc/for-main' into 'main'
contour: Optimize bounds

See merge request GNOME/gtk!6304
2023-08-18 14:35:09 +00: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
Sergey Bugaev
e45cba13ed paintable: Implement gdk_paintable_default_get_current_image ()
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2023-08-18 11:10:22 +03:00
G.Willems
b4977decc1 gtktexthistory: restore 'modified' flag on redo
When redoing a history entry, its `is_modified` flag is not
reflected to the history state tracker. So GtkTextBuffers may
expose a modified=FALSE status, despite a change was actually
applied to the buffer.

For the undo case, an `is_modified_set` flag was set on the last
entry of the undo queue when a change of the modified state of
the history is requested. This commit does the same on the first
entry of the redo queue.

Closes #5777
2023-08-17 22:26:00 +02:00
Jiri Grönroos
2da9d5862f Update Finnish translation 2023-08-17 17:51:26 +00:00
Matthias Clasen
b948e03e8a Merge branch 'dboles/popover-menu-flags-property' into 'main'
PopoverMenu: Make :flags a property for use in UI…

Closes #6030

See merge request GNOME/gtk!6298
2023-08-17 10:26:16 +00:00
Daniel Boles
2c90cadef4 PopoverMenu: Make :flags a property for use in UI…
…files, or other cases other than calling new_from_model_full(), which
generally makes it far easier to experiment with the effect of flags,
including by changing the value of the property in the Inspector.

fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/6030#note_1818229
2023-08-17 10:52:35 +01:00
Matthias Clasen
08c064d79a Merge branch 'matthiasc/for-main' into 'main'
Rename an internal function

See merge request GNOME/gtk!6301
2023-08-16 20:40:12 +00:00
Matthias Clasen
73853f1a6b contour: Add an assertion 2023-08-16 16:18:38 -04:00
Matthias Clasen
8634d67cff Some fixes for gsk_path_builder_add_segment
We must be careful with single-point contours
that contain just a move. These never occur in
practice, but our randomized tests produce them
regularly.
2023-08-16 16:15:26 -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
ffba5a3f42 Merge branch 'matthiasc/for-main' into 'main'
build: Drop some unused variables

See merge request GNOME/gtk!6297
2023-08-16 19:28:12 +00:00
Matthias Clasen
60df21213b Merge branch 'dboles/popover-css-nodes' into 'main'
Popover: Fix & add to CSS nodes documentation

See merge request GNOME/gtk!6300
2023-08-16 19:16:12 +00:00
Sabri Ünal
14ba577acb Update Turkish translation 2023-08-16 18:31:30 +00:00
Benjamin Otte
7d5ef1117e Merge branch 'color-matrix' into 'main'
Color matrix node fixes & clarifications

See merge request GNOME/gtk!6290
2023-08-16 17:07:35 +00:00
Daniel Boles
af0e2bff94 Popover: Fix & add to CSS nodes documentation
* The `.background` class gets put on `popover`, not `content`
* Use backticks to style node and class names with monospace
* Link to GtkPopoverMenu
* Add to PopoverMenu a bit outlining how items and sections look in CSS.
2023-08-16 17:11:45 +01:00
Matthias Clasen
7d65f81d7f Merge branch 'path-world-resource' into 'main'
Fix MSVC build (turn world map path into a resource)

See merge request GNOME/gtk!6296
2023-08-16 13:51:32 +00:00
Matthias Clasen
b08ecfcf9e build: Drop some unused variables
We are not using gtk_private_packages at all,
so drop it.
2023-08-16 09:43:34 -04:00
Matthias Clasen
e2cd362f24 Merge branch 'fg_color_docs' into 'main'
gsk: Update docs for gtk_snapshot_append_layout

See merge request GNOME/gtk!6295
2023-08-16 12:52:43 +00:00
Yuri Chornoivan
1a1b6fe66b Update Ukrainian translation 2023-08-16 11:37:47 +00:00
Sergey Bugaev
122176a3a1 gtk-demo: Turn world map path into a resource
The C string literal way way too long for MSVC.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2023-08-16 14:35:35 +03:00
Matthias Clasen
5beccc8208 Merge branch 'fix-pc-files' into 'main'
meson: Add wayland-client to gtk4-wayland requires

See merge request GNOME/gtk!6293
2023-08-16 11:29:39 +00:00
Matthias Clasen
6715a3267a Merge branch 'remove-out-caller-allocates-from-pod-types' into 'main'
introspection: Remove 'caller-allocates' from POD types

See merge request GNOME/gtk!6294
2023-08-16 11:29:25 +00:00
Alexandros Theodotou
313078b77c gsk: Update docs for gtk_snapshot_append_layout
Mention how to get the current theme's foreground color.
2023-08-16 20:09:15 +09:00
Sergey Bugaev
246a7cfeab rendernode, snapshot: Slightly expand color matrix docs
Based on reverse engineering the color node and contrary to my
expectations, the matrix/offset is expressed in, and applied to,
unpremultiplied colors. The colors are being explicitly
unpremultiplied, transformed according to the matrix/offset, and
premultiplied back (see color_matrix.glsl). The matrix is getting
transposed.

Also, copy the same blurb to the corresponding GtkSnapshot function.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2023-08-16 13:55:04 +03:00
Sergey Bugaev
082fdfdb24 snapshot: Fix merging color matrix nodes
The code was appliying the matrices in the wrong order: we have to apply
the inner node's matrix first, and the outer one second. Due to the
matrices being implicitly transposed, the matrix multiplication was done
in the right order, yet the wrong matrix was being mutliplied by the
wrong offset vector.

To make the code a little easier to follow, create explicit variables
for the resulting matrix and offset (instead of reusing matrix2 and
offset2), and fix & expand the comment to document how matrix
transposition factors into this.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2023-08-16 13:54:54 +03:00
Philip Chimento
823cb714ec introspection: Remove 'caller-allocates' from POD types
The (out caller-allocates) and (out callee-allocates) annotations are
meant for structured or pointer types. Plain old data types are just
regular out parameters and don't need the annotation about who allocates
them.

See glib!2005, gjs#570
2023-08-15 22:30:27 -07:00
Ekaterine Papava
cc93347fe6 Update Georgian translation 2023-08-16 03:36:32 +00:00
Xavier Claessens
d6a07cd617 meson: Add x11_dep to gtk4-x11 requires 2023-08-15 21:17:39 -04:00
Fran Dieguez
858bd9f84c Update Galician translation 2023-08-15 23:40:15 +00:00
Matthias Clasen
be7e5c866f Merge branch 'matthiasc/for-main' into 'main'
gsk: Add more details to the docs

See merge request GNOME/gtk!6292
2023-08-15 19:27:59 +00:00
Matthias Clasen
93a90bafc3 Add some statistics to the map demo 2023-08-15 13:55:46 -04:00
Xavier Claessens
090e01b383 meson: Add wayland-client to gtk4-wayland requires 2023-08-15 13:35:46 -04:00
Matthias Clasen
03a511aab4 path-tool: Make info show statistics
It is somewhat interesting to know how many
contours, lines, etc. a path consists of.
2023-08-15 13:33:23 -04:00
Matthias Clasen
5cf9a09c07 gsk: Add more details to the docs 2023-08-15 12:38:24 -04:00
Matthias Clasen
9558c70683 Merge branch 'dboles/signal-factory-typos' into 'main'
SignalListItemFactory: small doc grammar+sense fix

See merge request GNOME/gtk!6291
2023-08-15 14:36:35 +00:00
Daniel Boles
57d98a12fa SignalListItemFactory: small doc grammar+sense fix
* "to to" => "to"
* "a object" => "an object"
* "its new prop is about to be unset" => "its prop is about to be unset"
2023-08-15 10:47:30 +01:00
Danial Behzadi
3dd40049a9 Update Persian translation 2023-08-14 22:35:12 +00:00
Matthias Clasen
225e626ada Merge branch 'matthiasc/for-main' into 'main'
Fix GskStandardContour to have a 'good' size

See merge request GNOME/gtk!6289
2023-08-14 20:28:46 +00:00
Matthias Clasen
081f504ae4 Tweak the directions illustration
Still not 100% happy with it, but it is better.
2023-08-14 16:09:27 -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
87430be658 Fix up a testcase
I had gotten the path direction enum mixed up here.
2023-08-14 15:59:45 -04:00
Matthias Clasen
012c16ccd6 Merge branch 'matthiasc/for-main' into 'main'
gtk-demo: Clean up path walk demo

See merge request GNOME/gtk!6288
2023-08-14 19:20:57 +00:00
Matthias Clasen
de0cef5d4d Merge branch 'path-convenience' into 'main'
pathpoint: Add gsk_path_get_rotation

See merge request GNOME/gtk!6284
2023-08-14 19:20:40 +00:00
Matthias Clasen
e807a84967 gtk-demo: Clean up path walk demo 2023-08-14 15:19:42 -04:00
Matthias Clasen
b5e105d4f4 snapshot: Add more path api
Add convenience methods to fill or stroke
a path with a color.
2023-08-14 14:58:22 -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
a1d40c5236 Add gsk_path_point_get_rotation
This returns the tangent in the form of an angle.
2023-08-14 14:58:22 -04:00
Matthias Clasen
95ea6b2615 Merge branch 'path-point-api-revision2' into 'main'
pathpoint: Revise argument order

See merge request GNOME/gtk!6287
2023-08-14 18:53:23 +00:00
Ekaterine Papava
82d8bc9403 Update Georgian translation 2023-08-14 18:34:10 +00:00
Matthias Clasen
536d432444 Merge branch 'path-map-demo' into 'main'
demos: Add a map demo

See merge request GNOME/gtk!6285
2023-08-14 17:49:26 +00:00
Yuri Chornoivan
3b8c26a116 Update Ukrainian translation 2023-08-14 17:30:53 +00:00
Matthias Clasen
6ace4b60d8 pathpoint: Revise argument order
In order for introspection and documentation to
not be confused, we need to have the GskPathPoint
be the first argument.

Update all callers.
2023-08-14 13:20:34 -04:00
Matthias Clasen
7601b89561 Merge branch 'fix-4986' into 'main'
Fix native filechooser on macOS

Closes #4986

See merge request GNOME/gtk!6272
2023-08-14 16:26:15 +00:00
Matthias Clasen
0cdd2e7008 Merge branch 'color-dialog-button-activate' into 'main'
Make new-style dialog buttons activatable

See merge request GNOME/gtk!6255
2023-08-14 16:26:13 +00:00
Piotr Drąg
595152bdba Update POTFILES.in 2023-08-14 15:16:29 +02:00
Benjamin Otte
90f0733673 demos: Add a map demo
For now, this just shows a world map.

Once we have measures, we can make this
a little more interesting.
2023-08-14 08:41:16 -04:00
Matthias Clasen
625e83e1de Merge branch 'wip/alice/menu-button' into 'main'
menubutton: Fix focus on the internal gizmo

Closes #6025

See merge request GNOME/gtk!6283
2023-08-14 11:19:21 +00:00
Matthias Clasen
daac04be82 Merge branch 'bilelmoussaoui/gi' into 'main'
gi: Add missing since annotation

See merge request GNOME/gtk!6282
2023-08-14 11:15:28 +00:00
Matthias Clasen
8ec9bba892 Merge branch 'dboles/inspector-object-tree-flash' into 'main'
inspector/object-tree: Fix ! flash @ select widget

Closes #6022

See merge request GNOME/gtk!6279
2023-08-14 11:14:49 +00:00
Alice Mikhaylenko
b63e365fd2 menubutton: Fix focus on the internal gizmo
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/6025
2023-08-14 14:24:06 +04:00
Daniel Boles
859a25b0e7 Inspector: Fix ! flash on select widget @ obj tree
Widgets are flashed by the window when it receives Tree::object-selected
- but we were emitting said signal from select_object(), i.e. if we were
made to select by an external caller. We should also emit it if the user
interactively selects an item, so the window receives+flashes the widget

fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/6022
2023-08-14 10:48:26 +01:00
Bilal Elmoussaoui
f5d47a4658 gi: Add missing since annotation 2023-08-14 08:41:12 +00:00
Matthias Clasen
fa6645f157 Merge branch 'fix-add-segment' into 'main'
Fix gsk_path_builder_add_segment

See merge request GNOME/gtk!6280
2023-08-14 01:01:37 +00:00
Joshua Lee
69b6067c5e fontdialogbutton: Make activatable 2023-08-14 01:26:23 +01:00
Joshua Lee
e645f59748 colordialogbutton: Make activatable 2023-08-14 01:26:20 +01:00
Efstathios Iosifidis
2929686c1d Update Greek translation 2023-08-13 21:18:23 +00:00
Andika Triwidada
c83256e080 Update Indonesian translation 2023-08-13 13:42:39 +00: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
95a8821614 text: Track user changes better
Make all the action signal handlers call
begin/end_change(), so we can rely on
change_count being >0 to check later if
an action is user-initiated or programmatic.

Fixes: #6018
2023-08-13 09:31:42 -04:00
Benjamin Otte
73500f9ebb Merge branch 'wip/otte/for-main' into 'main'
treeviewcolumn: Set ascending class for ascending order

Closes #6002

See merge request GNOME/gtk!6277
2023-08-13 03:54:19 +00:00
Matthias Clasen
eae38756c2 Merge branch 'matthiasc/for-main' into 'main'
path-tool: Make the docs match

See merge request GNOME/gtk!6278
2023-08-12 23:51:21 +00:00
Matthias Clasen
8bf7187b89 path-tool: Make the docs match
We've removed various things from the tool,
and forgot to keep the docs up-to-date.
2023-08-12 19:29:27 -04:00
Matthias Clasen
e7fb8842b5 Merge branch 'path-for-merge-8' into 'main'
Add gtk-path-tool

See merge request GNOME/gtk!6263
2023-08-12 21:39:15 +00:00
Matthias Clasen
aaac0cb4a1 Merge branch 'bilelmoussaoui/linkify' into 'main'
docs: Drop uneeded ` in gi-docgen links

See merge request GNOME/gtk!6276
2023-08-12 21:23:13 +00:00
Benjamin Otte
67a4279d3f rendernode: Put typedef into gsktypes.h
Makes includes simpler for headers that want to use GskRenderNode.
2023-08-12 23:13:47 +02:00
Benjamin Otte
dd4b8a4c89 gl: Pass swizzle array directly
There's no need to pass pointers to arrays, as arrays are already
pointers.
2023-08-12 23:13:23 +02:00
Benjamin Otte
4cc5a54da3 viewport: Fix leak
Fixes #6002
2023-08-12 23:13:23 +02:00
Benjamin Otte
07add0144e columnview: Fix refcounting woes
The new code did not deal with the GtkScrollInfo properly.

Related: #6002
2023-08-12 23:13:23 +02:00
Benjamin Otte
d1c7376b05 gdkcontext: Make has_unpack_subimage() do the version check
Makes the code look simpler when we actually use that function.
2023-08-12 23:13:23 +02:00
Benjamin Otte
a71388d2d6 treeviewcolumn: Set ascending class for ascending order
The alternative button order confused the code and so the "ascending"
class was set for descending order by default, not when alternate order
is set.
2023-08-12 23:13:23 +02:00
Matthias Clasen
62176a3bd0 tools: Add gtk4-path-tool
This comes in handy for testing, among other things.

For now, this supports decomposing, reversing, rendering,
info and preview.
2023-08-12 16:34:19 -04:00
Bilal Elmoussaoui
8475a29836 docs: Drop uneeded ` in gi-docgen links
Causes the rust docs to fail parsing those as links
2023-08-12 22:26:25 +02:00
Matthias Clasen
44bc5a139c Add rounded rects to the tests 2023-08-12 16:09:31 -04:00
Matthias Clasen
11f48f3c5b Add gsk_path_builder_add_rounded_rect
For now, this is using gsk_path_builder_svg_arc_to
to approximate elliptical arcs.
2023-08-12 15:34:54 -04:00
Matthias Clasen
fa4ad1590d Merge branch 'matthiasc/for-main' into 'main'
path: Some documentation improvements

See merge request GNOME/gtk!6273
2023-08-11 16:42:25 +00:00
Matthias Clasen
47ddc742fc path: Some documentation improvements
Among other things, add a quick summary of
SVG path syntax, and add a few illustrations.
2023-08-11 12:09:12 -04:00
Matthias Clasen
31d994837b Merge branch 'path-tests-3' into 'main'
path builder: Fix add_cairo_path

Closes #6011

See merge request GNOME/gtk!6270
2023-08-11 12:44:00 +00:00
Matthias Clasen
83d692e2d3 path: Add tests for gsk_path_builder_add methods
Check that they all end the current contour.

Fixes: #6011
2023-08-11 07:24:19 -04:00
Qiu Wenbo
2a96dde115 macos: use NSPopUpButton for filter selection in native filechooser
On macOS 14, NSComboBox can't popup the dropdown list of filters. That
makes native filechooser on macOS completed broken. And NSComboBox is
more complex since it is a widget focused on edit capability.
NSPopUpButton is more suitable for plain selectable dropdown list.

Fixes: 4986

Signed-off-by: Qiu Wenbo <qiuwenbo@kylinos.com.cn>
2023-08-11 16:19:48 +08:00
Qiu Wenbo
f55b3c68ad filefilter: fix UTI type conversion on macOS
GContentType on macOS switched to UTI since glib 2.51. We should not assume it as MIME type anymore.

Fixes: #4986

Signed-off-by: Qiu Wenbo <qiuwenbo@kylinos.com.cn>
2023-08-11 16:19:38 +08:00
Matthias Clasen
f2835bb48b pathbuilder: Treat current point consistently
Arrange that none of the 'add' methods change
the current point.
2023-08-10 22:56:47 -04:00
Fran Dieguez
857c22db32 Update Galician translation 2023-08-11 00:35:58 +00:00
Matthias Clasen
fff1645060 path builder: Fix add_cairo_path
We were forgetting to end the current contour.
2023-08-10 16:08:32 -04:00
Matthias Clasen
4f0c3c81fb Merge branch 'matthiasc/for-main' into 'main'
Matthiasc/for main

See merge request GNOME/gtk!6269
2023-08-10 04:28:26 +00:00
Matthias Clasen
421365cfc3 Add more path point tests 2023-08-09 23:55:08 -04:00
Matthias Clasen
59c5b41f3d Cosmetics 2023-08-09 23:48:50 -04:00
Matthias Clasen
267367355f Merge branch 'path-fill-tests2' into 'main'
Add more path fill tests

See merge request GNOME/gtk!6268
2023-08-10 03:10:14 +00:00
Matthias Clasen
0aa3356499 Add more path fill tests
These also used to live with measure tests.
2023-08-09 22:47:13 -04:00
Matthias Clasen
14a3b35333 Merge branch 'path-fill-tests' into 'main'
Add path fill tests

See merge request GNOME/gtk!6267
2023-08-10 02:21:34 +00:00
Matthias Clasen
77def95659 Add path fill tests
These used to live with the measure tests, but
path_in_fill no longer involves a measure.
2023-08-09 21:50:29 -04:00
Matthias Clasen
4e91cd1155 Merge branch 'matthiasc/for-main' into 'main'
pathpoint: Use the right type

See merge request GNOME/gtk!6266
2023-08-09 20:37:14 +00:00
Matthias Clasen
2d923d362f Merge branch 'bilelmoussaoui/gi-gsk' into 'main'
gsk/gi: new Path api fixes

See merge request GNOME/gtk!6265
2023-08-09 19:40:53 +00: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
917307a6a4 pathpoint: Use the right type 2023-08-09 14:37:14 -04:00
Matthias Clasen
5f49b7b492 Merge branch 'matthiasc/for-main' into 'main'
pathpoint: Clarify docs

See merge request GNOME/gtk!6262
2023-08-09 18:36:05 +00:00
Bilal Elmoussaoui
b03abea402 gsk: Don't change the GskRenderNodeType order
As we use their values to check that a node can be downcasted to a node
type in the Rust bindings
such change would break existing code
2023-08-09 20:26:46 +02:00
Bilal Elmoussaoui
d4fcc883cb gsk/gi: Add missing since annotations & docs 2023-08-09 20:26:46 +02:00
Daniel Boles
ca2a2697d6 Merge branch 'dboles/for-main' into 'main'
docs: Add/fix some links; avoid pluralisation

See merge request GNOME/gtk!6261
2023-08-09 16:57:19 +00:00
Matthias Clasen
68c6f63e90 pathpoint: Clarify docs
Add a paragraph explaining the situation
for comparing the start- and endpoint of
a closed path.
2023-08-09 11:30:26 -04:00
Daniel Boles
0e89fed8ed docs: Add/fix some links; avoid pluralisation
Appending `s` breaks the [type@NS.Object] notation, so fix that in
ListHeader. Add links to ListItem and Overlay, and avoid appending `s`
after `backtick`s just for consistency with the [type@NS.Object] issue.
2023-08-09 15:35:12 +01:00
Benjamin Otte
4d726543d0 Merge branch 'path-for-merge-6' into 'main'
Simplify GskPathPoint

See merge request GNOME/gtk!6260
2023-08-09 14:24:33 +00:00
Matthias Clasen
2bcc998e90 Add tests for gsk_path_builder_add_segment
Test at least some of the special cases:
- start and end point on the same contour
- start and end point on the same segment
- end before start
2023-08-09 07:01:01 -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
Matthias Clasen
ded30049db path: Add gsk_path_get_start/end_point
These are useful to have, now that we are
relying more on GskPathPoint in our api.
2023-08-08 22:05:34 -04:00
Matthias Clasen
5c55e9d11e Add gsk_path_point_equal/compare
These just make sense to have.
2023-08-08 22:05:34 -04:00
Matthias Clasen
c35bb11c18 Simplify GskPathPoint
Use simple representation of just
{ contour index, segment index, t value }
2023-08-08 20:31:56 -04:00
Matthias Clasen
cc19781d27 Merge branch 'cpdb-fix' into 'main'
print: Update printerprivate header location for cpdb backend

See merge request GNOME/gtk!6259
2023-08-08 23:01:12 +00:00
Jeremy Bícha
08d08678e8 print: Update printerprivate header location for cpdb backend
This fixes the print-cpdb build option
2023-08-08 17:55:54 -04:00
Matthias Clasen
11b632a691 Merge branch 'timezone' into 'main'
test-calendar: Update timezone name

See merge request GNOME/gtk!6258
2023-08-08 19:31:31 +00:00
Jeremy Bícha
4881ef251e test-calendar: Update timezone name
Debian no longer provides the MET timezone
but instead provides geographical region and city name
2023-08-08 15:01:42 -04:00
Luca Bacci
5b39abd1a4 Merge branch 'fix-server-side-decorations' into 'main'
win32: Fix minimize and maximize buttons missing on ssd

Closes #5142

See merge request GNOME/gtk!6052
2023-08-08 15:17:09 +00:00
Daniel Mustieles
f0089097dd Update Spanish translation 2023-08-08 10:41:17 +00:00
Fran Dieguez
d603925ab2 Update Galician translation 2023-08-08 00:05:18 +00:00
Matthias Clasen
6af9dc8612 Merge branch 'xry111/issue6003' into 'main'
print: Revert "Start sorting apart includes" change for gtkprinteroptionprivate.h

Closes #6003

See merge request GNOME/gtk!6250
2023-08-07 22:52:43 +00:00
Benjamin Otte
35b313f9b0 Merge branch 'path-for-merge-3' into 'main'
gskpath: Add stroking

See merge request GNOME/gtk!6248
2023-08-07 22:17:53 +00:00
Matthias Clasen
fe84ce8686 gsk: Try to fix flipped fallback rendering
This patch is pretty much a blind guess, but
it seems to fix flipped rendering of fill
and stroke nodes.
2023-08-07 17:53:49 -04:00
Matthias Clasen
02a4e5a457 Add compare tests for fill and stroke nodes 2023-08-07 13:02:57 -04:00
Matthias Clasen
a548a91e6d Add nodeparser tests for fill and stroke nodes 2023-08-07 13:02:57 -04:00
Matthias Clasen
fc3c2e0942 gsk: Implement parsing fill and stroke nodes
Make serialization and deserialization work for stroke and
fill nodes.
2023-08-07 13:02:57 -04:00
Matthias Clasen
60e07335a1 demos: Add stroking to the path fill demo 2023-08-07 13:02:57 -04:00
Benjamin Otte
cb6b968fb5 snapshot: Add gtk_snapshot_push_stroke()
This is the obvious GtkSnapshot API to go
along with the new stroke nodes.
2023-08-07 13:02:57 -04:00
Benjamin Otte
3aa3816125 gsk: Add GskStrokeNode
Take a rendernode as source and a GskPath and GskStroke,
and fill the area that is covered when stroking the path
with the given stroke parameters, like cairo_stroke() would.
2023-08-07 13:02:57 -04:00
Matthias Clasen
c37c29422a Add gsk_path_get_stroke_bounds
This is a helper to compute the bounds for
stroke nodes. We keep it private for now.
2023-08-07 13:02:57 -04:00
Matthias Clasen
db71c07f8f Add GskStroke
A GskStroke struct collects the parameters that are
needed for stroking a path.
2023-08-07 13:02:57 -04:00
Emmanuele Bassi
bf1b97efd3 Merge branch 'gdk-macos-depth-fix' into 'main'
gdk: Fix compilation on macos

See merge request GNOME/gtk!6208
2023-08-07 14:46:47 +00:00
Xi Ruoyao
4d7277f72c print: Revert "Start sorting apart includes" change for gtkprinteroptionprivate.h
The print backends needs the functions in gtkprinteroptionprivate.h to
be exported.

Fixes #6003.
2023-08-07 22:29:10 +08:00
Matthias Clasen
3296f01edf Merge branch 'path-fixes' into 'main'
Fix path point preconditions

See merge request GNOME/gtk!6251
2023-08-07 13:00:18 +00:00
Matthias Clasen
dbcbf0523b Add tests for GskPathPoint
As always, untested code doesn't work...
2023-08-07 08:33:05 -04:00
Matthias Clasen
888abb6f24 path: Make get_closest_point work
We weren't setting point->path. Oops.
Good to have tests.
2023-08-07 08:33:05 -04:00
Matthias Clasen
9b916b329a pathpoint: Implement get_tangent fully
We were not taking the direction into account
at all.
2023-08-07 08:33:05 -04:00
Matthias Clasen
eb3ada6386 Fix path point preconditions
These were inverted and did not work. Oops.
2023-08-07 08:32:50 -04:00
Daniel Boles
eebe370e0a Add API to programmatically build ShortcutsWindow
and friends. This used to work OK via Container.add() but stopped
working in GTK4. While we have some ways left to TRY to add children
(via GtkWindow and Box), those don't work and result in broken layout
and assertion failures. Add basic API that can allow this to work again.

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/6001
2023-08-07 11:37:10 +01:00
Matthias Clasen
2a725b658b Merge branch 'path-for-merge-2' into 'main'
GskPath for merge, part 0

See merge request GNOME/gtk!6247
2023-08-07 01:31:37 +00:00
Benjamin Otte
97f605f811 demos: Add a simple demo filling a path 2023-08-06 21:01:11 -04:00
Benjamin Otte
4e7d578881 rendernode: Implement fast-path for solid fills
They happen so often that it's worth avoiding the clip + paint path
there.
2023-08-06 21:01:11 -04:00
Benjamin Otte
438d936f57 gtk: Add gtk_snapshot_push_fill()
This is the obvious GtkSnapshot API to go
along with the new fill nodes.
2023-08-06 21:01:11 -04:00
Benjamin Otte
fc4a464b47 gsk: Add GskFillNode
Take a rendernode as source and a GskPath and fill
the region inside the path with the source, just like
cairo_fill() would.
2023-08-06 21:01:11 -04:00
Matthias Clasen
785b9541f6 gsk: Add tests for GskPath 2023-08-06 21:01:11 -04:00
Matthias Clasen
a4cbabb80f gsk: Add tests for GskCurve 2023-08-06 20:48:09 -04:00
Matthias Clasen
1b5dfcba7e gsk: Add GskPath
This commit adds the basic infrastructure for paths.
The public APIs consists of GskPath, GskPathPoint and
GskPathBuilder.

GskPath is a data structure for paths that consists
of contours, which in turn might contain Bézier curves.
The Bezier data structure is inspired by Skia, with separate
arrays for points and operations. One advantage of this
arrangement is that start and end points are shared
between adjacent curves.

A GskPathPoint represents a point on a path, which can
be queried for various properties.

GskPathBuilder is an auxiliary builder object for paths.
2023-08-06 20:48:09 -04:00
Matthias Clasen
ba41edf531 gsk: Add tests for GskBoundingBox 2023-08-06 17:16:46 -04:00
Matthias Clasen
bf3892caed gsk: Add a bounding box type
graphene_rect_t is not well-suited for this purpose,
since you end up with floating-point precision problems
at the upper bound (x + width, y + height).
2023-08-06 17:16:30 -04:00
Benjamin Otte
1e6a95aa1b Merge branch 'grid-scroll-crash' into 'main'
gtkgridview: Fix crash on scroll to 0 sized tile

Closes #5945

See merge request GNOME/gtk!6228
2023-08-06 17:56:57 +00:00
tszymanski
70a9d08e21 gtkgridview: return empty area for empty tiles during scroll 2023-08-06 10:26:32 -07:00
Piotr Drąg
7511d4e281 Update Polish translation 2023-08-06 14:22:51 +02:00
Asier Sarasua Garmendia
53ea97decb Update Basque translation 2023-08-06 07:20:22 +00:00
Matthias Clasen
28190ded71 Merge branch 'matthiasc/for-main' into 'main'
Update tests

See merge request GNOME/gtk!6244
2023-08-05 19:32:56 +00:00
Matthias Clasen
8083cb0e47 Merge branch 'smaller-than' into 'main'
section-accessibility: Close tag

See merge request GNOME/gtk!6243
2023-08-05 19:21:44 +00:00
Hari Rana
544320a961 section-accessibility: Close tag 2023-08-05 12:25:23 -04:00
Florentina Musat
ee5a95ba24 Update Romanian translation 2023-08-05 15:54:45 +00:00
Jordi Mas
232260b86b Update Catalan translation 2023-08-05 17:30:28 +02:00
Matthias Clasen
857f50649c Merge branch 'microoptimize-label-wfh' into 'main'
Microoptimize GtkLabel width-for-height computation

See merge request GNOME/gtk!6219
2023-08-05 15:15:55 +00:00
tszymanski
a483fb2d96 gtkgridview: Fix crash on scroll to 0 sized tile
No longer crashes with my listview_clocks demo or in real scrolling in
my application. "GtkGridView failed to scroll to given position. Ignoring..."
warnings are printed when it would have crashed.

Sometimes the scroll jumps incorrectly when it doesn't crash, but that's
a separate bug but is probably related to whatever is causing this
crash.

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/5945, at least in
terms of the immediate crash.
2023-08-01 22:17:54 -07:00
Sergey Bugaev
d27e7e0180 label: Microoptimize width-for-height computation
We told Pango to limit width to mid pixels, and it returned a layout
size of text_width by text_height; text_width can be considerably
smaller than mid. If the layout fits, we know that it fits at
text_width, so set max to that. This lets us skip many iterations in a
typical case.
2023-07-28 18:42:17 +03:00
Jayson Reis
aa888c0b3f gdk: Remove a leftover reference to the renamed variable prefers_high_depth 2023-07-23 23:13:47 +02:00
dgsasha
5240d8cdf5 win32: Fix minimize and maximize buttons missing on ssd
Completely fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/5142
2023-06-10 23:08:21 -04:00
234 changed files with 44510 additions and 14731 deletions

View File

@@ -30,8 +30,16 @@ variables:
workflow:
rules:
- if: $CI_COMMIT_TAG
# run merge request pipelines
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# do not run branch pipelines if corresponding merge requests exist...
# (this avoids duplicate pipelines)
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
# ...but otherwise run branch pipelines
- if: $CI_COMMIT_BRANCH
# run tag pipelines
- if: $CI_COMMIT_TAG
default:
retry:
@@ -197,21 +205,30 @@ msys2-mingw64:
paths:
- "${CI_PROJECT_DIR}/_build/gtkdll.tar.gz"
macos:
# Sadly, this fails regularly, and its failure is never enlightening
allow_failure: true
macos-x86_64:
rules:
# Do not run in forks as the runner is not available there.
- if: $CI_PROJECT_NAMESPACE == "GNOME"
stage: build
tags:
- macos
- macosintel
needs: []
variables:
MESON_FORCE_BACKTRACKE: 1
TMPDIR: /Users/Shared/work/tmp
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
CCACHE_DIR: /Users/Shared/work/ccache
PIP_CACHE_DIR: /Users/Shared/build/cache
PIPENV_CACHE_DIR: $PIP_CACHE_DIR
PYTHONPYCACHEPREFIX: $PIP_CACHE_DIR
before_script:
- bash .gitlab-ci/show-info-osx.sh
- pip3 install --user meson~=1.0
- pip3 install --user ninja
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
- export MESON_FORCE_BACKTRACE=1
- python3 -m venv .venv
- ln -s /opt/cmake/CMake.app/Contents/bin/cmake .venv/bin
- ln -s /opt/ccache/ccache .venv/bin
- source .venv/bin/activate
- pip3 install meson==1.2.0
- pip3 install ninja==1.11.1
script:
- meson setup ${COMMON_MESON_FLAGS}
-Dx11-backend=false

View File

@@ -6,7 +6,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliar
:: FIXME: make warnings fatal
pip3 install --upgrade --user meson~=0.64 || goto :error
meson -Ddebug=false -Dmedia-gstreamer=disabled _build || goto :error
meson setup -Dbackend_max_links=1 -Ddebug=false -Dmedia-gstreamer=disabled _build || goto :error
ninja -C _build || goto :error
goto :EOF

77
NEWS
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
=========================================

View File

@@ -127,6 +127,7 @@
<file>fishbowl.ui</file>
<file>gtkfishbowl.c</file>
<file>gtkfishbowl.h</file>
<file>tiger.node</file>
</gresource>
<gresource prefix="/frames">
<file>frames.ui</file>
@@ -335,6 +336,11 @@
<file>paintable_symbolic.c</file>
<file>panes.c</file>
<file>password_entry.c</file>
<file>path_fill.c</file>
<file>path_maze.c</file>
<file>path_spinner.c</file>
<file>path_walk.c</file>
<file>path_text.c</file>
<file>peg_solitaire.c</file>
<file>pickers.c</file>
<file>printing.c</file>
@@ -420,6 +426,13 @@
<gresource prefix="/fontrendering">
<file>fontrendering.ui</file>
</gresource>
<gresource prefix="/path_walk">
<file>path_walk.ui</file>
<file compressed="true">path_world.txt</file>
</gresource>
<gresource prefix="/path_text">
<file>path_text.ui</file>
</gresource>
<gresource prefix="/org/gtk/Demo4">
<file>icons/16x16/actions/application-exit.png</file>
<file>icons/16x16/actions/document-new.png</file>

View File

@@ -11,6 +11,9 @@
#include "gtkgears.h"
#include "gskshaderpaintable.h"
#include "nodewidget.h"
#include "graphwidget.h"
const char *const css =
".blurred-button {"
" box-shadow: 0px 0px 5px 10px rgba(0, 0, 0, 0.5);"
@@ -208,6 +211,18 @@ create_menu_button (void)
return w;
}
static GtkWidget *
create_tiger (void)
{
return node_widget_new ("/fishbowl/tiger.node");
}
static GtkWidget *
create_graph (void)
{
return graph_widget_new ();
}
static const struct {
const char *name;
GtkWidget * (*create_func) (void);
@@ -225,6 +240,8 @@ static const struct {
{ "Switch", create_switch },
{ "Menubutton", create_menu_button },
{ "Shader", create_cogs },
{ "Tiger", create_tiger },
{ "Graph", create_graph },
};
static int selected_widget_type = -1;

View File

@@ -0,0 +1,153 @@
#include "graphwidget.h"
struct _GraphWidget
{
GtkWidget parent_instance;
GskPath *path;
GskStroke *stroke;
GdkRGBA color;
guint tick_cb;
guint64 start_time;
double period;
double amplitude;
};
struct _GraphWidgetClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (GraphWidget, graph_widget, GTK_TYPE_WIDGET)
static void
update_path (GraphWidget *self,
float amplitude)
{
graphene_point_t p[20];
GskPathBuilder *builder;
g_clear_pointer (&self->path, gsk_path_unref);
for (int i = 0; i < 20; i++)
{
p[i].x = 10 * i;
p[i].y = 50;
if (i % 4 == 1 || i % 4 == 2)
{
if (i % 8 < 4)
p[i].y += amplitude;
else
p[i].y -= amplitude;
}
}
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder, p[0].x, p[0].y);
for (int i = 0; i < 20; i += 4)
gsk_path_builder_cubic_to (builder,
p[i+1].x, p[i+1].y,
p[i+2].x, p[i+2].y,
p[i+3].x, p[i+3].y);
self->path = gsk_path_builder_free_to_path (builder);
}
static gboolean
tick_cb (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
GraphWidget *self = GRAPH_WIDGET (widget);
guint64 now;
double angle;
now = gdk_frame_clock_get_frame_time (frame_clock);
if (self->start_time == 0)
self->start_time = now;
angle = 360 * (now - self->start_time) / (double)(self->period * G_TIME_SPAN_MINUTE);
update_path (self, sin (angle) * self->amplitude);
gtk_widget_queue_draw (widget);
return G_SOURCE_CONTINUE;
}
static void
graph_widget_init (GraphWidget *self)
{
self->color.red = g_random_double_range (0, 1);
self->color.green = g_random_double_range (0, 1);
self->color.blue = g_random_double_range (0, 1);
self->color.alpha = 1;
self->period = g_random_double_range (0.5, 1);
self->amplitude = g_random_double_range (10, 25);
self->stroke = gsk_stroke_new (2);
update_path (self, 0);
self->start_time = 0;
self->tick_cb = gtk_widget_add_tick_callback (GTK_WIDGET (self), tick_cb, NULL, NULL);
}
static void
graph_widget_dispose (GObject *object)
{
GraphWidget *self = GRAPH_WIDGET (object);
g_clear_pointer (&self->path, gsk_path_unref);
gsk_stroke_free (self->stroke);
G_OBJECT_CLASS (graph_widget_parent_class)->dispose (object);
}
static void
graph_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GraphWidget *self = GRAPH_WIDGET (widget);
gtk_snapshot_append_stroke (snapshot, self->path, self->stroke, &self->color);
}
static void
graph_widget_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*minimum = *natural = 200;
else
*minimum = *natural = 100;
}
static void
graph_widget_class_init (GraphWidgetClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = graph_widget_dispose;
widget_class->snapshot = graph_widget_snapshot;
widget_class->measure = graph_widget_measure;
}
GtkWidget *
graph_widget_new (void)
{
return g_object_new (GRAPH_TYPE_WIDGET, NULL);
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include <gtk/gtk.h>
#define GRAPH_TYPE_WIDGET (graph_widget_get_type ())
G_DECLARE_FINAL_TYPE (GraphWidget, graph_widget, GRAPH, WIDGET, GtkWidget)
GtkWidget * graph_widget_new (void);

View File

@@ -840,24 +840,24 @@ gtk_gears_unrealize (GtkWidget *widget)
GtkGearsPrivate *priv = gtk_gears_get_instance_private ((GtkGears *) widget);
gtk_gl_area_make_current (glarea);
if (gtk_gl_area_get_error (glarea) != NULL)
return;
if (gtk_gl_area_get_error (glarea) == NULL)
{
/* Release the resources associated with OpenGL */
if (priv->gear_vbo[0] != 0)
glDeleteBuffers (1, &(priv->gear_vbo[0]));
/* Release the resources associated with OpenGL */
if (priv->gear_vbo[0] != 0)
glDeleteBuffers (1, &(priv->gear_vbo[0]));
if (priv->gear_vbo[1] != 0)
glDeleteBuffers (1, &(priv->gear_vbo[1]));
if (priv->gear_vbo[1] != 0)
glDeleteBuffers (1, &(priv->gear_vbo[1]));
if (priv->gear_vbo[2] != 0)
glDeleteBuffers (1, &(priv->gear_vbo[2]));
if (priv->gear_vbo[2] != 0)
glDeleteBuffers (1, &(priv->gear_vbo[2]));
if (priv->vao != 0)
glDeleteVertexArrays (1, &priv->vao);
if (priv->vao != 0)
glDeleteVertexArrays (1, &priv->vao);
if (priv->program != 0)
glDeleteProgram (priv->program);
if (priv->program != 0)
glDeleteProgram (priv->program);
}
priv->ModelViewProjectionMatrix_location = 0;
priv->NormalMatrix_location = 0;

View File

@@ -72,6 +72,11 @@ demos = files([
'paintable_symbolic.c',
'panes.c',
'password_entry.c',
'path_fill.c',
'path_maze.c',
'path_spinner.c',
'path_walk.c',
'path_text.c',
'peg_solitaire.c',
'pickers.c',
'printing.c',
@@ -136,6 +141,8 @@ extra_demo_sources = files([
'unicode-names.c',
'suggestionentry.c',
'language-names.c',
'nodewidget.c',
'graphwidget.c',
])
if os_unix

View File

@@ -0,0 +1,76 @@
#include "nodewidget.h"
struct _NodeWidget
{
GtkWidget parent_instance;
GskRenderNode *node;
};
struct _NodeWidgetClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (NodeWidget, node_widget, GTK_TYPE_WIDGET)
static void
node_widget_init (NodeWidget *self)
{
}
static void
node_widget_dispose (GObject *object)
{
NodeWidget *self = NODE_WIDGET (object);
gsk_render_node_unref (self->node);
G_OBJECT_CLASS (node_widget_parent_class)->dispose (object);
}
static void
node_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
NodeWidget *self = NODE_WIDGET (widget);
gtk_snapshot_append_node (snapshot, self->node);
}
static void
node_widget_class_init (NodeWidgetClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = node_widget_dispose;
widget_class->snapshot = node_widget_snapshot;
}
GtkWidget *
node_widget_new (const char *resource)
{
NodeWidget *self;
GBytes *bytes;
GskRenderNode *node;
graphene_rect_t bounds;
float scale;
GskTransform *transform;
self = g_object_new (NODE_TYPE_WIDGET, NULL);
bytes = g_resources_lookup_data (resource, 0, NULL);
node = gsk_render_node_deserialize (bytes, NULL, NULL);
g_bytes_unref (bytes);
gsk_render_node_get_bounds (node, &bounds);
scale = MIN (100.0/bounds.size.width, 100.0/bounds.size.height);
transform = gsk_transform_scale (NULL, scale, scale);
self->node = gsk_transform_node_new (node, transform);
gsk_transform_unref (transform);
gsk_render_node_unref (node);
return GTK_WIDGET (self);
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include <gtk/gtk.h>
#define NODE_TYPE_WIDGET (node_widget_get_type ())
G_DECLARE_FINAL_TYPE (NodeWidget, node_widget, NODE, WIDGET, GtkWidget)
GtkWidget * node_widget_new (const char *file);

198
demos/gtk-demo/path_fill.c Normal file
View File

@@ -0,0 +1,198 @@
/* Path/Fill and Stroke
*
* This demo shows how to use GskPath to draw shapes that are (a bit)
* more complex than a rounded rectangle.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "paintable.h"
#define GTK_TYPE_LOGO_PAINTABLE (gtk_logo_paintable_get_type ())
G_DECLARE_FINAL_TYPE (GtkLogoPaintable, gtk_logo_paintable, GTK, LOGO_PAINTABLE, GObject)
struct _GtkLogoPaintable
{
GObject parent_instance;
int width;
int height;
GskPath *path[3];
GdkRGBA color[3];
GskPath *stroke_path;
GskStroke *stroke1;
GskStroke *stroke2;
GdkRGBA stroke_color;
};
struct _GtkLogoPaintableClass
{
GObjectClass parent_class;
};
static int
gtk_logo_paintable_get_intrinsic_width (GdkPaintable *paintable)
{
GtkLogoPaintable *self = GTK_LOGO_PAINTABLE (paintable);
return self->width;
}
static int
gtk_logo_paintable_get_intrinsic_height (GdkPaintable *paintable)
{
GtkLogoPaintable *self = GTK_LOGO_PAINTABLE (paintable);
return self->height;
}
static void
gtk_logo_paintable_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GtkLogoPaintable *self = GTK_LOGO_PAINTABLE (paintable);
for (unsigned int i = 0; i < 3; i++)
{
gtk_snapshot_push_fill (snapshot, self->path[i], GSK_FILL_RULE_WINDING);
gtk_snapshot_append_color (snapshot,
&self->color[i],
&GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
}
for (unsigned int i = 0; i < 3; i++)
{
gtk_snapshot_push_stroke (snapshot, self->stroke_path, self->stroke1);
gtk_snapshot_append_color (snapshot,
&self->stroke_color,
&GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
}
gtk_snapshot_push_stroke (snapshot, self->stroke_path, self->stroke2);
gtk_snapshot_append_color (snapshot,
&self->stroke_color,
&GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
}
static GdkPaintableFlags
gtk_logo_paintable_get_flags (GdkPaintable *paintable)
{
return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE;
}
static void
gtk_logo_paintable_paintable_init (GdkPaintableInterface *iface)
{
iface->get_intrinsic_width = gtk_logo_paintable_get_intrinsic_width;
iface->get_intrinsic_height = gtk_logo_paintable_get_intrinsic_height;
iface->snapshot = gtk_logo_paintable_snapshot;
iface->get_flags = gtk_logo_paintable_get_flags;
}
/* When defining the GType, we need to implement the GdkPaintable interface */
G_DEFINE_TYPE_WITH_CODE (GtkLogoPaintable, gtk_logo_paintable, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_logo_paintable_paintable_init))
static void
gtk_logo_paintable_dispose (GObject *object)
{
GtkLogoPaintable *self = GTK_LOGO_PAINTABLE (object);
for (unsigned int i = 0; i < 3; i++)
gsk_path_unref (self->path[i]);
gsk_path_unref (self->stroke_path);
gsk_stroke_free (self->stroke1);
gsk_stroke_free (self->stroke2);
G_OBJECT_CLASS (gtk_logo_paintable_parent_class)->dispose (object);
}
static void
gtk_logo_paintable_class_init (GtkLogoPaintableClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_logo_paintable_dispose;
}
static void
gtk_logo_paintable_init (GtkLogoPaintable *self)
{
}
static GdkPaintable *
gtk_logo_paintable_new (void)
{
GtkLogoPaintable *self;
graphene_rect_t bounds, bounds2;
self = g_object_new (GTK_TYPE_LOGO_PAINTABLE, NULL);
/* Paths and colors extracted from gtk-logo.svg */
self->path[0] = gsk_path_parse ("m3.12,66.17 -2.06,-51.46 32.93,24.7 v55.58 l-30.87,-28.82 z");
self->path[1] = gsk_path_parse ("m34,95 49.4,-20.58 4.12,-51.46 -53.52,16.47 v55.58 z");
self->path[2] = gsk_path_parse ("m1.06,14.71 32.93,24.7 53.52,-16.47 -36.75,-21.88 -49.7,13.65 z");
gdk_rgba_parse (&self->color[0], "#e40000");
gdk_rgba_parse (&self->color[1], "#7fe719");
gdk_rgba_parse (&self->color[2], "#729fcf");
self->stroke_path = gsk_path_parse ("m50.6,51.3 -47.3,14 z l33,23 z v-50");
self->stroke1 = gsk_stroke_new (2.12);
self->stroke2 = gsk_stroke_new (1.25);
gdk_rgba_parse (&self->stroke_color, "#ffffff");
gsk_path_get_stroke_bounds (self->path[0], self->stroke1, &bounds);
gsk_path_get_stroke_bounds (self->path[1], self->stroke1, &bounds2);
graphene_rect_union (&bounds, &bounds2, &bounds);
gsk_path_get_stroke_bounds (self->path[2], self->stroke1, &bounds2);
graphene_rect_union (&bounds, &bounds2, &bounds);
gsk_path_get_stroke_bounds (self->stroke_path, self->stroke2, &bounds2);
graphene_rect_union (&bounds, &bounds2, &bounds);
self->width = bounds.origin.x + bounds.size.width;
self->height = bounds.origin.y + bounds.size.height;
return GDK_PAINTABLE (self);
}
GtkWidget *
do_path_fill (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *picture;
GdkPaintable *paintable;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Fill and Stroke");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
paintable = gtk_logo_paintable_new ();
picture = gtk_picture_new_for_paintable (paintable);
gtk_picture_set_content_fit (GTK_PICTURE (picture), GTK_CONTENT_FIT_CONTAIN);
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
g_object_unref (paintable);
gtk_window_set_child (GTK_WINDOW (window), picture);
}
if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window));
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

348
demos/gtk-demo/path_maze.c Normal file
View File

@@ -0,0 +1,348 @@
/* Path/Maze
*
* This demo shows how to use a GskPath to create a maze and use
* gsk_path_get_closest_point() to check the mouse stays
* on the path.
*
* It also shows off the performance of GskPath (or not) as this
* is a rather complex path.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "paintable.h"
#define MAZE_GRID_SIZE 20
#define MAZE_STROKE_SIZE_ACTIVE (MAZE_GRID_SIZE - 4)
#define MAZE_STROKE_SIZE_INACTIVE (MAZE_GRID_SIZE - 12)
#define MAZE_WIDTH 31
#define MAZE_HEIGHT 21
#define GTK_TYPE_MAZE (gtk_maze_get_type ())
G_DECLARE_FINAL_TYPE (GtkMaze, gtk_maze, GTK, MAZE, GtkWidget)
struct _GtkMaze
{
GtkWidget parent_instance;
int width;
int height;
GskPath *path;
GskPathMeasure *measure;
GdkPaintable *background;
gboolean active;
};
struct _GtkMazeClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (GtkMaze, gtk_maze, GTK_TYPE_WIDGET)
static void
gtk_maze_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkMaze *self = GTK_MAZE (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*minimum = *natural = self->width;
else
*minimum = *natural = self->height;
}
static void
gtk_maze_snapshot (GtkWidget *widget,
GdkSnapshot *snapshot)
{
GtkMaze *self = GTK_MAZE (widget);
double width = gtk_widget_get_width (widget);
double height = gtk_widget_get_height (widget);
GskStroke *stroke;
stroke = gsk_stroke_new (MAZE_STROKE_SIZE_INACTIVE);
if (self->active)
gsk_stroke_set_line_width (stroke, MAZE_STROKE_SIZE_ACTIVE);
gsk_stroke_set_line_join (stroke, GSK_LINE_JOIN_ROUND);
gsk_stroke_set_line_cap (stroke, GSK_LINE_CAP_ROUND);
gtk_snapshot_push_stroke (snapshot, self->path, stroke);
gsk_stroke_free (stroke);
if (self->background)
{
gdk_paintable_snapshot (self->background, snapshot, width, height);
}
else
{
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, height),
(GskColorStop[8]) {
{ 0.0, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.2, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.3, { 1.0, 1.0, 0.0, 1.0 } },
{ 0.4, { 0.0, 1.0, 0.0, 1.0 } },
{ 0.6, { 0.0, 1.0, 1.0, 1.0 } },
{ 0.7, { 0.0, 0.0, 1.0, 1.0 } },
{ 0.8, { 1.0, 0.0, 1.0, 1.0 } },
{ 1.0, { 1.0, 0.0, 1.0, 1.0 } }
},
8);
}
gtk_snapshot_pop (snapshot);
}
static void
gtk_maze_dispose (GObject *object)
{
GtkMaze *self = GTK_MAZE (object);
g_clear_pointer (&self->path, gsk_path_unref);
g_clear_pointer (&self->measure, gsk_path_measure_unref);
if (self->background)
{
g_signal_handlers_disconnect_matched (self->background, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
g_clear_object (&self->background);
}
G_OBJECT_CLASS (gtk_maze_parent_class)->dispose (object);
}
static void
gtk_maze_class_init (GtkMazeClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_maze_dispose;
widget_class->measure = gtk_maze_measure;
widget_class->snapshot = gtk_maze_snapshot;
}
static void
pointer_motion (GtkEventControllerMotion *controller,
double x,
double y,
GtkMaze *self)
{
GskPathPoint point;
float distance;
if (!self->active)
return;
if (gsk_path_get_closest_point (self->path,
&GRAPHENE_POINT_INIT (x, y),
INFINITY,
&point,
&distance))
{
if (distance < MAZE_STROKE_SIZE_ACTIVE / 2.f)
return;
}
self->active = FALSE;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
pointer_leave (GtkEventControllerMotion *controller,
GtkMaze *self)
{
if (!self->active)
{
self->active = TRUE;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
}
static void
gtk_maze_init (GtkMaze *self)
{
GtkEventController *controller;
controller = GTK_EVENT_CONTROLLER (gtk_event_controller_motion_new ());
g_signal_connect (controller, "motion", G_CALLBACK (pointer_motion), self);
g_signal_connect (controller, "leave", G_CALLBACK (pointer_leave), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
self->active = TRUE;
}
static void
gtk_maze_set_path (GtkMaze *self,
GskPath *path)
{
g_clear_pointer (&self->path, gsk_path_unref);
g_clear_pointer (&self->measure, gsk_path_measure_unref);
self->path = gsk_path_ref (path);
self->measure = gsk_path_measure_new (path);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
GtkWidget *
gtk_maze_new (GskPath *path,
GdkPaintable *background,
int width,
int height)
{
GtkMaze *self;
self = g_object_new (GTK_TYPE_MAZE, NULL);
gtk_maze_set_path (self, path);
gsk_path_unref (path);
self->background = background;
if (self->background)
{
g_signal_connect_swapped (self->background, "invalidate-contents", G_CALLBACK (gtk_widget_queue_draw), self);
g_signal_connect_swapped (self->background, "invalidate-size", G_CALLBACK (gtk_widget_queue_resize), self);
}
self->width = width;
self->height = height;
return GTK_WIDGET (self);
}
static void
add_point_to_maze (GtkBitset *maze,
GskPathBuilder *builder,
guint x,
guint y)
{
gboolean set[4] = { FALSE, FALSE, FALSE, FALSE };
guint dir;
gtk_bitset_add (maze, y * MAZE_WIDTH + x);
while (TRUE)
{
set[0] = set[0] || x == 0 || gtk_bitset_contains (maze, y * MAZE_WIDTH + x - 1);
set[1] = set[1] || y == 0 || gtk_bitset_contains (maze, (y - 1) * MAZE_WIDTH + x);
set[2] = set[2] || x + 1 == MAZE_WIDTH || gtk_bitset_contains (maze, y * MAZE_WIDTH + x + 1);
set[3] = set[3] || y + 1 == MAZE_HEIGHT || gtk_bitset_contains (maze, (y + 1) * MAZE_WIDTH + x);
if (set[0] && set[1] && set[2] && set[3])
return;
do
{
dir = g_random_int_range (0, 4);
}
while (set[dir]);
switch (dir)
{
case 0:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x - 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x - 1, y);
break;
case 1:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y - 0.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x, y - 1);
break;
case 2:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x + 1.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x + 1, y);
break;
case 3:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 1.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x, y + 1);
break;
default:
g_assert_not_reached ();
break;
}
}
}
static GskPath *
create_path_for_maze (GtkWidget *widget)
{
GskPathBuilder *builder;
GtkBitset *maze;
builder = gsk_path_builder_new ();
maze = gtk_bitset_new_empty ();
/* make sure the outer lines are unreachable:
* Set the full range, then remove the center again. */
gtk_bitset_add_range (maze, 0, MAZE_WIDTH * MAZE_HEIGHT);
gtk_bitset_remove_rectangle (maze, MAZE_WIDTH + 1, MAZE_WIDTH - 2, MAZE_HEIGHT - 2, MAZE_WIDTH);
/* Fill the maze */
add_point_to_maze (maze, builder, MAZE_WIDTH / 2, MAZE_HEIGHT / 2);
/* Add start and stop lines */
gsk_path_builder_move_to (builder, 1.5 * MAZE_GRID_SIZE, -0.5 * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, 1.5 * MAZE_GRID_SIZE, 1.5 * MAZE_GRID_SIZE);
gsk_path_builder_move_to (builder, (MAZE_WIDTH - 1.5) * MAZE_GRID_SIZE, (MAZE_HEIGHT - 1.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (MAZE_WIDTH - 1.5) * MAZE_GRID_SIZE, (MAZE_HEIGHT + 0.5) * MAZE_GRID_SIZE);
gtk_bitset_unref (maze);
return gsk_path_builder_free_to_path (builder);
}
GtkWidget *
do_path_maze (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *maze;
GtkMediaStream *stream;
GskPath *path;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Follow the maze with the mouse");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
#if 0
stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
#else
stream = gtk_nuclear_media_stream_new ();
#endif
gtk_media_stream_play (stream);
gtk_media_stream_set_loop (stream, TRUE);
path = create_path_for_maze (window);
maze = gtk_maze_new (path,
GDK_PAINTABLE (stream),
MAZE_WIDTH * MAZE_GRID_SIZE,
MAZE_HEIGHT * MAZE_GRID_SIZE);
gtk_window_set_child (GTK_WINDOW (window), maze);
}
if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window));
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -0,0 +1,320 @@
/* Path/Spinner
*
* This demo shows how to use GskPath to draw a simple animation
* that could be used as a spinner.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "paintable.h"
#define GTK_TYPE_SPINNER_PAINTABLE (gtk_spinner_paintable_get_type ())
G_DECLARE_FINAL_TYPE (GtkSpinnerPaintable, gtk_spinner_paintable, GTK, SPINNER_PAINTABLE, GObject)
struct _GtkSpinnerPaintable
{
GObject parent_instance;
gint64 start_time;
int width;
double angle;
double completion;
GskPath *circle;
GskPath *path;
GskStroke *stroke;
GdkRGBA color;
GdkRGBA circle_color;
#ifdef SHOW_CONTROLS
GskPath *controls;
GdkRGBA control_color;
#endif
};
struct _GtkSpinnerPaintableClass
{
GObjectClass parent_class;
};
static int
gtk_spinner_paintable_get_intrinsic_width (GdkPaintable *paintable)
{
GtkSpinnerPaintable *self = GTK_SPINNER_PAINTABLE (paintable);
return self->width;
}
static int
gtk_spinner_paintable_get_intrinsic_height (GdkPaintable *paintable)
{
GtkSpinnerPaintable *self = GTK_SPINNER_PAINTABLE (paintable);
return self->width;
}
static void
gtk_spinner_paintable_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GtkSpinnerPaintable *self = GTK_SPINNER_PAINTABLE (paintable);
gtk_snapshot_append_stroke (snapshot, self->circle, self->stroke, &self->circle_color);
gtk_snapshot_append_stroke (snapshot, self->path, self->stroke, &self->color);
#ifdef SHOW_CONTROLS
GskStroke *stroke = gsk_stroke_new (1);
gtk_snapshot_append_stroke (snapshot, self->controls, stroke, &self->control_color);
gsk_stroke_free (stroke);
#endif
}
static GdkPaintableFlags
gtk_spinner_paintable_get_flags (GdkPaintable *paintable)
{
return GDK_PAINTABLE_STATIC_SIZE;
}
static void
gtk_spinner_paintable_paintable_init (GdkPaintableInterface *iface)
{
iface->get_intrinsic_width = gtk_spinner_paintable_get_intrinsic_width;
iface->get_intrinsic_height = gtk_spinner_paintable_get_intrinsic_height;
iface->snapshot = gtk_spinner_paintable_snapshot;
iface->get_flags = gtk_spinner_paintable_get_flags;
}
/* When defining the GType, we need to implement the GdkPaintable interface */
G_DEFINE_TYPE_WITH_CODE (GtkSpinnerPaintable, gtk_spinner_paintable, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_spinner_paintable_paintable_init))
static void
gtk_spinner_paintable_dispose (GObject *object)
{
GtkSpinnerPaintable *self = GTK_SPINNER_PAINTABLE (object);
gsk_path_unref (self->circle);
gsk_path_unref (self->path);
#ifdef SHOW_CONTROLS
gsk_path_unref (self->controls);
#endif
gsk_stroke_free (self->stroke);
G_OBJECT_CLASS (gtk_spinner_paintable_parent_class)->dispose (object);
}
static void
gtk_spinner_paintable_class_init (GtkSpinnerPaintableClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_spinner_paintable_dispose;
}
static void
gtk_spinner_paintable_init (GtkSpinnerPaintable *self)
{
}
static GdkPaintable *
gtk_spinner_paintable_new (void)
{
GtkSpinnerPaintable *self;
GskPathBuilder *builder;
self = g_object_new (GTK_TYPE_SPINNER_PAINTABLE, NULL);
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (50, 50), 40);
self->circle = gsk_path_builder_free_to_path (builder);
self->width = 100;
self->angle = 0;
self->completion = 1;
gdk_rgba_parse (&self->color, "green");
gdk_rgba_parse (&self->circle_color, "lightgray");
#ifdef SHOW_CONTROLS
gdk_rgba_parse (&self->control_color, "black");
#endif
self->stroke = gsk_stroke_new (5);
return GDK_PAINTABLE (self);
}
#ifdef SHOW_CONTROLS
static gboolean
add_controls (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
gpointer data)
{
GskPathBuilder *builder = data;
switch (op)
{
case GSK_PATH_MOVE:
gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
break;
case GSK_PATH_CLOSE:
case GSK_PATH_LINE:
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
break;
case GSK_PATH_QUAD:
case GSK_PATH_ARC:
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
gsk_path_builder_line_to (builder, pts[2].x, pts[2].y);
break;
case GSK_PATH_CUBIC:
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
gsk_path_builder_line_to (builder, pts[2].x, pts[2].y);
gsk_path_builder_line_to (builder, pts[3].x, pts[3].y);
break;
default:
g_assert_not_reached ();
}
return TRUE;
}
#endif
static void
update_path (GtkSpinnerPaintable *self)
{
GskPathBuilder *builder;
GskPathPoint start, end;
graphene_point_t p0, p1;
float start_angle, end_angle;
start_angle = self->angle;
end_angle = fmod (self->angle + 360 * self->completion / 100, 360);
p0 = GRAPHENE_POINT_INIT (50 + 40 * cos (M_PI * start_angle / 180),
50 + 40 * sin (M_PI * start_angle / 180));
p1 = GRAPHENE_POINT_INIT (50 + 40 * cos (M_PI * end_angle / 180),
50 + 40 * sin (M_PI * end_angle / 180));
g_clear_pointer (&self->path, gsk_path_unref);
gsk_path_get_closest_point (self->circle, &p0, INFINITY, &start, NULL);
gsk_path_get_closest_point (self->circle, &p1, INFINITY, &end, NULL);
builder = gsk_path_builder_new ();
gsk_path_builder_add_segment (builder, self->circle, &start, &end);
self->path = gsk_path_builder_free_to_path (builder);
#ifdef SHOW_CONTROLS
g_clear_pointer (&self->controls, gsk_path_unref);
builder = gsk_path_builder_new ();
gsk_path_foreach (self->path, -1, add_controls, builder);
self->controls = gsk_path_builder_free_to_path (builder);
#endif
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
}
static void
gtk_spinner_paintable_set_completion (GtkSpinnerPaintable *self,
float completion)
{
self->completion = CLAMP (completion, 0, 100);
update_path (self);
}
static float
gtk_spinner_paintable_get_completion (GtkSpinnerPaintable *self)
{
return self->completion;
}
static void
gtk_spinner_paintable_set_frame_time (GtkSpinnerPaintable *self,
gint64 time)
{
double delta;
if (self->start_time == 0)
self->start_time = time;
delta = (time - self->start_time) / (double) G_TIME_SPAN_SECOND;
self->angle = fmod (60 * delta, 360);
update_path (self);
}
static gboolean
tick_cb (GtkWidget *widget,
GdkFrameClock *clock,
gpointer data)
{
GtkSpinnerPaintable *self = data;
gtk_spinner_paintable_set_frame_time (self, gdk_frame_clock_get_frame_time (clock));
return G_SOURCE_CONTINUE;
}
static gboolean
progress_timeout (gpointer data)
{
GtkSpinnerPaintable *self = data;
static float progress_delta = 0.5;
float progress;
progress = gtk_spinner_paintable_get_completion (self);
if (progress >= 100 || progress <= 0)
progress_delta = -progress_delta;
gtk_spinner_paintable_set_completion (self, progress + progress_delta);
return G_SOURCE_CONTINUE;
}
static void
unset_timeout (gpointer data)
{
g_source_remove (GPOINTER_TO_UINT (data));
}
GtkWidget *
do_path_spinner (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *picture;
GdkPaintable *paintable;
guint timeout_id;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Spinner");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
paintable = gtk_spinner_paintable_new ();
picture = gtk_picture_new_for_paintable (paintable);
gtk_picture_set_content_fit (GTK_PICTURE (picture), GTK_CONTENT_FIT_CONTAIN);
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
g_object_unref (paintable);
gtk_widget_add_tick_callback (picture, tick_cb, paintable, NULL);
timeout_id = g_timeout_add (100, progress_timeout, paintable);
g_object_set_data_full (G_OBJECT (picture), "timeout", GUINT_TO_POINTER (timeout_id), unset_timeout);
gtk_window_set_child (GTK_WINDOW (window), picture);
}
if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window));
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

584
demos/gtk-demo/path_text.c Normal file
View File

@@ -0,0 +1,584 @@
/* Path/Text
*
* This demo shows how to use GskPath to transform a path along another path.
*
* It also demonstrates that paths can be filled with more interesting
* content than just plain colors.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define GTK_TYPE_PATH_WIDGET (gtk_path_widget_get_type ())
G_DECLARE_FINAL_TYPE (GtkPathWidget, gtk_path_widget, GTK, PATH_WIDGET, GtkWidget)
#define POINT_SIZE 8
enum {
PROP_0,
PROP_TEXT,
PROP_EDITABLE,
N_PROPS
};
struct _GtkPathWidget
{
GtkWidget parent_instance;
char *text;
gboolean editable;
graphene_point_t points[4];
guint active_point;
GskPath *line_path;
GskPath *text_path;
GdkPaintable *background;
};
struct _GtkPathWidgetClass
{
GtkWidgetClass parent_class;
};
static GParamSpec *properties[N_PROPS] = { NULL, };
G_DEFINE_TYPE (GtkPathWidget, gtk_path_widget, GTK_TYPE_WIDGET)
static GskPath *
create_path_from_text (GtkWidget *widget,
const char *text,
graphene_point_t *out_offset)
{
PangoLayout *layout;
PangoFontDescription *desc;
GskPathBuilder *builder;
GskPath *result;
layout = gtk_widget_create_pango_layout (widget, text);
desc = pango_font_description_from_string ("sans bold 36");
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
builder = gsk_path_builder_new ();
gsk_path_builder_add_layout (builder, layout);
result = gsk_path_builder_free_to_path (builder);
if (out_offset)
graphene_point_init (out_offset, 0, - pango_layout_get_baseline (layout) / (double) PANGO_SCALE);
g_object_unref (layout);
return result;
}
typedef struct
{
GskPathMeasure *measure;
GskPathBuilder *builder;
graphene_point_t offset;
double scale;
} GtkPathTransform;
static void
gtk_path_transform_point (GskPathMeasure *measure,
const graphene_point_t *pt,
const graphene_point_t *offset,
float scale,
graphene_point_t *res)
{
graphene_vec2_t tangent;
GskPathPoint point;
if (gsk_path_measure_get_point (measure, (pt->x + offset->x) * scale, &point))
{
GskPath *path = gsk_path_measure_get_path (measure);
gsk_path_point_get_position (&point, path, res);
gsk_path_point_get_tangent (&point, path, GSK_PATH_TO_END, &tangent);
res->x -= (pt->y + offset->y) * scale * graphene_vec2_get_y (&tangent);
res->y += (pt->y + offset->y) * scale * graphene_vec2_get_x (&tangent);
}
}
static gboolean
gtk_path_transform_op (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
GtkPathTransform *transform = data;
switch (op)
{
case GSK_PATH_MOVE:
{
graphene_point_t 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;
case GSK_PATH_LINE:
{
graphene_point_t 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;
case GSK_PATH_QUAD:
{
graphene_point_t 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]);
gsk_path_builder_quad_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y);
}
break;
case GSK_PATH_CUBIC:
{
graphene_point_t res[3];
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;
case GSK_PATH_CONIC:
{
graphene_point_t res[2];
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;
case GSK_PATH_CLOSE:
gsk_path_builder_close (transform->builder);
break;
default:
g_assert_not_reached();
return FALSE;
}
return TRUE;
}
static GskPath *
gtk_path_transform (GskPath *line_path,
GskPath *path,
const graphene_point_t *offset)
{
GskPathMeasure *measure = gsk_path_measure_new (line_path);
GtkPathTransform transform = { measure, gsk_path_builder_new (), *offset };
graphene_rect_t bounds;
gsk_path_get_bounds (path, &bounds);
if (bounds.origin.x + bounds.size.width > 0)
transform.scale = gsk_path_measure_get_length (measure) / (bounds.origin.x + bounds.size.width);
else
transform.scale = 1.0f;
gsk_path_foreach (path, -1, gtk_path_transform_op, &transform);
gsk_path_measure_unref (measure);
return gsk_path_builder_free_to_path (transform.builder);
}
static void
gtk_path_widget_clear_text_path (GtkPathWidget *self)
{
g_clear_pointer (&self->text_path, gsk_path_unref);
}
static void
gtk_path_widget_clear_paths (GtkPathWidget *self)
{
gtk_path_widget_clear_text_path (self);
g_clear_pointer (&self->line_path, gsk_path_unref);
}
static void
gtk_path_widget_create_text_path (GtkPathWidget *self)
{
GskPath *path;
graphene_point_t offset;
gtk_path_widget_clear_text_path (self);
path = create_path_from_text (GTK_WIDGET (self), self->text, &offset);
self->text_path = gtk_path_transform (self->line_path, path, &offset);
gsk_path_unref (path);
}
static void
gtk_path_widget_create_paths (GtkPathWidget *self)
{
double width = gtk_widget_get_width (GTK_WIDGET (self));
double height = gtk_widget_get_height (GTK_WIDGET (self));
GskPathBuilder *builder;
gtk_path_widget_clear_paths (self);
if (width <= 0 || height <= 0)
return;
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder,
self->points[0].x * width, self->points[0].y * height);
gsk_path_builder_cubic_to (builder,
self->points[1].x * width, self->points[1].y * height,
self->points[2].x * width, self->points[2].y * height,
self->points[3].x * width, self->points[3].y * height);
self->line_path = gsk_path_builder_free_to_path (builder);
gtk_path_widget_create_text_path (self);
}
static void
gtk_path_widget_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkPathWidget *self = GTK_PATH_WIDGET (widget);
GTK_WIDGET_CLASS (gtk_path_widget_parent_class)->size_allocate (widget, width, height, baseline);
gtk_path_widget_create_paths (self);
}
static void
gtk_path_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkPathWidget *self = GTK_PATH_WIDGET (widget);
double width = gtk_widget_get_width (widget);
double height = gtk_widget_get_height (widget);
GskPath *path;
GskStroke *stroke;
gsize i;
/* frosted glass the background */
gtk_snapshot_push_blur (snapshot, 100);
gdk_paintable_snapshot (self->background, snapshot, width, height);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 1, 1, 1, 0.6 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
/* draw the text */
if (self->text_path)
{
gtk_snapshot_push_fill (snapshot, self->text_path, GSK_FILL_RULE_WINDING);
gdk_paintable_snapshot (self->background, snapshot, width, height);
/* ... with an emboss effect */
stroke = gsk_stroke_new (2.0);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT(1, 1));
gtk_snapshot_push_stroke (snapshot, self->text_path, stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 0.2 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gsk_stroke_free (stroke);
gtk_snapshot_pop (snapshot);
gtk_snapshot_pop (snapshot);
}
if (self->editable && self->line_path)
{
GskPathBuilder *builder;
/* draw the control line */
stroke = gsk_stroke_new (1.0);
gtk_snapshot_push_stroke (snapshot, self->line_path, stroke);
gsk_stroke_free (stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
/* draw the points */
builder = gsk_path_builder_new ();
for (i = 0; i < 4; i++)
{
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (self->points[i].x * width, self->points[i].y * height), POINT_SIZE);
}
path = gsk_path_builder_free_to_path (builder);
gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 1, 1, 1, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
stroke = gsk_stroke_new (1.0);
gtk_snapshot_push_stroke (snapshot, path, stroke);
gsk_stroke_free (stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
gsk_path_unref (path);
}
}
static void
gtk_path_widget_set_text (GtkPathWidget *self,
const char *text)
{
if (g_strcmp0 (self->text, text) == 0)
return;
g_free (self->text);
self->text = g_strdup (text);
gtk_path_widget_create_paths (self);
gtk_widget_queue_draw (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TEXT]);
}
static void
gtk_path_widget_set_editable (GtkPathWidget *self,
gboolean editable)
{
if (self->editable == editable)
return;
self->editable = editable;
gtk_widget_queue_draw (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_EDITABLE]);
}
static void
gtk_path_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkPathWidget *self = GTK_PATH_WIDGET (object);
switch (prop_id)
{
case PROP_TEXT:
gtk_path_widget_set_text (self, g_value_get_string (value));
break;
case PROP_EDITABLE:
gtk_path_widget_set_editable (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkPathWidget *self = GTK_PATH_WIDGET (object);
switch (prop_id)
{
case PROP_TEXT:
g_value_set_string (value, self->text);
break;
case PROP_EDITABLE:
g_value_set_boolean (value, self->editable);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_widget_dispose (GObject *object)
{
GtkPathWidget *self = GTK_PATH_WIDGET (object);
gtk_path_widget_clear_paths (self);
G_OBJECT_CLASS (gtk_path_widget_parent_class)->dispose (object);
}
static void
gtk_path_widget_class_init (GtkPathWidgetClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_path_widget_dispose;
object_class->set_property = gtk_path_widget_set_property;
object_class->get_property = gtk_path_widget_get_property;
widget_class->size_allocate = gtk_path_widget_allocate;
widget_class->snapshot = gtk_path_widget_snapshot;
properties[PROP_TEXT] =
g_param_spec_string ("text",
"text",
"Text transformed along a path",
NULL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
properties[PROP_EDITABLE] =
g_param_spec_boolean ("editable",
"editable",
"If the path can be edited by the user",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
drag_begin (GtkGestureDrag *gesture,
double x,
double y,
GtkPathWidget *self)
{
graphene_point_t mouse = GRAPHENE_POINT_INIT (x, y);
double width = gtk_widget_get_width (GTK_WIDGET (self));
double height = gtk_widget_get_height (GTK_WIDGET (self));
gsize i;
for (i = 0; i < 4; i++)
{
if (graphene_point_distance (&GRAPHENE_POINT_INIT (self->points[i].x * width, self->points[i].y * height), &mouse, NULL, NULL) <= POINT_SIZE)
{
self->active_point = i;
break;
}
}
if (i == 4)
{
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
return;
}
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
drag_update (GtkGestureDrag *drag,
double offset_x,
double offset_y,
GtkPathWidget *self)
{
double width = gtk_widget_get_width (GTK_WIDGET (self));
double height = gtk_widget_get_height (GTK_WIDGET (self));
double start_x, start_y;
gtk_gesture_drag_get_start_point (drag, &start_x, &start_y);
self->points[self->active_point] = GRAPHENE_POINT_INIT ((start_x + offset_x) / width,
(start_y + offset_y) / height);
self->points[self->active_point].x = CLAMP (self->points[self->active_point].x, 0, 1);
self->points[self->active_point].y = CLAMP (self->points[self->active_point].y, 0, 1);
gtk_path_widget_create_paths (self);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
pointer_motion (GtkEventControllerMotion *controller,
double x,
double y,
GtkPathWidget *self)
{
GskPathPoint point;
if (gsk_path_get_closest_point (self->line_path,
&GRAPHENE_POINT_INIT (x, y),
INFINITY,
&point,
NULL))
{
gtk_widget_queue_draw (GTK_WIDGET (self));
}
}
static void
pointer_leave (GtkEventControllerMotion *controller,
GtkPathWidget *self)
{
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
gtk_path_widget_init (GtkPathWidget *self)
{
GtkEventController *controller;
controller = GTK_EVENT_CONTROLLER (gtk_gesture_drag_new ());
g_signal_connect (controller, "drag-begin", G_CALLBACK (drag_begin), self);
g_signal_connect (controller, "drag-update", G_CALLBACK (drag_update), self);
g_signal_connect (controller, "drag-end", G_CALLBACK (drag_update), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
controller = GTK_EVENT_CONTROLLER (gtk_event_controller_motion_new ());
g_signal_connect (controller, "enter", G_CALLBACK (pointer_motion), self);
g_signal_connect (controller, "motion", G_CALLBACK (pointer_motion), self);
g_signal_connect (controller, "leave", G_CALLBACK (pointer_leave), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
self->points[0] = GRAPHENE_POINT_INIT (0.1, 0.9);
self->points[1] = GRAPHENE_POINT_INIT (0.3, 0.1);
self->points[2] = GRAPHENE_POINT_INIT (0.7, 0.1);
self->points[3] = GRAPHENE_POINT_INIT (0.9, 0.9);
self->background = GDK_PAINTABLE (gdk_texture_new_from_resource ("/sliding_puzzle/portland-rose.jpg"));
gtk_path_widget_set_text (self, "It's almost working");
}
GtkWidget *
gtk_path_widget_new (void)
{
GtkPathWidget *self;
self = g_object_new (GTK_TYPE_PATH_WIDGET, NULL);
return GTK_WIDGET (self);
}
GtkWidget *
do_path_text (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkBuilder *builder;
g_type_ensure (GTK_TYPE_PATH_WIDGET);
builder = gtk_builder_new_from_resource ("/path_text/path_text.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window));
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">Text along a Path</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<child type="end">
<object class="GtkToggleButton" id="edit-toggle">
<property name="icon-name">document-edit-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkRevealer">
<property name="reveal-child" bind-source="edit-toggle" bind-property="active" bind-flags="sync-create"></property>
<child>
<object class="GtkEntry" id="text">
<property name="text">Through the looking glass</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPathWidget" id="view">
<property name="editable" bind-source="edit-toggle" bind-property="active" bind-flags="sync-create"></property>
<property name="text" bind-source="text" bind-property="text" bind-flags="sync-create"></property>
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
</child>
</object>
</child>
</object>
</interface>

373
demos/gtk-demo/path_walk.c Normal file
View File

@@ -0,0 +1,373 @@
/* Path/Walk
*
* This demo draws a world map and shows how to animate objects along a GskPath.
*
* The world map that is used here is a path with 211 lines and 1569 cubic
* Bėzier segments in 121 contours.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define GTK_TYPE_PATH_WALK (gtk_path_walk_get_type ())
G_DECLARE_FINAL_TYPE (GtkPathWalk, gtk_path_walk, GTK, PATH_WALK, GtkWidget)
#define POINT_SIZE 8
enum {
PROP_0,
PROP_N_POINTS,
PROP_PATH,
N_PROPS
};
struct _GtkPathWalk
{
GtkWidget parent_instance;
GskPath *path;
GskPathMeasure *measure;
graphene_rect_t bounds;
GskPath *arrow_path;
guint n_points;
};
struct _GtkPathWalkClass
{
GtkWidgetClass parent_class;
};
static GParamSpec *properties[N_PROPS] = { NULL, };
G_DEFINE_TYPE (GtkPathWalk, gtk_path_walk, GTK_TYPE_WIDGET)
static void
rgba_init_from_hsla (GdkRGBA *rgba,
float hue,
float saturation,
float lightness,
float alpha)
{
float m1, m2;
if (lightness <= 0.5)
m2 = lightness * (1 + saturation);
else
m2 = lightness + saturation - lightness * saturation;
m1 = 2 * lightness - m2;
rgba->alpha = alpha;
if (saturation == 0)
{
rgba->red = lightness;
rgba->green = lightness;
rgba->blue = lightness;
}
else
{
hue = hue + 120;
while (hue > 360)
hue -= 360;
while (hue < 0)
hue += 360;
if (hue < 60)
rgba->red = m1 + (m2 - m1) * hue / 60;
else if (hue < 180)
rgba->red = m2;
else if (hue < 240)
rgba->red = m1 + (m2 - m1) * (240 - hue) / 60;
else
rgba->red = m1;
hue -= 120;
if (hue < 0)
hue += 360;
if (hue < 60)
rgba->green = m1 + (m2 - m1) * hue / 60;
else if (hue < 180)
rgba->green = m2;
else if (hue < 240)
rgba->green = m1 + (m2 - m1) * (240 - hue) / 60;
else
rgba->green = m1;
hue -= 120;
if (hue < 0)
hue += 360;
if (hue < 60)
rgba->blue = m1 + (m2 - m1) * hue / 60;
else if (hue < 180)
rgba->blue = m2;
else if (hue < 240)
rgba->blue = m1 + (m2 - m1) * (240 - hue) / 60;
else
rgba->blue = m1;
}
}
static void
gtk_path_walk_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkPathWalk *self = GTK_PATH_WALK (widget);
double width = gtk_widget_get_width (widget);
double height = gtk_widget_get_height (widget);
float length, progress;
GskStroke *stroke;
guint i;
if (self->path == NULL)
return;
gtk_snapshot_save (snapshot);
stroke = gsk_stroke_new (2.0);
gtk_snapshot_push_stroke (snapshot, self->path, stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
gsk_stroke_free (stroke);
length = gsk_path_measure_get_length (self->measure);
progress = 25.f * gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget)) / G_USEC_PER_SEC;
stroke = gsk_stroke_new (1.0);
for (i = 0; i < self->n_points; i++)
{
GskPathPoint point;
graphene_point_t position;
float angle;
GdkRGBA color;
float distance;
distance = i * length / self->n_points;
distance = fmod (distance + progress, length);
gsk_path_measure_get_point (self->measure, distance, &point);
gsk_path_point_get_position (&point, self->path, &position);
angle = gsk_path_point_get_rotation (&point, self->path, GSK_PATH_FROM_START);
rgba_init_from_hsla (&color, 360.f * i / self->n_points, 1, 0.5, 1);
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &position);
gtk_snapshot_rotate (snapshot, angle);
gtk_snapshot_append_fill (snapshot, self->arrow_path, GSK_FILL_RULE_EVEN_ODD, &color);
gtk_snapshot_append_stroke (snapshot, self->arrow_path, stroke, &(GdkRGBA) { 0, 0, 0, 1 });
gtk_snapshot_restore (snapshot);
}
gsk_stroke_free (stroke);
gtk_snapshot_restore (snapshot);
}
static void
gtk_path_walk_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkPathWalk *self = GTK_PATH_WALK (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*minimum = *natural = (int) ceilf (self->bounds.size.width);
else
*minimum = *natural = (int) ceilf (self->bounds.size.height);
}
static void
gtk_path_walk_set_n_points (GtkPathWalk *self,
gsize n_points)
{
if (self->n_points == n_points)
return;
self->n_points = n_points;
gtk_widget_queue_draw (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_POINTS]);
}
static void
gtk_path_walk_set_path (GtkPathWalk *self,
GskPath *path)
{
if (self->path == path)
return;
g_clear_pointer (&self->path, gsk_path_unref);
graphene_rect_init (&self->bounds, 0, 0, 0, 0);
if (path)
{
GskStroke *stroke;
self->path = gsk_path_ref (path);
stroke = gsk_stroke_new (2.0);
gsk_path_get_stroke_bounds (path, stroke, &self->bounds);
gsk_stroke_free (stroke);
self->measure = gsk_path_measure_new (self->path);
}
gtk_widget_queue_resize (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PATH]);
}
static void
gtk_path_walk_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkPathWalk *self = GTK_PATH_WALK (object);
switch (prop_id)
{
case PROP_N_POINTS:
gtk_path_walk_set_n_points (self, g_value_get_uint (value));
break;
case PROP_PATH:
gtk_path_walk_set_path (self, g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_walk_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkPathWalk *self = GTK_PATH_WALK (object);
switch (prop_id)
{
case PROP_N_POINTS:
g_value_set_uint (value, self->n_points);
break;
case PROP_PATH:
g_value_set_boxed (value, self->path);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_walk_dispose (GObject *object)
{
GtkPathWalk *self = GTK_PATH_WALK (object);
g_clear_pointer (&self->path, gsk_path_unref);
g_clear_pointer (&self->measure, gsk_path_measure_unref);
g_clear_pointer (&self->arrow_path, gsk_path_unref);
G_OBJECT_CLASS (gtk_path_walk_parent_class)->dispose (object);
}
static void
gtk_path_walk_class_init (GtkPathWalkClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_path_walk_dispose;
object_class->set_property = gtk_path_walk_set_property;
object_class->get_property = gtk_path_walk_get_property;
widget_class->snapshot = gtk_path_walk_snapshot;
widget_class->measure = gtk_path_walk_measure;
properties[PROP_N_POINTS] =
g_param_spec_uint ("n-points",
NULL, NULL,
1, G_MAXUINT,
500,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
properties[PROP_PATH] =
g_param_spec_boxed ("path",
NULL, NULL,
GSK_TYPE_PATH,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static gboolean
tick_tick_tick (GtkWidget *self,
GdkFrameClock *frame_clock,
gpointer unused)
{
gtk_widget_queue_draw (GTK_WIDGET (self));
return G_SOURCE_CONTINUE;
}
static void
gtk_path_walk_init (GtkPathWalk *self)
{
/* Data taken from
* https://commons.wikimedia.org/wiki/Maps_of_the_world#/media/File:Simplified_blank_world_map_without_Antartica_(no_borders).svg
*/
GBytes *data = g_resources_lookup_data ("/path_walk/path_world.txt", 0, NULL);
GskPath *path = gsk_path_parse (g_bytes_get_data (data, NULL));
g_bytes_unref (data);
gtk_path_walk_set_path (self, path);
gsk_path_unref (path);
self->arrow_path = gsk_path_parse ("M 5 0 L 0 -5. 0 -2, -5 -2, -5 2, 0 2, 0 5 Z");
self->n_points = 500;
gtk_widget_add_tick_callback (GTK_WIDGET (self), tick_tick_tick, NULL, NULL);
}
GtkWidget *
gtk_path_walk_new (void)
{
GtkPathWalk *self;
self = g_object_new (GTK_TYPE_PATH_WALK, NULL);
return GTK_WIDGET (self);
}
GtkWidget *
do_path_walk (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkBuilder *builder;
g_type_ensure (GTK_TYPE_PATH_WALK);
builder = gtk_builder_new_from_resource ("/path_walk/path_walk.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window));
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">World Map</property>
<property name="titlebar">
<object class="GtkHeaderBar">
<child type="end">
<object class="GtkSpinButton">
<property name="adjustment">
<object class="GtkAdjustment" id="adjustment">
<property name="lower">0</property>
<property name="upper">5000</property>
<property name="value">500</property>
</object>
</property>
</object>
</child>
</object>
</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkPathWalk" id="view">
<property name="n-points" bind-source="adjustment" bind-property="value"/>
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
</child>
</object>
</property>
</object>
</interface>

File diff suppressed because one or more lines are too long

2218
demos/gtk-demo/tiger.node Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -147,6 +147,19 @@ 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 the default color node, but created with the
bounds of the path.
### glshader
| property | syntax | default | printed |
@@ -289,6 +302,24 @@ 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 the default color node, but created with the
stroke bounds of the path.
### text
| property | syntax | default | printed |

View File

@@ -32,7 +32,34 @@ show_class_hierarchy = true
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
[extra]
content_files = [
"paths.md",
]
content_images = [
"gtk-logo.svg",
"images/arc-dark.png",
"images/arc-light.png",
"images/caps-dark.png",
"images/caps-light.png",
"images/conic-light.png",
"images/conic-dark.png",
"images/cubic-dark.png",
"images/cubic-light.png",
"images/curvature-dark.png",
"images/curvature-light.png",
"images/directions-dark.png",
"images/directions-light.png",
"images/fill-even-odd.png",
"images/fill-winding.png",
"images/join-dark.png",
"images/join-light.png",
"images/line-dark.png",
"images/line-light.png",
"images/path-dark.png",
"images/path-light.png",
"images/quad-dark.png",
"images/quad-light.png",
"images/stroke-miter.png",
"images/stroke-round.png",
]
urlmap_file = "urlmap.js"

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -0,0 +1,92 @@
<?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="arcto.svg"
inkscape:export-filename="cubic-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="399.39592"
inkscape:cy="466.51023"
inkscape:window-width="1920"
inkscape:window-height="1123"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showgrid="false" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
d="M 58.033485,123.96862 C 75.231194,113.95411 92.489919,103.26728 107.81401,113.89786"
id="path3"
sodipodi:nodetypes="cc" />
<ellipse
style="fill:none;stroke:#000000;stroke-width:0.20061772;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2"
cx="-16.837238"
cy="154.55043"
rx="35.832706"
ry="17.920988"
transform="matrix(0.86643544,-0.49928912,0.59215321,0.8058254,0,0)" />
<path
style="fill:none;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
d="M 57.432798,124.38759 86.59638,102.1496 107.25717,113.71009"
id="path1"
sodipodi:nodetypes="ccc" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-9"
cx="86.580566"
cy="102.81618"
r="1.5" />
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 45.061871,134.70541 12.60825,-10.20893"
id="path4-4"
sodipodi:nodetypes="cc" />
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"
d="m 35.405008,142.35717 8.95641,-7.26298"
id="path4-8-8"
sodipodi:nodetypes="cc" />
<circle
style="fill:#818181;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-61-1"
cx="57.597607"
cy="124.23325"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-6-5"
cx="108.01463"
cy="114.17829"
r="1.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,81 @@
<?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="caps.svg"
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="2.1493149"
inkscape:cx="438.74445"
inkscape:cy="288.69664"
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">
<linearGradient
id="swatch1"
inkscape:swatch="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop1" />
</linearGradient>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:#000064;stroke-width:1;stroke-miterlimit:0;stroke-dasharray:none"
d="m 73.096455,77.084329 c 0,0 6.439436,18.711677 18.172676,26.635721"
id="path1"
sodipodi:nodetypes="cc" />
<path
style="color:#000000;fill:none;stroke:#000064;stroke-width:0.2;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 94.214979,99.722163 c -4.705477,-3.177832 -9.013472,-9.233699 -11.888672,-14.531169 -2.8752,-5.29748 -4.353516,-9.587833 -4.353516,-9.587833 L 68.51576,78.85704 c 0,0 1.743663,5.064163 5.021484,11.103457 3.277822,6.039297 8.05428,13.302573 15.082031,18.048773"
id="path1-1"
sodipodi:nodetypes="csccsc" />
<path
style="fill:none;stroke:#000064;stroke-width:1;stroke-miterlimit:0;stroke-dasharray:none"
d="m 112.14213,75.736452 c 0,0 6.43944,18.711675 18.17268,26.635728"
id="path1-4"
sodipodi:nodetypes="cc" />
<path
style="color:#000000;fill:none;stroke:#000064;stroke-width:0.2;stroke-linecap:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1"
d="m 132.83284,98.590758 c -4.70551,-3.177807 -9.01347,-9.233742 -11.88867,-14.53125 -2.8752,-5.297508 -4.35351,-9.587891 -4.35351,-9.587891 -0.89828,-2.611719 -3.74396,-4.000453 -6.35547,-3.101562 -2.61172,0.898277 -4.00046,3.743958 -3.10157,6.355468 0,0 1.74367,5.064185 5.02149,11.103516 3.27782,6.039331 8.05428,13.302641 15.08203,18.048851"
id="path1-4-5"
sodipodi:nodetypes="cscccsc" />
<path
style="fill:none;stroke:#000064;stroke-width:1;stroke-miterlimit:0;stroke-dasharray:none"
d="m 154.10911,73.84561 c 0,0 6.43943,18.711677 18.17267,26.63572"
id="path1-0"
sodipodi:nodetypes="cc" />
<path
style="color:#000000;fill:none;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="M 175.16683,96.47344 C 170.46135,93.295592 166.1514,87.239699 163.2762,81.94219 160.401,76.644682 158.92269,72.3543 158.92269,72.3543 l -1.62696,-4.728516 -9.45508,3.253906 1.62696,4.728516 c 0,0 1.74171,5.066138 5.01953,11.105469 3.27782,6.039331 8.05428,13.300675 15.08203,18.046895"
id="path1-4-1"
sodipodi:nodetypes="csccccsc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,93 @@
<?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="conic.svg"
inkscape:export-filename="path-dark.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="1.5197952"
inkscape:cx="397.75096"
inkscape:cy="525.39974"
inkscape:window-width="1920"
inkscape:window-height="1123"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showgrid="false" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:#8b8b8b;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 66.52304,196.79607 c 27.88945,-10.42358 28.400227,-11.25919 57.24918,-4.59693"
id="path5-7-6"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#848484;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 66.150275,196.9925 c 28.059619,-18.89157 28.355331,-21.42218 57.249175,-4.59693"
id="path5"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 65.439496,197.17632 30.328009,-21.33704 28.506125,16.61621"
id="path6" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 66.25585,197.17683 c 29.459015,-15.97487 29.941733,-16.52508 57.24918,-4.59693"
id="path5-7"
sodipodi:nodetypes="cc" />
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 52.936092,207.66575 12.60825,-10.20893"
id="path4"
sodipodi:nodetypes="cc" />
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"
d="m 43.279229,215.31751 8.95641,-7.26298"
id="path4-8"
sodipodi:nodetypes="cc" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7"
cx="95.69075"
cy="175.70657"
r="1.5" />
<circle
style="fill:#818181;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-61"
cx="65.471832"
cy="197.19359"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-6"
cx="123.73506"
cy="192.49165"
r="1.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@@ -0,0 +1,90 @@
<?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="cubic.svg"
inkscape:export-filename="path-dark.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="398.73794"
inkscape:cy="466.51023"
inkscape:window-width="1920"
inkscape:window-height="1123"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showgrid="false" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 65.680232,196.81045 31.85267,-27.20583 3.379138,46.6055 23.3915,-31.31401"
id="path6"
sodipodi:nodetypes="cccc" />
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 52.936092,207.66575 12.60825,-10.20893"
id="path4"
sodipodi:nodetypes="cc" />
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"
d="m 43.279229,215.31751 8.95641,-7.26298"
id="path4-8"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 65.857856,197.15027 c 31.390863,-27.80022 35.053874,18.93262 59.490604,-13.30694"
id="path5"
sodipodi:nodetypes="cc" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7"
cx="97.246689"
cy="169.65689"
r="1.5" />
<circle
style="fill:#818181;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-61"
cx="65.471832"
cy="197.19359"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-6"
cx="101.05927"
cy="215.75879"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-6-3"
cx="124.97194"
cy="184.30319"
r="1.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -0,0 +1,65 @@
<?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="curvature.svg"
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="1.0746575"
inkscape:cx="396.87064"
inkscape:cy="561.57428"
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" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
d="m 61.499887,117.85302 0.05055,-14.89554"
id="path3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
d="m 47.704374,176.11887 c 0,0 -17.048386,-67.06278 9.674156,-72.76426 29.478854,-6.289566 30.433539,55.72526 58.46942,50.81836"
id="path1"
sodipodi:nodetypes="csc" />
<ellipse
style="fill:none;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2"
cy="117.87344"
cx="61.445835"
rx="14.692688"
ry="14.525347" />
<circle
style="fill:#818181;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"
cx="61.42588"
cy="117.79034"
r="1.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,328 @@
<?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="1.0746575"
inkscape:cx="371.28108"
inkscape:cy="266.59657"
inkscape:window-width="1920"
inkscape:window-height="1123"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showgrid="false" />
<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,170.91959 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,53.839137 130.44855,69.048774"
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,133.73955 141.43055,133.1318"
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:300;font-stretch:normal;font-size:3.88055556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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="99.90786"
y="24.737305"
id="text4"><tspan
sodipodi:role="line"
id="tspan4"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88055556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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="99.90786"
y="24.737305">GSK_PATH_FROM_START</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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.84389"
y="128.82414"
id="text4-5"><tspan
sodipodi:role="line"
id="tspan4-7"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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="142.84389"
y="128.82414">GSK_PATH_FROM_START</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88055556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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="29.309605"
y="100.65614"
id="text5"><tspan
sodipodi:role="line"
id="tspan5"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88055556px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.2"
x="29.309605"
y="100.65614">GSK_PATH_TO_START</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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="14.843884"
y="141.82414"
id="text5-8"><tspan
sodipodi:role="line"
id="tspan5-8"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.2"
x="14.843884"
y="141.82414">GSK_PATH_TO_START</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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="70.811882"
id="text6"><tspan
sodipodi:role="line"
id="tspan6"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.2"
x="135.70834"
y="70.811882">GSK_PATH_TO_END</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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.84389"
y="141.82416"
id="text6-6"><tspan
sodipodi:role="line"
id="tspan6-2"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.2"
x="142.84389"
y="141.82416">GSK_PATH_TO_END</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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="14.843884"
y="48.774254"
id="text7"><tspan
sodipodi:role="line"
id="tspan7"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.2"
x="14.843884"
y="48.774254">GSK_PATH_FROM_END</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';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="14.843884"
y="128.82414"
id="text7-5"><tspan
sodipodi:role="line"
id="tspan7-9"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.88056px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Light';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.2"
x="14.843884"
y="128.82414">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="133.30902"
r="1.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,72 @@
<?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="join.svg"
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="118.43701"
inkscape:cy="570.47161"
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" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:#000064;stroke-width:1;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none"
d="m 12.748727,122.15935 c 4.449842,-15.44496 4.175632,-15.92044 16.908788,-26.568585 0,0 8.478091,16.421195 35.150804,33.660325"
id="path1"
sodipodi:nodetypes="ccc" />
<path
style="color:#000000;fill:none;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 17.59375,123.72266 c 3.810222,-13.2249 3.591775,-14.13123 11.107422,-20.53516 1.289688,1.82186 2.604788,3.71164 4.800781,6.23242 5.743296,6.59272 14.891452,15.32766 28.632813,24.20899 M 67.5625,125.23047 C 54.631174,116.87268 46.204933,108.77726 41.041016,102.84961 35.877098,96.921954 34.140625,93.474609 34.140625,93.474609 l -2.861328,-5.544922 -4.789063,4.003907 C 13.673794,102.6514 12.411529,105.58692 7.984375,120.95313"
id="path1-3"
sodipodi:nodetypes="ccsccscccc" />
<path
style="fill:none;stroke:#000064;stroke-width:1;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none"
d="m 147.99215,122.60257 c 4.44988,-15.44499 4.17566,-15.92048 16.90889,-26.568657 0,0 8.47814,16.421267 35.15101,33.660397"
id="path1-5"
sodipodi:nodetypes="ccc" />
<path
style="color:#000000;fill:none;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 152.79687,123.98633 c 3.81053,-13.22586 3.59005,-14.12993 11.10743,-20.53516 1.28968,1.82184 2.6029,3.71173 4.79882,6.23242 5.74333,6.59274 14.89333,15.32961 28.63477,24.21094 m 5.42773,-8.40039 c -12.9314,-8.35778 -21.35753,-16.45123 -26.52148,-22.37891 -5.16395,-5.927668 -6.90039,-9.374996 -6.90039,-9.374996 l -7.65039,-1.541015 C 148.87685,102.91706 147.61469,105.85252 143.1875,121.21875"
id="path1-5-8"
sodipodi:nodetypes="ccsccsccc" />
<path
style="fill:none;stroke:#000064;stroke-width:1;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none"
d="m 79.729342,122.0734 c 4.449844,-15.44499 4.175634,-15.92048 16.908794,-26.568654 0,0 8.478114,16.421264 35.150984,33.660394"
id="path1-7"
sodipodi:nodetypes="ccc" />
<path
style="color:#000000;fill:none;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 84.533203,123.19336 c 3.810222,-13.22495 3.591776,-14.1312 11.107422,-20.53516 1.289696,1.82187 2.604775,3.71164 4.800785,6.23243 5.74333,6.59275 14.89136,15.32765 28.63281,24.20898 m 5.42969,-8.39844 c -12.93141,-8.35778 -21.35949,-16.45122 -26.52344,-22.3789 -5.16395,-5.927686 -6.90039,-9.375004 -6.90039,-9.375004 -0.69636,-1.348401 -1.967393,-2.307601 -3.45508,-2.607422 -1.487509,-0.300132 -3.03083,0.09145 -4.195313,1.064453 C 80.61325,102.12215 79.350982,105.05756 74.923828,120.42383"
id="path1-7-4"
sodipodi:nodetypes="ccsccscccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,73 @@
<?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="line.svg"
inkscape:export-filename="line-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="398.73794"
inkscape:cy="466.51023"
inkscape:window-width="1920"
inkscape:window-height="1123"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showgrid="false" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 52.936092,207.66575 12.60825,-10.20893"
id="path4"
sodipodi:nodetypes="cc" />
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"
d="m 43.279229,215.31751 8.95641,-7.26298"
id="path4-8"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 66.150275,196.9925 40.275255,-5.24977"
id="path5"
sodipodi:nodetypes="cc" />
<circle
style="fill:#818181;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-61"
cx="65.471832"
cy="197.19359"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-6"
cx="106.42249"
cy="191.8156"
r="1.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,108 @@
<?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="path.svg"
inkscape:export-filename="path-dark.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="397.42198"
inkscape:cy="561.25984"
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" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="M 128.28233,149.47912 154.23127,90.244656 86.340809,68.820468"
id="path3" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;fill-opacity:1;stroke-dasharray:none;stroke-opacity:1"
d="m 33.956804,113.31099 c -9.049189,-11.90893 5.40551,-40.570358 20.351208,-39.990271 26.687501,1.035822 4.06495,71.984581 30.695656,74.009711 19.642072,1.49368 41.962402,-34.42048 30.634382,-50.536241 C 99.663884,74.068616 50.763019,135.42833 33.956804,113.31099 Z"
id="path1"
sodipodi:nodetypes="sssss" />
<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"
cx="34.517788"
cy="113.66589"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8"
cx="55.045853"
cy="73.566689"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-5"
cx="55.045834"
cy="73.831245"
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"
cx="55.045834"
cy="73.831245"
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"
cx="86.398613"
cy="68.897667"
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-8"
cx="153.87553"
cy="90.112595"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7"
cx="84.803238"
cy="147.51736"
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-7-2"
cx="115.28235"
cy="96.705284"
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-9"
cx="127.92362"
cy="150.03427"
r="1.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -0,0 +1,83 @@
<?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="path.svg"
inkscape:export-filename="path-dark.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="398.07996"
inkscape:cy="466.51023"
inkscape:window-width="1920"
inkscape:window-height="1123"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showgrid="false" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 52.936092,207.66575 12.60825,-10.20893"
id="path4"
sodipodi:nodetypes="cc" />
<path
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"
d="m 43.279229,215.31751 8.95641,-7.26298"
id="path4-8"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="M 66.150275,196.9925 C 86.276878,182.17569 104.9512,180.54783 123.39945,192.39557"
id="path5"
sodipodi:nodetypes="cc" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7"
cx="95.69075"
cy="175.70657"
r="1.5" />
<circle
style="fill:#818181;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-61"
cx="65.471832"
cy="197.19359"
r="1.5" />
<circle
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
id="path2-8-7-6"
cx="123.73506"
cy="192.49165"
r="1.5" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 65.439496,197.17632 30.328009,-21.33704 28.506125,16.61621"
id="path6" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,3 +1,7 @@
gsk_expand_content_md_files = [
'paths.md',
]
if get_option('documentation')
gsk4_toml = configure_file(
input: 'gsk4.toml.in',
@@ -21,7 +25,7 @@ if get_option('documentation')
'@INPUT1@',
],
depends: [ gdk_gir[0] ],
depend_files: [ expand_content_md_files ],
depend_files: [ gsk_expand_content_md_files ],
build_by_default: true,
install: true,
install_dir: docs_dir,

174
docs/reference/gsk/paths.md Normal file
View File

@@ -0,0 +1,174 @@
Title: Paths
Slug: paths
GSK provides a path API that can be used to render more complex
shapes than lines or rounded rectangles. It is comparable to cairos
[path API](https://www.cairographics.org/manual/cairo-Paths.html),
with some notable differences.
In general, a path consists of one or more connected **_contours_**,
each of which may have multiple **_operations_**, and may or may not be closed.
Operations can be straight lines or curves of various kinds. At the points
where the operations connect, the path can have sharp turns.
<figure>
<picture>
<source srcset="path-dark.png" media="(prefers-color-scheme: dark)">
<img alt="A path with multiple contours" src="path-light.png">
</picture>
<figcaption>A path with one closed, and one open contour</figcaption>
</figure>
The central object of the GSK path API is the immutable [struct@Gsk.Path]
struct, which contains path data in compact form suitable for rendering.
## Creating Paths
Since `GskPath` is immutable, the auxiliary [struct@Gsk.PathBuilder] struct
can be used to construct a path piece by piece. The pieces are specified with
points, some of which will be on the path, while others are just **_control points_**
that are used to influence the shape of the resulting path.
<figure>
<picture>
<source srcset="cubic-dark.png" media="(prefers-color-scheme: dark)">
<img alt="An cubic Bézier" src="cubic-light.png">
</picture>
<figcaption>A cubic Bézier operation, with 2 control points</figcaption>
</figure>
The `GskPathBuilder` API has three distinct groups of functions:
- Functions for building contours from individual operations, like [method@Gsk.PathBuilder.move_to],
[method@Gsk.PathBuilder.line_to], [method@Gsk.PathBuilder.cubic_to], [method@Gsk.PathBuilder.close]. `GskPathBuilder` maintains a **_current point_**, so these methods all
take one less points than necessary for the operation (e.g. `gsk_path_builder_line_to`
only takes a single point and draws a line from the current point to the new point).
- Functions for adding complete contours, such as [method@Gsk.PathBuilder.add_rect],
[method@Gsk.PathBuilder.add_rounded_rect], [method@Gsk.PathBuilder.add_circle].
- Adding parts of a preexisting path. Functions in this group include
[method@Gsk.PathBuilder.add_path] and [method@Gsk.PathBuilder.add_segment].
When you are done with building a path, you can convert the accumulated path
data into a `GskPath` struct with [method@Gsk.PathBuilder.free_to_path].
A sometimes convenient alternative is to create a path from a serialized form,
with [func@Gsk.Path.parse]. This function interprets strings in SVG path syntax,
such as:
M 100 100 C 100 200 200 200 200 100 Z
## Rendering with Paths
There are two main ways to render with paths. The first is to **_fill_** the
interior of a path with a color or more complex content, such as a gradient.
GSK supports different ways of determining what part of the plane are interior
to the path, which can be selected with a [enum@Gsk.FillRule] value.
<figure>
<picture>
<img alt="A filled path" src="fill-winding.png">
</picture>
<figcaption>A path filled with GSK_FILL_RULE_WINDING</figcaption>
</figure>
<figure>
<picture>
<img alt="A filled path" src="fill-even-odd.png">
</picture>
<figcaption>The same path, filled with GSK_FILL_RULE_EVEN_ODD</figcaption>
</figure>
To fill a path, use [gtk_snapshot_append_fill()](../gtk4/method.Snapshot.append_fill.html)
or the more general [gtk_snapshot_push_fill()](../gtk4/method.Snapshot.push_fill.html).
Alternatively, a path can be **_stroked_**, which means to emulate drawing
with an idealized pen along the path. The result of stroking a path is another
path (the **_stroke path_**), which is then filled.
The stroke operation can be influenced with the [struct@Gsk.Stroke] struct
that collects various stroke parameters, such as the line width, the style
of line joins and line caps, and a dash pattern.
<figure>
<picture>
<img alt="A stroked path" src="stroke-miter.png">
</picture>
<figcaption>The same path, stroked with GSK_LINE_JOIN_MITER</figcaption>
</figure>
<figure>
<picture>
<img alt="A stroked path" src="stroke-round.png">
</picture>
<figcaption>The same path, stroked with GSK_LINE_JOIN_ROUND</figcaption>
</figure>
To stroke a path, use
[gtk_snapshot_append_stroke()](../gtk4/method.Snapshot.append_stroke.html)
or [gtk_snapshot_push_stroke()](../gtk4/method.Snapshot.push_stroke.html).
## Hit testing
When paths are rendered as part of an interactive interface, it is sometimes
necessary to determine whether the mouse points is over the path. GSK provides
[method@Gsk.Path.in_fill] for this purpose.
## Path length
An important property of paths is their **_length_**. Computing it efficiently
requires caching, therefore GSK provides a separate [struct@Gsk.PathMeasure] object
to deal with path lengths. After constructing a `GskPathMeasure` object for a path,
it can be used to determine the length of the path with [method@Gsk.PathMeasure.get_length]
and locate points at a given distance into the path with [method@Gsk.PathMeasure.get_point].
## Other Path APIs
Paths have uses beyond rendering, for example as trajectories in animations.
In such uses, it is often important to access properties of paths, such as
their tangents at certain points. GSK provides an abstract representation
for points on a path in the form of the [struct@Gsk.PathPoint] struct.
You can query properties of a path at certain point once you have a
`GskPathPoint` representing that point.
`GskPathPoint` structs can be compared for equality with [method@Gsk.PathPoint.equal]
and ordered wrt. to which one comes first, using [method@Gsk.PathPoint.compare].
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].
To query properties of the path at a point, use [method@Gsk.PathPoint.get_position],
[method@Gsk.PathPoint.get_tangent], [method@Gsk.PathPoint.get_rotation],
[method@Gsk.PathPoint.get_curvature] and [method@Gsk.PathPoint.get_distance].
Some of the properties can have different values for the path going into
the point and the path leaving the point, typically at points where the
path takes sharp turns. Examples for this are tangents (which can have up
to 4 different values) and curvatures (which can have two different values).
<figure>
<picture>
<source srcset="directions-dark.png" media="(prefers-color-scheme: dark)">
<img alt="Path Tangents" src="directions-light.png">
</picture>
<figcaption>Path Tangents</figcaption>
</figure>
## Going beyond GskPath
Lots of powerful functionality can be implemented for paths:
- Finding intersections
- Offsetting curves
- Turning stroke outlines into paths
- Molding curves (making them pass through a given point)
GSK does not provide API for all of these, but it does offer a way to get at
the underlying Bézier curves, so you can implement such functionality yourself.
You can use [method@Gsk.Path.foreach] to iterate over the operations of the
path, and get the points needed to reconstruct or modify the path piece by piece.
See e.g. the [Primer on Bézier curves](https://pomax.github.io/bezierinfo/)
for inspiration of useful things to explore.

View File

@@ -0,0 +1,200 @@
.. _gtk4-path-tool(1):
=================
gtk4-path-tool
=================
-----------------------
GskPath Utility
-----------------------
SYNOPSIS
--------
| **gtk4-path-tool** <COMMAND> [OPTIONS...] <PATH>
|
| **gtk4-path-tool** decompose [OPTIONS...] <PATH>
| **gtk4-path-tool** show [OPTIONS...] <PATH>
| **gtk4-path-tool** render [OPTIONS...] <PATH>
| **gtk4-path-tool** reverse [OPTIONS...] <PATH>
| **gtk4-path-tool** info [OPTIONS...] <PATH>
DESCRIPTION
-----------
``gtk4-path-tool`` can perform various tasks on paths. Paths are specified
in SVG syntax, as strings like "M 100 100 C 100 200 200 200 200 100 Z".
To read a path from a file, use a filename that starts with a '.' or a '/'.
To read a path from stdin, use '-'.
COMMANDS
--------
Decomposing
^^^^^^^^^^^
The ``decompose`` command approximates the path by one with simpler elements.
When used without options, the curves of the path are approximated by line
segments.
``--allow-quad``
Allow quadratic Bézier curves to be used in the generated path.
``--allow-cubic``
Allow cubic Bézier curves to be used in the generated path.
``--allow-conic``
Allow conic Bézier curves to be used in the generated path.
Showing
^^^^^^^
The ``show`` command displays the given path in a window. The interior
of the path is filled.
``--fill-rule=VALUE``
The fill rule that is used to determine what areas are inside the path.
The possible values are ``winding`` or ``even-odd``. The default is ``winding``.
``--fg-color=COLOR``
The color that is used to fill the interior of the path or stroke the path.
If not specified, black is used.
``--bg-color=COLOR``
The color that is used to render the background behind the path.
If not specified, white is used.
``--fill``
Fill the path (this is the default).
``--stroke``
Stroke the path instead of filling it.
``--line-width=VALUE``
The line width to use for the stroke. ``VALUE`` must be a positive number.
The default line width is 1.
``--line-cap=VALUE``
The cap style to use at line ends. The possible values are ``butt``, ``round``
or ``square``. See the SVG specification for details on these styles.
The default cap style is ``butt``.
``--line-join=VALUE``
The join style to use at line joins. The possible values are ``miter``,
``miter-clip``, ``round``, ``bevel`` or ``arcs``. See the SVG specification
for details on these styles.
The default join style is ``miter``.
``--miter-limit=VALUE``
The limit at which to clip miters at line joins. The default value is 4.
``--dashes=VALUE``
The dash pattern to use for this stroke. A dash pattern is specified by
a comma-separated list of alternating non-negative numbers. Each number
provides the length of alternate "on" and "off" portions of the stroke.
If the dash pattern is empty, dashing is disabled, which is the default.
See the SVG specification for details on dashing.
``--dash-offset=VALUE``
The offset into the dash pattern where dashing should begin.
The default value is 0.
Rendering
^^^^^^^^^
The ``render`` command renders the given path as a PNG image.
The interior of the path is filled.
``--fill-rule=VALUE``
The fill rule that is used to determine what areas are inside the path.
The possible values are ``winding`` or ``even-odd``. The default is ``winding``.
``--fg-color=COLOR``
The color that is used to fill the interior of the path or stroke the path.
If not specified, black is used.
``--bg-color=COLOR``
The color that is used to render the background behind the path.
If not specified, white is used.
``--output-file=FILE``
The file to save the PNG image to.
If not specified, "path.png" is used.
``--fill``
Fill the path (this is the default).
``--stroke``
Stroke the path instead of filling it.
``--line-width=VALUE``
The line width to use for the stroke. ``VALUE`` must be a positive number.
The default line width is 1.
``--line-cap=VALUE``
The cap style to use at line ends. The possible values are ``butt``, ``round``
or ``square``. See the SVG specification for details on these styles.
The default cap style is ``butt``.
``--line-join=VALUE``
The join style to use at line joins. The possible values are ``miter``,
``miter-clip``, ``round``, ``bevel`` or ``arcs``. See the SVG specification
for details on these styles.
The default join style is ``miter``.
``--miter-limit=VALUE``
The limit at which to clip miters at line joins. The default value is 4.
``--dashes=VALUE``
The dash pattern to use for this stroke. A dash pattern is specified by
a comma-separated list of alternating non-negative numbers. Each number
provides the length of alternate "on" and "off" portions of the stroke.
If the dash pattern is empty, dashing is disabled, which is the default.
See the SVG specification for details on dashing.
``--dash-offset=VALUE``
The offset into the dash pattern where dashing should begin.
The default value is 0.
Reversing
^^^^^^^^^
The ``reverse`` command changes the direction of the path. The resulting
paths starts where the original path ends.
Info
^^^^
The ``info`` command shows various information about the given path,
such as its bounding box.
REFERENCES
----------
- SVG Path Specification, https://www.w3.org/TR/SVG2/paths.html

View File

@@ -77,6 +77,7 @@ if get_option('man-pages') and rst2man.found()
[ 'gtk4-query-settings', '1', ],
[ 'gtk4-rendernode-tool', '1' ],
[ 'gtk4-update-icon-cache', '1', ],
[ 'gtk4-path-tool', '1', ],
]
if get_option('demos')

View File

@@ -222,7 +222,7 @@ It is possible to set accessible attributes in UI files as well:
<accessibility>
<property name="label">Download</property>
<relation name="labelled-by">label1</relation>
/accessibility>
</accessibility>
</object>
```

View File

@@ -297,7 +297,7 @@ gdk_clipboard_read_local_async (GdkClipboard *clipboard,
{
GOutputStream *output_stream;
GIOStream *stream;
stream = gdk_pipe_io_stream_new ();
output_stream = g_io_stream_get_output_stream (stream);
gdk_clipboard_write_async (clipboard,
@@ -767,7 +767,7 @@ gdk_clipboard_read_value_internal (GdkClipboard *clipboard,
GdkContentFormats *formats;
GValue *value;
GTask *task;
task = g_task_new (clipboard, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
g_task_set_source_tag (task, source_tag);
@@ -946,7 +946,7 @@ gdk_clipboard_read_texture_finish (GdkClipboard *clipboard,
value = g_task_propagate_pointer (G_TASK (result), error);
if (!value)
return NULL;
return g_value_dup_object (value);
}
@@ -1011,7 +1011,7 @@ gdk_clipboard_read_text_finish (GdkClipboard *clipboard,
value = g_task_propagate_pointer (G_TASK (result), error);
if (!value)
return NULL;
return g_value_dup_string (value);
}
@@ -1110,7 +1110,7 @@ gdk_clipboard_write_async (GdkClipboard *clipboard,
GError *error = NULL;
g_assert (gtype != G_TYPE_INVALID);
g_value_init (&value, gtype);
if (gdk_content_provider_get_value (priv->content, &value, &error))
{
@@ -1126,7 +1126,7 @@ gdk_clipboard_write_async (GdkClipboard *clipboard,
{
g_task_return_error (task, error);
}
g_value_unset (&value);
}
else
@@ -1148,7 +1148,7 @@ gdk_clipboard_write_finish (GdkClipboard *clipboard,
g_return_val_if_fail (g_task_is_valid (result, clipboard), FALSE);
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_clipboard_write_async, FALSE);
return g_task_propagate_boolean (G_TASK (result), error);
return g_task_propagate_boolean (G_TASK (result), error);
}
static gboolean
@@ -1248,8 +1248,8 @@ gdk_clipboard_set_content (GdkClipboard *clipboard,
* Sets the clipboard to contain the value collected from the given varargs.
*
* Values should be passed the same way they are passed to other value
* collecting APIs, such as [`method@GObject.Object.set`] or
* [`func@GObject.signal_emit`].
* collecting APIs, such as [method@GObject.Object.set] or
* [func@GObject.signal_emit].
*
* ```c
* gdk_clipboard_set (clipboard, GTK_TYPE_STRING, "Hello World");
@@ -1263,7 +1263,7 @@ gdk_clipboard_set (GdkClipboard *clipboard,
...)
{
va_list args;
g_return_if_fail (GDK_IS_CLIPBOARD (clipboard));
va_start (args, type);

View File

@@ -1528,7 +1528,8 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
if (gdk_gl_context_get_use_es (context))
{
priv->has_unpack_subimage = epoxy_has_gl_extension ("GL_EXT_unpack_subimage");
priv->has_unpack_subimage = gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)) ||
epoxy_has_gl_extension ("GL_EXT_unpack_subimage");
priv->has_khr_debug = epoxy_has_gl_extension ("GL_KHR_debug");
}
else

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;
}
@@ -153,7 +159,7 @@ gdk_gl_texture_find_format (gboolean use_es,
if (gdk_memory_format_alpha (format) != alpha)
continue;
if (!gdk_memory_format_gl_format (format, use_es, gl_major, gl_minor, &q_internal_format, &q_format, &q_type, &q_swizzle))
if (!gdk_memory_format_gl_format (format, use_es, gl_major, gl_minor, &q_internal_format, &q_format, &q_type, q_swizzle))
continue;
if (q_format != gl_format || q_type != gl_type)
@@ -188,7 +194,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
FALSE,
major, minor,
&gl_internal_format,
&gl_format, &gl_type, &gl_swizzle))
&gl_format, &gl_type, gl_swizzle))
{
if (download->stride == expected_stride &&
download->format == format)

View File

@@ -739,12 +739,12 @@ gdk_memory_format_gl_format (GdkMemoryFormat format,
guint *out_internal_format,
guint *out_format,
guint *out_type,
GLint (*out_swizzle)[4])
GLint out_swizzle[4])
{
*out_internal_format = memory_formats[format].gl.internal_format;
*out_format = memory_formats[format].gl.format;
*out_type = memory_formats[format].gl.type;
memcpy (out_swizzle, &memory_formats[format].gl.swizzle, sizeof(GLint) * 4);
memcpy (out_swizzle, memory_formats[format].gl.swizzle, sizeof(GLint) * 4);
if (gles)
{

View File

@@ -52,7 +52,7 @@ gboolean gdk_memory_format_gl_format (GdkMemoryFormat
guint *out_internal_format,
guint *out_format,
guint *out_type,
GLint (*out_gizzle)[4]);
GLint out_gizzle[4]);
void gdk_memory_convert (guchar *dest_data,
gsize dest_stride,

View File

@@ -25,10 +25,12 @@
#include "gdkprivate.h"
/* HACK: So we don't need to include any (not-yet-created) GSK or GTK headers */
GdkSnapshot * gtk_snapshot_new (void);
void gtk_snapshot_push_debug (GdkSnapshot *snapshot,
const char *message,
...) G_GNUC_PRINTF (2, 3);
void gtk_snapshot_pop (GdkSnapshot *snapshot);
GdkPaintable * gtk_snapshot_free_to_paintable (GdkSnapshot *snapshot);
/**
* GdkPaintable:
@@ -102,9 +104,21 @@ gdk_paintable_default_snapshot (GdkPaintable *paintable,
static GdkPaintable *
gdk_paintable_default_get_current_image (GdkPaintable *paintable)
{
g_warning ("FIXME: implement by snapshotting at default size and returning a GskRendererNodePaintable");
int width, height;
GdkSnapshot *snapshot;
return paintable;
/* No need to check whether the paintable is static, as
* gdk_paintable_get_current_image () takes care of that already. */
width = gdk_paintable_get_intrinsic_width (paintable);
height = gdk_paintable_get_intrinsic_height (paintable);
if (width <= 0 || height <= 0)
return gdk_paintable_new_empty (width, height);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
return gtk_snapshot_free_to_paintable (snapshot);
}
static GdkPaintableFlags

View File

@@ -27,9 +27,7 @@
#include "gdkmacosdisplay.h"
#include "gdkmacossurface.h"
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl3.h>
#import <AppKit/AppKit.h>
#import <epoxy/gl.h>
G_BEGIN_DECLS

View File

@@ -21,7 +21,6 @@
#include "gdkconfig.h"
#include <OpenGL/gl3.h>
#include <OpenGL/CGLIOSurface.h>
#include <QuartzCore/QuartzCore.h>
@@ -499,7 +498,7 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
gdk_macos_gl_context_allocate (self);
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, prefers_high_depth, region);
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, depth, region);
gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
CHECK_GL (NULL, glBindFramebuffer (GL_FRAMEBUFFER, self->fbo));

View File

@@ -331,7 +331,7 @@ _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
gdk_monitor_set_physical_size (GDK_MONITOR (self), width_mm, height_mm);
gdk_monitor_set_scale_factor (GDK_MONITOR (self), scale_factor);
gdk_monitor_set_refresh_rate (GDK_MONITOR (self), refresh_rate);
gdk_monitor_set_subpixel_layout (GDK_MONITOR (self), GDK_SUBPIXEL_LAYOUT_UNKNOWN);
gdk_monitor_set_subpixel_layout (GDK_MONITOR (self), subpixel_layout);
self->workarea = [screen visibleFrame];

View File

@@ -93,7 +93,8 @@ gdk_wayland_app_launch_context_get_startup_notify_id (GAppLaunchContext *context
id = app_launch_data.token;
wl_event_queue_destroy (event_queue);
}
else if (gtk_shell1_get_version (display->gtk_shell) >= GTK_SHELL1_NOTIFY_LAUNCH_SINCE_VERSION)
else if (display->gtk_shell &&
gtk_shell1_get_version (display->gtk_shell) >= GTK_SHELL1_NOTIFY_LAUNCH_SINCE_VERSION)
{
id = g_uuid_string_random ();
gtk_shell1_notify_launch (display->gtk_shell, id);

View File

@@ -127,3 +127,6 @@ libgdk_wayland = static_library('gdk-wayland',
link_with: [ libwayland_cursor, ],
dependencies: [ gdk_deps, gdk_wayland_deps ],
)
# Used to generate pkg-config Requires
wayland_public_deps = [wlclientdep]

View File

@@ -2857,7 +2857,10 @@ gdk_event_translate (MSG *msg,
break;
case WM_SYSCOMMAND:
switch (msg->wParam)
/* 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)
{
case SC_MINIMIZE:
case SC_RESTORE:
@@ -2964,6 +2967,14 @@ 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;

View File

@@ -1230,18 +1230,11 @@ 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 | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
*decoration = GDK_DECOR_ALL;
return TRUE;
}

View File

@@ -201,7 +201,7 @@ gdk_x11_clipboard_formats_to_targets (GdkContentFormats *formats)
continue;
if (g_str_equal (mime_types[i], special_targets[j].mime_type))
targets = g_slist_prepend (targets, (gpointer) g_intern_string (special_targets[j].x_target));
targets = g_slist_prepend (targets, (gpointer) g_intern_static_string (special_targets[j].x_target));
}
targets = g_slist_prepend (targets, (gpointer) mime_types[i]);
}
@@ -238,6 +238,8 @@ gdk_x11_clipboard_formats_to_atoms (GdkDisplay *display,
for (l = targets; l; l = l->next)
atoms[i++] = gdk_x11_get_xatom_by_name_for_display (display, l->data);
g_slist_free (targets);
return atoms;
}

View File

@@ -86,3 +86,5 @@ libgdk_x11 = static_library('gdk-x11',
] + common_cflags,
dependencies: [ gdk_deps, gdk_x11_deps, ],
)
x11_public_deps = [x11_dep]

View File

@@ -271,6 +271,8 @@ collect_reused_child_nodes (GskRenderer *renderer,
case GSK_CROSS_FADE_NODE:
case GSK_BLUR_NODE:
case GSK_MASK_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
default:
@@ -859,6 +861,8 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
case GSK_CROSS_FADE_NODE:
case GSK_BLUR_NODE:
case GSK_GL_SHADER_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
default:
break; /* Fallback */
}

View File

@@ -1456,7 +1456,7 @@ memory_format_gl_format (GdkMemoryFormat data_format,
guint *gl_internalformat,
guint *gl_format,
guint *gl_type,
GLint (*gl_swizzle)[4])
GLint gl_swizzle[4])
{
GdkMemoryDepth depth;
@@ -1577,7 +1577,7 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
&gl_internalformat,
&gl_format,
&gl_type,
&gl_swizzle);
gl_swizzle);
gdk_texture_downloader_init (&downloader, texture);
gdk_texture_downloader_set_format (&downloader, data_format);
@@ -1595,8 +1595,7 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
{
glTexSubImage2D (GL_TEXTURE_2D, 0, x, y, width, height, gl_format, gl_type, data);
}
else if (stride % bpp == 0 &&
(gdk_gl_context_check_version (self->context, NULL, "3.0") || gdk_gl_context_has_unpack_subimage (self->context)))
else if (stride % bpp == 0 && gdk_gl_context_has_unpack_subimage (self->context))
{
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);
@@ -1684,7 +1683,7 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
&gl_internalformat,
&gl_format,
&gl_type,
&gl_swizzle);
gl_swizzle);
glTexImage2D (GL_TEXTURE_2D, 0, gl_internalformat, width, height, 0, gl_format, gl_type, NULL);

View File

@@ -255,6 +255,8 @@ node_supports_2d_transform (const GskRenderNode *node)
case GSK_BLEND_NODE:
case GSK_BLUR_NODE:
case GSK_MASK_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
return TRUE;
case GSK_SHADOW_NODE:
@@ -309,6 +311,8 @@ node_supports_transform (const GskRenderNode *node)
case GSK_BLEND_NODE:
case GSK_BLUR_NODE:
case GSK_MASK_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
return TRUE;
case GSK_SHADOW_NODE:
@@ -1241,9 +1245,9 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
done:
if (scale_x < 0 || scale_y < 0)
{
GskTransform *transform = gsk_transform_translate (NULL,
&GRAPHENE_POINT_INIT (scale_x < 0 ? - surface_width : 0,
scale_y < 0 ? - surface_height : 0));
GskTransform *transform = gsk_transform_translate (gsk_transform_scale (NULL, scale_x < 0 ? -1 : 1, scale_y < 0 ? -1 : 1),
&GRAPHENE_POINT_INIT (scale_x < 0 ? - (node->bounds.size.width + 2 * node->bounds.origin.x) : 0,
scale_y < 0 ? - (node->bounds.size.height + 2 * node->bounds.origin.y) : 0));
gsk_gl_render_job_push_modelview (job, transform);
gsk_transform_unref (transform);
}
@@ -4089,6 +4093,14 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
gsk_gl_render_job_visit_as_fallback (job, node);
break;
case GSK_FILL_NODE:
gsk_gl_render_job_visit_as_fallback (job, node);
break;
case GSK_STROKE_NODE:
gsk_gl_render_job_visit_as_fallback (job, node);
break;
case GSK_NOT_A_RENDER_NODE:
default:
g_assert_not_reached ();

View File

@@ -20,9 +20,14 @@
#define __GSK_H_INSIDE__
#include <gsk/gskenums.h>
#include <gsk/gskpath.h>
#include <gsk/gskpathbuilder.h>
#include <gsk/gskpathmeasure.h>
#include <gsk/gskpathpoint.h>
#include <gsk/gskrenderer.h>
#include <gsk/gskrendernode.h>
#include <gsk/gskroundedrect.h>
#include <gsk/gskstroke.h>
#include <gsk/gsktransform.h>
#include <gsk/gskglshader.h>

115
gsk/gskboundingboxprivate.h Normal file
View File

@@ -0,0 +1,115 @@
#pragma once
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
typedef struct _GskBoundingBox GskBoundingBox;
struct _GskBoundingBox {
graphene_point_t min;
graphene_point_t max;
};
static inline GskBoundingBox *
gsk_bounding_box_init (GskBoundingBox *self,
const graphene_point_t *a,
const graphene_point_t *b)
{
self->min.x = MIN (a->x, b->x);
self->min.y = MIN (a->y, b->y);
self->max.x = MAX (a->x, b->x);
self->max.y = MAX (a->y, b->y);
return self;
}
static inline GskBoundingBox *
gsk_bounding_box_init_copy (GskBoundingBox *self,
const GskBoundingBox *src)
{
self->min = src->min;
self->max = src->max;
return self;
}
static inline GskBoundingBox *
gsk_bounding_box_init_from_rect (GskBoundingBox *self,
const graphene_rect_t *bounds)
{
self->min = bounds->origin;
self->max.x = bounds->origin.x + bounds->size.width;
self->max.y = bounds->origin.y + bounds->size.height;
return self;
}
static inline void
gsk_bounding_box_expand (GskBoundingBox *self,
const graphene_point_t *p)
{
self->min.x = MIN (self->min.x, p->x);
self->min.y = MIN (self->min.y, p->y);
self->max.x = MAX (self->max.x, p->x);
self->max.y = MAX (self->max.y, p->y);
}
static inline graphene_rect_t *
gsk_bounding_box_to_rect (const GskBoundingBox *self,
graphene_rect_t *rect)
{
rect->origin = self->min;
rect->size.width = self->max.x - self->min.x;
rect->size.height = self->max.y - self->min.y;
return rect;
}
static inline gboolean
gsk_bounding_box_contains_point (const GskBoundingBox *self,
const graphene_point_t *p)
{
return self->min.x <= p->x && p->x <= self->max.x &&
self->min.y <= p->y && p->y <= self->max.y;
}
static inline gboolean
gsk_bounding_box_contains_point_with_epsilon (const GskBoundingBox *self,
const graphene_point_t *p,
float epsilon)
{
return self->min.x - epsilon <= p->x && p->x <= self->max.x + epsilon &&
self->min.y - epsilon <= p->y && p->y <= self->max.y + epsilon;
}
static inline gboolean
gsk_bounding_box_intersection (const GskBoundingBox *a,
const GskBoundingBox *b,
GskBoundingBox *res)
{
graphene_point_t min, max;
min.x = MAX (a->min.x, b->min.x);
min.y = MAX (a->min.y, b->min.y);
max.x = MIN (a->max.x, b->max.x);
max.y = MIN (a->max.y, b->max.y);
if (res)
gsk_bounding_box_init (res, &min, &max);
return min.x <= max.x && min.y <= max.y;
}
static inline void
gsk_bounding_box_union (const GskBoundingBox *a,
const GskBoundingBox *b,
GskBoundingBox *res)
{
graphene_point_t min, max;
min.x = MIN (a->min.x, b->min.x);
min.y = MIN (a->min.y, b->min.y);
max.x = MAX (a->max.x, b->max.x);
max.y = MAX (a->max.y, b->max.y);
gsk_bounding_box_init (res, &min, &max);
}
G_END_DECLS

2538
gsk/gskcontour.c Normal file

File diff suppressed because it is too large Load Diff

102
gsk/gskcontourprivate.h Normal file
View File

@@ -0,0 +1,102 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#pragma once
#include "gskpathprivate.h"
#include "gskpathpoint.h"
#include "gskpathopprivate.h"
#include "gskboundingboxprivate.h"
G_BEGIN_DECLS
GskContour * gsk_standard_contour_new (GskPathFlags flags,
const graphene_point_t *points,
gsize n_points,
const gskpathop *ops,
gsize n_ops,
gssize offset);
GskContour * gsk_circle_contour_new (const graphene_point_t *center,
float radius);
GskContour * gsk_rect_contour_new (const graphene_rect_t *rect);
GskContour * gsk_rounded_rect_contour_new (const GskRoundedRect *rounded_rect);
const char * gsk_contour_get_type_name (const GskContour *self);
void gsk_contour_copy (GskContour * dest,
const GskContour *src);
GskContour * gsk_contour_dup (const GskContour *src);
GskContour * gsk_contour_reverse (const GskContour *src);
gsize gsk_contour_get_size (const GskContour *self);
GskPathFlags gsk_contour_get_flags (const GskContour *self);
void gsk_contour_print (const GskContour *self,
GString *string);
gboolean gsk_contour_get_bounds (const GskContour *self,
GskBoundingBox *bounds);
gboolean gsk_contour_get_stroke_bounds (const GskContour *self,
const GskStroke *stroke,
GskBoundingBox *bounds);
gboolean gsk_contour_foreach (const GskContour *self,
GskPathForeachFunc func,
gpointer user_data);
int gsk_contour_get_winding (const GskContour *self,
const graphene_point_t *point);
gsize gsk_contour_get_n_ops (const GskContour *self);
gboolean gsk_contour_get_closest_point (const GskContour *self,
const graphene_point_t *point,
float threshold,
GskPathPoint *result,
float *out_dist);
void gsk_contour_get_position (const GskContour *self,
const GskPathPoint *point,
graphene_point_t *pos);
void gsk_contour_get_tangent (const GskContour *self,
const GskPathPoint *point,
GskPathDirection direction,
graphene_vec2_t *tangent);
float gsk_contour_get_curvature (const GskContour *self,
const GskPathPoint *point,
GskPathDirection direction,
graphene_point_t *center);
void gsk_contour_add_segment (const GskContour *self,
GskPathBuilder *builder,
gboolean emit_move_to,
const GskPathPoint *start,
const GskPathPoint *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 distance,
GskPathPoint *result);
float gsk_contour_get_distance (const GskContour *self,
const GskPathPoint *point,
gpointer measure_data);
gboolean gsk_contour_dash (const GskContour *contour,
GskStroke *stroke,
GskPathForeachFunc func,
gpointer user_data);
G_END_DECLS

272
gsk/gskcurve-ct-values.c Normal file
View File

@@ -0,0 +1,272 @@
/* Legendre-Gauss values,
* see https://pomax.github.io/bezierinfo/legendre-gauss.html
*/
#if defined(USE_64_SAMPLES)
/* n = 64 */
static const double T[] = {
-0.0243502926634244325089558428537156614268871093149758091634531663960566965166295288529853061657116894882370493013671717560479926679408068852617342586968190919443025679363843727751902756254975073084367002129407854253246662805532069172532219089321005870178809284335033318073251039701073379759,
0.0243502926634244325089558428537156614268871093149758091634531663960566965166295288529853061657116894882370493013671717560479926679408068852617342586968190919443025679363843727751902756254975073084367002129407854253246662805532069172532219089321005870178809284335033318073251039701073379759,
-0.0729931217877990394495429419403374932441261816687788533563163323377395217254429050181833064967505478802134768007678458612956459126148837496307967995621683597067400860540057918571357609346700883624064782909888895547912499697295335516804810990011835717296819569741981551097569810739977931249,
0.0729931217877990394495429419403374932441261816687788533563163323377395217254429050181833064967505478802134768007678458612956459126148837496307967995621683597067400860540057918571357609346700883624064782909888895547912499697295335516804810990011835717296819569741981551097569810739977931249,
-0.1214628192961205544703764634922478782186836383371912940423495826006931832245070944213952236889690237679661122848626352437115925113582515415979746598665681268376919737373113667247142315234607397986222184384307059013512155412722263090766858403726100735651684437098923088469949297570988091677,
0.1214628192961205544703764634922478782186836383371912940423495826006931832245070944213952236889690237679661122848626352437115925113582515415979746598665681268376919737373113667247142315234607397986222184384307059013512155412722263090766858403726100735651684437098923088469949297570988091677,
-0.1696444204239928180373136297482698441999902667343778505894178746884342357796505591325925801106834127602396624627746208498838190598644711533868179088757129652678801285453336384132061358206434768209251779433993367981112053126660575920785488821886662635718276505127786854167528795165050389903,
0.1696444204239928180373136297482698441999902667343778505894178746884342357796505591325925801106834127602396624627746208498838190598644711533868179088757129652678801285453336384132061358206434768209251779433993367981112053126660575920785488821886662635718276505127786854167528795165050389903,
-0.217423643740007084149648748988822617578485831141222348630380401885689634737659235537163737740243604800759921292790013642836998201691226098978544332296437547642195961469059807833597096166848933098833151166287901339013986496737408125314858259377210847115061960167857239951500335854820530586,
0.217423643740007084149648748988822617578485831141222348630380401885689634737659235537163737740243604800759921292790013642836998201691226098978544332296437547642195961469059807833597096166848933098833151166287901339013986496737408125314858259377210847115061960167857239951500335854820530586,
-0.2646871622087674163739641725100201179804131362950932439559895448126206429452852982016450901649805445999078728714943692622330016257776575354105370883948495294882935681426154386660616476411740312465060150591301869544672050088454083442813632094277160007745547301572849406353682760306061929911,
0.2646871622087674163739641725100201179804131362950932439559895448126206429452852982016450901649805445999078728714943692622330016257776575354105370883948495294882935681426154386660616476411740312465060150591301869544672050088454083442813632094277160007745547301572849406353682760306061929911,
-0.3113228719902109561575126985601568835577153578680501269954571709858169098868398268719654999460149709757804582988077747605532896065842023340674450299515989484487746153929299031759475919924980452933324186984188982046762542556035347023744560814177013801414889023264804693830155588690576492164,
0.3113228719902109561575126985601568835577153578680501269954571709858169098868398268719654999460149709757804582988077747605532896065842023340674450299515989484487746153929299031759475919924980452933324186984188982046762542556035347023744560814177013801414889023264804693830155588690576492164,
-0.357220158337668115950442615046202531626264464640909112021237019340099177403802509741325589540743874845093675632547750287037622834793938695456980400958079292460482315821150714268593539935795231095157602025909339384694681190969656053235824652679875951093689200190014853543993102190088381483,
0.357220158337668115950442615046202531626264464640909112021237019340099177403802509741325589540743874845093675632547750287037622834793938695456980400958079292460482315821150714268593539935795231095157602025909339384694681190969656053235824652679875951093689200190014853543993102190088381483,
-0.4022701579639916036957667712601588487132652056150208082760431843129087214967261515969669708970990221669508217089555714806012046537594438323569293594638517933840725639831594134038262580440842200076281605641993773325072728778928440394419613403725280285705765326861533477990551765453978736181,
0.4022701579639916036957667712601588487132652056150208082760431843129087214967261515969669708970990221669508217089555714806012046537594438323569293594638517933840725639831594134038262580440842200076281605641993773325072728778928440394419613403725280285705765326861533477990551765453978736181,
-0.4463660172534640879849477147589151892067507578262501763082606820212937626970791295735937384813941473610238854736863966831464694923749954564921955859791688348936235671762050333408576202492209167272366373825152067680845198006626563761196191045700093968519269790165913301841545609485952718504,
0.4463660172534640879849477147589151892067507578262501763082606820212937626970791295735937384813941473610238854736863966831464694923749954564921955859791688348936235671762050333408576202492209167272366373825152067680845198006626563761196191045700093968519269790165913301841545609485952718504,
-0.4894031457070529574785263070219213908493732974637398373316540793240315585537584844752851087115581833443158831657759501916744927211636581386025171070582998790865902140901838128045602667002106847665927788023098753138400106615804847725751247952878407027140260429761863258319891988431055536872,
0.4894031457070529574785263070219213908493732974637398373316540793240315585537584844752851087115581833443158831657759501916744927211636581386025171070582998790865902140901838128045602667002106847665927788023098753138400106615804847725751247952878407027140260429761863258319891988431055536872,
-0.531279464019894545658013903544455247408525588734180238053268047166041778398245121448843253296460411619816073385211875151397248937264089998182375345915413219579220233566173902955487674957069948591213673456625912506280248298229907928060620469290406581396192419570799497688513058132396498814,
0.531279464019894545658013903544455247408525588734180238053268047166041778398245121448843253296460411619816073385211875151397248937264089998182375345915413219579220233566173902955487674957069948591213673456625912506280248298229907928060620469290406581396192419570799497688513058132396498814,
-0.5718956462026340342838781166591886431831910060912509932273284719418912212643223327597417735844776972648163821225207266145263395898251858906124801356522395225326954546582593857056725545247314092886133249957455688586118199388064447508712958637376347457406936802691416300157802889354368128467,
0.5718956462026340342838781166591886431831910060912509932273284719418912212643223327597417735844776972648163821225207266145263395898251858906124801356522395225326954546582593857056725545247314092886133249957455688586118199388064447508712958637376347457406936802691416300157802889354368128467,
-0.6111553551723932502488529710185489186961245593079718443367976666933088374650288148448667879830703867726577720666491772560110368248450475818132595468834493579434418252468978282181164008820769765174450056817468275783966537351796625224747700783378315186174632657840114512887287754747902924865,
0.6111553551723932502488529710185489186961245593079718443367976666933088374650288148448667879830703867726577720666491772560110368248450475818132595468834493579434418252468978282181164008820769765174450056817468275783966537351796625224747700783378315186174632657840114512887287754747902924865,
-0.6489654712546573398577612319934048855296904334732011728792502624366057598865738239773166627826358871699142531853930525866830933399401844502541092962631127742267449897116125748014270680393024011359139031312062573520509858894743036198986443014969748157931850178889912972291202354657382925509,
0.6489654712546573398577612319934048855296904334732011728792502624366057598865738239773166627826358871699142531853930525866830933399401844502541092962631127742267449897116125748014270680393024011359139031312062573520509858894743036198986443014969748157931850178889912972291202354657382925509,
-0.6852363130542332425635583710313763019356410785396718681324042749913611976548967332647625541234155413035075739348863233240851709341392873173633850612006618690218164007761541855237208605116527909791956398350719463021018362527198358286721239529091637248252469435642287693207506339068528700205,
0.6852363130542332425635583710313763019356410785396718681324042749913611976548967332647625541234155413035075739348863233240851709341392873173633850612006618690218164007761541855237208605116527909791956398350719463021018362527198358286721239529091637248252469435642287693207506339068528700205,
-0.7198818501716108268489402178319472447581380033149019526220473151184468592486433646042300919262498902882179891494724046747921544602557246455427317830132976771174504209146835854012577372395960646854355024460204286901035470812684876587693044068989973704915078171158689213412715251485203442313,
0.7198818501716108268489402178319472447581380033149019526220473151184468592486433646042300919262498902882179891494724046747921544602557246455427317830132976771174504209146835854012577372395960646854355024460204286901035470812684876587693044068989973704915078171158689213412715251485203442313,
-0.7528199072605318966118637748856939855517142713220871932461987761167722639636968539390413583009467924995905147153923286347693864945784890119950315095740891764880991728646942920208355501445550654259850385377192973526980795946453961077798744753892199929235882097232836682421729944934586281945,
0.7528199072605318966118637748856939855517142713220871932461987761167722639636968539390413583009467924995905147153923286347693864945784890119950315095740891764880991728646942920208355501445550654259850385377192973526980795946453961077798744753892199929235882097232836682421729944934586281945,
-0.7839723589433414076102205252137682840564141249898259334132759617476816578705098509357116190608002325895348207611752987335385494893726027026038902508685496606160441965948835252795524014713290879877269643684102005605450140247125536147801312017065532602835003540212221564314236937509990182173,
0.7839723589433414076102205252137682840564141249898259334132759617476816578705098509357116190608002325895348207611752987335385494893726027026038902508685496606160441965948835252795524014713290879877269643684102005605450140247125536147801312017065532602835003540212221564314236937509990182173,
-0.8132653151227975597419233380863033406981418225655972166956485149356586346082019870309280128411412936411423614767918756843380999442447282903502051218203273573634847203121451086379808399639198510674436238195505371716160648058477202993836014352158139813219612968106205248494087577632573534973,
0.8132653151227975597419233380863033406981418225655972166956485149356586346082019870309280128411412936411423614767918756843380999442447282903502051218203273573634847203121451086379808399639198510674436238195505371716160648058477202993836014352158139813219612968106205248494087577632573534973,
-0.840629296252580362751691544695873302982489823801755353928202683075593465893922171840726147868117503717663799561956411215937924134571068943700343442753760445948626598735504632170407243376224222403038093781056024445977626666740664628412660960413062370047183186652885532589557452614451434048,
0.840629296252580362751691544695873302982489823801755353928202683075593465893922171840726147868117503717663799561956411215937924134571068943700343442753760445948626598735504632170407243376224222403038093781056024445977626666740664628412660960413062370047183186652885532589557452614451434048,
-0.8659993981540928197607833850701575024125019187582496425664279511808356713122188567857456842034906362573453815878913951040194915987006979015304835979058725276345799813088989383312475641092775164460639450521468294104011206574786429237252678172922104036725327539940502197291939132802457917836,
0.8659993981540928197607833850701575024125019187582496425664279511808356713122188567857456842034906362573453815878913951040194915987006979015304835979058725276345799813088989383312475641092775164460639450521468294104011206574786429237252678172922104036725327539940502197291939132802457917836,
-0.8893154459951141058534040382728516224291944615104521893194744566084811090577722526400445910623711480590529533188832105988657269430913287263821624762648137092066620632787986348052306840101775313644572400860845559833367997001666659907951051347410546710134120144598833115095140475669485797579,
0.8893154459951141058534040382728516224291944615104521893194744566084811090577722526400445910623711480590529533188832105988657269430913287263821624762648137092066620632787986348052306840101775313644572400860845559833367997001666659907951051347410546710134120144598833115095140475669485797579,
-0.9105221370785028057563806680083298610134880848883640292531723714467102234556291968179018775780308458024302103848451312741663820589200520720207891653884985710130867134073520525932445557074805974235006810370309087879564826639263972805682465506594098949560288847385983395160311034445386606259,
0.9105221370785028057563806680083298610134880848883640292531723714467102234556291968179018775780308458024302103848451312741663820589200520720207891653884985710130867134073520525932445557074805974235006810370309087879564826639263972805682465506594098949560288847385983395160311034445386606259,
-0.9295691721319395758214901545592256073474270144297154975928116833612430986265594515998834499355844736686512805129688214992047597092114291955925880175797899765980745854426738149516325837607227287481909072315347776012991222301207304052068204069335766550173941103055407746774520789612843561385,
0.9295691721319395758214901545592256073474270144297154975928116833612430986265594515998834499355844736686512805129688214992047597092114291955925880175797899765980745854426738149516325837607227287481909072315347776012991222301207304052068204069335766550173941103055407746774520789612843561385,
-0.9464113748584028160624814913472647952793949717952331902317789712973664402149436591260928179188420533516264142755452159723722786167537167514691534968355366202934342465086995943893699962972237343218079763936958985487264411542890941861254842843026890160131607678957282346112697993618567018237,
0.9464113748584028160624814913472647952793949717952331902317789712973664402149436591260928179188420533516264142755452159723722786167537167514691534968355366202934342465086995943893699962972237343218079763936958985487264411542890941861254842843026890160131607678957282346112697993618567018237,
-0.9610087996520537189186141218971572067621146110378459494461586158623919945488992563976780806866203786216001498788310714552847469661399216303755820947005848739467276644122915754949838610353627723679982220628115164983443994552616161584523205789167087822341423097206088828267065770404672828066,
0.9610087996520537189186141218971572067621146110378459494461586158623919945488992563976780806866203786216001498788310714552847469661399216303755820947005848739467276644122915754949838610353627723679982220628115164983443994552616161584523205789167087822341423097206088828267065770404672828066,
-0.9733268277899109637418535073522726680261452944551741758819139781978152256958453749994966038154125547612207903105020176172420237675899907788807087542221018040460410464083361271842759039530092449625891215101984663282728542290395875313124045226564547294745437773482395329023327909760431499638,
0.9733268277899109637418535073522726680261452944551741758819139781978152256958453749994966038154125547612207903105020176172420237675899907788807087542221018040460410464083361271842759039530092449625891215101984663282728542290395875313124045226564547294745437773482395329023327909760431499638,
-0.9833362538846259569312993021568311169452475066237403837464872131233426128415470535606559721330818003585532628124845662897410684694651251174207713020897795837892725294581710205598344576799985346970638130204876060998657059283079767876980544166132523941283823202290746667358872631036031924711,
0.9833362538846259569312993021568311169452475066237403837464872131233426128415470535606559721330818003585532628124845662897410684694651251174207713020897795837892725294581710205598344576799985346970638130204876060998657059283079767876980544166132523941283823202290746667358872631036031924711,
-0.9910133714767443207393823834433031136413494453907904852225427459378131658644129997345108950133770434340330151289100150097018332483423277136039914249575686591612502752158650205954671083696496347591169012794322303027309768195334920157669446268175983954105533989275308193580349506657360682085,
0.9910133714767443207393823834433031136413494453907904852225427459378131658644129997345108950133770434340330151289100150097018332483423277136039914249575686591612502752158650205954671083696496347591169012794322303027309768195334920157669446268175983954105533989275308193580349506657360682085,
-0.9963401167719552793469245006763991232098575063402266121352522199507030568202208530946066801021703916301511794658310735397567341036554686814952726523955953805437164277655915410358813984246580862850974195805395101678543649116458555272523253307828290553873260588621490898443701779725568118502,
0.9963401167719552793469245006763991232098575063402266121352522199507030568202208530946066801021703916301511794658310735397567341036554686814952726523955953805437164277655915410358813984246580862850974195805395101678543649116458555272523253307828290553873260588621490898443701779725568118502,
-0.9993050417357721394569056243456363119697121916756087760628072954617646543505331997843242376462639434945376776512170265314011232493020401570891594274831367800115383317335285468800574240152992751785027563437707875403545865305271045717258142571193695943317890367167086616955235477529427992282,
0.9993050417357721394569056243456363119697121916756087760628072954617646543505331997843242376462639434945376776512170265314011232493020401570891594274831367800115383317335285468800574240152992751785027563437707875403545865305271045717258142571193695943317890367167086616955235477529427992282
};
static const double C[] = {
0.0486909570091397203833653907347499124426286922838743305086688042456914190998246107310291565645676057401607079939845156005172257043376703767287395573765236401039685866479381075274920900511719320271157129622463682509122641788910270632229694394595885032921037399187298767076084601033342936131,
0.0486909570091397203833653907347499124426286922838743305086688042456914190998246107310291565645676057401607079939845156005172257043376703767287395573765236401039685866479381075274920900511719320271157129622463682509122641788910270632229694394595885032921037399187298767076084601033342936131,
0.0485754674415034269347990667839781136875565447049294857111516761025158193093697039229163427633930410186232149083923688162761488505704450697417589593116703853157329164894580165517236877241308351214870169600093357854651930986960906313726182992933363325614247750209880050786299287510692780499,
0.0485754674415034269347990667839781136875565447049294857111516761025158193093697039229163427633930410186232149083923688162761488505704450697417589593116703853157329164894580165517236877241308351214870169600093357854651930986960906313726182992933363325614247750209880050786299287510692780499,
0.048344762234802957169769527158017809703692550609501080629442201445249828946429202156764153264348308119169811534137999799779908820312744765416129733427088646813066886130539178187597540312913636916139844188190193872629488730769015964208394624398401975043997268903006190530430762197842013971,
0.048344762234802957169769527158017809703692550609501080629442201445249828946429202156764153264348308119169811534137999799779908820312744765416129733427088646813066886130539178187597540312913636916139844188190193872629488730769015964208394624398401975043997268903006190530430762197842013971,
0.0479993885964583077281261798713460699543167134714936209446323930933335214619650277588138568504103427609283146728470455041360837549685364869161566863222680599110109210456299588352028330169041000166382937545505655464884266691630625402297821494221827392164049587946530563778771030124675514431,
0.0479993885964583077281261798713460699543167134714936209446323930933335214619650277588138568504103427609283146728470455041360837549685364869161566863222680599110109210456299588352028330169041000166382937545505655464884266691630625402297821494221827392164049587946530563778771030124675514431,
0.0475401657148303086622822069442231716408252512625387521584740318784735191312349586041971325618543660076682369564304738487584849740943805934034367382833518752314207901993991333786062812015195073547884746598535775062676699885664167707011249029305697669004958515813436770491520105115843742005,
0.0475401657148303086622822069442231716408252512625387521584740318784735191312349586041971325618543660076682369564304738487584849740943805934034367382833518752314207901993991333786062812015195073547884746598535775062676699885664167707011249029305697669004958515813436770491520105115843742005,
0.0469681828162100173253262857545810751998975284738125649829240886861900500181800807437012381630302198876925642461830694029139318555787845567143614289552410495903601238284556145544858090965965782916339169651505119399637862876053945518410353459767034026687936026945199383607112976484520939933,
0.0469681828162100173253262857545810751998975284738125649829240886861900500181800807437012381630302198876925642461830694029139318555787845567143614289552410495903601238284556145544858090965965782916339169651505119399637862876053945518410353459767034026687936026945199383607112976484520939933,
0.0462847965813144172959532492322611849696503075324468007778340818364698861774606986244241539105685321088517142947579291476238551538798963436740600968513359005801910700069462154098456091711311098901749803777735222026075473081311483686560830539773763176758567914860207820170792365910140063798,
0.0462847965813144172959532492322611849696503075324468007778340818364698861774606986244241539105685321088517142947579291476238551538798963436740600968513359005801910700069462154098456091711311098901749803777735222026075473081311483686560830539773763176758567914860207820170792365910140063798,
0.0454916279274181444797709969712690588873234618023998968168834081606504637618082102750954507142497706775055424364453740562113890878382679420378787427100982909191308430750899201141096789461078632697297091763378573830284133736378128577579722120264252594541491899441765769262904055702701625378,
0.0454916279274181444797709969712690588873234618023998968168834081606504637618082102750954507142497706775055424364453740562113890878382679420378787427100982909191308430750899201141096789461078632697297091763378573830284133736378128577579722120264252594541491899441765769262904055702701625378,
0.0445905581637565630601347100309448432940237999912217256432193286861948363377761089569585678875932857237669096941854082976565514031401996407675401022860761183118504326746863327792604337217763335682212515058414863183914930810334329596384915832703655935958010948424747251920190851700662833367,
0.0445905581637565630601347100309448432940237999912217256432193286861948363377761089569585678875932857237669096941854082976565514031401996407675401022860761183118504326746863327792604337217763335682212515058414863183914930810334329596384915832703655935958010948424747251920190851700662833367,
0.0435837245293234533768278609737374809227888974971180150532193925502569499020021803936448815937567079991401855477391110804568848623412043870399620479222000249538880795788245633051476595555730388360811011823841525667998427392843673284072004068821750061964976796287623004834501604656318714989,
0.0435837245293234533768278609737374809227888974971180150532193925502569499020021803936448815937567079991401855477391110804568848623412043870399620479222000249538880795788245633051476595555730388360811011823841525667998427392843673284072004068821750061964976796287623004834501604656318714989,
0.0424735151236535890073397679088173661655466481806496697314607722055245433487169327182398988553670128358787507582463602377168227019625334754497484024668087975720049504975593281010888062806587161032924284354938115463233015024659299046001504100674918329532481611571863222497170398830691222425,
0.0424735151236535890073397679088173661655466481806496697314607722055245433487169327182398988553670128358787507582463602377168227019625334754497484024668087975720049504975593281010888062806587161032924284354938115463233015024659299046001504100674918329532481611571863222497170398830691222425,
0.0412625632426235286101562974736380477399306355305474105429034779122704951178045914463267035032832336161816547420067160277921114474557623647771372636679857599931025531633255548770293397336318597716427093310378312957479805159734598610664983115148350548735211568465338522875618805992499897174,
0.0412625632426235286101562974736380477399306355305474105429034779122704951178045914463267035032832336161816547420067160277921114474557623647771372636679857599931025531633255548770293397336318597716427093310378312957479805159734598610664983115148350548735211568465338522875618805992499897174,
0.0399537411327203413866569261283360739186769506703336301114037026981570543670430333260307390357287606111017588757685176701688554806178713759519003171090525332423003042251947304213502522332118258365256241174986409729902714098049024753746340158430732115642207673265332738358717839602955875715,
0.0399537411327203413866569261283360739186769506703336301114037026981570543670430333260307390357287606111017588757685176701688554806178713759519003171090525332423003042251947304213502522332118258365256241174986409729902714098049024753746340158430732115642207673265332738358717839602955875715,
0.0385501531786156291289624969468089910127871122017180319662378854088005271323682681394418540442928363090545214563022868422017877042243007014244875098498616146404178795110038170109976252865902624380463581094085479557660525450020049773872343621719025128277593787164021147974906095237533202082,
0.0385501531786156291289624969468089910127871122017180319662378854088005271323682681394418540442928363090545214563022868422017877042243007014244875098498616146404178795110038170109976252865902624380463581094085479557660525450020049773872343621719025128277593787164021147974906095237533202082,
0.0370551285402400460404151018095833750834649453056563021747536272028091562122966687178302646649066832960609370472485057031765338738734008482025086366647963664178752038995704175623165041724901843573087856883034472545386037691055680911138721623610172486110313241291773258491882452773847899443,
0.0370551285402400460404151018095833750834649453056563021747536272028091562122966687178302646649066832960609370472485057031765338738734008482025086366647963664178752038995704175623165041724901843573087856883034472545386037691055680911138721623610172486110313241291773258491882452773847899443,
0.0354722132568823838106931467152459479480946310024100946926514848199381113651392962399922996268087884509143420993419937430515415557908457195618550238075571721209638845910166697234073788332647695349442265578792857058786796417110738673392400570019770741873271724201517438135222598792344040215,
0.0354722132568823838106931467152459479480946310024100946926514848199381113651392962399922996268087884509143420993419937430515415557908457195618550238075571721209638845910166697234073788332647695349442265578792857058786796417110738673392400570019770741873271724201517438135222598792344040215,
0.0338051618371416093915654821107254310210499263140045346675500650400323727745785853730452808963944098691936344225349051741060036935288424090581463711756382878498537611980973238606529148664990420534952057130296232922368792280098852092993207644225150541876980292972087619863453425206929192216,
0.0338051618371416093915654821107254310210499263140045346675500650400323727745785853730452808963944098691936344225349051741060036935288424090581463711756382878498537611980973238606529148664990420534952057130296232922368792280098852092993207644225150541876980292972087619863453425206929192216,
0.032057928354851553585467504347898716966221573881398062250169407854535275399124366530227987935629046729162364779969274126431870966979526186907589490002269660893281421728773647001279141626157958271220102615163092206489916992120482595587916535390136003611498634162765724522022671474313619317,
0.032057928354851553585467504347898716966221573881398062250169407854535275399124366530227987935629046729162364779969274126431870966979526186907589490002269660893281421728773647001279141626157958271220102615163092206489916992120482595587916535390136003611498634162765724522022671474313619317,
0.030234657072402478867974059819548659158281397768481241636026542045969161851838118212761980885178641520596873511042783163461341979185470882574743804555268086640389062237383427702813367624714014426121485626242067362445894463989335423458464954799181190120473168677930333898873084606011285311,
0.030234657072402478867974059819548659158281397768481241636026542045969161851838118212761980885178641520596873511042783163461341979185470882574743804555268086640389062237383427702813367624714014426121485626242067362445894463989335423458464954799181190120473168677930333898873084606011285311,
0.0283396726142594832275113052002373519812075841257543359907955185084500175712880712901834579816476269393013386531176072296695948860841466158639973753393323262188023471133258509422081952937349849822864752636994881600343083839805990853930436233762729622213044478376753949590318846038229829528,
0.0283396726142594832275113052002373519812075841257543359907955185084500175712880712901834579816476269393013386531176072296695948860841466158639973753393323262188023471133258509422081952937349849822864752636994881600343083839805990853930436233762729622213044478376753949590318846038229829528,
0.0263774697150546586716917926252251856755993308422457184496156736853021592428967790284780487213653480867620409279447766944383920384284787790772384251090745670478105870527396429136326932261251511732466974897397268573168068852344129736214469830280087710575094607457344820944885011053938108899,
0.0263774697150546586716917926252251856755993308422457184496156736853021592428967790284780487213653480867620409279447766944383920384284787790772384251090745670478105870527396429136326932261251511732466974897397268573168068852344129736214469830280087710575094607457344820944885011053938108899,
0.0243527025687108733381775504090689876499784155133784119819985685535536787083770723737264828464464223276155821319330210193549896426801083040150047332857692873011433649334477370145389017577189505240415125600908800786897201425473757275187332157593198572919772969833130729981971352463730545469,
0.0243527025687108733381775504090689876499784155133784119819985685535536787083770723737264828464464223276155821319330210193549896426801083040150047332857692873011433649334477370145389017577189505240415125600908800786897201425473757275187332157593198572919772969833130729981971352463730545469,
0.0222701738083832541592983303841550024229592905997594051455205429744914460867081990116647982811451138592401156680063927909718825845915896692701716212710541472344073624315399429951255221519263275095347974129106415903376085208797420439500915674568159744176912567285070988940509294826076696882,
0.0222701738083832541592983303841550024229592905997594051455205429744914460867081990116647982811451138592401156680063927909718825845915896692701716212710541472344073624315399429951255221519263275095347974129106415903376085208797420439500915674568159744176912567285070988940509294826076696882,
0.0201348231535302093723403167285438970895266801007919519220072343276769828211923597982299498416998597995443052252531684909219367615574440281549241161294448697202959593344989612626641188010558013085389491205901106884167596038790695150496733123662891637942237462337673353651179115491957031948,
0.0201348231535302093723403167285438970895266801007919519220072343276769828211923597982299498416998597995443052252531684909219367615574440281549241161294448697202959593344989612626641188010558013085389491205901106884167596038790695150496733123662891637942237462337673353651179115491957031948,
0.0179517157756973430850453020011193688971673570364158572977184273569247295870620984743089140579199272107974903016785911970727080884655646148340637373001805876560334052431930062983734905886704331100259778249929425439377011315288821865303197904492848823994202996722656114004109123107733596987,
0.0179517157756973430850453020011193688971673570364158572977184273569247295870620984743089140579199272107974903016785911970727080884655646148340637373001805876560334052431930062983734905886704331100259778249929425439377011315288821865303197904492848823994202996722656114004109123107733596987,
0.0157260304760247193219659952975397944260290098431565121528943932284210502164124556525745628476326997189475680077625258949765335021586482683126547283634704087193102431454662772463321304938516661086261262080252305539171654570677889578063634007609097342035360186636479612243231917699790225637,
0.0157260304760247193219659952975397944260290098431565121528943932284210502164124556525745628476326997189475680077625258949765335021586482683126547283634704087193102431454662772463321304938516661086261262080252305539171654570677889578063634007609097342035360186636479612243231917699790225637,
0.0134630478967186425980607666859556841084257719773496708184682785221983598894666268489697837056105038485845901773961664652581563686185523959473293683490869846700009741156668864960127745507806046701586435579547632680339906665338521813319281296935586498194608460412423723103161161922347608637,
0.0134630478967186425980607666859556841084257719773496708184682785221983598894666268489697837056105038485845901773961664652581563686185523959473293683490869846700009741156668864960127745507806046701586435579547632680339906665338521813319281296935586498194608460412423723103161161922347608637,
0.011168139460131128818590493019208135072778797816827287215251362273969701224836131369547661822970774719521543690039908073147476182135228738610704246958518755712518444434075738269866120460156365855324768445411463643114925829148750923090201475035559533993035986264487097245733097728698218563,
0.011168139460131128818590493019208135072778797816827287215251362273969701224836131369547661822970774719521543690039908073147476182135228738610704246958518755712518444434075738269866120460156365855324768445411463643114925829148750923090201475035559533993035986264487097245733097728698218563,
0.0088467598263639477230309146597306476951762660792204997984715769296110380005985367341694286322550520156167431790573509593010611842062630262878798782558974712042810219159674181580449655112696028911646066461502678711637780164986283350190669684468398617127841853445303466680698660632269500149,
0.0088467598263639477230309146597306476951762660792204997984715769296110380005985367341694286322550520156167431790573509593010611842062630262878798782558974712042810219159674181580449655112696028911646066461502678711637780164986283350190669684468398617127841853445303466680698660632269500149,
0.0065044579689783628561173603999812667711317610549523400952448792575685125717613068203530526491113296049409911387320826711045787146267036866881961532403342811327869183281273743976710008917886491097375367147212074243884772614562628844975421736416404173672075979097191581386023407454532945934,
0.0065044579689783628561173603999812667711317610549523400952448792575685125717613068203530526491113296049409911387320826711045787146267036866881961532403342811327869183281273743976710008917886491097375367147212074243884772614562628844975421736416404173672075979097191581386023407454532945934,
0.0041470332605624676352875357285514153133028192536848024628763661431834776690157393776820933106187137592011723199002845429836606307797425496666456172753165824787973801175029578301513761259541022471768825518482406145696380621686627285992715643614469568410535180218496973657001203470470418364,
0.0041470332605624676352875357285514153133028192536848024628763661431834776690157393776820933106187137592011723199002845429836606307797425496666456172753165824787973801175029578301513761259541022471768825518482406145696380621686627285992715643614469568410535180218496973657001203470470418364,
0.0017832807216964329472960791449719331799593472719279556695308063655858546954239803486698215802150348282744786016134857283616955449868451969230490863774274598030023211055562492709717566919237924255297982774711177411074145151155610163293142044147991553384925940046957893721166251082473659733,
0.0017832807216964329472960791449719331799593472719279556695308063655858546954239803486698215802150348282744786016134857283616955449868451969230490863774274598030023211055562492709717566919237924255297982774711177411074145151155610163293142044147991553384925940046957893721166251082473659733
};
#elif defined(USE_32_SAMPLES)
/* n = 32 */
static double T[] = {
-0.0483076656877383162348125704405021636908472517308488971677937345463685926042778777794060365911173780988289503411375793689757446357461295741679964108035347980667582792392651327368009453047606446744575790523465655622949909588624860214137051585425884056992683442137333250625173849291299678673,
0.0483076656877383162348125704405021636908472517308488971677937345463685926042778777794060365911173780988289503411375793689757446357461295741679964108035347980667582792392651327368009453047606446744575790523465655622949909588624860214137051585425884056992683442137333250625173849291299678673,
-0.1444719615827964934851863735988106522038459913156355521379528938242184438164519731102406769974924713989580220758441301598578946580142268413547299935841673092513202403499286272686350814272974392746706128556678811982653393383080797337231702069432462445053984587997153683967433095128570624414,
0.1444719615827964934851863735988106522038459913156355521379528938242184438164519731102406769974924713989580220758441301598578946580142268413547299935841673092513202403499286272686350814272974392746706128556678811982653393383080797337231702069432462445053984587997153683967433095128570624414,
-0.2392873622521370745446032091655015206088554219602530155470960995597029133039943915553593695844147813728958071901224632260145752503694970545640339873418480550362677768010887468668377893757173424222709744116861683634989914911762187599464033126988486345234374380695224452457957624756811128321,
0.2392873622521370745446032091655015206088554219602530155470960995597029133039943915553593695844147813728958071901224632260145752503694970545640339873418480550362677768010887468668377893757173424222709744116861683634989914911762187599464033126988486345234374380695224452457957624756811128321,
-0.3318686022821276497799168057301879961957751368050598360182296306285376829657438169809731852312743263005943551508559377834274303920771100489026913715847854727626540340157368609696698131829681988642689780208633461925468064919389286805624602715005948661328152252049795463242055567997437182143,
0.3318686022821276497799168057301879961957751368050598360182296306285376829657438169809731852312743263005943551508559377834274303920771100489026913715847854727626540340157368609696698131829681988642689780208633461925468064919389286805624602715005948661328152252049795463242055567997437182143,
-0.4213512761306353453641194361724264783358772886324433305416613404557190462549837315607633055675740638739884093394574651160978879545562247406839036854173715776910866941643197988581928900702286425821151586000969947406313405310082646561917980302543820974679501841964453794193724645925031841919,
0.4213512761306353453641194361724264783358772886324433305416613404557190462549837315607633055675740638739884093394574651160978879545562247406839036854173715776910866941643197988581928900702286425821151586000969947406313405310082646561917980302543820974679501841964453794193724645925031841919,
-0.5068999089322293900237474743778212301802836995994354639743662809707712640478764442266190213124522047999876916596854537447047905434649918210338296049592120273725464263651562560829050004258268002241145951271730860506703690843719936432852920782304931272053564539127514959875734718036950073563,
0.5068999089322293900237474743778212301802836995994354639743662809707712640478764442266190213124522047999876916596854537447047905434649918210338296049592120273725464263651562560829050004258268002241145951271730860506703690843719936432852920782304931272053564539127514959875734718036950073563,
-0.5877157572407623290407454764018268584509401154544205727031788473129228586684474311408145102018661764979429510790747919023774933113319119601088669936958908618326367715806216053155906936017362413244183150445492317940727345571648726363597097311647731726438279098059670236086983675374932643925,
0.5877157572407623290407454764018268584509401154544205727031788473129228586684474311408145102018661764979429510790747919023774933113319119601088669936958908618326367715806216053155906936017362413244183150445492317940727345571648726363597097311647731726438279098059670236086983675374932643925,
-0.6630442669302152009751151686632383689770222859605053010170834964924461749232229404368981536611965356686820332804126742949900731319113817214392193185613161549689934301410316417342588149871686184296988807305719690974644891055567340650986465615021143958920599684258616066247948224049997371166,
0.6630442669302152009751151686632383689770222859605053010170834964924461749232229404368981536611965356686820332804126742949900731319113817214392193185613161549689934301410316417342588149871686184296988807305719690974644891055567340650986465615021143958920599684258616066247948224049997371166,
-0.732182118740289680387426665091267146630270483506629100821139573270385253587797727611292298988652560055905228466313310601075333829094630570926240639601009902567982815376254840388565733846030450161774620971196087756484387383432502715118096615117242484073636640563609696801484680439912327302,
0.732182118740289680387426665091267146630270483506629100821139573270385253587797727611292298988652560055905228466313310601075333829094630570926240639601009902567982815376254840388565733846030450161774620971196087756484387383432502715118096615117242484073636640563609696801484680439912327302,
-0.7944837959679424069630972989704289020954794016388354532507582449720593922816426654241878967890821228397041480126630294067578180914548706957761322921470535094589673860419616615738928385807346185892317514562489971543238450942224396667500582904031225063621511429185567036727089257387570529468,
0.7944837959679424069630972989704289020954794016388354532507582449720593922816426654241878967890821228397041480126630294067578180914548706957761322921470535094589673860419616615738928385807346185892317514562489971543238450942224396667500582904031225063621511429185567036727089257387570529468,
-0.849367613732569970133693004967742538954886793049759233100219598613724656141562558741881463752754991143937635778596582088915769685796612254240615386941355933272723068952531445772190363422003834495043219316062885999846179078139659341918527603834809670576387535564876596379488780285979062125,
0.849367613732569970133693004967742538954886793049759233100219598613724656141562558741881463752754991143937635778596582088915769685796612254240615386941355933272723068952531445772190363422003834495043219316062885999846179078139659341918527603834809670576387535564876596379488780285979062125,
-0.8963211557660521239653072437192122684789964967957595765636154129650249794910409173494503783167666654202705333374285522819507600044591355080910768854012859468015827508424619812224062460791781333400979810176198916239783226706506012473250929962326307746466256167673927887144428859779028909399,
0.8963211557660521239653072437192122684789964967957595765636154129650249794910409173494503783167666654202705333374285522819507600044591355080910768854012859468015827508424619812224062460791781333400979810176198916239783226706506012473250929962326307746466256167673927887144428859779028909399,
-0.9349060759377396891709191348354093255286714322828372184584037398118161947182932855418880831417927728359606280450921427988850058691931014887248988124656348299653052688344696135840215712191162135178273756415771123010111796122671724143565383396162107206772781551029308751511942924942333859805,
0.9349060759377396891709191348354093255286714322828372184584037398118161947182932855418880831417927728359606280450921427988850058691931014887248988124656348299653052688344696135840215712191162135178273756415771123010111796122671724143565383396162107206772781551029308751511942924942333859805,
-0.9647622555875064307738119281182749603888952204430187193220113218370995254867038008243801877562227002840740910741483519987441236283464394249183812395373150090695515823078220949436846111682404866338388944248976976566275875721000356873959697266702651250019105084704924793016185368873243713355,
0.9647622555875064307738119281182749603888952204430187193220113218370995254867038008243801877562227002840740910741483519987441236283464394249183812395373150090695515823078220949436846111682404866338388944248976976566275875721000356873959697266702651250019105084704924793016185368873243713355,
-0.9856115115452683354001750446309019786323957143358063182107821705820305847193755946663846485510970266115353839862364606643634021712823093784875255943834038377710426488328772047833289470320023596895438028281274741367781028592272459887917924171204666683239464005128153533797603112851826904814,
0.9856115115452683354001750446309019786323957143358063182107821705820305847193755946663846485510970266115353839862364606643634021712823093784875255943834038377710426488328772047833289470320023596895438028281274741367781028592272459887917924171204666683239464005128153533797603112851826904814,
-0.9972638618494815635449811286650407271385376637294611593011185457862359083917418520130456693085426416474280482200936551645510686196373231416035137741332968299789863385253514914078766236061488136738023162574655835389902337937054326098485227311719825229066712510246574949376367552421728646398,
0.9972638618494815635449811286650407271385376637294611593011185457862359083917418520130456693085426416474280482200936551645510686196373231416035137741332968299789863385253514914078766236061488136738023162574655835389902337937054326098485227311719825229066712510246574949376367552421728646398
};
static double C[] = {
0.0965400885147278005667648300635757947368606312355700687323182099577497758679466512968173871061464644599963197828969869820251559172455698832434930732077927850876632725829187045819145660710266452161095406358159608874152584850413283587913891015545638518881205600825069096855488296437485836866,
0.0965400885147278005667648300635757947368606312355700687323182099577497758679466512968173871061464644599963197828969869820251559172455698832434930732077927850876632725829187045819145660710266452161095406358159608874152584850413283587913891015545638518881205600825069096855488296437485836866,
0.0956387200792748594190820022041311005948905081620055509529898509437067444366006256133614167190847508238474888230077112990752876436158047205555474265705582078453283640212465537132165041268773645168746774530146140911679782502276289938840330631903789120176765314495900053061764438990021439069,
0.0956387200792748594190820022041311005948905081620055509529898509437067444366006256133614167190847508238474888230077112990752876436158047205555474265705582078453283640212465537132165041268773645168746774530146140911679782502276289938840330631903789120176765314495900053061764438990021439069,
0.0938443990808045656391802376681172600361000757462364500506275696355695118623098075097804207682530277555307864917078828352419853248607668520631751470962234105835015158485760721979732297206950719908744248285672032436598213262204039212897239890934116841559005147755270269705682414708355646603,
0.0938443990808045656391802376681172600361000757462364500506275696355695118623098075097804207682530277555307864917078828352419853248607668520631751470962234105835015158485760721979732297206950719908744248285672032436598213262204039212897239890934116841559005147755270269705682414708355646603,
0.0911738786957638847128685771116370625448614132753900053231278739777031520613017513597426417145878622654027367650308019870251963114683369110451524174258161390823876554910693202594383388549640738095422966058367070348943662290656339592299608558384147559830707904449930677260444604329157917977,
0.0911738786957638847128685771116370625448614132753900053231278739777031520613017513597426417145878622654027367650308019870251963114683369110451524174258161390823876554910693202594383388549640738095422966058367070348943662290656339592299608558384147559830707904449930677260444604329157917977,
0.0876520930044038111427714627518022875484497217017572223192228034747061150211380239263021665771581379364685191248848158059408000065275041643745927401342920150588893827207354226012701872322225514682178439577327346929209121046816487338309068375228210705166692551938339727096609740531893725675,
0.0876520930044038111427714627518022875484497217017572223192228034747061150211380239263021665771581379364685191248848158059408000065275041643745927401342920150588893827207354226012701872322225514682178439577327346929209121046816487338309068375228210705166692551938339727096609740531893725675,
0.0833119242269467552221990746043486115387468839428344598401864047287594069244380966536255650452315042012372905572506028852130723585016898197140339352228963465326746426938359210160503509807644396182380868089959855742801355208471205261406307895519604387550841954817025499019984032594036141439,
0.0833119242269467552221990746043486115387468839428344598401864047287594069244380966536255650452315042012372905572506028852130723585016898197140339352228963465326746426938359210160503509807644396182380868089959855742801355208471205261406307895519604387550841954817025499019984032594036141439,
0.078193895787070306471740918828306671039786798482159190307481553869493700115196435401943819761440851294456424770323467367505109006517482028994114252939401250416132320553639542341400437522236191275346323130525969269563653003188829786549728825182082678498917784036375053244425839341945385297,
0.078193895787070306471740918828306671039786798482159190307481553869493700115196435401943819761440851294456424770323467367505109006517482028994114252939401250416132320553639542341400437522236191275346323130525969269563653003188829786549728825182082678498917784036375053244425839341945385297,
0.0723457941088485062253993564784877916043369833018248707397632823511765345816800402874475958591657429073027694582930574378890633404841054620298756279975430795706338162404545590689277985270140590721779502609564199074051863640176937117952488466002340085264819537808079947788437998042296495822,
0.0723457941088485062253993564784877916043369833018248707397632823511765345816800402874475958591657429073027694582930574378890633404841054620298756279975430795706338162404545590689277985270140590721779502609564199074051863640176937117952488466002340085264819537808079947788437998042296495822,
0.0658222227763618468376500637069387728775364473732465153710916696852412442018627316280044447764609054151761388378861151807154113495715653711918644796313239555117970398473141615070299152284100887258072240524028885129828725430021172354299810423059697133688823072212214503334259555369485963074,
0.0658222227763618468376500637069387728775364473732465153710916696852412442018627316280044447764609054151761388378861151807154113495715653711918644796313239555117970398473141615070299152284100887258072240524028885129828725430021172354299810423059697133688823072212214503334259555369485963074,
0.0586840934785355471452836373001708867501204674575467587150032786132877518019090643743123653437052116901895704813134467814193905269714480573030647540887991405215103758723074481312705449946311993670933802369300463315125015975216910705047901943865293781921122370996257470349807212516159332678,
0.0586840934785355471452836373001708867501204674575467587150032786132877518019090643743123653437052116901895704813134467814193905269714480573030647540887991405215103758723074481312705449946311993670933802369300463315125015975216910705047901943865293781921122370996257470349807212516159332678,
0.0509980592623761761961632446895216952601847767397628437069071236525030510385137821267442193868358292147899714519363571211100873456269865150186456681043804358654826791768545393024953758025593924464295555854744882720755747096079325496814455853004350452095212995888025282619932613606999567133,
0.0509980592623761761961632446895216952601847767397628437069071236525030510385137821267442193868358292147899714519363571211100873456269865150186456681043804358654826791768545393024953758025593924464295555854744882720755747096079325496814455853004350452095212995888025282619932613606999567133,
0.0428358980222266806568786466061255284928108575989407395620219408911043916962572261359138025961596979511472539467367407419206021900868371610612953162236233351132214438513203223655531564777278515080476421262443325932320214191168239648611793958596884827086182431203349730049744697408543115307,
0.0428358980222266806568786466061255284928108575989407395620219408911043916962572261359138025961596979511472539467367407419206021900868371610612953162236233351132214438513203223655531564777278515080476421262443325932320214191168239648611793958596884827086182431203349730049744697408543115307,
0.0342738629130214331026877322523727069948402029116274337814057454192310522168984446294442724624445760666244242305266023810860790282088335398182296698622433517061843276344829146573593201201081743714879684153735672789104567624853712011151505225193933019375481618760594889854480408562043658635,
0.0342738629130214331026877322523727069948402029116274337814057454192310522168984446294442724624445760666244242305266023810860790282088335398182296698622433517061843276344829146573593201201081743714879684153735672789104567624853712011151505225193933019375481618760594889854480408562043658635,
0.0253920653092620594557525897892240292875540475469487209362512822192154788532376645960457016338988332029324531233401833547954942765653767672102838323550828207273795044402516181251040411735351747299230615776597356956641506445501689924551185923348003766988424170511157069264716719906995309826,
0.0253920653092620594557525897892240292875540475469487209362512822192154788532376645960457016338988332029324531233401833547954942765653767672102838323550828207273795044402516181251040411735351747299230615776597356956641506445501689924551185923348003766988424170511157069264716719906995309826,
0.0162743947309056706051705622063866181795429637952095664295931749613369651752917857651844425586692833071042366002861684552859449530958901379260437604156888337987656773068694383447504913457771896770689760342192010638946676879735404121702279005140285599424477022083127753774756520463311689155,
0.0162743947309056706051705622063866181795429637952095664295931749613369651752917857651844425586692833071042366002861684552859449530958901379260437604156888337987656773068694383447504913457771896770689760342192010638946676879735404121702279005140285599424477022083127753774756520463311689155,
0.0070186100094700966004070637388531825133772207289396032320082356192151241454178686953297376907573215077936155545790593837513204206518026084505878987243348925784479817181234617862457418214505322067610482902501455504204433524520665822704844582452877416001060465891907497519632353148380799619,
0.0070186100094700966004070637388531825133772207289396032320082356192151241454178686953297376907573215077936155545790593837513204206518026084505878987243348925784479817181234617862457418214505322067610482902501455504204433524520665822704844582452877416001060465891907497519632353148380799619
};
#else
/* n = 24 */
static double T[] = {
-0.0640568928626056260850430826247450385909991954207473934243510817897392835939101078028928761342525090823242273835115756994869112500371756765277735374378372436515481804668409746233647956019276711845937319580510697455314397618513360822351096139837050674073737720614748330506959387258141490546,
0.0640568928626056260850430826247450385909991954207473934243510817897392835939101078028928761342525090823242273835115756994869112500371756765277735374378372436515481804668409746233647956019276711845937319580510697455314397618513360822351096139837050674073737720614748330506959387258141490546,
-0.1911188674736163091586398207570696318404051033147533561489185765880859526918717419824911112452097307135934146013595461392721542943443689459384015952736491888634107638852139839821480663334386199430823059446316182589874503457282270169922471283825305735240671464262733609193984099421023790425,
0.1911188674736163091586398207570696318404051033147533561489185765880859526918717419824911112452097307135934146013595461392721542943443689459384015952736491888634107638852139839821480663334386199430823059446316182589874503457282270169922471283825305735240671464262733609193984099421023790425,
-0.3150426796961633743867932913198102407864782608248172687542301295298821563412434083438735095552082106072251617364030643536658931791308690387340350108862316429911426633492164449851684039691011610681827256891467485494251442677599304969349712405008328365242087382043028815467866505618650936915,
0.3150426796961633743867932913198102407864782608248172687542301295298821563412434083438735095552082106072251617364030643536658931791308690387340350108862316429911426633492164449851684039691011610681827256891467485494251442677599304969349712405008328365242087382043028815467866505618650936915,
-0.4337935076260451384870842319133497124524215109279688080808012846567644070336309140577354304660756168836170633415002629755076381975174699198632370585889341378575229685577710965327823199539830928400741454067377627746745635503614810834602257701251585352190552527778684113280867150779959852524,
0.4337935076260451384870842319133497124524215109279688080808012846567644070336309140577354304660756168836170633415002629755076381975174699198632370585889341378575229685577710965327823199539830928400741454067377627746745635503614810834602257701251585352190552527778684113280867150779959852524,
-0.5454214713888395356583756172183723700107839925876181754336143898305648391795708970958348674408062501977746653313676778948810297400650828985504068941547021866808914316854182653519436295728612315264181208390018064915325250677148594855874434492614547180849377989457776201862945948751249939033,
0.5454214713888395356583756172183723700107839925876181754336143898305648391795708970958348674408062501977746653313676778948810297400650828985504068941547021866808914316854182653519436295728612315264181208390018064915325250677148594855874434492614547180849377989457776201862945948751249939033,
-0.6480936519369755692524957869107476266696582986189567802989336650244483175685397719281177703657272433990519954414744003453347794058626075519074876962003580684127104697893556584036149935275154534232685850207671594298434446955488396349075497667624732345971957611938685137884801129695447597312,
0.6480936519369755692524957869107476266696582986189567802989336650244483175685397719281177703657272433990519954414744003453347794058626075519074876962003580684127104697893556584036149935275154534232685850207671594298434446955488396349075497667624732345971957611938685137884801129695447597312,
-0.7401241915785543642438281030999784255232924870141854568663823682719003386409229324413313561311287943298526270745398288213617461973439599491355223046073660810109486527571776420522757185953076208759863287235084614803697918067466580746275122563457575959399650481778575563118955957829855078072,
0.7401241915785543642438281030999784255232924870141854568663823682719003386409229324413313561311287943298526270745398288213617461973439599491355223046073660810109486527571776420522757185953076208759863287235084614803697918067466580746275122563457575959399650481778575563118955957829855078072,
-0.8200019859739029219539498726697452080761264776678555872439810260013829789535545400822605211725837960666424765858309152369975956748693910897310401393217997751433463343851603146734984964062776585418194561809063555489816762580329418137298754264378316716417347949040725111554705589243953692169,
0.8200019859739029219539498726697452080761264776678555872439810260013829789535545400822605211725837960666424765858309152369975956748693910897310401393217997751433463343851603146734984964062776585418194561809063555489816762580329418137298754264378316716417347949040725111554705589243953692169,
-0.8864155270044010342131543419821967550873330433089200403710379167756748343989591721041235019961817012535295108910075024175885664874383567124270976139069615059721185542370372118538064873468961679956606315961988138722471292807573552657465373246065266349095264290446955886450980216411579068464,
0.8864155270044010342131543419821967550873330433089200403710379167756748343989591721041235019961817012535295108910075024175885664874383567124270976139069615059721185542370372118538064873468961679956606315961988138722471292807573552657465373246065266349095264290446955886450980216411579068464,
-0.9382745520027327585236490017087214496548196580774513466350271759095894960525356709599646415358699555094267057623515929895997449470704383076095012442349544937551633313675972481722466159802428487600880633341786121580661077521685134893546419567859808853944866142065617471979973235700469563606,
0.9382745520027327585236490017087214496548196580774513466350271759095894960525356709599646415358699555094267057623515929895997449470704383076095012442349544937551633313675972481722466159802428487600880633341786121580661077521685134893546419567859808853944866142065617471979973235700469563606,
-0.9747285559713094981983919930081690617411830530401787198115935651071811212809802245386374742817154549827412585755713491144798180281062083910290010368962899139003272102551955405455775700818480561392470581718221938768668731616756379649281934548623489251537698395239432800432811839537332490367,
0.9747285559713094981983919930081690617411830530401787198115935651071811212809802245386374742817154549827412585755713491144798180281062083910290010368962899139003272102551955405455775700818480561392470581718221938768668731616756379649281934548623489251537698395239432800432811839537332490367,
-0.9951872199970213601799974097007368118745976925960028774416005451142838320694577378833972893371157088623453462978965853994497237745715598401409351804188189455255566266162142239452364851560816782389596967291836243391359167365098731808888455424405665558369621091780571617968925046375452278564,
0.9951872199970213601799974097007368118745976925960028774416005451142838320694577378833972893371157088623453462978965853994497237745715598401409351804188189455255566266162142239452364851560816782389596967291836243391359167365098731808888455424405665558369621091780571617968925046375452278564,
};
static double C[] = {
0.1279381953467521569740561652246953718517112395416678824212995763723475915405364024120919775667347423307078678605027534354336365506630173201256407760369958705384835762891562911475479559477218918074170718365754182501974550951925484331523758090745471505157505768499921691572488912345533434646,
0.1279381953467521569740561652246953718517112395416678824212995763723475915405364024120919775667347423307078678605027534354336365506630173201256407760369958705384835762891562911475479559477218918074170718365754182501974550951925484331523758090745471505157505768499921691572488912345533434646,
0.1258374563468282961213753825111836887264033255813454041780915168813938726666625968820381792564211407244125340112283619371640023694354842556219623307075721695505167028832011944572440814161265754364153991752782846305315778293182951298508346824950922490384565834525141570991957343073460241123,
0.1258374563468282961213753825111836887264033255813454041780915168813938726666625968820381792564211407244125340112283619371640023694354842556219623307075721695505167028832011944572440814161265754364153991752782846305315778293182951298508346824950922490384565834525141570991957343073460241123,
0.1216704729278033912044631534762624256070295592038057787774717545126253937177169619177578034307728419129571458407698685455109927385962626203664197972099671299080663146992247474377374928428629909818345130957392521139337403891946990001210368274459006298591636884893163373907763429334385715701,
0.1216704729278033912044631534762624256070295592038057787774717545126253937177169619177578034307728419129571458407698685455109927385962626203664197972099671299080663146992247474377374928428629909818345130957392521139337403891946990001210368274459006298591636884893163373907763429334385715701,
0.1155056680537256013533444839067835598622703113764964705844493600886702535513185499403442576468127956599599096047023274406552399890629831050388267870570157536484442644788074009392626299528272339158271789101012709245867329169327356527615681351864802567093740938014246237226139721687821239517,
0.1155056680537256013533444839067835598622703113764964705844493600886702535513185499403442576468127956599599096047023274406552399890629831050388267870570157536484442644788074009392626299528272339158271789101012709245867329169327356527615681351864802567093740938014246237226139721687821239517,
0.107444270115965634782577342446606222794628690134220021766541640886821866394437105980586727120915236672945076498454815476823439901643102885282830543962266851556251956709331696682107380679861280071851870323872823740641856241992841364843152888380035317713347953732555881218806283399463124951,
0.107444270115965634782577342446606222794628690134220021766541640886821866394437105980586727120915236672945076498454815476823439901643102885282830543962266851556251956709331696682107380679861280071851870323872823740641856241992841364843152888380035317713347953732555881218806283399463124951,
0.097618652104113888269880664464247154427918968853685944083310610022954338577591978348020039690718187482414745713364268645676642419728572107043424944384211806071042042791689191672508012725933985685876262715739521302925263010913644942223616059647289160432915821120275634713911721781926285332,
0.097618652104113888269880664464247154427918968853685944083310610022954338577591978348020039690718187482414745713364268645676642419728572107043424944384211806071042042791689191672508012725933985685876262715739521302925263010913644942223616059647289160432915821120275634713911721781926285332,
0.0861901615319532759171852029837426671850805882379330055884071438612868844607805312688886562972816971732787465671984327992158782827038381983594380916492525003385563462630861694048857276454548529177279961693054540872738963763950131372564031674654030737773100525128451496727198421916322556908,
0.0861901615319532759171852029837426671850805882379330055884071438612868844607805312688886562972816971732787465671984327992158782827038381983594380916492525003385563462630861694048857276454548529177279961693054540872738963763950131372564031674654030737773100525128451496727198421916322556908,
0.0733464814110803057340336152531165181193365098484994714027024906600413884758709348323251422694445551958844309079341158927693012247996928526423877450601776912550600854944985229487704917122675007345403564777169078420148392438502785281584325129303566997853186794893103931008654660416023204965,
0.0733464814110803057340336152531165181193365098484994714027024906600413884758709348323251422694445551958844309079341158927693012247996928526423877450601776912550600854944985229487704917122675007345403564777169078420148392438502785281584325129303566997853186794893103931008654660416023204965,
0.0592985849154367807463677585001085845412001265652134910373765512940983031775082415660683556106090092998654733952492642466909653073834070291103432919838456250955380753837859345492817299145644958959367291816621761687898337760987530926613795554356869343124524696513178977787335055019515914172,
0.0592985849154367807463677585001085845412001265652134910373765512940983031775082415660683556106090092998654733952492642466909653073834070291103432919838456250955380753837859345492817299145644958959367291816621761687898337760987530926613795554356869343124524696513178977787335055019515914172,
0.0442774388174198061686027482113382288593128418338578967413972297210243762822664396343947170155594934934611803046066530352490769669525012630503089839091175520932522330681764807671830570648211944799908348398720715944900305481342571090714940628894962186599515560606956040614089479788668773348,
0.0442774388174198061686027482113382288593128418338578967413972297210243762822664396343947170155594934934611803046066530352490769669525012630503089839091175520932522330681764807671830570648211944799908348398720715944900305481342571090714940628894962186599515560606956040614089479788668773348,
0.0285313886289336631813078159518782864491977979319081166016648047576440056374291434256854254228098755422737224452711633426188506404779428430343631052424983978091405445557790206527391293478807818130301641760878492678184457761229065303399826533483010921962299302202888714000294545957159715602,
0.0285313886289336631813078159518782864491977979319081166016648047576440056374291434256854254228098755422737224452711633426188506404779428430343631052424983978091405445557790206527391293478807818130301641760878492678184457761229065303399826533483010921962299302202888714000294545957159715602,
0.0123412297999871995468056670700372915759100408913665168172873209410917255178811137917987186719204245118391668507179752021919736085531955203240536027970786521356478573832633493407323107496772162595516230980489700767963287958540270795597236457014112169997285946194632806836898378754527134097,
0.0123412297999871995468056670700372915759100408913665168172873209410917255178811137917987186719204245118391668507179752021919736085531955203240536027970786521356478573832633493407323107496772162595516230980489700767963287958540270795597236457014112169997285946194632806836898378754527134097,
};
#endif

2586
gsk/gskcurve.c Normal file

File diff suppressed because it is too large Load Diff

189
gsk/gskcurveprivate.h Normal file
View File

@@ -0,0 +1,189 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#pragma once
#include "gskpathopprivate.h"
#include "gskpath.h"
#include "gskboundingboxprivate.h"
G_BEGIN_DECLS
typedef gpointer gskpathop;
typedef union _GskCurve GskCurve;
typedef struct _GskLineCurve GskLineCurve;
typedef struct _GskQuadCurve GskQuadCurve;
typedef struct _GskCubicCurve GskCubicCurve;
typedef struct _GskConicCurve GskConicCurve;
struct _GskLineCurve
{
GskPathOperation op;
gboolean padding;
graphene_point_t points[2];
};
struct _GskQuadCurve
{
GskPathOperation op;
gboolean has_coefficients;
graphene_point_t points[3];
graphene_point_t coeffs[3];
};
struct _GskCubicCurve
{
GskPathOperation op;
gboolean has_coefficients;
graphene_point_t points[4];
graphene_point_t coeffs[4];
};
struct _GskConicCurve
{
GskPathOperation op;
gboolean has_coefficients;
/* points[0], points[1], points[3] are the control points,
* points[2].x is the weight
*/
graphene_point_t points[4];
graphene_point_t num[3];
graphene_point_t denom[3];
};
union _GskCurve
{
GskPathOperation op;
GskLineCurve line;
GskQuadCurve quad;
GskCubicCurve cubic;
GskConicCurve conic;
};
typedef enum {
GSK_CURVE_LINE_REASON_STRAIGHT,
GSK_CURVE_LINE_REASON_SHORT
} GskCurveLineReason;
typedef gboolean (* GskCurveAddLineFunc) (const graphene_point_t *from,
const graphene_point_t *to,
float from_progress,
float to_progress,
GskCurveLineReason reason,
gpointer user_data);
typedef gboolean (* GskCurveAddCurveFunc) (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer user_data);
void gsk_curve_init (GskCurve *curve,
gskpathop op);
void gsk_curve_init_foreach (GskCurve *curve,
GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight);
void gsk_curve_print (const GskCurve *curve,
GString *string);
char * gsk_curve_to_string (const GskCurve *curve);
gskpathop gsk_curve_pathop (const GskCurve *curve);
const graphene_point_t *gsk_curve_get_start_point (const GskCurve *curve);
const graphene_point_t *gsk_curve_get_end_point (const GskCurve *curve);
void gsk_curve_get_start_tangent (const GskCurve *curve,
graphene_vec2_t *tangent);
void gsk_curve_get_end_tangent (const GskCurve *curve,
graphene_vec2_t *tangent);
void gsk_curve_get_point (const GskCurve *curve,
float progress,
graphene_point_t *pos);
void gsk_curve_get_tangent (const GskCurve *curve,
float progress,
graphene_vec2_t *tangent);
void gsk_curve_reverse (const GskCurve *curve,
GskCurve *reverse);
void gsk_curve_split (const GskCurve *curve,
float progress,
GskCurve *start,
GskCurve *end);
void gsk_curve_segment (const GskCurve *curve,
float start,
float end,
GskCurve *segment);
gboolean gsk_curve_decompose (const GskCurve *curve,
float tolerance,
GskCurveAddLineFunc add_line_func,
gpointer user_data);
gboolean gsk_curve_decompose_curve (const GskCurve *curve,
GskPathForeachFlags flags,
float tolerance,
GskCurveAddCurveFunc add_curve_func,
gpointer user_data);
#define gsk_curve_builder_to(curve, builder) gsk_path_builder_pathop_to ((builder), gsk_curve_pathop (curve))
float gsk_curve_get_curvature (const GskCurve *curve,
float t,
graphene_point_t *center);
void gsk_curve_get_bounds (const GskCurve *curve,
GskBoundingBox *bounds);
void gsk_curve_get_tight_bounds (const GskCurve *curve,
GskBoundingBox *bounds);
void gsk_curve_get_derivative_at (const GskCurve *curve,
float t,
graphene_point_t *value);
int gsk_curve_get_crossing (const GskCurve *curve,
const graphene_point_t *point);
gboolean gsk_curve_get_closest_point (const GskCurve *curve,
const graphene_point_t *point,
float threshold,
float *out_dist,
float *out_t);
float gsk_curve_get_length (const GskCurve *curve);
float gsk_curve_get_length_to (const GskCurve *curve,
float t);
float gsk_curve_at_length (const GskCurve *curve,
float distance,
float epsilon);
int gsk_curve_get_curvature_points (const GskCurve * curve,
float t[3]);
G_END_DECLS

View File

@@ -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
@@ -51,7 +51,9 @@
* @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 {
@@ -82,7 +84,9 @@ typedef enum {
GSK_DEBUG_NODE,
GSK_GL_SHADER_NODE,
GSK_TEXTURE_SCALE_NODE,
GSK_MASK_NODE
GSK_MASK_NODE,
GSK_FILL_NODE,
GSK_STROKE_NODE
} GskRenderNodeType;
/**
@@ -170,6 +174,164 @@ typedef enum {
GSK_CORNER_BOTTOM_LEFT
} GskCorner;
/**
* GskFillRule:
* @GSK_FILL_RULE_WINDING: If the path crosses the ray from
* left-to-right, counts +1. If the path crosses the ray
* from right to left, counts -1. (Left and right are determined
* from the perspective of looking along the ray from the starting
* point.) If the total count is non-zero, the point will be filled.
* @GSK_FILL_RULE_EVEN_ODD: Counts the total number of
* intersections, without regard to the orientation of the contour. If
* the total number of intersections is odd, the point will be
* filled.
*
* `GskFillRule` is used to select how paths are filled.
*
* Whether or not a point is included in the fill is determined by taking
* a ray from that point to infinity and looking at intersections with the
* path. The ray can be in any direction, as long as it doesn't pass through
* the end point of a segment or have a tricky intersection such as
* intersecting tangent to the path.
*
* (Note that filling is not actually implemented in this way. This
* is just a description of the rule that is applied.)
*
* New entries may be added in future versions.
*
* Since: 4.14
*/
typedef enum {
GSK_FILL_RULE_WINDING,
GSK_FILL_RULE_EVEN_ODD
} GskFillRule;
/**
* GskLineCap:
* @GSK_LINE_CAP_BUTT: Start and stop the line exactly at the start
* and end point
* @GSK_LINE_CAP_ROUND: Use a round ending, the center of the circle
* is the start or end point
* @GSK_LINE_CAP_SQUARE: use squared ending, the center of the square
* is the start or end point
*
* Specifies how to render the start and end points of contours or
* dashes when stroking.
*
* The default line cap style is `GSK_LINE_CAP_BUTT`.
*
* New entries may be added in future versions.
*
* <figure>
* <picture>
* <source srcset="caps-dark.png" media="(prefers-color-scheme: dark)">
* <img alt="Line Cap Styles" src="caps-light.png">
* </picture>
* <figcaption>GSK_LINE_CAP_BUTT, GSK_LINE_CAP_ROUND, GSK_LINE_CAP_SQUARE</figcaption>
* </figure>
*
* Since: 4.14
*/
typedef enum {
GSK_LINE_CAP_BUTT,
GSK_LINE_CAP_ROUND,
GSK_LINE_CAP_SQUARE
} GskLineCap;
/**
* GskLineJoin:
* @GSK_LINE_JOIN_MITER: Use a sharp angled corner
* @GSK_LINE_JOIN_ROUND: Use a round join, the center of the circle is
* the join point
* @GSK_LINE_JOIN_BEVEL: use a cut-off join, the join is cut off at half
* the line width from the joint point
*
* Specifies how to render the junction of two lines when stroking.
*
* The default line join style is `GSK_LINE_JOIN_MITER`.
*
* New entries may be added in future versions.
*
* <figure>
* <picture>
* <source srcset="join-dark.png" media="(prefers-color-scheme: dark)">
* <img alt="Line Join Styles" src="join-light.png">
* </picture>
* <figcaption>GSK_LINE_JOINT_MITER, GSK_LINE_JOINT_ROUND, GSK_LINE_JOIN_BEVEL</figcaption>
* </figure>
*
* Since: 4.14
*/
typedef enum {
GSK_LINE_JOIN_MITER,
GSK_LINE_JOIN_ROUND,
GSK_LINE_JOIN_BEVEL,
} GskLineJoin;
/**
* GskPathOperation:
* @GSK_PATH_MOVE: A move-to operation, with 1 point describing the target point.
* @GSK_PATH_CLOSE: A close operation ending the current contour with a line back
* to the starting point. Two points describe the start and end of the line.
* @GSK_PATH_LINE: A line-to operation, with 2 points describing the start and
* end point of a straight line.
* @GSK_PATH_QUAD: A curve-to operation describing a quadratic Bézier curve
* with 3 points describing the start point, the control point and the end
* point of the curve.
* @GSK_PATH_CUBIC: A curve-to operation describing a cubic Bézier curve with 4
* points describing the start point, the two control points and the end point
* of the curve.
* @GSK_PATH_CONIC: A rational quadratic Bézier curve with 3 points describing
* the start point, control point and end point of the curve. A weight for the
* curve will be passed, too.
*
* Path operations are used to describe the segments of a `GskPath`.
*
* More values may be added in the future.
*
* Since: 4.14
*/
typedef enum {
GSK_PATH_MOVE,
GSK_PATH_CLOSE,
GSK_PATH_LINE,
GSK_PATH_QUAD,
GSK_PATH_CUBIC,
GSK_PATH_CONIC,
} GskPathOperation;
/**
* GskPathDirection:
* @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 four tangents at a given point on the path.
*
* Note that the directions for @GSK_PATH_FROM_START/@GSK_PATH_TO_END and
* @GSK_PATH_TO_START/@GSK_PATH_FROM_END will coincide for smooth points.
* Only sharp turns will exhibit four different directions.
*
* <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_FROM_START,
GSK_PATH_TO_START,
GSK_PATH_TO_END,
GSK_PATH_FROM_END,
} GskPathDirection;
/**
* GskSerializationError:
* @GSK_SERIALIZATION_UNSUPPORTED_FORMAT: The format can not be identified
@@ -274,4 +436,3 @@ typedef enum
GSK_MASK_MODE_LUMINANCE,
GSK_MASK_MODE_INVERTED_LUMINANCE
} GskMaskMode;

1619
gsk/gskpath.c Normal file

File diff suppressed because it is too large Load Diff

155
gsk/gskpath.h Normal file
View File

@@ -0,0 +1,155 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#pragma once
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
/**
* GskPathForeachFlags:
* @GSK_PATH_FOREACH_ALLOW_ONLY_LINES: The default behavior, only allow lines.
* @GSK_PATH_FOREACH_ALLOW_QUAD: Allow emission of `GSK_PATH_QUAD` operations
* @GSK_PATH_FOREACH_ALLOW_CUBIC: Allow emission of `GSK_PATH_CUBIC` operations.
* @GSK_PATH_FOREACH_ALLOW_CONIC: Allow emission of `GSK_PATH_CONIC` operations.
*
* Flags that can be passed to gsk_path_foreach() to influence what
* kinds of operations the path is decomposed into.
*
* 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
{
GSK_PATH_FOREACH_ALLOW_ONLY_LINES = 0,
GSK_PATH_FOREACH_ALLOW_QUAD = (1 << 0),
GSK_PATH_FOREACH_ALLOW_CUBIC = (1 << 1),
GSK_PATH_FOREACH_ALLOW_CONIC = (1 << 2),
} GskPathForeachFlags;
/**
* GskPathForeachFunc:
* @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 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.
*
* Returns: %TRUE to continue iterating the path, %FALSE to
* immediately abort and not call the function again.
*/
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 ())
GDK_AVAILABLE_IN_4_14
GType gsk_path_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_ref (GskPath *self);
GDK_AVAILABLE_IN_4_14
void gsk_path_unref (GskPath *self);
GDK_AVAILABLE_IN_4_14
void gsk_path_print (GskPath *self,
GString *string);
GDK_AVAILABLE_IN_4_14
char * gsk_path_to_string (GskPath *self);
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_parse (const char *string);
GDK_AVAILABLE_IN_4_14
void gsk_path_to_cairo (GskPath *self,
cairo_t *cr);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_is_empty (GskPath *self);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_is_closed (GskPath *self);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_get_bounds (GskPath *self,
graphene_rect_t *bounds);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_get_stroke_bounds (GskPath *self,
const GskStroke *stroke,
graphene_rect_t *bounds);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_in_fill (GskPath *self,
const graphene_point_t *point,
GskFillRule fill_rule);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_get_start_point (GskPath *self,
GskPathPoint *result);
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,
float *distance);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_foreach (GskPath *self,
GskPathForeachFlags flags,
GskPathForeachFunc func,
gpointer user_data);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_dash (GskPath *self,
GskStroke *stroke,
GskPathForeachFunc func,
gpointer user_data);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPath, gsk_path_unref)
G_END_DECLS

1451
gsk/gskpathbuilder.c Normal file

File diff suppressed because it is too large Load Diff

192
gsk/gskpathbuilder.h Normal file
View File

@@ -0,0 +1,192 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#pragma once
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gskroundedrect.h>
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
#define GSK_TYPE_PATH_BUILDER (gsk_path_builder_get_type ())
GDK_AVAILABLE_IN_4_14
GType gsk_path_builder_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GskPathBuilder * gsk_path_builder_new (void);
GDK_AVAILABLE_IN_4_14
GskPathBuilder * gsk_path_builder_ref (GskPathBuilder *self);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_unref (GskPathBuilder *self);
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_builder_free_to_path (GskPathBuilder *self) G_GNUC_WARN_UNUSED_RESULT;
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_builder_to_path (GskPathBuilder *self) G_GNUC_WARN_UNUSED_RESULT;
GDK_AVAILABLE_IN_4_14
const graphene_point_t *gsk_path_builder_get_current_point (GskPathBuilder *self);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_add_path (GskPathBuilder *self,
GskPath *path);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_add_reverse_path (GskPathBuilder *self,
GskPath *path);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_add_cairo_path (GskPathBuilder *self,
const cairo_path_t *path);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_add_layout (GskPathBuilder *self,
PangoLayout *layout);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_add_rect (GskPathBuilder *self,
const graphene_rect_t *rect);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_add_rounded_rect (GskPathBuilder *self,
const GskRoundedRect *rect);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_add_circle (GskPathBuilder *self,
const graphene_point_t *center,
float radius);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_add_segment (GskPathBuilder *self,
GskPath *path,
const GskPathPoint *start,
const GskPathPoint *end);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_move_to (GskPathBuilder *self,
float x,
float y);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_rel_move_to (GskPathBuilder *self,
float x,
float y);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_line_to (GskPathBuilder *self,
float x,
float y);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_rel_line_to (GskPathBuilder *self,
float x,
float y);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_quad_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_rel_quad_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_cubic_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_rel_cubic_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_conic_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2,
float weight);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_rel_conic_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2,
float weight);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_arc_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_rel_arc_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_svg_arc_to (GskPathBuilder *self,
float rx,
float ry,
float x_axis_rotation,
gboolean large_arc,
gboolean positive_sweep,
float x,
float y);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_rel_svg_arc_to (GskPathBuilder *self,
float rx,
float ry,
float x_axis_rotation,
gboolean large_arc,
gboolean positive_sweep,
float x,
float y);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_html_arc_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2,
float radius);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_rel_html_arc_to (GskPathBuilder *self,
float x1,
float y1,
float x2,
float y2,
float radius);
GDK_AVAILABLE_IN_4_14
void gsk_path_builder_close (GskPathBuilder *self);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPathBuilder, gsk_path_builder_unref)
G_END_DECLS

280
gsk/gskpathdash.c Normal file
View File

@@ -0,0 +1,280 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gskcontourprivate.h"
#include "gskcurveprivate.h"
#include "gskpathprivate.h"
#include "gskstrokeprivate.h"
typedef struct
{
float offset; /* how much of the current dash we've spent */
gsize dash_index; /* goes from 0 to n_dash * 2, so we don't have to care about on/off
* for uneven dashes
*/
gboolean on; /* If we're currently dashing or not */
gboolean may_close; /* TRUE if we haven't turned the dash off in this contour */
gboolean needs_move_to; /* If we have emitted the initial move_to() yet */
enum {
NORMAL, /* no special behavior required */
SKIP, /* skip the next dash */
ONLY, /* only do the first dash */
DONE /* done with the first dash */
} first_dash_behavior; /* How to handle the first dash in the loop. We loop closed contours
* twice to make sure the first dash and the last dash can get joined
*/
float collect_start; /* We're collecting multiple line segments when decomposing. */
/* from the stroke */
float *dash;
gsize n_dash;
float dash_length;
float dash_offset;
GskPathForeachFunc func;
gpointer user_data;
} GskPathDash;
static void
gsk_path_dash_setup (GskPathDash *self)
{
self->offset = fmodf (self->dash_offset, 2 * self->dash_length);
self->dash_index = 0;
self->on = TRUE;
self->may_close = TRUE;
while (self->offset > self->dash[self->dash_index % self->n_dash])
{
self->offset -= self->dash[self->dash_index % self->n_dash];
self->dash_index++;
self->on = !self->on;
}
if (self->first_dash_behavior != ONLY)
self->needs_move_to = TRUE;
}
static gboolean
gsk_path_dash_ensure_move_to (GskPathDash *self,
const graphene_point_t *pt)
{
if (!self->needs_move_to)
return TRUE;
if (!self->func (GSK_PATH_MOVE, pt, 1, 0.f, self->user_data))
return FALSE;
self->needs_move_to = FALSE;
return TRUE;
}
static gboolean
gsk_path_dash_add_curve (const GskCurve *curve,
GskPathDash *self)
{
float remaining, t_start, t_end;
float used;
remaining = gsk_curve_get_length (curve);
used = 0;
t_start = 0;
while (remaining > 0)
{
float piece;
if (self->offset + remaining <= self->dash[self->dash_index % self->n_dash])
piece = remaining;
else
piece = self->dash[self->dash_index % self->n_dash] - self->offset;
t_end = gsk_curve_at_length (curve, used + piece, 0.001);
if (self->on)
{
if (self->first_dash_behavior != SKIP)
{
GskCurve segment;
if (piece > 0)
{
gsk_curve_segment (curve, t_start, t_end, &segment);
if (!gsk_path_dash_ensure_move_to (self, gsk_curve_get_start_point (&segment)))
return FALSE;
if (!gsk_pathop_foreach (gsk_curve_pathop (&segment), self->func, self->user_data))
return FALSE;
}
else
{
graphene_point_t p;
gsk_curve_get_point (curve, t_start, &p);
if (!gsk_path_dash_ensure_move_to (self, &p))
return FALSE;
}
}
}
else
{
self->may_close = FALSE;
if (self->first_dash_behavior == ONLY)
{
self->first_dash_behavior = DONE;
return FALSE;
}
self->first_dash_behavior = NORMAL;
}
if (self->offset + remaining <= self->dash[self->dash_index % self->n_dash])
{
self->offset += remaining;
remaining = 0;
}
else
{
t_start = t_end;
remaining -= piece;
used += piece;
self->offset = 0;
self->dash_index++;
self->dash_index %= 2 * self->n_dash;
self->on = !self->on;
self->needs_move_to = TRUE;
}
}
return TRUE;
}
static gboolean
gsk_path_dash_foreach (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer user_data)
{
GskPathDash *self = user_data;
GskCurve curve;
switch (op)
{
case GSK_PATH_MOVE:
gsk_path_dash_setup (self);
break;
case GSK_PATH_CLOSE:
if (self->may_close)
{
if (graphene_point_equal (&pts[0], &pts[1]))
return self->func (GSK_PATH_CLOSE, pts, 2, weight, self->user_data);
}
else
op = GSK_PATH_LINE;
G_GNUC_FALLTHROUGH;
case GSK_PATH_LINE:
case GSK_PATH_QUAD:
case GSK_PATH_CUBIC:
case GSK_PATH_CONIC:
gsk_curve_init_foreach (&curve, op, pts, n_pts, weight);
if (!gsk_path_dash_add_curve (&curve, self))
return FALSE;
break;
default:
g_assert_not_reached ();
break;
}
return TRUE;
}
gboolean
gsk_contour_dash (const GskContour *contour,
GskStroke *stroke,
GskPathForeachFunc func,
gpointer user_data)
{
GskPathDash self = {
.offset = 0,
.dash = stroke->dash,
.n_dash = stroke->n_dash,
.dash_length = stroke->dash_length,
.dash_offset = stroke->dash_offset,
.func = func,
.user_data = user_data
};
gboolean is_closed = gsk_contour_get_flags (contour) & GSK_PATH_CLOSED ? TRUE : FALSE;
self.first_dash_behavior = is_closed ? SKIP : NORMAL;
if (!gsk_contour_foreach (contour, gsk_path_dash_foreach, &self))
return FALSE;
if (is_closed)
{
if (self.first_dash_behavior == NORMAL)
self.first_dash_behavior = ONLY;
else
self.first_dash_behavior = NORMAL;
self.needs_move_to = !self.on;
if (!gsk_contour_foreach (contour, gsk_path_dash_foreach, &self) &&
self.first_dash_behavior != DONE)
return FALSE;
}
return TRUE;
}
/**
* gsk_path_dash:
* @self: the `GskPath` to dash
* @stroke: the stroke containing the dash parameters
* @func: (scope call) (closure user_data): the function to call for operations
* @user_data: (nullable): user data passed to @func
*
* Calls @func for every operation of the path that is the result
* of dashing @self with the dash pattern from @stroke.
*
* Returns: `FALSE` if @func returned FALSE`, `TRUE` otherwise.
*
* Since: 4.14
*/
gboolean
gsk_path_dash (GskPath *self,
GskStroke *stroke,
GskPathForeachFunc func,
gpointer user_data)
{
gsize i;
/* Dashing disabled, no need to do any work */
if (stroke->dash_length <= 0)
return gsk_path_foreach (self, -1, func, user_data);
for (i = 0; i < gsk_path_get_n_contours (self); i++)
{
if (!gsk_contour_dash (gsk_path_get_contour (self, i), stroke, func, user_data))
return FALSE;
}
return TRUE;
}

328
gsk/gskpathmeasure.c Normal file
View File

@@ -0,0 +1,328 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gskpathmeasure.h"
#include "gskpathbuilder.h"
#include "gskpathpointprivate.h"
#include "gskcontourprivate.h"
#include "gskpathprivate.h"
/**
* GskPathMeasure:
*
* `GskPathMeasure` is an object that allows measurements
* on `GskPath`s such as determining the length of the path.
*
* Many measuring operations require sampling the path length
* at intermediate points. Therefore, a `GskPathMeasure` has
* a tolerance that determines what precision is required
* for such approximations.
*
* A `GskPathMeasure` struct is a reference counted struct
* and should be treated as opaque.
*
* Since: 4.14
*/
typedef struct _GskContourMeasure GskContourMeasure;
struct _GskContourMeasure
{
float length;
gpointer contour_data;
};
struct _GskPathMeasure
{
/*< private >*/
guint ref_count;
GskPath *path;
float tolerance;
float length;
gsize n_contours;
GskContourMeasure measures[];
};
G_DEFINE_BOXED_TYPE (GskPathMeasure, gsk_path_measure,
gsk_path_measure_ref,
gsk_path_measure_unref)
/**
* gsk_path_measure_new:
* @path: the path to measure
*
* Creates a measure object for the given @path with the
* default tolerance.
*
* Returns: a new `GskPathMeasure` representing @path
*
* Since: 4.14
*/
GskPathMeasure *
gsk_path_measure_new (GskPath *path)
{
return gsk_path_measure_new_with_tolerance (path, GSK_PATH_TOLERANCE_DEFAULT);
}
/**
* gsk_path_measure_new_with_tolerance:
* @path: the path to measure
* @tolerance: the tolerance for measuring operations
*
* Creates a measure object for the given @path and @tolerance.
*
* Returns: a new `GskPathMeasure` representing @path
*
* Since: 4.14
*/
GskPathMeasure *
gsk_path_measure_new_with_tolerance (GskPath *path,
float tolerance)
{
GskPathMeasure *self;
gsize i, n_contours;
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (tolerance > 0, NULL);
n_contours = gsk_path_get_n_contours (path);
self = g_malloc0 (sizeof (GskPathMeasure) + n_contours * sizeof (GskContourMeasure));
self->ref_count = 1;
self->path = gsk_path_ref (path);
self->tolerance = tolerance;
self->n_contours = n_contours;
for (i = 0; i < n_contours; i++)
{
self->measures[i].contour_data = gsk_contour_init_measure (gsk_path_get_contour (path, i),
self->tolerance,
&self->measures[i].length);
self->length += self->measures[i].length;
}
return self;
}
/**
* gsk_path_measure_ref:
* @self: a `GskPathMeasure`
*
* Increases the reference count of a `GskPathMeasure` by one.
*
* Returns: the passed in `GskPathMeasure`.
*
* Since: 4.14
*/
GskPathMeasure *
gsk_path_measure_ref (GskPathMeasure *self)
{
g_return_val_if_fail (self != NULL, NULL);
self->ref_count++;
return self;
}
/**
* gsk_path_measure_unref:
* @self: a `GskPathMeasure`
*
* Decreases the reference count of a `GskPathMeasure` by one.
*
* If the resulting reference count is zero, frees the object.
*
* Since: 4.14
*/
void
gsk_path_measure_unref (GskPathMeasure *self)
{
gsize i;
g_return_if_fail (self != NULL);
g_return_if_fail (self->ref_count > 0);
self->ref_count--;
if (self->ref_count > 0)
return;
for (i = 0; i < self->n_contours; i++)
{
gsk_contour_free_measure (gsk_path_get_contour (self->path, i),
self->measures[i].contour_data);
}
gsk_path_unref (self->path);
g_free (self);
}
/**
* gsk_path_measure_get_path:
* @self: a `GskPathMeasure`
*
* Returns the path that the measure was created for.
*
* Returns: (transfer none): the path of @self
*
* Since: 4.14
*/
GskPath *
gsk_path_measure_get_path (GskPathMeasure *self)
{
return self->path;
}
/**
* gsk_path_measure_get_tolerance:
* @self: a `GskPathMeasure`
*
* Returns the tolerance that the measure was created with.
*
* Returns: the tolerance of @self
*
* Since: 4.14
*/
float
gsk_path_measure_get_tolerance (GskPathMeasure *self)
{
return self->tolerance;
}
/**
* gsk_path_measure_get_length:
* @self: a `GskPathMeasure`
*
* Gets the length of the path being measured.
*
* The length is cached, so this function does not do any work.
*
* Returns: The length of the path measured by @self
*
* Since: 4.14
*/
float
gsk_path_measure_get_length (GskPathMeasure *self)
{
g_return_val_if_fail (self != NULL, 0);
return self->length;
}
static float
gsk_path_measure_clamp_distance (GskPathMeasure *self,
float distance)
{
if (isnan (distance))
return 0;
return CLAMP (distance, 0, self->length);
}
/**
* gsk_path_measure_get_point:
* @self: a `GskPathMeasure`
* @distance: the distance
* @result: (out caller-allocates): return location for the result
*
* Sets @result to the point at the given distance into the path.
*
* An empty path has no points, so `FALSE` is returned in that case.
*
* Returns: `TRUE` if @result was set
*
* Since: 4.14
*/
gboolean
gsk_path_measure_get_point (GskPathMeasure *self,
float distance,
GskPathPoint *result)
{
gsize i;
const GskContour *contour;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (result != NULL, FALSE);
if (self->n_contours == 0)
return FALSE;
distance = gsk_path_measure_clamp_distance (self, distance);
for (i = 0; i < self->n_contours - 1; i++)
{
if (distance < self->measures[i].length)
break;
distance -= self->measures[i].length;
}
g_assert (0 <= i && i < self->n_contours);
distance = CLAMP (distance, 0, self->measures[i].length);
contour = gsk_path_get_contour (self->path, i);
gsk_contour_get_point (contour, self->measures[i].contour_data, distance, result);
g_assert (0 <= result->t && result->t <= 1);
result->contour = i;
return TRUE;
}
/**
* gsk_path_point_get_distance:
* @point: a `GskPathPoint on the path
* @measure: a `GskPathMeasure` for the path
*
* Returns the distance from the beginning of the path
* to @point.
*
* Returns: the distance of @point
*
* Since: 4.14
*/
float
gsk_path_point_get_distance (const GskPathPoint *point,
GskPathMeasure *measure)
{
float contour_offset = 0;
g_return_val_if_fail (measure != NULL, 0);
g_return_val_if_fail (gsk_path_point_valid (point, measure->path), 0);
for (gsize i = 0; i < measure->n_contours; i++)
{
if (i == point->contour)
return contour_offset + gsk_contour_get_distance (gsk_path_get_contour (measure->path, i),
point,
measure->measures[i].contour_data);
contour_offset += measure->measures[i].length;
}
g_return_val_if_reached (0);
}

62
gsk/gskpathmeasure.h Normal file
View File

@@ -0,0 +1,62 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#pragma once
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gskpath.h>
#include <gsk/gskpathpoint.h>
G_BEGIN_DECLS
#define GSK_TYPE_PATH_MEASURE (gsk_path_measure_get_type ())
GDK_AVAILABLE_IN_4_14
GType gsk_path_measure_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GskPathMeasure * gsk_path_measure_new (GskPath *path);
GDK_AVAILABLE_IN_4_14
GskPathMeasure * gsk_path_measure_new_with_tolerance (GskPath *path,
float tolerance);
GDK_AVAILABLE_IN_4_14
GskPathMeasure * gsk_path_measure_ref (GskPathMeasure *self);
GDK_AVAILABLE_IN_4_14
void gsk_path_measure_unref (GskPathMeasure *self);
GDK_AVAILABLE_IN_4_14
GskPath * gsk_path_measure_get_path (GskPathMeasure *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
float gsk_path_measure_get_tolerance (GskPathMeasure *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
float gsk_path_measure_get_length (GskPathMeasure *self);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_measure_get_point (GskPathMeasure *self,
float distance,
GskPathPoint *result);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPathMeasure, gsk_path_measure_unref)
G_END_DECLS

193
gsk/gskpathopprivate.h Normal file
View File

@@ -0,0 +1,193 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#pragma once
#include "gskpath.h"
#include "gskpathbuilder.h"
G_BEGIN_DECLS
typedef gpointer gskpathop;
static inline
gskpathop gsk_pathop_encode (GskPathOperation op,
const graphene_point_t *pts);
static inline
const graphene_point_t *gsk_pathop_points (gskpathop pop);
static inline
GskPathOperation gsk_pathop_op (gskpathop pop);
static inline
gboolean gsk_pathop_foreach (gskpathop pop,
GskPathForeachFunc func,
gpointer user_data);
/* included inline so tests can use them */
static inline
void gsk_path_builder_pathop_to (GskPathBuilder *builder,
gskpathop op);
static inline
void gsk_path_builder_pathop_reverse_to (GskPathBuilder *builder,
gskpathop op);
/* IMPLEMENTATION */
/* Note:
*
* The weight of conics is encoded as p[2].x, and the endpoint is p[3].
* This is important, since contours store the points of adjacent
* operations overlapping, so we can't put the weight at the end.
*/
#define GSK_PATHOP_OPERATION_MASK (0x7)
static inline gskpathop
gsk_pathop_encode (GskPathOperation op,
const graphene_point_t *pts)
{
/* g_assert (op & GSK_PATHOP_OPERATION_MASK == op); */
g_assert ((GPOINTER_TO_SIZE (pts) & GSK_PATHOP_OPERATION_MASK) == 0);
return GSIZE_TO_POINTER (GPOINTER_TO_SIZE (pts) | op);
}
static inline const graphene_point_t *
gsk_pathop_points (gskpathop pop)
{
return GSIZE_TO_POINTER (GPOINTER_TO_SIZE (pop) & ~GSK_PATHOP_OPERATION_MASK);
}
static inline
GskPathOperation gsk_pathop_op (gskpathop pop)
{
return GPOINTER_TO_SIZE (pop) & GSK_PATHOP_OPERATION_MASK;
}
static inline gboolean
gsk_pathop_foreach (gskpathop pop,
GskPathForeachFunc func,
gpointer user_data)
{
switch (gsk_pathop_op (pop))
{
case GSK_PATH_MOVE:
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_op (pop), gsk_pathop_points (pop), 2, 0, user_data);
case GSK_PATH_QUAD:
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 3, 0, user_data);
case GSK_PATH_CUBIC:
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 4, 0, user_data);
case GSK_PATH_CONIC:
{
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 ();
return TRUE;
}
}
static inline void
gsk_path_builder_pathop_to (GskPathBuilder *builder,
gskpathop op)
{
const graphene_point_t *pts = gsk_pathop_points (op);
switch (gsk_pathop_op (op))
{
case GSK_PATH_MOVE:
gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
break;
case GSK_PATH_CLOSE:
gsk_path_builder_close (builder);
break;
case GSK_PATH_LINE:
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
break;
case GSK_PATH_QUAD:
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, 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, pts[1].x, pts[1].y, pts[3].x, pts[3].y, pts[2].x);
break;
default:
g_assert_not_reached ();
break;
}
}
static inline void
gsk_path_builder_pathop_reverse_to (GskPathBuilder *builder,
gskpathop op)
{
const graphene_point_t *pts = gsk_pathop_points (op);
switch (gsk_pathop_op (op))
{
case GSK_PATH_MOVE:
gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
break;
case GSK_PATH_CLOSE:
gsk_path_builder_line_to (builder, pts[0].x, pts[0].y);
break;
case GSK_PATH_LINE:
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
break;
case GSK_PATH_QUAD:
gsk_path_builder_quad_to (builder, pts[1].x, pts[1].y, pts[0].x, pts[0].y);
break;
case GSK_PATH_CUBIC:
gsk_path_builder_cubic_to (builder, pts[2].x, pts[2].y, pts[1].x, pts[1].y, pts[0].x, pts[0].y);
break;
case GSK_PATH_CONIC:
gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y, pts[0].x, pts[0].y, pts[2].x);
break;
default:
g_assert_not_reached ();
break;
}
}
G_END_DECLS

284
gsk/gskpathpoint.c Normal file
View File

@@ -0,0 +1,284 @@
/*
* Copyright © 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#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:
*
* `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.
*
* 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 hold 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,
gsk_path_point_copy,
gsk_path_point_free)
GskPathPoint *
gsk_path_point_copy (GskPathPoint *point)
{
GskPathPoint *copy;
copy = g_new0 (GskPathPoint, 1);
memcpy (copy, point, sizeof (GskPathPoint));
return copy;
}
void
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
*
* Since: 4.14
*/
gboolean
gsk_path_point_equal (const GskPathPoint *point1,
const GskPathPoint *point2)
{
if (point1->contour == point2->contour)
{
if ((point1->idx == point2->idx && point1->t == point2->t) ||
(point1->idx + 1 == point2->idx && point1->t == 1 && point2->t == 0) ||
(point1->idx == point2->idx + 1 && point1->t == 0 && point2->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
*
* Since: 4.14
*/
int
gsk_path_point_compare (const GskPathPoint *point1,
const GskPathPoint *point2)
{
if (gsk_path_point_equal (point1, point2))
return 0;
if (point1->contour < point2->contour)
return -1;
else if (point1->contour > point2->contour)
return 1;
else if (point1->idx < point2->idx)
return -1;
else if (point1->idx > point2->idx)
return 1;
else if (point1->t < point2->t)
return -1;
else if (point1->t > point2->t)
return 1;
return 0;
}
/**
* gsk_path_point_get_position:
* @point: a `GskPathPoint`
* @path: the path that @point is on
* @position: (out caller-allocates): Return location for
* the coordinates of the point
*
* Gets the position of the point.
*
* Since: 4.14
*/
void
gsk_path_point_get_position (const GskPathPoint *point,
GskPath *path,
graphene_point_t *position)
{
const GskContour *contour;
g_return_if_fail (path != NULL);
g_return_if_fail (gsk_path_point_valid (point, path));
g_return_if_fail (position != NULL);
contour = gsk_path_get_contour (path, point->contour),
gsk_contour_get_position (contour, point, position);
}
/**
* gsk_path_point_get_tangent:
* @point: a `GskPathPoint`
* @path: the path that @point is on
* @direction: the direction for which to return the tangent
* @tangent: (out caller-allocates): Return location for
* the tangent at the point
*
* Gets the tangent of the path at the point.
*
* Note that certain points on a path may not have a single
* tangent, such as sharp turns. At such points, there are
* two tangents -- the direction of the path going into the
* 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
gsk_path_point_get_tangent (const GskPathPoint *point,
GskPath *path,
GskPathDirection direction,
graphene_vec2_t *tangent)
{
const GskContour *contour;
g_return_if_fail (path != NULL);
g_return_if_fail (gsk_path_point_valid (point, path));
g_return_if_fail (tangent != NULL);
contour = gsk_path_get_contour (path, point->contour),
gsk_contour_get_tangent (contour, point, 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
* [gtk_snapshot_rotate()](../gtk4/method.Snapshot.rotate.html).
*
* 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)
{
graphene_vec2_t tangent;
g_return_val_if_fail (path != NULL, 0);
g_return_val_if_fail (gsk_path_point_valid (point, 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`
* @path: the path that @point is on
* @direction: the direction for which to return the curvature
* @center: (out caller-allocates) (nullable): Return location for
* the center of the osculating circle
*
* Calculates the curvature of the path at the point.
*
* Optionally, returns the center of the osculating circle as well.
* The curvature is the inverse of the radius of the osculating circle.
*
* Lines have a curvature of zero (indicating an osculating circle of
* infinite radius. In this case, the @center is not modified.
*
* Circles with a radius of zero have `INFINITY` as curvature
*
* Note that certain points on a path may not have a single curvature,
* such as sharp turns. At such points, there are two curvatures --
* the (limit of) the curvature of the path going into the point,
* and the (limit of) the curvature of the path coming out of it.
* The @direction argument lets you choose which one to get.
*
* <picture>
* <source srcset="curvature-dark.png" media="(prefers-color-scheme: dark)">
* <img alt="Osculating circle" src="curvature-light.png">
* </picture>
* Returns: The curvature of the path at the given point
*
* Since: 4.14
*/
float
gsk_path_point_get_curvature (const GskPathPoint *point,
GskPath *path,
GskPathDirection direction,
graphene_point_t *center)
{
const GskContour *contour;
g_return_val_if_fail (path != NULL, 0);
g_return_val_if_fail (gsk_path_point_valid (point, path), 0);
contour = gsk_path_get_contour (path, point->contour);
return gsk_contour_get_curvature (contour, point, direction, center);
}

90
gsk/gskpathpoint.h Normal file
View File

@@ -0,0 +1,90 @@
/*
* Copyright © 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
#define GSK_TYPE_PATH_POINT (gsk_path_point_get_type ())
typedef struct _GskPathPoint GskPathPoint;
struct _GskPathPoint {
/*< private >*/
union {
struct {
gsize contour;
gsize idx;
float t;
};
gpointer padding[8];
graphene_vec4_t alignment;
};
};
GDK_AVAILABLE_IN_4_14
GType gsk_path_point_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GskPathPoint * gsk_path_point_copy (GskPathPoint *point);
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 (const GskPathPoint *point,
GskPath *path,
graphene_point_t *position);
GDK_AVAILABLE_IN_4_14
void gsk_path_point_get_tangent (const GskPathPoint *point,
GskPath *path,
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,
GskPathDirection direction,
graphene_point_t *center);
GDK_AVAILABLE_IN_4_14
float gsk_path_point_get_distance (const GskPathPoint *point,
GskPathMeasure *measure);
G_END_DECLS

39
gsk/gskpathpointprivate.h Normal file
View File

@@ -0,0 +1,39 @@
#pragma once
#include "gskpathpoint.h"
#include "gskcontourprivate.h"
G_BEGIN_DECLS
#define GSK_PATH_POINT_INIT(c,i,tt) ((GskPathPoint){ .contour=(c), .idx=(i), .t=(tt) })
static inline gboolean
gsk_path_point_valid (const GskPathPoint *point,
GskPath *path)
{
const GskContour *contour;
gsize n_ops;
if (point == NULL)
return FALSE;
if (path == NULL)
return TRUE;
if (point->contour >= gsk_path_get_n_contours (path))
return FALSE;
contour = gsk_path_get_contour (path, point->contour);
n_ops = gsk_contour_get_n_ops (contour);
if ((n_ops > 1 && point->idx >= n_ops) ||
(n_ops == 1 && point->idx > n_ops))
return FALSE;
if (point->t < 0 || point->t > 1)
return FALSE;
return TRUE;
}
G_END_DECLS

60
gsk/gskpathprivate.h Normal file
View File

@@ -0,0 +1,60 @@
/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#pragma once
#include "gskpath.h"
#include "gskpathopprivate.h"
G_BEGIN_DECLS
typedef enum
{
GSK_PATH_FLAT,
GSK_PATH_CLOSED
} GskPathFlags;
typedef struct _GskContour GskContour;
typedef struct _GskRealPathPoint GskRealPathPoint;
/* Same as Skia, so looks like a good value. ¯\_(ツ)_/¯ */
#define GSK_PATH_TOLERANCE_DEFAULT (0.5)
GskPath * gsk_path_new_from_contours (const GSList *contours);
gsize gsk_path_get_n_contours (const GskPath *self);
const GskContour * gsk_path_get_contour (const GskPath *self,
gsize i);
GskPathFlags gsk_path_get_flags (const GskPath *self);
gboolean gsk_path_foreach_with_tolerance (GskPath *self,
GskPathForeachFlags flags,
double tolerance,
GskPathForeachFunc func,
gpointer user_data);
void gsk_path_builder_add_contour (GskPathBuilder *builder,
GskContour *contour);
G_END_DECLS

20
gsk/gskpointprivate.h Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include <graphene.h>
static inline void G_GNUC_PURE
gsk_point_interpolate (const graphene_point_t *p1,
const graphene_point_t *p2,
float t,
graphene_point_t *p)
{
p->x = p1->x * (1 - t) + p2->x * t;
p->Y = p1->y * (1 - t) + p2->y * t;
}
static inline float G_GNUC_PURE
gsk_point_distance (const graphene_point_t *p1,
const graphene_point_t *p2)
{
return sqrtf ((p1->x - p2->x)*(p1->x - p2->x) + (p1->y - p2->y)*(p1->y - p2->y));
}

Some files were not shown because too many files have changed in this diff Show More