Compare commits

..

96 Commits

Author SHA1 Message Date
Emmanuele Bassi 69c3a43ec4 tests: Change test timeout for GDK
We use the same approach as the GTK testsuite:

- default timeout of 60 seconds
- timeout of 90 seconds if a test is inside the 'slow' suite
2024-01-16 18:33:40 +00:00
Matthias Clasen 9f2778b97c Merge branch 'fallback-6298' into 'main'
popovermenu: Add default sliding flag

See merge request GNOME/gtk!6746
2024-01-16 13:41:58 +00:00
Matthias Clasen ed4eeb8adb Merge branch 'wip/chergert/fix-object-expression-notify' into 'main'
expression: combine GWeakNotify and GWeakRef for object expression

Closes #5542 and #6220

See merge request GNOME/gtk!6763
2024-01-16 13:34:08 +00:00
Matthias Clasen fb36d30685 Merge branch 'custom-font-url' into 'main'
gsk: Keep a fontmap reference in text nodes

See merge request GNOME/gtk!6759
2024-01-16 13:04:13 +00:00
Matthias Clasen 385b9a7241 gsk: Serialize custom fonts with url
If we see custom fonts when serializeing text nodes, write data
url that contains the font file, the first time we see it.

This does not add blobs standard fonts, like Cantarell or Monospace.

Update all affected nodeparser tests.
2024-01-16 07:04:45 -05:00
Matthias Clasen c2abf30c46 Revert "node-editor: Make test fonts available"
This reverts commit 4882514234.

We can now put custom fonts into node files, so there is
no more need for this.
2024-01-16 07:04:45 -05:00
Matthias Clasen 50a47f55d9 Revert "rendernode-tool: Make test fonts available"
This reverts commit cdbfb35067.

We can now put custom fonts into node files, so there is
no more need for this.
2024-01-16 07:04:45 -05:00
Matthias Clasen cd7fe772a7 tests: Drop fontconfig setup for custom fonts
We are putting custom fonts into node files now, so there is
no more need for this.
2024-01-16 07:04:45 -05:00
Matthias Clasen 317bba756e Port existing gsk tests to embedded custom fonts
Make all the tests using custom fonts use the new url syntax.
2024-01-16 07:04:45 -05:00
Matthias Clasen 2212049e8f Merge branch 'wip/otte/for-main' into 'main'
Fix infinite loop in zenity

See merge request GNOME/gtk!6767
2024-01-16 11:36:34 +00:00
Matthias Clasen 0f26a006ee Merge branch 'revert-364eec24' into 'main'
Revert "Merge branch 'demos-enable-vulkan' into 'main'"

See merge request GNOME/gtk!6766
2024-01-16 10:15:52 +00:00
Benjamin Otte 3c451b3ec7 columnview: Make sure cells disconnect from their column
When a cell is removed from the columnview, we need to make sure it s
not just removed from the cell (via unset_parent()) but also from the
column.

Previously, we were doing this from dispose(), but this is broken
because dispose() only runs when the refcount goes to zero. But if some
code still has a reference for whatever reason, this won't happen.

So now we do it explicitly together with unset_parent().
2024-01-16 07:20:23 +01:00
Benjamin Otte 323adf9aa8 Revert "gtkcolumnviewcellwidget: move cleanup from dispose to unroot"
This reverts commit ff262c081e.

This is a wrong fix because it triggers when the columnview gets
unrooted but the cell keeps existing. Later, when the columnview gets
re-rooted, the cell is still there but thinks it has no column.

And that's bad.
2024-01-16 06:59:15 +01:00
Benjamin Otte 70f0cde730 tests: Fix gio API usage
Related: glib!3261
2024-01-16 06:22:43 +01:00
Christian Hergert 14e78663ee expression: combine GWeakNotify and GWeakRef for bind expression
This does the same thing to GtkExpressionBind that was done to
GtkExpressionObject. Use a GWeakRef to ensure we're working with a valid
object instead of relying on when our weak pointer and/or notify callback.
2024-01-15 20:59:27 -08:00
Christian Hergert d8279209a2 expression: retrieve next pointer before notifying closure
Any time we call back into user code we risk re-entrancy issues. Get the
next pointer for the list before calling back into notifiers.
2024-01-15 20:41:45 -08:00
Christian Hergert a0527ff0bd expression: combine GWeakNotify and GWeakRef for object expression
When using a GtkObjectExpression multiple times in the same GtkBuilder
template, we can run into a situation where we are in disposal but have
not yet had our callback notified.

This attempts to improve on that situation by using something I've done in
other projects for years. Combine both GWeakNotify and GWeakRef. Only use
the GWeakRef to get an object instance rather than relying on the
GWeakNotify alone.

By doing this, we can avoid trying to remove an object weak reference for
an object that is in disposal and causing runtime warnings.

Fixes #5542
Fixes #6220
2024-01-15 19:29:29 -08:00
Matthias Clasen 771ea81715 Merge branch 'fix-doc-link' into 'main'
docs: Update link to GitLab documentation

See merge request GNOME/gtk!6764
2024-01-16 01:49:34 +00:00
Emmanuele Bassi f22a3f9ec6 Revert "Merge branch 'demos-enable-vulkan' into 'main'"
This reverts merge request !6724
2024-01-16 00:45:00 +00:00
Matthias Clasen 246876a404 Add a test for font-related node parser errors
This tests the behaviors implemented in the previous commit.
2024-01-15 18:58:17 -05:00
Matthias Clasen 27a086b5f0 Add a test for new text node syntax
Add a test that checks that font: properties can be parsed without
error, both with and without the optional url.
2024-01-15 18:58:17 -05:00
Matthias Clasen 8158945de9 gsk: Allow custom fonts in node files
This will let us store complete test fonts inside node files,
as data: urls. You can also use a file: url to refer to a local
file.

The syntax is as follows:

text {
  font: "FONT DESCRIPTION" url("data:font/ttf;base64,FONT DATA");
}

with the url being optional.
2024-01-15 18:58:17 -05:00
Matthias Clasen 1c85141612 gsk: Keep a fontmap reference in text nodes
A PangoFont keeps a weak reference to its fontmap. In addition,
keep a strong reference in GskTextNode, so we can be sure that
custom font maps won't go away before the node is finalized.
2024-01-15 18:25:15 -05:00
Matthias Clasen 690381672b tests: Fix up test font naming
The entry for the family name in the name table has nameID=1, not
nameID=0, so we were relying on the filename to be just right.
Oops.
2024-01-15 18:25:15 -05:00
Matthias Clasen 3d7ff44dc5 Cosmetics 2024-01-15 18:25:15 -05:00
Florian Müllner a518c59098 docs: Update link to GitLab documentation
The original link no longer works, so update the reference to
point to the currently correct location.
2024-01-15 21:41:15 +01:00
Benjamin Otte 1dd5e92499 Merge branch 'unroot' into 'main'
gtkcolumnviewcellwidget: move cleanup from dispose to unroot

Closes #6200

See merge request GNOME/gtk!6758
2024-01-15 14:13:09 +00:00
Matthias Clasen fbd3c5ebd0 Merge branch 'matthiasc/for-main' into 'main'
Update the node format docs

See merge request GNOME/gtk!6761
2024-01-15 13:00:51 +00:00
Matthias Clasen 48dc7df5b7 Update the node format docs
Mention the new syntax for naming and reusing textures.
2024-01-15 07:46:18 -05:00
Emmanuele Bassi 0c4c90d606 Merge branch 'stackpage-auto-cleanup' into 'main'
stack: Add automatic cleanup for GtkStackPage

See merge request GNOME/gtk!6760
2024-01-15 11:33:07 +00:00
Guido Günther da954d20f9 stack: Add automatic cleanup for GtkStackPage
Useful when iterating over the pages via g_list_model_get_item ().
2024-01-15 11:48:21 +01:00
tszymanski ff262c081e gtkcolumnviewcellwidget: move cleanup from dispose to unroot
No longer gets stuck in an infinite loop.

Fixes #6200
2024-01-14 15:38:21 -08:00
Matthias Clasen c6967234de Merge branch 'matthiasc/for-main' into 'main'
gsk: Inline some more rect functions

See merge request GNOME/gtk!6755
2024-01-14 22:37:02 +00:00
Matthias Clasen cdbfb35067 rendernode-tool: Make test fonts available
We are likely to use the tool with node files from out testsuite,
which may now refer to custom test fonts, so make them available
in the same way as in the node editor.

If in doubt, you can set GTK_SOURCE_DIR to make the tool find the
fonts.
2024-01-14 16:58:05 -05:00
Matthias Clasen 53e17ab14e Merge branch 'node-editor-autosave' into 'main'
node-editor: Add an auto-reload property

See merge request GNOME/gtk!6757
2024-01-14 21:51:19 +00:00
Matthias Clasen 550e98090a node-editor: Redo crash recovery UX
Switch from a dialog to an in-app notification, and make use
of the new auto-reload property for it.
2024-01-14 14:40:51 -05:00
Matthias Clasen 2771befdd9 node-editor: Add a menu items for auto reloading
Expose the auto-reload property as a toggle action, and add
a menu item for it.
2024-01-14 14:40:51 -05:00
Matthias Clasen 911730493d node-editor: Add an auto-reload property
This is not exposed anywhere yet.
2024-01-14 14:40:51 -05:00
Maximiliano Sandoval d05f47a695 popovermenu: Add default sliding flag
Also add missing annotation.

Continuation of https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6298
2024-01-14 16:32:20 +01:00
Quentin PAGÈS 11dc15207e Update Occitan translation 2024-01-14 11:32:22 +00:00
Matthias Clasen 4ea748a676 Merge branch 'matthiasc/for-main' into 'main'
Add another font rendering test

See merge request GNOME/gtk!6752
2024-01-14 01:16:57 +00:00
Matthias Clasen b78d2a7f75 Add another font rendering test
This one tests that we handle glyphs with lsb correctly wrt. to
positioning.
2024-01-13 17:47:27 -05:00
Benjamin Otte 1fd9e1e916 Merge branch 'wip/otte/benchmark' into 'main'
Add gtk-rendernode-tool benchmark

See merge request GNOME/gtk!6751
2024-01-13 17:20:45 +00:00
Benjamin Otte 24ceb47cbc tools: Add the new benchmark command to the docs 2024-01-13 17:22:57 +01:00
Benjamin Otte 8872e1cbb0 tools: Add gtk-rendernode-tool benchmark
A simple tool that runs gsk_renderer_render_texture() a few times with
every renderer and prints the results.
2024-01-13 17:22:57 +01:00
Benjamin Otte c1e2ffac83 tools: Split out a function
There's a function now that creates a renderer by name - and allows NULL
for the default renderer
2024-01-13 17:22:57 +01:00
Piotr Drąg 17df646663 Update POTFILES.in 2024-01-13 13:29:25 +01:00
Ngọc Quân Trần 6f8fae590f Update Vietnamese translation
(cherry picked from commit cbc44e202a)
2024-01-13 07:19:30 +00:00
Matthias Clasen 4146db0003 Merge branch 'matthiasc/for-main' into 'main'
glarea: Add some details to the docs

Closes #6317

See merge request GNOME/gtk!6749
2024-01-13 03:17:05 +00:00
Matthias Clasen 9c228cc634 glarea: Add some details to the docs
Mention that the rendering is integrated into the GTK scene graph
as a texture and that the initial framebuffer contents are
transparent.

Fixes: #6317
2024-01-12 21:58:44 -05:00
Matthias Clasen df2cdb6913 Merge branch 'node-editor-autosave' into 'main'
node-editor: Add autosave

See merge request GNOME/gtk!6748
2024-01-13 02:30:06 +00:00
Matthias Clasen 22a5447039 docs: Document new node-editor options 2024-01-12 21:13:51 -05:00
Matthias Clasen a2475051fa Merge branch 'use-modifier-none' into 'main'
Use GDK_NO_MODIFIER_MASK in default prop values

See merge request GNOME/gtk!6747
2024-01-13 01:55:12 +00:00
Matthias Clasen d41fb7c5a6 node-editor: Add commandline options
Add --reset to remove the autosave file. While we're at it, also
add --version.
2024-01-12 20:50:34 -05:00
Matthias Clasen 3b28c46595 node-editor: Add autosave
Save the buffer contents to a file in ~/.cache/gtk4-node-editor
and restore it on startup.
2024-01-12 20:50:34 -05:00
Maximiliano Sandoval f57300b924 Use GDK_NO_MODIFIER_MASK in default prop values 2024-01-13 01:30:02 +01:00
Matthias Clasen c146f225ff Merge branch 'big-glyph-test' into 'main'
gsk: Fix big glyphs getting clipped

See merge request GNOME/gtk!6744
2024-01-12 21:31:35 +00:00
Matthias Clasen 9f4f65be4a gsk: Add test for clipped big glyphs
Tests the fix in the previous commit 93715b963e.

Sadly, the flipped variant of this test fails with the cairo
renderer, so it is marked as -nocairo. All the other renderers
pass it.
2024-01-12 16:02:05 -05:00
Matthias Clasen 93715b963e gsk: Fix big glyphs getting clipped
We were inadvertedly shifting the rendering by one pixel.
2024-01-12 15:55:27 -05:00
Benjamin Otte c1407f2ca6 Merge branch 'wip/otte/for-main' into 'main'
gpu: Remove unnecessary optimization

Closes #6322

See merge request GNOME/gtk!6743
2024-01-12 19:23:46 +00:00
Benjamin Otte 3b299f574d testsuite: Add a test for contained clips
Related: #6322
2024-01-12 20:06:04 +01:00
Benjamin Otte a51c6aed47 gpu: Introduce "contained" clip
This clip is different from "none" in that the bounds rect cannot be
ignored and that potential drawing outside the clip must be avoided.

In particular it means that clip nodes cannot be discarded if they
encompass the full clip region.

Fixes #6322
2024-01-12 20:06:04 +01:00
Benjamin Otte b552cf74dd gpu: Remove unnecessary optimization
Every branch in the switch is so optimized that it does this check
early anyway, so there's no need to have it as an extra step.
2024-01-12 20:06:04 +01:00
Matthias Clasen 0be0265751 Merge branch 'ebassi/doc-since-fix' into 'main'
docs: Add missing Since to gtk-show-status-shapes setting

See merge request GNOME/gtk!6741
2024-01-12 15:04:05 +00:00
Matthias Clasen 207dd6fe0d Merge branch 'matthiasc/for-main' into 'main'
gsk: Fix up test names to include 'compare'

See merge request GNOME/gtk!6739
2024-01-12 14:38:46 +00:00
Emmanuele Bassi a87ff8d556 docs: Add missing Since to gtk-show-status-shapes setting 2024-01-12 12:54:54 +00:00
Matthias Clasen 153cb8316e gsk: Fix up test names to include 'compare' 2024-01-11 23:19:29 -05:00
Matthias Clasen 7ad7c0d8c1 Merge branch 'switch-shapes' into 'main'
switch: Follow "switch-shapes" setting

Closes #5354

See merge request GNOME/gtk!6731
2024-01-11 19:19:58 +00:00
Benjamin Otte 61595af586 Merge branch 'ngl-backbuffer-leak' into 'main'
ngl: Don't leak the backbuffer

See merge request GNOME/gtk!6736
2024-01-11 11:16:31 +00:00
Matthias Clasen d240c35850 ngl: Don't leak the backbuffer
Clear it in unrealize, just like the vulkan renderer does with
its targets.
2024-01-10 23:08:01 -05:00
Matthias Clasen d276eb9e9a Merge branch 'test-font-tweaks' into 'main'
tests: Change the way custom fonts are handled

See merge request GNOME/gtk!6734
2024-01-11 03:33:15 +00:00
Matthias Clasen afe4cbf26d tests: Change the way custom fonts are handled
Instead of setting FONTCONFIG_FILE to a custom font configuration,
pass the directory containing the fonts as TEST_FONTS and use
FcConfigAppFontAddDir to add them to the default font configuration.
2024-01-10 22:18:37 -05:00
Matthias Clasen 76e5ef6937 Merge branch 'node-editor-tweaks' into 'main'
node-editor: Make test fonts available

See merge request GNOME/gtk!6733
2024-01-11 02:55:50 +00:00
Matthias Clasen 0ed43f66a9 docs: Beef up the node-editor man page
Mention the GTK_SOURCE_DIR environment variable in the man page.
2024-01-10 21:10:36 -05:00
Matthias Clasen 4882514234 node-editor: Make test fonts available
Add the directory containing test fonts for gsk tests to the
font configuration, so that node files from the testsuite using
these fonts just work.
2024-01-10 21:10:36 -05:00
Matthias Clasen a15e87d2a6 Merge branch 'mixed-color-test' into 'main'
gsk: Add another font text

See merge request GNOME/gtk!6732
2024-01-11 01:50:09 +00:00
Matthias Clasen cc92b9b19f gsk: Add another font text
This is similar to text-mixed-color, but it uses the COLRv1 table,
to test our support for this font technology.
2024-01-10 19:44:55 -05:00
Florian Müllner bf0120f73d switch: Follow "show-status-shapes" setting
Whether or not switches include shapes to indicate their ON/OFF
state is currently controlled by the stylesheet (in particular
the HighContrast style).

However there are use cases for both using the HighContrast style
without shapes, and for using shapes with the regular stylesheet,
so follow the newly added "show-status-shapes" setting instead.

https://gitlab.gnome.org/GNOME/gtk/-/issues/5354
2024-01-11 01:33:16 +01:00
Matthias Clasen 7f06eed8da Merge branch 'hc-cleanup' into 'main'
wayland/display: Don't notify "icon-theme" on high-contrast changes

See merge request GNOME/gtk!6730
2024-01-10 21:38:55 +00:00
Matthias Clasen dc30044829 Merge branch 'gpu-fix-mixed-color-text' into 'main'
gpu: Fix handling of mixed-color text runs

See merge request GNOME/gtk!6725
2024-01-10 18:11:23 +00:00
Matthias Clasen 781fe2d7fa gsk: Add a compare test for mixed color runs
This tests the fixes in aa82190da659b5 and dcaa2c4ccb182c74cb40.

The test uses a custom font named 'text-mixed-color' which contains
six glyphs that are just boxes. Glyphs 1, 2, 3 are just plain glyphs,
and glyphs 4, 5, 6 are color glyphs in red, green and blue.

The glyphs are mapped to the characters A, B, C, D, E, F.

The test is currently disabled for cairo, since it has some issues
with transformed color glyphs.
2024-01-10 12:49:08 -05:00
Florian Müllner b8a61f7899 wayland/display: Don't notify "icon-theme" on high-contrast changes
Since commit c3706ea9ec, the "high-contrast" setting no longer
forces the "HighContrast" icon theme.
2024-01-10 15:46:46 +01:00
Matthias Clasen a44ca6756a gpu: Use the right format for atlases
The glyph atlas format needs to match the cairo memory format.
NGL was getting this wrong, causing color glyphs to have their
red and blue swapped.
2024-01-10 08:00:15 -05:00
Matthias Clasen 490a9f193d gpu: Fix handling of mixed color text runs
We need to decide per-glyph whether to use coloring or texture ops.
2024-01-10 08:00:15 -05:00
Matthias Clasen 754d364efd gsk: Allow custom fonts in tests
The commit adds a custom fontconfig configuration in
testsuite/gsk/fonts/fonts.conf and sets the FONTCONFIG_FILE
environment variable for the gsk compare tests to point at it.

To use a custom font in tests, just drop it into the
testsuite/gsk/fonts/ directory.

The font configuration includes the system configuration,
so existing tests should not be affected.
2024-01-10 07:58:19 -05:00
Benjamin Otte 4939f0bb75 Merge branch 'wip/otte/for-main' into 'main'
contour: Fix stroke bounds for rect contour

See merge request GNOME/gtk!6728
2024-01-10 01:05:22 +00:00
Carlos Garnacho 7537d80047 Merge branch 'wip/show-tablet-cursor' into 'main'
gdk/wayland: reset cursor_is_default on proximity out

Closes #6312

See merge request GNOME/gtk!6720
2024-01-10 00:55:32 +00:00
Benjamin Otte c5bdf0a995 testsuite: Add tests for pixel grid accuracy
See previous commit for details.
2024-01-10 01:33:49 +01:00
Peter Hutterer 04870fc1a1 gdk/wayland: Reset cursor_is_default on proximity out
For tablet tools if we have NULL cursor, we use the default cursor
instead. This provides us with a tablet cursor when an application never
sets the cursor.

However, on proximity out when we clear said cursor we also
need to toggle off cursor_is_default, otherwise on the next proximity in
we assume we already have a cursor and never update it again.

This leads to an invisible cursor over GTK application when the tablet
tool is brought into proximity over the widget (but not when moving into
the widget from the outside).

Closes: #6312
2024-01-10 00:25:01 +00:00
Matthias Clasen 43e5bc795a Merge branch 'log_whitespace' into 'main'
Add missing space to warning

See merge request GNOME/gtk!6729
2024-01-10 00:06:05 +00:00
Spencer Burris f3ec58d290 Add missing space to warning 2024-01-09 16:57:26 -07:00
Benjamin Otte 5b3d14e15b gpu: respect pixel grid for Cairo rendering
Make sure fallbacks and fill/stroke masks use image surfaces with the
same pixel grid as the target if possible.

Fixes blurriness with some path renderings.
2024-01-10 00:13:52 +01:00
Benjamin Otte 131ab11f5c testsuite: Check that pixel grid math respects offsets 2024-01-10 00:13:52 +01:00
Benjamin Otte a2eb467663 gpu: Change rect_round_pixels() to take an offset
We need to respect the offset when converting to the pixel grid, so pass
the current offset into the function.

Also move the rounded out of gsk_gpu_get_node_as_image() and into the 2
callers, because the offset is not passed into the function and I see no
reason to change that.
2024-01-10 00:13:52 +01:00
Benjamin Otte 06f85ee566 contour: Fix stroke bounds for rect contour
There's no tests for stroke bounds, oh no!
2024-01-09 23:27:55 +01:00
Benjamin Otte aab40ad6a2 gpu: Fix text coordinates in the ubershader 2024-01-09 23:27:55 +01:00
88 changed files with 11206 additions and 6580 deletions
+1 -1
View File
@@ -213,7 +213,7 @@ Closes #1234
`git commit -a --author "Joe Coder <joe@coder.org>"` and `--signoff`.
- If your commit is addressing an issue, use the
[GitLab syntax](https://docs.gitlab.com/ce/user/project/issues/automatic_issue_closing.html)
[GitLab syntax](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
to automatically close the issue when merging the commit with the upstream
repository:
+2
View File
@@ -185,6 +185,7 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
],
@@ -199,6 +200,7 @@
],
"build-options" : {
"env" : {
"GSK_RENDERER" : "opengl"
}
}
}
@@ -114,6 +114,7 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
],
@@ -114,6 +114,7 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
],
@@ -129,6 +130,8 @@
"build-options" : {
"env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''",
"GSK_RENDERER" : "opengl",
"GDK_DEBUG" : "vulkan-disable",
"G_ENABLE_DEBUG" : "true"
}
}
@@ -114,6 +114,7 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
],
@@ -129,6 +130,8 @@
"build-options" : {
"env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''",
"GSK_RENDERER" : "opengl",
"GDK_DEBUG" : "vulkan-disable",
"G_ENABLE_DEBUG" : "true"
}
}
+58 -4
View File
@@ -19,6 +19,8 @@
#include "config.h"
#include <glib/gstdio.h>
#include "node-editor-application.h"
#include "node-editor-window.h"
@@ -247,11 +249,63 @@ node_editor_application_class_init (NodeEditorApplicationClass *class)
application_class->open = node_editor_application_open;
}
static void
print_version (void)
{
g_print ("gtk4-node-editor %s%s%s\n",
PACKAGE_VERSION,
g_strcmp0 (PROFILE, "devel") == 0 ? "-" : "",
g_strcmp0 (PROFILE, "devel") == 0 ? VCS_TAG : "");
}
static int
local_options (GApplication *app,
GVariantDict *options,
gpointer data)
{
gboolean version = FALSE;
gboolean reset = FALSE;
g_variant_dict_lookup (options, "version", "b", &version);
if (version)
{
print_version ();
return 0;
}
g_variant_dict_lookup (options, "reset", "b", &reset);
if (reset)
{
char *path;
path = get_autosave_path ("-unsafe");
g_remove (path);
g_free (path);
path = get_autosave_path (NULL);
g_remove (path);
g_free (path);
}
return -1;
}
NodeEditorApplication *
node_editor_application_new (void)
{
return g_object_new (NODE_EDITOR_APPLICATION_TYPE,
"application-id", "org.gtk.gtk4.NodeEditor",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
NodeEditorApplication *app;
app = g_object_new (NODE_EDITOR_APPLICATION_TYPE,
"application-id", "org.gtk.gtk4.NodeEditor",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
g_application_add_main_option (G_APPLICATION (app), "version", 0, 0,G_OPTION_ARG_NONE, "Show program version", NULL);
g_application_add_main_option (G_APPLICATION (app), "reset", 0, 0,G_OPTION_ARG_NONE, "Remove autosave content", NULL);
g_signal_connect (app, "handle-local-options", G_CALLBACK (local_options), NULL);
return app;
}
+311 -89
View File
@@ -28,6 +28,8 @@
#include "gsk/broadway/gskbroadwayrenderer.h"
#endif
#include <glib/gstdio.h>
#include <cairo.h>
#ifdef CAIRO_HAS_SVG_SURFACE
#include <cairo-svg.h>
@@ -55,6 +57,7 @@ struct _NodeEditorWindow
GtkWidget *testcase_name_entry;
GtkWidget *testcase_save_button;
GtkWidget *scale_scale;
GtkWidget *crash_warning;
GtkWidget *renderer_listbox;
GListStore *renderers;
@@ -64,6 +67,9 @@ struct _NodeEditorWindow
GFileMonitor *file_monitor;
GArray *errors;
guint update_timeout;
gboolean auto_reload;
};
struct _NodeEditorWindowClass
@@ -71,6 +77,13 @@ struct _NodeEditorWindowClass
GtkApplicationWindowClass parent_class;
};
enum {
PROP_AUTO_RELOAD = 1,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
G_DEFINE_TYPE(NodeEditorWindow, node_editor_window, GTK_TYPE_APPLICATION_WINDOW);
static void
@@ -163,19 +176,84 @@ text_iter_skip_whitespace_backward (GtkTextIter *iter)
}
static void
text_changed (GtkTextBuffer *buffer,
NodeEditorWindow *self)
highlight_text (NodeEditorWindow *self)
{
GtkTextIter iter;
GtkTextIter start, end;
gtk_text_buffer_get_start_iter (self->text_buffer, &iter);
while (!gtk_text_iter_is_end (&iter))
{
gunichar c = gtk_text_iter_get_char (&iter);
if (c == '{')
{
GtkTextIter word_end = iter;
GtkTextIter word_start;
gtk_text_iter_backward_char (&word_end);
text_iter_skip_whitespace_backward (&word_end);
word_start = word_end;
gtk_text_iter_backward_word_start (&word_start);
text_iter_skip_alpha_backward (&word_start);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "nodename", &word_start, &word_end);
}
else if (c == ':')
{
GtkTextIter word_end = iter;
GtkTextIter word_start;
gtk_text_iter_backward_char (&word_end);
text_iter_skip_whitespace_backward (&word_end);
word_start = word_end;
gtk_text_iter_backward_word_start (&word_start);
text_iter_skip_alpha_backward (&word_start);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "propname", &word_start, &word_end);
}
else if (c == '"')
{
GtkTextIter string_start = iter;
GtkTextIter string_end = iter;
gtk_text_iter_forward_char (&iter);
while (!gtk_text_iter_is_end (&iter))
{
c = gtk_text_iter_get_char (&iter);
if (c == '"')
{
gtk_text_iter_forward_char (&iter);
string_end = iter;
break;
}
gtk_text_iter_forward_char (&iter);
}
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "string", &string_start, &string_end);
}
gtk_text_iter_forward_char (&iter);
}
gtk_text_buffer_get_bounds (self->text_buffer, &start, &end);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "no-hyphens", &start, &end);
}
static void
reload (NodeEditorWindow *self)
{
char *text;
GBytes *bytes;
GtkTextIter iter;
GtkTextIter start, end;
float scale;
GskRenderNode *big_node;
g_array_remove_range (self->errors, 0, self->errors->len);
text = get_current_text (self->text_buffer);
text_buffer_remove_all_tags (self->text_buffer);
bytes = g_bytes_new_take (text, strlen (text));
g_clear_pointer (&self->node, gsk_render_node_unref);
@@ -236,73 +314,19 @@ text_changed (GtkTextBuffer *buffer,
}
g_clear_pointer (&big_node, gsk_render_node_unref);
}
gtk_text_buffer_get_start_iter (self->text_buffer, &iter);
static void
text_changed (GtkTextBuffer *buffer,
NodeEditorWindow *self)
{
g_array_remove_range (self->errors, 0, self->errors->len);
text_buffer_remove_all_tags (self->text_buffer);
while (!gtk_text_iter_is_end (&iter))
{
gunichar c = gtk_text_iter_get_char (&iter);
if (self->auto_reload)
reload (self);
if (c == '{')
{
GtkTextIter word_end = iter;
GtkTextIter word_start;
gtk_text_iter_backward_char (&word_end);
text_iter_skip_whitespace_backward (&word_end);
word_start = word_end;
gtk_text_iter_backward_word_start (&word_start);
text_iter_skip_alpha_backward (&word_start);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "nodename",
&word_start, &word_end);
}
else if (c == ':')
{
GtkTextIter word_end = iter;
GtkTextIter word_start;
gtk_text_iter_backward_char (&word_end);
text_iter_skip_whitespace_backward (&word_end);
word_start = word_end;
gtk_text_iter_backward_word_start (&word_start);
text_iter_skip_alpha_backward (&word_start);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "propname",
&word_start, &word_end);
}
else if (c == '"')
{
GtkTextIter string_start = iter;
GtkTextIter string_end = iter;
gtk_text_iter_forward_char (&iter);
while (!gtk_text_iter_is_end (&iter))
{
c = gtk_text_iter_get_char (&iter);
if (c == '"')
{
gtk_text_iter_forward_char (&iter);
string_end = iter;
break;
}
gtk_text_iter_forward_char (&iter);
}
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "string",
&string_start, &string_end);
}
gtk_text_iter_forward_char (&iter);
}
gtk_text_buffer_get_bounds (self->text_buffer, &start, &end);
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "no-hyphens",
&start, &end);
highlight_text (self);
}
static void
@@ -1101,6 +1125,9 @@ node_editor_window_finalize (GObject *object)
{
NodeEditorWindow *self = (NodeEditorWindow *)object;
if (self->update_timeout)
g_source_remove (self->update_timeout);
g_array_free (self->errors, TRUE);
g_clear_pointer (&self->node, gsk_render_node_unref);
@@ -1540,6 +1567,79 @@ edit_action_cb (GtkWidget *widget,
node_editor_window_edit (self, &start);
}
static void
node_editor_window_map (GtkWidget *widget)
{
char *path;
GTK_WIDGET_CLASS (node_editor_window_parent_class)->map (widget);
path = get_autosave_path (NULL);
if (g_file_test (path, G_FILE_TEST_EXISTS))
{
g_free (path);
return;
}
g_free (path);
}
static void
node_editor_window_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NodeEditorWindow *self = NODE_EDITOR_WINDOW (object);
switch (prop_id)
{
case PROP_AUTO_RELOAD:
{
gboolean auto_reload = g_value_get_boolean (value);
if (self->auto_reload != auto_reload)
{
self->auto_reload = auto_reload;
if (self->auto_reload)
reload (self);
}
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
node_editor_window_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NodeEditorWindow *self = NODE_EDITOR_WINDOW (object);
switch (prop_id)
{
case PROP_AUTO_RELOAD:
g_value_set_boolean (value, self->auto_reload);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
close_crash_warning (GtkButton *button,
NodeEditorWindow *self)
{
gtk_revealer_set_reveal_child (GTK_REVEALER (self->crash_warning), FALSE);
}
static void
node_editor_window_class_init (NodeEditorWindowClass *class)
{
@@ -1551,6 +1651,8 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
object_class->dispose = node_editor_window_dispose;
object_class->finalize = node_editor_window_finalize;
object_class->set_property = node_editor_window_set_property;
object_class->get_property = node_editor_window_get_property;
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/node-editor/node-editor-window.ui");
@@ -1558,6 +1660,14 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
widget_class->realize = node_editor_window_realize;
widget_class->unrealize = node_editor_window_unrealize;
widget_class->map = node_editor_window_map;
properties[PROP_AUTO_RELOAD] = g_param_spec_boolean ("auto-reload", NULL, NULL,
TRUE,
G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME);
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, text_view);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, picture);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, renderer_listbox);
@@ -1567,6 +1677,7 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_name_entry);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_save_button);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, scale_scale);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, crash_warning);
gtk_widget_class_bind_template_callback (widget_class, text_view_query_tooltip_cb);
gtk_widget_class_bind_template_callback (widget_class, open_cb);
@@ -1579,6 +1690,7 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
gtk_widget_class_bind_template_callback (widget_class, on_picture_drag_prepare_cb);
gtk_widget_class_bind_template_callback (widget_class, on_picture_drop_cb);
gtk_widget_class_bind_template_callback (widget_class, click_gesture_pressed);
gtk_widget_class_bind_template_callback (widget_class, close_crash_warning);
gtk_widget_class_install_action (widget_class, "smart-edit", NULL, edit_action_cb);
@@ -1630,11 +1742,133 @@ static GActionEntry win_entries[] = {
{ "open", window_open, NULL, NULL, NULL },
};
char *
get_autosave_path (const char *suffix)
{
char *path;
char *name;
name = g_strconcat ("autosave", suffix, NULL);
path = g_build_filename (g_get_user_cache_dir (), "gtk4-node-editor", name, NULL);
g_free (name);
return path;
}
static void
set_initial_text (NodeEditorWindow *self)
{
char *path, *path1;
char *initial_text;
gsize len;
path = get_autosave_path (NULL);
path1 = get_autosave_path ("-unsafe");
if (g_file_get_contents (path, &initial_text, &len, NULL))
{
gtk_text_buffer_set_text (self->text_buffer, initial_text, len);
g_free (initial_text);
}
else if (g_file_get_contents (path1, &initial_text, &len, NULL))
{
self->auto_reload = FALSE;
gtk_revealer_set_reveal_child (GTK_REVEALER (self->crash_warning), TRUE);
gtk_text_buffer_set_text (self->text_buffer, initial_text, len);
g_free (initial_text);
}
else
{
/* Default */
gtk_text_buffer_set_text (self->text_buffer,
"shadow {\n"
" child: texture {\n"
" bounds: 0 0 128 128;\n"
" texture: url(\"resource:///org/gtk/gtk4/node-editor/icons/apps/org.gtk.gtk4.NodeEditor.svg\");\n"
" }\n"
" shadows: rgba(0,0,0,0.5) 0 1 12;\n"
"}\n"
"\n"
"transform {\n"
" child: text {\n"
" color: rgb(46,52,54);\n"
" font: \"Cantarell Bold 11\";\n"
" glyphs: \"GTK Node Editor\";\n"
" offset: 8 14.418;\n"
" }\n"
" transform: translate(0, 140);\n"
"}", -1);
}
g_free (path);
g_free (path1);
}
static void
autosave_contents (NodeEditorWindow *self)
{
char *path = NULL;
char *dir = NULL;
char *contents;
GtkTextIter start, end;
gtk_text_buffer_get_bounds (self->text_buffer, &start, &end);
contents = gtk_text_buffer_get_text (self->text_buffer, &start, &end, TRUE);
path = get_autosave_path ("-unsafe");
dir = g_path_get_dirname (path);
g_mkdir_with_parents (dir, 0755);
g_file_set_contents (path, contents, -1, NULL);
g_free (dir);
g_free (path);
g_free (contents);
}
static void
mark_autosave_as_safe (void)
{
char *path1 = NULL;
char *path2 = NULL;
path1 = get_autosave_path ("-unsafe");
path2 = get_autosave_path (NULL);
g_rename (path1, path2);
}
static gboolean
update_timeout_cb (gpointer data)
{
NodeEditorWindow *self = data;
self->update_timeout = 0;
mark_autosave_as_safe ();
return G_SOURCE_REMOVE;
}
static void
initiate_autosave (NodeEditorWindow *self)
{
autosave_contents (self);
if (self->update_timeout != 0)
g_source_remove (self->update_timeout);
self->update_timeout = g_timeout_add (100, update_timeout_cb, self);
}
static void
node_editor_window_init (NodeEditorWindow *self)
{
GAction *action;
gtk_widget_init_template (GTK_WIDGET (self));
self->auto_reload = TRUE;
self->renderers = g_list_store_new (GDK_TYPE_PAINTABLE);
gtk_list_box_bind_model (GTK_LIST_BOX (self->renderer_listbox),
G_LIST_MODEL (self->renderers),
@@ -1647,6 +1881,10 @@ node_editor_window_init (NodeEditorWindow *self)
g_action_map_add_action_entries (G_ACTION_MAP (self), win_entries, G_N_ELEMENTS (win_entries), self);
action = G_ACTION (g_property_action_new ("auto-reload", self, "auto-reload"));
g_action_map_add_action (G_ACTION_MAP (self), action);
g_object_unref (action);
self->tag_table = gtk_text_tag_table_new ();
gtk_text_tag_table_add (self->tag_table,
g_object_new (GTK_TYPE_TEXT_TAG,
@@ -1684,25 +1922,9 @@ node_editor_window_init (NodeEditorWindow *self)
g_signal_connect (self->scale_scale, "notify::value", G_CALLBACK (scale_changed), self);
gtk_text_view_set_buffer (GTK_TEXT_VIEW (self->text_view), self->text_buffer);
/* Default */
gtk_text_buffer_set_text (self->text_buffer,
"shadow {\n"
" child: texture {\n"
" bounds: 0 0 128 128;\n"
" texture: url(\"resource:///org/gtk/gtk4/node-editor/icons/apps/org.gtk.gtk4.NodeEditor.svg\");\n"
" }\n"
" shadows: rgba(0,0,0,0.5) 0 1 12;\n"
"}\n"
"\n"
"transform {\n"
" child: text {\n"
" color: rgb(46,52,54);\n"
" font: \"Cantarell Bold 11\";\n"
" glyphs: \"GTK Node Editor\";\n"
" offset: 8 14.418;\n"
" }\n"
" transform: translate(0, 140);\n"
"}", -1);
set_initial_text (self);
g_signal_connect_swapped (self->text_buffer, "changed", G_CALLBACK (initiate_autosave), self);
if (g_getenv ("GSK_RENDERER"))
{
+2
View File
@@ -37,3 +37,5 @@ NodeEditorWindow * node_editor_window_new (NodeEditorApplication
gboolean node_editor_window_load (NodeEditorWindow *self,
GFile *file);
char * get_autosave_path (const char *suffix);
+113 -65
View File
@@ -2,6 +2,14 @@
<interface>
<menu id="gear_menu">
<section>
<item>
<attribute name="label" translatable="yes">_Reload automatically</attribute>
<attribute name="action">win.auto-reload</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Help</attribute>
<attribute name="action">app.help</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Help</attribute>
<attribute name="action">app.help</attribute>
@@ -24,7 +32,6 @@
</item>
</section>
</menu>
<object class="GtkPopover" id="testcase_popover">
<child>
<object class="GtkGrid">
@@ -39,7 +46,7 @@
<object class="GtkEntry" id="testcase_name_entry">
<property name="hexpand">1</property>
<property name="activates-default">1</property>
<signal name="notify::text" handler="testcase_name_entry_changed_cb" />
<signal name="notify::text" handler="testcase_name_entry_changed_cb"/>
</object>
</child>
<child>
@@ -52,7 +59,6 @@
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="wrap">1</property>
@@ -66,7 +72,6 @@
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="testcase_error_label">
<property name="wrap">1</property>
@@ -78,7 +83,6 @@
</layout>
</object>
</child>
<child>
<object class="GtkButton" id="testcase_save_button">
<property name="label">Save</property>
@@ -86,9 +90,9 @@
<property name="halign">end</property>
<property name="receives-default">1</property>
<property name="sensitive">0</property>
<signal name="clicked" handler="testcase_save_clicked_cb" />
<signal name="clicked" handler="testcase_save_clicked_cb"/>
<style>
<class name="suggested-action" />
<class name="suggested-action"/>
</style>
<layout>
<property name="row">4</property>
@@ -100,7 +104,6 @@
</object>
</child>
</object>
<template class="NodeEditorWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">GTK Node Editor</property>
<property name="default-width">1024</property>
@@ -185,83 +188,128 @@
</object>
</child>
<child>
<object class="GtkPaned">
<property name="shrink-start-child">false</property>
<property name="shrink-end-child">false</property>
<property name="position">400</property>
<property name="start-child">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="wrap-mode">word</property>
<property name="monospace">1</property>
<property name="top-margin">6</property>
<property name="left-margin">6</property>
<property name="right-margin">6</property>
<property name="bottom-margin">6</property>
<property name="has-tooltip">1</property>
<property name="extra-menu">extra_menu</property>
<signal name="query-tooltip" handler="text_view_query_tooltip_cb"/>
<object class="GtkOverlay">
<child type="overlay">
<object class="GtkRevealer" id="crash_warning">
<property name="transition-type">slide-down</property>
<property name="halign">center</property>
<property name="valign">start</property>
<property name="child">
<object class="GtkFrame">
<style>
<class name="editor" />
<class name="app-notification"/>
</style>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">20</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<child>
<object class="GtkLabel">
<property name="hexpand">1</property>
<property name="halign">1</property>
<property name="label" translatable="1">The application may have crashed.
As a precaution, auto-loading has been turned off.
</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="valign">3</property>
<property name="use-underline">1</property>
<property name="label" translatable="1">_Close</property>
<signal name="clicked" handler="close_crash_warning"/>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</child>
<property name="child">
<object class="GtkPaned">
<property name="shrink-start-child">false</property>
<property name="shrink-end-child">false</property>
<property name="position">400</property>
<property name="start-child">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child>
<object class="GtkGestureClick">
<property name="button">1</property>
<signal name="pressed" handler="click_gesture_pressed"/>
<object class="GtkTextView" id="text_view">
<property name="wrap-mode">word</property>
<property name="monospace">1</property>
<property name="top-margin">6</property>
<property name="left-margin">6</property>
<property name="right-margin">6</property>
<property name="bottom-margin">6</property>
<property name="has-tooltip">1</property>
<property name="extra-menu">extra_menu</property>
<signal name="query-tooltip" handler="text_view_query_tooltip_cb"/>
<style>
<class name="editor"/>
</style>
<child>
<object class="GtkGestureClick">
<property name="button">1</property>
<signal name="pressed" handler="click_gesture_pressed"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
<property name="end-child">
<object class="GtkBox">
<child>
<object class="GtkScrolledWindow">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="min-content-height">100</property>
<property name="min-content-width">100</property>
</property>
<property name="end-child">
<object class="GtkBox">
<child>
<object class="GtkViewport">
<object class="GtkScrolledWindow">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="min-content-height">100</property>
<property name="min-content-width">100</property>
<child>
<object class="GtkPicture" id="picture">
<property name="can-shrink">0</property>
<property name="halign">center</property>
<property name="valign">center</property>
<object class="GtkViewport">
<child>
<object class="GtkDragSource">
<object class="GtkPicture" id="picture">
<property name="can-shrink">0</property>
<property name="halign">center</property>
<property name="valign">center</property>
<child>
<object class="GtkDragSource">
<property name="actions">copy</property>
<signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkDropTargetAsync">
<property name="actions">copy</property>
<signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/>
<property name="formats">application/x-gtk-render-node</property>
<signal name="drop" handler="on_picture_drop_cb" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkDropTargetAsync">
<property name="actions">copy</property>
<property name="formats">application/x-gtk-render-node</property>
<signal name="drop" handler="on_picture_drop_cb" swapped="no"/>
<object class="GtkListBox" id="renderer_listbox">
<property name="selection-mode">none</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkListBox" id="renderer_listbox">
<property name="selection-mode">none</property>
</object>
</child>
</object>
</child>
</property>
</object>
</property>
</object>
+22 -10
View File
@@ -322,27 +322,39 @@ stroke bounds of the path.
### text
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| color | `<color>` | black | non-default |
| font | `<string>` | "Cantarell 11" | always |
| glyphs | `<glyphs>` | "Hello" | always |
| offset | `<point>` | 0 0 | non-default |
| property | syntax | default | printed |
| -------- | ------------------- | ------------------- | ----------- |
| color | `<color>` | black | non-default |
| font | `<string>` `<url>`? | "Cantarell 11" | always |
| glyphs | `<glyphs>` | "Hello" | always |
| offset | `<point>` | 0 0 | non-default |
Creates a node like `gsk_text_node_new()` with the given properties.
If a url is specified for the font, it must point to a font file for the
font that is specified in the string. It can be either a data url containing
a base64-encoded font file, or a regular url that points to a font file.
Glyphs can be specified as an ASCII string, or as a comma-separated list of
their glyph ID and advance width. Optionally, x and y offsets and flags can
be specified as well, like this: 40 10 0 0 color.
If the given font does not exist or the given glyphs are invalid for the given
font, an error node will be returned.
### texture
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| bounds | `<rect>` | 50 | always |
| texture | `<url>` | *see below* | always |
| property | syntax | default | printed |
| -------- | ------------------- | ---------------------- | ----------- |
| bounds | `<rect>` | 50 | always |
| texture | `<string>`?`<url>`? | *see below* | always |
Creates a node like `gsk_texture_node_new()` with the given properties.
If a string is specified for the texture, it will be used as a name for the text.
Textures can be reused by specifying the name of a previously used texture. In
that case, the url can be omitted.
The default texture is a 10x10 checkerboard with the top left and bottom right
5x5 being in the color #FF00CC and the other part being transparent. A possible
representation for this texture is `url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABmJLR0QA/wD/AP+gvaeTAAAAKUlEQVQYlWP8z3DmPwMaYGQwYUQXY0IXwAUGUCGGoxkYGBiweXAoeAYAz44F3e3U1xUAAAAASUVORK5CYII=")
+24 -2
View File
@@ -11,13 +11,17 @@ Editor render nodes
SYNOPSIS
--------
| **gtk4-node-editor** [OPTIONS...]
| **gtk4-node-editor** [OPTIONS...] [FILE]
DESCRIPTION
-----------
``gtk4-node-editor`` is a utility to show and edit render node files.
Such render node files can be obtained e.g. from the GTK inspector.
Such render node files can be obtained e.g. from the GTK inspector or
as part of the testsuite in the GTK sources.
``gtk4-node-editor`` is used by GTK developers for debugging and testing,
and it has built-in support for saving testcases as part of the GTK testsuite.
OPTIONS
-------
@@ -25,3 +29,21 @@ OPTIONS
``-h, --help``
Show the application help.
``--version``
Show the program version.
``--reset``
Don't restore autosaved content and remove autosave files.
ENVIRONMENT
-----------
``GTK_SOURCE_DIR``
can be set to point to the location where the GTK sources reside, so that
testcases can be saved to the right location. If unsed, `gtk4-node-editor``
checks if the current working directory looks like a GTK checkout, and failing
that, saves testcase in the the current working directory.
+30 -1
View File
@@ -12,9 +12,10 @@ SYNOPSIS
--------
| **gtk4-rendernode-tool** <COMMAND> [OPTIONS...] <FILE>
|
| **gtk4-rendernode-tool** benchmark [OPTIONS...] <FILE>
| **gtk4-rendernode-tool** info [OPTIONS...] <FILE>
| **gtk4-rendernode-tool** show [OPTIONS...] <FILE>
| **gtk4-rendernode-tool** render [OPTIONS...] <FILE> [<FILE>]
| **gtk4-rendernode-tool** show [OPTIONS...] <FILE>
DESCRIPTION
-----------
@@ -50,3 +51,31 @@ The name of the file to write can be specified as a second FILE argument.
Use the given renderer. Use ``--renderer=help`` to get a information
about poassible values for the ``RENDERER``.
Benchmark
^^^^^^^^^
The ``benchmark`` command benchmarks rendering of a node with the existing renderers
and prints the runtimes.
``--renderer=RENDERER``
Add the given renderer. This argument can be passed multiple times to test multiple
renderers. By default, all major GTK renderers are run.
``--runs=RUNS``
Number of times to render the node on each renderer. By default, this is 3 times.
Keep in mind that the first run is often used to populate caches and might be
significantly slower.
``--no-download``
Do not attempt to download the result. This may cause the measurement to not include
the execution of the commands on the GPU. It can be useful to use this flag to test
command submission performance.
+2 -1
View File
@@ -289,7 +289,8 @@ gdk_device_class_init (GdkDeviceClass *klass)
*/
device_props[PROP_MODIFIER_STATE] =
g_param_spec_flags ("modifier-state", NULL, NULL,
GDK_TYPE_MODIFIER_TYPE, 0,
GDK_TYPE_MODIFIER_TYPE,
GDK_NO_MODIFIER_MASK,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROP, device_props);
+1 -1
View File
@@ -194,7 +194,7 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
if ((image->width % cursor_scale != 0) ||
(image->height % cursor_scale != 0))
{
g_warning (G_STRLOC " cursor image size (%dx%d) not an integer"
g_warning (G_STRLOC " cursor image size (%dx%d) not an integer "
"multiple of scale (%d)", image->width, image->height,
cursor_scale);
cursor_scale = 1;
+2 -8
View File
@@ -1796,6 +1796,7 @@ static TranslationEntry translations[] = {
{ FALSE, "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } },
{ FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } },
{ FALSE, "org.gnome.desktop.a11y.interface", "high-contrast", "high-contast", G_TYPE_NONE, { .b = FALSE } },
{ FALSE, "org.gnome.desktop.a11y.interface", "show-status-shapes", "gtk-show-status-shapes", G_TYPE_BOOLEAN, { .b = FALSE } },
/* Note, this setting doesn't exist, the portal and gsd fake it */
{ FALSE, "org.gnome.fontconfig", "serial", "gtk-fontconfig-timestamp", G_TYPE_NONE, { .i = 0 } },
};
@@ -1845,13 +1846,6 @@ find_translation_entry_by_setting (const char *setting)
return NULL;
}
static void
high_contrast_changed (GdkDisplay *display)
{
gdk_display_setting_changed (display, "gtk-theme-name");
gdk_display_setting_changed (display, "gtk-icon-theme-name");
}
static void
settings_changed (GSettings *settings,
const char *key,
@@ -1866,7 +1860,7 @@ settings_changed (GSettings *settings,
if (entry->type != G_TYPE_NONE)
gdk_display_setting_changed (display, entry->setting);
else if (strcmp (key, "high-contrast") == 0)
high_contrast_changed (display);
gdk_display_setting_changed (display, "gtk-theme-name");
else
update_xft_settings (display);
}
+1
View File
@@ -2859,6 +2859,7 @@ tablet_tool_handle_proximity_out (void *data,
gdk_device_update_tool (tablet->stylus_device, NULL);
g_clear_object (&tablet->pointer_info.cursor);
tablet->pointer_info.cursor_is_default = FALSE;
}
static double *
+1
View File
@@ -39,6 +39,7 @@ static const struct {
{"Gtk/CursorThemeSize", "gtk-cursor-theme-size"},
{"Gtk/ColorScheme", "gtk-color-scheme"},
{"Gtk/EnableAnimations", "gtk-enable-animations"},
{"Gtk/ShowStatusStates", "gtk-show-status-shapes"},
{"Xft/Antialias", "gtk-xft-antialias"},
{"Xft/Hinting", "gtk-xft-hinting"},
{"Xft/HintStyle", "gtk-xft-hintstyle"},
+1 -1
View File
@@ -119,7 +119,7 @@ gsk_gl_device_create_atlas_image (GskGpuDevice *device,
GskGLDevice *self = GSK_GL_DEVICE (device);
return gsk_gl_image_new (self,
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
GDK_MEMORY_DEFAULT,
GSK_GPU_IMAGE_RENDERABLE,
width,
height);
+21 -11
View File
@@ -14,6 +14,14 @@ gsk_gpu_clip_init_empty (GskGpuClip *clip,
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
}
void
gsk_gpu_clip_init_contained (GskGpuClip *clip,
const graphene_rect_t *rect)
{
clip->type = GSK_GPU_CLIP_CONTAINED;
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
}
void
gsk_gpu_clip_init_rect (GskGpuClip *clip,
const graphene_rect_t *rect)
@@ -54,17 +62,6 @@ gsk_gpu_clip_intersect_rect (GskGpuClip *dest,
{
GskRoundedRectIntersection res;
if (gsk_rect_contains_rect (rect, &src->rect.bounds))
{
gsk_gpu_clip_init_copy (dest, src);
return TRUE;
}
if (!gsk_rect_intersects (rect, &src->rect.bounds))
{
dest->type = GSK_GPU_CLIP_ALL_CLIPPED;
return TRUE;
}
switch (src->type)
{
case GSK_GPU_CLIP_ALL_CLIPPED:
@@ -72,6 +69,14 @@ gsk_gpu_clip_intersect_rect (GskGpuClip *dest,
break;
case GSK_GPU_CLIP_NONE:
if (gsk_rect_contains_rect (rect, &src->rect.bounds))
{
gsk_gpu_clip_init_copy (dest, src);
return TRUE;
}
G_GNUC_FALLTHROUGH;
case GSK_GPU_CLIP_CONTAINED:
gsk_gpu_clip_init_copy (dest, src);
if (gsk_rect_intersection (&dest->rect.bounds, rect, &dest->rect.bounds))
dest->type = GSK_GPU_CLIP_RECT;
@@ -124,6 +129,7 @@ gsk_gpu_clip_intersect_rounded_rect (GskGpuClip *dest,
break;
case GSK_GPU_CLIP_NONE:
case GSK_GPU_CLIP_CONTAINED:
case GSK_GPU_CLIP_RECT:
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);
if (!gsk_gpu_clip_init_after_intersection (dest, res))
@@ -174,6 +180,7 @@ gsk_gpu_clip_transform (GskGpuClip *dest,
return TRUE;
case GSK_GPU_CLIP_NONE:
case GSK_GPU_CLIP_CONTAINED:
case GSK_GPU_CLIP_RECT:
case GSK_GPU_CLIP_ROUNDED:
switch (gsk_transform_get_category (transform))
@@ -246,6 +253,7 @@ gsk_gpu_clip_may_intersect_rect (const GskGpuClip *self,
return FALSE;
case GSK_GPU_CLIP_NONE:
case GSK_GPU_CLIP_CONTAINED:
case GSK_GPU_CLIP_RECT:
case GSK_GPU_CLIP_ROUNDED:
return gsk_rect_intersects (&self->rect.bounds, &r);
@@ -269,6 +277,7 @@ gsk_gpu_clip_contains_rect (const GskGpuClip *self,
return FALSE;
case GSK_GPU_CLIP_NONE:
case GSK_GPU_CLIP_CONTAINED:
case GSK_GPU_CLIP_RECT:
return gsk_rect_contains_rect (&self->rect.bounds, &r);
@@ -283,6 +292,7 @@ gsk_gpu_clip_get_shader_clip (const GskGpuClip *self,
const graphene_rect_t *rect)
{
if (self->type == GSK_GPU_CLIP_NONE ||
self->type == GSK_GPU_CLIP_CONTAINED ||
gsk_gpu_clip_contains_rect (self, offset, rect))
return GSK_GPU_SHADER_CLIP_NONE;
else if (self->type == GSK_GPU_CLIP_RECT)
+5
View File
@@ -18,6 +18,9 @@ typedef enum {
* to the actual bounds of the underlying framebuffer
*/
GSK_GPU_CLIP_NONE,
/* The clip exists outside the rect, so clipping must
* happen if rendering can't be proven to stay in the rect */
GSK_GPU_CLIP_CONTAINED,
/* The clip is a rectangular area */
GSK_GPU_CLIP_RECT,
/* The clip is a rounded rectangle */
@@ -34,6 +37,8 @@ struct _GskGpuClip
void gsk_gpu_clip_init_empty (GskGpuClip *clip,
const graphene_rect_t *rect);
void gsk_gpu_clip_init_contained (GskGpuClip *clip,
const graphene_rect_t *rect);
void gsk_gpu_clip_init_copy (GskGpuClip *self,
const GskGpuClip *src);
void gsk_gpu_clip_init_rect (GskGpuClip *clip,
+10 -16
View File
@@ -663,17 +663,10 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
cache = g_new (GskGpuCachedGlyph, 1);
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
pango_extents_to_pixels (&ink_rect, NULL);
ink_rect.x -= 1;
ink_rect.width += 2;
ink_rect.y -= 1;
ink_rect.height += 2;
origin.x = floor (ink_rect.x * scale);
origin.y = floor (ink_rect.y * scale);
rect.size.width = ceil ((ink_rect.x + ink_rect.width) * scale) - origin.x;
rect.size.height = ceil ((ink_rect.y + ink_rect.height) * scale) - origin.y;
origin.x = floor (ink_rect.x * scale / PANGO_SCALE);
origin.y = floor (ink_rect.y * scale / PANGO_SCALE);
rect.size.width = ceil ((ink_rect.x + ink_rect.width) * scale / PANGO_SCALE) - origin.x;
rect.size.height = ceil ((ink_rect.y + ink_rect.height) * scale / PANGO_SCALE) - origin.y;
padding = 1;
image = gsk_gpu_device_add_atlas_image (self,
@@ -689,9 +682,10 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
}
else
{
image = gsk_gpu_device_create_upload_image (self, FALSE, GDK_MEMORY_DEFAULT, rect.size.width + 2 * padding, rect.size.height + 2 * padding),
rect.origin.x = padding;
rect.origin.y = padding;
image = gsk_gpu_device_create_upload_image (self, FALSE, GDK_MEMORY_DEFAULT, rect.size.width, rect.size.height),
rect.origin.x = 0;
rect.origin.y = 0;
padding = 0;
cache = gsk_gpu_cached_new (self, &GSK_GPU_CACHED_GLYPH_CLASS, NULL);
}
@@ -715,8 +709,8 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
.height = rect.size.height + 2 * padding,
},
scale,
&GRAPHENE_POINT_INIT (cache->origin.x + 1,
cache->origin.y + 1));
&GRAPHENE_POINT_INIT (cache->origin.x + padding,
cache->origin.y + padding));
g_hash_table_insert (priv->glyph_cache, cache, cache);
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
+52 -39
View File
@@ -305,9 +305,10 @@ gsk_gpu_node_processor_add_images (GskGpuNodeProcessor *self,
}
static void
rect_round_to_pixels (const graphene_rect_t *src,
const graphene_vec2_t *pixel_scale,
graphene_rect_t *dest)
rect_round_to_pixels (const graphene_rect_t *src,
const graphene_vec2_t *pixel_scale,
const graphene_point_t *pixel_offset,
graphene_rect_t *dest)
{
float x, y, xscale, yscale, inv_xscale, inv_yscale;
@@ -316,13 +317,13 @@ rect_round_to_pixels (const graphene_rect_t *src,
inv_xscale = 1.0f / xscale;
inv_yscale = 1.0f / yscale;
x = floorf (src->origin.x * xscale);
y = floorf (src->origin.y * yscale);
x = floorf ((src->origin.x + pixel_offset->x) * xscale);
y = floorf ((src->origin.y + pixel_offset->y) * yscale);
*dest = GRAPHENE_RECT_INIT (
x * inv_xscale,
y * inv_yscale,
(ceil ((src->origin.x + src->size.width) * xscale) - x) * inv_xscale,
(ceil ((src->origin.y + src->size.height) * yscale) - y) * inv_yscale);
x * inv_xscale - pixel_offset->x,
y * inv_yscale - pixel_offset->y,
(ceil ((src->origin.x + pixel_offset->x + src->size.width) * xscale) - x) * inv_xscale,
(ceil ((src->origin.y + pixel_offset->y + src->size.height) * yscale) - y) * inv_yscale);
}
static GskGpuImage *
@@ -787,7 +788,6 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame,
gsk_rect_intersection (clip_bounds, &node->bounds, &clipped);
if (gsk_rect_is_empty (&clipped))
return NULL;
rect_round_to_pixels (&clipped, scale, &clipped);
result = gsk_gpu_upload_cairo_op (frame,
scale,
@@ -808,7 +808,6 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame,
gsk_rect_intersection (clip_bounds, &node->bounds, &clipped);
if (gsk_rect_is_empty (&clipped))
return NULL;
rect_round_to_pixels (&clipped, scale, &clipped);
GSK_DEBUG (FALLBACK, "Offscreening node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
result = gsk_gpu_render_pass_op_offscreen (frame,
@@ -931,17 +930,18 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self,
graphene_rect_t *out_bounds)
{
GskGpuImage *image, *ensure;
graphene_rect_t default_clip;
graphene_rect_t clip;
if (clip_bounds == NULL)
{
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &default_clip))
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip))
return NULL;
clip_bounds = &default_clip;
clip_bounds = &clip;
}
rect_round_to_pixels (clip_bounds, &self->scale, &self->offset, &clip);
image = gsk_gpu_get_node_as_image (self->frame,
clip_bounds,
&clip,
&self->scale,
node,
out_bounds);
@@ -1073,6 +1073,8 @@ gsk_gpu_node_processor_add_fallback_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clipped_bounds))
return;
rect_round_to_pixels (&clipped_bounds, &self->scale, &self->offset, &clipped_bounds);
gsk_gpu_node_processor_sync_globals (self, 0);
image = gsk_gpu_upload_cairo_op (self->frame,
@@ -1426,7 +1428,7 @@ gsk_gpu_node_processor_add_rounded_clip_node_with_mask (GskGpuNodeProcessor *sel
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
rect_round_to_pixels (&clip_bounds, &self->scale, &clip_bounds);
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
child_image = gsk_gpu_node_processor_get_node_as_image (self,
0,
@@ -1589,7 +1591,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
if (gsk_gpu_clip_contains_rect (&self->clip, &self->offset, &node->bounds))
{
gsk_gpu_clip_init_empty (&self->clip, &child->bounds);
gsk_gpu_clip_init_contained (&self->clip, &child->bounds);
}
else if (old_clip.type == GSK_GPU_CLIP_NONE)
{
@@ -1598,7 +1600,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
inverse = gsk_transform_invert (gsk_transform_ref (clip_transform));
gsk_transform_transform_bounds (inverse, &old_clip.rect.bounds, &new_bounds);
gsk_transform_unref (inverse);
gsk_gpu_clip_init_empty (&self->clip, &new_bounds);
gsk_gpu_clip_init_contained (&self->clip, &new_bounds);
}
else if (!gsk_gpu_clip_transform (&self->clip, &old_clip, clip_transform, &child->bounds))
{
@@ -2250,7 +2252,7 @@ gsk_gpu_node_processor_add_gradient_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &bounds))
return;
rect_round_to_pixels (&bounds, &self->scale, &bounds);
rect_round_to_pixels (&bounds, &self->scale, &self->offset, &bounds);
image = gsk_gpu_node_processor_init_draw (&other,
self->frame,
@@ -3018,7 +3020,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
if (gsk_text_node_has_color_glyphs (node))
if (glyphs[i].attr.is_color)
gsk_gpu_texture_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &glyph_offset, &glyph_bounds),
self->desc,
@@ -3096,21 +3098,26 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
last_image = image;
}
graphene_rect_scale (&glyph_bounds, inv_scale, inv_scale, &glyph_bounds);
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
gsk_gpu_pattern_writer_append_uint (self, tex_id);
gsk_gpu_pattern_writer_append_rect (self,
&glyph_bounds,
&glyph_offset);
&GRAPHENE_RECT_INIT (
0,
0,
glyph_bounds.size.width * inv_scale,
glyph_bounds.size.height * inv_scale
),
&glyph_offset);
gsk_gpu_pattern_writer_append_rect (self,
&GRAPHENE_RECT_INIT (
0, 0,
gsk_gpu_image_get_width (image) * inv_scale,
gsk_gpu_image_get_height (image) * inv_scale
),
&glyph_offset);
&GRAPHENE_RECT_INIT (
- glyph_bounds.origin.x * inv_scale,
- glyph_bounds.origin.y * inv_scale,
gsk_gpu_image_get_width (image) * inv_scale,
gsk_gpu_image_get_height (image) * inv_scale
),
&glyph_offset);
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
}
@@ -3476,6 +3483,7 @@ gsk_gpu_node_processor_add_fill_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
child = gsk_fill_node_get_child (node);
@@ -3517,9 +3525,9 @@ gsk_gpu_node_processor_add_fill_node (GskGpuNodeProcessor *self,
descriptors);
gsk_gpu_mask_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &clip_bounds),
self->desc,
&node->bounds,
&clip_bounds,
&self->offset,
self->opacity,
GSK_MASK_MODE_ALPHA,
@@ -3572,6 +3580,7 @@ gsk_gpu_node_processor_add_stroke_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
child = gsk_stroke_node_get_child (node);
@@ -3613,9 +3622,9 @@ gsk_gpu_node_processor_add_stroke_node (GskGpuNodeProcessor *self,
descriptors);
gsk_gpu_mask_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &clip_bounds),
self->desc,
&node->bounds,
&clip_bounds,
&self->offset,
self->opacity,
GSK_MASK_MODE_ALPHA,
@@ -3970,13 +3979,17 @@ gsk_gpu_node_processor_create_node_pattern (GskGpuPatternWriter *self,
gsk_gpu_descriptors_set_size (self->desc, images_before, buffers_before);
}
rect_round_to_pixels (&GRAPHENE_RECT_INIT (
self->bounds.origin.x - self->offset.x,
self->bounds.origin.y - self->offset.y,
self->bounds.size.width,
self->bounds.size.height
),
&self->scale,
&self->offset,
&bounds);
image = gsk_gpu_get_node_as_image (self->frame,
&GRAPHENE_RECT_INIT (
self->bounds.origin.x - self->offset.x,
self->bounds.origin.y - self->offset.y,
self->bounds.size.width,
self->bounds.size.height
),
&bounds,
&self->scale,
node,
&bounds);
+20 -1
View File
@@ -75,6 +75,12 @@ gsk_ngl_renderer_make_current (GskGpuRenderer *renderer)
gdk_gl_context_make_current (GDK_GL_CONTEXT (gsk_gpu_renderer_get_context (renderer)));
}
static void
gsk_ngl_renderer_free_backbuffer (GskNglRenderer *self)
{
g_clear_object (&self->backbuffer);
}
static GskGpuImage *
gsk_ngl_renderer_get_backbuffer (GskGpuRenderer *renderer)
{
@@ -91,7 +97,7 @@ gsk_ngl_renderer_get_backbuffer (GskGpuRenderer *renderer)
gsk_gpu_image_get_width (self->backbuffer) != ceil (gdk_surface_get_width (surface) * scale) ||
gsk_gpu_image_get_height (self->backbuffer) != ceil (gdk_surface_get_height (surface) * scale))
{
g_clear_object (&self->backbuffer);
gsk_ngl_renderer_free_backbuffer (self);
self->backbuffer = gsk_gl_image_new_backbuffer (GSK_GL_DEVICE (gsk_gpu_renderer_get_device (renderer)),
GDK_MEMORY_DEFAULT /* FIXME */,
ceil (gdk_surface_get_width (surface) * scale),
@@ -124,10 +130,21 @@ gsk_ngl_renderer_get_dmabuf_formats (GskGpuRenderer *renderer)
return display->egl_dmabuf_formats;
}
static void
gsk_ngl_renderer_unrealize (GskRenderer *renderer)
{
GskNglRenderer *self = GSK_NGL_RENDERER (renderer);
gsk_ngl_renderer_free_backbuffer (self);
GSK_RENDERER_CLASS (gsk_ngl_renderer_parent_class)->unrealize (renderer);
}
static void
gsk_ngl_renderer_class_init (GskNglRendererClass *klass)
{
GskGpuRendererClass *gpu_renderer_class = GSK_GPU_RENDERER_CLASS (klass);
GskRendererClass *renderer_class = GSK_RENDERER_CLASS (klass);
gpu_renderer_class->frame_type = GSK_TYPE_GL_FRAME;
@@ -138,6 +155,8 @@ gsk_ngl_renderer_class_init (GskNglRendererClass *klass)
gpu_renderer_class->wait = gsk_ngl_renderer_wait;
gpu_renderer_class->get_scale = gsk_ngl_renderer_get_scale;
gpu_renderer_class->get_dmabuf_formats = gsk_ngl_renderer_get_dmabuf_formats;
renderer_class->unrealize = gsk_ngl_renderer_unrealize;
}
static void
+1 -1
View File
@@ -1819,7 +1819,7 @@ gsk_rect_contour_get_stroke_bounds (const GskContour *contour,
graphene_rect_t rect;
graphene_rect_init (&rect, self->x, self->y, self->width, self->height);
graphene_rect_inset (&rect, - stroke->line_width, - stroke->line_width);
graphene_rect_inset (&rect, - 0.5 * stroke->line_width, - 0.5 * stroke->line_width);
gsk_bounding_box_init_from_rect (bounds, &rect);
return TRUE;
+3
View File
@@ -5658,6 +5658,7 @@ struct _GskTextNode
{
GskRenderNode render_node;
PangoFontMap *fontmap;
PangoFont *font;
gboolean has_color_glyphs;
@@ -5675,6 +5676,7 @@ gsk_text_node_finalize (GskRenderNode *node)
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_TEXT_NODE));
g_object_unref (self->font);
g_object_unref (self->fontmap);
g_free (self->glyphs);
parent_class->finalize (node);
@@ -5788,6 +5790,7 @@ gsk_text_node_new (PangoFont *font,
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
self->fontmap = g_object_ref (pango_font_get_font_map (font));
self->font = g_object_ref (font);
self->color = *color;
self->offset = *offset;
+280 -26
View File
@@ -46,12 +46,20 @@
#include <cairo-script-interpreter.h>
#endif
#include <pango/pangocairo.h>
#ifdef HAVE_PANGOFT
#include <pango/pangofc-fontmap.h>
#endif
#include <glib/gstdio.h>
typedef struct _Context Context;
struct _Context
{
GHashTable *named_nodes;
GHashTable *named_textures;
PangoFontMap *fontmap;
};
typedef struct _Declaration Declaration;
@@ -65,7 +73,7 @@ struct _Declaration
};
static void
context_init (Context *context)
context_init (Context *context)
{
memset (context, 0, sizeof (Context));
}
@@ -75,6 +83,7 @@ context_finish (Context *context)
{
g_clear_pointer (&context->named_nodes, g_hash_table_unref);
g_clear_pointer (&context->named_textures, g_hash_table_unref);
g_clear_object (&context->fontmap);
}
static gboolean
@@ -844,20 +853,35 @@ parse_mask_mode (GtkCssParser *parser,
}
static PangoFont *
font_from_string (const char *string)
font_from_string (PangoFontMap *fontmap,
const char *string)
{
PangoFontDescription *desc;
PangoFontMap *font_map;
PangoContext *context;
PangoContext *ctx;
PangoFont *font;
desc = pango_font_description_from_string (string);
font_map = pango_cairo_font_map_get_default ();
context = pango_font_map_create_context (font_map);
font = pango_font_map_load_font (font_map, context, desc);
ctx = pango_font_map_create_context (fontmap);
font = pango_font_map_load_font (fontmap, ctx, desc);
g_object_unref (ctx);
if (font)
{
PangoFontDescription *desc2;
const char *family, *family2;
desc2 = pango_font_describe (font);
family = pango_font_description_get_family (desc);
family2 = pango_font_description_get_family (desc2);
if (g_strcmp0 (family, family2) != 0)
g_clear_object (&font);
pango_font_description_free (desc2);
}
pango_font_description_free (desc);
g_object_unref (context);
return font;
}
@@ -926,22 +950,204 @@ create_ascii_glyphs (PangoFont *font)
return result;
}
#ifdef HAVE_PANGOFT
static void
delete_file (gpointer data)
{
char *path = data;
g_remove (path);
g_free (path);
}
static void
ensure_fontmap (Context *context)
{
FcConfig *config;
GPtrArray *files;
if (context->fontmap)
return;
context->fontmap = pango_cairo_font_map_new ();
config = FcInitLoadConfig ();
pango_fc_font_map_set_config (PANGO_FC_FONT_MAP (context->fontmap), config);
FcConfigDestroy (config);
files = g_ptr_array_new_with_free_func (delete_file);
g_object_set_data_full (G_OBJECT (context->fontmap), "font-files", files, (GDestroyNotify) g_ptr_array_unref);
}
static void
add_font_from_file (Context *context,
const char *path,
GError **error)
{
FcConfig *config;
GPtrArray *files;
ensure_fontmap (context);
if (!PANGO_IS_FC_FONT_MAP (context->fontmap))
{
g_set_error (error,
GTK_CSS_PARSER_ERROR,
GTK_CSS_PARSER_ERROR_FAILED,
"Custom fonts are not implemented for %s", G_OBJECT_TYPE_NAME (context->fontmap));
return;
}
config = pango_fc_font_map_get_config (PANGO_FC_FONT_MAP (context->fontmap));
if (!FcConfigAppFontAddFile (config, (FcChar8 *) path))
{
g_set_error (error,
GTK_CSS_PARSER_ERROR,
GTK_CSS_PARSER_ERROR_FAILED,
"Failed to add %s to FcConfig", path);
return;
}
files = (GPtrArray *) g_object_get_data (G_OBJECT (context->fontmap), "font-files");
g_ptr_array_add (files, g_strdup (path));
pango_fc_font_map_config_changed (PANGO_FC_FONT_MAP (context->fontmap));
}
static void
add_font_from_bytes (Context *context,
GBytes *bytes,
GError **error)
{
GFile *file;
GIOStream *iostream;
GOutputStream *ostream;
file = g_file_new_tmp ("gtk4-font-XXXXXX.ttf", (GFileIOStream **) &iostream, error);
if (!file)
return;
ostream = g_io_stream_get_output_stream (iostream);
if (g_output_stream_write_bytes (ostream, bytes, NULL, error) == -1)
{
g_object_unref (file);
g_object_unref (iostream);
return;
}
g_io_stream_close (iostream, NULL, NULL);
g_object_unref (iostream);
add_font_from_file (context, g_file_peek_path (file), error);
g_object_unref (file);
}
#else /* !HAVE_PANGOFT */
static void
add_font_from_bytes (Context *context,
GBytes *bytes,
GError **error)
{
g_set_error (error,
GTK_CSS_PARSER_ERROR,
GTK_CSS_PARSER_ERROR_FAILED,
"Not implemented");
}
#endif
static gboolean
parse_font (GtkCssParser *parser,
Context *context,
gpointer out_font)
{
PangoFont *font;
PangoFont *font = NULL;
char *s;
GtkCssLocation start_location;
PangoFontMap *fontmap;
fontmap = pango_cairo_font_map_get_default ();
s = gtk_css_parser_consume_string (parser);
if (s == NULL)
return FALSE;
font = font_from_string (s);
if (font == NULL)
start_location = *gtk_css_parser_get_start_location (parser);
if (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_URL) ||
gtk_css_parser_has_function (parser, "url"))
{
gtk_css_parser_error_syntax (parser, "This font does not exist.");
char *url;
char *scheme;
GBytes *bytes = NULL;
GError *error = NULL;
/* If we have a url, it is a bug if the font already exists in our custom fontmap */
if (context->fontmap)
{
font = font_from_string (context->fontmap, s);
if (font)
{
g_object_unref (font);
gtk_css_parser_error_value (parser, "This font already exists.");
return FALSE;
}
}
url = gtk_css_parser_consume_url (parser);
scheme = g_uri_parse_scheme (url);
if (scheme && g_ascii_strcasecmp (scheme, "data") == 0)
{
bytes = gtk_css_data_url_parse (url, NULL, &error);
}
else
{
GFile *file;
file = g_file_new_for_uri (url);
bytes = g_file_load_bytes (file, NULL, NULL, &error);
g_object_unref (file);
}
g_free (scheme);
g_free (url);
if (bytes)
{
add_font_from_bytes (context, bytes, &error);
g_bytes_unref (bytes);
fontmap = context->fontmap;
}
else
{
g_assert (error != NULL);
gtk_css_parser_emit_error (parser,
&start_location,
gtk_css_parser_get_end_location (parser),
error);
g_clear_error (&error);
return FALSE;
}
}
font = font_from_string (fontmap, s);
if (!font && context->fontmap && fontmap != context->fontmap)
font = font_from_string (context->fontmap, s);
if (!font)
{
gtk_css_parser_error_value (parser, "This font does not exist.");
return FALSE;
}
@@ -2013,7 +2219,7 @@ parse_text_node (GtkCssParser *parser,
if (font == NULL)
{
font = font_from_string ("Cantarell 11");
font = font_from_string (pango_cairo_font_map_get_default (), "Cantarell 11");
g_assert (font);
}
@@ -2629,6 +2835,7 @@ typedef struct
gsize named_node_counter;
GHashTable *named_textures;
gsize named_texture_counter;
GHashTable *serialized_fonts;
} Printer;
static void
@@ -2781,6 +2988,7 @@ printer_init (Printer *self,
self->named_node_counter = 0;
self->named_textures = g_hash_table_new_full (NULL, NULL, NULL, g_free);
self->named_texture_counter = 0;
self->serialized_fonts = g_hash_table_new (g_str_hash, g_str_equal);
printer_init_duplicates_for_node (self, node);
}
@@ -2792,6 +3000,7 @@ printer_clear (Printer *self)
g_string_free (self->str, TRUE);
g_hash_table_unref (self->named_nodes);
g_hash_table_unref (self->named_textures);
g_hash_table_unref (self->serialized_fonts);
}
#define IDENT_LEVEL 2 /* Spaces per level */
@@ -3235,6 +3444,59 @@ append_texture_param (Printer *p,
g_bytes_unref (bytes);
}
static void
gsk_text_node_serialize_font (GskRenderNode *node,
Printer *p)
{
PangoFont *font = gsk_text_node_get_font (node);
PangoFontMap *fontmap = pango_font_get_font_map (font);
PangoFontDescription *desc;
char *s;
desc = pango_font_describe (font);
s = pango_font_description_to_string (desc);
g_string_append_printf (p->str, "\"%s\"", s);
g_free (s);
pango_font_description_free (desc);
/* Check if this is a custom font that we created from a url */
if (!g_object_get_data (G_OBJECT (fontmap), "font-files"))
return;
#ifdef HAVE_PANGOFT
{
FcPattern *pat;
FcResult res;
const char *file;
char *data;
gsize len;
char *b64;
pat = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
res = FcPatternGetString (pat, FC_FILE, 0, (FcChar8 **)&file);
if (res != FcResultMatch)
return;
if (g_hash_table_contains (p->serialized_fonts, file))
return;
if (!g_file_get_contents (file, &data, &len, NULL))
return;
g_hash_table_add (p->serialized_fonts, (gpointer) file);
b64 = base64_encode_with_linebreaks ((const guchar *) data, len);
g_string_append (p->str, " url(\"data:font/ttf;base64,");
append_escaping_newlines (p->str, b64);
g_string_append (p->str, "\")");
g_free (b64);
g_free (data);
}
#endif
}
void
gsk_text_node_serialize_glyphs (GskRenderNode *node,
GString *p)
@@ -3788,29 +4050,21 @@ render_node_print (Printer *p,
{
const graphene_point_t *offset = gsk_text_node_get_offset (node);
const GdkRGBA *color = gsk_text_node_get_color (node);
PangoFont *font = gsk_text_node_get_font (node);
PangoFontDescription *desc;
char *font_name;
start_node (p, "text", node_name);
if (!gdk_rgba_equal (color, &GDK_RGBA("000000")))
if (!gdk_rgba_equal (color, &GDK_RGBA ("000000")))
append_rgba_param (p, "color", color);
_indent (p);
desc = pango_font_describe (font);
font_name = pango_font_description_to_string (desc);
g_string_append_printf (p->str, "font: \"%s\";\n", font_name);
g_free (font_name);
pango_font_description_free (desc);
g_string_append (p->str, "font: ");
gsk_text_node_serialize_font (node, p);
g_string_append (p->str, ";\n");
_indent (p);
g_string_append (p->str, "glyphs: ");
gsk_text_node_serialize_glyphs (node, p->str);
g_string_append_c (p->str, ';');
g_string_append_c (p->str, '\n');
g_string_append (p->str, ";\n");
if (!graphene_point_equal (offset, graphene_point_zero ()))
append_point_param (p, "offset", offset);
-1
View File
@@ -6,4 +6,3 @@
GskRenderNode * gsk_render_node_deserialize_from_bytes (GBytes *bytes,
GskParseErrorFunc error_func,
gpointer user_data);
+1 -1
View File
@@ -191,7 +191,7 @@ gtk_cell_renderer_accel_class_init (GtkCellRendererAccelClass *cell_accel_class)
PROP_ACCEL_MODS,
g_param_spec_flags ("accel-mods", NULL, NULL,
GDK_TYPE_MODIFIER_TYPE,
0,
GDK_NO_MODIFIER_MASK,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
/**
+14 -4
View File
@@ -269,11 +269,12 @@ gtk_column_view_cell_widget_size_allocate (GtkWidget *widget,
}
}
static void
gtk_column_view_cell_widget_dispose (GObject *object)
/* This should be to be called when unsetting the parent, but we have no
* set_parent vfunc().
*/
void
gtk_column_view_cell_widget_unset_column (GtkColumnViewCellWidget *self)
{
GtkColumnViewCellWidget *self = GTK_COLUMN_VIEW_CELL_WIDGET (object);
if (self->column)
{
gtk_column_view_column_remove_cell (self->column, self);
@@ -288,6 +289,15 @@ gtk_column_view_cell_widget_dispose (GObject *object)
g_clear_object (&self->column);
}
}
static void
gtk_column_view_cell_widget_dispose (GObject *object)
{
GtkColumnViewCellWidget *self = GTK_COLUMN_VIEW_CELL_WIDGET (object);
/* unset_parent() forgot to call this. Be very angry. */
g_warn_if_fail (self->column == NULL);
G_OBJECT_CLASS (gtk_column_view_cell_widget_parent_class)->dispose (object);
}
+1
View File
@@ -46,5 +46,6 @@ void gtk_column_view_cell_widget_remove (
GtkColumnViewCellWidget * gtk_column_view_cell_widget_get_next (GtkColumnViewCellWidget *self);
GtkColumnViewCellWidget * gtk_column_view_cell_widget_get_prev (GtkColumnViewCellWidget *self);
GtkColumnViewColumn * gtk_column_view_cell_widget_get_column (GtkColumnViewCellWidget *self);
void gtk_column_view_cell_widget_unset_column (GtkColumnViewCellWidget *self);
G_END_DECLS
+3
View File
@@ -592,6 +592,9 @@ void
gtk_column_view_row_widget_remove_child (GtkColumnViewRowWidget *self,
GtkWidget *child)
{
if (GTK_IS_COLUMN_VIEW_CELL_WIDGET (child))
gtk_column_view_cell_widget_unset_column (GTK_COLUMN_VIEW_CELL_WIDGET (child));
gtk_widget_unparent (child);
}
+7 -4
View File
@@ -1803,16 +1803,19 @@ typedef enum { /*< prefix=GTK_ACCESSIBLE_SORT >*/
/**
* GtkPopoverMenuFlags:
* @GTK_POPOVER_MENU_NESTED: Create submenus as nested
* popovers. Without this flag, submenus are created as
* sliding pages that replace the main menu.
* @GTK_POPOVER_MENU_SLIDING: Submenus are presented as sliding submenus that
* replace the main menu.
* @GTK_POPOVER_MENU_NESTED: Submenus are presented as traditional, nested
* popovers.
*
* Flags that affect how [class@Gtk.PopoverMenu] widgets built from
* a [class@Gio.MenuModel] are created and displayed.
*
* Since: 4.14
*/
typedef enum { /*< prefix=GTK_POPOVER_MENU >*/
GTK_POPOVER_MENU_SLIDING = 0,
GTK_POPOVER_MENU_NESTED = 1 << 0
} GtkPopoverMenuFlags;
G_END_DECLS
+51 -27
View File
@@ -903,7 +903,7 @@ struct _GtkObjectExpression
{
GtkExpression parent;
GObject *object;
GWeakRef object_wr;
GSList *watches;
};
@@ -918,14 +918,12 @@ gtk_object_expression_weak_ref_cb (gpointer data,
GObject *object)
{
GtkObjectExpression *self = (GtkObjectExpression *) data;
GSList *l;
GSList *iter = self->watches;
self->object = NULL;
for (l = self->watches; l; l = l->next)
while (iter)
{
GtkObjectExpressionWatch *owatch = l->data;
GtkObjectExpressionWatch *owatch = iter->data;
iter = iter->next;
owatch->notify (owatch->user_data);
}
}
@@ -934,9 +932,17 @@ static void
gtk_object_expression_finalize (GtkExpression *expr)
{
GtkObjectExpression *self = (GtkObjectExpression *) expr;
GObject *object;
if (self->object)
g_object_weak_unref (self->object, gtk_object_expression_weak_ref_cb, self);
object = g_weak_ref_get (&self->object_wr);
if (object != NULL)
{
g_object_weak_unref (object, gtk_object_expression_weak_ref_cb, self);
g_object_unref (object);
}
g_weak_ref_clear (&self->object_wr);
g_assert (self->watches == NULL);
@@ -955,12 +961,14 @@ gtk_object_expression_evaluate (GtkExpression *expr,
GValue *value)
{
GtkObjectExpression *self = (GtkObjectExpression *) expr;
GObject *object;
if (self->object == NULL)
object = g_weak_ref_get (&self->object_wr);
if (object == NULL)
return FALSE;
g_value_init (value, gtk_expression_get_value_type (expr));
g_value_set_object (value, self->object);
g_value_take_object (value, object);
return TRUE;
}
@@ -1035,7 +1043,7 @@ gtk_object_expression_new (GObject *object)
result = gtk_expression_alloc (GTK_TYPE_OBJECT_EXPRESSION, G_OBJECT_TYPE (object));
self = (GtkObjectExpression *) result;
self->object = object;
g_weak_ref_init (&self->object_wr, object);
g_object_weak_ref (object, gtk_object_expression_weak_ref_cb, self);
return result;
@@ -1053,10 +1061,17 @@ GObject *
gtk_object_expression_get_object (GtkExpression *expression)
{
GtkObjectExpression *self = (GtkObjectExpression *) expression;
GObject *object;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (expression, GTK_TYPE_OBJECT_EXPRESSION), NULL);
return self->object;
object = g_weak_ref_get (&self->object_wr);
/* Return a borrowed instance */
if (object != NULL)
g_object_unref (object);
return object;
}
/* }}} */
@@ -2019,7 +2034,7 @@ gtk_expression_watch_evaluate (GtkExpressionWatch *watch,
typedef struct {
GtkExpressionWatch *watch;
GObject *target;
GWeakRef target_wr;
GParamSpec *pspec;
} GtkExpressionBind;
@@ -2029,34 +2044,39 @@ invalidate_binds (gpointer unused,
{
GSList *l, *binds;
binds = g_object_get_data (object, "gtk-expression-binds");
for (l = binds; l; l = l->next)
l = binds = g_object_get_data (object, "gtk-expression-binds");
while (l)
{
GtkExpressionBind *bind = l->data;
l = l->next;
/* This guarantees we neither try to update bindings
* (which would wreck havoc because the object is
* dispose()ing itself) nor try to destroy bindings
* anymore, so destruction can be done in free_binds().
*/
bind->target = NULL;
g_weak_ref_set (&bind->target_wr, NULL);
}
}
static void
free_binds (gpointer data)
{
GSList *l;
GSList *l = data;
for (l = data; l; l = l->next)
while (l)
{
GtkExpressionBind *bind = l->data;
g_assert (bind->target == NULL);
l = l->next;
if (bind->watch)
gtk_expression_watch_unwatch (bind->watch);
g_weak_ref_clear (&bind->target_wr);
g_free (bind);
}
g_slist_free (data);
}
@@ -2064,17 +2084,19 @@ static void
gtk_expression_bind_free (gpointer data)
{
GtkExpressionBind *bind = data;
GObject *target = g_weak_ref_get (&bind->target_wr);
if (bind->target)
if (target)
{
GSList *binds;
binds = g_object_steal_data (bind->target, "gtk-expression-binds");
binds = g_object_steal_data (target, "gtk-expression-binds");
binds = g_slist_remove (binds, bind);
if (binds)
g_object_set_data_full (bind->target, "gtk-expression-binds", binds, free_binds);
g_object_set_data_full (target, "gtk-expression-binds", binds, free_binds);
else
g_object_weak_unref (bind->target, invalidate_binds, NULL);
g_object_weak_unref (target, invalidate_binds, NULL);
g_object_unref (target);
g_free (bind);
}
else
@@ -2096,14 +2118,16 @@ gtk_expression_bind_notify (gpointer data)
{
GValue value = G_VALUE_INIT;
GtkExpressionBind *bind = data;
GObject *target = g_weak_ref_get (&bind->target_wr);
if (bind->target == NULL)
if (target == NULL)
return;
if (!gtk_expression_watch_evaluate (bind->watch, &value))
return;
g_object_set_property (bind->target, bind->pspec->name, &value);
g_object_set_property (target, bind->pspec->name, &value);
g_object_unref (target);
g_value_unset (&value);
}
@@ -2163,7 +2187,7 @@ gtk_expression_bind (GtkExpression *self,
binds = g_object_steal_data (target, "gtk-expression-binds");
if (binds == NULL)
g_object_weak_ref (target, invalidate_binds, NULL);
bind->target = target;
g_weak_ref_init (&bind->target_wr, target);
bind->pspec = pspec;
bind->watch = gtk_expression_watch (self,
this_,
+4
View File
@@ -47,6 +47,8 @@
* `GtkGLArea` sets up its own [class@Gdk.GLContext], and creates a custom
* GL framebuffer that the widget will do GL rendering onto. It also ensures
* that this framebuffer is the default GL rendering target when rendering.
* The completed rendering is integrated into the larger GTK scene graph as
* a texture.
*
* In order to draw, you have to connect to the [signal@Gtk.GLArea::render]
* signal, or subclass `GtkGLArea` and override the GtkGLAreaClass.render
@@ -64,6 +66,8 @@
* The `render()` function will be called when the `GtkGLArea` is ready
* for you to draw its content:
*
* The initial contents of the framebuffer are transparent.
*
* ```c
* static gboolean
* render (GtkGLArea *area, GdkGLContext *context)
+1 -1
View File
@@ -53,7 +53,7 @@ _gtk_pango_attr_list_merge (PangoAttrList *into,
if (into)
pango_attr_list_filter (from, attr_list_merge_filter, into);
else
return pango_attr_list_ref (from);
return pango_attr_list_ref (from);
}
return into;
+3 -6
View File
@@ -637,7 +637,8 @@ gtk_popover_menu_class_init (GtkPopoverMenuClass *klass)
g_object_class_install_property (object_class,
PROP_FLAGS,
g_param_spec_flags ("flags", NULL, NULL,
GTK_TYPE_POPOVER_MENU_FLAGS, 0,
GTK_TYPE_POPOVER_MENU_FLAGS,
GTK_POPOVER_MENU_SLIDING,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
| G_PARAM_EXPLICIT_NOTIFY));
@@ -783,7 +784,7 @@ GtkWidget *
gtk_popover_menu_new_from_model (GMenuModel *model)
{
return gtk_popover_menu_new_from_model_full (model, 0);
return gtk_popover_menu_new_from_model_full (model, GTK_POPOVER_MENU_SLIDING);
}
/**
@@ -799,10 +800,6 @@ gtk_popover_menu_new_from_model (GMenuModel *model)
* belongs. Actions can also be added using [method@Gtk.Widget.insert_action_group]
* on the parent widget or on any of its parent widgets.
*
* The only flag that is supported currently is
* %GTK_POPOVER_MENU_NESTED, which makes GTK create traditional,
* nested submenus instead of the default sliding submenus.
*
* Returns: the new `GtkPopoverMenu`
*/
GtkWidget *
+12
View File
@@ -172,6 +172,7 @@ enum {
PROP_ALTERNATIVE_SORT_ARROWS,
PROP_ENABLE_ANIMATIONS,
PROP_ERROR_BELL,
PROP_STATUS_SHAPES,
PROP_PRINT_BACKENDS,
PROP_PRINT_PREVIEW_COMMAND,
PROP_ENABLE_ACCELS,
@@ -571,6 +572,17 @@ gtk_settings_class_init (GtkSettingsClass *class)
TRUE,
GTK_PARAM_READWRITE);
/**
* GtkSettings:gtk-show-status-shapes:
*
* When %TRUE, widgets like switches include shapes to indicate their on/off state.
*
* Since: 4.14
*/
pspecs[PROP_STATUS_SHAPES] = g_param_spec_boolean ("gtk-show-status-shapes", NULL, NULL,
FALSE,
GTK_PARAM_READWRITE);
/**
* GtkSettings:gtk-print-backends:
*
+1 -1
View File
@@ -671,7 +671,7 @@ gtk_keyval_trigger_class_init (GtkKeyvalTriggerClass *klass)
keyval_props[KEYVAL_PROP_MODIFIERS] =
g_param_spec_flags (I_("modifiers"), NULL, NULL,
GDK_TYPE_MODIFIER_TYPE,
0,
GDK_NO_MODIFIER_MASK,
G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE);
+1
View File
@@ -179,6 +179,7 @@ GDK_AVAILABLE_IN_ALL
GtkSelectionModel * gtk_stack_get_pages (GtkStack *stack);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkStack, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkStackPage, g_object_unref)
G_END_DECLS
+27
View File
@@ -549,6 +549,18 @@ state_set (GtkSwitch *self,
return TRUE;
}
static gboolean
translate_switch_shapes_to_opacity (GBinding *binding,
const GValue *from_value,
GValue *to_value,
gpointer user_data)
{
gboolean visible = g_value_get_boolean (from_value);
g_value_set_double (to_value, visible ? 1.0 : 0.0);
return TRUE;
}
static void
gtk_switch_class_init (GtkSwitchClass *klass)
{
@@ -658,6 +670,7 @@ gtk_switch_init (GtkSwitch *self)
{
GtkLayoutManager *layout;
GtkGesture *gesture;
GtkSettings *gtk_settings;
gtk_widget_set_focusable (GTK_WIDGET (self), TRUE);
@@ -690,18 +703,32 @@ gtk_switch_init (GtkSwitch *self)
gtk_switch_allocate);
gtk_widget_set_layout_manager (GTK_WIDGET (self), layout);
gtk_settings = gtk_settings_get_default ();
self->on_image = g_object_new (GTK_TYPE_IMAGE,
"accessible-role", GTK_ACCESSIBLE_ROLE_NONE,
"icon-name", "switch-on-symbolic",
NULL);
gtk_widget_set_parent (self->on_image, GTK_WIDGET (self));
g_object_bind_property_full (gtk_settings, "gtk-show-status-shapes",
self->on_image, "opacity",
G_BINDING_SYNC_CREATE,
translate_switch_shapes_to_opacity,
NULL, NULL, NULL);
self->off_image = g_object_new (GTK_TYPE_IMAGE,
"accessible-role", GTK_ACCESSIBLE_ROLE_NONE,
"icon-name", "switch-off-symbolic",
NULL);
gtk_widget_set_parent (self->off_image, GTK_WIDGET (self));
g_object_bind_property_full (gtk_settings, "gtk-show-status-shapes",
self->off_image, "opacity",
G_BINDING_SYNC_CREATE,
translate_switch_shapes_to_opacity,
NULL, NULL, NULL);
self->slider = gtk_gizmo_new_with_role ("slider",
GTK_ACCESSIBLE_ROLE_NONE,
NULL, NULL, NULL, NULL, NULL, NULL);
-4
View File
@@ -2482,10 +2482,6 @@ switch {
transition: $button_transition;
}
@if $contrast != 'high' {
> image { color: transparent; } /* only show i / o for the accessible theme */
}
&:hover > slider {
@include button(hover);
}
+1
View File
@@ -58,6 +58,7 @@ gdk/x11/gdkmain-x11.c
gdk/x11/gdkselectioninputstream-x11.c
gdk/x11/gdktextlistconverter-x11.c
gsk/gl/gskglrenderer.c
gsk/gpu/gskgldevice.c
gsk/gskrendernodeimpl.c
gtk/a11y/gtkatspiaction.c
gtk/a11y/gtkatspiroot.c
+8850 -6081
View File
File diff suppressed because it is too large Load Diff
+168 -147
View File
@@ -5,14 +5,14 @@
# Joern v. Kattchee <kattchee@cs.tu-berlin.de>, 2000-2002.
# Nguyễn Thái Ngọc Duy <pclouds@gmail.com>, 2002-2004,2007-2009,2011-2013.
# Clytie Siddall <clytie@riverland.net.au>, 2005-2010.
# Trần Ngọc Quân <vnwildman@gmail.com>, 2013-2015, 2023
# Trần Ngọc Quân <vnwildman@gmail.com>, 2013-2024.
#
msgid ""
msgstr ""
"Project-Id-Version: gtk main\n"
"Project-Id-Version: gtk.po-ui main\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
"POT-Creation-Date: 2023-07-22 08:17+0000\n"
"PO-Revision-Date: 2023-07-22 15:52+0700\n"
"POT-Creation-Date: 2024-01-12 11:17+0000\n"
"PO-Revision-Date: 2024-01-13 14:17+0700\n"
"Last-Translator: Trần Ngọc Quân <vnwildman@gmail.com>\n"
"Language-Team: Vietnamese <gnome-vi-list@gnome.org>\n"
"Language: vi\n"
@@ -20,6 +20,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Gtranslator 42.0\n"
#: gdk/broadway/gdkbroadway-server.c:135
#, c-format
@@ -49,57 +50,57 @@ msgstr "Không thể cung cấp nội dung dạng “%s”"
msgid "Cannot provide contents as %s"
msgstr "Không thể cung cấp nội dung dạng %s"
#: gdk/gdkdisplay.c:156 gdk/gdkglcontext.c:442
#: gdk/gdkdisplay.c:156 gdk/gdkglcontext.c:443
msgid "The current backend does not support OpenGL"
msgstr "Ứng dụng chạy phía sau không hỗ trợ OpenGL"
#: gdk/gdkdisplay.c:1245 gdk/gdksurface.c:1252
#: gdk/gdkdisplay.c:1244 gdk/gdksurface.c:1252
msgid "Vulkan support disabled via GDK_DEBUG"
msgstr "Vulkan hỗ trợ tắt thông qua GDK_DEBUG"
#: gdk/gdkdisplay.c:1277
#: gdk/gdkdisplay.c:1276
msgid "GL support disabled via GDK_DEBUG"
msgstr "GL hỗ trợ tắt thông qua GDK_DEBUG"
#: gdk/gdkdisplay.c:1575
#: gdk/gdkdisplay.c:1574
msgid "No EGL configuration available"
msgstr "Không có cấu hình EGL nào"
#: gdk/gdkdisplay.c:1583
#: gdk/gdkdisplay.c:1582
msgid "Failed to get EGL configurations"
msgstr "Gặp lỗi khi lấy cấu hình EGL"
#: gdk/gdkdisplay.c:1613
#: gdk/gdkdisplay.c:1612
msgid "No EGL configuration with required features found"
msgstr "Không tìm thấy cấu hình EGL với các tính năng cần thiết"
#: gdk/gdkdisplay.c:1620
#: gdk/gdkdisplay.c:1619
msgid "No perfect EGL configuration found"
msgstr "Không tìm thấy cấu hình EGL hoàn hảo"
#: gdk/gdkdisplay.c:1662
#: gdk/gdkdisplay.c:1661
#, c-format
msgid "EGL implementation is missing extension %s"
msgid_plural "EGL implementation is missing %2$d extensions: %1$s"
msgstr[0] "Phần mã thực thi EGL thiếu tiện %2$d ích mở rộng: %1$s"
#: gdk/gdkdisplay.c:1695
#: gdk/gdkdisplay.c:1694
msgid "libEGL not available in this sandbox"
msgstr "libEGL không khả dụng trong sandbox này"
#: gdk/gdkdisplay.c:1696
#: gdk/gdkdisplay.c:1695
msgid "libEGL not available"
msgstr "libEGL không sẵn có"
#: gdk/gdkdisplay.c:1706
#: gdk/gdkdisplay.c:1705
msgid "Failed to create EGL display"
msgstr "Gặp lỗi khi tạo bộ hiển thị EGL"
#: gdk/gdkdisplay.c:1716
#: gdk/gdkdisplay.c:1715
msgid "Could not initialize EGL display"
msgstr "Không thể khởi tạo bộ hiển thị EGL"
#: gdk/gdkdisplay.c:1727
#: gdk/gdkdisplay.c:1726
#, c-format
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
msgstr "Phiên bản EGL %d.%d quá cũ. GTK yêu cầu %d.%d"
@@ -112,33 +113,33 @@ msgstr "Kéo và thả từ các ứng dụng khác không được hỗ trợ."
msgid "No compatible formats to transfer contents."
msgstr "Không có định dạng tương thích để chuyển nội dung."
#: gdk/gdkglcontext.c:401 gdk/x11/gdkglcontext-glx.c:642
#: gdk/gdkglcontext.c:402 gdk/x11/gdkglcontext-glx.c:642
msgid "No GL API allowed."
msgstr "Không cho phép API GL."
#: gdk/gdkglcontext.c:425 gdk/win32/gdkglcontext-win32-wgl.c:387
#: gdk/gdkglcontext.c:426 gdk/win32/gdkglcontext-win32-wgl.c:387
#: gdk/win32/gdkglcontext-win32-wgl.c:530
#: gdk/win32/gdkglcontext-win32-wgl.c:574 gdk/x11/gdkglcontext-glx.c:691
msgid "Unable to create a GL context"
msgstr "Không thể tạo ngữ cảnh GL"
#: gdk/gdkglcontext.c:1280
#: gdk/gdkglcontext.c:1281
msgid "Anything but OpenGL ES disabled via GDK_DEBUG"
msgstr "Mọi thứ trừ OpenGL ES bị vô hiệu hóa qua GDK_DEBUG"
#: gdk/gdkglcontext.c:1289
#: gdk/gdkglcontext.c:1290
#, c-format
msgid "Application does not support %s API"
msgstr "Ứng dụng không hỗ trợ %s API"
#. translators: This is about OpenGL backend names, like
#. * "Trying to use X11 GLX, but EGL is already in use"
#: gdk/gdkglcontext.c:1863
#: gdk/gdkglcontext.c:1899
#, c-format
msgid "Trying to use %s, but %s is already in use"
msgstr "Đang cố dùng %s, nhưng %s đã được sử dụng rồi"
#: gdk/gdktexture.c:528
#: gdk/gdktexture.c:530
msgid "Unknown image format."
msgstr "Định dạng ảnh chưa biết."
@@ -565,7 +566,7 @@ msgstr "Gặp lỗi khi đang đọc dữ liệu tại dòng %d"
#: gdk/macos/gdkmacospasteboard.c:211 gdk/wayland/gdkclipboard-wayland.c:240
#: gdk/wayland/gdkdrop-wayland.c:207 gdk/wayland/gdkprimary-wayland.c:343
#: gdk/win32/gdkdrop-win32.c:1018 gdk/win32/gdkdrop-win32.c:1063
#: gdk/x11/gdkclipboard-x11.c:805 gdk/x11/gdkdrop-x11.c:235
#: gdk/x11/gdkclipboard-x11.c:807 gdk/x11/gdkdrop-x11.c:235
msgid "No compatible transfer format found"
msgstr "Không tìm thấy định dạng chuyển tương thích"
@@ -574,60 +575,60 @@ msgstr "Không tìm thấy định dạng chuyển tương thích"
msgid "Failed to decode contents with mime-type of '%s'"
msgstr "Gặp lỗi khi giải mã các nội dung với kiểu mine của '%s'"
#: gdk/win32/gdkclipdrop-win32.c:721
#: gdk/win32/gdkclipdrop-win32.c:719
#, c-format
msgid "Cannot claim clipboard ownership. OpenClipboard() timed out."
msgstr ""
"Không thể yêu cầu quyền sở hữu clipboard. OpenClipboard() đã hết thời gian "
"chờ."
#: gdk/win32/gdkclipdrop-win32.c:731
#: gdk/win32/gdkclipdrop-win32.c:729
#, c-format
msgid "Cannot claim clipboard ownership. Another process claimed it before us."
msgstr ""
"Không thể yêu cầu quyền sở hữu clipboard. Một tiến trình khác đã tuyên bố nó "
"trước chúng ta."
#: gdk/win32/gdkclipdrop-win32.c:745
#: gdk/win32/gdkclipdrop-win32.c:743
#, c-format
msgid "Cannot claim clipboard ownership. OpenClipboard() failed: 0x%lx."
msgstr ""
"Không thể yêu cầu quyền sở hữu clipboard. OpenClipboard() gặp lỗi: 0x%lx."
#: gdk/win32/gdkclipdrop-win32.c:757
#: gdk/win32/gdkclipdrop-win32.c:755
#, c-format
msgid "Cannot claim clipboard ownership. EmptyClipboard() failed: 0x%lx."
msgstr ""
"Không thể yêu cầu quyền sở hữu clipboard. EmptyClipboard() gặp lỗi: 0x%lx."
#: gdk/win32/gdkclipdrop-win32.c:800
#: gdk/win32/gdkclipdrop-win32.c:798
#, c-format
msgid "Cannot set clipboard data. OpenClipboard() timed out."
msgstr "Không thể đặt dữ liệu clipboard. OpenClipboard() chờ quá lâu."
#: gdk/win32/gdkclipdrop-win32.c:810 gdk/win32/gdkclipdrop-win32.c:841
#: gdk/win32/gdkclipdrop-win32.c:808 gdk/win32/gdkclipdrop-win32.c:839
#, c-format
msgid "Cannot set clipboard data. Another process claimed clipboard ownership."
msgstr ""
"Không thể đặt dữ liệu clipboard. Một tiến trình khác đã xác nhận quyền sở "
"hữu clipboard."
#: gdk/win32/gdkclipdrop-win32.c:824
#: gdk/win32/gdkclipdrop-win32.c:822
#, c-format
msgid "Cannot set clipboard data. OpenClipboard() failed: 0x%lx."
msgstr "Không thể đặt dữ liệu clipboard. OpenClipboard() gặp lỗi: 0x%lx."
#: gdk/win32/gdkclipdrop-win32.c:876
#: gdk/win32/gdkclipdrop-win32.c:874
#, c-format
msgid "Cannot get clipboard data. GlobalLock(0x%p) failed: 0x%lx."
msgstr "Không thể lấy dữ liệu clipboard. GlobalLock(0x%p) gặp lỗi: 0x%lx."
#: gdk/win32/gdkclipdrop-win32.c:887
#: gdk/win32/gdkclipdrop-win32.c:885
#, c-format
msgid "Cannot get clipboard data. GlobalSize(0x%p) failed: 0x%lx."
msgstr "Không thể lấy dữ liệu clipboard. GlobalSize(0x%p) gặp lỗi: 0x%lx."
#: gdk/win32/gdkclipdrop-win32.c:900
#: gdk/win32/gdkclipdrop-win32.c:898
#, c-format
msgid ""
"Cannot get clipboard data. Failed to allocate %s bytes to store the data."
@@ -635,17 +636,17 @@ msgstr ""
"Không thể lấy dữ liệu clipboard. Không thể phân bổ %s byte để lưu trữ dữ "
"liệu."
#: gdk/win32/gdkclipdrop-win32.c:932
#: gdk/win32/gdkclipdrop-win32.c:930
#, c-format
msgid "Cannot get clipboard data. OpenClipboard() timed out."
msgstr "Không thể lấy dữ liệu clipboard. OpenClipboard() chờ quá lâu."
#: gdk/win32/gdkclipdrop-win32.c:942
#: gdk/win32/gdkclipdrop-win32.c:940
#, c-format
msgid "Cannot get clipboard data. Clipboard ownership changed."
msgstr "Không thể lấy dữ liệu clipboard. Chủ sở hữu clipboard đã thay đổi."
#: gdk/win32/gdkclipdrop-win32.c:952
#: gdk/win32/gdkclipdrop-win32.c:950
#, c-format
msgid ""
"Cannot get clipboard data. Clipboard data changed before we could get it."
@@ -653,18 +654,18 @@ msgstr ""
"Không thể lấy dữ liệu clipboard. Dữ liệu clipboard đã thay đổi trước khi "
"chúng ta có thể lấy được."
#: gdk/win32/gdkclipdrop-win32.c:969
#: gdk/win32/gdkclipdrop-win32.c:967
#, c-format
msgid "Cannot get clipboard data. OpenClipboard() failed: 0x%lx."
msgstr "Không thể lấy dữ liệu clipboard. OpenClipboard() gặp lỗi: 0x%lx."
#: gdk/win32/gdkclipdrop-win32.c:994
#: gdk/win32/gdkclipdrop-win32.c:992
#, c-format
msgid "Cannot get clipboard data. No compatible transfer format found."
msgstr ""
"Không thể lấy dữ liệu clipboard. Không tìm thấy định dạng tương thích nào."
#: gdk/win32/gdkclipdrop-win32.c:1004
#: gdk/win32/gdkclipdrop-win32.c:1002
#, c-format
msgid "Cannot get clipboard data. GetClipboardData() failed: 0x%lx."
msgstr "Không thể lấy dữ liệu clipboard. GetClipboardData() gặp lỗi: 0x%lx."
@@ -773,11 +774,11 @@ msgid "Opening %d Item"
msgid_plural "Opening %d Items"
msgstr[0] "Đang mở %d mục"
#: gdk/x11/gdkclipboard-x11.c:475
#: gdk/x11/gdkclipboard-x11.c:477
msgid "Clipboard manager could not store selection."
msgstr "Trình quản lý clipboard không thể lưu trữ phần lựa chọn."
#: gdk/x11/gdkclipboard-x11.c:655
#: gdk/x11/gdkclipboard-x11.c:657
msgid "Cannot store clipboard. No clipboard manager is active."
msgstr ""
"Không thể lưu trữ clipboard. Không có trình quản lý clipboard nào đang được "
@@ -1039,19 +1040,19 @@ msgctxt "progress bar label"
msgid "%d%%"
msgstr "%d%%"
#: gtk/deprecated/gtkcolorbutton.c:183 gtk/deprecated/gtkcolorbutton.c:311
#: gtk/deprecated/gtkcolorbutton.c:183 gtk/deprecated/gtkcolorbutton.c:314
#: gtk/gtkcolordialog.c:411
msgid "Pick a Color"
msgstr "Chọn màu"
#: gtk/deprecated/gtkcolorbutton.c:502 gtk/gtkcolorchooserwidget.c:313
#: gtk/gtkcolordialogbutton.c:302
#: gtk/deprecated/gtkcolorbutton.c:505 gtk/gtkcolorchooserwidget.c:313
#: gtk/gtkcolordialogbutton.c:335
#, c-format
msgid "Red %d%%, Green %d%%, Blue %d%%, Alpha %d%%"
msgstr "Đỏ %d%%, Xanh %d%%, Lục %d%%, Trong suốt %d%%"
#: gtk/deprecated/gtkcolorbutton.c:508 gtk/gtkcolorchooserwidget.c:319
#: gtk/gtkcolordialogbutton.c:308
#: gtk/deprecated/gtkcolorbutton.c:511 gtk/gtkcolorchooserwidget.c:319
#: gtk/gtkcolordialogbutton.c:341
#, c-format
msgid "Red %d%%, Green %d%%, Blue %d%%"
msgstr "Đỏ %d%%, Xanh %d%%, Lục %d%%"
@@ -1060,17 +1061,17 @@ msgstr "Đỏ %d%%, Xanh %d%%, Lục %d%%"
msgid "Sans 12"
msgstr "Sans 12"
#: gtk/deprecated/gtkfontbutton.c:507 gtk/deprecated/gtkfontbutton.c:621
#: gtk/deprecated/gtkfontbutton.c:507 gtk/deprecated/gtkfontbutton.c:624
#: gtk/gtkfontdialog.c:596
msgid "Pick a Font"
msgstr "Chọn phông chữ"
#: gtk/deprecated/gtkfontbutton.c:597 gtk/gtkfilechooserwidget.c:3871
#: gtk/gtkfontdialogbutton.c:115 gtk/inspector/visual.ui:169
#: gtk/deprecated/gtkfontbutton.c:600 gtk/gtkfilechooserwidget.c:3871
#: gtk/gtkfontdialogbutton.c:126 gtk/inspector/visual.ui:169
msgid "Font"
msgstr "Phông chữ"
#: gtk/deprecated/gtkfontbutton.c:1152 gtk/gtkfontdialogbutton.c:614
#: gtk/deprecated/gtkfontbutton.c:1155 gtk/gtkfontdialogbutton.c:652
msgctxt "font"
msgid "None"
msgstr "Không"
@@ -1728,7 +1729,7 @@ msgstr "Đón_g"
#. * suspend or screen locking, and the caller hasn't specified
#. * a reason.
#.
#: gtk/gtkapplication-dbus.c:713
#: gtk/gtkapplication-dbus.c:721
msgid "Reason not specified"
msgstr "Không cung cấp lý do"
@@ -2134,7 +2135,7 @@ msgstr "_Phải:"
msgid "Paper Margins"
msgstr "Lề giấy"
#: gtk/gtkentry.c:3673
#: gtk/gtkentry.c:3685
msgid "Insert Emoji"
msgstr "Chèn Emoji"
@@ -2204,7 +2205,7 @@ msgstr "Một tập tin mang tên đó đã có rồi"
#: gtk/gtkmessagedialog.c:179 gtk/gtkmountoperation.c:608
#: gtk/print/gtkpagesetupunixdialog.c:282 gtk/print/gtkprintbackend.c:638
#: gtk/print/gtkprintunixdialog.c:682 gtk/print/gtkprintunixdialog.c:839
#: gtk/gtkwindow.c:6193 gtk/ui/gtkappchooserdialog.ui:48
#: gtk/gtkwindow.c:6233 gtk/ui/gtkappchooserdialog.ui:48
#: gtk/ui/gtkassistant.ui:52 gtk/ui/gtkcolorchooserdialog.ui:36
#: gtk/ui/gtkfontchooserdialog.ui:27
msgid "_Cancel"
@@ -2220,7 +2221,7 @@ msgstr "_Mở"
msgid "_Save"
msgstr "_Lưu"
#: gtk/gtkfilechoosernativequartz.c:340 gtk/ui/gtkfilechooserwidget.ui:288
#: gtk/gtkfilechoosernativequartz.c:344 gtk/ui/gtkfilechooserwidget.ui:288
msgid "Select which types of files are shown"
msgstr "Chọn hiển thị những kiểu tập tin nào"
@@ -2292,7 +2293,7 @@ msgid "If you delete an item, it will be permanently lost."
msgstr "Nếu bạn xóa bỏ một mục, nó sẽ bị mất vĩnh viễn."
#: gtk/gtkfilechooserwidget.c:1185 gtk/gtkfilechooserwidget.c:1815
#: gtk/gtklabel.c:5693 gtk/gtktext.c:6127 gtk/gtktextview.c:9024
#: gtk/gtklabel.c:5695 gtk/gtktext.c:6147 gtk/gtktextview.c:9018
msgid "_Delete"
msgstr "_Xóa bỏ"
@@ -2433,7 +2434,7 @@ msgstr "Chương trình"
msgid "Audio"
msgstr "Âm thanh"
#: gtk/gtkfilechooserwidget.c:3872 gtk/gtkfilefilter.c:1035
#: gtk/gtkfilechooserwidget.c:3872 gtk/gtkfilefilter.c:1032
msgid "Image"
msgstr "Ảnh"
@@ -2543,7 +2544,7 @@ msgstr "Chọn nhiều thư mục"
msgid "Select a Folder"
msgstr "Chọn thư mục"
#: gtk/gtkfilefilter.c:1048
#: gtk/gtkfilefilter.c:1045
msgid "Unspecified"
msgstr "Chưa xác định"
@@ -2631,31 +2632,31 @@ msgstr "Đóng"
msgid "Close the infobar"
msgstr "Đóng infobar"
#: gtk/gtklabel.c:5690 gtk/gtktext.c:6115 gtk/gtktextview.c:9012
#: gtk/gtklabel.c:5692 gtk/gtktext.c:6135 gtk/gtktextview.c:9006
msgid "Cu_t"
msgstr "Cắ_t"
#: gtk/gtklabel.c:5691 gtk/gtktext.c:6119 gtk/gtktextview.c:9016
#: gtk/gtklabel.c:5693 gtk/gtktext.c:6139 gtk/gtktextview.c:9010
msgid "_Copy"
msgstr "_Chép"
#: gtk/gtklabel.c:5692 gtk/gtktext.c:6123 gtk/gtktextview.c:9020
#: gtk/gtklabel.c:5694 gtk/gtktext.c:6143 gtk/gtktextview.c:9014
msgid "_Paste"
msgstr "_Dán"
#: gtk/gtklabel.c:5698 gtk/gtktext.c:6136 gtk/gtktextview.c:9045
#: gtk/gtklabel.c:5700 gtk/gtktext.c:6156 gtk/gtktextview.c:9039
msgid "Select _All"
msgstr "Chọn tất _cả"
#: gtk/gtklabel.c:5703
#: gtk/gtklabel.c:5705
msgid "_Open Link"
msgstr "_Mở liên kết"
#: gtk/gtklabel.c:5707
#: gtk/gtklabel.c:5709
msgid "Copy _Link Address"
msgstr "Chép địa chỉ _liên kết"
#: gtk/gtklabel.c:5751 gtk/gtktext.c:2716 gtk/gtktextview.c:9094
#: gtk/gtklabel.c:5753 gtk/gtktext.c:2716 gtk/gtktextview.c:9088
msgid "Context menu"
msgstr "Trình đơn ngữ cảnh"
@@ -2726,7 +2727,7 @@ msgid "Play"
msgstr "Phát"
#: gtk/gtkmessagedialog.c:162 gtk/gtkmessagedialog.c:180
#: gtk/print/gtkprintbackend.c:639 gtk/gtkwindow.c:6194
#: gtk/print/gtkprintbackend.c:639 gtk/gtkwindow.c:6234
msgid "_OK"
msgstr "_OK"
@@ -2792,7 +2793,7 @@ msgstr "_Nhớ mật khẩu cho đến khi bạn đăng xuất"
#: gtk/gtkmountoperation.c:781
msgid "Remember _forever"
msgstr "_Nhớ mãi mãi"
msgstr "Nhớ _mãi mãi"
#: gtk/gtkmountoperation.c:1251
#, c-format
@@ -2858,7 +2859,7 @@ msgstr "Thẻ kế trước"
msgid "Next tab"
msgstr "Thẻ kế tiếp"
#: gtk/gtknotebook.c:4331 gtk/gtknotebook.c:6539
#: gtk/gtknotebook.c:4331 gtk/gtknotebook.c:6541
#, c-format
msgid "Page %u"
msgstr "Trang %u"
@@ -3326,8 +3327,8 @@ msgstr "Lý do thường là không thể tạo tập tin tạm."
#. window
#: gtk/print/gtkprintoperation-portal.c:264
#: gtk/print/gtkprintoperation-portal.c:584
#: gtk/print/gtkprintoperation-portal.c:653 gtk/print/gtkprintunixdialog.c:3008
#: gtk/print/gtkprintoperation-portal.c:594
#: gtk/print/gtkprintoperation-portal.c:663 gtk/print/gtkprintunixdialog.c:3008
msgid "Print"
msgstr "In"
@@ -3499,7 +3500,7 @@ msgstr "Không thể di chuyển mục có URI “%s” đến “%s”"
msgid "No registered application with name “%s” for item with URI “%s” found"
msgstr "Không tìm thấy ứng dụng nào đăng ký tên “%s” cho mục có URI “%s”"
#: gtk/gtksearchentry.c:758
#: gtk/gtksearchentry.c:767
msgid "Clear Entry"
msgstr "Xóa mục tin"
@@ -3590,24 +3591,24 @@ msgctxt "accessibility"
msgid "Sidebar"
msgstr "Thanh bên"
#: gtk/gtktext.c:6141 gtk/gtktextview.c:9050
#: gtk/gtktext.c:6161 gtk/gtktextview.c:9044
msgid "Insert _Emoji"
msgstr "Chèn _Emoji"
#: gtk/gtktextview.c:9032
#: gtk/gtktextview.c:9026
msgid "_Undo"
msgstr "_Hoàn tác"
#: gtk/gtktextview.c:9036
#: gtk/gtktextview.c:9030
msgid "_Redo"
msgstr "Làm _lại"
#: gtk/gtkwindow.c:6182
#: gtk/gtkwindow.c:6222
#, c-format
msgid "Do you want to use GTK Inspector?"
msgstr "Bạn có muốn dùng GTK Inspector?"
#: gtk/gtkwindow.c:6184
#: gtk/gtkwindow.c:6224
#, c-format
msgid ""
"GTK Inspector is an interactive debugger that lets you explore and modify "
@@ -3617,7 +3618,7 @@ msgstr ""
"Bộ điều tra GTK là một bộ gỡ lỗi tương tác, nó giúp bạn dò tìm và sửa bên "
"trong bất kỳ ứng dụng GTK nào. Dùng nó có thể gây ra sự đổ vỡ của ứng dụng."
#: gtk/gtkwindow.c:6189
#: gtk/gtkwindow.c:6229
msgid "Dont show this message again"
msgstr "Đừng hiện lời nhắc này nữa"
@@ -3653,7 +3654,7 @@ msgstr "Vai trò"
msgid "Description"
msgstr "Mô tả"
#: gtk/inspector/a11y.ui:99 gtk/inspector/misc-info.ui:297
#: gtk/inspector/a11y.ui:99 gtk/inspector/misc-info.ui:296
msgid "Bounds"
msgstr "Giới hạn"
@@ -3955,61 +3956,61 @@ msgstr "Chế độ yêu cầu"
msgid "Measure map"
msgstr "Bản đồ đo lường"
#: gtk/inspector/misc-info.ui:254
#: gtk/inspector/misc-info.ui:253
msgid "Expand"
msgstr "Mở rộng"
#: gtk/inspector/misc-info.ui:322
#: gtk/inspector/misc-info.ui:321
msgid "Baseline"
msgstr "Đường cơ sở"
#: gtk/inspector/misc-info.ui:347
#: gtk/inspector/misc-info.ui:346
msgid "Surface"
msgstr "Bề mặt"
#: gtk/inspector/misc-info.ui:366 gtk/inspector/misc-info.ui:401
#: gtk/inspector/misc-info.ui:436 gtk/inspector/prop-editor.c:1150
#: gtk/inspector/prop-editor.c:1533 gtk/inspector/window.ui:396
#: gtk/inspector/misc-info.ui:365 gtk/inspector/misc-info.ui:400
#: gtk/inspector/misc-info.ui:435 gtk/inspector/prop-editor.c:1153
#: gtk/inspector/prop-editor.c:1536 gtk/inspector/window.ui:396
msgid "Properties"
msgstr "Thuộc tính"
#: gtk/inspector/misc-info.ui:382
#: gtk/inspector/misc-info.ui:381
msgid "Renderer"
msgstr "Bộ vẽ"
#: gtk/inspector/misc-info.ui:417
#: gtk/inspector/misc-info.ui:416
msgid "Frame Clock"
msgstr "Đồng hồ khung"
#: gtk/inspector/misc-info.ui:452
#: gtk/inspector/misc-info.ui:451
msgid "Tick Callback"
msgstr "Gọi ngược tick"
#: gtk/inspector/misc-info.ui:478
#: gtk/inspector/misc-info.ui:477
msgid "Frame Count"
msgstr "Số lượng khung hình"
#: gtk/inspector/misc-info.ui:503
#: gtk/inspector/misc-info.ui:502
msgid "Frame Rate"
msgstr "Tốc độ khung hình"
#: gtk/inspector/misc-info.ui:528
#: gtk/inspector/misc-info.ui:527
msgid "Scale"
msgstr "Tỷ lệ"
#: gtk/inspector/misc-info.ui:553
#: gtk/inspector/misc-info.ui:552
msgid "Mapped"
msgstr "Đã ánh xạ"
#: gtk/inspector/misc-info.ui:579
#: gtk/inspector/misc-info.ui:578
msgid "Realized"
msgstr "Hiện thực hóa"
#: gtk/inspector/misc-info.ui:605
#: gtk/inspector/misc-info.ui:604
msgid "Is Toplevel"
msgstr "Là mức đỉnh"
#: gtk/inspector/misc-info.ui:631
#: gtk/inspector/misc-info.ui:630
msgid "Child Visible"
msgstr "Con khả kiến"
@@ -4021,7 +4022,7 @@ msgstr "Con trỏ: %p"
#. Translators: %s is a type name, for example
#. * GtkPropertyExpression with value \"2.5\"
#.
#: gtk/inspector/prop-editor.c:824
#: gtk/inspector/prop-editor.c:827
#, c-format
msgid "%s with value \"%s\""
msgstr "%s với giá trị \"%s\""
@@ -4029,7 +4030,7 @@ msgstr "%s với giá trị \"%s\""
#. Translators: Both %s are type names, for example
#. * GtkPropertyExpression with type GObject
#.
#: gtk/inspector/prop-editor.c:835
#: gtk/inspector/prop-editor.c:838
#, c-format
msgid "%s with type %s"
msgstr "%s với kiểu %s"
@@ -4037,7 +4038,7 @@ msgstr "%s với kiểu %s"
#. Translators: Both %s are type names, for example
#. * GtkObjectExpression for GtkStringObject 0x23456789
#.
#: gtk/inspector/prop-editor.c:848
#: gtk/inspector/prop-editor.c:851
#, c-format
msgid "%s for %s %p"
msgstr "%s cho %s %p"
@@ -4045,71 +4046,71 @@ msgstr "%s cho %s %p"
#. Translators: Both %s are type names, for example
#. * GtkPropertyExpression with value type: gchararray
#.
#: gtk/inspector/prop-editor.c:878
#: gtk/inspector/prop-editor.c:881
#, c-format
msgid "%s with value type %s"
msgstr "%s với kiểu giá trị %s"
#: gtk/inspector/prop-editor.c:1227
#: gtk/inspector/prop-editor.c:1230
#, c-format
msgid "Uneditable property type: %s"
msgstr "Kiểu thuộc tính không thể chỉnh sửa: %s"
#: gtk/inspector/prop-editor.c:1385
#: gtk/inspector/prop-editor.c:1388
msgctxt "column number"
msgid "None"
msgstr "Không"
#: gtk/inspector/prop-editor.c:1422
#: gtk/inspector/prop-editor.c:1425
msgid "Attribute:"
msgstr "Thuộc tính:"
#: gtk/inspector/prop-editor.c:1425
#: gtk/inspector/prop-editor.c:1428
msgid "Model"
msgstr "Mô hình"
#: gtk/inspector/prop-editor.c:1430
#: gtk/inspector/prop-editor.c:1433
msgid "Column:"
msgstr "Cột:"
#. Translators: %s is a type name, for example
#. * Action from 0x2345678 (GtkApplicationWindow)
#.
#: gtk/inspector/prop-editor.c:1529
#: gtk/inspector/prop-editor.c:1532
#, c-format
msgid "Action from: %p (%s)"
msgstr "Thao tác từ: %p (%s)"
#: gtk/inspector/prop-editor.c:1584
#: gtk/inspector/prop-editor.c:1587
msgid "Reset"
msgstr "Đặt lại"
#: gtk/inspector/prop-editor.c:1592
#: gtk/inspector/prop-editor.c:1595
msgctxt "GtkSettings source"
msgid "Default"
msgstr "Mặc định"
#: gtk/inspector/prop-editor.c:1595
#: gtk/inspector/prop-editor.c:1598
msgctxt "GtkSettings source"
msgid "Theme"
msgstr "Chủ đề"
#: gtk/inspector/prop-editor.c:1598
#: gtk/inspector/prop-editor.c:1601
msgctxt "GtkSettings source"
msgid "XSettings"
msgstr "Cài đặt X"
#: gtk/inspector/prop-editor.c:1602
#: gtk/inspector/prop-editor.c:1605
msgctxt "GtkSettings source"
msgid "Application"
msgstr "Ứng dụng"
#: gtk/inspector/prop-editor.c:1605
#: gtk/inspector/prop-editor.c:1608
msgctxt "GtkSettings source"
msgid "Unknown"
msgstr "Không rõ"
#: gtk/inspector/prop-editor.c:1608
#: gtk/inspector/prop-editor.c:1611
msgid "Source:"
msgstr "Nguồn:"
@@ -4255,11 +4256,11 @@ msgstr "Thứ bậc"
msgid "Implements"
msgstr "Thực hiện"
#: gtk/inspector/visual.c:640 gtk/inspector/visual.c:659
#: gtk/inspector/visual.c:637 gtk/inspector/visual.c:656
msgid "Theme is hardcoded by GTK_THEME"
msgstr "Chủ đề bị có định do GTK_THEME"
#: gtk/inspector/visual.c:908
#: gtk/inspector/visual.c:905
msgid "Backend does not support window scaling"
msgstr "Phần ứng dụng chạy phía sau không hỗ trợ co dãn cửa sổ"
@@ -4355,11 +4356,7 @@ msgstr "Hiển thị tiêu điểm"
msgid "Show Accessibility warnings"
msgstr "Hiện cảnh báo hỗ trợ Truy cập"
#: gtk/inspector/visual.ui:670
msgid "Simulate Touchscreen"
msgstr "Mô phỏng màn hình cảm ứng"
#: gtk/inspector/visual.ui:701
#: gtk/inspector/visual.ui:667
msgid "Inspect Inspector"
msgstr "Xem xét Inspector"
@@ -4970,7 +4967,7 @@ msgstr "Chữ hoa nhỏ"
#: gtk/open-type-layout.h:110
msgctxt "OpenType layout"
msgid "Simplified Forms"
msgstr "Simplified Forms"
msgstr "Mẫu đơn giản hóa"
#: gtk/open-type-layout.h:111
msgctxt "OpenType layout"
@@ -5726,17 +5723,17 @@ msgstr "f"
#: gtk/print/paper_names_offsets.c:131
msgctxt "paper size"
msgid "Fan-Fold European"
msgstr "Gấp quạt Âu"
msgstr "Âu Gấp-quạt"
#: gtk/print/paper_names_offsets.c:132
msgctxt "paper size"
msgid "Fan-Fold US"
msgstr "Gấp quạt Mỹ"
msgstr "Mỹ Gấp-quạt"
#: gtk/print/paper_names_offsets.c:133
msgctxt "paper size"
msgid "Fan-Fold German Legal"
msgstr "Gấp quạt Đức hành pháp"
msgstr "Hành pháp Đức Gấp-quạt"
#: gtk/print/paper_names_offsets.c:134
msgctxt "paper size"
@@ -6182,11 +6179,11 @@ msgstr "_Tạo"
#: gtk/ui/gtkfontchooserdialog.ui:4
msgid "Select Font"
msgstr "Chọn phông"
msgstr "Chọn phông chữ"
#: gtk/ui/gtkfontchooserwidget.ui:64
msgid "Search font name"
msgstr "Tìm tên phông"
msgstr "Tìm kiếm tên phông chữ"
#: gtk/ui/gtkfontchooserwidget.ui:77
msgid "Filters"
@@ -6489,7 +6486,7 @@ msgstr "Một số cài đặt trong trường hợp xung đột hộp thoại"
#: modules/media/gtkffmediafile.c:253
#, c-format
msgid "Unspecified error decoding media"
msgstr "ặp lỗi khi giải mã chưa biết"
msgstr "Gặp lỗi khi giải mã chưa biết"
#: modules/media/gtkffmediafile.c:286
#, c-format
@@ -7168,7 +7165,7 @@ msgstr ""
#: tools/gtk-builder-tool-enumerate.c:56 tools/gtk-builder-tool-preview.c:179
#: tools/gtk-builder-tool-preview.c:180 tools/gtk-builder-tool-screenshot.c:360
#: tools/gtk-builder-tool-simplify.c:2529 tools/gtk-builder-tool-validate.c:261
#: tools/gtk-rendernode-tool-info.c:200 tools/gtk-rendernode-tool-show.c:102
#: tools/gtk-rendernode-tool-info.c:202 tools/gtk-rendernode-tool-show.c:106
msgid "FILE"
msgstr "TẬP_TIN"
@@ -7200,8 +7197,8 @@ msgid "Use style from CSS file"
msgstr "Dùng kiểu dáng từ tập tin CSS"
#: tools/gtk-builder-tool-preview.c:187 tools/gtk-builder-tool-screenshot.c:370
#: tools/gtk-builder-tool-validate.c:268 tools/gtk-rendernode-tool-show.c:109
#: tools/gtk-rendernode-tool-render.c:131
#: tools/gtk-builder-tool-validate.c:268 tools/gtk-rendernode-tool-show.c:113
#: tools/gtk-rendernode-tool-render.c:204
#, c-format
msgid "Could not initialize windowing system\n"
msgstr "Không thể khởi tạo hệ thống cửa sổ\n"
@@ -7237,7 +7234,6 @@ msgid "Failed to take a screenshot\n"
msgstr "Gặp lỗi khi chụp màn hình\n"
#: tools/gtk-builder-tool-screenshot.c:309
#: tools/gtk-rendernode-tool-render.c:83
#, c-format
msgid ""
"File %s exists.\n"
@@ -7247,13 +7243,13 @@ msgstr ""
"Dùng tùy chọn --force để ghi đè.\n"
#: tools/gtk-builder-tool-screenshot.c:332
#: tools/gtk-rendernode-tool-render.c:96
#: tools/gtk-rendernode-tool-render.c:172
#, c-format
msgid "Output written to %s.\n"
msgstr "Đầu ra ghi vào %s.\n"
#: tools/gtk-builder-tool-screenshot.c:336
#: tools/gtk-rendernode-tool-render.c:100
#: tools/gtk-rendernode-tool-render.c:176
#, c-format
msgid "Failed to save %s: %s\n"
msgstr "Gặp lỗi khi lưu %s: %s\n"
@@ -7267,12 +7263,11 @@ msgid "Save as node file instead of png"
msgstr "Lưu dạng tập tin nút thay vì png"
#: tools/gtk-builder-tool-screenshot.c:362
#: tools/gtk-rendernode-tool-render.c:123
msgid "Overwrite existing file"
msgstr "Ghi đè lên tập tin sẵn có"
#: tools/gtk-builder-tool-screenshot.c:363
#: tools/gtk-rendernode-tool-render.c:124
#: tools/gtk-rendernode-tool-render.c:197
msgid "FILE…"
msgstr "TẬP_TIN…"
@@ -7472,63 +7467,81 @@ msgstr ""
" render Chụp màn hình nút\n"
"\n"
#: tools/gtk-rendernode-tool-info.c:177
#: tools/gtk-rendernode-tool-info.c:179
#, c-format
msgid "Number of nodes: %u\n"
msgstr "Số lượng nút: %u\n"
#: tools/gtk-rendernode-tool-info.c:184
#: tools/gtk-rendernode-tool-info.c:186
#, c-format
msgid "Depth: %u\n"
msgstr "Độ sâu: %u\n"
#: tools/gtk-rendernode-tool-info.c:187
#: tools/gtk-rendernode-tool-info.c:189
#, c-format
msgid "Bounds: %g x %g\n"
msgstr "Giới hạn: %g x %g\n"
#: tools/gtk-rendernode-tool-info.c:188
#: tools/gtk-rendernode-tool-info.c:190
#, c-format
msgid "Origin: %g %g\n"
msgstr "Gốc: %g %g\n"
#: tools/gtk-rendernode-tool-info.c:209
#: tools/gtk-rendernode-tool-info.c:211
msgid "Provide information about the render node."
msgstr "Cung cấp thông tin về nút bộ vẽ."
#: tools/gtk-rendernode-tool-info.c:222 tools/gtk-rendernode-tool-show.c:130
#: tools/gtk-rendernode-tool-render.c:152
#: tools/gtk-rendernode-tool-info.c:224 tools/gtk-rendernode-tool-show.c:134
#: tools/gtk-rendernode-tool-render.c:225
#, c-format
msgid "No .node file specified\n"
msgstr "Chưa chỉ ra tập tin .node\n"
#: tools/gtk-rendernode-tool-info.c:228
#: tools/gtk-rendernode-tool-info.c:230
#, c-format
msgid "Can only accept a single .node file\n"
msgstr "Chỉ có thể chấp nhận một tập tin nút đơn\n"
#: tools/gtk-rendernode-tool-show.c:117
#: tools/gtk-rendernode-tool-show.c:105
msgid "Don't add a titlebar"
msgstr "Đừng thêm thanh tựa đề"
#: tools/gtk-rendernode-tool-show.c:121
msgid "Show the render node."
msgstr "Hiện nút bộ vẽ."
#: tools/gtk-rendernode-tool-show.c:136
#: tools/gtk-rendernode-tool-show.c:140
#, c-format
msgid "Can only preview a single .node file\n"
msgstr "Chỉ có thể xem trước một tập tin nút đơn\n"
#: tools/gtk-rendernode-tool-render.c:122
#: tools/gtk-rendernode-tool-render.c:123
#, c-format
msgid ""
"File %s exists.\n"
"If you want to overwrite, specify the filename.\n"
msgstr ""
"Tập tin %s sẵn có.\n"
"Nếu bạn muốn đè hãy chỉ định tên tập tin.\n"
#: tools/gtk-rendernode-tool-render.c:137
#, c-format
msgid "Failed to generate SVG: %s\n"
msgstr "Gặp lỗi khi tạo SVG: %s\n"
#: tools/gtk-rendernode-tool-render.c:196
msgid "Renderer to use"
msgstr "Bộ vẽ được dùng"
#: tools/gtk-rendernode-tool-render.c:122
#: tools/gtk-rendernode-tool-render.c:196
msgid "RENDERER"
msgstr "BỘ_VẼ"
#: tools/gtk-rendernode-tool-render.c:139
#: tools/gtk-rendernode-tool-render.c:212
msgid "Render a .node file to an image."
msgstr "Vẽ một tập tin .node ra một ảnh."
#: tools/gtk-rendernode-tool-render.c:158
#: tools/gtk-rendernode-tool-render.c:231
#, c-format
msgid "Can only render a single .node file to a single output file\n"
msgstr "Chỉ có thể vẽ một tập tin .node đơn ra một tập tin đầu ra đơn\n"
@@ -7538,6 +7551,11 @@ msgstr "Chỉ có thể vẽ một tập tin .node đơn ra một tập tin đ
msgid "Error at %s: %s\n"
msgstr "Lỗi tại %s: %s\n"
#: tools/gtk-rendernode-tool-utils.c:69
#, c-format
msgid "Failed to load node file: %s\n"
msgstr "Gặp lỗi khi tải tập tin nút: %s\n"
#: tools/updateiconcache.c:1391
#, c-format
msgid "Failed to write header\n"
@@ -7646,6 +7664,9 @@ msgstr ""
"Nếu bạn thật muốn tạo một bộ nhớ biểu tượng ở đây, hãy dùng --ignore-theme-"
"index.\n"
#~ msgid "Simulate Touchscreen"
#~ msgstr "Mô phỏng màn hình cảm ứng"
#~ msgid "Tab list"
#~ msgstr "Danh sách tab"
+6 -1
View File
@@ -119,10 +119,15 @@ row_data_update_info (RowData *data,
icon = g_file_icon_new (thumbnail_file);
g_object_unref (thumbnail_file);
}
else
else if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON))
{
icon = g_file_info_get_icon (info);
}
else
{
icon = NULL;
}
gtk_widget_set_visible (data->icon, icon != NULL);
gtk_image_set_from_gicon (GTK_IMAGE (data->icon), icon);
+5 -1
View File
@@ -376,10 +376,14 @@ row_data_update_info (RowData *data,
icon = g_file_icon_new (thumbnail_file);
g_object_unref (thumbnail_file);
}
else
else if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON))
{
icon = g_file_info_get_icon (info);
}
else
{
icon = NULL;
}
gtk_widget_set_visible (data->icon, icon != NULL);
gtk_image_set_from_gicon (GTK_IMAGE (data->icon), icon);
+6
View File
@@ -43,10 +43,16 @@ foreach t : tests
suites = ['gdk'] + t.get('suites', [])
test_timeout = 60
if 'slow' in suites
test_timeout = 90
endif
test(test_name, test_exe,
args: [ '--tap', '-k' ],
protocol: 'tap',
is_parallel: t.get('parallel', false),
timeout: test_timeout,
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
+2
View File
@@ -1,9 +1,11 @@
#include "config.h"
#include <string.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include "../reftests/reftest-compare.h"
static char *arg_output_dir = NULL;
static gboolean flip = FALSE;
static gboolean rotate = FALSE;
@@ -0,0 +1,21 @@
transform {
transform: scale(30);
child: text {
font: "text-mixed-color 7.5" url("data:font/ttf;base64,\
AAEAAAAKAIAAAwAgQ09MUgATAEEAAAJ8AAAALENQQUwB/wATAAACqAAAABpjbWFwAHcAPQAAATwA\
AAA0Z2x5Zu8g4kAAAAGEAAAA0mhlYWQmofyJAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AQAAAAEoAAAAFGxvY2EAyAD5AAABcAAAABRtYXhwAAwACQAAAQgAAAAgbmFtZX7VdrQAAAJYAAAA\
IgABAAAAARmajs74k18PPPUAAggAAAAAAOHCPQAAAAAA4cpY+QAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAJAAgAAgAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAADAAAADAAEACgAAAAGAAQAAQAC\
ACAASP//AAAAIABB////4P/AAAEAAAAAAAAAAAAAAAwAGAAkADAAPABIAFwAaQABAAAAAAQACAAA\
AwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA\
/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAA\
AAQACAAAAwAAMSERIQQA/AAIAAACAAAAAAQACAAAAwAHAAAxIREhExEhEQQA/AAFA/YIAPgFB/b4\
CgAAAQEAAAADAAgAAAMAACEhESEBAAIA/gAIAAAAAAAAAQASAAEAAAAAAAEAEAAAdGV4dC1taXhl\
ZC1jb2xvcgAAAAAAAwAAAA4AAAAgAAMABAAAAAEABQABAAEABgACAAEAAgAAAAMAAQADAAIAAAAD\
AAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 7 10;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1002 B

+29
View File
@@ -0,0 +1,29 @@
transform {
transform: scale(30);
child: text {
font: "text-mixed-color 7.5" url("data:font/ttf;base64,\
AAEAAAAKAIAAAwAgQ09MUgATAEEAAAJ8AAAALENQQUwB/wATAAACqAAAABpjbWFwAHcAPQAAATwA\
AAA0Z2x5Zu8g4kAAAAGEAAAA0mhlYWQmofyJAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AQAAAAEoAAAAFGxvY2EAyAD5AAABcAAAABRtYXhwAAwACQAAAQgAAAAgbmFtZX7VdrQAAAJYAAAA\
IgABAAAAARmajs74k18PPPUAAggAAAAAAOHCPQAAAAAA4cpY+QAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAJAAgAAgAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAADAAAADAAEACgAAAAGAAQAAQAC\
ACAASP//AAAAIABB////4P/AAAEAAAAAAAAAAAAAAAwAGAAkADAAPABIAFwAaQABAAAAAAQACAAA\
AwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA\
/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAA\
AAQACAAAAwAAMSERIQQA/AAIAAACAAAAAAQACAAAAwAHAAAxIREhExEhEQQA/AAFA/YIAPgFB/b4\
CgAAAQEAAAADAAgAAAMAACEhESEBAAIA/gAIAAAAAAAAAQASAAEAAAAAAAEAEAAAdGV4dC1taXhl\
ZC1jb2xvcgAAAAAAAwAAAA4AAAAgAAMABAAAAAEABQABAAEABgACAAEAAgAAAAMAAQADAAIAAAAD\
AAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 7 10;
}
}
color {
bounds: 144 -305 10 10;
color: rgb(0,0,0);
}
color {
bounds: 144 -5 10 10;
color: rgb(0,0,0);
}
+22
View File
@@ -0,0 +1,22 @@
transform {
transform: rotate(45);
child: clip {
clip: -10 -2.5 20 5;
child: color {
bounds: -25 -25 50 50;
color: rgb(255,0,0);
}
}
}
color {
bounds: -16 -16 16 16;
color: rgb(0,0,0);
}
color {
bounds: -8 -8 16 16;
color: rgb(0,0,0);
}
color {
bounds: 0 0 16 16;
color: rgb(0,0,0);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

@@ -0,0 +1,27 @@
color {
bounds: 0 0 15 15;
color: rgb(0,0,0);
}
transform {
transform: translate(2, 2.6);
child: fill {
child: linear-gradient {
bounds: -1 -1 12 12;
start: -1 0;
end: 11 0;
stops: 0.5 rgb(0,80,0), 0.5 rgb(80,0,0);
}
path: "\
M 0 0\
L 10 0\
L 10 10\
L 0 10\
Z\
M 1 1\
L 1 9\
L 9 9\
L 9 1\
Z";
fill-rule: winding;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

@@ -0,0 +1,25 @@
color {
bounds: 0 0 15 15;
color: rgba(0,0,0,1);
}
transform {
transform: translate(2, 2.6);
child: fill {
child: color {
bounds: 0 0 50 50;
color: rgb(0,120,0);
}
path: "\
M 0 0\
L 10 0\
L 10 10\
L 0 10\
Z\
M 1 1\
L 1 9\
L 9 9\
L 9 1\
Z";
fill-rule: winding;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

@@ -0,0 +1,17 @@
color {
bounds: 0 0 14 14;
color: rgb(255,0,0);
}
transform {
transform: scale(2) translate(0.75, 0.25);
child: color-matrix {
matrix: matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
child: transform {
transform: translate(0.25, 0.75);
child: color {
bounds: 0 0 5 5;
color: rgb(255,255,255);
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 94 B

@@ -0,0 +1,20 @@
color {
bounds: 0 0 15 15;
color: rgb(0,0,0);
}
transform {
transform: translate(2.6, 2);
child: stroke {
child: linear-gradient {
bounds: -1 -1 12 12;
start: 0 -1;
end: 0 11;
stops: 0.5 rgb(0,80,0), 0.5 rgb(80,0,0);
}
path: "\
M 0.5 0.5 h 9 v 9 h -9 z";
line-width: 1;
line-cap: butt;
line-join: miter;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

@@ -0,0 +1,18 @@
color {
bounds: 0 0 15 15;
color: rgb(0,0,0);
}
transform {
transform: translate(2.6, 2);
child: stroke {
child: color {
bounds: 0 0 50 50;
color: rgb(0,80,0);
}
path: "\
M 0.5 0.5 h 9 v 9 h -9 z";
line-width: 1;
line-cap: butt;
line-join: miter;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 B

+18
View File
@@ -0,0 +1,18 @@
text {
font: "text-mixed-color 30" url("data:font/ttf;base64,\
AAEAAAAKAIAAAwAgQ09MUgATAEEAAAJ8AAAALENQQUwB/wATAAACqAAAABpjbWFwAHcAPQAAATwA\
AAA0Z2x5Zu8g4kAAAAGEAAAA0mhlYWQmofyJAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AQAAAAEoAAAAFGxvY2EAyAD5AAABcAAAABRtYXhwAAwACQAAAQgAAAAgbmFtZX7VdrQAAAJYAAAA\
IgABAAAAARmajs74k18PPPUAAggAAAAAAOHCPQAAAAAA4cpY+QAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAJAAgAAgAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAADAAAADAAEACgAAAAGAAQAAQAC\
ACAASP//AAAAIABB////4P/AAAEAAAAAAAAAAAAAAAwAGAAkADAAPABIAFwAaQABAAAAAAQACAAA\
AwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA\
/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAA\
AAQACAAAAwAAMSERIQQA/AAIAAACAAAAAAQACAAAAwAHAAAxIREhExEhEQQA/AAFA/YIAPgFB/b4\
CgAAAQEAAAADAAgAAAMAACEhESEBAAIA/gAIAAAAAAAAAQASAAEAAAAAAAEAEAAAdGV4dC1taXhl\
ZC1jb2xvcgAAAAAAAwAAAA4AAAAgAAMABAAAAAEABQABAAEABgACAAEAAgAAAAMAAQADAAIAAAAD\
AAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 1 40, 1 40, 8 40, 1 40;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

@@ -0,0 +1,18 @@
text {
font: "text-mixed-color-colrv1 15" url("data:font/ttf;base64,\
AAEAAAAKAIAAAwAgQ09MUhc9T40AAAI4AAAAe0NQQUwB/wATAAACtAAAABpjbWFwAHUAPQAAATgA\
AAA0Z2x5Zn7NhtgAAAF8AAAAkGhlYWQmof0NAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AAAAAAEoAAAAEGxvY2EAbACQAAABbAAAABBtYXhwAAkABQAAAQgAAAAgbmFtZR9CFpQAAAIMAAAA\
KQABAAAAARmaAQnTZV8PPPUAAggAAAAAAOHCPQAAAAAA4cpZfQAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAHAAQAAQAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAMAAQAKAAAAAYABAABAAIAIABG\
//8AAAAgAEH////g/8AAAQAAAAAAAAAAAAAADAAYACQAMAA8AEgAAQAAAAAEAAgAAAMAADEhESEE\
APwACAAAAQAAAAAEAAgAAAMAADEhESEEAPwACAAAAQAAAAAEAAgAAAMAADEhESEEAPwACAAAAQAA\
AAAEAAgAAAMAADEhESEEAPwACAAAAQAAAAAEAAgAAAMAADEhESEEAPwACAAAAQAAAAAEAAgAAAMA\
ADEhESEEAPwACAAAAAABABIAAQAAAAAAAQAXAAB0ZXh0LW1peGVkLWNvbG9yLWNvbHJ2MQAAAAAB\
AAAAAAAAAAAAAAAAAAAAIgAAAEoAAAAAAAAAAAAAAAAAAAADAAQAAAAWAAUAAAAcAAYAAAAiAQEA\
AAAAAQEAAAABAQEAAAACAAAAAwAAABAAAAAbAAAAJgoAAAYAAQIAAEAACgAABgACAgABQAAKAAAG\
AAMCAAJAAAAAAAADAAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 1 20, 2 20, 3 20, 4 20 0 0 color, 5 20 0 0 color, 6 20 0 0 color;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

@@ -0,0 +1,21 @@
transform {
transform: translate(0, 100);
child: text {
font: "text-mixed-color 20" url("data:font/ttf;base64,\
AAEAAAAKAIAAAwAgQ09MUgATAEEAAAJ8AAAALENQQUwB/wATAAACqAAAABpjbWFwAHcAPQAAATwA\
AAA0Z2x5Zu8g4kAAAAGEAAAA0mhlYWQmofyJAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AQAAAAEoAAAAFGxvY2EAyAD5AAABcAAAABRtYXhwAAwACQAAAQgAAAAgbmFtZX7VdrQAAAJYAAAA\
IgABAAAAARmajs74k18PPPUAAggAAAAAAOHCPQAAAAAA4cpY+QAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAJAAgAAgAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAADAAAADAAEACgAAAAGAAQAAQAC\
ACAASP//AAAAIABB////4P/AAAEAAAAAAAAAAAAAAAwAGAAkADAAPABIAFwAaQABAAAAAAQACAAA\
AwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA\
/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAA\
AAQACAAAAwAAMSERIQQA/AAIAAACAAAAAAQACAAAAwAHAAAxIREhExEhEQQA/AAFA/YIAPgFB/b4\
CgAAAQEAAAADAAgAAAMAACEhESEBAAIA/gAIAAAAAAAAAQASAAEAAAAAAAEAEAAAdGV4dC1taXhl\
ZC1jb2xvcgAAAAAAAwAAAA4AAAAgAAMABAAAAAEABQABAAEABgACAAEAAgAAAAMAAQADAAIAAAAD\
AAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 1 20, 2 20, 3 20, 4 20 0 0 color, 5 20 0 0 color, 6 20 0 0 color;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.
@@ -0,0 +1,226 @@
<?xml version="1.0" encoding="utf-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="2.4">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="A"/>
<GlyphID id="2" name="B"/>
<GlyphID id="3" name="C"/>
<GlyphID id="4" name="D"/>
<GlyphID id="5" name="E"/>
<GlyphID id="6" name="F"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.1"/>
<checkSumAdjustment value="0x2a3f4cae"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000010"/>
<unitsPerEm value="2048"/>
<created value="Tue Jan 9 00:00:00 2024"/>
<modified value="Tue Jan 9 00:00:00 2024"/>
<xMin value="0"/>
<yMin value="0"/>
<xMax value="0"/>
<yMax value="0"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="1"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="1.0"/>
<ascent value="2048"/>
<descent value="0"/>
<lineGap value="0"/>
<advanceWidthMax value="20480"/>
<minLeftSideBearing value="0"/>
<minRightSideBearing value="0"/>
<xMaxExtent value="0"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="2"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="4"/>
<maxPoints value="0"/>
<maxContours value="0"/>
<maxCompositePoints value="0"/>
<maxCompositeContours value="0"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="0"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="0"/>
<maxSizeOfInstructions value="0"/>
<maxComponentElements value="0"/>
<maxComponentDepth value="0"/>
</maxp>
<hmtx>
<mtx name=".notdef" width="1024" lsb="0"/>
<mtx name="A" width="1024" lsb="0"/>
<mtx name="B" width="1024" lsb="0"/>
<mtx name="C" width="1024" lsb="0"/>
<mtx name="D" width="1024" lsb="0"/>
<mtx name="E" width="1024" lsb="0"/>
<mtx name="F" width="1024" lsb="0"/>
</hmtx>
<loca>
</loca>
<glyf> <!-- Will result in empty table -->
<TTGlyph name=".notdef"/>
<TTGlyph name="A">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="B">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="C">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="D">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="E">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="F">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
</glyf>
<COLR>
<Version value="1"/>
<BaseGlyphList>
<BaseGlyphPaintRecord index="0">
<BaseGlyph value="D"/>
<Paint Format="1">
<NumLayers value="1"/>
<FirstLayerIndex value="0"/>
</Paint>
</BaseGlyphPaintRecord>
<BaseGlyphPaintRecord index="1">
<BaseGlyph value="E"/>
<Paint Format="1">
<NumLayers value="1"/>
<FirstLayerIndex value="1"/>
</Paint>
</BaseGlyphPaintRecord>
<BaseGlyphPaintRecord index="2">
<BaseGlyph value="F"/>
<Paint Format="1">
<NumLayers value="1"/>
<FirstLayerIndex value="2"/>
</Paint>
</BaseGlyphPaintRecord>
</BaseGlyphList>
<LayerList>
<Paint index="0" Format="10">
<Paint Format="2">
<PaletteIndex value="0"/>
<Alpha value="1.0"/>
</Paint>
<Glyph value="A"/>
</Paint>
<Paint index="1" Format="10">
<Paint Format="2">
<PaletteIndex value="1"/>
<Alpha value="1.0"/>
</Paint>
<Glyph value="B"/>
</Paint>
<Paint index="2" Format="10">
<Paint Format="2">
<PaletteIndex value="2"/>
<Alpha value="1.0"/>
</Paint>
<Glyph value="C"/>
</Paint>
</LayerList>
</COLR>
<CPAL>
<version value="0"/>
<numPaletteEntries value="3"/>
<palette index="0">
<color index="0" value="#FF0000FF"/>
<color index="1" value="#00FF00FF"/>
<color index="2" value="#0000FFFF"/>
</palette>
</CPAL>
<name>
<namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
text-mixed-color-colrv1
</namerecord>
</name>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name=".notdef"/>
<map code="0x41" name="A"/>
<map code="0x42" name="B"/>
<map code="0x43" name="C"/>
<map code="0x44" name="D"/>
<map code="0x45" name="E"/>
<map code="0x46" name="F"/>
</cmap_format_4>
</cmap>
</ttFont>
Binary file not shown.
+219
View File
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="2.4">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="A"/>
<GlyphID id="2" name="B"/>
<GlyphID id="3" name="C"/>
<GlyphID id="4" name="D"/>
<GlyphID id="5" name="E"/>
<GlyphID id="6" name="F"/>
<GlyphID id="7" name="G"/>
<GlyphID id="8" name="H"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.1"/>
<checkSumAdjustment value="0x2a3f4cae"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000010"/>
<unitsPerEm value="2048"/>
<created value="Tue Jan 9 00:00:00 2024"/>
<modified value="Tue Jan 9 00:00:00 2024"/>
<xMin value="0"/>
<yMin value="0"/>
<xMax value="0"/>
<yMax value="0"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="1"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="1.0"/>
<ascent value="2048"/>
<descent value="0"/>
<lineGap value="0"/>
<advanceWidthMax value="20480"/>
<minLeftSideBearing value="0"/>
<minRightSideBearing value="0"/>
<xMaxExtent value="0"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="2"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="4"/>
<maxPoints value="0"/>
<maxContours value="0"/>
<maxCompositePoints value="0"/>
<maxCompositeContours value="0"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="0"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="0"/>
<maxSizeOfInstructions value="0"/>
<maxComponentElements value="0"/>
<maxComponentDepth value="0"/>
</maxp>
<hmtx>
<mtx name=".notdef" width="1024" lsb="0"/>
<mtx name="A" width="1024" lsb="0"/>
<mtx name="B" width="1024" lsb="0"/>
<mtx name="C" width="1024" lsb="0"/>
<mtx name="D" width="1024" lsb="0"/>
<mtx name="E" width="1024" lsb="0"/>
<mtx name="F" width="1024" lsb="0"/>
<mtx name="G" width="1024" lsb="0"/>
<mtx name="H" width="1024" lsb="256" rsb="256"/>
</hmtx>
<loca>
</loca>
<glyf>
<TTGlyph name=".notdef"/>
<TTGlyph name="A">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="B">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="C">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="D">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="E">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="F">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="G">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="1024" y="0" on="1"/>
<pt x="1024" y="2048" on="1"/>
<pt x="0" y="2048" on="1"/>
</contour>
<contour>
<pt x="5" y="5" on="1"/>
<pt x="5" y="2043" on="1"/>
<pt x="1019" y="2043" on="1"/>
<pt x="1019" y="5" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="H">
<contour>
<pt x="256" y="0" on="1"/>
<pt x="768" y="0" on="1"/>
<pt x="768" y="2048" on="1"/>
<pt x="256" y="2048" on="1"/>
</contour>
<instructions><assembly></assembly></instructions>
</TTGlyph>
</glyf>
<COLR>
<version value="0"/>
<ColorGlyph name="D">
<layer colorID="0" name="B"/>
</ColorGlyph>
<ColorGlyph name="E">
<layer colorID="1" name="C"/>
</ColorGlyph>
<ColorGlyph name="F">
<layer colorID="2" name="C"/>
</ColorGlyph>
</COLR>
<CPAL>
<version value="0"/>
<numPaletteEntries value="3"/>
<palette index="0">
<color index="0" value="#FF0000FF"/>
<color index="1" value="#00FF00FF"/>
<color index="2" value="#0000FFFF"/>
</palette>
</CPAL>
<name>
<namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
text-mixed-color
</namerecord>
</name>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name=".notdef"/>
<map code="0x41" name="A"/>
<map code="0x42" name="B"/>
<map code="0x43" name="C"/>
<map code="0x44" name="D"/>
<map code="0x45" name="E"/>
<map code="0x46" name="F"/>
<map code="0x47" name="G"/>
<map code="0x48" name="H"/>
</cmap_format_4>
</cmap>
</ttFont>
+24 -8
View File
@@ -10,6 +10,7 @@ node_parser = executable('node-parser', 'node-parser.c',
)
compare_render_tests = [
'big-box-glyph-nocairo',
'big-checkerboard',
'big-checkerboard-scaled-down',
'big-checkerboard-scaled-down-nearest',
@@ -28,6 +29,7 @@ compare_render_tests = [
'border-opacity',
'borders-rotated',
'borders-scaled',
'clip-contained',
'clip-coordinates-2d',
'clip-coordinates-nocairo',
'clip-in-rounded-clip1',
@@ -70,6 +72,8 @@ compare_render_tests = [
'empty-transform',
'fill',
'fill-clipped-nogl',
'fill-fractional-translate-gradient-nogl',
'fill-fractional-translate-nogl',
'fill-opacity',
'fill-scaled-up',
'fill-with-3d-contents-nogl-nocairo',
@@ -89,6 +93,7 @@ compare_render_tests = [
'mask-texture-color-alpha',
'mipmap-generation-later',
'nested-rounded-clips',
'offscreen-fractional-translate-nogl',
'offscreen-pixel-alignment-nogl-nocairo',
'opacity_clip',
'opacity-colormatrix-combinations',
@@ -127,8 +132,13 @@ compare_render_tests = [
'shrink-rounded-border',
'stroke',
'stroke-clipped-nogl',
'stroke-fractional-translate-gradient-nogl',
'stroke-fractional-translate-nogl',
'stroke-opacity',
'stroke-with-3d-contents-nogl-nocairo',
'text-glyph-lsb',
'text-mixed-color-nocairo',
'text-mixed-color-colrv1',
'texture-coords',
'texture-scale-filters-nocairo',
'texture-scale-magnify-10000x',
@@ -196,13 +206,14 @@ foreach renderer : renderers
'GSK_RENDERER=' + renderer_name,
'GTK_A11Y=test',
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
'TEST_FONT_DIR=@0@/fonts'.format(meson.current_source_dir())
]
if ((not testname.contains(exclude_term)) and
(renderer_name != 'broadway' or broadway_enabled) and
(renderer_name != 'vulkan' or have_vulkan))
test(renderer_name + ' ' + testname, compare_render,
test('compare ' + renderer_name + ' ' + testname, compare_render,
args: [
'--output', join_paths(meson.current_build_dir(), 'compare', renderer_name),
join_paths(meson.current_source_dir(), 'compare', testname + '.node'),
@@ -211,7 +222,7 @@ foreach renderer : renderers
env: test_env,
suite: suites,
)
test(renderer_name + ' ' + testname + ' flipped', compare_render,
test('compare ' + renderer_name + ' ' + testname + ' flipped', compare_render,
args: [
'--flip',
'--output', join_paths(meson.current_build_dir(), 'compare', renderer_name),
@@ -221,7 +232,7 @@ foreach renderer : renderers
env: test_env,
suite: suites + [ 'gsk-compare-flipped-' + renderer_name ],
)
test(renderer_name + ' ' + testname + ' repeated', compare_render,
test('compare ' + renderer_name + ' ' + testname + ' repeated', compare_render,
args: [
'--repeat',
'--output', join_paths(meson.current_build_dir(), 'compare', renderer_name),
@@ -231,7 +242,7 @@ foreach renderer : renderers
env: test_env,
suite: suites + [ 'gsk-compare-repeated-' + renderer_name ],
)
test(renderer_name + ' ' + testname + ' rotated', compare_render,
test('compare ' + renderer_name + ' ' + testname + ' rotated', compare_render,
args: [
'--rotate',
'--output', join_paths(meson.current_build_dir(), 'compare', renderer_name),
@@ -241,7 +252,7 @@ foreach renderer : renderers
env: test_env,
suite: suites + [ 'gsk-compare-rotated-' + renderer_name ],
)
test(renderer_name + ' ' + testname + ' masked', compare_render,
test('compare ' + renderer_name + ' ' + testname + ' masked', compare_render,
args: [
'--mask',
'--output', join_paths(meson.current_build_dir(), 'compare', renderer_name),
@@ -251,7 +262,7 @@ foreach renderer : renderers
env: test_env,
suite: suites + [ 'gsk-compare-masked-' + renderer_name ],
)
test(renderer_name + ' ' + testname + ' replayed', compare_render,
test('compare ' + renderer_name + ' ' + testname + ' replayed', compare_render,
args: [
'--replay',
'--output', join_paths(meson.current_build_dir(), 'compare', renderer_name),
@@ -374,10 +385,15 @@ node_parser_tests = [
'text-fail.node',
'text-fail.ref.node',
'text-fail.errors',
'text-font-blob.node',
'text-font-blob.ref.node',
'text-font-errors.node',
'text-font-errors.ref.node',
'text-font-errors.errors',
'text-no-color.node',
'texture-fail.node',
'texture-fail.ref.node',
'texture-fail.ref.errors',
'texture-fail.errors',
'texture-names.node',
'texture-scale-filters.node',
'texture-scale-filters.ref.node',
+2 -2
View File
@@ -1,3 +1,3 @@
<data>:4:3-7: error: GTK_CSS_PARSER_WARNING_SYNTAX
<data>:3:11-12: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE
<data>:4:11-12: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE
<data>:6:3-9: error: GTK_CSS_PARSER_WARNING_SYNTAX
<data>:8:1-2: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE
+5 -3
View File
@@ -1,4 +1,6 @@
color {
bounds: 0 0 50 50;
color: rgb(255,0,204);
text {
color: rgb(50,50,50);
font: "Cantarell 11";
glyphs: "N";
offset: 0 32.0186;
}
@@ -0,0 +1,23 @@
text {
font: "text-mixed-color 7.5" url("data:font/ttf;base64,\
AAEAAAAKAIAAAwAgQ09MUgATAEEAAAJ8AAAALENQQUwB/wATAAACqAAAABpjbWFwAHcAPQAAATwA\
AAA0Z2x5Zu8g4kAAAAGEAAAA0mhlYWQmofyJAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AQAAAAEoAAAAFGxvY2EAyAD5AAABcAAAABRtYXhwAAwACQAAAQgAAAAgbmFtZX7VdrQAAAJYAAAA\
IgABAAAAARmajs74k18PPPUAAggAAAAAAOHCPQAAAAAA4cpY+QAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAJAAgAAgAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAADAAAADAAEACgAAAAGAAQAAQAC\
ACAASP//AAAAIABB////4P/AAAEAAAAAAAAAAAAAAAwAGAAkADAAPABIAFwAaQABAAAAAAQACAAA\
AwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA\
/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAA\
AAQACAAAAwAAMSERIQQA/AAIAAACAAAAAAQACAAAAwAHAAAxIREhExEhEQQA/AAFA/YIAPgFB/b4\
CgAAAQEAAAADAAgAAAMAACEhESEBAAIA/gAIAAAAAAAAAQASAAEAAAAAAAEAEAAAdGV4dC1taXhl\
ZC1jb2xvcgAAAAAAAwAAAA4AAAAgAAMABAAAAAEABQABAAEABgACAAEAAgAAAAMAAQADAAIAAAAD\
AAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 7 10;
}
text {
font: "Cantarell 11";
glyphs: "Hello";
}
@@ -0,0 +1,21 @@
text {
font: "text-mixed-color 7.5" url("data:font/ttf;base64,AAEAAAAKAIAAAwAgQ09MUgATAEEAAAJ8AAAALENQQUwB/wATAAACqAAAABpjbWFwAHcAPQAAATwA\
AAA0Z2x5Zu8g4kAAAAGEAAAA0mhlYWQmofyJAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AQAAAAEoAAAAFGxvY2EAyAD5AAABcAAAABRtYXhwAAwACQAAAQgAAAAgbmFtZX7VdrQAAAJYAAAA\
IgABAAAAARmajs74k18PPPUAAggAAAAAAOHCPQAAAAAA4cpY+QAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAJAAgAAgAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAADAAAADAAEACgAAAAGAAQAAQAC\
ACAASP//AAAAIABB////4P/AAAEAAAAAAAAAAAAAAAwAGAAkADAAPABIAFwAaQABAAAAAAQACAAA\
AwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA\
/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAA\
AAQACAAAAwAAMSERIQQA/AAIAAACAAAAAAQACAAAAwAHAAAxIREhExEhEQQA/AAFA/YIAPgFB/b4\
CgAAAQEAAAADAAgAAAMAACEhESEBAAIA/gAIAAAAAAAAAQASAAEAAAAAAAEAEAAAdGV4dC1taXhl\
ZC1jb2xvcgAAAAAAAwAAAA4AAAAgAAMABAAAAAEABQABAAEABgACAAEAAgAAAAMAAQADAAIAAAAD\
AAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 7 10;
}
text {
font: "Cantarell 11";
glyphs: "Hello";
}
@@ -0,0 +1,2 @@
<data>:21:32-36: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE
<data>:50:23-24: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE
@@ -0,0 +1,52 @@
text {
font: "text-mixed-color 7.5" url("data:font/ttf;base64,\
AAEAAAAKAIAAAwAgQ09MUgATAEEAAAJ8AAAALENQQUwB/wATAAACqAAAABpjbWFwAHcAPQAAATwA\
AAA0Z2x5Zu8g4kAAAAGEAAAA0mhlYWQmofyJAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AQAAAAEoAAAAFGxvY2EAyAD5AAABcAAAABRtYXhwAAwACQAAAQgAAAAgbmFtZX7VdrQAAAJYAAAA\
IgABAAAAARmajs74k18PPPUAAggAAAAAAOHCPQAAAAAA4cpY+QAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAJAAgAAgAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAADAAAADAAEACgAAAAGAAQAAQAC\
ACAASP//AAAAIABB////4P/AAAEAAAAAAAAAAAAAAAwAGAAkADAAPABIAFwAaQABAAAAAAQACAAA\
AwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA\
/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAA\
AAQACAAAAwAAMSERIQQA/AAIAAACAAAAAAQACAAAAwAHAAAxIREhExEhEQQA/AAFA/YIAPgFB/b4\
CgAAAQEAAAADAAgAAAMAACEhESEBAAIA/gAIAAAAAAAAAQASAAEAAAAAAAEAEAAAdGV4dC1taXhl\
ZC1jb2xvcgAAAAAAAwAAAA4AAAAgAAMABAAAAAEABQABAAEABgACAAEAAgAAAAMAAQADAAIAAAAD\
AAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 7 10;
}
text {
font: "text-mixed-color 7.5" url("data:font/ttf;base64,\
AAEAAAAKAIAAAwAgQ09MUgATAEEAAAJ8AAAALENQQUwB/wATAAACqAAAABpjbWFwAHcAPQAAATwA\
AAA0Z2x5Zu8g4kAAAAGEAAAA0mhlYWQmofyJAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AQAAAAEoAAAAFGxvY2EAyAD5AAABcAAAABRtYXhwAAwACQAAAQgAAAAgbmFtZX7VdrQAAAJYAAAA\
IgABAAAAARmajs74k18PPPUAAggAAAAAAOHCPQAAAAAA4cpY+QAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAJAAgAAgAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAADAAAADAAEACgAAAAGAAQAAQAC\
ACAASP//AAAAIABB////4P/AAAEAAAAAAAAAAAAAAAwAGAAkADAAPABIAFwAaQABAAAAAAQACAAA\
AwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA\
/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAA\
AAQACAAAAwAAMSERIQQA/AAIAAACAAAAAAQACAAAAwAHAAAxIREhExEhEQQA/AAFA/YIAPgFB/b4\
CgAAAQEAAAADAAgAAAMAACEhESEBAAIA/gAIAAAAAAAAAQASAAEAAAAAAAEAEAAAdGV4dC1taXhl\
ZC1jb2xvcgAAAAAAAwAAAA4AAAAgAAMABAAAAAEABQABAAEABgACAAEAAgAAAAMAAQADAAIAAAAD\
AAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 7 10;
}
text {
font: "text-mixed-color 7.5";
glyphs: 7 10;
}
text {
font: "Cantarell 11";
glyphs: "Hello";
}
text {
font: "Demon Cat 11";
glyphs: "Hello";
}
@@ -0,0 +1,33 @@
text {
font: "text-mixed-color 7.5" url("data:font/ttf;base64,AAEAAAAKAIAAAwAgQ09MUgATAEEAAAJ8AAAALENQQUwB/wATAAACqAAAABpjbWFwAHcAPQAAATwA\
AAA0Z2x5Zu8g4kAAAAGEAAAA0mhlYWQmofyJAAAArAAAADZoaGVhDAEEAgAAAOQAAAAkaG10eAQA\
AQAAAAEoAAAAFGxvY2EAyAD5AAABcAAAABRtYXhwAAwACQAAAQgAAAAgbmFtZX7VdrQAAAJYAAAA\
IgABAAAAARmajs74k18PPPUAAggAAAAAAOHCPQAAAAAA4cpY+QAAAAAEAAgAAAAAAQACAAAAAAAA\
AAEAAAgAAAAAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAABAAEAAAAJAAgAAgAAAAAAAQAAAAAA\
AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAADAAAADAAEACgAAAAGAAQAAQAC\
ACAASP//AAAAIABB////4P/AAAEAAAAAAAAAAAAAAAwAGAAkADAAPABIAFwAaQABAAAAAAQACAAA\
AwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA\
/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAAAAQACAAAAwAAMSERIQQA/AAIAAABAAAA\
AAQACAAAAwAAMSERIQQA/AAIAAACAAAAAAQACAAAAwAHAAAxIREhExEhEQQA/AAFA/YIAPgFB/b4\
CgAAAQEAAAADAAgAAAMAACEhESEBAAIA/gAIAAAAAAAAAQASAAEAAAAAAAEAEAAAdGV4dC1taXhl\
ZC1jb2xvcgAAAAAAAwAAAA4AAAAgAAMABAAAAAEABQABAAEABgACAAEAAgAAAAMAAQADAAIAAAAD\
AAEAAwAAAA4AAAAA//8A/wD//wAA/wAA\
");
glyphs: 7 10;
}
text {
font: "Cantarell 11";
glyphs: 7 10;
}
text {
font: "text-mixed-color 7.5";
glyphs: 7 10;
}
text {
font: "Cantarell 11";
glyphs: "Hello";
}
text {
font: "Cantarell 11";
glyphs: "Hello";
}
+1 -1
View File
@@ -10,7 +10,7 @@ echo "1..1"
name=gtk-query-settings
result=$TEST_RESULT_DIR/$name.out
$GTK_QUERY_SETTINGS 2>/dev/null >$result
EXPECTED=50
EXPECTED=51
SEEN=$(wc -l $result | cut -f1 -d' ')
if [ $SEEN -eq $EXPECTED ]; then
+151
View File
@@ -0,0 +1,151 @@
/* Copyright 2024 Red Hat, Inc.
*
* GTK 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 of the
* License, or (at your option) any later version.
*
* GTK 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 GTK; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*
* Author: Benjamin Otte
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <glib/gi18n-lib.h>
#include <glib/gprintf.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include "gtk-rendernode-tool.h"
static void
benchmark_node (GskRenderNode *node,
const char *renderer_name,
guint runs,
gboolean download)
{
GError *error = NULL;
GskRenderer *renderer;
guint i;
renderer = create_renderer (renderer_name, &error);
if (renderer == NULL)
{
g_printerr ("Could not benchmark renderer \"%s\": %s\n", renderer_name, error->message);
g_clear_error (&error);
return;
}
for (i = 0; i < runs; i++)
{
GdkTexture *texture;
gint64 start_time, end_time, duration;
start_time = g_get_monotonic_time ();
texture = gsk_renderer_render_texture (renderer, node, NULL);
if (download)
{
GdkTextureDownloader *downloader;
GBytes *bytes;
gsize stride;
downloader = gdk_texture_downloader_new (texture);
bytes = gdk_texture_downloader_download_bytes (downloader, &stride);
g_bytes_unref (bytes);
gdk_texture_downloader_free (downloader);
}
end_time = g_get_monotonic_time ();
duration = end_time - start_time;
g_print ("%s\t%lld.%03ds\n",
renderer_name,
(long long) duration / G_USEC_PER_SEC,
(int) ((duration * 1000 / G_USEC_PER_SEC) % 1000));
g_object_unref (texture);
}
gsk_renderer_unrealize (renderer);
g_object_unref (renderer);
}
void
do_benchmark (int *argc,
const char ***argv)
{
GOptionContext *context;
char **filenames = NULL;
char **renderers = NULL;
gboolean nodownload = FALSE;
int runs = 3;
const GOptionEntry entries[] = {
{ "renderer", 0, 0, G_OPTION_ARG_STRING_ARRAY, &renderers, N_("Add renderer to benchmark"), N_("RENDERER") },
{ "runs", 0, 0, G_OPTION_ARG_INT, &runs, N_("Number of runs with each renderer"), N_("RUNS") },
{ "no-download", 0, 0, G_OPTION_ARG_NONE, &nodownload, N_("Dont download result/wait for GPU to finish"), NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, N_("FILE…") },
{ NULL, }
};
GskRenderNode *node;
GError *error = NULL;
gsize i;
if (gdk_display_get_default () == NULL)
{
g_printerr (_("Could not initialize windowing system\n"));
exit (1);
}
g_set_prgname ("gtk4-rendernode-tool benchmark");
context = g_option_context_new (NULL);
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_set_summary (context, _("Benchmark rendering of a .node file."));
if (!g_option_context_parse (context, argc, (char ***)argv, &error))
{
g_printerr ("%s\n", error->message);
g_error_free (error);
exit (1);
}
g_option_context_free (context);
if (filenames == NULL)
{
g_printerr (_("No .node file specified\n"));
exit (1);
}
if (g_strv_length (filenames) > 1)
{
g_printerr (_("Can only benchmark a single .node file\n"));
exit (1);
}
if (renderers == NULL || renderers[0] == NULL)
renderers = g_strdupv ((char **) (const char *[]) { "gl", "ngl", "vulkan", "cairo", NULL });
node = load_node_file (filenames[0]);
for (i = 0; renderers[i] != NULL; i++)
{
benchmark_node (node, renderers[i], runs, !nodownload);
}
gsk_render_node_unref (node);
g_strfreev (filenames);
g_strfreev (renderers);
}
+6 -7
View File
@@ -143,14 +143,13 @@ render_file (const char *filename,
{
GdkTexture *texture;
GskRenderer *renderer;
GdkSurface *window;
if (renderer_name)
g_object_set_data_full (G_OBJECT (gdk_display_get_default ()), "gsk-renderer",
g_strdup (renderer_name), g_free);
window = gdk_surface_new_toplevel (gdk_display_get_default ());
renderer = gsk_renderer_new_for_surface (window);
renderer = create_renderer (renderer_name, &error);
if (renderer == NULL)
{
g_printerr (_("Failed to create renderer: %s\n"), error->message);
exit (1);
}
texture = gsk_renderer_render_texture (renderer, node, NULL);
+62
View File
@@ -29,6 +29,9 @@
#include <gtk/gtk.h>
#include "gtk-rendernode-tool.h"
#ifdef GDK_WINDOWING_BROADWAY
#include <gsk/broadway/gskbroadwayrenderer.h>
#endif
static void
deserialize_error_func (const GskParseLocation *start,
@@ -73,3 +76,62 @@ load_node_file (const char *filename)
return gsk_render_node_deserialize (bytes, deserialize_error_func, NULL);
}
/* keep in sync with gsk/gskrenderer.c */
static GskRenderer *
get_renderer_for_name (const char *renderer_name)
{
if (renderer_name == NULL)
return NULL;
#ifdef GDK_WINDOWING_BROADWAY
else if (g_ascii_strcasecmp (renderer_name, "broadway") == 0)
return gsk_broadway_renderer_new ();
#endif
else if (g_ascii_strcasecmp (renderer_name, "cairo") == 0)
return gsk_cairo_renderer_new ();
else if (g_ascii_strcasecmp (renderer_name, "opengl") == 0 ||
g_ascii_strcasecmp (renderer_name, "gl") == 0)
return gsk_gl_renderer_new ();
else if (g_ascii_strcasecmp (renderer_name, "ngl") == 0)
return gsk_ngl_renderer_new ();
#ifdef GDK_RENDERING_VULKAN
else if (g_ascii_strcasecmp (renderer_name, "vulkan") == 0)
return gsk_vulkan_renderer_new ();
#endif
else
return NULL;
}
GskRenderer *
create_renderer (const char *name, GError **error)
{
GskRenderer *renderer;
if (name == NULL)
{
/* awwwwwkward - there should be code to get the
* default renderer without a surface */
static GdkSurface *window = NULL;
if (window == NULL)
window = gdk_surface_new_toplevel (gdk_display_get_default ());
return gsk_renderer_new_for_surface (window);
}
renderer = get_renderer_for_name (name);
if (renderer == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"No renderer named \"%s\"", name);
return NULL;
}
if (!gsk_renderer_realize_for_display (renderer, gdk_display_get_default (), error))
{
g_object_unref (renderer);
return NULL;
}
return renderer;
}
+3
View File
@@ -38,6 +38,7 @@ usage (void)
"Perform various tasks on GTK render nodes.\n"
"\n"
"Commands:\n"
" benchmark Benchmark rendering of a node\n"
" info Provide information about the node\n"
" show Show the node\n"
" render Take a screenshot of the node\n"
@@ -113,6 +114,8 @@ main (int argc, const char *argv[])
do_render (&argc, &argv);
else if (strcmp (argv[0], "info") == 0)
do_info (&argc, &argv);
else if (strcmp (argv[0], "benchmark") == 0)
do_benchmark (&argc, &argv);
else
usage ();
+5 -3
View File
@@ -1,8 +1,10 @@
#pragma once
void do_show (int *argc, const char ***argv);
void do_render (int *argc, const char ***argv);
void do_info (int *argc, const char ***argv);
void do_benchmark (int *argc, const char ***argv);
void do_info (int *argc, const char ***argv);
void do_show (int *argc, const char ***argv);
void do_render (int *argc, const char ***argv);
GskRenderNode *load_node_file (const char *filename);
GskRenderer *create_renderer (const char *name, GError **error);
+1
View File
@@ -41,6 +41,7 @@ gtk_tools = [
'gtk-builder-tool-preview.c',
'fake-scope.c'], [libgtk_dep] ],
['gtk4-rendernode-tool', ['gtk-rendernode-tool.c',
'gtk-rendernode-tool-benchmark.c',
'gtk-rendernode-tool-info.c',
'gtk-rendernode-tool-render.c',
'gtk-rendernode-tool-show.c',