Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f2bce941a | |||
| 0a7fb26909 |
+5
-15
@@ -222,7 +222,7 @@ macos:
|
||||
-Dcpp_std=c++11
|
||||
-Dpixman:tests=disabled
|
||||
-Dlibjpeg-turbo:simd=disabled
|
||||
-Dbuild-demos=false
|
||||
-Ddemos=false
|
||||
-Dbuild-tests=false
|
||||
-Dbuild-examples=false
|
||||
-Dbuild-testsuite=false
|
||||
@@ -385,27 +385,17 @@ asan-build:
|
||||
tags: [ asan ]
|
||||
stage: analysis
|
||||
needs: []
|
||||
when: manual
|
||||
variables:
|
||||
script:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- CC=clang meson setup
|
||||
--buildtype=debugoptimized
|
||||
-Db_sanitize=address
|
||||
-Db_lundef=false
|
||||
-Dbuild-demos=false
|
||||
-Dbuild-tests=false
|
||||
-Dbuild-examples=false
|
||||
-Dintrospection=disabled
|
||||
-Df16c=disabled
|
||||
_build
|
||||
- CC=clang meson setup --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled -Df16c=disabled _build
|
||||
- ninja -C _build
|
||||
- .gitlab-ci/run-tests.sh _build wayland
|
||||
- .gitlab-ci/run-tests.sh _build wayland_gles
|
||||
- .gitlab-ci/run-tests.sh _build x11
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs"
|
||||
- _build/meson-logs
|
||||
allow_failure: true
|
||||
|
||||
reference:
|
||||
image: $FEDORA_IMAGE
|
||||
|
||||
@@ -23,8 +23,8 @@ flatpak build ${builddir} meson \
|
||||
-Dbuild-testsuite=false \
|
||||
-Dbuild-examples=false \
|
||||
-Dintrospection=disabled \
|
||||
-Dbuild-demos=true \
|
||||
-Ddemo-profile=devel \
|
||||
-Ddemos=true \
|
||||
-Dprofile=devel \
|
||||
_flatpak_build
|
||||
|
||||
flatpak build ${builddir} ninja -C _flatpak_build install
|
||||
|
||||
@@ -9,7 +9,7 @@ backend=$2
|
||||
multiplier=${MESON_TEST_TIMEOUT_MULTIPLIER:-1}
|
||||
|
||||
# Ignore memory leaks lower in dependencies
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:detect_leaks=0:allocator_may_return_null=1
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:verbosity=1:log_threads=1
|
||||
export G_SLICE=always-malloc
|
||||
|
||||
case "${backend}" in
|
||||
|
||||
@@ -1,93 +1,4 @@
|
||||
Overview of Changes in 4.11.5, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
Overview of Changes in 4.11.4, 03-07-2023
|
||||
=========================================
|
||||
|
||||
* GtkFileChooser:
|
||||
- Default to sorting folders first
|
||||
- Fix a crash when visiting recent files
|
||||
|
||||
* GtkTextView:
|
||||
- Fix corner cases in word navigation
|
||||
|
||||
* GtkMenuButton:
|
||||
- Normalize label layout
|
||||
|
||||
* GtkDropDown:
|
||||
- Add support for sections
|
||||
|
||||
* GtkVideo:
|
||||
- Make the overlay icon clickable
|
||||
|
||||
* GtkWindow:
|
||||
- Clear the resize cursors to avoid artifacts
|
||||
|
||||
* GtkFileDialog:
|
||||
- Always set initial-folder
|
||||
|
||||
* GtkDropDown:
|
||||
- Update on expression changes
|
||||
|
||||
* GtkMapListModel:
|
||||
- Implement GtkSectionModel
|
||||
|
||||
* Accessibility:
|
||||
- Improvements all over the place: GtkButton, GtkPasswordEntry,
|
||||
GtkFontChooserDialog, GtkColorChooserDialog, GtkShortcutsWindow,
|
||||
GtkMenuButton, GtkAboutDialog, GtkFileChooserDialog, GtkStackSidebar,
|
||||
GtkStackSwitcher, GtkMediaControls, GtkColorDialogButton, GtkDropDown,
|
||||
GtkInfoBar, GtkNotebook, GtkPrintUnixDialog, GtkModelButton
|
||||
- Make name computation follow the ARIA spec more closely
|
||||
- Adapt name computation for the common 'nested button' scenario
|
||||
- Change many containers to use `generic` instead of `group`
|
||||
- Use `generic` as the default role
|
||||
- Use `application` instead of `window` for windows
|
||||
- Add properties for accessible names of not directly exposed
|
||||
widgets in GtkListView, GtkGridView and GtkColumnView
|
||||
|
||||
* DND:
|
||||
- Fix criticals when drops are rejected
|
||||
|
||||
* X11:
|
||||
- Fix regressions in GLX setup
|
||||
|
||||
* Windows:
|
||||
- Center newly created transient windows
|
||||
|
||||
* Vulkan:
|
||||
- Add antialising for gradients
|
||||
- Do less work on clipped away nodes
|
||||
- Redo image uploading
|
||||
- Support different image depths and formats
|
||||
- Add a pipeline cache
|
||||
|
||||
* Demos:
|
||||
- gtk4-demo: Improve window sizing
|
||||
- gtk4-demo: Improve focus behavior
|
||||
- gtk4-demo: Add many missing a11y properties
|
||||
|
||||
* Tools:
|
||||
- gtk4-builder-tool: Make render an alias screenshot
|
||||
|
||||
* Inspector:
|
||||
- Show more information in the a11y tab
|
||||
- Add an accessibility overlay with warnings and recommendations
|
||||
- Limit the width of the a11y tab
|
||||
|
||||
* Build:
|
||||
- Require GLib 2.76
|
||||
- Make asan builds work again
|
||||
- Fix the build if ld is not ld.bdf
|
||||
|
||||
* Translation updates:
|
||||
Brazilian Portuguese
|
||||
Catalan
|
||||
Czech
|
||||
Georgian
|
||||
|
||||
|
||||
Overview of Changes in 4.11.3, 05-06-2023
|
||||
Overview of Changes in 4.11.3, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
* GtkGridView:
|
||||
@@ -109,41 +20,22 @@ Overview of Changes in 4.11.3, 05-06-2023
|
||||
* GtkPopoverMenu:
|
||||
- Avoid unnecessary left padding
|
||||
|
||||
* GtkSearchEntry:
|
||||
- Improve size allocation for the clear icon
|
||||
|
||||
* GtkBoxLayout:
|
||||
- Fix a regression from recent baseline work
|
||||
|
||||
* CSS:
|
||||
* Css:
|
||||
- Add new binding-friendly css provider apis
|
||||
|
||||
* GDK:
|
||||
- Support grayscale texture and alpha texture formats
|
||||
for loading and saving to png and tiff, and in GL
|
||||
|
||||
* Theme:
|
||||
- Show focus in the shortcuts window
|
||||
|
||||
* GDK:
|
||||
- Support grayscale and alpha texture formats for loading
|
||||
and saving to png and tiff, and in GL
|
||||
- Fix some regressions in GL context initialization
|
||||
|
||||
* GSK:
|
||||
- Support grayscale and alpha texture formats in the GL renderer
|
||||
- Support straight alpha textures in the GL renderer
|
||||
- Many improvements to the experimental Vulkan renderer
|
||||
* Tests:
|
||||
- Improve test coverage
|
||||
|
||||
* Wayland:
|
||||
- Make exporting surface handles more flexible
|
||||
|
||||
* X11:
|
||||
- Trap XRandr errors
|
||||
- Stop using passive grabs during DND
|
||||
|
||||
* Windows:
|
||||
- Many cleanups and simplifications
|
||||
|
||||
* Tests:
|
||||
- Improve test coverage
|
||||
|
||||
* Build:
|
||||
- Some build options have been renamed:
|
||||
demos -> build-demos
|
||||
@@ -163,7 +55,6 @@ Overview of Changes in 4.11.3, 05-06-2023
|
||||
* Translation updates:
|
||||
Basque
|
||||
Catalan
|
||||
Georgian
|
||||
Russian
|
||||
Turkish
|
||||
|
||||
|
||||
@@ -162,10 +162,6 @@ create_page4 (GtkWidget *assistant)
|
||||
gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), progress_bar, GTK_ASSISTANT_PAGE_PROGRESS);
|
||||
gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), progress_bar, "Applying changes");
|
||||
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (progress_bar),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Applying changes",
|
||||
-1);
|
||||
|
||||
/* This prevents the assistant window from being
|
||||
* closed while we're "busy" applying changes.
|
||||
*/
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="resizable">1</property>
|
||||
<property name="title">Clipboard</property>
|
||||
<accessibility>
|
||||
<relation name="described-by">label</relation>
|
||||
</accessibility>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
@@ -16,7 +13,7 @@
|
||||
<property name="margin-bottom">12</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">“Copy” will copy the selected data the clipboard, “Paste” will show the current clipboard contents. You can also drag the data to the bottom.</property>
|
||||
<property name="wrap">1</property>
|
||||
<property name="max-width-chars">40</property>
|
||||
@@ -27,9 +24,6 @@
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="source_chooser">
|
||||
<accessibility>
|
||||
<property name="label">Source Type</property>
|
||||
</accessibility>
|
||||
<property name="valign">center</property>
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
@@ -60,9 +54,6 @@
|
||||
<property name="name">Text</property>
|
||||
<property name="child">
|
||||
<object class="GtkEntry" id="source_text">
|
||||
<accessibility>
|
||||
<property name="label">Text Drag Source</property>
|
||||
</accessibility>
|
||||
<property name="valign">center</property>
|
||||
<signal name="notify::text" handler="text_changed_cb" object="copy_button"/>
|
||||
<property name="text">Copy this!</property>
|
||||
@@ -75,9 +66,6 @@
|
||||
<property name="name">Color</property>
|
||||
<property name="child">
|
||||
<object class="GtkColorDialogButton" id="source_color">
|
||||
<accessibility>
|
||||
<property name="label">Color Drag Source</property>
|
||||
</accessibility>
|
||||
<property name="dialog">
|
||||
<object class="GtkColorDialog">
|
||||
</object>
|
||||
@@ -99,17 +87,14 @@
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="image_rose">
|
||||
<accessibility>
|
||||
<property name="label">Photo Drag Source</property>
|
||||
</accessibility>
|
||||
<property name="active">1</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<signal name="prepare" handler="drag_prepare"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<accessibility>
|
||||
<property name="label">Portland Rose Photo</property>
|
||||
</accessibility>
|
||||
<style>
|
||||
<class name="large-icons"/>
|
||||
</style>
|
||||
@@ -120,9 +105,6 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="image_floppy">
|
||||
<accessibility>
|
||||
<property name="label">Icon Drag Source</property>
|
||||
</accessibility>
|
||||
<property name="group">image_rose</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
@@ -131,9 +113,6 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<accessibility>
|
||||
<property name="label">Floppy Buddy Icon</property>
|
||||
</accessibility>
|
||||
<style>
|
||||
<class name="large-icons"/>
|
||||
</style>
|
||||
@@ -144,9 +123,6 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="image_logo">
|
||||
<accessibility>
|
||||
<property name="label">SVG Drag Source</property>
|
||||
</accessibility>
|
||||
<property name="group">image_floppy</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
@@ -155,9 +131,6 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<accessibility>
|
||||
<property name="label">gtk-demo logo</property>
|
||||
</accessibility>
|
||||
<style>
|
||||
<class name="large-icons"/>
|
||||
</style>
|
||||
@@ -175,9 +148,6 @@
|
||||
<property name="name">File</property>
|
||||
<property name="child">
|
||||
<object class="GtkButton" id="source_file">
|
||||
<accessibility>
|
||||
<property name="label">File Drag Source</property>
|
||||
</accessibility>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="propagation-phase">capture</property>
|
||||
@@ -202,9 +172,6 @@
|
||||
<property name="name">Folder</property>
|
||||
<property name="child">
|
||||
<object class="GtkButton" id="source_folder">
|
||||
<accessibility>
|
||||
<property name="label">Folder Drag Source</property>
|
||||
</accessibility>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="propagation-phase">capture</property>
|
||||
@@ -258,7 +225,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="paste_label">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="visible-child-name" type="GtkStack">
|
||||
@@ -285,9 +252,6 @@
|
||||
<property name="name">Text</property>
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<accessibility>
|
||||
<relation name="labelled-by">paste_label</relation>
|
||||
</accessibility>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="xalign">0</property>
|
||||
@@ -301,9 +265,6 @@
|
||||
<property name="name">Image</property>
|
||||
<property name="child">
|
||||
<object class="GtkImage">
|
||||
<accessibility>
|
||||
<relation name="labelled-by">paste_label</relation>
|
||||
</accessibility>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
@@ -322,9 +283,6 @@
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkColorSwatch">
|
||||
<accessibility>
|
||||
<relation name="labelled-by">paste_label</relation>
|
||||
</accessibility>
|
||||
<property name="accessible-role">img</property>
|
||||
<property name="can-focus">0</property>
|
||||
<property name="selectable">0</property>
|
||||
@@ -340,9 +298,6 @@
|
||||
<property name="name">File</property>
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<accessibility>
|
||||
<relation name="labelled-by">paste_label</relation>
|
||||
</accessibility>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="xalign">0</property>
|
||||
|
||||
@@ -387,8 +387,6 @@ demo3_widget_class_init (Demo3WidgetClass *class)
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu);
|
||||
gtk_widget_class_bind_template_callback (widget_class, pressed_cb);
|
||||
|
||||
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_IMG);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
|
||||
@@ -19,14 +19,8 @@
|
||||
</item>
|
||||
</menu>
|
||||
<template class="Demo3Widget">
|
||||
<accessibility>
|
||||
<property name="label">Demo image</property>
|
||||
</accessibility>
|
||||
<child>
|
||||
<object class="GtkPopoverMenu" id="menu">
|
||||
<accessibility>
|
||||
<property name="label">Context menu</property>
|
||||
</accessibility>
|
||||
<property name="has-arrow">0</property>
|
||||
<property name="menu-model">model</property>
|
||||
</object>
|
||||
|
||||
+7
-19
@@ -162,39 +162,27 @@ click_done (GtkGesture *gesture)
|
||||
gtk_widget_insert_after (item, canvas, last_child);
|
||||
}
|
||||
|
||||
/* GtkSettings treats `GTK_THEME=foo:dark` as theme name `foo`, variant `dark`,
|
||||
* and our embedded CSS files let `foo-dark` work as an alias for `foo:dark`. */
|
||||
static gboolean
|
||||
has_dark_suffix (const char *theme)
|
||||
{
|
||||
return g_str_has_suffix (theme, ":dark") ||
|
||||
g_str_has_suffix (theme, "-dark");
|
||||
}
|
||||
|
||||
/* So we can make a good guess whether the current theme is dark by checking for
|
||||
* either: it is suffixed `[:-]dark`, or Settings:…prefer-dark-theme is TRUE. */
|
||||
static gboolean
|
||||
theme_is_dark (void)
|
||||
{
|
||||
const char *env_theme;
|
||||
GtkSettings *settings;
|
||||
char *theme;
|
||||
gboolean prefer_dark;
|
||||
gboolean dark;
|
||||
|
||||
/* Like GtkSettings, 1st see if theme is overridden by environment variable */
|
||||
env_theme = g_getenv ("GTK_THEME");
|
||||
if (env_theme != NULL)
|
||||
return has_dark_suffix (env_theme);
|
||||
|
||||
/* If not, test Settings:…theme-name in the same way OR :…prefer-dark-theme */
|
||||
settings = gtk_settings_get_default ();
|
||||
g_object_get (settings,
|
||||
"gtk-theme-name", &theme,
|
||||
"gtk-application-prefer-dark-theme", &prefer_dark,
|
||||
NULL);
|
||||
dark = prefer_dark || has_dark_suffix (theme);
|
||||
|
||||
if ((strcmp (theme, "Adwaita") == 0 && prefer_dark) || strcmp (theme, "HighContrastInverse") == 0)
|
||||
dark = TRUE;
|
||||
else
|
||||
dark = FALSE;
|
||||
|
||||
g_free (theme);
|
||||
|
||||
return dark;
|
||||
}
|
||||
|
||||
|
||||
@@ -334,17 +334,11 @@ do_drawingarea (GtkWidget *do_widget)
|
||||
gtk_widget_set_vexpand (frame, TRUE);
|
||||
gtk_box_append (GTK_BOX (vbox), frame);
|
||||
|
||||
da = g_object_new (GTK_TYPE_DRAWING_AREA,
|
||||
"accessible-role", GTK_ACCESSIBLE_ROLE_IMG,
|
||||
NULL);
|
||||
gtk_frame_set_child (GTK_FRAME (frame), da);
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (da),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
|
||||
-1);
|
||||
|
||||
da = gtk_drawing_area_new ();
|
||||
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 100);
|
||||
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 100);
|
||||
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), groups_draw, NULL, NULL);
|
||||
gtk_frame_set_child (GTK_FRAME (frame), da);
|
||||
|
||||
/*
|
||||
* Create the scribble area
|
||||
@@ -358,17 +352,11 @@ do_drawingarea (GtkWidget *do_widget)
|
||||
gtk_widget_set_vexpand (frame, TRUE);
|
||||
gtk_box_append (GTK_BOX (vbox), frame);
|
||||
|
||||
da = g_object_new (GTK_TYPE_DRAWING_AREA,
|
||||
"accessible-role", GTK_ACCESSIBLE_ROLE_IMG,
|
||||
NULL);
|
||||
gtk_frame_set_child (GTK_FRAME (frame), da);
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (da),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
|
||||
-1);
|
||||
|
||||
da = gtk_drawing_area_new ();
|
||||
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 100);
|
||||
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 100);
|
||||
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), scribble_draw, NULL, NULL);
|
||||
gtk_frame_set_child (GTK_FRAME (frame), da);
|
||||
|
||||
g_signal_connect (da, "resize",
|
||||
G_CALLBACK (scribble_resize), NULL);
|
||||
@@ -384,7 +372,7 @@ do_drawingarea (GtkWidget *do_widget)
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
gtk_widget_set_visible (window, TRUE);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
|
||||
@@ -95,13 +95,6 @@ do_entry_completion (GtkWidget *do_widget)
|
||||
entry = gtk_entry_new ();
|
||||
gtk_box_append (GTK_BOX (vbox), entry);
|
||||
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (entry),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
|
||||
-1);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (entry),
|
||||
GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE, GTK_ACCESSIBLE_AUTOCOMPLETE_LIST,
|
||||
-1);
|
||||
|
||||
/* Create the completion object */
|
||||
completion = gtk_entry_completion_new ();
|
||||
|
||||
|
||||
@@ -43,10 +43,6 @@ do_entry_undo (GtkWidget *do_widget)
|
||||
entry = gtk_entry_new ();
|
||||
gtk_editable_set_enable_undo (GTK_EDITABLE (entry), TRUE);
|
||||
gtk_box_append (GTK_BOX (vbox), entry);
|
||||
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (entry),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
|
||||
-1);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -22,15 +22,11 @@ validate_more_details (GtkEntry *entry,
|
||||
{
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (entry), "Must have details first");
|
||||
gtk_widget_add_css_class (GTK_WIDGET (entry), "error");
|
||||
gtk_accessible_update_state (GTK_ACCESSIBLE (entry),
|
||||
GTK_ACCESSIBLE_STATE_INVALID, GTK_ACCESSIBLE_INVALID_TRUE,
|
||||
-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (entry), "");
|
||||
gtk_widget_remove_css_class (GTK_WIDGET (entry), "error");
|
||||
gtk_accessible_reset_state (GTK_ACCESSIBLE (entry), GTK_ACCESSIBLE_STATE_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,18 +44,10 @@ mode_switch_state_set (GtkSwitch *sw,
|
||||
{
|
||||
gtk_widget_set_visible (label, FALSE);
|
||||
gtk_switch_set_state (sw, state);
|
||||
gtk_accessible_reset_relation (GTK_ACCESSIBLE (sw), GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE);
|
||||
gtk_accessible_reset_state (GTK_ACCESSIBLE (sw), GTK_ACCESSIBLE_STATE_INVALID);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_visible (label, TRUE);
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (sw),
|
||||
GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE, label,
|
||||
-1);
|
||||
gtk_accessible_update_state (GTK_ACCESSIBLE (sw),
|
||||
GTK_ACCESSIBLE_STATE_INVALID, GTK_ACCESSIBLE_INVALID_TRUE,
|
||||
-1);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -85,9 +73,6 @@ level_scale_value_changed (GtkRange *range,
|
||||
{
|
||||
gtk_switch_set_state (GTK_SWITCH (sw), FALSE);
|
||||
}
|
||||
|
||||
gtk_accessible_reset_relation (GTK_ACCESSIBLE (sw), GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE);
|
||||
gtk_accessible_reset_state (GTK_ACCESSIBLE (sw), GTK_ACCESSIBLE_STATE_INVALID);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
|
||||
@@ -59,9 +59,6 @@
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkFontDialogButton" id="font">
|
||||
<accessibility>
|
||||
<property name="label">Font</property>
|
||||
</accessibility>
|
||||
<property name="dialog">
|
||||
<object class="GtkFontDialog">
|
||||
</object>
|
||||
@@ -76,7 +73,7 @@
|
||||
<property name="column-spacing">10</property>
|
||||
<property name="row-spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="size_label">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Size</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
@@ -92,9 +89,6 @@
|
||||
<property name="width-request">100</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="adjustment">size_adjustment</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">size_label</relation>
|
||||
</accessibility>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
@@ -107,9 +101,6 @@
|
||||
<property name="max-width-chars">4</property>
|
||||
<property name="hexpand">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">size_label</relation>
|
||||
</accessibility>
|
||||
<signal name="activate" handler="basic_entry_activated"
|
||||
object="size_adjustment" swapped="false"/>
|
||||
<layout>
|
||||
@@ -119,7 +110,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="letterspacing_label">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Letterspacing</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
@@ -135,9 +126,6 @@
|
||||
<property name="width-request">100</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="adjustment">letterspacing_adjustment</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">letterspacing_label</relation>
|
||||
</accessibility>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
@@ -150,9 +138,6 @@
|
||||
<property name="max-width-chars">4</property>
|
||||
<property name="hexpand">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">letterspacing_label</relation>
|
||||
</accessibility>
|
||||
<signal name="activate" handler="basic_entry_activated"
|
||||
object="letterspacing_adjustment" swapped="false"/>
|
||||
<layout>
|
||||
@@ -162,7 +147,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="line_height_label">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Line Height</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
@@ -178,9 +163,6 @@
|
||||
<property name="width-request">100</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="adjustment">line_height_adjustment</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">line_height_label</relation>
|
||||
</accessibility>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
@@ -193,9 +175,6 @@
|
||||
<property name="max-width-chars">4</property>
|
||||
<property name="hexpand">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">line_height_label</relation>
|
||||
</accessibility>
|
||||
<signal name="activate" handler="basic_entry_activated"
|
||||
object="line_height_adjustment" swapped="false"/>
|
||||
<layout>
|
||||
@@ -205,7 +184,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="foreground_label">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Foreground</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
@@ -223,9 +202,6 @@
|
||||
</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="rgba">black</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">foreground_label</relation>
|
||||
</accessibility>
|
||||
<signal name="notify::rgba" handler="color_set_cb"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
@@ -234,7 +210,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="background_label">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Background</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
@@ -252,9 +228,6 @@
|
||||
</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="rgba">white</property>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">background_label</relation>
|
||||
</accessibility>
|
||||
<signal name="notify::rgba" handler="color_set_cb"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
@@ -267,9 +240,6 @@
|
||||
<property name="icon-name">object-flip-vertical-symbolic</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<accessibility>
|
||||
<property name="label">Swap colors</property>
|
||||
</accessibility>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
@@ -371,9 +341,6 @@
|
||||
<property name="yalign">0</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="selectable">1</property>
|
||||
<accessibility>
|
||||
<property name="label">Font example</property>
|
||||
</accessibility>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
@@ -383,9 +350,6 @@
|
||||
<property name="name">entry</property>
|
||||
<property name="child">
|
||||
<object class="GtkTextView" id="entry">
|
||||
<accessibility>
|
||||
<property name="label">Example text</property>
|
||||
</accessibility>
|
||||
<property name="buffer">
|
||||
<object class="GtkTextBuffer">
|
||||
<property name="text">Grumpy wizards make toxic brew for the evil Queen and Jack. A quick movement of the enemy will jeopardize six gunboats. The job of waxing linoleum frequently peeves chintzy kids. My girl wove six dozen plaid jackets before she quit. Twelve ziggurats quickly jumped a finch box.
|
||||
@@ -482,9 +446,6 @@
|
||||
<property name="icon-name">document-edit-symbolic</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">end</property>
|
||||
<accessibility>
|
||||
<property name="label">Edit text</property>
|
||||
</accessibility>
|
||||
<signal name="clicked" handler="font_features_toggle_edit"/>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
@@ -306,7 +306,7 @@ retry:
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf2);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (image), GDK_PAINTABLE (texture));
|
||||
g_object_unref (pixbuf2);
|
||||
g_object_unref (texture);
|
||||
g_object_unref (pixbuf2);
|
||||
}
|
||||
|
||||
static gboolean fading = FALSE;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<property name="row-spacing">10</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="text_label">
|
||||
<object class="GtkLabel">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="label">Text</property>
|
||||
<property name="xalign">1</property>
|
||||
@@ -57,13 +57,10 @@
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
</layout>
|
||||
<accessibility>
|
||||
<relation name="labelled-by">text_label</relation>
|
||||
</accessibility>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="font_label">
|
||||
<object class="GtkLabel">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="label">Font</property>
|
||||
<property name="xalign">1</property>
|
||||
@@ -78,9 +75,6 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFontDialogButton" id="font_button">
|
||||
<accessibility>
|
||||
<relation name="labelled-by">font_label</relation>
|
||||
</accessibility>
|
||||
<property name="dialog">
|
||||
<object class="GtkFontDialog">
|
||||
</object>
|
||||
@@ -192,9 +186,6 @@
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<accessibility>
|
||||
<property name="label">Zoom in</property>
|
||||
</accessibility>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
@@ -220,9 +211,6 @@
|
||||
<property name="icon-name">list-remove-symbolic</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<accessibility>
|
||||
<property name="label">Zoom out</property>
|
||||
</accessibility>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
@@ -263,9 +251,6 @@
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkPicture" id="image">
|
||||
<accessibility>
|
||||
<property name="label">Font rendering example</property>
|
||||
</accessibility>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="can-shrink">0</property>
|
||||
|
||||
@@ -18,7 +18,6 @@ do_headerbar (GtkWidget *do_widget)
|
||||
GtkWidget *header;
|
||||
GtkWidget *button;
|
||||
GtkWidget *box;
|
||||
GtkWidget *content;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
@@ -38,26 +37,16 @@ do_headerbar (GtkWidget *do_widget)
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_add_css_class (box, "linked");
|
||||
button = gtk_button_new_from_icon_name ("go-previous-symbolic");
|
||||
gtk_widget_set_tooltip_text (button, "Back");
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
button = gtk_button_new_from_icon_name ("go-next-symbolic");
|
||||
gtk_widget_set_tooltip_text (button, "Forward");
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), box);
|
||||
button = gtk_switch_new ();
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (button),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Change something",
|
||||
-1);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), gtk_switch_new ());
|
||||
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
content = gtk_text_view_new ();
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (content),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Content",
|
||||
-1);
|
||||
gtk_window_set_child (GTK_WINDOW (window), content);
|
||||
gtk_window_set_child (GTK_WINDOW (window), gtk_text_view_new ());
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -164,18 +164,12 @@ do_image_scaling (GtkWidget *do_widget)
|
||||
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, -10., 10., 0.1);
|
||||
gtk_scale_add_mark (GTK_SCALE (scale), 0., GTK_POS_TOP, NULL);
|
||||
gtk_widget_set_tooltip_text (scale, "Zoom");
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (scale),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Zoom",
|
||||
-1);
|
||||
gtk_range_set_value (GTK_RANGE (scale), 0.);
|
||||
gtk_widget_set_hexpand (scale, TRUE);
|
||||
gtk_box_append (GTK_BOX (box2), scale);
|
||||
|
||||
dropdown = gtk_drop_down_new (G_LIST_MODEL (gtk_string_list_new ((const char *[]){ "Linear", "Nearest", "Trilinear", NULL })), NULL);
|
||||
gtk_widget_set_tooltip_text (dropdown, "Filter");
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (dropdown),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Filter",
|
||||
-1);
|
||||
gtk_box_append (GTK_BOX (box2), dropdown);
|
||||
|
||||
g_object_bind_property (dropdown, "selected", widget, "filter", G_BINDING_DEFAULT);
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="mnemonic-widget">switch</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -74,7 +73,6 @@
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="mnemonic-widget">check</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -112,7 +110,6 @@
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="opacity">0</property>
|
||||
<property name="accessible-role">status</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -153,11 +150,10 @@
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="mnemonic-widget">scale</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale" id="scale">
|
||||
<object class="GtkScale">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="draw-value">0</property>
|
||||
@@ -189,11 +185,10 @@
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="mnemonic-widget">spin</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spin">
|
||||
<object class="GtkSpinButton">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="adjustment">
|
||||
@@ -222,11 +217,10 @@
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="mnemonic-widget">dropdown</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="dropdown">
|
||||
<object class="GtkDropDown">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="model">
|
||||
@@ -258,11 +252,10 @@
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="mnemonic-widget">entry</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry">
|
||||
<object class="GtkEntry">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="placeholder-text">Type here…</property>
|
||||
|
||||
@@ -52,10 +52,6 @@ setup_listitem_cb (GtkListItemFactory *factory,
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||
image = gtk_image_new ();
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (image),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL,
|
||||
"App icon",
|
||||
-1);
|
||||
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
||||
gtk_box_append (GTK_BOX (box), image);
|
||||
label = gtk_label_new ("");
|
||||
@@ -83,7 +79,6 @@ bind_listitem_cb (GtkListItemFactory *factory,
|
||||
|
||||
gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (app_info));
|
||||
gtk_label_set_label (GTK_LABEL (label), g_app_info_get_display_name (app_info));
|
||||
gtk_list_item_set_accessible_label (list_item, g_app_info_get_display_name (app_info));
|
||||
}
|
||||
|
||||
/* In more complex code, we would also need functions to unbind and teardown
|
||||
|
||||
@@ -431,9 +431,6 @@ setup_listitem_cb (GtkListItemFactory *factory,
|
||||
picture = gtk_picture_new ();
|
||||
gtk_expression_bind (expression, picture, "paintable", picture);
|
||||
gtk_box_append (GTK_BOX (box), picture);
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (picture),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, location_label, NULL,
|
||||
-1);
|
||||
|
||||
|
||||
/* And finally, everything comes together.
|
||||
@@ -490,9 +487,6 @@ do_listview_clocks (GtkWidget *do_widget)
|
||||
|
||||
model = GTK_SELECTION_MODEL (gtk_no_selection_new (create_clocks_model ()));
|
||||
gridview = gtk_grid_view_new (model, factory);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (gridview),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Clocks",
|
||||
-1);
|
||||
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
|
||||
gtk_scrollable_set_vscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
|
||||
|
||||
|
||||
@@ -368,38 +368,6 @@ match_func (MatchObject *obj,
|
||||
g_free (tmp2);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_header (GtkSignalListItemFactory *factory,
|
||||
GObject *list_item,
|
||||
gpointer data)
|
||||
{
|
||||
GtkListHeader *self = GTK_LIST_HEADER (list_item);
|
||||
GtkWidget *child;
|
||||
|
||||
child = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (child), 0);
|
||||
gtk_label_set_use_markup (GTK_LABEL (child), TRUE);
|
||||
gtk_widget_set_margin_top (child, 10);
|
||||
gtk_widget_set_margin_bottom (child, 10);
|
||||
|
||||
gtk_list_header_set_child (self, child);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_header (GtkSignalListItemFactory *factory,
|
||||
GObject *list_item,
|
||||
gpointer data)
|
||||
{
|
||||
GtkListHeader *self = GTK_LIST_HEADER (list_item);
|
||||
GtkWidget *child = gtk_list_header_get_child (self);
|
||||
GObject *item = gtk_list_header_get_item (self);
|
||||
|
||||
if (strstr (gtk_string_object_get_string (GTK_STRING_OBJECT (item)), "hour"))
|
||||
gtk_label_set_label (GTK_LABEL (child), "<big><b>Hours</b></big>");
|
||||
else
|
||||
gtk_label_set_label (GTK_LABEL (child), "<big><b>Minutes</b></big>");
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_listview_selections (GtkWidget *do_widget)
|
||||
{
|
||||
@@ -409,12 +377,10 @@ do_listview_selections (GtkWidget *do_widget)
|
||||
GtkExpression *expression;
|
||||
GtkListItemFactory *factory;
|
||||
const char * const times[] = { "1 minute", "2 minutes", "5 minutes", "20 minutes", NULL };
|
||||
const char * const minutes[] = {
|
||||
const char * const many_times[] = {
|
||||
"1 minute", "2 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes",
|
||||
"25 minutes", "30 minutes", "35 minutes", "40 minutes", "45 minutes", "50 minutes",
|
||||
"55 minutes", NULL
|
||||
};
|
||||
const char * const hours[] = { "1 hour", "2 hours", "3 hours", "5 hours", "6 hours", "7 hours",
|
||||
"55 minutes", "1 hour", "2 hours", "3 hours", "5 hours", "6 hours", "7 hours",
|
||||
"8 hours", "9 hours", "10 hours", "11 hours", "12 hours", NULL
|
||||
};
|
||||
const char * const device_titles[] = { "Digital Output", "Headphones", "Digital Output", "Analog Output", NULL };
|
||||
@@ -429,10 +395,6 @@ do_listview_selections (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkStringList *minutes_model, *hours_model;
|
||||
GListStore *store;
|
||||
GtkFlattenListModel *flat;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
@@ -460,25 +422,14 @@ do_listview_selections (GtkWidget *do_widget)
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
/* A dropdown using an expression to obtain strings */
|
||||
minutes_model = gtk_string_list_new (minutes);
|
||||
hours_model = gtk_string_list_new (hours);
|
||||
store = g_list_store_new (G_TYPE_LIST_MODEL);
|
||||
g_list_store_append (store, minutes_model);
|
||||
g_list_store_append (store, hours_model);
|
||||
g_object_unref (minutes_model);
|
||||
g_object_unref (hours_model);
|
||||
flat = gtk_flatten_list_model_new (G_LIST_MODEL (store));
|
||||
button = drop_down_new_from_strings (many_times, NULL, NULL);
|
||||
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_title,
|
||||
NULL, NULL);
|
||||
button = gtk_drop_down_new (G_LIST_MODEL (flat), expression);
|
||||
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_header), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_header), NULL);
|
||||
gtk_drop_down_set_header_factory (GTK_DROP_DOWN (button), factory);
|
||||
g_object_unref (factory);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
|
||||
gtk_expression_unref (expression);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
button = gtk_drop_down_new (NULL, NULL);
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
<property name="child">
|
||||
<object class="GtkInscription">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="nat-chars">25</property>
|
||||
<property name="text-overflow">ellipsize-end</property>
|
||||
<binding name="text">
|
||||
<lookup name="title" type="GtkDemo">
|
||||
<lookup name="item">expander</lookup>
|
||||
|
||||
+24
-38
@@ -18,6 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
@@ -267,9 +268,9 @@ activate_run (GSimpleAction *action,
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
display_image (const char *format,
|
||||
const char *resource,
|
||||
GtkWidget *label)
|
||||
display_image (const char *format,
|
||||
const char *resource,
|
||||
char **label)
|
||||
{
|
||||
GtkWidget *sw, *image;
|
||||
|
||||
@@ -279,17 +280,13 @@ display_image (const char *format,
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), image);
|
||||
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (image),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
|
||||
-1);
|
||||
|
||||
return sw;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
display_images (const char *format,
|
||||
const char *resource_dir,
|
||||
GtkWidget *label)
|
||||
display_images (const char *format,
|
||||
const char *resource_dir,
|
||||
char **label)
|
||||
{
|
||||
char **resources;
|
||||
GtkWidget *grid;
|
||||
@@ -314,15 +311,13 @@ display_images (const char *format,
|
||||
{
|
||||
char *resource_name;
|
||||
GtkWidget *box;
|
||||
GtkWidget *image_label;
|
||||
|
||||
resource_name = g_strconcat (resource_dir, "/", resources[i], NULL);
|
||||
|
||||
image_label = gtk_label_new (resources[i]);
|
||||
widget = display_image (NULL, resource_name, image_label);
|
||||
widget = display_image (NULL, resource_name, NULL);
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_box_append (GTK_BOX (box), widget);
|
||||
gtk_box_append (GTK_BOX (box), image_label);
|
||||
gtk_box_append (GTK_BOX (box), gtk_label_new (resources[i]));
|
||||
gtk_flow_box_insert (GTK_FLOW_BOX (grid), box, -1);
|
||||
|
||||
g_free (resource_name);
|
||||
@@ -330,19 +325,15 @@ display_images (const char *format,
|
||||
|
||||
g_strfreev (resources);
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (label), "Images");
|
||||
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (grid),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
|
||||
-1);
|
||||
*label = g_strdup ("Images");
|
||||
|
||||
return sw;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
display_text (const char *format,
|
||||
const char *resource,
|
||||
GtkWidget *label)
|
||||
display_text (const char *format,
|
||||
const char *resource,
|
||||
char **label)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkWidget *textview, *sw;
|
||||
@@ -377,10 +368,6 @@ display_text (const char *format,
|
||||
|
||||
gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
|
||||
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (textview),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
|
||||
-1);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
@@ -391,19 +378,15 @@ display_text (const char *format,
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
display_video (const char *format,
|
||||
const char *resource,
|
||||
GtkWidget *label)
|
||||
display_video (const char *format,
|
||||
const char *resource,
|
||||
char **label)
|
||||
{
|
||||
GtkWidget *video;
|
||||
|
||||
video = gtk_video_new_for_resource (resource);
|
||||
gtk_video_set_loop (GTK_VIDEO (video), TRUE);
|
||||
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (video),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
|
||||
-1);
|
||||
|
||||
return video;
|
||||
}
|
||||
|
||||
@@ -425,9 +408,9 @@ display_nothing (const char *resource)
|
||||
static struct {
|
||||
const char *extension;
|
||||
const char *format;
|
||||
GtkWidget * (* display_func) (const char *format,
|
||||
const char *resource,
|
||||
GtkWidget *label);
|
||||
GtkWidget * (* display_func) (const char *format,
|
||||
const char *resource,
|
||||
char **label);
|
||||
} display_funcs[] = {
|
||||
{ ".gif", NULL, display_image },
|
||||
{ ".jpg", NULL, display_image },
|
||||
@@ -450,6 +433,7 @@ add_data_tab (const char *demoname)
|
||||
char **resources;
|
||||
GtkWidget *widget, *label;
|
||||
guint i, j;
|
||||
char *label_string;
|
||||
|
||||
resource_dir = g_strconcat ("/", demoname, NULL);
|
||||
resources = g_resources_enumerate_children (resource_dir, 0, NULL);
|
||||
@@ -469,21 +453,23 @@ add_data_tab (const char *demoname)
|
||||
break;
|
||||
}
|
||||
|
||||
label = gtk_label_new (resources[i]);
|
||||
label_string = NULL;
|
||||
|
||||
if (j < G_N_ELEMENTS (display_funcs))
|
||||
widget = display_funcs[j].display_func (display_funcs[j].format,
|
||||
resource_name,
|
||||
label);
|
||||
&label_string);
|
||||
else
|
||||
widget = display_nothing (resource_name);
|
||||
|
||||
label = gtk_label_new (label_string ? label_string : resources[i]);
|
||||
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, label);
|
||||
g_object_set (gtk_notebook_get_page (GTK_NOTEBOOK (notebook), widget),
|
||||
"tab-expand", FALSE,
|
||||
NULL);
|
||||
|
||||
g_free (resource_name);
|
||||
g_free (label_string);
|
||||
}
|
||||
|
||||
g_strfreev (resources);
|
||||
|
||||
@@ -57,17 +57,14 @@
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="width-request">220</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSearchBar" id="searchbar">
|
||||
<accessibility>
|
||||
<relation name="labelled-by">search-entry</relation>
|
||||
</accessibility>
|
||||
<property name="key-capture-widget">window</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="search-entry">
|
||||
<accessibility>
|
||||
<property name="label" translatable="yes">Search</property>
|
||||
<relation name="controls">listview</relation>
|
||||
</accessibility>
|
||||
</object>
|
||||
@@ -79,15 +76,15 @@
|
||||
<style>
|
||||
<class name="sidebar"/>
|
||||
</style>
|
||||
<property name="width-request">120</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="propagate-natural-width">1</property>
|
||||
<property name="min-content-width">150</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkListView" id="listview">
|
||||
<style>
|
||||
<class name="navigation-sidebar"/>
|
||||
</style>
|
||||
<property name="tab-behavior">item</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/ui/main-listitem.ui</property>
|
||||
|
||||
@@ -158,7 +158,17 @@ demos_h = custom_target('gtk4 demo header',
|
||||
command: [ find_program('geninclude.py'), '@OUTPUT@', '@INPUT@' ],
|
||||
)
|
||||
|
||||
if can_use_objcopy_for_resources
|
||||
objcopy_supports_add_symbol = false
|
||||
objcopy = find_program('objcopy', required : false)
|
||||
if objcopy.found()
|
||||
objcopy_supports_add_symbol = run_command(objcopy, '--help', check: false).stdout().contains('--add-symbol')
|
||||
endif
|
||||
|
||||
ld = find_program('ld', required : false)
|
||||
|
||||
if not meson.is_cross_build() and build_machine.cpu_family() != 'arm' and build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_add_symbol and ld.found()
|
||||
glib_compile_resources = find_program('glib-compile-resources')
|
||||
|
||||
# Create the resource blob
|
||||
gtkdemo_gresource = custom_target('gtkdemo.gresource',
|
||||
input : 'demo.gresource.xml',
|
||||
|
||||
@@ -68,9 +68,6 @@ do_password_entry (GtkWidget *do_widget)
|
||||
"placeholder-text", "Password",
|
||||
"activates-default", TRUE,
|
||||
NULL);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (entry),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Password",
|
||||
-1);
|
||||
g_signal_connect (entry, "notify::text", G_CALLBACK (update_button), NULL);
|
||||
gtk_box_append (GTK_BOX (box), entry);
|
||||
|
||||
@@ -80,9 +77,6 @@ do_password_entry (GtkWidget *do_widget)
|
||||
"placeholder-text", "Confirm",
|
||||
"activates-default", TRUE,
|
||||
NULL);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (entry2),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Confirm",
|
||||
-1);
|
||||
g_signal_connect (entry2, "notify::text", G_CALLBACK (update_button), NULL);
|
||||
gtk_box_append (GTK_BOX (box), entry2);
|
||||
|
||||
|
||||
@@ -189,7 +189,6 @@ do_pickers (GtkWidget *do_widget)
|
||||
gtk_grid_attach (GTK_GRID (table), label, 0, 0, 1, 1);
|
||||
|
||||
picker = gtk_color_dialog_button_new (gtk_color_dialog_new ());
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), picker);
|
||||
gtk_grid_attach (GTK_GRID (table), picker, 1, 0, 1, 1);
|
||||
|
||||
label = gtk_label_new ("Font:");
|
||||
@@ -199,7 +198,6 @@ do_pickers (GtkWidget *do_widget)
|
||||
gtk_grid_attach (GTK_GRID (table), label, 0, 1, 1, 1);
|
||||
|
||||
picker = gtk_font_dialog_button_new (gtk_font_dialog_new ());
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), picker);
|
||||
gtk_grid_attach (GTK_GRID (table), picker, 1, 1, 1, 1);
|
||||
|
||||
label = gtk_label_new ("File:");
|
||||
@@ -210,9 +208,6 @@ do_pickers (GtkWidget *do_widget)
|
||||
|
||||
picker = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
button = gtk_button_new_from_icon_name ("document-open-symbolic");
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (button),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Select File",
|
||||
-1);
|
||||
|
||||
label = gtk_label_new ("None");
|
||||
|
||||
@@ -228,9 +223,6 @@ do_pickers (GtkWidget *do_widget)
|
||||
gtk_box_append (GTK_BOX (picker), button);
|
||||
app_picker = gtk_button_new_from_icon_name ("emblem-system-symbolic");
|
||||
gtk_widget_set_halign (app_picker, GTK_ALIGN_END);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (app_picker),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Open File",
|
||||
-1);
|
||||
gtk_widget_set_sensitive (app_picker, FALSE);
|
||||
g_signal_connect (app_picker, "clicked", G_CALLBACK (open_app), NULL);
|
||||
gtk_box_append (GTK_BOX (picker), app_picker);
|
||||
@@ -249,7 +241,7 @@ do_pickers (GtkWidget *do_widget)
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
gtk_widget_set_visible (window, TRUE);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
|
||||
@@ -150,36 +150,20 @@ do_video_player (GtkWidget *do_widget)
|
||||
|
||||
button = gtk_button_new ();
|
||||
image = gtk_image_new_from_resource ("/cursors/images/gtk_logo_cursor.png");
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (image),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, button, NULL,
|
||||
-1);
|
||||
gtk_image_set_pixel_size (GTK_IMAGE (image), 24);
|
||||
gtk_button_set_child (GTK_BUTTON (button), image);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (logo_clicked_cb), video);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (button),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "GTK Logo",
|
||||
-1);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (title), button);
|
||||
|
||||
button = gtk_button_new ();
|
||||
image = gtk_image_new_from_resource ("/video-player/bbb.png");
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (image),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, button, NULL,
|
||||
-1);
|
||||
gtk_image_set_pixel_size (GTK_IMAGE (image), 24);
|
||||
gtk_button_set_child (GTK_BUTTON (button), image);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (bbb_clicked_cb), video);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (button),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Big Buck Bunny",
|
||||
-1);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (title), button);
|
||||
|
||||
fullscreen_button = gtk_button_new_from_icon_name ("view-fullscreen-symbolic");
|
||||
g_signal_connect (fullscreen_button, "clicked", G_CALLBACK (fullscreen_clicked_cb), NULL);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (fullscreen_button),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, "Fullscreen",
|
||||
-1);
|
||||
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (title), fullscreen_button);
|
||||
|
||||
controller = gtk_shortcut_controller_new ();
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
# demos/widget-factory
|
||||
|
||||
if can_use_objcopy_for_resources
|
||||
objcopy_supports_add_symbol = false
|
||||
objcopy = find_program('objcopy', required : false)
|
||||
if objcopy.found()
|
||||
objcopy_supports_add_symbol = run_command(objcopy, '--help', check: false).stdout().contains('--add-symbol')
|
||||
endif
|
||||
|
||||
ld = find_program('ld', required : false)
|
||||
|
||||
if not meson.is_cross_build() and build_machine.cpu_family() != 'arm' and build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_add_symbol and ld.found()
|
||||
glib_compile_resources = find_program('glib-compile-resources')
|
||||
|
||||
# Create the resource blob
|
||||
widgetfactory_gresource = custom_target('widgetfactory.gresource',
|
||||
input : 'widget-factory.gresource.xml',
|
||||
|
||||
@@ -1572,9 +1572,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<property name="valign">3</property>
|
||||
<child>
|
||||
<object class="GtkVolumeButton">
|
||||
<accessibility>
|
||||
<property name="label" translatable="1">Volume</property>
|
||||
</accessibility>
|
||||
<property name="orientation">1</property>
|
||||
<property name="valign">3</property>
|
||||
<property name="value">.5</property>
|
||||
@@ -1587,9 +1584,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScaleButton" id="mic-button">
|
||||
<accessibility>
|
||||
<property name="label" translatable="1">Microphone gain</property>
|
||||
</accessibility>
|
||||
<property name="has-tooltip">1</property>
|
||||
<property name="icons">microphone-sensitivity-muted-symbolic
|
||||
microphone-sensitivity-high-symbolic
|
||||
|
||||
@@ -23,7 +23,7 @@ When it comes to rendering, GTK follows the CSS box model as far as practical.
|
||||
|
||||
The CSS stylesheet that is in use determines the sizes (and appearance) of the
|
||||
margin, border and padding areas for each widget. The size of the content area
|
||||
is determined by GTKs layout algorithm using each widget’s [vfunc@Gtk.Widget.measure]
|
||||
is determined by GTKs layout algorithm using each widgets [vfunc@Gtk.Widget.measure]
|
||||
and [vfunc@Gtk.Widget.size_allocate] vfuncs.
|
||||
|
||||
You can learn more about the CSS box model by reading the
|
||||
@@ -37,11 +37,11 @@ To learn more about where GTK CSS differs from CSS on the web, see the
|
||||
|
||||
The content area in the CSS box model is the region that the widget considers its own.
|
||||
|
||||
The origin of the widget’s coordinate system is the top left corner of the content area,
|
||||
and its size is the widget’s size. The size can be queried with [method@Gtk.Widget.get_width]
|
||||
The origin of the widgets coordinate system is the top left corner of the content area,
|
||||
and its size is the widgets size. The size can be queried with [method@Gtk.Widget.get_width]
|
||||
and [method@Gtk.Widget.get_height]. GTK allows general 3D transformations to position
|
||||
widgets (although most of the time, the transformation will be a simple 2D translation).
|
||||
The transform to go from one widget’s coordinate system to another one can be obtained
|
||||
The transform to go from one widgets coordinate system to another one can be obtained
|
||||
with [method@Gtk.Widget.compute_transform].
|
||||
|
||||
In addition to a size, widgets can optionally have a **_baseline_** to position text on.
|
||||
@@ -55,8 +55,8 @@ or [method@Gtk.Widget.compute_bounds]. These methods can fail (either because th
|
||||
don't share a common ancestor, or because of a singular transformation), and callers need
|
||||
to handle this eventuality.
|
||||
|
||||
Another area that is occasionally relevant are the widget’s **_bounds_**, which is the area
|
||||
that a widget’s rendering is typically confined to (technically, widgets can draw outside
|
||||
Another area that is occasionally relevant are the widgets **_bounds_**, which is the area
|
||||
that a widgets rendering is typically confined to (technically, widgets can draw outside
|
||||
of this area, unless clipping is enforced via the [property@Gtk.Widget:overflow] property).
|
||||
In CSS terms, the bounds of a widget correspond to the border area.
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ SYNOPSIS
|
||||
| **gtk4-builder-tool** enumerate [OPTIONS...] <FILE>
|
||||
| **gtk4-builder-tool** simplify [OPTIONS...] <FILE>
|
||||
| **gtk4-builder-tool** preview [OPTIONS...] <FILE>
|
||||
| **gtk4-builder-tool** render [OPTIONS...] <FILE>
|
||||
| **gtk4-builder-tool** screenshot [OPTIONS...] <FILE>
|
||||
|
||||
DESCRIPTION
|
||||
@@ -70,11 +69,12 @@ file to use.
|
||||
|
||||
Load style information from the given CSS file.
|
||||
|
||||
Render
|
||||
^^^^^^
|
||||
Screenshot
|
||||
^^^^^^^^^^
|
||||
|
||||
The ``render`` command saves a rendering of the UI definition file as a png image
|
||||
or node file. The name of the file to write can be specified as a second FILE argument.
|
||||
The ``screenshot`` command saves a rendering of the UI definition file
|
||||
as a png image or node file. The name of the file to write can be specified as
|
||||
a second FILE argument.
|
||||
|
||||
This command accepts options to specify the ID of the toplevel object and a CSS
|
||||
file to use.
|
||||
@@ -96,11 +96,6 @@ file to use.
|
||||
|
||||
Overwrite an existing file.
|
||||
|
||||
Screenshot
|
||||
^^^^^^^^^^
|
||||
|
||||
The ``screenshot`` command is an alias for ``render``.
|
||||
|
||||
Simplification
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -208,12 +208,6 @@ A number of options affect behavior instead of logging:
|
||||
`nograbs`
|
||||
: Turn off all pointer and keyboard grabs
|
||||
|
||||
`portals`
|
||||
: Force the use of [portals](https://docs.flatpak.org/en/latest/portals.html)
|
||||
|
||||
`no-portals`
|
||||
: Disable use of [portals](https://docs.flatpak.org/en/latest/portals.html)
|
||||
|
||||
`gl-disable`
|
||||
: Disable OpenGL support
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ described by a set of *attributes*.
|
||||
Roles define the taxonomy and semantics of a UI control to any assistive
|
||||
technology application; for instance, a button will have a role of
|
||||
`GTK_ACCESSIBLE_ROLE_BUTTON`; an entry will have a role of
|
||||
`GTK_ACCESSIBLE_ROLE_TEXTBOX`; a check button will have a role of
|
||||
`GTK_ACCESSIBLE_ROLE_TEXTBOX`; a toggle button will have a role of
|
||||
`GTK_ACCESSIBLE_ROLE_CHECKBOX`; etc.
|
||||
|
||||
Each role is part of the widget's instance, and **cannot** be changed over
|
||||
@@ -46,7 +46,6 @@ Each role name is part of the #GtkAccessibleRole enumeration.
|
||||
|
||||
| Role name | Description | Related GTK widget |
|
||||
|-----------|-------------|--------------------|
|
||||
| `APPLICATION` | An application window | [class@Gtk.Window] |
|
||||
| `BUTTON` | A control that performs an action when pressed | [class@Gtk.Button], [class@Gtk.LinkButton], [class@Gtk.Expander] |
|
||||
| `CHECKBOX` | A control that has three possible value: `true`, `false`, or `undefined` | [class@Gtk.CheckButton] |
|
||||
| `COMBOBOX` | A control that can be expanded to show a list of possible values to select | [class@Gtk.ComboBox] |
|
||||
@@ -79,6 +78,7 @@ Each role name is part of the #GtkAccessibleRole enumeration.
|
||||
| `TAB_PANEL` | A page in a notebook or stack | [class@Gtk.Stack] |
|
||||
| `TEXT_BOX` | A type of input that allows free-form text as its value. | [class@Gtk.Entry], [class@Gtk.PasswordEntry], [class@Gtk.TextView] |
|
||||
| `TREE_GRID` | A treeview-like columned list | [class@Gtk.ColumnView] |
|
||||
| `WINDOW` | An application window | [class@Gtk.Window] |
|
||||
| `...` | … |
|
||||
|
||||
See the [WAI-ARIA](https://www.w3.org/WAI/PF/aria/appendices#quickref) list
|
||||
@@ -204,27 +204,19 @@ you should ensure that:
|
||||
readable and localised action performed when pressed; for instance "Copy",
|
||||
"Paste", "Add layer", or "Remove"
|
||||
|
||||
GTK will try to fill in some information by using ancillary UI control properties,
|
||||
for instance the accessible name will be taken from the label used by the UI control,
|
||||
or from its tooltip, if the `GTK_ACCESSIBLE_PROPERTY_LABEL` property or the
|
||||
`GTK_ACCESSIBLE_RELATION_LABELLED_BY` relation are unset. Similary for the accessible
|
||||
description. Nevertheless, it is good practice and project hygiene to explicitly specify
|
||||
the accessible properties, just like it's good practice to specify tooltips and style classes.
|
||||
GTK will try to fill in some information by using ancillary UI control
|
||||
properties, for instance the accessible label will be taken from the label or
|
||||
placeholder text used by the UI control, or from its tooltip, if the
|
||||
`GTK_ACCESSIBLE_PROPERTY_LABEL` property or the `GTK_ACCESSIBLE_RELATION_LABELLED_BY`
|
||||
relation are unset. Nevertheless, it is good practice and project hygiene
|
||||
to explicitly specify the accessible properties, just like it's good practice
|
||||
to specify tooltips and style classes.
|
||||
|
||||
Application developers using GTK **should** ensure that their UI controls
|
||||
are accessible as part of the development process. The GTK Inspector shows
|
||||
the accessible attributes of each widget, and also provides an overlay that
|
||||
can highlight accessibility issues.
|
||||
|
||||
It is possible to set accessible attributes in UI files as well:
|
||||
```xml
|
||||
<object class="GtkButton" id="button1">
|
||||
<accessibility>
|
||||
<property name="label">Download</property>
|
||||
<relation name="labelled-by">label1</relation>
|
||||
/accessibility>
|
||||
</object>
|
||||
```
|
||||
are accessible as part of the development process. When using `GtkBuilder`
|
||||
templates and UI definition files, GTK provides a validation tool that
|
||||
verifies that each UI element has a valid role and properties; this tool can
|
||||
be used as part of the application's test suite to avoid regressions.
|
||||
|
||||
## Implementations
|
||||
|
||||
@@ -267,13 +259,6 @@ turn automatically any widget into a `GtkButton`; but if your widget behaves
|
||||
like a button, using the %GTK_ACCESSIBLE_ROLE_BUTTON will allow any
|
||||
assistive technology to handle it like they would a `GtkButton`.
|
||||
|
||||
For widgets that act as containers of other widgets, you should use
|
||||
%GTK_ACCESSIBLE_ROLE_GROUP if the grouping of the children is semantic
|
||||
in nature; for instance, the children of a [class@Gtk.HeaderBar] are
|
||||
grouped together on the header of a window. For generic containers that
|
||||
only impose a layout on their children, you should use
|
||||
%GTK_ACCESSIBLE_ROLE_GENERIC instead.
|
||||
|
||||
### Attributes can both hide and enhance
|
||||
|
||||
Accessible attributes can be used to override the content of a UI element,
|
||||
@@ -382,6 +367,3 @@ To allow changing the value via accessible technologies, you can export
|
||||
actions. Since the accessibility interfaces only support actions
|
||||
without parameters, you should provide actions such as `increase-value`
|
||||
and `decrease-value`.
|
||||
|
||||
Since GTK 4.10, the best way to suppose changing the value is by implementing
|
||||
the [iface@Gtk.AccessibleRange] interface.
|
||||
|
||||
@@ -30,12 +30,12 @@ Views display data from a **_model_**. Models implement the [`iface@Gio.ListMode
|
||||
interface and can be provided in a variety of ways:
|
||||
|
||||
* List model implementations for many specific types of data already exist, for
|
||||
example [`class@Gtk.DirectoryList`] or [`class@Gtk.StringList`].
|
||||
example `GtkDirectoryList` or `GtkStringList`.
|
||||
|
||||
* There are generic list model implementations like [`class@Gio.ListStore`] that allow building
|
||||
* There are generic list model implementations like`GListStore` that allow building
|
||||
lists of arbitrary objects.
|
||||
|
||||
* Wrapping list models like [`class@Gtk.FilterListModel`] or [`class@Gtk.SortListModel`]
|
||||
* Wrapping list models like `GtkFilterListModel` or `GtkSortListModel`
|
||||
modify, adapt or combine other models.
|
||||
|
||||
* Last but not least, developers are encouraged to create their own `GListModel`
|
||||
@@ -133,8 +133,8 @@ tradeoffs of those and experiment with them.
|
||||
|
||||
GTK offers a wide variety of wrapping models which change or supplement an
|
||||
existing model (or models) in some way. But when it comes to storing your
|
||||
actual data, there are only a few ready-made choices available:
|
||||
[`class@Gio.ListStore`], [`class@Gtk.StringList`], and [`class@Gtk.DirectoryList`].
|
||||
actual data, there are only a few ready-made choices available: [`class@Gio.ListStore`]
|
||||
and [`class@Gtk.StringList`].
|
||||
|
||||
`GListStore` is backed by a balanced tree and has performance characteristics
|
||||
that are expected for that data structure. It works reasonably well for dataset
|
||||
@@ -147,10 +147,6 @@ that are expected for that data structure. `GtkStringList` is a good fit for any
|
||||
place where you would otherwise use `char*[]` and works best if the dataset
|
||||
is not very dynamic.
|
||||
|
||||
`GtkDirectoryList` is a list model that wraps [`method@Gio.File.enumerate_children_async`].
|
||||
It presents a `GListModel` and fills it asynchronously with the [`iface@Gio.File`]s
|
||||
returned from that function.
|
||||
|
||||
If these models don't fit your use case or scalability requirements, you
|
||||
should make a custom `GListModel` implementation. It is a small interface and
|
||||
not very hard to implement.
|
||||
@@ -203,7 +199,7 @@ the `.data-table` style class.
|
||||
## Sections
|
||||
|
||||
List models can optionally group their items into **_sections_**, by implementing
|
||||
the `GtkSectionModel` interface. `GtkListView` can
|
||||
the `GtkSectionModel` interface. Both `GtkListView` and `GtkGridView` can
|
||||
display headers for sections, by installing a separate **_header factory_**.
|
||||
|
||||
Many GTK list models support section inherently, or they pass through the
|
||||
|
||||
@@ -34,7 +34,7 @@ gdk_broadway_cairo_context_dispose (GObject *object)
|
||||
|
||||
static void
|
||||
gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkBroadwayCairoContext *self = GDK_BROADWAY_CAIRO_CONTEXT (draw_context);
|
||||
|
||||
@@ -34,7 +34,7 @@ gdk_broadway_draw_context_dispose (GObject *object)
|
||||
|
||||
static void
|
||||
gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkBroadwayDrawContext *self = GDK_BROADWAY_DRAW_CONTEXT (draw_context);
|
||||
|
||||
@@ -645,9 +645,6 @@ gdk_content_formats_builder_clear (GdkContentFormatsBuilder *builder)
|
||||
{
|
||||
g_clear_pointer (&builder->gtypes, g_slist_free);
|
||||
g_clear_pointer (&builder->mime_types, g_slist_free);
|
||||
|
||||
builder->n_gtypes = 0;
|
||||
builder->n_mime_types = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkmonitorprivate.h"
|
||||
#include "gdkrectangle.h"
|
||||
#include "gdkvulkancontext.h"
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#include <epoxy/egl.h>
|
||||
@@ -384,9 +383,6 @@ gdk_display_dispose (GObject *object)
|
||||
#endif
|
||||
g_clear_error (&priv->gl_error);
|
||||
|
||||
for (GList *l = display->seats; l; l = l->next)
|
||||
g_object_run_dispose (G_OBJECT (l->data));
|
||||
|
||||
G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@@ -1217,49 +1213,6 @@ gdk_display_get_keymap (GdkDisplay *display)
|
||||
return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_display_create_vulkan_context:
|
||||
* @self: a `GdkDisplay`
|
||||
* @error: return location for an error
|
||||
*
|
||||
* Creates a new `GdkVulkanContext` for use with @display.
|
||||
*
|
||||
* The context can not be used to draw to surfaces, it can only be
|
||||
* used for custom rendering or compute.
|
||||
*
|
||||
* If the creation of the `GdkVulkanContext` failed, @error will be set.
|
||||
*
|
||||
* Returns: (transfer full): the newly created `GdkVulkanContext`, or
|
||||
* %NULL on error
|
||||
*/
|
||||
GdkVulkanContext *
|
||||
gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (self), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (gdk_display_get_debug_flags (self) & GDK_DEBUG_VULKAN_DISABLE)
|
||||
{
|
||||
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
|
||||
_("Vulkan support disabled via GDK_DEBUG"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (GDK_DISPLAY_GET_CLASS (self)->vk_extension_name == NULL)
|
||||
{
|
||||
g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
|
||||
"The %s backend has no Vulkan support.", G_OBJECT_TYPE_NAME (self));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return g_initable_new (GDK_DISPLAY_GET_CLASS (self)->vk_context_type,
|
||||
NULL,
|
||||
error,
|
||||
"display", self,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_init_gl (GdkDisplay *self)
|
||||
{
|
||||
|
||||
@@ -100,11 +100,6 @@ struct _GdkDisplay
|
||||
VkDevice vk_device;
|
||||
VkQueue vk_queue;
|
||||
uint32_t vk_queue_family_index;
|
||||
VkPipelineCache vk_pipeline_cache;
|
||||
gsize vk_pipeline_cache_size;
|
||||
char *vk_pipeline_cache_etag;
|
||||
guint vk_save_pipeline_cache_source;
|
||||
GHashTable *vk_shader_modules;
|
||||
|
||||
guint vulkan_refcount;
|
||||
#endif /* GDK_RENDERING_VULKAN */
|
||||
@@ -207,9 +202,6 @@ gulong _gdk_display_get_next_serial (GdkDisplay *display
|
||||
void _gdk_display_pause_events (GdkDisplay *display);
|
||||
void _gdk_display_unpause_events (GdkDisplay *display);
|
||||
|
||||
GdkVulkanContext * gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
GError **error);
|
||||
|
||||
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display);
|
||||
|
||||
gboolean gdk_display_init_egl (GdkDisplay *display,
|
||||
|
||||
+10
-11
@@ -311,20 +311,19 @@ gdk_draw_context_begin_frame (GdkDrawContext *context,
|
||||
g_return_if_fail (priv->surface != NULL);
|
||||
g_return_if_fail (region != NULL);
|
||||
|
||||
gdk_draw_context_begin_frame_full (context, GDK_MEMORY_U8, region);
|
||||
gdk_draw_context_begin_frame_full (context, FALSE, region);
|
||||
}
|
||||
|
||||
/*
|
||||
* @depth: best depth to render in
|
||||
* @prefers_high_depth: %TRUE to request a higher bit depth
|
||||
*
|
||||
* If the given depth is not `GDK_MEMORY_U8`, GDK will see about providing a
|
||||
* rendering target that supports a higher bit depth than 8 bits per channel.
|
||||
* Typically this means a target supporting 16bit floating point pixels, but
|
||||
* that is not guaranteed.
|
||||
* If high depth is preferred, GDK will see about providing a rendering target
|
||||
* that supports higher bit depth than 8 bits per channel. Typically this means
|
||||
* a target supporting 16bit floating point pixels, but that is not guaranteed.
|
||||
*
|
||||
* This is only a request and if the GDK backend does not support HDR rendering
|
||||
* or does not consider it worthwhile, it may choose to not honor the request.
|
||||
* It may also choose to provide a differnet depth even if it was not requested.
|
||||
* It may also choose to provide high depth even if it was not requested.
|
||||
* Typically the steps undertaken by a backend are:
|
||||
* 1. Check if high depth is supported by this drawing backend.
|
||||
* 2. Check if the compositor supports high depth.
|
||||
@@ -334,12 +333,12 @@ gdk_draw_context_begin_frame (GdkDrawContext *context,
|
||||
* In either of those cases, the context will usually choose to not honor the request.
|
||||
*
|
||||
* The rendering code must be able to deal with content in any bit depth, no matter
|
||||
* the preference. The depth argument is only a hint and GDK is free
|
||||
* the preference. The prefers_high_depth argument is only a hint and GDK is free
|
||||
* to choose.
|
||||
*/
|
||||
void
|
||||
gdk_draw_context_begin_frame_full (GdkDrawContext *context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
|
||||
@@ -366,12 +365,12 @@ gdk_draw_context_begin_frame_full (GdkDrawContext *context,
|
||||
}
|
||||
|
||||
if (gdk_display_get_debug_flags (priv->display) & GDK_DEBUG_HIGH_DEPTH)
|
||||
depth = GDK_MEMORY_FLOAT32;
|
||||
prefers_high_depth = TRUE;
|
||||
|
||||
priv->frame_region = cairo_region_copy (region);
|
||||
priv->surface->paint_context = g_object_ref (context);
|
||||
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, depth, priv->frame_region);
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, prefers_high_depth, priv->frame_region);
|
||||
|
||||
cairo_region_intersect_rectangle (priv->frame_region,
|
||||
&(cairo_rectangle_int_t) {
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
|
||||
#include "gdkdrawcontext.h"
|
||||
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_DRAW_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAW_CONTEXT, GdkDrawContextClass))
|
||||
@@ -42,7 +40,7 @@ struct _GdkDrawContextClass
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* begin_frame) (GdkDrawContext *context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *update_area);
|
||||
void (* end_frame) (GdkDrawContext *context,
|
||||
cairo_region_t *painted);
|
||||
@@ -52,7 +50,7 @@ struct _GdkDrawContextClass
|
||||
void gdk_draw_context_surface_resized (GdkDrawContext *context);
|
||||
|
||||
void gdk_draw_context_begin_frame_full (GdkDrawContext *context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
const cairo_region_t *region);
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
+9
-5
@@ -173,8 +173,12 @@ static GPrivate thread_current_context = G_PRIVATE_INIT (unref_unmasked);
|
||||
static void
|
||||
gdk_gl_context_clear_old_updated_area (GdkGLContext *context)
|
||||
{
|
||||
for (unsigned int i = 0; i < GDK_GL_MAX_TRACKED_BUFFERS; i++)
|
||||
g_clear_pointer (&context->old_updated_area[i], cairo_region_destroy);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
g_clear_pointer (&context->old_updated_area[i], cairo_region_destroy);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -581,7 +585,7 @@ gdk_gl_context_get_scale (GdkGLContext *self)
|
||||
|
||||
static void
|
||||
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
@@ -597,7 +601,7 @@ gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
if (priv->egl_context)
|
||||
gdk_surface_ensure_egl_surface (surface, depth != GDK_MEMORY_U8);
|
||||
gdk_surface_ensure_egl_surface (surface, prefers_high_depth);
|
||||
#endif
|
||||
|
||||
damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
|
||||
@@ -1552,7 +1556,7 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
|
||||
priv->has_sync = gdk_gl_context_check_version (context, "3.2", "3.0") ||
|
||||
epoxy_has_gl_extension ("GL_ARB_sync") ||
|
||||
epoxy_has_gl_extension ("GL_APPLE_sync");
|
||||
epoxy_has_gl_extension ("GK_APPLE_sync");
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
{
|
||||
|
||||
+38
-72
@@ -258,7 +258,7 @@ struct _GdkMemoryFormatDescription
|
||||
GdkMemoryAlpha alpha;
|
||||
gsize bytes_per_pixel;
|
||||
gsize alignment;
|
||||
GdkMemoryDepth depth;
|
||||
gboolean prefers_high_depth;
|
||||
struct {
|
||||
guint gl_major;
|
||||
guint gl_minor;
|
||||
@@ -289,7 +289,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
b8g8r8a8_premultiplied_to_float,
|
||||
@@ -299,7 +299,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
a8r8g8b8_premultiplied_to_float,
|
||||
@@ -309,7 +309,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, 0, 0 },
|
||||
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
r8g8b8a8_premultiplied_to_float,
|
||||
@@ -319,7 +319,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
b8g8r8a8_to_float,
|
||||
@@ -329,7 +329,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
a8r8g8b8_to_float,
|
||||
@@ -339,7 +339,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, 0, 0 },
|
||||
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
r8g8b8a8_to_float,
|
||||
@@ -349,7 +349,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
a8b8g8r8_to_float,
|
||||
@@ -359,7 +359,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
3,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, 0, 0 },
|
||||
{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
|
||||
r8g8b8_to_float,
|
||||
@@ -369,7 +369,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
3,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
|
||||
b8g8r8_to_float,
|
||||
@@ -379,7 +379,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
6,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_U16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
|
||||
r16g16b16_to_float,
|
||||
@@ -389,7 +389,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
8,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_U16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
r16g16b16a16_to_float,
|
||||
@@ -399,7 +399,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
8,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_U16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
r16g16b16a16_to_float,
|
||||
@@ -409,7 +409,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
6,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_FLOAT16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RGB16F, GL_RGB, GL_HALF_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
|
||||
r16g16b16_float_to_float,
|
||||
@@ -419,7 +419,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
8,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_FLOAT16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
r16g16b16a16_float_to_float,
|
||||
@@ -429,7 +429,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
8,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_FLOAT16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
r16g16b16a16_float_to_float,
|
||||
@@ -439,7 +439,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
12,
|
||||
G_ALIGNOF (float),
|
||||
GDK_MEMORY_FLOAT32,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RGB32F, GL_RGB, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
|
||||
r32g32b32_float_to_float,
|
||||
@@ -459,7 +459,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
16,
|
||||
G_ALIGNOF (float),
|
||||
GDK_MEMORY_FLOAT32,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RGBA32F, GL_RGBA, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
r32g32b32a32_float_to_float,
|
||||
@@ -469,7 +469,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
2,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RG8, GL_RG, GL_UNSIGNED_BYTE, { GL_RED, GL_RED, GL_RED, GL_GREEN } },
|
||||
g8a8_premultiplied_to_float,
|
||||
@@ -479,7 +479,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
2,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RG8, GL_RG, GL_UNSIGNED_BYTE, { GL_RED, GL_RED, GL_RED, GL_GREEN } },
|
||||
g8a8_to_float,
|
||||
@@ -489,7 +489,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
1,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_R8, GL_RED, GL_UNSIGNED_BYTE, { GL_RED, GL_RED, GL_RED, GL_ONE } },
|
||||
g8_to_float,
|
||||
@@ -499,7 +499,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
4,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_U16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RG16, GL_RG, GL_UNSIGNED_SHORT, { GL_RED, GL_RED, GL_RED, GL_GREEN } },
|
||||
g16a16_premultiplied_to_float,
|
||||
@@ -509,7 +509,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_U16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RG16, GL_RG, GL_UNSIGNED_SHORT, { GL_RED, GL_RED, GL_RED, GL_GREEN } },
|
||||
g16a16_to_float,
|
||||
@@ -519,7 +519,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
2,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_U16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_R16, GL_RED, GL_UNSIGNED_SHORT, { GL_RED, GL_RED, GL_RED, GL_ONE } },
|
||||
g16_to_float,
|
||||
@@ -529,7 +529,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
1,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
FALSE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_R8, GL_RED, GL_UNSIGNED_BYTE, { GL_ONE, GL_ONE, GL_ONE, GL_RED } },
|
||||
a8_to_float,
|
||||
@@ -539,7 +539,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
2,
|
||||
G_ALIGNOF (guint16),
|
||||
GDK_MEMORY_U16,
|
||||
TRUE,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_R16, GL_RED, GL_UNSIGNED_SHORT, { GL_ONE, GL_ONE, GL_ONE, GL_RED } },
|
||||
a16_to_float,
|
||||
@@ -566,57 +566,23 @@ gdk_memory_format_alignment (GdkMemoryFormat format)
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_memory_format_get_depth:
|
||||
* gdk_memory_format_prefers_high_depth:
|
||||
* @format: a memory format
|
||||
*
|
||||
* Gets the depth of the individual channels of the format.
|
||||
* See gsk_render_node_prefers_high_depth() for more
|
||||
* information on this.
|
||||
* Checks if the given format benefits from being rendered
|
||||
* in bit depths higher than 8bits per pixel. See
|
||||
* gsk_render_node_prefers_high_depth() for more information
|
||||
* on this.
|
||||
* Usually this is the case when
|
||||
* gdk_memory_format_bytes_per_pixel() is larger than 4.
|
||||
*
|
||||
* Usually renderers want to use higher depth for render
|
||||
* targets to match these formats.
|
||||
*
|
||||
* Returns: The depth of this format
|
||||
* Returns: %TRUE if the format benefits from being
|
||||
* composited in hgiher bit depths.
|
||||
**/
|
||||
GdkMemoryDepth
|
||||
gdk_memory_format_get_depth (GdkMemoryFormat format)
|
||||
gboolean
|
||||
gdk_memory_format_prefers_high_depth (GdkMemoryFormat format)
|
||||
{
|
||||
return memory_formats[format].depth;
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_memory_depth_merge:
|
||||
* @depth1: the first depth
|
||||
* @depth2: the second depth
|
||||
*
|
||||
* Returns a depth that can accomodate both given depths
|
||||
* without any loss of precision.
|
||||
*
|
||||
* Returns: The merged depth
|
||||
**/
|
||||
GdkMemoryDepth
|
||||
gdk_memory_depth_merge (GdkMemoryDepth depth1,
|
||||
GdkMemoryDepth depth2)
|
||||
{
|
||||
switch (depth1)
|
||||
{
|
||||
case GDK_MEMORY_U8:
|
||||
return depth2;
|
||||
|
||||
case GDK_MEMORY_FLOAT32:
|
||||
return GDK_MEMORY_FLOAT32;
|
||||
|
||||
case GDK_MEMORY_U16:
|
||||
case GDK_MEMORY_FLOAT16:
|
||||
if (depth2 == depth1 || depth2 == GDK_MEMORY_U8)
|
||||
return depth1;
|
||||
else
|
||||
return GDK_MEMORY_FLOAT32;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return GDK_MEMORY_U8;
|
||||
}
|
||||
return memory_formats[format].prefers_high_depth;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -31,19 +31,10 @@ typedef enum {
|
||||
GDK_MEMORY_ALPHA_OPAQUE
|
||||
} GdkMemoryAlpha;
|
||||
|
||||
typedef enum {
|
||||
GDK_MEMORY_U8,
|
||||
GDK_MEMORY_U16,
|
||||
GDK_MEMORY_FLOAT16,
|
||||
GDK_MEMORY_FLOAT32
|
||||
} GdkMemoryDepth;
|
||||
|
||||
gsize gdk_memory_format_alignment (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
GdkMemoryAlpha gdk_memory_format_alpha (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
GdkMemoryDepth gdk_memory_format_get_depth (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
GdkMemoryDepth gdk_memory_depth_merge (GdkMemoryDepth depth1,
|
||||
GdkMemoryDepth depth2) G_GNUC_CONST;
|
||||
gboolean gdk_memory_format_prefers_high_depth(GdkMemoryFormat format) G_GNUC_CONST;
|
||||
gboolean gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
guint gl_major,
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ typedef enum {
|
||||
GDK_SEAT_CAPABILITY_KEYBOARD = 1 << 3,
|
||||
GDK_SEAT_CAPABILITY_TABLET_PAD = 1 << 4,
|
||||
GDK_SEAT_CAPABILITY_ALL_POINTING = (GDK_SEAT_CAPABILITY_POINTER | GDK_SEAT_CAPABILITY_TOUCH | GDK_SEAT_CAPABILITY_TABLET_STYLUS),
|
||||
GDK_SEAT_CAPABILITY_ALL = (GDK_SEAT_CAPABILITY_ALL_POINTING | GDK_SEAT_CAPABILITY_KEYBOARD | GDK_SEAT_CAPABILITY_TABLET_PAD)
|
||||
GDK_SEAT_CAPABILITY_ALL = (GDK_SEAT_CAPABILITY_ALL_POINTING | GDK_SEAT_CAPABILITY_KEYBOARD)
|
||||
} GdkSeatCapabilities;
|
||||
|
||||
struct _GdkSeat
|
||||
|
||||
+1
-2
@@ -25,8 +25,7 @@
|
||||
* multiple frames, and will be used for a long time.
|
||||
*
|
||||
* There are various ways to create `GdkTexture` objects from a
|
||||
* [class@GdkPixbuf.Pixbuf], or from bytes stored in memory, a file, or a
|
||||
* [struct@Gio.Resource].
|
||||
* [class@GdkPixbuf.Pixbuf], or a Cairo surface, or other pixel data.
|
||||
*
|
||||
* The ownership of the pixel data is transferred to the `GdkTexture`
|
||||
* instance; you can only make a copy of it, via [method@Gdk.Texture.download].
|
||||
|
||||
+25
-424
@@ -47,12 +47,7 @@ typedef struct _GdkVulkanContextPrivate GdkVulkanContextPrivate;
|
||||
struct _GdkVulkanContextPrivate {
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
VkSurfaceKHR surface;
|
||||
struct {
|
||||
VkSurfaceFormatKHR vk_format;
|
||||
GdkMemoryFormat gdk_format;
|
||||
} formats[4];
|
||||
GdkMemoryDepth current_format;
|
||||
GdkMemoryFormat offscreen_formats[4];
|
||||
VkSurfaceFormatKHR image_format;
|
||||
|
||||
VkSwapchainKHR swapchain;
|
||||
VkSemaphore draw_semaphore;
|
||||
@@ -383,13 +378,6 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context,
|
||||
|
||||
device = gdk_vulkan_context_get_device (context);
|
||||
|
||||
/*
|
||||
* Wait for device to be idle because this function is also called in window resizes.
|
||||
* And if we destroy old swapchain it also destroy the old VkImages, those images could
|
||||
* be in use by a vulkan render.
|
||||
*/
|
||||
vkDeviceWaitIdle (device);
|
||||
|
||||
res = GDK_VK_CHECK (vkGetPhysicalDeviceSurfaceCapabilitiesKHR, gdk_vulkan_context_get_physical_device (context),
|
||||
priv->surface,
|
||||
&capabilities);
|
||||
@@ -441,8 +429,8 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context,
|
||||
.minImageCount = CLAMP (4,
|
||||
capabilities.minImageCount,
|
||||
capabilities.maxImageCount ? capabilities.maxImageCount : G_MAXUINT32),
|
||||
.imageFormat = priv->formats[priv->current_format].vk_format.format,
|
||||
.imageColorSpace = priv->formats[priv->current_format].vk_format.colorSpace,
|
||||
.imageFormat = priv->image_format.format,
|
||||
.imageColorSpace = priv->image_format.colorSpace,
|
||||
.imageExtent = capabilities.currentExtent,
|
||||
.imageArrayLayers = 1,
|
||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
@@ -511,20 +499,19 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
physical_device_supports_extension (VkPhysicalDevice device,
|
||||
const char *extension_name)
|
||||
device_supports_incremental_present (VkPhysicalDevice device)
|
||||
{
|
||||
VkExtensionProperties *extensions;
|
||||
uint32_t n_device_extensions;
|
||||
|
||||
GDK_VK_CHECK (vkEnumerateDeviceExtensionProperties, device, NULL, &n_device_extensions, NULL);
|
||||
vkEnumerateDeviceExtensionProperties (device, NULL, &n_device_extensions, NULL);
|
||||
|
||||
extensions = g_newa (VkExtensionProperties, n_device_extensions);
|
||||
GDK_VK_CHECK (vkEnumerateDeviceExtensionProperties, device, NULL, &n_device_extensions, extensions);
|
||||
vkEnumerateDeviceExtensionProperties (device, NULL, &n_device_extensions, extensions);
|
||||
|
||||
for (uint32_t i = 0; i < n_device_extensions; i++)
|
||||
{
|
||||
if (g_str_equal (extensions[i].extensionName, extension_name))
|
||||
if (g_str_equal (extensions[i].extensionName, VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -533,27 +520,13 @@ physical_device_supports_extension (VkPhysicalDevice device,
|
||||
|
||||
static void
|
||||
gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (draw_context);
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
guint i;
|
||||
|
||||
if (depth != priv->current_format)
|
||||
{
|
||||
if (priv->formats[depth].gdk_format != priv->formats[priv->current_format].gdk_format)
|
||||
{
|
||||
GError *error = NULL;
|
||||
if (!gdk_vulkan_context_check_swapchain (context, &error))
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
priv->current_format = depth;
|
||||
}
|
||||
for (i = 0; i < priv->n_images; i++)
|
||||
{
|
||||
cairo_region_union (priv->regions[i], region);
|
||||
@@ -692,7 +665,6 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (initable);
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
|
||||
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
|
||||
VkResult res;
|
||||
VkBool32 supported;
|
||||
uint32_t i;
|
||||
@@ -701,22 +673,6 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
if (!priv->vulkan_ref)
|
||||
return FALSE;
|
||||
|
||||
priv->offscreen_formats[GDK_MEMORY_U8] = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
priv->offscreen_formats[GDK_MEMORY_U16] = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
priv->offscreen_formats[GDK_MEMORY_FLOAT16] = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
priv->offscreen_formats[GDK_MEMORY_FLOAT32] = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
|
||||
if (surface == NULL)
|
||||
{
|
||||
for (i = 0; i < G_N_ELEMENTS (priv->formats); i++)
|
||||
{
|
||||
priv->formats[i].vk_format.format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
priv->formats[i].vk_format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
priv->formats[i].gdk_format = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
res = GDK_VULKAN_CONTEXT_GET_CLASS (context)->create_surface (context, &priv->surface);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
@@ -751,74 +707,17 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
&n_formats, formats);
|
||||
for (i = 0; i < n_formats; i++)
|
||||
{
|
||||
if (formats[i].colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||
continue;
|
||||
|
||||
switch ((int) formats[i].format)
|
||||
{
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
if (priv->formats[GDK_MEMORY_U8].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
priv->formats[GDK_MEMORY_U8].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U8].gdk_format = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
priv->offscreen_formats[GDK_MEMORY_U8] = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
};
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
if (priv->formats[GDK_MEMORY_U8].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
priv->formats[GDK_MEMORY_U8].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U8].gdk_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R16G16B16A16_UNORM:
|
||||
priv->formats[GDK_MEMORY_U16].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U16].gdk_format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
priv->formats[GDK_MEMORY_FLOAT16].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_FLOAT16].gdk_format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT:
|
||||
priv->formats[GDK_MEMORY_FLOAT32].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_FLOAT32].gdk_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM)
|
||||
break;
|
||||
}
|
||||
if (priv->formats[GDK_MEMORY_U8].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
if (i == n_formats)
|
||||
{
|
||||
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
|
||||
"No supported image format found.");
|
||||
goto out_surface;
|
||||
}
|
||||
/* Ensure all the formats exist:
|
||||
* - If a format was found, keep that one.
|
||||
* - FLOAT32 chooses the best format we have.
|
||||
* - FLOAT16 and U16 pick the format FLOAT32 uses
|
||||
*/
|
||||
if (priv->formats[GDK_MEMORY_FLOAT32].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
if (priv->formats[GDK_MEMORY_FLOAT16].vk_format.format != VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_FLOAT32] = priv->formats[GDK_MEMORY_FLOAT16];
|
||||
else if (priv->formats[GDK_MEMORY_U16].vk_format.format != VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_FLOAT32] = priv->formats[GDK_MEMORY_U16];
|
||||
else
|
||||
priv->formats[GDK_MEMORY_FLOAT32] = priv->formats[GDK_MEMORY_U8];
|
||||
}
|
||||
if (priv->formats[GDK_MEMORY_FLOAT16].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_FLOAT16] = priv->formats[GDK_MEMORY_FLOAT32];
|
||||
if (priv->formats[GDK_MEMORY_U16].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_U16] = priv->formats[GDK_MEMORY_FLOAT32];
|
||||
|
||||
priv->has_present_region = physical_device_supports_extension (display->vk_physical_device,
|
||||
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
|
||||
priv->image_format = formats[i];
|
||||
priv->has_present_region = device_supports_incremental_present (display->vk_physical_device);
|
||||
|
||||
if (!gdk_vulkan_context_check_swapchain (context, error))
|
||||
goto out_surface;
|
||||
@@ -841,15 +740,6 @@ out_surface:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GdkMemoryFormat
|
||||
gdk_vulkan_context_get_offscreen_format (GdkVulkanContext *context,
|
||||
GdkMemoryDepth depth)
|
||||
{
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
|
||||
return priv->offscreen_formats[depth];
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_vulkan_context_initable_init (GInitableIface *iface)
|
||||
{
|
||||
@@ -938,216 +828,6 @@ gdk_vulkan_context_get_queue_family_index (GdkVulkanContext *context)
|
||||
return gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context))->vk_queue_family_index;
|
||||
}
|
||||
|
||||
static char *
|
||||
gdk_vulkan_get_pipeline_cache_dirname (void)
|
||||
{
|
||||
return g_build_filename (g_get_user_cache_dir (), "gtk-4.0", "vulkan-pipeline-cache", NULL);
|
||||
}
|
||||
|
||||
static GFile *
|
||||
gdk_vulkan_get_pipeline_cache_file (GdkDisplay *display)
|
||||
{
|
||||
VkPhysicalDeviceProperties props;
|
||||
char *dirname, *basename, *path;
|
||||
GFile *result;
|
||||
|
||||
vkGetPhysicalDeviceProperties (display->vk_physical_device, &props);
|
||||
|
||||
dirname = gdk_vulkan_get_pipeline_cache_dirname ();
|
||||
basename = g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x"
|
||||
"-%02x%02x%02x%02x%02x%02x.%u",
|
||||
props.pipelineCacheUUID[0], props.pipelineCacheUUID[1],
|
||||
props.pipelineCacheUUID[2], props.pipelineCacheUUID[3],
|
||||
props.pipelineCacheUUID[4], props.pipelineCacheUUID[5],
|
||||
props.pipelineCacheUUID[6], props.pipelineCacheUUID[7],
|
||||
props.pipelineCacheUUID[8], props.pipelineCacheUUID[9],
|
||||
props.pipelineCacheUUID[10], props.pipelineCacheUUID[11],
|
||||
props.pipelineCacheUUID[12], props.pipelineCacheUUID[13],
|
||||
props.pipelineCacheUUID[14], props.pipelineCacheUUID[15],
|
||||
props.driverVersion);
|
||||
|
||||
path = g_build_filename (dirname, basename, NULL);
|
||||
result = g_file_new_for_path (path);
|
||||
|
||||
g_free (path);
|
||||
g_free (basename);
|
||||
g_free (dirname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkPipelineCache
|
||||
gdk_display_load_pipeline_cache (GdkDisplay *display)
|
||||
{
|
||||
GError *error = NULL;
|
||||
VkPipelineCache result;
|
||||
GFile *cache_file;
|
||||
char *etag, *data;
|
||||
gsize size;
|
||||
|
||||
cache_file = gdk_vulkan_get_pipeline_cache_file (display);
|
||||
if (!g_file_load_contents (cache_file, NULL, &data, &size, &etag, &error))
|
||||
{
|
||||
GDK_DEBUG (VULKAN, "failed to load Vulkan pipeline cache file '%s': %s\n",
|
||||
g_file_peek_path (cache_file), error->message);
|
||||
g_object_unref (cache_file);
|
||||
g_clear_error (&error);
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (GDK_VK_CHECK (vkCreatePipelineCache, display->vk_device,
|
||||
&(VkPipelineCacheCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
|
||||
.initialDataSize = size,
|
||||
.pInitialData = data,
|
||||
},
|
||||
NULL,
|
||||
&result) != VK_SUCCESS)
|
||||
result = VK_NULL_HANDLE;
|
||||
|
||||
g_free (data);
|
||||
g_free (display->vk_pipeline_cache_etag);
|
||||
display->vk_pipeline_cache_etag = etag;
|
||||
display->vk_pipeline_cache_size = size;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_vulkan_save_pipeline_cache (GdkDisplay *display)
|
||||
{
|
||||
GError *error = NULL;
|
||||
VkDevice device;
|
||||
VkPipelineCache cache;
|
||||
GFile *file;
|
||||
char *path;
|
||||
size_t size;
|
||||
char *data, *etag;
|
||||
|
||||
device = display->vk_device;
|
||||
cache = display->vk_pipeline_cache;
|
||||
|
||||
GDK_VK_CHECK (vkGetPipelineCacheData, device, cache, &size, NULL);
|
||||
if (size == 0)
|
||||
return TRUE;
|
||||
|
||||
if (size == display->vk_pipeline_cache_size)
|
||||
{
|
||||
GDK_DEBUG (VULKAN, "pipeline cache size (%zu bytes) unchanged, skipping save", size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
data = g_malloc (size);
|
||||
if (GDK_VK_CHECK (vkGetPipelineCacheData, device, cache, &size, data) != VK_SUCCESS)
|
||||
{
|
||||
g_free (data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
path = gdk_vulkan_get_pipeline_cache_dirname ();
|
||||
if (g_mkdir_with_parents (path, 0755) != 0)
|
||||
{
|
||||
g_warning_once ("Failed to create pipeline cache directory");
|
||||
g_free (path);
|
||||
return FALSE;
|
||||
}
|
||||
g_free (path);
|
||||
|
||||
file = gdk_vulkan_get_pipeline_cache_file (display);
|
||||
|
||||
GDK_DEBUG (VULKAN, "Saving pipeline cache to %s", g_file_peek_path (file));
|
||||
|
||||
if (!g_file_replace_contents (file,
|
||||
data,
|
||||
size,
|
||||
display->vk_pipeline_cache_etag,
|
||||
FALSE,
|
||||
0,
|
||||
&etag,
|
||||
NULL,
|
||||
&error))
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WRONG_ETAG))
|
||||
{
|
||||
VkPipelineCache new_cache;
|
||||
|
||||
GDK_DEBUG (VULKAN, "Pipeline cache file modified, merging into current");
|
||||
new_cache = gdk_display_load_pipeline_cache (display);
|
||||
if (new_cache)
|
||||
{
|
||||
GDK_VK_CHECK (vkMergePipelineCaches, device, cache, 1, &new_cache);
|
||||
vkDestroyPipelineCache (device, new_cache, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_clear_pointer (&display->vk_pipeline_cache_etag, g_free);
|
||||
}
|
||||
g_clear_error (&error);
|
||||
g_object_unref (file);
|
||||
|
||||
/* try again */
|
||||
return gdk_vulkan_save_pipeline_cache (display);
|
||||
}
|
||||
|
||||
g_warning ("Failed to save pipeline cache: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
g_object_unref (file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
g_free (display->vk_pipeline_cache_etag);
|
||||
display->vk_pipeline_cache_etag = etag;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_vulkan_save_pipeline_cache_cb (gpointer data)
|
||||
{
|
||||
GdkDisplay *display = data;
|
||||
|
||||
gdk_vulkan_save_pipeline_cache (display);
|
||||
|
||||
display->vk_save_pipeline_cache_source = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_vulkan_context_pipeline_cache_updated (GdkVulkanContext *self)
|
||||
{
|
||||
GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (self));
|
||||
|
||||
g_clear_handle_id (&display->vk_save_pipeline_cache_source, g_source_remove);
|
||||
display->vk_save_pipeline_cache_source = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE - 10,
|
||||
10, /* random choice that is not now */
|
||||
gdk_vulkan_save_pipeline_cache_cb,
|
||||
display,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_create_pipeline_cache (GdkDisplay *display)
|
||||
{
|
||||
display->vk_pipeline_cache = gdk_display_load_pipeline_cache (display);
|
||||
|
||||
GDK_VK_CHECK (vkCreatePipelineCache, display->vk_device,
|
||||
&(VkPipelineCacheCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
|
||||
},
|
||||
NULL,
|
||||
&display->vk_pipeline_cache);
|
||||
}
|
||||
|
||||
VkPipelineCache
|
||||
gdk_vulkan_context_get_pipeline_cache (GdkVulkanContext *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (self), NULL);
|
||||
|
||||
return gdk_draw_context_get_display (GDK_DRAW_CONTEXT (self))->vk_pipeline_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_vulkan_context_get_image_format:
|
||||
* @context: a `GdkVulkanContext`
|
||||
@@ -1163,7 +843,7 @@ gdk_vulkan_context_get_image_format (GdkVulkanContext *context)
|
||||
|
||||
g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), VK_FORMAT_UNDEFINED);
|
||||
|
||||
return priv->formats[priv->current_format].vk_format.format;
|
||||
return priv->image_format.format;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1359,10 +1039,6 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
for (i = first; i < last; i++)
|
||||
{
|
||||
uint32_t n_queue_props;
|
||||
|
||||
if (!physical_device_supports_extension (devices[i], VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
|
||||
continue;
|
||||
|
||||
vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, NULL);
|
||||
VkQueueFamilyProperties *queue_props = g_newa (VkQueueFamilyProperties, n_queue_props);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, queue_props);
|
||||
@@ -1373,36 +1049,30 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
GPtrArray *device_extensions;
|
||||
gboolean has_incremental_present;
|
||||
|
||||
has_incremental_present = physical_device_supports_extension (devices[i],
|
||||
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
|
||||
has_incremental_present = device_supports_incremental_present (devices[i]);
|
||||
|
||||
device_extensions = g_ptr_array_new ();
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
if (has_incremental_present)
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
|
||||
|
||||
GDK_DISPLAY_DEBUG (display, VULKAN, "Using Vulkan device %u, queue %u", i, j);
|
||||
if (GDK_VK_CHECK (vkCreateDevice, devices[i],
|
||||
&(VkDeviceCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &(VkDeviceQueueCreateInfo) {
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
NULL,
|
||||
0,
|
||||
1,
|
||||
&(VkDeviceQueueCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||
.queueFamilyIndex = j,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = (float []) { 1.0f },
|
||||
},
|
||||
.enabledExtensionCount = device_extensions->len,
|
||||
.ppEnabledExtensionNames = (const char * const *) device_extensions->pdata,
|
||||
.pNext = &(VkPhysicalDeviceDescriptorIndexingFeatures) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
|
||||
.descriptorBindingPartiallyBound = VK_TRUE,
|
||||
.descriptorBindingVariableDescriptorCount = VK_TRUE,
|
||||
.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE,
|
||||
.descriptorBindingStorageBufferUpdateAfterBind = VK_TRUE,
|
||||
}
|
||||
0,
|
||||
NULL,
|
||||
device_extensions->len,
|
||||
(const char * const *) device_extensions->pdata
|
||||
},
|
||||
NULL,
|
||||
&display->vk_device) != VK_SUCCESS)
|
||||
@@ -1474,7 +1144,6 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
|
||||
used_extensions = g_ptr_array_new ();
|
||||
g_ptr_array_add (used_extensions, (gpointer) VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
g_ptr_array_add (used_extensions, (gpointer) VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
g_ptr_array_add (used_extensions, (gpointer) GDK_DISPLAY_GET_CLASS (display)->vk_extension_name);
|
||||
|
||||
for (i = 0; i < n_extensions; i++)
|
||||
@@ -1546,7 +1215,7 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
.enabledLayerCount = used_layers->len,
|
||||
.ppEnabledLayerNames = (const char * const *) used_layers->pdata,
|
||||
.enabledExtensionCount = used_extensions->len,
|
||||
.ppEnabledExtensionNames = (const char * const *) used_extensions->pdata,
|
||||
.ppEnabledExtensionNames = (const char * const *) used_extensions->pdata
|
||||
},
|
||||
NULL,
|
||||
&display->vk_instance);
|
||||
@@ -1598,10 +1267,6 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gdk_display_create_pipeline_cache (display);
|
||||
|
||||
display->vk_shader_modules = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1623,9 +1288,6 @@ gdk_display_ref_vulkan (GdkDisplay *display,
|
||||
void
|
||||
gdk_display_unref_vulkan (GdkDisplay *display)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
g_return_if_fail (display->vulkan_refcount > 0);
|
||||
|
||||
@@ -1633,26 +1295,6 @@ gdk_display_unref_vulkan (GdkDisplay *display)
|
||||
if (display->vulkan_refcount > 0)
|
||||
return;
|
||||
|
||||
display->vk_shader_modules = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
g_hash_table_iter_init (&iter, display->vk_shader_modules);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
g_free (key);
|
||||
vkDestroyShaderModule (display->vk_device,
|
||||
value,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (display->vk_save_pipeline_cache_source)
|
||||
{
|
||||
gdk_vulkan_save_pipeline_cache_cb (display);
|
||||
g_assert (display->vk_save_pipeline_cache_source == 0);
|
||||
}
|
||||
vkDestroyPipelineCache (display->vk_device, display->vk_pipeline_cache, NULL);
|
||||
display->vk_device = VK_NULL_HANDLE;
|
||||
g_clear_pointer (&display->vk_pipeline_cache_etag, g_free);
|
||||
display->vk_pipeline_cache_size = 0;
|
||||
|
||||
vkDestroyDevice (display->vk_device, NULL);
|
||||
display->vk_device = VK_NULL_HANDLE;
|
||||
if (display->vk_debug_callback != VK_NULL_HANDLE)
|
||||
@@ -1669,47 +1311,6 @@ gdk_display_unref_vulkan (GdkDisplay *display)
|
||||
display->vk_instance = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VkShaderModule
|
||||
gdk_display_get_vk_shader_module (GdkDisplay *self,
|
||||
const char *resource_name)
|
||||
{
|
||||
VkShaderModule shader;
|
||||
GError *error = NULL;
|
||||
GBytes *bytes;
|
||||
|
||||
shader = g_hash_table_lookup (self->vk_shader_modules, resource_name);
|
||||
if (shader)
|
||||
return shader;
|
||||
|
||||
bytes = g_resources_lookup_data (resource_name, 0, &error);
|
||||
if (bytes == NULL)
|
||||
{
|
||||
GDK_DEBUG (VULKAN, "Error loading shader data: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (GDK_VK_CHECK (vkCreateShaderModule, self->vk_device,
|
||||
&(VkShaderModuleCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.codeSize = g_bytes_get_size (bytes),
|
||||
.pCode = (uint32_t *) g_bytes_get_data (bytes, NULL),
|
||||
},
|
||||
NULL,
|
||||
&shader) == VK_SUCCESS)
|
||||
{
|
||||
g_hash_table_insert (self->vk_shader_modules, g_strdup (resource_name), shader);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
#else /* GDK_RENDERING_VULKAN */
|
||||
|
||||
static void
|
||||
|
||||
@@ -69,18 +69,9 @@ gdk_vulkan_handle_result (VkResult res,
|
||||
|
||||
#define GDK_VK_CHECK(func, ...) gdk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func))
|
||||
|
||||
gboolean gdk_display_ref_vulkan (GdkDisplay *display,
|
||||
GError **error);
|
||||
void gdk_display_unref_vulkan (GdkDisplay *display);
|
||||
|
||||
VkShaderModule gdk_display_get_vk_shader_module (GdkDisplay *display,
|
||||
const char *resource_name);
|
||||
|
||||
VkPipelineCache gdk_vulkan_context_get_pipeline_cache (GdkVulkanContext *self);
|
||||
void gdk_vulkan_context_pipeline_cache_updated (GdkVulkanContext *self);
|
||||
|
||||
GdkMemoryFormat gdk_vulkan_context_get_offscreen_format (GdkVulkanContext *context,
|
||||
GdkMemoryDepth depth);
|
||||
gboolean gdk_display_ref_vulkan (GdkDisplay *display,
|
||||
GError **error);
|
||||
void gdk_display_unref_vulkan (GdkDisplay *display);
|
||||
|
||||
#else /* !GDK_RENDERING_VULKAN */
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ copy_surface_data (GdkMacosBuffer *from,
|
||||
|
||||
static void
|
||||
_gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
|
||||
|
||||
@@ -480,7 +480,7 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context,
|
||||
|
||||
static void
|
||||
gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
|
||||
|
||||
@@ -207,7 +207,7 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
{
|
||||
char *path;
|
||||
XcursorImages *images;
|
||||
struct wl_cursor *cursor;
|
||||
struct cursor *cursor;
|
||||
struct cursor_image *image;
|
||||
int i, nbytes;
|
||||
unsigned int load_size;
|
||||
@@ -240,16 +240,17 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor->images =
|
||||
malloc(images->nimage * sizeof cursor->images[0]);
|
||||
if (!cursor->images) {
|
||||
cursor->cursor.images =
|
||||
malloc(images->nimage * sizeof cursor->cursor.images[0]);
|
||||
if (!cursor->cursor.images) {
|
||||
free(cursor);
|
||||
xcursor_images_destroy (images);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor->name = strdup(name);
|
||||
cursor->size = load_size;
|
||||
cursor->cursor.name = strdup(name);
|
||||
cursor->cursor.size = load_size;
|
||||
cursor->total_delay = 0;
|
||||
|
||||
for (i = 0; i < images->nimage; i++) {
|
||||
image = malloc(sizeof *image);
|
||||
@@ -290,13 +291,14 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor->images[i] = (struct wl_cursor_image *) image;
|
||||
cursor->total_delay += image->image.delay;
|
||||
cursor->cursor.images[i] = (struct wl_cursor_image *) image;
|
||||
}
|
||||
cursor->image_count = i;
|
||||
cursor->cursor.image_count = i;
|
||||
|
||||
if (cursor->image_count == 0) {
|
||||
free(cursor->name);
|
||||
free(cursor->images);
|
||||
if (cursor->cursor.image_count == 0) {
|
||||
free(cursor->cursor.name);
|
||||
free(cursor->cursor.images);
|
||||
free(cursor);
|
||||
xcursor_images_destroy (images);
|
||||
return NULL;
|
||||
@@ -304,7 +306,7 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
|
||||
xcursor_images_destroy (images);
|
||||
|
||||
return cursor;
|
||||
return &cursor->cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -145,7 +145,7 @@ gdk_wayland_cairo_context_create_surface (GdkWaylandCairoContext *self)
|
||||
|
||||
static void
|
||||
gdk_wayland_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (draw_context);
|
||||
|
||||
@@ -698,36 +698,7 @@ gdk_wayland_display_dispose (GObject *object)
|
||||
|
||||
g_list_free_full (display_wayland->on_has_globals_closures, g_free);
|
||||
|
||||
g_clear_pointer (&display_wayland->cursor_theme, wl_cursor_theme_destroy);
|
||||
g_clear_pointer (&display_wayland->compositor, wl_compositor_destroy);
|
||||
g_clear_pointer (&display_wayland->xdg_wm_base, xdg_wm_base_destroy);
|
||||
g_clear_pointer (&display_wayland->zxdg_shell_v6, zxdg_shell_v6_destroy);
|
||||
g_clear_pointer (&display_wayland->gtk_shell, gtk_shell1_destroy);
|
||||
g_clear_pointer (&display_wayland->data_device_manager, wl_data_device_manager_destroy);
|
||||
g_clear_pointer (&display_wayland->subcompositor, wl_subcompositor_destroy);
|
||||
g_clear_pointer (&display_wayland->pointer_gestures, zwp_pointer_gestures_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->primary_selection_manager, zwp_primary_selection_device_manager_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->tablet_manager, zwp_tablet_manager_v2_destroy);
|
||||
g_clear_pointer (&display_wayland->xdg_exporter, zxdg_exporter_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->xdg_exporter_v2, zxdg_exporter_v2_destroy);
|
||||
g_clear_pointer (&display_wayland->xdg_importer, zxdg_importer_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->xdg_importer_v2, zxdg_importer_v2_destroy);
|
||||
g_clear_pointer (&display_wayland->keyboard_shortcuts_inhibit, zwp_keyboard_shortcuts_inhibit_manager_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->server_decoration_manager, org_kde_kwin_server_decoration_manager_destroy);
|
||||
g_clear_pointer (&display_wayland->xdg_output_manager, zxdg_output_manager_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->idle_inhibit_manager, zwp_idle_inhibit_manager_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->xdg_activation, xdg_activation_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->fractional_scale, wp_fractional_scale_manager_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->viewporter, wp_viewporter_destroy);
|
||||
|
||||
g_clear_pointer (&display_wayland->shm, wl_shm_destroy);
|
||||
g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy);
|
||||
|
||||
g_list_store_remove_all (display_wayland->monitors);
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_display_parent_class)->dispose (object);
|
||||
|
||||
g_clear_pointer (&display_wayland->wl_display, wl_display_disconnect);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -737,17 +708,22 @@ gdk_wayland_display_finalize (GObject *object)
|
||||
|
||||
_gdk_wayland_display_finalize_cursors (display_wayland);
|
||||
|
||||
g_object_unref (display_wayland->monitors);
|
||||
|
||||
g_free (display_wayland->startup_notification_id);
|
||||
g_free (display_wayland->cursor_theme_name);
|
||||
xkb_context_unref (display_wayland->xkb_context);
|
||||
|
||||
g_clear_pointer (&display_wayland->cursor_theme, wl_cursor_theme_destroy);
|
||||
|
||||
g_list_store_remove_all (display_wayland->monitors);
|
||||
g_object_unref (display_wayland->monitors);
|
||||
|
||||
if (display_wayland->settings)
|
||||
g_hash_table_destroy (display_wayland->settings);
|
||||
|
||||
g_clear_object (&display_wayland->settings_portal);
|
||||
|
||||
wl_display_disconnect (display_wayland->wl_display);
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_display_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ struct _GdkWaylandDisplay
|
||||
struct xdg_wm_base *xdg_wm_base;
|
||||
struct zxdg_shell_v6 *zxdg_shell_v6;
|
||||
struct gtk_shell1 *gtk_shell;
|
||||
struct wl_input_device *input_device;
|
||||
struct wl_data_device_manager *data_device_manager;
|
||||
struct wl_subcompositor *subcompositor;
|
||||
struct zwp_pointer_gestures_v1 *pointer_gestures;
|
||||
|
||||
@@ -48,12 +48,12 @@ G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
|
||||
|
||||
static void
|
||||
gdk_wayland_gl_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
gdk_wayland_surface_ensure_wl_egl_window (gdk_draw_context_get_surface (draw_context));
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, depth, region);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, prefers_high_depth, region);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -2143,13 +2143,10 @@ _gdk_wayland_seat_remove_tablet_pad (GdkWaylandSeat *seat,
|
||||
{
|
||||
seat->tablet_pads = g_list_remove (seat->tablet_pads, pad);
|
||||
|
||||
if (pad->device)
|
||||
{
|
||||
gdk_seat_device_removed (GDK_SEAT (seat), pad->device);
|
||||
_gdk_device_set_associated_device (pad->device, NULL);
|
||||
g_object_unref (pad->device);
|
||||
}
|
||||
gdk_seat_device_removed (GDK_SEAT (seat), pad->device);
|
||||
_gdk_device_set_associated_device (pad->device, NULL);
|
||||
|
||||
g_object_unref (pad->device);
|
||||
g_free (pad);
|
||||
}
|
||||
|
||||
@@ -3064,9 +3061,9 @@ tablet_tool_handle_button (void *data,
|
||||
tablet->pointer_info.press_serial = serial;
|
||||
|
||||
if (button == BTN_STYLUS)
|
||||
n_button = GDK_BUTTON_MIDDLE;
|
||||
else if (button == BTN_STYLUS2)
|
||||
n_button = GDK_BUTTON_SECONDARY;
|
||||
else if (button == BTN_STYLUS2)
|
||||
n_button = GDK_BUTTON_MIDDLE;
|
||||
else if (button == BTN_STYLUS3)
|
||||
n_button = 8; /* Back */
|
||||
else
|
||||
@@ -3538,10 +3535,21 @@ static void
|
||||
tablet_pad_handle_done (void *data,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad)
|
||||
{
|
||||
G_GNUC_UNUSED GdkWaylandTabletPadData *pad = data;
|
||||
GdkWaylandTabletPadData *pad = data;
|
||||
|
||||
GDK_SEAT_DEBUG (pad->seat, EVENTS,
|
||||
"tablet pad handle done, pad = %p", wp_tablet_pad);
|
||||
|
||||
pad->device =
|
||||
g_object_new (GDK_TYPE_WAYLAND_DEVICE_PAD,
|
||||
"name", "Pad device",
|
||||
"source", GDK_SOURCE_TABLET_PAD,
|
||||
"display", gdk_seat_get_display (pad->seat),
|
||||
"seat", pad->seat,
|
||||
NULL);
|
||||
|
||||
_gdk_device_set_associated_device (pad->device, GDK_WAYLAND_SEAT (pad->seat)->logical_keyboard);
|
||||
gdk_seat_device_added (GDK_SEAT (pad->seat), pad->device);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3598,44 +3606,9 @@ tablet_pad_handle_enter (void *data,
|
||||
"tablet pad handle enter, pad = %p, tablet = %p surface = %p",
|
||||
wp_tablet_pad, wp_tablet, surface);
|
||||
|
||||
if (pad->device && pad->current_tablet != tablet)
|
||||
{
|
||||
gdk_seat_device_removed (GDK_SEAT (pad->seat), pad->device);
|
||||
_gdk_device_set_associated_device (pad->device, NULL);
|
||||
g_clear_object (&pad->device);
|
||||
}
|
||||
|
||||
/* Relate pad and tablet */
|
||||
tablet->pads = g_list_prepend (tablet->pads, pad);
|
||||
pad->current_tablet = tablet;
|
||||
|
||||
if (!pad->device)
|
||||
{
|
||||
gchar *name, *vid, *pid;
|
||||
|
||||
name = g_strdup_printf ("%s Pad %d",
|
||||
tablet->name,
|
||||
g_list_index (tablet->pads, pad) + 1);
|
||||
vid = g_strdup_printf ("%.4x", tablet->vid);
|
||||
pid = g_strdup_printf ("%.4x", tablet->pid);
|
||||
|
||||
pad->device =
|
||||
g_object_new (GDK_TYPE_WAYLAND_DEVICE_PAD,
|
||||
"name", name,
|
||||
"vendor-id", vid,
|
||||
"product-id", pid,
|
||||
"source", GDK_SOURCE_TABLET_PAD,
|
||||
"display", gdk_seat_get_display (pad->seat),
|
||||
"seat", pad->seat,
|
||||
NULL);
|
||||
|
||||
_gdk_device_set_associated_device (pad->device, GDK_WAYLAND_SEAT (pad->seat)->logical_keyboard);
|
||||
gdk_seat_device_added (GDK_SEAT (pad->seat), pad->device);
|
||||
|
||||
g_free (name);
|
||||
g_free (vid);
|
||||
g_free (pid);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3651,7 +3624,10 @@ tablet_pad_handle_leave (void *data,
|
||||
wp_tablet_pad, surface);
|
||||
|
||||
if (pad->current_tablet)
|
||||
pad->current_tablet->pads = g_list_remove (pad->current_tablet->pads, pad);
|
||||
{
|
||||
pad->current_tablet->pads = g_list_remove (pad->current_tablet->pads, pad);
|
||||
pad->current_tablet = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3899,23 +3875,6 @@ gdk_wayland_pointer_data_finalize (GdkWaylandPointerData *pointer)
|
||||
g_slist_free (pointer->pointer_surface_outputs);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_seat_dispose (GObject *object)
|
||||
{
|
||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (object);
|
||||
|
||||
g_clear_pointer (&seat->wl_seat, wl_seat_destroy);
|
||||
g_clear_pointer (&seat->wl_pointer, wl_pointer_destroy);
|
||||
g_clear_pointer (&seat->wl_keyboard, wl_keyboard_destroy);
|
||||
g_clear_pointer (&seat->wl_touch, wl_touch_destroy);
|
||||
g_clear_pointer (&seat->wp_pointer_gesture_swipe, zwp_pointer_gesture_swipe_v1_destroy);
|
||||
g_clear_pointer (&seat->wp_pointer_gesture_pinch, zwp_pointer_gesture_pinch_v1_destroy);
|
||||
g_clear_pointer (&seat->wp_pointer_gesture_hold, zwp_pointer_gesture_hold_v1_destroy);
|
||||
g_clear_pointer (&seat->wp_tablet_seat, zwp_tablet_seat_v2_destroy);
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_seat_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_seat_finalize (GObject *object)
|
||||
{
|
||||
@@ -4230,7 +4189,6 @@ gdk_wayland_seat_class_init (GdkWaylandSeatClass *klass)
|
||||
GdkSeatClass *seat_class = GDK_SEAT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gdk_wayland_seat_finalize;
|
||||
object_class->dispose = gdk_wayland_seat_dispose;
|
||||
|
||||
seat_class->get_capabilities = gdk_wayland_seat_get_capabilities;
|
||||
seat_class->grab = gdk_wayland_seat_grab;
|
||||
|
||||
@@ -53,7 +53,7 @@ create_cairo_surface_for_surface (GdkSurface *surface,
|
||||
|
||||
static void
|
||||
gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkWin32CairoContext *self = GDK_WIN32_CAIRO_CONTEXT (draw_context);
|
||||
|
||||
+15
-23
@@ -139,6 +139,7 @@ static GSourceFuncs event_funcs = {
|
||||
|
||||
static GdkSurface *mouse_window = NULL;
|
||||
static GdkSurface *mouse_window_ignored_leave = NULL;
|
||||
static int current_x, current_y;
|
||||
static int current_root_x, current_root_y;
|
||||
|
||||
static UINT got_gdk_events_message;
|
||||
@@ -1521,15 +1522,14 @@ generate_button_event (GdkEventType type,
|
||||
GdkEvent *event;
|
||||
GdkDeviceManagerWin32 *device_manager;
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (window);
|
||||
double x, y;
|
||||
|
||||
if (_gdk_input_ignore_core > 0)
|
||||
return;
|
||||
|
||||
device_manager = GDK_DEVICE_MANAGER_WIN32 (_gdk_device_manager);
|
||||
|
||||
x = (double) GET_X_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
y = (double) GET_Y_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
current_x = (gint16) GET_X_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
current_y = (gint16) GET_Y_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
|
||||
_gdk_device_virtual_set_active (_gdk_device_manager->core_pointer,
|
||||
_gdk_device_manager->system_pointer);
|
||||
@@ -1541,10 +1541,10 @@ generate_button_event (GdkEventType type,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
build_pointer_event_state (msg),
|
||||
button,
|
||||
x,
|
||||
y,
|
||||
current_x,
|
||||
current_y,
|
||||
NULL);
|
||||
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
}
|
||||
|
||||
@@ -2350,19 +2350,19 @@ gdk_event_translate (MSG *msg,
|
||||
* sends WM_MOUSEMOVE messages after a new window is shown under
|
||||
* the mouse, even if the mouse hasn't moved. This disturbs gtk.
|
||||
*/
|
||||
if (msg->pt.x == current_root_x &&
|
||||
msg->pt.y == current_root_y)
|
||||
if (msg->pt.x / impl->surface_scale == current_root_x &&
|
||||
msg->pt.y / impl->surface_scale == current_root_y)
|
||||
break;
|
||||
|
||||
current_root_x = msg->pt.x;
|
||||
current_root_y = msg->pt.y;
|
||||
current_root_x = msg->pt.x / impl->surface_scale;
|
||||
current_root_y = msg->pt.y / impl->surface_scale;
|
||||
|
||||
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
|
||||
gdk_win32_surface_do_move_resize_drag (window, msg->pt.x, msg->pt.y);
|
||||
gdk_win32_surface_do_move_resize_drag (window, current_root_x, current_root_y);
|
||||
else if (_gdk_input_ignore_core == 0)
|
||||
{
|
||||
double x = (double) GET_X_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
double y = (double) GET_Y_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
current_x = (gint16) GET_X_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
current_y = (gint16) GET_Y_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
|
||||
_gdk_device_virtual_set_active (_gdk_device_manager->core_pointer,
|
||||
_gdk_device_manager->system_pointer);
|
||||
@@ -2372,8 +2372,8 @@ gdk_event_translate (MSG *msg,
|
||||
NULL,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
build_pointer_event_state (msg),
|
||||
x,
|
||||
y,
|
||||
current_x,
|
||||
current_y,
|
||||
NULL);
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
@@ -2734,10 +2734,6 @@ gdk_event_translate (MSG *msg,
|
||||
if (GDK_IS_DRAG_SURFACE (window) ||
|
||||
_gdk_modal_blocked (window))
|
||||
{
|
||||
/* Focus the modal window */
|
||||
GdkSurface *modal_window = _gdk_modal_current ();
|
||||
if (modal_window != NULL)
|
||||
SetFocus (GDK_SURFACE_HWND (modal_window));
|
||||
*ret_valp = MA_NOACTIVATE;
|
||||
return_val = TRUE;
|
||||
}
|
||||
@@ -2748,10 +2744,6 @@ gdk_event_translate (MSG *msg,
|
||||
if (GDK_IS_DRAG_SURFACE (window) ||
|
||||
_gdk_modal_blocked (window))
|
||||
{
|
||||
/* Focus the modal window */
|
||||
GdkSurface *modal_window = _gdk_modal_current ();
|
||||
if (modal_window != NULL)
|
||||
SetFocus (GDK_SURFACE_HWND (modal_window));
|
||||
*ret_valp = PA_NOACTIVATE;
|
||||
return_val = TRUE;
|
||||
}
|
||||
|
||||
@@ -109,12 +109,12 @@ gdk_win32_gl_context_egl_end_frame (GdkDrawContext *draw_context,
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *update_area)
|
||||
{
|
||||
gdk_win32_surface_handle_queued_move_resize (draw_context);
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, depth, update_area);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, prefers_high_depth, update_area);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -118,12 +118,12 @@ gdk_win32_gl_context_wgl_end_frame (GdkDrawContext *draw_context,
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *update_area)
|
||||
{
|
||||
gdk_win32_surface_handle_queued_move_resize (draw_context);
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, depth, update_area);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, prefers_high_depth, update_area);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -271,10 +271,9 @@ winpointer_make_event (GdkDeviceWinpointer *device,
|
||||
y /= impl->surface_scale;
|
||||
|
||||
state = 0;
|
||||
/* Note that info->dwKeyStates is not reliable, use GetKeyState() */
|
||||
if (GetKeyState (VK_CONTROL) < 0)
|
||||
if (info->dwKeyStates & POINTER_MOD_CTRL)
|
||||
state |= GDK_CONTROL_MASK;
|
||||
if (GetKeyState (VK_SHIFT) < 0)
|
||||
if (info->dwKeyStates & POINTER_MOD_SHIFT)
|
||||
state |= GDK_SHIFT_MASK;
|
||||
if (GetKeyState (VK_MENU) < 0)
|
||||
state |= GDK_ALT_MASK;
|
||||
|
||||
@@ -725,7 +725,11 @@ show_window_internal (GdkSurface *window,
|
||||
|
||||
if (center)
|
||||
{
|
||||
GetWindowRect (GDK_SURFACE_HWND (window), &window_rect);
|
||||
window_rect.left = 0;
|
||||
window_rect.top = 0;
|
||||
window_rect.right = window->width * surface->surface_scale;
|
||||
window_rect.bottom = window->height * surface->surface_scale;
|
||||
_gdk_win32_adjust_client_rect (window, &window_rect);
|
||||
|
||||
x = center_on_rect.left + ((center_on_rect.right - center_on_rect.left) - (window_rect.right - window_rect.left)) / 2;
|
||||
y = center_on_rect.top + ((center_on_rect.bottom - center_on_rect.top) - (window_rect.bottom - window_rect.top)) / 2;
|
||||
@@ -3535,8 +3539,6 @@ setup_drag_move_resize_context (GdkSurface *surface,
|
||||
context->button = button;
|
||||
context->start_root_x = root_x;
|
||||
context->start_root_y = root_y;
|
||||
context->current_root_x = root_x;
|
||||
context->current_root_y = root_y;
|
||||
context->timestamp = timestamp;
|
||||
context->start_rect = rect;
|
||||
|
||||
@@ -3652,16 +3654,6 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
|
||||
if (!_gdk_win32_get_window_rect (window, &rect))
|
||||
return;
|
||||
|
||||
x /= impl->surface_scale;
|
||||
y /= impl->surface_scale;
|
||||
|
||||
if (context->current_root_x == x &&
|
||||
context->current_root_y == y)
|
||||
return;
|
||||
|
||||
context->current_root_x = x;
|
||||
context->current_root_y = y;
|
||||
|
||||
new_rect = context->start_rect;
|
||||
diffx = (x - context->start_root_x) * impl->surface_scale;
|
||||
diffy = (y - context->start_root_y) * impl->surface_scale;
|
||||
|
||||
@@ -137,12 +137,6 @@ struct _GdkW32DragMoveResizeContext
|
||||
int start_root_x;
|
||||
int start_root_y;
|
||||
|
||||
/* Last processed cursor position. Values are divided by the window
|
||||
* scale.
|
||||
*/
|
||||
int current_root_x;
|
||||
int current_root_y;
|
||||
|
||||
/* Initial window rectangle (position and size).
|
||||
* The window is resized/moved relative to this (see start_root_*).
|
||||
*/
|
||||
|
||||
@@ -66,12 +66,12 @@ gdk_win32_vulkan_context_create_surface (GdkVulkanContext *context,
|
||||
|
||||
static void
|
||||
gdk_win32_vulkan_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *update_area)
|
||||
{
|
||||
gdk_win32_surface_handle_queued_move_resize (draw_context);
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_vulkan_context_parent_class)->begin_frame (draw_context, depth, update_area);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_vulkan_context_parent_class)->begin_frame (draw_context, prefers_high_depth, update_area);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -55,7 +55,7 @@ create_cairo_surface_for_surface (GdkSurface *surface)
|
||||
|
||||
static void
|
||||
gdk_x11_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkX11CairoContext *self = GDK_X11_CAIRO_CONTEXT (draw_context);
|
||||
|
||||
+24
-36
@@ -549,6 +549,8 @@ gdk_x11_context_create_glx_context (GdkGLContext *context,
|
||||
context_attribs [major_idx] = gdk_gl_version_get_major (&supported_versions[j]);
|
||||
context_attribs [minor_idx] = gdk_gl_version_get_minor (&supported_versions[j]);
|
||||
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
|
||||
/* If we don't have access to GLX_ARB_create_context_profile, then
|
||||
* we have to fall back to the old GLX 1.3 API.
|
||||
*/
|
||||
@@ -566,16 +568,19 @@ gdk_x11_context_create_glx_context (GdkGLContext *context,
|
||||
True,
|
||||
context_attribs);
|
||||
|
||||
if (ctx != NULL)
|
||||
if (ctx == NULL)
|
||||
{
|
||||
gdk_x11_display_error_trap_pop_ignored (display);
|
||||
}
|
||||
else if (gdk_x11_display_error_trap_pop (display))
|
||||
{
|
||||
glXDestroyContext (dpy, ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctx == NULL)
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (display, OPENGL, "Failed to create a GLX context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
GDK_DISPLAY_DEBUG (display, OPENGL,
|
||||
"Realized GLX context[%p], %s, version: %d.%d",
|
||||
context_glx->glx_context,
|
||||
@@ -656,42 +661,25 @@ gdk_x11_gl_context_glx_realize (GdkGLContext *context,
|
||||
if (share != NULL && gdk_gl_context_is_legacy (share))
|
||||
legacy = TRUE;
|
||||
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
|
||||
/* Increase XNextRequest because GLX may fake errors with the last request
|
||||
* and we want the error trap to catch them */
|
||||
XChangeWindowAttributes (GDK_DISPLAY_XDISPLAY (display),
|
||||
GDK_X11_DISPLAY (display)->leader_window,
|
||||
0,
|
||||
(XSetWindowAttributes[1]) { 0, });
|
||||
|
||||
if (preferred_api == GDK_GL_API_GL)
|
||||
{
|
||||
api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, legacy);
|
||||
if (api == 0)
|
||||
api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GLES, legacy);
|
||||
if (api == 0)
|
||||
api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, TRUE);
|
||||
if ((api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, legacy)) ||
|
||||
(api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GLES, legacy)) ||
|
||||
(api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, TRUE)))
|
||||
return api;
|
||||
}
|
||||
else
|
||||
{
|
||||
api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GLES, FALSE);
|
||||
if (api == 0)
|
||||
api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, legacy);
|
||||
if (api == 0)
|
||||
api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, TRUE);
|
||||
if ((api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GLES, FALSE)) ||
|
||||
(api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, legacy)) ||
|
||||
(api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, TRUE)))
|
||||
return api;
|
||||
}
|
||||
|
||||
gdk_x11_display_error_trap_pop_ignored (display);
|
||||
|
||||
if (api == 0)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Unable to create a GL context"));
|
||||
}
|
||||
|
||||
return api;
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Unable to create a GL context"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef N_GLX_ATTRS
|
||||
|
||||
+4
-4
@@ -165,7 +165,7 @@ void half_to_float4 (const guint16 h[4], float f[4]) __attribute__((ifunc ("reso
|
||||
void float_to_half (const float *f, guint16 *h, int n) __attribute__((ifunc ("resolve_float_to_half")));
|
||||
void half_to_float (const guint16 *h, float *f, int n) __attribute__((ifunc ("resolve_half_to_float")));
|
||||
|
||||
static void * __attribute__ ((no_sanitize_address))
|
||||
static void *
|
||||
resolve_float_to_half4 (void)
|
||||
{
|
||||
__builtin_cpu_init ();
|
||||
@@ -175,7 +175,7 @@ resolve_float_to_half4 (void)
|
||||
return float_to_half4_c;
|
||||
}
|
||||
|
||||
static void * __attribute__ ((no_sanitize_address))
|
||||
static void *
|
||||
resolve_half_to_float4 (void)
|
||||
{
|
||||
__builtin_cpu_init ();
|
||||
@@ -185,7 +185,7 @@ resolve_half_to_float4 (void)
|
||||
return half_to_float4_c;
|
||||
}
|
||||
|
||||
static void * __attribute__ ((no_sanitize_address))
|
||||
static void *
|
||||
resolve_float_to_half (void)
|
||||
{
|
||||
__builtin_cpu_init ();
|
||||
@@ -195,7 +195,7 @@ resolve_float_to_half (void)
|
||||
return float_to_half_c;
|
||||
}
|
||||
|
||||
static void * __attribute__ ((no_sanitize_address))
|
||||
static void *
|
||||
resolve_half_to_float (void)
|
||||
{
|
||||
__builtin_cpu_init ();
|
||||
|
||||
@@ -1458,9 +1458,6 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
guint *gl_type,
|
||||
GLint (*gl_swizzle)[4])
|
||||
{
|
||||
GdkMemoryDepth depth;
|
||||
|
||||
/* First, try the format itself */
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
@@ -1472,48 +1469,7 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
gdk_memory_format_alpha (data_format) != GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
return data_format;
|
||||
|
||||
depth = gdk_memory_format_get_depth (data_format);
|
||||
|
||||
/* Next, try the generic format for the given bit depth */
|
||||
switch (depth)
|
||||
{
|
||||
case GDK_MEMORY_FLOAT16:
|
||||
data_format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
gl_swizzle))
|
||||
return data_format;
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_U16:
|
||||
data_format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
gl_swizzle))
|
||||
return data_format;
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_FLOAT32:
|
||||
case GDK_MEMORY_U8:
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the format is high depth, also try float32 */
|
||||
if (depth != GDK_MEMORY_U8)
|
||||
if (gdk_memory_format_prefers_high_depth (data_format))
|
||||
{
|
||||
data_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
@@ -1527,7 +1483,6 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
return data_format;
|
||||
}
|
||||
|
||||
/* If all else fails, pick the one format that's always supported */
|
||||
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
if (!gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
|
||||
+5
-14
@@ -32,7 +32,6 @@
|
||||
#include "gskglcommandqueueprivate.h"
|
||||
#include "gskglcompilerprivate.h"
|
||||
#include "gskglglyphlibraryprivate.h"
|
||||
#include "gskglglyphylibraryprivate.h"
|
||||
#include "gskgliconlibraryprivate.h"
|
||||
#include "gskglprogramprivate.h"
|
||||
#include "gskglshadowlibraryprivate.h"
|
||||
@@ -274,7 +273,6 @@ gsk_gl_driver_dispose (GObject *object)
|
||||
}
|
||||
|
||||
g_clear_object (&self->glyphs_library);
|
||||
g_clear_object (&self->glyphy_library);
|
||||
g_clear_object (&self->icons_library);
|
||||
g_clear_object (&self->shadows_library);
|
||||
|
||||
@@ -465,7 +463,6 @@ gsk_gl_driver_new (GskGLCommandQueue *command_queue,
|
||||
}
|
||||
|
||||
self->glyphs_library = gsk_gl_glyph_library_new (self);
|
||||
self->glyphy_library = gsk_gl_glyphy_library_new (self);
|
||||
self->icons_library = gsk_gl_icon_library_new (self);
|
||||
self->shadows_library = gsk_gl_shadow_library_new (self);
|
||||
|
||||
@@ -576,8 +573,6 @@ gsk_gl_driver_begin_frame (GskGLDriver *self,
|
||||
self->current_frame_id);
|
||||
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphs_library),
|
||||
self->current_frame_id);
|
||||
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphy_library),
|
||||
self->current_frame_id);
|
||||
|
||||
/* Cleanup old shadows */
|
||||
gsk_gl_shadow_library_begin_frame (self->shadows_library);
|
||||
@@ -691,21 +686,17 @@ gsk_gl_driver_cache_texture (GskGLDriver *self,
|
||||
const GskTextureKey *key,
|
||||
guint texture_id)
|
||||
{
|
||||
GskTextureKey *k;
|
||||
|
||||
g_assert (GSK_IS_GL_DRIVER (self));
|
||||
g_assert (key != NULL);
|
||||
g_assert (texture_id > 0);
|
||||
g_assert (g_hash_table_contains (self->textures, GUINT_TO_POINTER (texture_id)));
|
||||
|
||||
if (!g_hash_table_contains (self->key_to_texture_id, key))
|
||||
{
|
||||
GskTextureKey *k;
|
||||
k = g_memdup (key, sizeof *key);
|
||||
|
||||
k = g_memdup (key, sizeof *key);
|
||||
|
||||
g_assert (!g_hash_table_contains (self->texture_id_to_key, GUINT_TO_POINTER (texture_id)));
|
||||
g_hash_table_insert (self->key_to_texture_id, k, GUINT_TO_POINTER (texture_id));
|
||||
g_hash_table_insert (self->texture_id_to_key, GUINT_TO_POINTER (texture_id), k);
|
||||
}
|
||||
g_hash_table_insert (self->key_to_texture_id, k, GUINT_TO_POINTER (texture_id));
|
||||
g_hash_table_insert (self->texture_id_to_key, GUINT_TO_POINTER (texture_id), k);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -97,7 +97,6 @@ struct _GskGLDriver
|
||||
GskGLCommandQueue *command_queue;
|
||||
|
||||
GskGLGlyphLibrary *glyphs_library;
|
||||
GskGLGlyphyLibrary *glyphy_library;
|
||||
GskGLIconLibrary *icons_library;
|
||||
GskGLShadowLibrary *shadows_library;
|
||||
|
||||
|
||||
@@ -1,544 +0,0 @@
|
||||
/* gskglglyphylibrary.c
|
||||
*
|
||||
* Copyright 2020 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
/* Some of the glyphy cache is based upon the original glyphy code.
|
||||
* It's license is provided below.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2012 Google, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
|
||||
#include "gskglcommandqueueprivate.h"
|
||||
#include "gskgldriverprivate.h"
|
||||
#include "gskglglyphylibraryprivate.h"
|
||||
#include "gskdebugprivate.h"
|
||||
|
||||
#include "gskpathprivate.h"
|
||||
|
||||
#include <glyphy.h>
|
||||
|
||||
#define TOLERANCE (1/2048.)
|
||||
#define MIN_FONT_SIZE 14
|
||||
#define GRID_SIZE 20 /* Per EM */
|
||||
#define ENLIGHTEN_MAX .01 /* Per EM */
|
||||
#define EMBOLDEN_MAX .024 /* Per EM */
|
||||
|
||||
/* We split the atlas into cells of size 64x8, so the minimum number of
|
||||
* bytes we store per glyph is 2048, and an atlas of size 2048x1024 can
|
||||
* hold at most 4096 glyphs. We need 5 and 7 bits to store the position
|
||||
* of a glyph in the atlas.
|
||||
*
|
||||
* We allocate each glyph a column of as many vertically adjacent cells
|
||||
* as it needs.
|
||||
*/
|
||||
#define ITEM_W 64
|
||||
#define ITEM_H_QUANTUM 8
|
||||
|
||||
G_DEFINE_TYPE (GskGLGlyphyLibrary, gsk_gl_glyphy_library, GSK_TYPE_GL_TEXTURE_LIBRARY)
|
||||
|
||||
GskGLGlyphyLibrary *
|
||||
gsk_gl_glyphy_library_new (GskGLDriver *driver)
|
||||
{
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), NULL);
|
||||
|
||||
return g_object_new (GSK_TYPE_GL_GLYPHY_LIBRARY,
|
||||
"driver", driver,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static guint
|
||||
gsk_gl_glyphy_key_hash (gconstpointer data)
|
||||
{
|
||||
const GskGLGlyphyKey *key = data;
|
||||
|
||||
/* malloc()'d pointers already guarantee 3 bits from the LSB on 64-bit and
|
||||
* 2 bits from the LSB on 32-bit. Shift by enough to give us 256 entries
|
||||
* in our front cache for the glyph since languages will naturally cluster
|
||||
* for us.
|
||||
*/
|
||||
|
||||
return (key->font << 8) ^ key->glyph;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_glyphy_key_equal (gconstpointer v1,
|
||||
gconstpointer v2)
|
||||
{
|
||||
return memcmp (v1, v2, sizeof (GskGLGlyphyKey)) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_key_free (gpointer data)
|
||||
{
|
||||
GskGLGlyphyKey *key = data;
|
||||
|
||||
g_slice_free (GskGLGlyphyKey, key);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_value_free (gpointer data)
|
||||
{
|
||||
g_slice_free (GskGLGlyphyValue, data);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_clear_cache (GskGLTextureLibrary *library)
|
||||
{
|
||||
GskGLGlyphyLibrary *self = (GskGLGlyphyLibrary *)library;
|
||||
|
||||
g_assert (GSK_IS_GL_GLYPHY_LIBRARY (self));
|
||||
|
||||
memset (self->front, 0, sizeof self->front);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_init_atlas (GskGLTextureLibrary *library,
|
||||
GskGLTextureAtlas *atlas)
|
||||
{
|
||||
g_assert (GSK_IS_GL_GLYPHY_LIBRARY (library));
|
||||
g_assert (atlas != NULL);
|
||||
|
||||
atlas->cursor_x = 0;
|
||||
atlas->cursor_y = 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_glyphy_library_allocate (GskGLTextureLibrary *library,
|
||||
GskGLTextureAtlas *atlas,
|
||||
int width,
|
||||
int height,
|
||||
int *out_x,
|
||||
int *out_y)
|
||||
{
|
||||
GskGLGlyphyLibrary *self = (GskGLGlyphyLibrary *)library;
|
||||
int cursor_save_x;
|
||||
int cursor_save_y;
|
||||
|
||||
g_assert (GSK_IS_GL_GLYPHY_LIBRARY (self));
|
||||
g_assert (atlas != NULL);
|
||||
|
||||
cursor_save_x = atlas->cursor_x;
|
||||
cursor_save_y = atlas->cursor_y;
|
||||
|
||||
if ((height & (self->item_h_q-1)) != 0)
|
||||
height = (height + self->item_h_q - 1) & ~(self->item_h_q - 1);
|
||||
|
||||
/* Require allocations in columns of 64 and rows of 8 */
|
||||
g_assert (width == self->item_w);
|
||||
g_assert ((height % self->item_h_q) == 0);
|
||||
|
||||
if (atlas->cursor_y + height > atlas->height)
|
||||
{
|
||||
/* Go to next column */
|
||||
atlas->cursor_x += self->item_w;
|
||||
atlas->cursor_y = 0;
|
||||
}
|
||||
|
||||
if (atlas->cursor_x + width <= atlas->width &&
|
||||
atlas->cursor_y + height <= atlas->height)
|
||||
{
|
||||
*out_x = atlas->cursor_x;
|
||||
*out_y = atlas->cursor_y;
|
||||
atlas->cursor_y += height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
atlas->cursor_x = cursor_save_x;
|
||||
atlas->cursor_y = cursor_save_y;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_finalize (GObject *object)
|
||||
{
|
||||
GskGLGlyphyLibrary *self = (GskGLGlyphyLibrary *)object;
|
||||
|
||||
g_clear_pointer (&self->acc, glyphy_arc_accumulator_destroy);
|
||||
g_clear_pointer (&self->acc_endpoints, g_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_glyphy_library_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
GQuark quark_glyphy_font_key;
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_class_init (GskGLGlyphyLibraryClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GskGLTextureLibraryClass *library_class = GSK_GL_TEXTURE_LIBRARY_CLASS (klass);
|
||||
|
||||
quark_glyphy_font_key = g_quark_from_static_string ("glyphy-font-key");
|
||||
|
||||
object_class->finalize = gsk_gl_glyphy_library_finalize;
|
||||
|
||||
library_class->allocate = gsk_gl_glyphy_library_allocate;
|
||||
library_class->clear_cache = gsk_gl_glyphy_library_clear_cache;
|
||||
library_class->init_atlas = gsk_gl_glyphy_library_init_atlas;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_glyphy_library_init (GskGLGlyphyLibrary *self)
|
||||
{
|
||||
GskGLTextureLibrary *tl = (GskGLTextureLibrary *)self;
|
||||
|
||||
tl->max_entry_size = 0;
|
||||
tl->max_frame_age = 512;
|
||||
tl->atlas_width = 2048;
|
||||
tl->atlas_height = 1024;
|
||||
gsk_gl_texture_library_set_funcs (tl,
|
||||
gsk_gl_glyphy_key_hash,
|
||||
gsk_gl_glyphy_key_equal,
|
||||
gsk_gl_glyphy_key_free,
|
||||
gsk_gl_glyphy_value_free);
|
||||
|
||||
self->acc = glyphy_arc_accumulator_create ();
|
||||
self->acc_endpoints = g_array_new (FALSE, FALSE, sizeof (glyphy_arc_endpoint_t));
|
||||
self->item_w = ITEM_W;
|
||||
self->item_h_q = ITEM_H_QUANTUM;
|
||||
}
|
||||
|
||||
static glyphy_bool_t
|
||||
accumulate_endpoint (glyphy_arc_endpoint_t *endpoint,
|
||||
GArray *endpoints)
|
||||
{
|
||||
g_array_append_vals (endpoints, endpoint, 1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
move_to (hb_draw_funcs_t *dfuncs,
|
||||
GskPathBuilder *builder,
|
||||
hb_draw_state_t *st,
|
||||
float x,
|
||||
float y,
|
||||
void *data)
|
||||
{
|
||||
gsk_path_builder_move_to (builder, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
line_to (hb_draw_funcs_t *dfuncs,
|
||||
GskPathBuilder *builder,
|
||||
hb_draw_state_t *st,
|
||||
float x,
|
||||
float y,
|
||||
void *data)
|
||||
{
|
||||
gsk_path_builder_line_to (builder, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
cubic_to (hb_draw_funcs_t *dfuncs,
|
||||
GskPathBuilder *builder,
|
||||
hb_draw_state_t *st,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float x3,
|
||||
float y3,
|
||||
void *data)
|
||||
{
|
||||
gsk_path_builder_cubic_to (builder, x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
static void
|
||||
close_path (hb_draw_funcs_t *dfuncs,
|
||||
GskPathBuilder *builder,
|
||||
hb_draw_state_t *st,
|
||||
void *data)
|
||||
{
|
||||
gsk_path_builder_close (builder);
|
||||
}
|
||||
|
||||
static hb_draw_funcs_t *
|
||||
gsk_path_get_draw_funcs (void)
|
||||
{
|
||||
static hb_draw_funcs_t *funcs = NULL;
|
||||
|
||||
if (!funcs)
|
||||
{
|
||||
funcs = hb_draw_funcs_create ();
|
||||
|
||||
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, NULL, NULL);
|
||||
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, NULL, NULL);
|
||||
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
|
||||
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, NULL, NULL);
|
||||
|
||||
hb_draw_funcs_make_immutable (funcs);
|
||||
}
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
acc_callback (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
float weight,
|
||||
gpointer user_data)
|
||||
{
|
||||
glyphy_arc_accumulator_t *acc = user_data;
|
||||
glyphy_point_t p0, p1, p2, p3;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case GSK_PATH_MOVE:
|
||||
p0.x = pts[0].x; p0.y = pts[0].y;
|
||||
glyphy_arc_accumulator_move_to (acc, &p0);
|
||||
break;
|
||||
case GSK_PATH_CLOSE:
|
||||
glyphy_arc_accumulator_close_path (acc);
|
||||
break;
|
||||
case GSK_PATH_LINE:
|
||||
p1.x = pts[1].x; p1.y = pts[1].y;
|
||||
glyphy_arc_accumulator_line_to (acc, &p1);
|
||||
break;
|
||||
case GSK_PATH_QUAD:
|
||||
p1.x = pts[1].x; p1.y = pts[1].y;
|
||||
p2.x = pts[2].x; p2.y = pts[2].y;
|
||||
/* This glyphy api is mis-named */
|
||||
glyphy_arc_accumulator_conic_to (acc, &p1, &p2);
|
||||
break;
|
||||
case GSK_PATH_CUBIC:
|
||||
p1.x = pts[1].x; p1.y = pts[1].y;
|
||||
p2.x = pts[2].x; p2.y = pts[2].y;
|
||||
p3.x = pts[3].x; p3.y = pts[3].y;
|
||||
glyphy_arc_accumulator_cubic_to (acc, &p1, &p2, &p3);
|
||||
break;
|
||||
case GSK_PATH_CONIC:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
encode_glyph (GskGLGlyphyLibrary *self,
|
||||
hb_font_t *font,
|
||||
unsigned int glyph_index,
|
||||
double tolerance_per_em,
|
||||
glyphy_rgba_t *buffer,
|
||||
guint buffer_len,
|
||||
guint *output_len,
|
||||
guint *nominal_width,
|
||||
guint *nominal_height,
|
||||
glyphy_extents_t *extents)
|
||||
{
|
||||
hb_face_t *face = hb_font_get_face (font);
|
||||
guint upem = hb_face_get_upem (face);
|
||||
double tolerance = upem * tolerance_per_em;
|
||||
double faraway = (double)upem / (MIN_FONT_SIZE * M_SQRT2);
|
||||
double unit_size = (double) upem / GRID_SIZE;
|
||||
double enlighten_max = (double) upem * ENLIGHTEN_MAX;
|
||||
double embolden_max = (double) upem * EMBOLDEN_MAX;
|
||||
double avg_fetch_achieved;
|
||||
GskPathBuilder *builder;
|
||||
GskPath *path, *simplified;
|
||||
|
||||
self->acc_endpoints->len = 0;
|
||||
|
||||
glyphy_arc_accumulator_reset (self->acc);
|
||||
glyphy_arc_accumulator_set_tolerance (self->acc, tolerance);
|
||||
glyphy_arc_accumulator_set_callback (self->acc,
|
||||
(glyphy_arc_endpoint_accumulator_callback_t)accumulate_endpoint,
|
||||
self->acc_endpoints);
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
#if HB_VERSION_ATLEAST (7, 0, 0)
|
||||
hb_font_draw_glyph (font, glyph_index, gsk_path_get_draw_funcs (), builder);
|
||||
#else
|
||||
hb_font_get_glyph_shape (font, glyph_index, gsk_path_get_draw_funcs (), builder);
|
||||
#endif
|
||||
path = gsk_path_builder_free_to_path (builder);
|
||||
simplified = gsk_path_op (GSK_PATH_OP_SIMPLIFY, GSK_FILL_RULE_WINDING, path, NULL);
|
||||
gsk_path_foreach (simplified, -1, acc_callback, self->acc);
|
||||
gsk_path_unref (simplified);
|
||||
gsk_path_unref (path);
|
||||
|
||||
if (!glyphy_arc_accumulator_successful (self->acc))
|
||||
return FALSE;
|
||||
|
||||
g_assert (glyphy_arc_accumulator_get_error (self->acc) <= tolerance);
|
||||
|
||||
if (self->acc_endpoints->len > 0)
|
||||
glyphy_outline_winding_from_even_odd ((gpointer)self->acc_endpoints->data,
|
||||
self->acc_endpoints->len,
|
||||
FALSE);
|
||||
|
||||
if (!glyphy_arc_list_encode_blob2 ((gpointer)self->acc_endpoints->data,
|
||||
self->acc_endpoints->len,
|
||||
buffer,
|
||||
buffer_len,
|
||||
faraway,
|
||||
unit_size,
|
||||
enlighten_max,
|
||||
embolden_max,
|
||||
&avg_fetch_achieved,
|
||||
output_len,
|
||||
nominal_width,
|
||||
nominal_height,
|
||||
extents))
|
||||
return FALSE;
|
||||
|
||||
glyphy_extents_scale (extents, 1./upem, 1./upem);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline hb_font_t *
|
||||
get_nominal_size_hb_font (PangoFont *font)
|
||||
{
|
||||
hb_font_t *hbfont;
|
||||
const float *coords;
|
||||
unsigned int length;
|
||||
|
||||
hbfont = (hb_font_t *) g_object_get_data ((GObject *)font, "glyph-nominal-size-font");
|
||||
if (hbfont == NULL)
|
||||
{
|
||||
hbfont = hb_font_create (hb_font_get_face (pango_font_get_hb_font (font)));
|
||||
coords = hb_font_get_var_coords_design (pango_font_get_hb_font (font), &length);
|
||||
if (length > 0)
|
||||
hb_font_set_var_coords_design (hbfont, coords, length);
|
||||
|
||||
g_object_set_data_full ((GObject *)font, "glyphy-nominal-size-font",
|
||||
hbfont, (GDestroyNotify)hb_font_destroy);
|
||||
}
|
||||
|
||||
return hbfont;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_gl_glyphy_library_add (GskGLGlyphyLibrary *self,
|
||||
GskGLGlyphyKey *key,
|
||||
PangoFont *font,
|
||||
const GskGLGlyphyValue **out_value)
|
||||
{
|
||||
static glyphy_rgba_t buffer[4096 * 16];
|
||||
GskGLTextureLibrary *tl = (GskGLTextureLibrary *)self;
|
||||
GskGLGlyphyValue *value;
|
||||
glyphy_extents_t extents;
|
||||
hb_font_t *hbfont;
|
||||
guint packed_x;
|
||||
guint packed_y;
|
||||
guint nominal_w, nominal_h;
|
||||
guint output_len = 0;
|
||||
guint texture_id;
|
||||
guint width, height;
|
||||
|
||||
g_assert (GSK_IS_GL_GLYPHY_LIBRARY (self));
|
||||
g_assert (key != NULL);
|
||||
g_assert (font != NULL);
|
||||
g_assert (out_value != NULL);
|
||||
|
||||
hbfont = get_nominal_size_hb_font (font);
|
||||
|
||||
/* Convert the glyph to a list of arcs */
|
||||
if (!encode_glyph (self, hbfont, key->glyph, TOLERANCE,
|
||||
buffer, sizeof buffer, &output_len,
|
||||
&nominal_w, &nominal_h, &extents))
|
||||
return FALSE;
|
||||
|
||||
/* Allocate space for list within atlas */
|
||||
width = self->item_w;
|
||||
height = (output_len + width - 1) / width;
|
||||
GSK_DEBUG (GLYPH_CACHE, "font %u glyph %u: %u bytes (%u x %u)", key->font, key->glyph, output_len * 4, width, height);
|
||||
|
||||
value = gsk_gl_texture_library_pack (tl, key, sizeof *value,
|
||||
width, height, 0,
|
||||
&packed_x, &packed_y);
|
||||
|
||||
g_assert (packed_x % ITEM_W == 0);
|
||||
g_assert (packed_y % ITEM_H_QUANTUM == 0);
|
||||
|
||||
/* Make sure we found space to pack */
|
||||
texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (value);
|
||||
if (texture_id == 0)
|
||||
return FALSE;
|
||||
|
||||
if (!glyphy_extents_is_empty (&extents))
|
||||
{
|
||||
/* Connect the texture for data upload */
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
|
||||
g_assert (width > 0);
|
||||
g_assert (height > 0);
|
||||
|
||||
/* Upload the arc list */
|
||||
if (width * height == output_len)
|
||||
{
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x, packed_y,
|
||||
width, height,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x, packed_y,
|
||||
width, height - 1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buffer);
|
||||
/* Upload the last row separately */
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x, packed_y + height - 1,
|
||||
output_len - (width * (height - 1)), 1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buffer + (width * (height - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
value->extents.min_x = extents.min_x;
|
||||
value->extents.min_y = extents.min_y;
|
||||
value->extents.max_x = extents.max_x;
|
||||
value->extents.max_y = extents.max_y;
|
||||
value->nominal_w = nominal_w;
|
||||
value->nominal_h = nominal_h;
|
||||
value->atlas_x = packed_x / self->item_w;
|
||||
value->atlas_y = packed_y / self->item_h_q;
|
||||
|
||||
*out_value = value;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/* gskglglyphylibraryprivate.h
|
||||
*
|
||||
* Copyright 2020-2022 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GSK_GL_GLYPHY_LIBRARY_PRIVATE_H__
|
||||
#define __GSK_GL_GLYPHY_LIBRARY_PRIVATE_H__
|
||||
|
||||
#include <glyphy.h>
|
||||
#include <pango/pango.h>
|
||||
|
||||
#include "gskgltexturelibraryprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_GLYPHY_LIBRARY (gsk_gl_glyphy_library_get_type())
|
||||
|
||||
typedef guint FontKey;
|
||||
|
||||
extern GQuark quark_glyphy_font_key;
|
||||
|
||||
static inline FontKey
|
||||
gsk_gl_glyphy_library_get_font_key (PangoFont *font)
|
||||
{
|
||||
FontKey key;
|
||||
|
||||
key = (FontKey) GPOINTER_TO_UINT (g_object_get_qdata ((GObject *)font, quark_glyphy_font_key));
|
||||
if (key == 0)
|
||||
{
|
||||
PangoFontDescription *desc = pango_font_describe (font);
|
||||
pango_font_description_set_size (desc, 10 * PANGO_SCALE);
|
||||
key = (FontKey) pango_font_description_hash (desc);
|
||||
pango_font_description_free (desc);
|
||||
g_object_set_qdata ((GObject *)font, quark_glyphy_font_key, GUINT_TO_POINTER (key));
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static inline float
|
||||
gsk_gl_glyphy_library_get_font_scale (PangoFont *font)
|
||||
{
|
||||
hb_font_t *hbfont;
|
||||
int x_scale, y_scale;
|
||||
|
||||
hbfont = pango_font_get_hb_font (font);
|
||||
hb_font_get_scale (hbfont, &x_scale, &y_scale);
|
||||
|
||||
return MAX (x_scale, y_scale) / 1000.0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct _GskGLGlyphyKey
|
||||
{
|
||||
FontKey font;
|
||||
PangoGlyph glyph;
|
||||
} GskGLGlyphyKey;
|
||||
|
||||
typedef struct _GskGLGlyphyValue
|
||||
{
|
||||
GskGLTextureAtlasEntry entry;
|
||||
struct {
|
||||
float min_x;
|
||||
float min_y;
|
||||
float max_x;
|
||||
float max_y;
|
||||
} extents;
|
||||
guint nominal_w;
|
||||
guint nominal_h;
|
||||
guint atlas_x;
|
||||
guint atlas_y;
|
||||
} GskGLGlyphyValue;
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLGlyphyLibrary, gsk_gl_glyphy_library, GSK, GL_GLYPHY_LIBRARY, GskGLTextureLibrary)
|
||||
|
||||
struct _GskGLGlyphyLibrary
|
||||
{
|
||||
GskGLTextureLibrary parent_instance;
|
||||
glyphy_arc_accumulator_t *acc;
|
||||
GArray *acc_endpoints;
|
||||
guint item_w;
|
||||
guint item_h_q;
|
||||
struct {
|
||||
GskGLGlyphyKey key;
|
||||
const GskGLGlyphyValue *value;
|
||||
} front[256];
|
||||
};
|
||||
|
||||
GskGLGlyphyLibrary *gsk_gl_glyphy_library_new (GskGLDriver *driver);
|
||||
gboolean gsk_gl_glyphy_library_add (GskGLGlyphyLibrary *self,
|
||||
GskGLGlyphyKey *key,
|
||||
PangoFont *font,
|
||||
const GskGLGlyphyValue **out_value);
|
||||
|
||||
static inline guint
|
||||
gsk_gl_glyphy_library_lookup_or_add (GskGLGlyphyLibrary *self,
|
||||
const GskGLGlyphyKey *key,
|
||||
PangoFont *font,
|
||||
const GskGLGlyphyValue **out_value)
|
||||
{
|
||||
GskGLTextureAtlasEntry *entry;
|
||||
guint front_index = key->glyph & 0xFF;
|
||||
|
||||
if (memcmp (key, &self->front[front_index], sizeof *key) == 0)
|
||||
{
|
||||
*out_value = self->front[front_index].value;
|
||||
}
|
||||
else if (gsk_gl_texture_library_lookup ((GskGLTextureLibrary *)self, key, &entry))
|
||||
{
|
||||
*out_value = (GskGLGlyphyValue *)entry;
|
||||
self->front[front_index].key = *key;
|
||||
self->front[front_index].value = *out_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
GskGLGlyphyKey *k = g_slice_copy (sizeof *key, key);
|
||||
gsk_gl_glyphy_library_add (self, k, font, out_value);
|
||||
self->front[front_index].key = *key;
|
||||
self->front[front_index].value = *out_value;
|
||||
}
|
||||
|
||||
return GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (*out_value);
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_GL_GLYPHY_LIBRARY_PRIVATE_H__ */
|
||||
@@ -87,21 +87,3 @@ GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
|
||||
GSK_GL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
|
||||
GSK_GL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
|
||||
GSK_GL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
||||
|
||||
GSK_GL_DEFINE_PROGRAM (glyphy,
|
||||
GSK_GL_SHADER_JOINED (VERTEX,
|
||||
GSK_GL_SHADER_RESOURCE ("glyphy.vs.glsl"),
|
||||
NULL)
|
||||
GSK_GL_SHADER_JOINED (FRAGMENT,
|
||||
GSK_GL_SHADER_RESOURCE ("glyphy.atlas.glsl"),
|
||||
GSK_GL_SHADER_STRING (glyphy_common_shader_source ()),
|
||||
GSK_GL_SHADER_STRING ("#define GLYPHY_SDF_PSEUDO_DISTANCE 1\n"),
|
||||
GSK_GL_SHADER_STRING (glyphy_sdf_shader_source ()),
|
||||
GSK_GL_SHADER_RESOURCE ("glyphy.fs.glsl"),
|
||||
NULL),
|
||||
GSK_GL_ADD_UNIFORM (0, GLYPHY_CONTRAST, u_contrast)
|
||||
GSK_GL_ADD_UNIFORM (1, GLYPHY_GAMMA_ADJUST, u_gamma_adjust)
|
||||
GSK_GL_ADD_UNIFORM (2, GLYPHY_OUTLINE_THICKNESS, u_outline_thickness)
|
||||
GSK_GL_ADD_UNIFORM (3, GLYPHY_OUTLINE, u_outline)
|
||||
GSK_GL_ADD_UNIFORM (4, GLYPHY_BOLDNESS, u_boldness)
|
||||
GSK_GL_ADD_UNIFORM (6, GLYPHY_ATLAS_INFO, u_atlas_info))
|
||||
|
||||
+2
-14
@@ -150,13 +150,6 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
|
||||
gsk_gl_command_queue_set_profiler (self->command_queue,
|
||||
gsk_renderer_get_profiler (renderer));
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (gsk_renderer_get_debug_flags (renderer) & GSK_DEBUG_NO_GLYPHY)
|
||||
GSK_RENDERER_DEBUG (renderer, RENDERER, "GL Renderer will use cairo for glyph rendering");
|
||||
else
|
||||
GSK_RENDERER_DEBUG (renderer, RENDERER, "GL Renderer will use glyphy for glyph rendering");
|
||||
#endif
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
failure:
|
||||
@@ -303,7 +296,7 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
viewport.size.height = gdk_surface_get_height (surface) * scale;
|
||||
|
||||
gdk_draw_context_begin_frame_full (GDK_DRAW_CONTEXT (self->context),
|
||||
gsk_render_node_get_preferred_depth (root),
|
||||
gsk_render_node_prefers_high_depth (root),
|
||||
update_area);
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
@@ -314,15 +307,10 @@ gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
|
||||
gsk_gl_driver_begin_frame (self->driver, self->command_queue);
|
||||
job = gsk_gl_render_job_new (self->driver, &viewport, scale, render_region, 0, clear_framebuffer);
|
||||
|
||||
if ((gsk_renderer_get_debug_flags (renderer) & GSK_DEBUG_NO_GLYPHY) == 0)
|
||||
gsk_gl_render_job_set_use_glyphy (job, TRUE);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), FALLBACK))
|
||||
gsk_gl_render_job_set_debug_fallback (job, TRUE);
|
||||
#endif
|
||||
|
||||
gsk_gl_render_job_render (job, root);
|
||||
gsk_gl_driver_end_frame (self->driver);
|
||||
gsk_gl_render_job_free (job);
|
||||
@@ -385,7 +373,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
|
||||
return texture;
|
||||
}
|
||||
|
||||
if (gsk_render_node_get_preferred_depth (root) != GDK_MEMORY_U8 &&
|
||||
if (gsk_render_node_prefers_high_depth (root) &&
|
||||
gdk_gl_context_check_version (self->context, "3.0", "3.0"))
|
||||
format = GL_RGBA32F;
|
||||
else
|
||||
|
||||
+5
-280
@@ -34,14 +34,10 @@
|
||||
#include <gsk/gskroundedrectprivate.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_PANGOFT
|
||||
#include <pango/pangofc-font.h>
|
||||
#endif
|
||||
|
||||
#include "gskglcommandqueueprivate.h"
|
||||
#include "gskgldriverprivate.h"
|
||||
#include "gskglglyphlibraryprivate.h"
|
||||
#include "gskglglyphylibraryprivate.h"
|
||||
#include "gskgliconlibraryprivate.h"
|
||||
#include "gskglprogramprivate.h"
|
||||
#include "gskglrenderjobprivate.h"
|
||||
@@ -153,9 +149,6 @@ struct _GskGLRenderJob
|
||||
*/
|
||||
guint clear_framebuffer : 1;
|
||||
|
||||
/* Allow experimental glyph rendering with glyphy */
|
||||
guint use_glyphy : 1;
|
||||
|
||||
/* Format we want to use for intermediate textures, determined by
|
||||
* looking at the format of the framebuffer we are rendering on.
|
||||
*/
|
||||
@@ -201,7 +194,7 @@ static inline int
|
||||
get_target_format (GskGLRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
{
|
||||
if (gsk_render_node_get_preferred_depth (node) != GDK_MEMORY_U8)
|
||||
if (gsk_render_node_prefers_high_depth (node))
|
||||
return job->target_format;
|
||||
|
||||
return GL_RGBA8;
|
||||
@@ -810,8 +803,6 @@ gsk_gl_render_job_untransform_bounds (GskGLRenderJob *job,
|
||||
|
||||
out_rect->origin.x -= job->offset_x;
|
||||
out_rect->origin.y -= job->offset_y;
|
||||
|
||||
gsk_transform_unref (transform);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -2966,10 +2957,10 @@ compute_phase_and_pos (float value, float *pos)
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_text_node_legacy (GskGLRenderJob *job,
|
||||
const GskRenderNode *node,
|
||||
const GdkRGBA *color,
|
||||
gboolean force_color)
|
||||
gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node,
|
||||
const GdkRGBA *color,
|
||||
gboolean force_color)
|
||||
{
|
||||
const PangoFont *font = gsk_text_node_get_font (node);
|
||||
const PangoGlyphInfo *glyphs = gsk_text_node_get_glyphs (node, NULL);
|
||||
@@ -3105,263 +3096,6 @@ gsk_gl_render_job_visit_text_node_legacy (GskGLRenderJob *job,
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep this in sync with glyph_vertex_transcode in glyphy.vs.glsl */
|
||||
typedef struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float g16hi;
|
||||
float g16lo;
|
||||
} EncodedGlyph;
|
||||
|
||||
static inline unsigned int
|
||||
glyph_encode (guint atlas_x , /* 7 bits */
|
||||
guint atlas_y, /* 7 bits */
|
||||
guint corner_x, /* 1 bit */
|
||||
guint corner_y, /* 1 bit */
|
||||
guint nominal_w, /* 6 bits */
|
||||
guint nominal_h) /* 6 bits */
|
||||
{
|
||||
guint x, y;
|
||||
|
||||
g_assert (0 == (atlas_x & ~0x7F));
|
||||
g_assert (0 == (atlas_y & ~0x7F));
|
||||
g_assert (0 == (corner_x & ~1));
|
||||
g_assert (0 == (corner_y & ~1));
|
||||
g_assert (0 == (nominal_w & ~0x3F));
|
||||
g_assert (0 == (nominal_h & ~0x3F));
|
||||
|
||||
x = (((atlas_x << 6) | nominal_w) << 1) | corner_x;
|
||||
y = (((atlas_y << 6) | nominal_h) << 1) | corner_y;
|
||||
|
||||
return (x << 16) | y;
|
||||
}
|
||||
|
||||
static inline void
|
||||
encoded_glyph_init (EncodedGlyph *eg,
|
||||
float x,
|
||||
float y,
|
||||
guint corner_x,
|
||||
guint corner_y,
|
||||
const GskGLGlyphyValue *gi)
|
||||
{
|
||||
guint encoded = glyph_encode (gi->atlas_x, gi->atlas_y, corner_x, corner_y, gi->nominal_w, gi->nominal_h);
|
||||
|
||||
eg->x = x;
|
||||
eg->y = y;
|
||||
eg->g16hi = encoded >> 16;
|
||||
eg->g16lo = encoded & 0xFFFF;
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_encoded_glyph (GskGLDrawVertex *vertices,
|
||||
const EncodedGlyph *eg,
|
||||
const guint16 c[4])
|
||||
{
|
||||
*vertices = (GskGLDrawVertex) { .position = { eg->x, eg->y}, .uv = { eg->g16hi, eg->g16lo}, .color = { c[0], c[1], c[2], c[3] } };
|
||||
}
|
||||
|
||||
static void
|
||||
get_synthetic_font_params (PangoFont *font,
|
||||
gboolean *embolden,
|
||||
PangoMatrix *matrix)
|
||||
{
|
||||
*embolden = FALSE;
|
||||
*matrix = (PangoMatrix) PANGO_MATRIX_INIT;
|
||||
|
||||
#ifdef HAVE_PANGOFT
|
||||
if (PANGO_IS_FC_FONT (font))
|
||||
{
|
||||
FcPattern *pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
|
||||
FcBool b;
|
||||
FcMatrix mat;
|
||||
FcMatrix *m;
|
||||
|
||||
if (FcPatternGetBool (pattern, FC_EMBOLDEN, 0, &b) == FcResultMatch)
|
||||
*embolden = b;
|
||||
|
||||
FcMatrixInit (&mat);
|
||||
for (int i = 0; FcPatternGetMatrix (pattern, FC_MATRIX, i, &m) == FcResultMatch; i++)
|
||||
FcMatrixMultiply (&mat, &mat, m);
|
||||
|
||||
matrix->xx = mat.xx;
|
||||
matrix->xy = mat.xy;
|
||||
matrix->yx = mat.yx;
|
||||
matrix->yy = mat.yy;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_text_node_glyphy (GskGLRenderJob *job,
|
||||
const GskRenderNode *node,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
const graphene_point_t *offset;
|
||||
const PangoGlyphInfo *glyphs;
|
||||
const PangoGlyphInfo *gi;
|
||||
GskGLGlyphyLibrary *library;
|
||||
GskGLCommandBatch *batch;
|
||||
PangoFont *font;
|
||||
GskGLDrawVertex *vertices;
|
||||
const guint16 *c;
|
||||
GskGLGlyphyKey lookup;
|
||||
guint16 cc[4];
|
||||
float x;
|
||||
float y;
|
||||
guint last_texture = 0;
|
||||
guint num_glyphs;
|
||||
guint used = 0;
|
||||
guint i;
|
||||
int x_position = 0;
|
||||
float font_scale;
|
||||
gboolean embolden;
|
||||
PangoMatrix matrix = PANGO_MATRIX_INIT;
|
||||
|
||||
#define GRID_SIZE 20
|
||||
|
||||
g_assert (!gsk_text_node_has_color_glyphs (node));
|
||||
|
||||
if (!(num_glyphs = gsk_text_node_get_num_glyphs (node)))
|
||||
return;
|
||||
|
||||
if (RGBA_IS_CLEAR (color))
|
||||
return;
|
||||
|
||||
font = (PangoFont *)gsk_text_node_get_font (node);
|
||||
get_synthetic_font_params (font, &embolden, &matrix);
|
||||
|
||||
glyphs = gsk_text_node_get_glyphs (node, NULL);
|
||||
library = job->driver->glyphy_library;
|
||||
offset = gsk_text_node_get_offset (node);
|
||||
x = offset->x + job->offset_x;
|
||||
y = offset->y + job->offset_y;
|
||||
|
||||
rgba_to_half (color, cc);
|
||||
c = cc;
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, glyphy));
|
||||
|
||||
batch = gsk_gl_command_queue_get_batch (job->command_queue);
|
||||
vertices = gsk_gl_command_queue_add_n_vertices (job->command_queue, num_glyphs);
|
||||
|
||||
lookup.font = gsk_gl_glyphy_library_get_font_key (font);
|
||||
font_scale = gsk_gl_glyphy_library_get_font_scale (font);
|
||||
|
||||
for (i = 0, gi = glyphs; i < num_glyphs; i++, gi++)
|
||||
{
|
||||
const GskGLGlyphyValue *glyph;
|
||||
float cx = 0, cy = 0;
|
||||
guint texture_id;
|
||||
|
||||
lookup.glyph = gi->glyph;
|
||||
texture_id = gsk_gl_glyphy_library_lookup_or_add (library, &lookup, font, &glyph);
|
||||
|
||||
if G_UNLIKELY (texture_id == 0)
|
||||
continue;
|
||||
|
||||
if G_UNLIKELY (last_texture != texture_id || batch->draw.vbo_count + GSK_GL_N_VERTICES > 0xffff)
|
||||
{
|
||||
if G_LIKELY (last_texture != 0)
|
||||
{
|
||||
guint vbo_offset = batch->draw.vbo_offset + batch->draw.vbo_count;
|
||||
|
||||
/* Since we have batched added our VBO vertices to avoid repeated
|
||||
* calls to the buffer, we need to manually tweak the vbo offset
|
||||
* of the new batch as otherwise it will point at the end of our
|
||||
* vbo array.
|
||||
*/
|
||||
gsk_gl_render_job_split_draw (job);
|
||||
batch = gsk_gl_command_queue_get_batch (job->command_queue);
|
||||
batch->draw.vbo_offset = vbo_offset;
|
||||
}
|
||||
|
||||
gsk_gl_program_set_uniform4i (job->current_program,
|
||||
UNIFORM_GLYPHY_ATLAS_INFO, 0,
|
||||
GSK_GL_TEXTURE_LIBRARY (library)->atlas_width,
|
||||
GSK_GL_TEXTURE_LIBRARY (library)->atlas_height,
|
||||
library->item_w,
|
||||
library->item_h_q);
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE0,
|
||||
texture_id);
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_GAMMA_ADJUST, 0,
|
||||
1.0);
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_CONTRAST, 0,
|
||||
1.0);
|
||||
|
||||
/* 0.0208 is the value used by freetype for synthetic emboldening */
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_BOLDNESS, 0,
|
||||
embolden ? 0.0208 * GRID_SIZE : 0.0);
|
||||
|
||||
#if 0
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_OUTLINE_THICKNESS, 0,
|
||||
1.0);
|
||||
gsk_gl_program_set_uniform1f (job->current_program,
|
||||
UNIFORM_GLYPHY_OUTLINE, 0,
|
||||
1.0);
|
||||
#endif
|
||||
|
||||
last_texture = texture_id;
|
||||
}
|
||||
|
||||
cx = (float)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
if G_UNLIKELY (gi->geometry.y_offset != 0)
|
||||
cy = (float)(gi->geometry.y_offset) / PANGO_SCALE;
|
||||
|
||||
x_position += gi->geometry.width;
|
||||
|
||||
EncodedGlyph encoded[4];
|
||||
#define ENCODE_CORNER(_cx, _cy) \
|
||||
G_STMT_START { \
|
||||
float _dx = _cx * (glyph->extents.max_x - glyph->extents.min_x); \
|
||||
float _dy = _cy * (glyph->extents.max_y - glyph->extents.min_y); \
|
||||
float _vx = x + cx + font_scale * (glyph->extents.min_x + matrix.xx * _dx + matrix.xy * _dy); \
|
||||
float _vy = y + cy - font_scale * (glyph->extents.min_y + matrix.yx * _dx + matrix.yy * _dy); \
|
||||
encoded_glyph_init (&encoded[_cx * 2 + _cy], _vx, _vy, _cx, _cy, glyph); \
|
||||
} G_STMT_END
|
||||
ENCODE_CORNER (0, 0);
|
||||
ENCODE_CORNER (0, 1);
|
||||
ENCODE_CORNER (1, 0);
|
||||
ENCODE_CORNER (1, 1);
|
||||
#undef ENCODE_CORNER
|
||||
|
||||
add_encoded_glyph (vertices++, &encoded[0], c);
|
||||
add_encoded_glyph (vertices++, &encoded[1], c);
|
||||
add_encoded_glyph (vertices++, &encoded[2], c);
|
||||
|
||||
add_encoded_glyph (vertices++, &encoded[1], c);
|
||||
add_encoded_glyph (vertices++, &encoded[2], c);
|
||||
add_encoded_glyph (vertices++, &encoded[3], c);
|
||||
|
||||
batch->draw.vbo_count += GSK_GL_N_VERTICES;
|
||||
used++;
|
||||
}
|
||||
|
||||
if (used != num_glyphs)
|
||||
gsk_gl_command_queue_retract_n_vertices (job->command_queue, num_glyphs - used);
|
||||
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node,
|
||||
const GdkRGBA *color,
|
||||
gboolean force_color)
|
||||
{
|
||||
if (job->use_glyphy && !gsk_text_node_has_color_glyphs (node))
|
||||
gsk_gl_render_job_visit_text_node_glyphy (job, node, color);
|
||||
else
|
||||
gsk_gl_render_job_visit_text_node_legacy (job, node, color, force_color);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
@@ -4727,15 +4461,6 @@ gsk_gl_render_job_set_debug_fallback (GskGLRenderJob *job,
|
||||
job->debug_fallback = !!debug_fallback;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_render_job_set_use_glyphy (GskGLRenderJob *job,
|
||||
gboolean use_glyphy)
|
||||
{
|
||||
g_return_if_fail (job != NULL);
|
||||
|
||||
job->use_glyphy = !!use_glyphy;
|
||||
}
|
||||
|
||||
static int
|
||||
get_framebuffer_format (GdkGLContext *context,
|
||||
guint framebuffer)
|
||||
|
||||
@@ -35,5 +35,4 @@ void gsk_gl_render_job_render_flipped (GskGLRenderJob *job
|
||||
GskRenderNode *root);
|
||||
void gsk_gl_render_job_set_debug_fallback (GskGLRenderJob *job,
|
||||
gboolean debug_fallback);
|
||||
void gsk_gl_render_job_set_use_glyphy (GskGLRenderJob *job,
|
||||
gboolean use_glyphy);
|
||||
|
||||
|
||||
@@ -204,7 +204,6 @@ gsk_gl_texture_library_dispose (GObject *object)
|
||||
|
||||
g_clear_pointer (&self->atlases, g_ptr_array_unref);
|
||||
g_clear_object (&self->driver);
|
||||
g_clear_pointer (&self->hash_table, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_texture_library_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@@ -36,14 +36,9 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskGLTextureAtlas
|
||||
{
|
||||
/* Used by Glyph/Icons */
|
||||
struct stbrp_context context;
|
||||
struct stbrp_node *nodes;
|
||||
|
||||
/* Used by Glyphy */
|
||||
int cursor_x;
|
||||
int cursor_y;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
@@ -53,6 +48,7 @@ typedef struct _GskGLTextureAtlas
|
||||
* But are now unused.
|
||||
*/
|
||||
int unused_pixels;
|
||||
|
||||
} GskGLTextureAtlas;
|
||||
|
||||
typedef struct _GskGLTextureAtlasEntry
|
||||
|
||||
@@ -36,7 +36,6 @@ typedef struct _GskGLCompiler GskGLCompiler;
|
||||
typedef struct _GskGLDrawVertex GskGLDrawVertex;
|
||||
typedef struct _GskGLRenderTarget GskGLRenderTarget;
|
||||
typedef struct _GskGLGlyphLibrary GskGLGlyphLibrary;
|
||||
typedef struct _GskGLGlyphyLibrary GskGLGlyphyLibrary;
|
||||
typedef struct _GskGLIconLibrary GskGLIconLibrary;
|
||||
typedef struct _GskGLProgram GskGLProgram;
|
||||
typedef struct _GskGLRenderJob GskGLRenderJob;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
uniform ivec4 u_atlas_info;
|
||||
|
||||
#define GLYPHY_TEXTURE1D_EXTRA_DECLS , sampler2D _tex, ivec4 _atlas_info, ivec2 _atlas_pos
|
||||
#define GLYPHY_TEXTURE1D_EXTRA_ARGS , _tex, _atlas_info, _atlas_pos
|
||||
#define GLYPHY_DEMO_EXTRA_ARGS , u_source, u_atlas_info, gi.atlas_pos
|
||||
|
||||
vec4
|
||||
glyphy_texture1D_func (int offset GLYPHY_TEXTURE1D_EXTRA_DECLS)
|
||||
{
|
||||
ivec2 item_geom = _atlas_info.zw;
|
||||
vec2 pos = (vec2 (_atlas_pos.xy * item_geom +
|
||||
ivec2 (mod (float (offset), float (item_geom.x)), offset / item_geom.x)) +
|
||||
+ vec2 (.5, .5)) / vec2(_atlas_info.xy);
|
||||
return GskTexture (_tex, pos);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
// FRAGMENT_SHADER:
|
||||
// glyphy.fs.glsl
|
||||
|
||||
uniform float u_contrast;
|
||||
uniform float u_gamma_adjust;
|
||||
uniform float u_outline_thickness;
|
||||
uniform bool u_outline;
|
||||
uniform float u_boldness;
|
||||
|
||||
_IN_ vec4 v_glyph;
|
||||
_IN_ vec4 final_color;
|
||||
|
||||
#define SQRT2 1.4142135623730951
|
||||
#define SQRT2_INV 0.70710678118654757 /* 1 / sqrt(2.) */
|
||||
|
||||
struct glyph_info_t {
|
||||
ivec2 nominal_size;
|
||||
ivec2 atlas_pos;
|
||||
};
|
||||
|
||||
glyph_info_t
|
||||
glyph_info_decode (vec4 v)
|
||||
{
|
||||
glyph_info_t gi;
|
||||
gi.nominal_size = (ivec2 (mod (v.zw, 256.)) + 2) / 4;
|
||||
gi.atlas_pos = ivec2 (v_glyph.zw) / 256;
|
||||
return gi;
|
||||
}
|
||||
|
||||
float
|
||||
antialias (float d)
|
||||
{
|
||||
return smoothstep (-.75, +.75, d);
|
||||
}
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
vec2 p = v_glyph.xy;
|
||||
glyph_info_t gi = glyph_info_decode (v_glyph);
|
||||
|
||||
/* isotropic antialiasing */
|
||||
vec2 dpdx = dFdx (p);
|
||||
vec2 dpdy = dFdy (p);
|
||||
float m = length (vec2 (length (dpdx), length (dpdy))) * SQRT2_INV;
|
||||
|
||||
float gsdist = glyphy_sdf (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS);
|
||||
gsdist -= u_boldness;
|
||||
float sdist = gsdist / m * u_contrast;
|
||||
|
||||
if (u_outline)
|
||||
sdist = abs (sdist) - u_outline_thickness * .5;
|
||||
|
||||
if (sdist > 1.)
|
||||
discard;
|
||||
|
||||
float alpha = antialias (-sdist);
|
||||
if (u_gamma_adjust != 1.)
|
||||
alpha = pow (alpha, 1./u_gamma_adjust);
|
||||
|
||||
gskSetOutputColor(final_color * alpha);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// VERTEX_SHADER:
|
||||
// glyphy.vs.glsl
|
||||
|
||||
_OUT_ vec4 v_glyph;
|
||||
_OUT_ vec4 final_color;
|
||||
|
||||
// Keep this in sync with glyph_encode in gskglrenderjob.c
|
||||
vec4
|
||||
glyph_vertex_transcode (vec2 v)
|
||||
{
|
||||
ivec2 g = ivec2 (v);
|
||||
ivec2 corner = ivec2 (mod (v, 2.));
|
||||
g /= 2;
|
||||
ivec2 nominal_size = ivec2 (mod (vec2(g), 64.));
|
||||
return vec4 (corner * nominal_size, g * 4);
|
||||
}
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
v_glyph = glyph_vertex_transcode(aUv);
|
||||
vUv = v_glyph.zw;
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
final_color = gsk_scaled_premultiply(aColor, u_alpha);
|
||||
}
|
||||
@@ -13,12 +13,6 @@ void main() {
|
||||
uniform int u_mode;
|
||||
uniform sampler2D u_mask;
|
||||
|
||||
float
|
||||
luminance (vec3 color)
|
||||
{
|
||||
return dot (vec3 (0.2126, 0.7152, 0.0722), color);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 source = GskTexture(u_source, vUv);
|
||||
vec4 mask = GskTexture(u_mask, vUv);
|
||||
@@ -29,9 +23,9 @@ void main() {
|
||||
else if (u_mode == 1)
|
||||
mask_value = 1.0 - mask.a;
|
||||
else if (u_mode == 2)
|
||||
mask_value = luminance (mask.rgb);
|
||||
mask_value = (0.2126 * mask.r + 0.7152 * mask.g + 0.0722 * mask.b) * mask.a;
|
||||
else if (u_mode == 3)
|
||||
mask_value = mask.a - luminance (mask.rgb);
|
||||
mask_value = 1.0 - (0.2126 * mask.r + 0.7152 * mask.g + 0.0722 * mask.b) * mask.a;
|
||||
else
|
||||
mask_value = 0.0;
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#extension GL_OES_standard_derivatives : enable
|
||||
|
||||
#ifndef GSK_LEGACY
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gsk/gsktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskBoundingBox GskBoundingBox;
|
||||
|
||||
struct _GskBoundingBox {
|
||||
graphene_point_t min;
|
||||
graphene_point_t max;
|
||||
};
|
||||
|
||||
static inline GskBoundingBox *
|
||||
gsk_bounding_box_init (GskBoundingBox *self,
|
||||
const graphene_point_t *a,
|
||||
const graphene_point_t *b)
|
||||
{
|
||||
self->min.x = MIN (a->x, b->x);
|
||||
self->min.y = MIN (a->y, b->y);
|
||||
self->max.x = MAX (a->x, b->x);
|
||||
self->max.y = MAX (a->y, b->y);
|
||||
return self;
|
||||
}
|
||||
|
||||
static inline GskBoundingBox *
|
||||
gsk_bounding_box_init_copy (GskBoundingBox *self,
|
||||
const GskBoundingBox *src)
|
||||
{
|
||||
self->min = src->min;
|
||||
self->max = src->max;
|
||||
return self;
|
||||
}
|
||||
|
||||
static inline GskBoundingBox *
|
||||
gsk_bounding_box_init_from_rect (GskBoundingBox *self,
|
||||
const graphene_rect_t *bounds)
|
||||
{
|
||||
self->min = bounds->origin;
|
||||
self->max.x = bounds->origin.x + bounds->size.width;
|
||||
self->max.y = bounds->origin.y + bounds->size.height;
|
||||
return self;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_bounding_box_expand (GskBoundingBox *self,
|
||||
const graphene_point_t *p)
|
||||
{
|
||||
self->min.x = MIN (self->min.x, p->x);
|
||||
self->min.y = MIN (self->min.y, p->y);
|
||||
self->max.x = MAX (self->max.x, p->x);
|
||||
self->max.y = MAX (self->max.y, p->y);
|
||||
}
|
||||
|
||||
static inline graphene_rect_t *
|
||||
gsk_bounding_box_to_rect (const GskBoundingBox *self,
|
||||
graphene_rect_t *rect)
|
||||
{
|
||||
rect->origin = self->min;
|
||||
rect->size.width = self->max.x - self->min.x;
|
||||
rect->size.height = self->max.y - self->min.y;
|
||||
return rect;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
gsk_bounding_box_contains_point (const GskBoundingBox *self,
|
||||
const graphene_point_t *p)
|
||||
{
|
||||
return self->min.x <= p->x && p->x <= self->max.x &&
|
||||
self->min.y <= p->y && p->y <= self->max.y;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
gsk_bounding_box_contains_point_with_epsilon (const GskBoundingBox *self,
|
||||
const graphene_point_t *p,
|
||||
float epsilon)
|
||||
{
|
||||
return self->min.x - epsilon <= p->x && p->x <= self->max.x + epsilon &&
|
||||
self->min.y - epsilon <= p->y && p->y <= self->max.y + epsilon;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
gsk_bounding_box_intersection (const GskBoundingBox *a,
|
||||
const GskBoundingBox *b,
|
||||
GskBoundingBox *res)
|
||||
{
|
||||
graphene_point_t min, max;
|
||||
|
||||
min.x = MAX (a->min.x, b->min.x);
|
||||
min.y = MAX (a->min.y, b->min.y);
|
||||
max.x = MIN (a->max.x, b->max.x);
|
||||
max.y = MIN (a->max.y, b->max.y);
|
||||
|
||||
if (res)
|
||||
gsk_bounding_box_init (res, &min, &max);
|
||||
|
||||
return min.x <= max.x && min.y <= max.y;
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
-2436
File diff suppressed because it is too large
Load Diff
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gskpath.h"
|
||||
|
||||
#include "gskpathopprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSK_PATH_FLAT,
|
||||
GSK_PATH_CLOSED
|
||||
} GskPathFlags;
|
||||
|
||||
typedef struct _GskContour GskContour;
|
||||
|
||||
GskContour * gsk_rect_contour_new (const graphene_rect_t *rect);
|
||||
GskContour * gsk_rounded_rect_contour_new (const GskRoundedRect *rounded_rect);
|
||||
GskContour * gsk_circle_contour_new (const graphene_point_t *center,
|
||||
float radius,
|
||||
float start_angle,
|
||||
float end_angle);
|
||||
GskContour * gsk_standard_contour_new (GskPathFlags flags,
|
||||
const graphene_point_t *points,
|
||||
gsize n_points,
|
||||
const gskpathop *ops,
|
||||
gsize n_ops,
|
||||
gssize offset);
|
||||
|
||||
void gsk_contour_copy (GskContour * dest,
|
||||
const GskContour *src);
|
||||
GskContour * gsk_contour_dup (const GskContour *src);
|
||||
GskContour * gsk_contour_reverse (const GskContour *src);
|
||||
|
||||
gsize gsk_contour_get_size (const GskContour *self);
|
||||
GskPathFlags gsk_contour_get_flags (const GskContour *self);
|
||||
void gsk_contour_print (const GskContour *self,
|
||||
GString *string);
|
||||
gboolean gsk_contour_get_bounds (const GskContour *self,
|
||||
graphene_rect_t *bounds);
|
||||
gpointer gsk_contour_init_measure (const GskContour *self,
|
||||
float tolerance,
|
||||
float *out_length);
|
||||
void gsk_contour_free_measure (const GskContour *self,
|
||||
gpointer data);
|
||||
gboolean gsk_contour_foreach (const GskContour *self,
|
||||
float tolerance,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data);
|
||||
void gsk_contour_get_start_end (const GskContour *self,
|
||||
graphene_point_t *start,
|
||||
graphene_point_t *end);
|
||||
void gsk_contour_get_point (const GskContour *self,
|
||||
gpointer measure_data,
|
||||
float distance,
|
||||
GskPathDirection direction,
|
||||
graphene_point_t *pos,
|
||||
graphene_vec2_t *tangent);
|
||||
gboolean gsk_contour_get_closest_point (const GskContour *self,
|
||||
gpointer measure_data,
|
||||
float tolerance,
|
||||
const graphene_point_t *point,
|
||||
float threshold,
|
||||
float *out_distance,
|
||||
graphene_point_t *out_pos,
|
||||
float *out_offset,
|
||||
graphene_vec2_t *out_tangent);
|
||||
int gsk_contour_get_winding (const GskContour *self,
|
||||
gpointer measure_data,
|
||||
const graphene_point_t *point);
|
||||
void gsk_contour_add_segment (const GskContour *self,
|
||||
GskPathBuilder *builder,
|
||||
gpointer measure_data,
|
||||
gboolean emit_move_to,
|
||||
float start,
|
||||
float end);
|
||||
float gsk_contour_get_curvature (const GskContour *self,
|
||||
gpointer measure_data,
|
||||
float distance,
|
||||
graphene_point_t *center);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
-2034
File diff suppressed because it is too large
Load Diff
@@ -1,879 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "gskcurveprivate.h"
|
||||
|
||||
/* {{{ Utilities */
|
||||
|
||||
static void
|
||||
get_tangent (const graphene_point_t *p0,
|
||||
const graphene_point_t *p1,
|
||||
graphene_vec2_t *t)
|
||||
{
|
||||
graphene_vec2_init (t, p1->x - p0->x, p1->y - p0->y);
|
||||
graphene_vec2_normalize (t, t);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
acceptable (float t)
|
||||
{
|
||||
return 0 - FLT_EPSILON <= t && t <= 1 + FLT_EPSILON;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_sincosf (float angle,
|
||||
float *out_s,
|
||||
float *out_c)
|
||||
{
|
||||
#ifdef HAVE_SINCOSF
|
||||
sincosf (angle, out_s, out_c);
|
||||
#else
|
||||
*out_s = sinf (angle);
|
||||
*out_c = cosf (angle);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
align_points (const graphene_point_t *p,
|
||||
const graphene_point_t *a,
|
||||
const graphene_point_t *b,
|
||||
graphene_point_t *q,
|
||||
int n)
|
||||
{
|
||||
graphene_vec2_t n1;
|
||||
float angle;
|
||||
float s, c;
|
||||
|
||||
get_tangent (a, b, &n1);
|
||||
angle = - atan2 (graphene_vec2_get_y (&n1), graphene_vec2_get_x (&n1));
|
||||
_sincosf (angle, &s, &c);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
q[i].x = (p[i].x - a->x) * c - (p[i].y - a->y) * s;
|
||||
q[i].y = (p[i].x - a->x) * s + (p[i].y - a->y) * c;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
find_point_on_line (const graphene_point_t *p1,
|
||||
const graphene_point_t *p2,
|
||||
const graphene_point_t *q,
|
||||
float *t)
|
||||
{
|
||||
if (p2->x != p1->x)
|
||||
*t = (q->x - p1->x) / (p2->x - p1->x);
|
||||
else
|
||||
*t = (q->y - p1->y) / (p2->y - p1->y);
|
||||
}
|
||||
|
||||
/* find solutions for at^2 + bt + c = 0 */
|
||||
static int
|
||||
solve_quadratic (float a, float b, float c, float t[2])
|
||||
{
|
||||
float d;
|
||||
int n = 0;
|
||||
|
||||
if (fabs (a) > 0.0001)
|
||||
{
|
||||
if (b*b > 4*a*c)
|
||||
{
|
||||
d = sqrt (b*b - 4*a*c);
|
||||
t[n++] = (-b + d)/(2*a);
|
||||
t[n++] = (-b - d)/(2*a);
|
||||
}
|
||||
else
|
||||
{
|
||||
t[n++] = -b / (2*a);
|
||||
}
|
||||
}
|
||||
else if (fabs (b) > 0.0001)
|
||||
{
|
||||
t[n++] = -c / b;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
filter_allowable (float t[3],
|
||||
int n)
|
||||
{
|
||||
float g[3];
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
if (0 < t[i] && t[i] < 1)
|
||||
g[j++] = t[i];
|
||||
for (int i = 0; i < j; i++)
|
||||
t[i] = g[i];
|
||||
return j;
|
||||
}
|
||||
|
||||
/* Solve P = 0 where P is
|
||||
* P = (1-t)^2*pa + 2*t*(1-t)*pb + t^2*pc
|
||||
*/
|
||||
static int
|
||||
get_quadratic_roots (float pa, float pb, float pc, float roots[2])
|
||||
{
|
||||
float a, b, c, d;
|
||||
int n_roots = 0;
|
||||
|
||||
a = pa - 2 * pb + pc;
|
||||
b = 2 * (pb - pa);
|
||||
c = pa;
|
||||
|
||||
d = b*b - 4*a*c;
|
||||
|
||||
if (d > 0.0001)
|
||||
{
|
||||
float q = sqrt (d);
|
||||
roots[n_roots] = (-b + q) / (2 * a);
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
roots[n_roots] = (-b - q) / (2 * a);
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
}
|
||||
else if (fabs (d) < 0.0001)
|
||||
{
|
||||
roots[n_roots] = -b / (2 * a);
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
}
|
||||
|
||||
return n_roots;
|
||||
}
|
||||
|
||||
static float
|
||||
cuberoot (float v)
|
||||
{
|
||||
if (v < 0)
|
||||
return -pow (-v, 1.f / 3);
|
||||
return pow (v, 1.f / 3);
|
||||
}
|
||||
|
||||
/* Solve P = 0 where P is
|
||||
* P = (1-t)^3*pa + 3*t*(1-t)^2*pb + 3*t^2*(1-t)*pc + t^3*pd
|
||||
*/
|
||||
static int
|
||||
get_cubic_roots (float pa, float pb, float pc, float pd, float roots[3])
|
||||
{
|
||||
float a, b, c, d;
|
||||
float q, q2;
|
||||
float p, p3;
|
||||
float discriminant;
|
||||
float u1, v1, sd;
|
||||
int n_roots = 0;
|
||||
|
||||
d = -pa + 3*pb - 3*pc + pd;
|
||||
a = 3*pa - 6*pb + 3*pc;
|
||||
b = -3*pa + 3*pb;
|
||||
c = pa;
|
||||
|
||||
if (fabs (d) < 0.0001)
|
||||
{
|
||||
if (fabs (a) < 0.0001)
|
||||
{
|
||||
if (fabs (b) < 0.0001)
|
||||
return 0;
|
||||
|
||||
if (acceptable (-c / b))
|
||||
{
|
||||
roots[0] = -c / b;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
q = sqrt (b*b - 4*a*c);
|
||||
roots[n_roots] = (-b + q) / (2 * a);
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
|
||||
roots[n_roots] = (-b - q) / (2 * a);
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
|
||||
return n_roots;
|
||||
}
|
||||
|
||||
a /= d;
|
||||
b /= d;
|
||||
c /= d;
|
||||
|
||||
p = (3*b - a*a)/3;
|
||||
p3 = p/3;
|
||||
q = (2*a*a*a - 9*a*b + 27*c)/27;
|
||||
q2 = q/2;
|
||||
discriminant = q2*q2 + p3*p3*p3;
|
||||
|
||||
if (discriminant < 0)
|
||||
{
|
||||
float mp3 = -p/3;
|
||||
float mp33 = mp3*mp3*mp3;
|
||||
float r = sqrt (mp33);
|
||||
float t = -q / (2*r);
|
||||
float cosphi = t < -1 ? -1 : (t > 1 ? 1 : t);
|
||||
float phi = acos (cosphi);
|
||||
float crtr = cuberoot (r);
|
||||
float t1 = 2*crtr;
|
||||
|
||||
roots[n_roots] = t1 * cos (phi/3) - a/3;
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
roots[n_roots] = t1 * cos ((phi + 2*M_PI) / 3) - a/3;
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
roots[n_roots] = t1 * cos ((phi + 4*M_PI) / 3) - a/3;
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
|
||||
return n_roots;
|
||||
}
|
||||
|
||||
if (discriminant == 0)
|
||||
{
|
||||
u1 = q2 < 0 ? cuberoot (-q2) : -cuberoot (q2);
|
||||
roots[n_roots] = 2*u1 - a/3;
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
roots[n_roots] = -u1 - a/3;
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
|
||||
return n_roots;
|
||||
}
|
||||
|
||||
sd = sqrt (discriminant);
|
||||
u1 = cuberoot (sd - q2);
|
||||
v1 = cuberoot (sd + q2);
|
||||
roots[n_roots] = u1 - v1 - a/3;
|
||||
if (acceptable (roots[n_roots]))
|
||||
n_roots++;
|
||||
|
||||
return n_roots;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Cusps and inflections */
|
||||
|
||||
/* Get the points where the curvature of curve is
|
||||
* zero, or a maximum or minimum, inside the open
|
||||
* interval from 0 to 1.
|
||||
*/
|
||||
int
|
||||
gsk_curve_get_curvature_points (const GskCurve *curve,
|
||||
float t[3])
|
||||
{
|
||||
const graphene_point_t *pts = curve->cubic.points;
|
||||
graphene_point_t p[4];
|
||||
float a, b, c, d;
|
||||
float x, y, z;
|
||||
int n;
|
||||
|
||||
if (curve->op != GSK_PATH_CUBIC)
|
||||
return 0;
|
||||
|
||||
align_points (pts, &pts[0], &pts[3], p, 4);
|
||||
|
||||
a = p[2].x * p[1].y;
|
||||
b = p[3].x * p[1].y;
|
||||
c = p[1].x * p[2].y;
|
||||
d = p[3].x * p[2].y;
|
||||
|
||||
x = - 3*a + 2*b + 3*c - d;
|
||||
y = 3*a - b - 3*c;
|
||||
z = c - a;
|
||||
|
||||
n = solve_quadratic (x, y, z, t);
|
||||
return filter_allowable (t, n);
|
||||
}
|
||||
|
||||
/* Find cusps inside the open interval from 0 to 1.
|
||||
*
|
||||
* According to Stone & deRose, A Geometric Characterization
|
||||
* of Parametric Cubic curves, a necessary and sufficient
|
||||
* condition is that the first derivative vanishes.
|
||||
*/
|
||||
int
|
||||
gsk_curve_get_cusps (const GskCurve *curve,
|
||||
float t[2])
|
||||
{
|
||||
const graphene_point_t *pts = curve->cubic.points;
|
||||
graphene_point_t p[3];
|
||||
float ax, bx, cx;
|
||||
float ay, by, cy;
|
||||
float tx[3];
|
||||
int nx;
|
||||
int n = 0;
|
||||
|
||||
if (curve->op != GSK_PATH_CUBIC)
|
||||
return 0;
|
||||
|
||||
p[0].x = 3 * (pts[1].x - pts[0].x);
|
||||
p[0].y = 3 * (pts[1].y - pts[0].y);
|
||||
p[1].x = 3 * (pts[2].x - pts[1].x);
|
||||
p[1].y = 3 * (pts[2].y - pts[1].y);
|
||||
p[2].x = 3 * (pts[3].x - pts[2].x);
|
||||
p[2].y = 3 * (pts[3].y - pts[2].y);
|
||||
|
||||
ax = p[0].x - 2 * p[1].x + p[2].x;
|
||||
bx = - 2 * p[0].x + 2 * p[1].x;
|
||||
cx = p[0].x;
|
||||
|
||||
nx = solve_quadratic (ax, bx, cx, tx);
|
||||
nx = filter_allowable (tx, nx);
|
||||
|
||||
ay = p[0].y - 2 * p[1].y + p[2].y;
|
||||
by = - 2 * p[0].y + 2 * p[1].y;
|
||||
cy = p[0].y;
|
||||
|
||||
for (int i = 0; i < nx; i++)
|
||||
{
|
||||
float ti = tx[i];
|
||||
|
||||
if (0 < ti && ti < 1 &&
|
||||
fabs (ay * ti * ti + by * ti + cy) < 0.001)
|
||||
t[n++] = ti;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Intersection */
|
||||
|
||||
static int
|
||||
line_intersect (const GskCurve *curve1,
|
||||
const GskCurve *curve2,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n)
|
||||
{
|
||||
const graphene_point_t *pts1 = curve1->line.points;
|
||||
const graphene_point_t *pts2 = curve2->line.points;
|
||||
float a1 = pts1[0].x - pts1[1].x;
|
||||
float b1 = pts1[0].y - pts1[1].y;
|
||||
float a2 = pts2[0].x - pts2[1].x;
|
||||
float b2 = pts2[0].y - pts2[1].y;
|
||||
float det = a1 * b2 - b1 * a2;
|
||||
|
||||
if (fabs(det) > 0.01)
|
||||
{
|
||||
float tt = ((pts1[0].x - pts2[0].x) * b2 - (pts1[0].y - pts2[0].y) * a2) / det;
|
||||
float ss = - ((pts1[0].y - pts2[0].y) * a1 - (pts1[0].x - pts2[0].x) * b1) / det;
|
||||
|
||||
if (acceptable (tt) && acceptable (ss))
|
||||
{
|
||||
p[0].x = pts1[0].x + tt * (pts1[1].x - pts1[0].x);
|
||||
p[0].y = pts1[0].y + tt * (pts1[1].y - pts1[0].y);
|
||||
|
||||
t1[0] = tt;
|
||||
t2[0] = ss;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else /* parallel lines */
|
||||
{
|
||||
float r = a1 * (pts1[1].y - pts2[0].y) - (pts1[1].x - pts2[0].x) * b1;
|
||||
float dist = (r * r) / (a1 * a1 + b1 * b1);
|
||||
float t, s, tt, ss;
|
||||
|
||||
if (dist > 0.01)
|
||||
return 0;
|
||||
|
||||
if (pts1[1].x != pts1[0].x)
|
||||
{
|
||||
t = (pts2[0].x - pts1[0].x) / (pts1[1].x - pts1[0].x);
|
||||
s = (pts2[1].x - pts1[0].x) / (pts1[1].x - pts1[0].x);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = (pts2[0].y - pts1[0].y) / (pts1[1].y - pts1[0].y);
|
||||
s = (pts2[1].y - pts1[0].y) / (pts1[1].y - pts1[0].y);
|
||||
}
|
||||
|
||||
if ((t < 0 && s < 0) || (t > 1 && s > 1))
|
||||
return 0;
|
||||
|
||||
if (acceptable (t))
|
||||
{
|
||||
t1[0] = t;
|
||||
t2[0] = 0;
|
||||
p[0] = pts2[0];
|
||||
}
|
||||
else if (t < 0)
|
||||
{
|
||||
if (pts2[1].x != pts2[0].x)
|
||||
tt = (pts1[0].x - pts2[0].x) / (pts2[1].x - pts2[0].x);
|
||||
else
|
||||
tt = (pts1[0].y - pts2[0].y) / (pts2[1].y - pts2[0].y);
|
||||
|
||||
t1[0] = 0;
|
||||
t2[0] = tt;
|
||||
p[0] = pts1[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pts2[1].x != pts2[0].x)
|
||||
tt = (pts1[1].x - pts2[0].x) / (pts2[1].x - pts2[0].x);
|
||||
else
|
||||
tt = (pts1[1].y - pts2[0].y) / (pts2[1].y - pts2[0].y);
|
||||
|
||||
t1[0] = 1;
|
||||
t2[0] = tt;
|
||||
p[0] = pts1[1];
|
||||
}
|
||||
|
||||
if (acceptable (s))
|
||||
{
|
||||
if (t2[0] == 1)
|
||||
return 1;
|
||||
|
||||
t1[1] = s;
|
||||
t2[1] = 1;
|
||||
p[1] = pts2[1];
|
||||
}
|
||||
else if (s < 0)
|
||||
{
|
||||
if (t1[0] == 0)
|
||||
return 1;
|
||||
|
||||
if (pts2[1].x != pts2[0].x)
|
||||
ss = (pts1[0].x - pts2[0].x) / (pts2[1].x - pts2[0].x);
|
||||
else
|
||||
ss = (pts1[0].y - pts2[0].y) / (pts2[1].y - pts2[0].y);
|
||||
|
||||
t1[1] = 0;
|
||||
t2[1] = ss;
|
||||
p[1] = pts1[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t1[0] == 1)
|
||||
return 1;
|
||||
|
||||
if (pts2[1].x != pts2[0].x)
|
||||
ss = (pts1[1].x - pts2[0].x) / (pts2[1].x - pts2[0].x);
|
||||
else
|
||||
ss = (pts1[1].y - pts2[0].y) / (pts2[1].y - pts2[0].y);
|
||||
|
||||
t1[1] = 1;
|
||||
t2[1] = ss;
|
||||
p[1] = pts1[1];
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
line_quad_intersect (const GskCurve *curve1,
|
||||
const GskCurve *curve2,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n)
|
||||
{
|
||||
const graphene_point_t *a = &curve1->line.points[0];
|
||||
const graphene_point_t *b = &curve1->line.points[1];
|
||||
graphene_point_t pts[4];
|
||||
float t[2];
|
||||
int m, i, j;
|
||||
|
||||
/* Rotate things to place curve1 on the x axis,
|
||||
* then solve curve2 for y == 0.
|
||||
*/
|
||||
align_points (curve2->quad.points, a, b, pts, 3);
|
||||
|
||||
m = get_quadratic_roots (pts[0].y, pts[1].y, pts[2].y, t);
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < m; i++)
|
||||
{
|
||||
t2[j] = t[i];
|
||||
gsk_curve_get_point (curve2, t2[j], &p[j]);
|
||||
find_point_on_line (a, b, &p[j], &t1[j]);
|
||||
if (acceptable (t1[j]))
|
||||
j++;
|
||||
if (j == n)
|
||||
break;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
static int
|
||||
line_cubic_intersect (const GskCurve *curve1,
|
||||
const GskCurve *curve2,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n)
|
||||
{
|
||||
const graphene_point_t *a = &curve1->line.points[0];
|
||||
const graphene_point_t *b = &curve1->line.points[1];
|
||||
graphene_point_t pts[4];
|
||||
float t[3];
|
||||
int m, i, j;
|
||||
|
||||
/* Rotate things to place curve1 on the x axis,
|
||||
* then solve curve2 for y == 0.
|
||||
*/
|
||||
align_points (curve2->cubic.points, a, b, pts, 4);
|
||||
|
||||
m = get_cubic_roots (pts[0].y, pts[1].y, pts[2].y, pts[3].y, t);
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < m; i++)
|
||||
{
|
||||
t2[j] = t[i];
|
||||
gsk_curve_get_point (curve2, t2[j], &p[j]);
|
||||
find_point_on_line (a, b, &p[j], &t1[j]);
|
||||
if (acceptable (t1[j]))
|
||||
j++;
|
||||
if (j == n)
|
||||
break;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
#define MAX_LEVEL 25
|
||||
#define TOLERANCE 0.001
|
||||
|
||||
static void
|
||||
cubic_intersect_recurse (const GskCurve *curve1,
|
||||
const GskCurve *curve2,
|
||||
float t1l,
|
||||
float t1r,
|
||||
float t2l,
|
||||
float t2r,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n,
|
||||
int *pos,
|
||||
int level)
|
||||
{
|
||||
GskCurve p11, p12, p21, p22;
|
||||
GskBoundingBox b1, b2;
|
||||
float d1, d2;
|
||||
|
||||
if (*pos == n)
|
||||
return;
|
||||
|
||||
if (level == MAX_LEVEL)
|
||||
return;
|
||||
|
||||
gsk_curve_get_bounds (curve1, &b1);
|
||||
gsk_curve_get_bounds (curve2, &b2);
|
||||
if (!gsk_bounding_box_intersection (&b1, &b2, NULL))
|
||||
return;
|
||||
|
||||
gsk_curve_get_tight_bounds (curve1, &b1);
|
||||
if (!gsk_bounding_box_intersection (&b1, &b2, NULL))
|
||||
return;
|
||||
|
||||
gsk_curve_get_tight_bounds (curve2, &b2);
|
||||
if (!gsk_bounding_box_intersection (&b1, &b2, NULL))
|
||||
return;
|
||||
|
||||
d1 = (t1r - t1l) / 2;
|
||||
d2 = (t2r - t2l) / 2;
|
||||
|
||||
if (b1.max.x - b1.min.x < TOLERANCE && b1.max.y - b1.min.y < TOLERANCE &&
|
||||
b2.max.x - b2.min.x < TOLERANCE && b2.max.y - b2.min.y < TOLERANCE)
|
||||
{
|
||||
graphene_point_t c;
|
||||
t1[*pos] = t1l + d1;
|
||||
t2[*pos] = t2l + d2;
|
||||
gsk_curve_get_point (curve1, 0.5, &c);
|
||||
|
||||
for (int i = 0; i < *pos; i++)
|
||||
{
|
||||
if (graphene_point_near (&c, &p[i], 0.1))
|
||||
return;
|
||||
}
|
||||
|
||||
p[*pos] = c;
|
||||
(*pos)++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gsk_curve_split (curve1, 0.5, &p11, &p12);
|
||||
gsk_curve_split (curve2, 0.5, &p21, &p22);
|
||||
|
||||
cubic_intersect_recurse (&p11, &p21, t1l, t1l + d1, t2l, t2l + d2, t1, t2, p, n, pos, level + 1);
|
||||
cubic_intersect_recurse (&p11, &p22, t1l, t1l + d1, t2l + d2, t2r, t1, t2, p, n, pos, level + 1);
|
||||
cubic_intersect_recurse (&p12, &p21, t1l + d1, t1r, t2l, t2l + d2, t1, t2, p, n, pos, level + 1);
|
||||
cubic_intersect_recurse (&p12, &p22, t1l + d1, t1r, t2l + d2, t2r, t1, t2, p, n, pos, level + 1);
|
||||
}
|
||||
|
||||
static int
|
||||
cubic_intersect (const GskCurve *curve1,
|
||||
const GskCurve *curve2,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
cubic_intersect_recurse (curve1, curve2, 0, 1, 0, 1, t1, t2, p, n, &pos, 0);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void
|
||||
get_bounds (const GskCurve *curve,
|
||||
float tl,
|
||||
float tr,
|
||||
GskBoundingBox *bounds)
|
||||
{
|
||||
GskCurve c;
|
||||
|
||||
gsk_curve_segment (curve, tl, tr, &c);
|
||||
gsk_curve_get_tight_bounds (&c, bounds);
|
||||
}
|
||||
|
||||
static void
|
||||
general_intersect_recurse (const GskCurve *curve1,
|
||||
const GskCurve *curve2,
|
||||
float t1l,
|
||||
float t1r,
|
||||
float t2l,
|
||||
float t2r,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n,
|
||||
int *pos,
|
||||
int level)
|
||||
{
|
||||
GskBoundingBox b1, b2;
|
||||
float d1, d2;
|
||||
|
||||
if (*pos == n)
|
||||
return;
|
||||
|
||||
if (level == MAX_LEVEL)
|
||||
return;
|
||||
|
||||
get_bounds (curve1, t1l, t1r, &b1);
|
||||
get_bounds (curve2, t2l, t2r, &b2);
|
||||
|
||||
if (!gsk_bounding_box_intersection (&b1, &b2, NULL))
|
||||
return;
|
||||
|
||||
d1 = (t1r - t1l) / 2;
|
||||
d2 = (t2r - t2l) / 2;
|
||||
|
||||
if (b1.max.x - b1.min.x < TOLERANCE && b1.max.y - b1.min.y < TOLERANCE &&
|
||||
b2.max.x - b2.min.x < TOLERANCE && b2.max.y - b2.min.y < TOLERANCE)
|
||||
{
|
||||
graphene_point_t c;
|
||||
t1[*pos] = t1l + d1;
|
||||
t2[*pos] = t2l + d2;
|
||||
gsk_curve_get_point (curve1, t1[*pos], &c);
|
||||
|
||||
for (int i = 0; i < *pos; i++)
|
||||
{
|
||||
if (graphene_point_near (&c, &p[i], 0.1))
|
||||
return;
|
||||
}
|
||||
|
||||
p[*pos] = c;
|
||||
(*pos)++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Note that in the conic case, we cannot just split the curves and
|
||||
* pass the two halves down, since splitting changes the parametrization,
|
||||
* and we need the t's to be valid parameters wrt to the original curve.
|
||||
*
|
||||
* So, instead, we determine the bounding boxes above by always starting
|
||||
* from the original curve. That is a bit less efficient, but also works
|
||||
* for conics.
|
||||
*/
|
||||
general_intersect_recurse (curve1, curve2, t1l, t1l + d1, t2l, t2l + d2, t1, t2, p, n, pos, level + 1);
|
||||
general_intersect_recurse (curve1, curve2, t1l, t1l + d1, t2l + d2, t2r, t1, t2, p, n, pos, level + 1);
|
||||
general_intersect_recurse (curve1, curve2, t1l + d1, t1r, t2l, t2l + d2, t1, t2, p, n, pos, level + 1);
|
||||
general_intersect_recurse (curve1, curve2, t1l + d1, t1r, t2l + d2, t2r, t1, t2, p, n, pos, level + 1);
|
||||
}
|
||||
|
||||
static int
|
||||
general_intersect (const GskCurve *curve1,
|
||||
const GskCurve *curve2,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
general_intersect_recurse (curve1, curve2, 0, 1, 0, 1, t1, t2, p, n, &pos, 0);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static int
|
||||
curve_self_intersect (const GskCurve *curve,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n)
|
||||
{
|
||||
float tt[3], ss[3], s;
|
||||
graphene_point_t pp[3];
|
||||
int m;
|
||||
GskCurve cs, ce;
|
||||
|
||||
if (curve->op != GSK_PATH_CUBIC)
|
||||
return 0;
|
||||
|
||||
s = 0.5;
|
||||
m = gsk_curve_get_curvature_points (curve, tt);
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
if (gsk_curve_get_curvature (curve, tt[i], NULL) == 0)
|
||||
{
|
||||
s = tt[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gsk_curve_split (curve, s, &cs, &ce);
|
||||
|
||||
m = cubic_intersect (&cs, &ce, tt, ss, pp, 3);
|
||||
|
||||
if (m > 1)
|
||||
{
|
||||
/* One of the (at most 2) intersections we found
|
||||
* must be the common point where we split the curve.
|
||||
* It will have a t value of 1 and an s value of 0.
|
||||
*/
|
||||
if (fabs (tt[0] - 1) > 1e-3)
|
||||
{
|
||||
t1[0] = t2[0] = tt[0] * s;
|
||||
p[0] = pp[0];
|
||||
}
|
||||
else if (fabs (tt[1] - 1) > 1e-3)
|
||||
{
|
||||
t1[0] = t2[0] = tt[1] * s;
|
||||
p[0] = pp[1];
|
||||
}
|
||||
|
||||
if (n == 1)
|
||||
return 1;
|
||||
|
||||
if (fabs (ss[0]) > 1e-3)
|
||||
{
|
||||
t1[1] = t2[1] = s + ss[0] * (1 - s);
|
||||
p[1] = pp[0];
|
||||
}
|
||||
else if (fabs (ss[1]) > 1e-3)
|
||||
{
|
||||
t1[1] = t2[1] = s + ss[1] * (1 - s);
|
||||
p[1] = pp[1];
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
curve_equal (const GskCurve *c1,
|
||||
const GskCurve *c2)
|
||||
{
|
||||
gsize curve_size[] = {
|
||||
sizeof (GskLineCurve),
|
||||
sizeof (GskLineCurve),
|
||||
sizeof (GskLineCurve),
|
||||
sizeof (GskQuadCurve),
|
||||
sizeof (GskCubicCurve),
|
||||
sizeof (GskConicCurve)
|
||||
};
|
||||
|
||||
return c1->op == c2->op && memcmp (c1, c2, curve_size[c1->op]) == 0;
|
||||
}
|
||||
|
||||
/* Place intersections between the curves in p, and their Bezier positions
|
||||
* in t1 and t2, up to n. Return the number of intersections found.
|
||||
*
|
||||
* Note that two cubic Beziers can have up to 9 intersections.
|
||||
*/
|
||||
int
|
||||
gsk_curve_intersect (const GskCurve *curve1,
|
||||
const GskCurve *curve2,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n)
|
||||
{
|
||||
GskPathOperation op1 = curve1->op;
|
||||
GskPathOperation op2 = curve2->op;
|
||||
|
||||
if (op1 == GSK_PATH_CLOSE)
|
||||
op1 = GSK_PATH_LINE;
|
||||
|
||||
if (op2 == GSK_PATH_CLOSE)
|
||||
op2 = GSK_PATH_LINE;
|
||||
|
||||
if (curve_equal (curve1, curve2))
|
||||
return curve_self_intersect (curve1, t1, t2, p, n);
|
||||
|
||||
/* We special-case line-line and line-cubic intersections,
|
||||
* since we can solve them directly.
|
||||
* Everything else is done via bisection.
|
||||
*/
|
||||
if (op1 == GSK_PATH_LINE && op2 == GSK_PATH_LINE)
|
||||
return line_intersect (curve1, curve2, t1, t2, p, n);
|
||||
else if (op1 == GSK_PATH_LINE && op2 == GSK_PATH_QUAD)
|
||||
return line_quad_intersect (curve1, curve2, t1, t2, p, n);
|
||||
else if (op1 == GSK_PATH_QUAD && op2 == GSK_PATH_LINE)
|
||||
return line_quad_intersect (curve2, curve1, t2, t1, p, n);
|
||||
else if (op1 == GSK_PATH_LINE && op2 == GSK_PATH_CUBIC)
|
||||
return line_cubic_intersect (curve1, curve2, t1, t2, p, n);
|
||||
else if (op1 == GSK_PATH_CUBIC && op2 == GSK_PATH_LINE)
|
||||
return line_cubic_intersect (curve2, curve1, t2, t1, p, n);
|
||||
else if ((op1 == GSK_PATH_QUAD || op1 == GSK_PATH_CUBIC) &&
|
||||
(op2 == GSK_PATH_QUAD || op2 == GSK_PATH_CUBIC))
|
||||
return cubic_intersect (curve1, curve2, t1, t2, p, n);
|
||||
else
|
||||
return general_intersect (curve1, curve2, t1, t2, p, n);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gskpathopprivate.h"
|
||||
#include "gskpath.h"
|
||||
#include "gskboundingboxprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef gpointer gskpathop;
|
||||
|
||||
typedef union _GskCurve GskCurve;
|
||||
|
||||
typedef struct _GskLineCurve GskLineCurve;
|
||||
typedef struct _GskQuadCurve GskQuadCurve;
|
||||
typedef struct _GskCubicCurve GskCubicCurve;
|
||||
typedef struct _GskConicCurve GskConicCurve;
|
||||
|
||||
struct _GskLineCurve
|
||||
{
|
||||
GskPathOperation op;
|
||||
|
||||
gboolean padding;
|
||||
|
||||
graphene_point_t points[2];
|
||||
};
|
||||
|
||||
struct _GskQuadCurve
|
||||
{
|
||||
GskPathOperation op;
|
||||
|
||||
gboolean has_coefficients;
|
||||
|
||||
graphene_point_t points[3];
|
||||
|
||||
graphene_point_t coeffs[3];
|
||||
};
|
||||
|
||||
struct _GskCubicCurve
|
||||
{
|
||||
GskPathOperation op;
|
||||
|
||||
gboolean has_coefficients;
|
||||
|
||||
graphene_point_t points[4];
|
||||
|
||||
graphene_point_t coeffs[4];
|
||||
};
|
||||
|
||||
struct _GskConicCurve
|
||||
{
|
||||
GskPathOperation op;
|
||||
|
||||
gboolean has_coefficients;
|
||||
|
||||
/* points[0], points[1], points[3] are the control points,
|
||||
* points[2].x is the weight
|
||||
*/
|
||||
graphene_point_t points[4];
|
||||
|
||||
graphene_point_t num[3];
|
||||
graphene_point_t denom[3];
|
||||
};
|
||||
|
||||
union _GskCurve
|
||||
{
|
||||
GskPathOperation op;
|
||||
GskLineCurve line;
|
||||
GskQuadCurve quad;
|
||||
GskCubicCurve cubic;
|
||||
GskConicCurve conic;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GSK_CURVE_LINE_REASON_STRAIGHT,
|
||||
GSK_CURVE_LINE_REASON_SHORT
|
||||
} GskCurveLineReason;
|
||||
|
||||
typedef gboolean (* GskCurveAddLineFunc) (const graphene_point_t *from,
|
||||
const graphene_point_t *to,
|
||||
float from_progress,
|
||||
float to_progress,
|
||||
GskCurveLineReason reason,
|
||||
gpointer user_data);
|
||||
|
||||
typedef gboolean (* GskCurveAddCurveFunc) (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
float weight,
|
||||
gpointer user_data);
|
||||
|
||||
void gsk_curve_init (GskCurve *curve,
|
||||
gskpathop op);
|
||||
void gsk_curve_init_foreach (GskCurve *curve,
|
||||
GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
float weight);
|
||||
|
||||
void gsk_curve_print (const GskCurve *curve,
|
||||
GString *string);
|
||||
|
||||
char * gsk_curve_to_string (const GskCurve *curve);
|
||||
|
||||
gskpathop gsk_curve_pathop (const GskCurve *curve);
|
||||
const graphene_point_t *gsk_curve_get_start_point (const GskCurve *curve);
|
||||
const graphene_point_t *gsk_curve_get_end_point (const GskCurve *curve);
|
||||
void gsk_curve_get_start_tangent (const GskCurve *curve,
|
||||
graphene_vec2_t *tangent);
|
||||
void gsk_curve_get_end_tangent (const GskCurve *curve,
|
||||
graphene_vec2_t *tangent);
|
||||
void gsk_curve_get_point (const GskCurve *curve,
|
||||
float progress,
|
||||
graphene_point_t *pos);
|
||||
void gsk_curve_get_tangent (const GskCurve *curve,
|
||||
float progress,
|
||||
graphene_vec2_t *tangent);
|
||||
void gsk_curve_reverse (const GskCurve *curve,
|
||||
GskCurve *reverse);
|
||||
void gsk_curve_split (const GskCurve *curve,
|
||||
float progress,
|
||||
GskCurve *start,
|
||||
GskCurve *end);
|
||||
void gsk_curve_segment (const GskCurve *curve,
|
||||
float start,
|
||||
float end,
|
||||
GskCurve *segment);
|
||||
gboolean gsk_curve_decompose (const GskCurve *curve,
|
||||
float tolerance,
|
||||
GskCurveAddLineFunc add_line_func,
|
||||
gpointer user_data);
|
||||
gboolean gsk_curve_decompose_curve (const GskCurve *curve,
|
||||
GskPathForeachFlags flags,
|
||||
float tolerance,
|
||||
GskCurveAddCurveFunc add_curve_func,
|
||||
gpointer user_data);
|
||||
|
||||
#define gsk_curve_builder_to(curve, builder) gsk_path_builder_pathop_to ((builder), gsk_curve_pathop (curve))
|
||||
|
||||
float gsk_curve_get_curvature (const GskCurve *curve,
|
||||
float t,
|
||||
graphene_point_t *center);
|
||||
void gsk_curve_get_bounds (const GskCurve *curve,
|
||||
GskBoundingBox *bounds);
|
||||
void gsk_curve_get_tight_bounds (const GskCurve *curve,
|
||||
GskBoundingBox *bounds);
|
||||
|
||||
int gsk_curve_get_curvature_points (const GskCurve *curve,
|
||||
float t[3]);
|
||||
|
||||
int gsk_curve_get_cusps (const GskCurve *curve,
|
||||
float t[2]);
|
||||
|
||||
int gsk_curve_intersect (const GskCurve *curve1,
|
||||
const GskCurve *curve2,
|
||||
float *t1,
|
||||
float *t2,
|
||||
graphene_point_t *p,
|
||||
int n);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
+2
-3
@@ -12,12 +12,11 @@ static const GdkDebugKey gsk_debug_keys[] = {
|
||||
{ "surface", GSK_DEBUG_SURFACE, "Information about surfaces" },
|
||||
{ "fallback", GSK_DEBUG_FALLBACK, "Information about fallbacks" },
|
||||
{ "glyphcache", GSK_DEBUG_GLYPH_CACHE, "Information about glyph caching" },
|
||||
{ "verbose", GSK_DEBUG_VERBOSE, "Print verbose output while rendering" },
|
||||
{ "geometry", GSK_DEBUG_GEOMETRY, "Show borders (when using cairo)" },
|
||||
{ "full-redraw", GSK_DEBUG_FULL_REDRAW, "Force full redraws" },
|
||||
{ "sync", GSK_DEBUG_SYNC, "Sync after each frame" },
|
||||
{ "staging", GSK_DEBUG_STAGING, "Use a staging image for texture upload (Vulkan only)" },
|
||||
{ "no-glyphy", GSK_DEBUG_NO_GLYPHY, "Don't use GPU for glyph rendering (OpenGL only)", TRUE },
|
||||
{ "vulkan-staging-image", GSK_DEBUG_VULKAN_STAGING_IMAGE, "Use a staging image for Vulkan texture upload" },
|
||||
{ "vulkan-staging-buffer", GSK_DEBUG_VULKAN_STAGING_BUFFER, "Use a staging buffer for Vulkan texture upload" }
|
||||
};
|
||||
|
||||
static guint gsk_debug_flags;
|
||||
|
||||
@@ -14,13 +14,12 @@ typedef enum {
|
||||
GSK_DEBUG_VULKAN = 1 << 5,
|
||||
GSK_DEBUG_FALLBACK = 1 << 6,
|
||||
GSK_DEBUG_GLYPH_CACHE = 1 << 7,
|
||||
GSK_DEBUG_VERBOSE = 1 << 8,
|
||||
/* flags below may affect behavior */
|
||||
GSK_DEBUG_GEOMETRY = 1 << 9,
|
||||
GSK_DEBUG_FULL_REDRAW = 1 << 10,
|
||||
GSK_DEBUG_SYNC = 1 << 11,
|
||||
GSK_DEBUG_STAGING = 1 << 12,
|
||||
GSK_DEBUG_NO_GLYPHY = 1 << 13
|
||||
GSK_DEBUG_VULKAN_STAGING_IMAGE = 1 << 12,
|
||||
GSK_DEBUG_VULKAN_STAGING_BUFFER = 1 << 13
|
||||
} GskDebugFlags;
|
||||
|
||||
#define GSK_DEBUG_ANY ((1 << 13) - 1)
|
||||
|
||||
+1
-43
@@ -170,49 +170,6 @@ typedef enum {
|
||||
GSK_CORNER_BOTTOM_LEFT
|
||||
} GskCorner;
|
||||
|
||||
/**
|
||||
* GskPathOperation:
|
||||
* @GSK_PATH_MOVE: A move-to operation, with 1 point describing the target point.
|
||||
* @GSK_PATH_CLOSE: A close operation ending the current contour with a line back
|
||||
* to the starting point. Two points describe the start and end of the line.
|
||||
* @GSK_PATH_LINE: A line-to operation, with 2 points describing the start and
|
||||
* end point of a straight line.
|
||||
* @GSK_PATH_QUAD: A curve-to operation describing a quadratic Bézier curve
|
||||
* with 3 points describing the start point, the control point and the end
|
||||
* point of the curve.
|
||||
* @GSK_PATH_CUBIC: A curve-to operation describing a cubic Bézier curve with 4
|
||||
* points describing the start point, the two control points and the end point
|
||||
* of the curve.
|
||||
* @GSK_PATH_CONIC: A weighted quadratic Bézier curve with 3 points describing
|
||||
* the start point, control point and end point of the curve. A weight for the
|
||||
* curve will be passed, too.
|
||||
*
|
||||
* Path operations can be used to approximate a `GskPath`.
|
||||
*
|
||||
* More values may be added in the future.
|
||||
**/
|
||||
typedef enum {
|
||||
GSK_PATH_MOVE,
|
||||
GSK_PATH_CLOSE,
|
||||
GSK_PATH_LINE,
|
||||
GSK_PATH_QUAD,
|
||||
GSK_PATH_CUBIC,
|
||||
GSK_PATH_CONIC,
|
||||
} GskPathOperation;
|
||||
|
||||
/**
|
||||
* GskPathDirection:
|
||||
* @GSK_PATH_START: The side that leads to the start of the path
|
||||
* @GSK_PATH_END: The side that leads to the end of the path
|
||||
*
|
||||
* The values of the `GskPathDirection` enum are used to pick one
|
||||
* of the two sides of the path that at a given point on the path.
|
||||
*/
|
||||
typedef enum {
|
||||
GSK_PATH_START,
|
||||
GSK_PATH_END
|
||||
} GskPathDirection;
|
||||
|
||||
/**
|
||||
* GskSerializationError:
|
||||
* @GSK_SERIALIZATION_UNSUPPORTED_FORMAT: The format can not be identified
|
||||
@@ -317,3 +274,4 @@ typedef enum
|
||||
GSK_MASK_MODE_LUMINANCE,
|
||||
GSK_MASK_MODE_INVERTED_LUMINANCE
|
||||
} GskMaskMode;
|
||||
|
||||
|
||||
-1187
File diff suppressed because it is too large
Load Diff
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gsk/gsk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
|
||||
#include <gsk/gsktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GSK_FILL_RULE_WINDING,
|
||||
GSK_FILL_RULE_EVEN_ODD
|
||||
} GskFillRule;
|
||||
|
||||
/**
|
||||
* GskPathForeachFlags:
|
||||
* @GSK_PATH_FOREACH_ALLOW_QUAD: Allow emission of `GSK_PATH_QUAD` operations
|
||||
* @GSK_PATH_FOREACH_ALLOW_CUBIC: Allow emission of `GSK_PATH_CUBIC` operations.
|
||||
* @GSK_PATH_FOREACH_ALLOW_CONIC: Allow emission of `GSK_PATH_CONIC` operations.
|
||||
*
|
||||
* Flags that can be passed to gsk_path_foreach() to enable additional
|
||||
* features.
|
||||
*
|
||||
* By default, [method@Gsk.Path.foreach] will only emit a path with all operations
|
||||
* flattened to straight lines to allow for maximum compatibility. The only
|
||||
* operations emitted will be `GSK_PATH_MOVE`, `GSK_PATH_LINE` and `GSK_PATH_CLOSE`.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GSK_PATH_FOREACH_ALLOW_QUAD = (1 << 0),
|
||||
GSK_PATH_FOREACH_ALLOW_CUBIC = (1 << 1),
|
||||
GSK_PATH_FOREACH_ALLOW_CONIC = (1 << 2),
|
||||
} GskPathForeachFlags;
|
||||
|
||||
/**
|
||||
* GskPathForeachFunc:
|
||||
* @op: The operation to perform
|
||||
* @pts: The points of the operation
|
||||
* @n_pts: The number of points
|
||||
* @weight: The weight for conic curves, or unused if not a conic curve.
|
||||
* @user_data: The user data provided with the function
|
||||
*
|
||||
* Prototype of the callback to iterate throught the operations of
|
||||
* a path.
|
||||
*
|
||||
* Returns: %TRUE to continue evaluating the path, %FALSE to
|
||||
* immediately abort and not call the function again.
|
||||
*/
|
||||
typedef gboolean (* GskPathForeachFunc) (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
float weight,
|
||||
gpointer user_data);
|
||||
|
||||
#define GSK_TYPE_PATH (gsk_path_get_type ())
|
||||
|
||||
GType gsk_path_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GskPath * gsk_path_ref (GskPath *self);
|
||||
void gsk_path_unref (GskPath *self);
|
||||
void gsk_path_print (GskPath *self,
|
||||
GString *string);
|
||||
char * gsk_path_to_string (GskPath *self);
|
||||
GskPath * gsk_path_parse (const char *string);
|
||||
void gsk_path_to_cairo (GskPath *self,
|
||||
cairo_t *cr);
|
||||
gboolean gsk_path_is_empty (GskPath *self);
|
||||
gboolean gsk_path_get_bounds (GskPath *self,
|
||||
graphene_rect_t *bounds);
|
||||
gboolean gsk_path_foreach (GskPath *self,
|
||||
GskPathForeachFlags flags,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPath, gsk_path_unref)
|
||||
|
||||
G_END_DECLS
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gsk/gsk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
|
||||
#include <gsk/gskroundedrect.h>
|
||||
#include <gsk/gsktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_PATH_BUILDER (gsk_path_builder_get_type ())
|
||||
|
||||
GType gsk_path_builder_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GskPathBuilder * gsk_path_builder_new (void);
|
||||
GskPathBuilder * gsk_path_builder_ref (GskPathBuilder *self);
|
||||
void gsk_path_builder_unref (GskPathBuilder *self);
|
||||
GskPath * gsk_path_builder_free_to_path (GskPathBuilder *self) G_GNUC_WARN_UNUSED_RESULT;
|
||||
GskPath * gsk_path_builder_to_path (GskPathBuilder *self) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
const graphene_point_t *gsk_path_builder_get_current_point (GskPathBuilder *self);
|
||||
|
||||
void gsk_path_builder_add_path (GskPathBuilder *self,
|
||||
GskPath *path);
|
||||
void gsk_path_builder_add_reverse_path (GskPathBuilder *self,
|
||||
GskPath *path);
|
||||
void gsk_path_builder_add_cairo_path (GskPathBuilder *self,
|
||||
const cairo_path_t *path);
|
||||
void gsk_path_builder_add_layout (GskPathBuilder *self,
|
||||
PangoLayout *layout);
|
||||
void gsk_path_builder_add_rect (GskPathBuilder *self,
|
||||
const graphene_rect_t *rect);
|
||||
void gsk_path_builder_add_rounded_rect (GskPathBuilder *self,
|
||||
const GskRoundedRect *rect);
|
||||
void gsk_path_builder_add_circle (GskPathBuilder *self,
|
||||
const graphene_point_t *center,
|
||||
float radius);
|
||||
void gsk_path_builder_add_ellipse (GskPathBuilder *self,
|
||||
const graphene_point_t *center,
|
||||
const graphene_size_t *radius);
|
||||
void gsk_path_builder_add_segment (GskPathBuilder *self,
|
||||
GskPathMeasure *measure,
|
||||
float start,
|
||||
float end);
|
||||
void gsk_path_builder_move_to (GskPathBuilder *self,
|
||||
float x,
|
||||
float y);
|
||||
void gsk_path_builder_rel_move_to (GskPathBuilder *self,
|
||||
float x,
|
||||
float y);
|
||||
void gsk_path_builder_line_to (GskPathBuilder *self,
|
||||
float x,
|
||||
float y);
|
||||
void gsk_path_builder_rel_line_to (GskPathBuilder *self,
|
||||
float x,
|
||||
float y);
|
||||
void gsk_path_builder_quad_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2);
|
||||
void gsk_path_builder_rel_quad_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2);
|
||||
void gsk_path_builder_cubic_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float x3,
|
||||
float y3);
|
||||
void gsk_path_builder_rel_cubic_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float x3,
|
||||
float y3);
|
||||
void gsk_path_builder_conic_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float weight);
|
||||
void gsk_path_builder_rel_conic_to (GskPathBuilder *self,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float weight);
|
||||
void gsk_path_builder_close (GskPathBuilder *self);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPathBuilder, gsk_path_builder_unref)
|
||||
|
||||
G_END_DECLS
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user