Compare commits
3 Commits
issue-4136
...
ebassi/set
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24b69a9a10 | ||
|
|
043eea6ae3 | ||
|
|
181fce8342 |
@@ -25,7 +25,7 @@ variables:
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v34"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v33"
|
||||
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
|
||||
|
||||
.only-default:
|
||||
|
||||
@@ -53,7 +53,6 @@ RUN dnf -y install \
|
||||
libpng-devel \
|
||||
librsvg2 \
|
||||
libselinux-devel \
|
||||
libtiff-devel \
|
||||
libubsan \
|
||||
libXcomposite-devel \
|
||||
libXcursor-devel \
|
||||
|
||||
13
README.md
13
README.md
@@ -10,12 +10,10 @@ GTK is a multi-platform toolkit for creating graphical user interfaces.
|
||||
Offering a complete set of widgets, GTK is suitable for projects ranging
|
||||
from small one-off projects to complete application suites.
|
||||
|
||||
GTK is a free and open-source software project. The licensing terms
|
||||
for GTK, the GNU LGPL, allow it to be used by all developers, including those
|
||||
developing proprietary software, without any license fees or royalties.
|
||||
|
||||
GTK is hosted by the GNOME project (thanks!) and used by a wide variety
|
||||
of applications and projects.
|
||||
GTK is free software and part of the GNU Project. However, the
|
||||
licensing terms for GTK, the GNU LGPL, allow it to be used by all
|
||||
developers, including those developing proprietary software, without any
|
||||
license fees or royalties.
|
||||
|
||||
The official download location
|
||||
|
||||
@@ -153,9 +151,6 @@ Contributing to GTK
|
||||
Please, follow the [contribution guide](./CONTRIBUTING.md) to know how to
|
||||
start contributing to GTK.
|
||||
|
||||
If you want to support GTK financially, please consider donating to
|
||||
the GNOME project, which runs the infrastructure hosting GTK.
|
||||
|
||||
Release notes
|
||||
-------------
|
||||
|
||||
|
||||
286
config.h.meson
Normal file
286
config.h.meson
Normal file
@@ -0,0 +1,286 @@
|
||||
/* always defined to indicate that i18n is enabled */
|
||||
#define ENABLE_NLS 1
|
||||
|
||||
/* Use structured logging */
|
||||
#define G_LOG_STRUCTURED 1
|
||||
|
||||
/* The prefix for our gettext translation domains. */
|
||||
#mesondefine GETTEXT_PACKAGE
|
||||
|
||||
/* Disable deprecation warnings from glib */
|
||||
#mesondefine GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
/* Define the location where the catalogs will be installed */
|
||||
#mesondefine GTK_LOCALEDIR
|
||||
|
||||
/* Define to 1 if you have the `bind_textdomain_codeset' function. */
|
||||
#mesondefine HAVE_BIND_TEXTDOMAIN_CODESET
|
||||
|
||||
/* Have the cloudproviders library */
|
||||
#mesondefine HAVE_CLOUDPROVIDERS
|
||||
|
||||
/* define if we have colord */
|
||||
#mesondefine HAVE_COLORD
|
||||
|
||||
/* Define to 1 if you have the <crt_externs.h> header file. */
|
||||
#mesondefine HAVE_CRT_EXTERNS_H
|
||||
|
||||
/* Define to 1 if you have the `dcgettext' function. */
|
||||
#mesondefine HAVE_DCGETTEXT
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#mesondefine HAVE_DLFCN_H
|
||||
|
||||
/* Have the ffmpeg library */
|
||||
#mesondefine HAVE_FFMPEG
|
||||
|
||||
/* Define to 1 if you have the <ftw.h> header file. */
|
||||
#mesondefine HAVE_FTW_H
|
||||
|
||||
/* Define to 1 if you have the `getpagesize' function. */
|
||||
#mesondefine HAVE_GETPAGESIZE
|
||||
|
||||
/* Define to 1 if you have the `getresuid' function. */
|
||||
#mesondefine HAVE_GETRESUID
|
||||
|
||||
/* Define if gio-unix is available */
|
||||
#mesondefine HAVE_GIO_UNIX
|
||||
|
||||
/* Define if GStreamer support is available */
|
||||
#mesondefine HAVE_GSTREAMER
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#mesondefine HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if the system has the type `IPrintDialogCallback'. */
|
||||
#mesondefine HAVE_IPRINTDIALOGCALLBACK
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#mesondefine HAVE_LOCALE_H
|
||||
|
||||
/* Define to 1 if you have the `lstat' function. */
|
||||
#mesondefine HAVE_LSTAT
|
||||
|
||||
/* Define to 1 if you have the `mallinfo' function. */
|
||||
#mesondefine HAVE_MALLINFO
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#mesondefine HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `mkstemp' function. */
|
||||
#mesondefine HAVE_MKSTEMP
|
||||
|
||||
/* Define to 1 if you have the `mlock` function. */
|
||||
#mesondefine HAVE_MLOCK
|
||||
|
||||
/* Define to 1 if you have a working `mmap' system call. */
|
||||
#mesondefine HAVE_MMAP
|
||||
|
||||
/* Define to 1 if you have a working `madvise' system call. */
|
||||
#mesondefine HAVE_MADVISE
|
||||
|
||||
/* Define to 1 if you have the `posix_fallocate' function. */
|
||||
#mesondefine HAVE_POSIX_FALLOCATE
|
||||
|
||||
/* Have the Xrandr extension library */
|
||||
#mesondefine HAVE_RANDR
|
||||
|
||||
/* Have the Xrandr 1.5 extension library */
|
||||
#mesondefine HAVE_RANDR15
|
||||
|
||||
/* Define to 1 if you have the `sincos' function. */
|
||||
#mesondefine HAVE_SINCOS
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#mesondefine HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#mesondefine HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#mesondefine HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#mesondefine HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
#mesondefine HAVE_SYS_MMAN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#mesondefine HAVE_SYS_PARAM_H
|
||||
|
||||
/* Have the sysprof-capture library */
|
||||
#mesondefine HAVE_SYSPROF
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#mesondefine HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#mesondefine HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#mesondefine HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#mesondefine HAVE_UNISTD_H
|
||||
|
||||
/* Have the Xcursor library */
|
||||
#mesondefine HAVE_XCURSOR
|
||||
|
||||
/* Have the XDAMAGE X extension */
|
||||
#mesondefine HAVE_XDAMAGE
|
||||
|
||||
/* Have the XFIXES X extension */
|
||||
#mesondefine HAVE_XFIXES
|
||||
|
||||
/* Define to 1 if XFree Xinerama is available */
|
||||
#mesondefine HAVE_XFREE_XINERAMA
|
||||
|
||||
/* Have XGenericEvent */
|
||||
#mesondefine HAVE_XGENERICEVENTS
|
||||
|
||||
/* Define to use XKB extension */
|
||||
#mesondefine HAVE_XKB
|
||||
|
||||
/* Have the SYNC extension library */
|
||||
#mesondefine HAVE_XSYNC
|
||||
|
||||
/* Define to 1 if you have the `_lock_file' function */
|
||||
#mesondefine HAVE__LOCK_FILE
|
||||
|
||||
/* Define to 1 if you have the `flockfile' function */
|
||||
#mesondefine HAVE_FLOCKFILE
|
||||
|
||||
/* Define if _NL_MEASUREMENT_MEASUREMENT is available */
|
||||
#mesondefine HAVE__NL_MEASUREMENT_MEASUREMENT
|
||||
|
||||
/* Define if _NL_PAPER_HEIGHT is available */
|
||||
#mesondefine HAVE__NL_PAPER_HEIGHT
|
||||
|
||||
/* Define if _NL_PAPER_WIDTH is available */
|
||||
#mesondefine HAVE__NL_PAPER_WIDTH
|
||||
|
||||
/* Define if _NL_TIME_FIRST_WEEKDAY is available */
|
||||
#mesondefine HAVE__NL_TIME_FIRST_WEEKDAY
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#mesondefine LT_OBJDIR
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#mesondefine NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#mesondefine PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#mesondefine PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#mesondefine PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#mesondefine PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#mesondefine PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#mesondefine PACKAGE_VERSION
|
||||
|
||||
/* Use NSBundle functions to determine load paths for libraries, translations,
|
||||
etc. */
|
||||
#mesondefine QUARTZ_RELOCATION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#mesondefine STDC_HEADERS
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to 1 if XInput 2.2 is available */
|
||||
#mesondefine XINPUT_2_2
|
||||
|
||||
/* Define to 1 if the X Window System is missing or not being used. */
|
||||
#mesondefine X_DISPLAY_MISSING
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#mesondefine _FILE_OFFSET_BITS
|
||||
|
||||
/* defines how to decorate public symbols while building */
|
||||
#mesondefine _GDK_EXTERN
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#mesondefine _LARGE_FILES
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#mesondefine _MINIX
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#mesondefine _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#mesondefine _POSIX_SOURCE
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#mesondefine gid_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#mesondefine uid_t
|
||||
|
||||
/* Define to 1 if linux/memfd.h exists */
|
||||
#mesondefine HAVE_LINUX_MEMFD_H
|
||||
|
||||
#mesondefine HAVE_LINUX_INPUT_H
|
||||
|
||||
#mesondefine HAVE_DEV_EVDEV_INPUT_H
|
||||
|
||||
#mesondefine GTK_SYSCONFDIR
|
||||
|
||||
#mesondefine GTK_LOCALEDIR
|
||||
|
||||
#mesondefine GTK_DATADIR
|
||||
|
||||
#mesondefine GTK_LIBDIR
|
||||
|
||||
#mesondefine GTK_PRINT_BACKENDS
|
||||
|
||||
#mesondefine HAVE_CAIRO_SCRIPT_INTERPRETER
|
||||
|
||||
#mesondefine HAVE_HARFBUZZ
|
||||
|
||||
#mesondefine HAVE_PANGOFT
|
||||
|
||||
#mesondefine ISO_CODES_PREFIX
|
||||
|
||||
/* Define if tracker3 is available */
|
||||
#mesondefine HAVE_TRACKER3
|
||||
|
||||
#mesondefine HAVE_F16C
|
||||
|
||||
/* Does the OS support GDesktopAppInfo? */
|
||||
#mesondefine HAVE_DESKTOPAPPINFO
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static GdkTexture *avatar_texture_other;
|
||||
static GdkPixbuf *avatar_pixbuf_other;
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
#define GTK_TYPE_MESSAGE (gtk_message_get_type ())
|
||||
@@ -196,9 +196,12 @@ gtk_message_row_update (GtkMessageRow *row)
|
||||
gtk_button_set_label (GTK_BUTTON (priv->resent_by_button), priv->message->resent_by);
|
||||
|
||||
if (strcmp (priv->message->sender_nick, "@GTKtoolkit") == 0)
|
||||
gtk_image_set_from_icon_name (priv->avatar_image, "org.gtk.Demo4");
|
||||
{
|
||||
gtk_image_set_from_icon_name (priv->avatar_image, "org.gtk.Demo4");
|
||||
gtk_image_set_icon_size (priv->avatar_image, GTK_ICON_SIZE_LARGE);
|
||||
}
|
||||
else
|
||||
gtk_image_set_from_paintable (priv->avatar_image, GDK_PAINTABLE (avatar_texture_other));
|
||||
gtk_image_set_from_pixbuf (priv->avatar_image, avatar_pixbuf_other);
|
||||
|
||||
}
|
||||
|
||||
@@ -341,7 +344,7 @@ do_listbox (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
avatar_texture_other = gdk_texture_new_from_resource ("/listbox/apple-red.png");
|
||||
avatar_pixbuf_other = gdk_pixbuf_new_from_resource_at_scale ("/listbox/apple-red.png", 32, 32, FALSE, NULL);
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
<property name="margin-start">8</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="icon-name">image-missing</property>
|
||||
<property name="icon-size">large</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
|
||||
@@ -198,7 +198,6 @@
|
||||
<child>
|
||||
<object class="GtkPicture" id="picture">
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="keep-aspect-ratio">1</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
struct _ExampleAppPrefs
|
||||
{
|
||||
GtkDialog parent;
|
||||
|
||||
GSettings *settings;
|
||||
GtkWidget *font;
|
||||
GtkWidget *transition;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ExampleAppPrefs, example_app_prefs, GTK_TYPE_DIALOG)
|
||||
@@ -19,41 +15,20 @@ static void
|
||||
example_app_prefs_init (ExampleAppPrefs *prefs)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (prefs));
|
||||
prefs->settings = g_settings_new ("org.gtk.exampleapp");
|
||||
|
||||
g_settings_bind (prefs->settings, "font",
|
||||
prefs->font, "font",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
g_settings_bind (prefs->settings, "transition",
|
||||
prefs->transition, "active-id",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
example_app_prefs_dispose (GObject *object)
|
||||
{
|
||||
ExampleAppPrefs *prefs;
|
||||
|
||||
prefs = EXAMPLE_APP_PREFS (object);
|
||||
|
||||
g_clear_object (&prefs->settings);
|
||||
|
||||
G_OBJECT_CLASS (example_app_prefs_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
example_app_prefs_class_init (ExampleAppPrefsClass *class)
|
||||
{
|
||||
G_OBJECT_CLASS (class)->dispose = example_app_prefs_dispose;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
|
||||
"/org/gtk/exampleapp/prefs.ui");
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppPrefs, font);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppPrefs, transition);
|
||||
}
|
||||
|
||||
ExampleAppPrefs *
|
||||
example_app_prefs_new (ExampleAppWindow *win)
|
||||
{
|
||||
return g_object_new (EXAMPLE_APP_PREFS_TYPE, "transient-for", win, "use-header-bar", TRUE, NULL);
|
||||
return g_object_new (EXAMPLE_APP_PREFS_TYPE,
|
||||
"transient-for", win,
|
||||
"use-header-bar", TRUE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFontButton" id="font">
|
||||
<property name="font" bind-settings-schema="org.gtk.exampleapp" bind-settings-key="font"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
@@ -48,6 +49,7 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="transition">
|
||||
<property name="active-id" bind-settings-schema="org.gtk.exampleapp" bind-settings-key="transition"/>
|
||||
<items>
|
||||
<item translatable="yes" id="none">None</item>
|
||||
<item translatable="yes" id="crossfade">Fade</item>
|
||||
|
||||
@@ -603,8 +603,8 @@ bloat_pad_startup (GApplication *application)
|
||||
g_object_unref (icon);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
icon = G_ICON (gdk_texture_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/folder-new.png"));
|
||||
item = g_menu_item_new ("Texture", NULL);
|
||||
icon = G_ICON (gdk_pixbuf_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/folder-new.png", NULL));
|
||||
item = g_menu_item_new ("Pixbuf", NULL);
|
||||
g_menu_item_set_icon (item, icon);
|
||||
g_menu_append_item (menu, item);
|
||||
g_object_unref (item);
|
||||
|
||||
@@ -29,7 +29,7 @@ gboolean gdk_should_use_portal (void);
|
||||
|
||||
const char * gdk_get_startup_notification_id (void);
|
||||
|
||||
PangoDirection gdk_unichar_direction (gunichar ch) G_GNUC_CONST;
|
||||
PangoDirection gdk_unichar_direction (gunichar ch);
|
||||
PangoDirection gdk_find_base_dir (const char *text,
|
||||
int len);
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ cairo_region_t *
|
||||
gdk_cairo_region_create_from_surface
|
||||
(cairo_surface_t *surface);
|
||||
|
||||
GDK_DEPRECATED_IN_4_6_FOR(gdk_gl_texture_new)
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
GdkSurface *surface,
|
||||
int source,
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "filetransferportalprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdkrgbaprivate.h"
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
@@ -657,56 +655,6 @@ pixbuf_deserializer (GdkContentDeserializer *deserializer)
|
||||
deserializer);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_deserializer_finish (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer deserializer)
|
||||
{
|
||||
GOutputStream *stream = G_OUTPUT_STREAM (source);
|
||||
GBytes *bytes;
|
||||
GError *error = NULL;
|
||||
GdkTexture *texture = NULL;
|
||||
gssize written;
|
||||
|
||||
written = g_output_stream_splice_finish (stream, result, &error);
|
||||
if (written < 0)
|
||||
{
|
||||
gdk_content_deserializer_return_error (deserializer, error);
|
||||
return;
|
||||
}
|
||||
|
||||
bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
|
||||
|
||||
texture = gdk_texture_new_from_bytes (bytes, &error);
|
||||
g_bytes_unref (bytes);
|
||||
if (texture == NULL)
|
||||
{
|
||||
gdk_content_deserializer_return_error (deserializer, error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_value_take_object (gdk_content_deserializer_get_value (deserializer), texture);
|
||||
gdk_content_deserializer_return_success (deserializer);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_deserializer (GdkContentDeserializer *deserializer)
|
||||
{
|
||||
GOutputStream *output;
|
||||
|
||||
output = g_memory_output_stream_new_resizable ();
|
||||
|
||||
g_output_stream_splice_async (output,
|
||||
gdk_content_deserializer_get_input_stream (deserializer),
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE
|
||||
| G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
|
||||
gdk_content_deserializer_get_priority (deserializer),
|
||||
gdk_content_deserializer_get_cancellable (deserializer),
|
||||
texture_deserializer_finish,
|
||||
deserializer);
|
||||
g_object_unref (output);
|
||||
}
|
||||
|
||||
static void
|
||||
string_deserializer_finish (GObject *source,
|
||||
GAsyncResult *result,
|
||||
@@ -915,71 +863,48 @@ init (void)
|
||||
|
||||
initialized = TRUE;
|
||||
|
||||
gdk_content_register_deserializer ("image/png",
|
||||
GDK_TYPE_TEXTURE,
|
||||
texture_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
gdk_content_register_deserializer ("image/tiff",
|
||||
GDK_TYPE_TEXTURE,
|
||||
texture_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
gdk_content_register_deserializer ("image/jpeg",
|
||||
GDK_TYPE_TEXTURE,
|
||||
texture_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
|
||||
formats = gdk_pixbuf_get_formats ();
|
||||
|
||||
/* Make sure png comes first */
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char *name;
|
||||
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
if (g_str_equal (name, "png"))
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
|
||||
g_free (name);
|
||||
break;
|
||||
}
|
||||
g_free (name);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char **mimes, **m;
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
mimes = gdk_pixbuf_format_get_mime_types (fmt);
|
||||
for (m = mimes; *m; m++)
|
||||
{
|
||||
/* Turning pngs, jpegs and tiffs into textures is handled above */
|
||||
if (!g_str_equal (name, "png") &&
|
||||
!g_str_equal (name, "jpeg") &&
|
||||
!g_str_equal (name, "tiff"))
|
||||
gdk_content_register_deserializer (*m,
|
||||
GDK_TYPE_TEXTURE,
|
||||
pixbuf_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
{
|
||||
gdk_content_register_deserializer (*m,
|
||||
GDK_TYPE_TEXTURE,
|
||||
pixbuf_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
gdk_content_register_deserializer (*m,
|
||||
GDK_TYPE_PIXBUF,
|
||||
pixbuf_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
g_strfreev (mimes);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_slist_free (formats);
|
||||
|
||||
@@ -26,10 +26,6 @@
|
||||
#include "filetransferportalprivate.h"
|
||||
#include "gdktextureprivate.h"
|
||||
#include "gdkrgba.h"
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
#include "loaders/gdkjpegprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <string.h>
|
||||
@@ -610,7 +606,6 @@ gdk_content_serialize_finish (GAsyncResult *result,
|
||||
|
||||
/*** SERIALIZERS ***/
|
||||
|
||||
|
||||
static void
|
||||
pixbuf_serializer_finish (GObject *source,
|
||||
GAsyncResult *res,
|
||||
@@ -663,77 +658,6 @@ pixbuf_serializer (GdkContentSerializer *serializer)
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_serializer_finish (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkContentSerializer *serializer = GDK_CONTENT_SERIALIZER (source);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_task_propagate_boolean (G_TASK (res), &error))
|
||||
gdk_content_serializer_return_error (serializer, error);
|
||||
else
|
||||
gdk_content_serializer_return_success (serializer);
|
||||
}
|
||||
|
||||
static void
|
||||
serialize_texture_in_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GdkContentSerializer *serializer = source_object;
|
||||
const GValue *value;
|
||||
GdkTexture *texture;
|
||||
GBytes *bytes = NULL;
|
||||
GError *error = NULL;
|
||||
gboolean result = FALSE;
|
||||
GInputStream *input;
|
||||
gssize spliced;
|
||||
|
||||
value = gdk_content_serializer_get_value (serializer);
|
||||
texture = g_value_get_object (value);
|
||||
|
||||
if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/png") == 0)
|
||||
bytes = gdk_save_png (texture);
|
||||
else if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/tiff") == 0)
|
||||
bytes = gdk_save_tiff (texture);
|
||||
else if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/jpeg") == 0)
|
||||
bytes = gdk_save_jpeg (texture);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
input = g_memory_input_stream_new_from_bytes (bytes);
|
||||
spliced = g_output_stream_splice (gdk_content_serializer_get_output_stream (serializer),
|
||||
input,
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
|
||||
gdk_content_serializer_get_cancellable (serializer),
|
||||
&error);
|
||||
g_object_unref (input);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
result = spliced != -1;
|
||||
|
||||
if (result)
|
||||
g_task_return_boolean (task, result);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_serializer (GdkContentSerializer *serializer)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (serializer,
|
||||
gdk_content_serializer_get_cancellable (serializer),
|
||||
texture_serializer_finish,
|
||||
NULL);
|
||||
g_task_run_in_thread (task, serialize_texture_in_thread);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
string_serializer_finish (GObject *source,
|
||||
GAsyncResult *result,
|
||||
@@ -953,72 +877,51 @@ init (void)
|
||||
|
||||
initialized = TRUE;
|
||||
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
"image/png",
|
||||
texture_serializer,
|
||||
NULL, NULL);
|
||||
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
"image/tiff",
|
||||
texture_serializer,
|
||||
NULL, NULL);
|
||||
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
"image/jpeg",
|
||||
texture_serializer,
|
||||
NULL, NULL);
|
||||
|
||||
formats = gdk_pixbuf_get_formats ();
|
||||
|
||||
/* Make sure png comes first */
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char *name;
|
||||
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
if (g_str_equal (name, "png"))
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
|
||||
g_free (name);
|
||||
break;
|
||||
}
|
||||
g_free (name);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char **mimes, **m;
|
||||
char *name;
|
||||
|
||||
if (!gdk_pixbuf_format_is_writable (fmt))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
mimes = gdk_pixbuf_format_get_mime_types (fmt);
|
||||
for (m = mimes; *m; m++)
|
||||
{
|
||||
/* Turning textures into pngs, tiffs or jpegs is handled above */
|
||||
if (!g_str_equal (name, "png") &&
|
||||
!g_str_equal (name, "tiff") &&
|
||||
!g_str_equal (name, "jpeg"))
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
*m,
|
||||
pixbuf_serializer,
|
||||
gdk_pixbuf_format_get_name (fmt),
|
||||
g_free);
|
||||
{
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
*m,
|
||||
pixbuf_serializer,
|
||||
gdk_pixbuf_format_get_name (fmt),
|
||||
g_free);
|
||||
gdk_content_register_serializer (GDK_TYPE_PIXBUF,
|
||||
*m,
|
||||
pixbuf_serializer,
|
||||
gdk_pixbuf_format_get_name (fmt),
|
||||
g_free);
|
||||
}
|
||||
}
|
||||
g_strfreev (mimes);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_slist_free (formats);
|
||||
|
||||
@@ -69,7 +69,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drag_get_selected_action (GdkDrag *drag);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_drag_action_is_unique (GdkDragAction action) G_GNUC_CONST;
|
||||
gboolean gdk_drag_action_is_unique (GdkDragAction action);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDrag * gdk_drag_begin (GdkSurface *surface,
|
||||
|
||||
@@ -301,7 +301,7 @@ gdk_gl_texture_quads (GdkGLContext *paint_context,
|
||||
* @width: The width of the region to draw
|
||||
* @height: The height of the region to draw
|
||||
*
|
||||
* The main way to not draw GL content in GTK.
|
||||
* The main way to draw GL content in GTK.
|
||||
*
|
||||
* It takes a render buffer ID (@source_type == GL_RENDERBUFFER) or a texture
|
||||
* id (@source_type == GL_TEXTURE) and draws it onto @cr with an OVER operation,
|
||||
@@ -319,12 +319,6 @@ gdk_gl_texture_quads (GdkGLContext *paint_context,
|
||||
* with alpha components, so make sure you use GL_TEXTURE if using alpha.
|
||||
*
|
||||
* Calling this may change the current GL context.
|
||||
*
|
||||
* Deprecated: 4.6: The function is overly complex and produces broken output
|
||||
* in various combinations of arguments. If you want to draw with GL textures
|
||||
* in GTK, use [ctor@Gdk.GLTexture.new]; if you want to use that texture in
|
||||
* Cairo, use [method@Gdk.Texture.download] to download the data into a Cairo
|
||||
* image surface.
|
||||
*/
|
||||
void
|
||||
gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
|
||||
@@ -229,83 +229,64 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
guchar *copy = NULL;
|
||||
GLint gl_internalformat;
|
||||
GLint gl_format;
|
||||
GLint gl_type;
|
||||
gsize bpp;
|
||||
guint gl_format;
|
||||
guint gl_type;
|
||||
guint bpp;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
if (!priv->use_es && data_format == GDK_MEMORY_DEFAULT) /* Cairo surface format */
|
||||
if (priv->use_es)
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R8G8B8) /* Pixmap non-alpha data */
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (priv->use_es && data_format == GDK_MEMORY_B8G8R8)
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_BGR;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16A16_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16_FLOAT)
|
||||
{
|
||||
gl_internalformat = GL_RGB16F;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16F;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R32G32B32_FLOAT)
|
||||
{
|
||||
gl_internalformat = GL_RGB32F;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA32F;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_FLOAT;
|
||||
}
|
||||
else /* Fall-back, convert to GLES format */
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
stride = width * 4;
|
||||
data = copy;
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
/* GLES only supports rgba, so convert if necessary */
|
||||
if (data_format != GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
stride = width * 4;
|
||||
data = copy;
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (data_format);
|
||||
bpp = 4;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data_format == GDK_MEMORY_DEFAULT) /* Cairo surface format */
|
||||
{
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
bpp = 4;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R8G8B8) /* Pixmap non-alpha data */
|
||||
{
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
bpp = 3;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_B8G8R8)
|
||||
{
|
||||
gl_format = GL_BGR;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
bpp = 3;
|
||||
}
|
||||
else /* Fall-back, convert to cairo-surface-format */
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
stride = width * 4;
|
||||
bpp = 4;
|
||||
data = copy;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
}
|
||||
|
||||
/* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if
|
||||
* the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available
|
||||
@@ -314,7 +295,7 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, data);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
|
||||
}
|
||||
else if ((!priv->use_es ||
|
||||
@@ -322,14 +303,14 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);
|
||||
|
||||
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, data);
|
||||
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, NULL);
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, NULL);
|
||||
for (i = 0; i < height; i++)
|
||||
glTexSubImage2D (texture_target, 0, 0, i, width, 1, gl_format, gl_type, data + (i * stride));
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkcairo.h"
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
@@ -38,7 +37,7 @@ struct _GdkGLTexture {
|
||||
GdkGLContext *context;
|
||||
guint id;
|
||||
|
||||
GdkTexture *saved;
|
||||
cairo_surface_t *saved;
|
||||
|
||||
GDestroyNotify destroy;
|
||||
gpointer data;
|
||||
@@ -65,258 +64,50 @@ gdk_gl_texture_dispose (GObject *object)
|
||||
g_clear_object (&self->context);
|
||||
self->id = 0;
|
||||
|
||||
g_clear_object (&self->saved);
|
||||
if (self->saved)
|
||||
{
|
||||
cairo_surface_destroy (self->saved);
|
||||
self->saved = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gdk_gl_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
typedef struct _InvokeData
|
||||
{
|
||||
GdkGLTexture *self;
|
||||
volatile int spinlock;
|
||||
GFunc func;
|
||||
gpointer data;
|
||||
} InvokeData;
|
||||
|
||||
static gboolean
|
||||
gdk_gl_texture_invoke_callback (gpointer data)
|
||||
{
|
||||
InvokeData *invoke = data;
|
||||
GdkGLContext *context;
|
||||
|
||||
context = gdk_display_get_gl_context (gdk_gl_context_get_display (invoke->self->context));
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
glBindTexture (GL_TEXTURE_2D, invoke->self->id);
|
||||
|
||||
invoke->func (invoke->self, invoke->data);
|
||||
|
||||
g_atomic_int_set (&invoke->spinlock, 1);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_run (GdkGLTexture *self,
|
||||
GFunc func,
|
||||
gpointer data)
|
||||
gdk_gl_texture_download (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
InvokeData invoke = { self, 0, func, data };
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
|
||||
g_main_context_invoke (NULL, gdk_gl_texture_invoke_callback, &invoke);
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
area->width, area->height,
|
||||
stride);
|
||||
|
||||
while (g_atomic_int_get (&invoke.spinlock) == 0);
|
||||
}
|
||||
cr = cairo_create (surface);
|
||||
|
||||
static inline void
|
||||
gdk_gl_texture_get_tex_image (GdkGLTexture *self,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
GLvoid *data)
|
||||
{
|
||||
if (gdk_gl_context_get_use_es (self->context))
|
||||
if (self->saved)
|
||||
{
|
||||
GdkTexture *texture = GDK_TEXTURE (self);
|
||||
GLuint fbo;
|
||||
|
||||
glGenFramebuffers (1, &fbo);
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->id, 0);
|
||||
glReadPixels (0, 0,
|
||||
texture->width, texture->height,
|
||||
gl_format,
|
||||
gl_type,
|
||||
data);
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers (1, &fbo);
|
||||
cairo_set_source_surface (cr, self->saved, 0, 0);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
gl_format,
|
||||
gl_type,
|
||||
data);
|
||||
}
|
||||
}
|
||||
static void
|
||||
gdk_gl_texture_do_download_texture (gpointer texture_,
|
||||
gpointer result_)
|
||||
{
|
||||
GdkTexture *texture = texture_;
|
||||
GdkTexture **result = result_;
|
||||
GdkMemoryFormat format;
|
||||
GLint internal_format, gl_format, gl_type;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
GBytes *bytes;
|
||||
GdkSurface *gl_surface;
|
||||
|
||||
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
|
||||
|
||||
switch (internal_format)
|
||||
{
|
||||
case GL_RGB8:
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_RGBA8:
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_RGB16:
|
||||
format = GDK_MEMORY_R16G16B16;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
|
||||
case GL_RGBA16:
|
||||
format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
|
||||
case GL_RGB16F:
|
||||
format = GDK_MEMORY_R16G16B16_FLOAT;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA16F:
|
||||
format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGB32F:
|
||||
format = GDK_MEMORY_R32G32B32_FLOAT;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA32F:
|
||||
format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_FLOAT;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Texture in unexpected format 0x%X (%d). File a bug about adding it to GTK", internal_format, internal_format);
|
||||
/* fallback to the dumbest possible format
|
||||
* so that even age old GLES can do it */
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
}
|
||||
|
||||
stride = gdk_memory_format_bytes_per_pixel (format) * texture->width;
|
||||
data = g_malloc (stride * texture->height);
|
||||
|
||||
gdk_gl_texture_get_tex_image (texture_,
|
||||
gl_format,
|
||||
gl_type,
|
||||
data);
|
||||
|
||||
bytes = g_bytes_new_take (data, stride * texture->height);
|
||||
*result = gdk_memory_texture_new (texture->width,
|
||||
texture->height,
|
||||
format,
|
||||
bytes,
|
||||
stride);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_gl_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
GdkTexture *result;
|
||||
|
||||
if (self->saved)
|
||||
return g_object_ref (self->saved);
|
||||
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download_texture, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_download (gpointer texture,
|
||||
gpointer data)
|
||||
{
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_BGRA,
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
GL_UNSIGNED_BYTE,
|
||||
#else
|
||||
#error "Unknown byte order for gdk_gl_texture_download()"
|
||||
#endif
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
gdk_texture_download (self->saved, data, stride);
|
||||
return;
|
||||
gl_surface = gdk_gl_context_get_surface (self->context);
|
||||
gdk_cairo_draw_from_gl (cr, gl_surface, self->id, GL_TEXTURE, 1,
|
||||
area->x, area->y,
|
||||
area->width, area->height);
|
||||
}
|
||||
|
||||
if (gdk_gl_context_get_use_es (self->context) ||
|
||||
stride != texture->width * 4)
|
||||
{
|
||||
GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download (texture, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download, data);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_download_float (gpointer texture,
|
||||
gpointer data)
|
||||
{
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_FLOAT,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
gdk_texture_download_float (self->saved, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gdk_gl_context_get_use_es (self->context) ||
|
||||
stride != texture->width * 4)
|
||||
{
|
||||
GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download_float (texture, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download_float, data);
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_finish (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -325,9 +116,7 @@ gdk_gl_texture_class_init (GdkGLTextureClass *klass)
|
||||
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
texture_class->download_texture = gdk_gl_texture_download_texture;
|
||||
texture_class->download = gdk_gl_texture_download;
|
||||
texture_class->download_float = gdk_gl_texture_download_float;
|
||||
gobject_class->dispose = gdk_gl_texture_dispose;
|
||||
}
|
||||
|
||||
@@ -361,10 +150,24 @@ gdk_gl_texture_get_id (GdkGLTexture *self)
|
||||
void
|
||||
gdk_gl_texture_release (GdkGLTexture *self)
|
||||
{
|
||||
GdkSurface *surface;
|
||||
GdkTexture *texture;
|
||||
cairo_t *cr;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_TEXTURE (self));
|
||||
g_return_if_fail (self->saved == NULL);
|
||||
|
||||
self->saved = gdk_texture_download_texture (GDK_TEXTURE (self));
|
||||
texture = GDK_TEXTURE (self);
|
||||
self->saved = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
texture->width, texture->height);
|
||||
|
||||
cr = cairo_create (self->saved);
|
||||
|
||||
surface = gdk_gl_context_get_surface (self->context);
|
||||
gdk_cairo_draw_from_gl (cr, surface, self->id, GL_TEXTURE, 1, 0, 0,
|
||||
texture->width, texture->height);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
if (self->destroy)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gsk/ngl/fp16private.h"
|
||||
|
||||
/**
|
||||
* GdkMemoryTexture:
|
||||
@@ -50,33 +49,19 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
return 4;
|
||||
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
return 3;
|
||||
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
return 4;
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
return 6;
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return 8;
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
return 12;
|
||||
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return 16;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -84,41 +69,6 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
}
|
||||
}
|
||||
|
||||
static gsize
|
||||
gdk_memory_format_alignment (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
return G_ALIGNOF (guchar);
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
return G_ALIGNOF (guint16);
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return G_ALIGNOF (guint16);
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return G_ALIGNOF (float);
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return G_ALIGNOF (double);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_dispose (GObject *object)
|
||||
{
|
||||
@@ -129,41 +79,22 @@ gdk_memory_texture_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (gdk_memory_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_memory_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
return g_object_ref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
gdk_memory_texture_download (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
|
||||
|
||||
gdk_memory_convert (data, stride,
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
GDK_MEMORY_CAIRO_FORMAT_ARGB32,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL)
|
||||
+ area->x * gdk_memory_format_bytes_per_pixel (self->format)
|
||||
+ area->y * self->stride,
|
||||
self->stride,
|
||||
self->format,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
|
||||
|
||||
gdk_memory_convert_to_float (data, stride,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
self->format,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
area->width, area->height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -172,9 +103,7 @@ gdk_memory_texture_class_init (GdkMemoryTextureClass *klass)
|
||||
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
texture_class->download_texture = gdk_memory_texture_download_texture;
|
||||
texture_class->download = gdk_memory_texture_download;
|
||||
texture_class->download_float = gdk_memory_texture_download_float;
|
||||
gobject_class->dispose = gdk_memory_texture_dispose;
|
||||
}
|
||||
|
||||
@@ -183,41 +112,6 @@ gdk_memory_texture_init (GdkMemoryTexture *self)
|
||||
{
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
gdk_memory_sanitize (GBytes *bytes,
|
||||
int width,
|
||||
int height,
|
||||
GdkMemoryFormat format,
|
||||
gsize stride,
|
||||
gsize *out_stride)
|
||||
{
|
||||
gsize align, size, copy_stride, bpp;
|
||||
const guchar *data;
|
||||
guchar *copy;
|
||||
int y;
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
align = gdk_memory_format_alignment (format);
|
||||
|
||||
if (GPOINTER_TO_SIZE (data) % align == 0 &&
|
||||
stride % align == 0)
|
||||
{
|
||||
*out_stride = stride;
|
||||
return g_bytes_ref (bytes);
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
copy_stride = bpp * width;
|
||||
/* align to multiples of 4, just to be sure */
|
||||
copy_stride = (copy_stride + 3) & ~3;
|
||||
copy = g_malloc (copy_stride * height);
|
||||
for (y = 0; y < height; y++)
|
||||
memcpy (copy + y * copy_stride, data + y * stride, bpp * width);
|
||||
|
||||
*out_stride = copy_stride;
|
||||
return g_bytes_new_take (copy, copy_stride * height);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_new:
|
||||
* @width: the width of the texture
|
||||
@@ -242,20 +136,13 @@ gdk_memory_texture_new (int width,
|
||||
{
|
||||
GdkMemoryTexture *self;
|
||||
|
||||
g_return_val_if_fail (width > 0, NULL);
|
||||
g_return_val_if_fail (height > 0, NULL);
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (stride >= width * gdk_memory_format_bytes_per_pixel (format), NULL);
|
||||
|
||||
bytes = gdk_memory_sanitize (bytes, width, height, format, stride, &stride);
|
||||
|
||||
self = g_object_new (GDK_TYPE_MEMORY_TEXTURE,
|
||||
"width", width,
|
||||
"height", height,
|
||||
NULL);
|
||||
|
||||
self->format = format;
|
||||
self->bytes = bytes;
|
||||
self->bytes = g_bytes_ref (bytes);
|
||||
self->stride = stride;
|
||||
|
||||
return GDK_TEXTURE (self);
|
||||
@@ -396,109 +283,6 @@ SWIZZLE_PREMULTIPLY (3,0,1,2, 0,1,2,3)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 3,0,1,2)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 0,3,2,1)
|
||||
|
||||
#define CONVERT_FUNC(name,suffix,R,G,B,A,step) \
|
||||
static void \
|
||||
convert_ ## name ## _to_ ## suffix (guchar *dest_data, \
|
||||
gsize dest_stride, \
|
||||
const guchar *src_data, \
|
||||
gsize src_stride, \
|
||||
gsize width, \
|
||||
gsize height) \
|
||||
{ \
|
||||
gsize x, y; \
|
||||
\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
guchar conv[4]; \
|
||||
convert_pixel_ ## name (conv, src_data + step * x); \
|
||||
dest_data[4 * x + R] = conv[0]; \
|
||||
dest_data[4 * x + G] = conv[1]; \
|
||||
dest_data[4 * x + B] = conv[2]; \
|
||||
dest_data[4 * x + A] = conv[3]; \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CONVERT_FUNCS(name,step) \
|
||||
CONVERT_FUNC(name, download_le, 2, 1, 0, 3, step) \
|
||||
CONVERT_FUNC(name, download_be, 1, 2, 3, 0, step) \
|
||||
CONVERT_FUNC(name, gles_rgba, 0, 1, 2, 3, step) \
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb16 (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest_data[0] = (guchar)(src[0] >> 8);
|
||||
dest_data[1] = (guchar)(src[1] >> 8);
|
||||
dest_data[2] = (guchar)(src[2] >> 8);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb16, 3 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba16 (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest_data[0] = (guchar)(src[0] >> 8);
|
||||
dest_data[1] = (guchar)(src[1] >> 8);
|
||||
dest_data[2] = (guchar)(src[2] >> 8);
|
||||
dest_data[3] = (guchar)(src[3] >> 8);
|
||||
}
|
||||
CONVERT_FUNCS(rgba16, 4 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb16f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float src[4];
|
||||
guint16 tmp[4];
|
||||
memcpy(tmp, src_data, sizeof(guint16) * 3);
|
||||
half_to_float4(tmp, src);
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb16f, 3 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba16f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float src[4];
|
||||
half_to_float4((const guint16 *) src_data, src);
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
|
||||
}
|
||||
CONVERT_FUNCS(rgba16f, 4 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb32f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float *src = (float *) src_data;
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb32f, 3 * sizeof (float))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba32f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float *src = (float *) src_data;
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
|
||||
}
|
||||
CONVERT_FUNCS(rgba32f, 4 * sizeof (float))
|
||||
|
||||
typedef void (* ConversionFunc) (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
@@ -506,7 +290,7 @@ typedef void (* ConversionFunc) (guchar *dest_data,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
static ConversionFunc converters[GDK_MEMORY_N_FORMATS][GDK_MEMORY_N_CONVERSIONS] =
|
||||
static ConversionFunc converters[GDK_MEMORY_N_FORMATS][3] =
|
||||
{
|
||||
{ convert_memcpy, convert_swizzle3210, convert_swizzle2103 },
|
||||
{ convert_swizzle3210, convert_memcpy, convert_swizzle3012 },
|
||||
@@ -516,192 +300,21 @@ static ConversionFunc converters[GDK_MEMORY_N_FORMATS][GDK_MEMORY_N_CONVERSIONS]
|
||||
{ convert_swizzle_premultiply_3210_3012, convert_swizzle_premultiply_0123_3012, convert_swizzle_premultiply_3012_3012 },
|
||||
{ convert_swizzle_premultiply_3210_0321, convert_swizzle_premultiply_0123_0321, convert_swizzle_premultiply_3012_0321 },
|
||||
{ convert_swizzle_opaque_3210, convert_swizzle_opaque_0123, convert_swizzle_opaque_3012 },
|
||||
{ convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 },
|
||||
{ convert_rgb16_to_download_le, convert_rgb16_to_download_be, convert_rgb16_to_gles_rgba },
|
||||
{ convert_rgba16_to_download_le, convert_rgba16_to_download_be, convert_rgba16_to_gles_rgba },
|
||||
{ convert_rgb16f_to_download_le, convert_rgb16f_to_download_be, convert_rgb16f_to_gles_rgba },
|
||||
{ convert_rgba16f_to_download_le, convert_rgba16f_to_download_be, convert_rgba16f_to_gles_rgba },
|
||||
{ convert_rgb32f_to_download_le, convert_rgb32f_to_download_be, convert_rgb32f_to_gles_rgba },
|
||||
{ convert_rgba32f_to_download_le, convert_rgba32f_to_download_be, convert_rgba32f_to_gles_rgba }
|
||||
{ convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 }
|
||||
};
|
||||
|
||||
void
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryConversion dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
g_assert (dest_format < 3);
|
||||
g_assert (src_format < GDK_MEMORY_N_FORMATS);
|
||||
|
||||
converters[src_format][dest_format] (dest_data, dest_stride, src_data, src_stride, width, height);
|
||||
}
|
||||
|
||||
#define CONVERT_FLOAT(R,G,B,A,premultiply) G_STMT_START {\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
if (A >= 0) \
|
||||
{ \
|
||||
dest_data[4 * x + 0] = src_data[4 * x + R] / 255.0f; \
|
||||
dest_data[4 * x + 1] = src_data[4 * x + G] / 255.0f; \
|
||||
dest_data[4 * x + 2] = src_data[4 * x + B] / 255.0f; \
|
||||
dest_data[4 * x + 3] = src_data[4 * x + A] / 255.0f; \
|
||||
if (premultiply) \
|
||||
{ \
|
||||
dest_data[4 * x + 0] *= dest_data[4 * x + 3]; \
|
||||
dest_data[4 * x + 1] *= dest_data[4 * x + 3]; \
|
||||
dest_data[4 * x + 2] *= dest_data[4 * x + 3]; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
dest_data[4 * x + 0] = src_data[3 * x + R] / 255.0f; \
|
||||
dest_data[4 * x + 1] = src_data[3 * x + G] / 255.0f; \
|
||||
dest_data[4 * x + 2] = src_data[3 * x + B] / 255.0f; \
|
||||
dest_data[4 * x + 3] = 1.0; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
|
||||
#define CONVERT_FLOAT_PIXEL(func,step) G_STMT_START{\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
func (dest_data + 4 * x, src_data + step * x); \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
|
||||
static inline void
|
||||
convert_rgb16_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest[0] = src[0] / 65535.f;
|
||||
dest[1] = src[1] / 65535.f;
|
||||
dest[2] = src[2] / 65535.f;
|
||||
dest[3] = 1.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba16_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest[0] = src[0] / 65535.f;
|
||||
dest[1] = src[1] / 65535.f;
|
||||
dest[2] = src[2] / 65535.f;
|
||||
dest[3] = src[3] / 65535.f;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgb16f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
guint16 tmp[4];
|
||||
memcpy(tmp, src_data, sizeof(guint16) * 3);
|
||||
tmp[3] = FP16_ONE;
|
||||
half_to_float4 (tmp, dest);
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba16f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
half_to_float4 ((const guint16 *) src_data, dest);
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgb32f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const float *src = (const float *) src_data;
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = 1.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba32f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const float *src = (const float *) src_data;
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = src[3];
|
||||
}
|
||||
|
||||
void
|
||||
gdk_memory_convert_to_float (float *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
gsize x, y;
|
||||
|
||||
switch (src_format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (2, 1, 0, 3, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (1, 2, 3, 0, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (0, 1, 2, 3, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
CONVERT_FLOAT (2, 1, 0, 3, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
CONVERT_FLOAT (1, 2, 3, 0, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
CONVERT_FLOAT (0, 1, 2, 3, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
CONVERT_FLOAT (3, 2, 1, 0, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
CONVERT_FLOAT (0, 1, 2, -1, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
CONVERT_FLOAT (2, 1, 0, -1, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb16_to_float, 3 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba16_to_float, 4 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb16f_to_float, 3 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba16f_to_float, 4 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb32f_to_float, 3 * sizeof (float));
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba32f_to_float, 4 * sizeof (float));
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,20 +42,6 @@ G_BEGIN_DECLS
|
||||
* @GDK_MEMORY_A8B8G8R8: 4 bytes; for alpha, blue, green, red.
|
||||
* @GDK_MEMORY_R8G8B8: 3 bytes; for red, green, blue. The data is opaque.
|
||||
* @GDK_MEMORY_B8G8R8: 3 bytes; for blue, green, red. The data is opaque.
|
||||
* @GDK_MEMORY_R16G16B16: 3 guint16 values; for red, green, blue. Since 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: 4 guint16 values; for red, green,
|
||||
* blue, alpha. The color values are premultiplied with the alpha value.
|
||||
* Since 4.6
|
||||
* @GDK_MEMORY_R16G16B16_FLOAT: 3 half-float values; for red, green, blue.
|
||||
* The data is opaque. Since 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: 4 half-float values; for
|
||||
* red, green, blue and alpha. The color values are premultiplied with
|
||||
* the alpha value. Since 4.6
|
||||
* @GDK_MEMORY_B32G32R32_FLOAT: 3 float values; for blue, green, red.
|
||||
* The data is opaque. Since 4.6
|
||||
* @GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: 4 float values; for
|
||||
* red, green, blue and alpha. The color values are premultiplied with
|
||||
* the alpha value. Since 4.6
|
||||
* @GDK_MEMORY_N_FORMATS: The number of formats. This value will change as
|
||||
* more formats get added, so do not rely on its concrete integer.
|
||||
*
|
||||
@@ -81,12 +67,6 @@ typedef enum {
|
||||
GDK_MEMORY_A8B8G8R8,
|
||||
GDK_MEMORY_R8G8B8,
|
||||
GDK_MEMORY_B8G8R8,
|
||||
GDK_MEMORY_R16G16B16,
|
||||
GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,
|
||||
GDK_MEMORY_R16G16B16_FLOAT,
|
||||
GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED,
|
||||
GDK_MEMORY_R32G32B32_FLOAT,
|
||||
GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
|
||||
|
||||
GDK_MEMORY_N_FORMATS
|
||||
} GdkMemoryFormat;
|
||||
|
||||
@@ -29,21 +29,7 @@ G_BEGIN_DECLS
|
||||
#define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
|
||||
#define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
|
||||
|
||||
typedef enum {
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN,
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD_BIT_ENDIAN,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
|
||||
GDK_MEMORY_N_CONVERSIONS
|
||||
} GdkMemoryConversion;
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_BIG_ENDIAN
|
||||
#else
|
||||
#error "Unknown byte order for GDK_MEMORY_CONVERT_DOWNLOAD"
|
||||
#endif
|
||||
#define GDK_MEMORY_CAIRO_FORMAT_ARGB32 GDK_MEMORY_DEFAULT
|
||||
|
||||
gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format);
|
||||
|
||||
@@ -51,22 +37,14 @@ GdkMemoryFormat gdk_memory_texture_get_format (GdkMemoryTexture *
|
||||
const guchar * gdk_memory_texture_get_data (GdkMemoryTexture *self);
|
||||
gsize gdk_memory_texture_get_stride (GdkMemoryTexture *self);
|
||||
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryConversion dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
void gdk_memory_convert_to_float (float *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "gdkhslaprivate.h"
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GdkRGBA, gdk_rgba,
|
||||
gdk_rgba_copy, gdk_rgba_free)
|
||||
@@ -187,7 +186,6 @@ gdk_rgba_parse (GdkRGBA *rgba,
|
||||
const char *spec)
|
||||
{
|
||||
gboolean has_alpha;
|
||||
gboolean is_hsl;
|
||||
double r, g, b, a;
|
||||
char *str = (char *) spec;
|
||||
char *p;
|
||||
@@ -198,26 +196,11 @@ gdk_rgba_parse (GdkRGBA *rgba,
|
||||
if (strncmp (str, "rgba", 4) == 0)
|
||||
{
|
||||
has_alpha = TRUE;
|
||||
is_hsl = FALSE;
|
||||
str += 4;
|
||||
}
|
||||
else if (strncmp (str, "rgb", 3) == 0)
|
||||
{
|
||||
has_alpha = FALSE;
|
||||
is_hsl = FALSE;
|
||||
a = 1;
|
||||
str += 3;
|
||||
}
|
||||
else if (strncmp (str, "hsla", 4) == 0)
|
||||
{
|
||||
has_alpha = TRUE;
|
||||
is_hsl = TRUE;
|
||||
str += 4;
|
||||
}
|
||||
else if (strncmp (str, "hsl", 3) == 0)
|
||||
{
|
||||
has_alpha = FALSE;
|
||||
is_hsl = TRUE;
|
||||
a = 1;
|
||||
str += 3;
|
||||
}
|
||||
@@ -308,22 +291,10 @@ gdk_rgba_parse (GdkRGBA *rgba,
|
||||
|
||||
if (rgba)
|
||||
{
|
||||
if (is_hsl)
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
hsla.hue = r * 255;
|
||||
hsla.saturation = CLAMP (g, 0, 1);
|
||||
hsla.lightness = CLAMP (b, 0, 1);
|
||||
hsla.alpha = CLAMP (a, 0, 1);
|
||||
_gdk_rgba_init_from_hsla (rgba, &hsla);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgba->red = CLAMP (r, 0, 1);
|
||||
rgba->green = CLAMP (g, 0, 1);
|
||||
rgba->blue = CLAMP (b, 0, 1);
|
||||
rgba->alpha = CLAMP (a, 0, 1);
|
||||
}
|
||||
rgba->red = CLAMP (r, 0, 1);
|
||||
rgba->green = CLAMP (g, 0, 1);
|
||||
rgba->blue = CLAMP (b, 0, 1);
|
||||
rgba->alpha = CLAMP (a, 0, 1);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -491,47 +462,6 @@ parse_color_channel (GtkCssParser *parser,
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
parse_hsla_color_channel (GtkCssParser *parser,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GdkHSLA *hsla = data;
|
||||
double dvalue;
|
||||
|
||||
switch (arg)
|
||||
{
|
||||
case 0:
|
||||
if (!gtk_css_parser_consume_number (parser, &dvalue))
|
||||
return 0;
|
||||
hsla->hue = dvalue;
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
if (!gtk_css_parser_consume_percentage (parser, &dvalue))
|
||||
return 0;
|
||||
hsla->saturation = CLAMP (dvalue, 0.0, 100.0) / 100.0;
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
if (!gtk_css_parser_consume_percentage (parser, &dvalue))
|
||||
return 0;
|
||||
hsla->lightness = CLAMP (dvalue, 0.0, 100.0) / 100.0;
|
||||
return 1;
|
||||
|
||||
case 3:
|
||||
if (!gtk_css_parser_consume_number (parser, &dvalue))
|
||||
return 0;
|
||||
|
||||
hsla->alpha = CLAMP (dvalue, 0.0, 1.0) / 1.0;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rgba_init_chars (GdkRGBA *rgba,
|
||||
const char s[8])
|
||||
@@ -571,18 +501,6 @@ gdk_rgba_parser_parse (GtkCssParser *parser,
|
||||
{
|
||||
return gtk_css_parser_consume_function (parser, 4, 4, parse_color_channel, rgba);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "hsl") || gtk_css_token_is_function (token, "hsla"))
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
|
||||
hsla.alpha = 1.0;
|
||||
|
||||
if (!gtk_css_parser_consume_function (parser, 3, 4, parse_hsla_color_channel, &hsla))
|
||||
return FALSE;
|
||||
|
||||
_gdk_rgba_init_from_hsla (rgba, &hsla);
|
||||
return TRUE;
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_UNRESTRICTED))
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_rgba_parse (GdkRGBA *rgba,
|
||||
const char *spec);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
char * gdk_rgba_to_string (const GdkRGBA *rgba) G_GNUC_MALLOC;
|
||||
char * gdk_rgba_to_string (const GdkRGBA *rgba);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
495
gdk/gdktexture.c
495
gdk/gdktexture.c
@@ -28,8 +28,8 @@
|
||||
* `GdkPixbuf`, 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]
|
||||
* or [method@Gdk.Texture.download_float].
|
||||
* instance; you can only make a copy of it, via
|
||||
* [method@Gdk.Texture.download].
|
||||
*
|
||||
* `GdkTexture` is an immutable object: That means you cannot change
|
||||
* anything about it other than increasing the reference count via
|
||||
@@ -41,17 +41,11 @@
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkpaintable.h"
|
||||
#include "gdksnapshot.h"
|
||||
|
||||
#include <graphene.h>
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
#include "loaders/gdkjpegprivate.h"
|
||||
|
||||
G_DEFINE_QUARK (gdk-texture-error-quark, gdk_texture_error)
|
||||
|
||||
/* HACK: So we don't need to include any (not-yet-created) GSK or GTK headers */
|
||||
void
|
||||
@@ -114,143 +108,20 @@ gdk_texture_paintable_init (GdkPaintableInterface *iface)
|
||||
iface->get_intrinsic_height = gdk_texture_paintable_get_intrinsic_height;
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
gdk_texture_icon_serialize (GIcon *icon)
|
||||
{
|
||||
GVariant *result;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_texture_save_to_png_bytes (GDK_TEXTURE (icon));
|
||||
result = g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING, bytes, TRUE);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return g_variant_new ("(sv)", "bytes", result);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_icon_init (GIconIface *iface)
|
||||
{
|
||||
iface->hash = (guint (*) (GIcon *)) g_direct_hash;
|
||||
iface->equal = (gboolean (*) (GIcon *, GIcon *)) g_direct_equal;
|
||||
iface->serialize = gdk_texture_icon_serialize;
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_texture_loadable_icon_load (GLoadableIcon *icon,
|
||||
int size,
|
||||
char **type,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_texture_save_to_png_bytes (GDK_TEXTURE (icon));
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
if (type)
|
||||
*type = NULL;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_loadable_icon_load_in_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_texture_save_to_png_bytes (source_object);
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
g_bytes_unref (bytes);
|
||||
g_task_return_pointer (task, stream, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_loadable_icon_load_async (GLoadableIcon *icon,
|
||||
int size,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (icon, cancellable, callback, user_data);
|
||||
g_task_run_in_thread (task, gdk_texture_loadable_icon_load_in_thread);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_texture_loadable_icon_load_finish (GLoadableIcon *icon,
|
||||
GAsyncResult *res,
|
||||
char **type,
|
||||
GError **error)
|
||||
{
|
||||
GInputStream *result;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (res, icon), NULL);
|
||||
|
||||
result = g_task_propagate_pointer (G_TASK (res), error);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
if (type)
|
||||
*type = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_loadable_icon_init (GLoadableIconIface *iface)
|
||||
{
|
||||
iface->load = gdk_texture_loadable_icon_load;
|
||||
iface->load_async = gdk_texture_loadable_icon_load_async;
|
||||
iface->load_finish = gdk_texture_loadable_icon_load_finish;
|
||||
}
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkTexture, gdk_texture, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gdk_texture_paintable_init)
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_ICON,
|
||||
gdk_texture_icon_init)
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LOADABLE_ICON, gdk_texture_loadable_icon_init))
|
||||
gdk_texture_paintable_init))
|
||||
|
||||
#define GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD(obj,method) \
|
||||
g_critical ("Texture of type '%s' does not implement GdkTexture::" # method, G_OBJECT_TYPE_NAME (obj))
|
||||
|
||||
static GdkTexture *
|
||||
gdk_texture_real_download_texture (GdkTexture *self)
|
||||
{
|
||||
GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download_texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_real_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
gdk_texture_real_download (GdkTexture *self,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkTexture *memory_texture;
|
||||
|
||||
memory_texture = gdk_texture_download_texture (texture);
|
||||
gdk_texture_download (memory_texture, data, stride);
|
||||
g_object_unref (memory_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_real_download_float (GdkTexture *self,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkTexture *memory_texture;
|
||||
|
||||
memory_texture = gdk_texture_download_texture (self);
|
||||
gdk_texture_download_float (memory_texture, data, stride);
|
||||
g_object_unref (memory_texture);
|
||||
GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -316,9 +187,7 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->download_texture = gdk_texture_real_download_texture;
|
||||
klass->download = gdk_texture_real_download;
|
||||
klass->download_float = gdk_texture_real_download_float;
|
||||
|
||||
gobject_class->set_property = gdk_texture_set_property;
|
||||
gobject_class->get_property = gdk_texture_get_property;
|
||||
@@ -394,7 +263,7 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
|
||||
|
||||
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
GDK_MEMORY_DEFAULT,
|
||||
GDK_MEMORY_CAIRO_FORMAT_ARGB32,
|
||||
bytes,
|
||||
cairo_image_surface_get_stride (surface));
|
||||
|
||||
@@ -456,23 +325,18 @@ gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf)
|
||||
GdkTexture *
|
||||
gdk_texture_new_from_resource (const char *resource_path)
|
||||
{
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GError *error = NULL;
|
||||
GdkTexture *texture;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
g_return_val_if_fail (resource_path != NULL, NULL);
|
||||
|
||||
bytes = g_resources_lookup_data (resource_path, 0, &error);
|
||||
if (bytes != NULL)
|
||||
{
|
||||
texture = gdk_texture_new_from_bytes (bytes, &error);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
else
|
||||
texture = NULL;
|
||||
pixbuf = gdk_pixbuf_new_from_resource (resource_path, &error);
|
||||
if (pixbuf == NULL)
|
||||
g_error ("Resource path %s is not a valid image: %s", resource_path, error->message);
|
||||
|
||||
if (texture == NULL)
|
||||
g_error ("Resource path %s s not a valid image: %s", resource_path, error->message);
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
return texture;
|
||||
}
|
||||
@@ -495,65 +359,17 @@ GdkTexture *
|
||||
gdk_texture_new_from_file (GFile *file,
|
||||
GError **error)
|
||||
{
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GdkPixbuf *pixbuf;
|
||||
GInputStream *stream;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, error);
|
||||
if (bytes == NULL)
|
||||
stream = G_INPUT_STREAM (g_file_read (file, NULL, error));
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
texture = gdk_texture_new_from_bytes (bytes, error);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_texture_can_load (GBytes *bytes)
|
||||
{
|
||||
return gdk_is_png (bytes) ||
|
||||
gdk_is_jpeg (bytes) ||
|
||||
gdk_is_tiff (bytes);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_texture_new_from_bytes_internal (GBytes *bytes,
|
||||
GError **error)
|
||||
{
|
||||
if (gdk_is_png (bytes))
|
||||
{
|
||||
return gdk_load_png (bytes, error);
|
||||
}
|
||||
else if (gdk_is_jpeg (bytes))
|
||||
{
|
||||
return gdk_load_jpeg (bytes, error);
|
||||
}
|
||||
else if (gdk_is_tiff (bytes))
|
||||
{
|
||||
return gdk_load_tiff (bytes, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("Unknown image format."));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_texture_new_from_bytes_pixbuf (GBytes *bytes,
|
||||
GError **error)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkTexture *texture;
|
||||
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, error);
|
||||
g_object_unref (stream);
|
||||
if (pixbuf == NULL)
|
||||
@@ -565,82 +381,6 @@ gdk_texture_new_from_bytes_pixbuf (GBytes *bytes,
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gdk_texture_new_from_bytes:
|
||||
* @bytes: a `GBytes` containing the data to load
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Creates a new texture by loading an image from memory,
|
||||
*
|
||||
* The file format is detected automatically. The supported formats
|
||||
* are PNG and JPEG, though more formats might be available.
|
||||
*
|
||||
* If %NULL is returned, then @error will be set.
|
||||
*
|
||||
* Return value: A newly-created `GdkTexture`
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_texture_new_from_bytes (GBytes *bytes,
|
||||
GError **error)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GError *internal_error = NULL;
|
||||
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
texture = gdk_texture_new_from_bytes_internal (bytes, &internal_error);
|
||||
if (texture)
|
||||
return texture;
|
||||
|
||||
if (!g_error_matches (internal_error, GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT) &&
|
||||
!g_error_matches (internal_error, GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_FORMAT))
|
||||
{
|
||||
g_propagate_error (error, internal_error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_clear_error (&internal_error);
|
||||
|
||||
return gdk_texture_new_from_bytes_pixbuf (bytes, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_new_from_filename:
|
||||
* @path: (type filename): the filename to load
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Creates a new texture by loading an image from a file.
|
||||
*
|
||||
* The file format is detected automatically. The supported formats
|
||||
* are PNG and JPEG, though more formats might be available.
|
||||
*
|
||||
* If %NULL is returned, then @error will be set.
|
||||
*
|
||||
* Return value: A newly-created `GdkTexture`
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_texture_new_from_filename (const char *path,
|
||||
GError **error)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GFile *file;
|
||||
|
||||
g_return_val_if_fail (path, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
file = g_file_new_for_path (path);
|
||||
|
||||
texture = gdk_texture_new_from_file (file, error);
|
||||
|
||||
g_object_unref (file);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_get_width: (attributes org.gtk.Method.get_property=width)
|
||||
* @texture: a `GdkTexture`
|
||||
@@ -695,6 +435,20 @@ gdk_texture_download_surface (GdkTexture *texture)
|
||||
return surface;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_texture_download_area (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
g_assert (area->x >= 0);
|
||||
g_assert (area->y >= 0);
|
||||
g_assert (area->x + area->width <= texture->width);
|
||||
g_assert (area->y + area->height <= texture->height);
|
||||
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, area, data, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_download:
|
||||
* @texture: a `GdkTexture`
|
||||
@@ -731,62 +485,10 @@ gdk_texture_download (GdkTexture *texture,
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
|
||||
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, data, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_download_float:
|
||||
* @texture: a `GdkTexture`
|
||||
* @data: (array): pointer to enough memory to be filled with the
|
||||
* downloaded data of @texture
|
||||
* @stride: rowstride in elements, will usually be equal to
|
||||
* gdk_texture_get_width() * 4
|
||||
*
|
||||
* Downloads the @texture into local memory in a high dynamic range format.
|
||||
*
|
||||
* This may be an expensive operation, as the actual texture data
|
||||
* may reside on a GPU or on a remote display server and because the data
|
||||
* may need to be upsampled if it was not already available in this
|
||||
* format.
|
||||
*
|
||||
* You may want to use [method@Gdk.Texture.download] instead if you don't
|
||||
* need high dynamic range support.
|
||||
*
|
||||
* The data format of the downloaded data is equivalent to
|
||||
* GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, so every downloaded
|
||||
* pixel requires 16 bytes of memory.
|
||||
*
|
||||
* Note that the caller is responsible to provide sufficiently
|
||||
* aligned memory to access the resulting data directly as floats.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
void
|
||||
gdk_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_TEXTURE (texture));
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
|
||||
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download_float (texture, data, stride);
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gdk_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
g_object_ref (texture);
|
||||
while (!GDK_IS_MEMORY_TEXTURE (texture))
|
||||
{
|
||||
GdkTexture *downloaded = GDK_TEXTURE_GET_CLASS (texture)->download_texture (texture);
|
||||
g_object_unref (texture);
|
||||
texture = downloaded;
|
||||
}
|
||||
|
||||
return texture;
|
||||
gdk_texture_download_area (texture,
|
||||
&(GdkRectangle) { 0, 0, texture->width, texture->height },
|
||||
data,
|
||||
stride);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -838,8 +540,7 @@ gdk_texture_get_render_data (GdkTexture *self,
|
||||
* This is a utility function intended for debugging and testing.
|
||||
* If you want more control over formats, proper error handling or
|
||||
* want to store to a `GFile` or other location, you might want to
|
||||
* use [method@Gdk.Texture.save_to_png_bytes] or look into the
|
||||
* gdk-pixbuf library.
|
||||
* look into using the gdk-pixbuf library.
|
||||
*
|
||||
* Returns: %TRUE if saving succeeded, %FALSE on failure.
|
||||
*/
|
||||
@@ -847,110 +548,30 @@ gboolean
|
||||
gdk_texture_save_to_png (GdkTexture *texture,
|
||||
const char *filename)
|
||||
{
|
||||
GBytes *bytes;
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t status;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
|
||||
bytes = gdk_save_png (texture);
|
||||
result = g_file_set_contents (filename,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes),
|
||||
NULL);
|
||||
g_bytes_unref (bytes);
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
gdk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
status = cairo_surface_write_to_png (surface, filename);
|
||||
|
||||
if (status != CAIRO_STATUS_SUCCESS ||
|
||||
cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
|
||||
result = FALSE;
|
||||
else
|
||||
result = TRUE;
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_save_to_png_bytes:
|
||||
* @texture: a `GdkTexture`
|
||||
*
|
||||
* Store the given @texture in memory as a PNG file.
|
||||
* Use [ctor@Gdk.Texture.new_from_bytes] to read it back.
|
||||
*
|
||||
* If you want to serialize a texture, this is a convenient and
|
||||
* portable way to do that.
|
||||
*
|
||||
* If you need more control over the generated image, such as
|
||||
* attaching metadata, you should look into an image handling
|
||||
* library such as the gdk-pixbuf library.
|
||||
*
|
||||
* If you are dealing with high dynamic range float data, you
|
||||
* might also want to consider [method@Gdk.Texture.save_to_tiff_bytes]
|
||||
* instead.
|
||||
*
|
||||
* Returns: a newly allocated `GBytes` containing PNG data
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GBytes *
|
||||
gdk_texture_save_to_png_bytes (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
return gdk_save_png (texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_save_to_tiff:
|
||||
* @texture: a `GdkTexture`
|
||||
* @filename: (type filename): the filename to store to
|
||||
*
|
||||
* Store the given @texture to the @filename as a TIFF file.
|
||||
*
|
||||
* GTK will attempt to store data without loss.
|
||||
* Returns: %TRUE if saving succeeded, %FALSE on failure.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
gboolean
|
||||
gdk_texture_save_to_tiff (GdkTexture *texture,
|
||||
const char *filename)
|
||||
{
|
||||
GBytes *bytes;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
|
||||
bytes = gdk_save_tiff (texture);
|
||||
result = g_file_set_contents (filename,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes),
|
||||
NULL);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_save_to_tiff_bytes:
|
||||
* @texture: a `GdkTexture`
|
||||
*
|
||||
* Store the given @texture in memory as a TIFF file.
|
||||
*
|
||||
* Use [ctor@Gdk.Texture.new_from_bytes] to read it back.
|
||||
*
|
||||
* This function is intended to store a representation of the
|
||||
* texture's data that is as accurate as possible. This is
|
||||
* particularly relevant when working with high dynamic range
|
||||
* images and floating-point texture data.
|
||||
*
|
||||
* If that is not your concern and you are interested in a
|
||||
* smaller size and a more portable format, you might want to
|
||||
* use [method@Gdk.Texture.save_to_png_bytes].
|
||||
*
|
||||
* Returns: a newly allocated `GBytes` containing TIFF data
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GBytes *
|
||||
gdk_texture_save_to_tiff_bytes (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
return gdk_save_tiff (texture);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,30 +38,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkTexture, g_object_unref)
|
||||
|
||||
typedef struct _GdkTextureClass GdkTextureClass;
|
||||
|
||||
#define GDK_TEXTURE_ERROR (gdk_texture_error_quark ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GQuark gdk_texture_error_quark (void);
|
||||
|
||||
/**
|
||||
* GdkTextureError:
|
||||
* @GDK_TEXTURE_ERROR_TOO_LARGE: Not enough memory to handle this image
|
||||
* @GDK_TEXTURE_ERROR_CORRUPT_IMAGE: The image data appears corrupted
|
||||
* @GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT: The image contains features
|
||||
* that cannot be loaded
|
||||
* @GDK_TEXTURE_ERROR_UNSUPPORTED_FORMAT: The image format is not supported
|
||||
*
|
||||
* Possible errors that can be returned by `GdkTexture` constructors.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GDK_TEXTURE_ERROR_TOO_LARGE,
|
||||
GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
|
||||
GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT,
|
||||
GDK_TEXTURE_ERROR_UNSUPPORTED_FORMAT,
|
||||
} GdkTextureError;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_texture_get_type (void) G_GNUC_CONST;
|
||||
@@ -73,12 +49,6 @@ GdkTexture * gdk_texture_new_from_resource (const char
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTexture * gdk_texture_new_from_file (GFile *file,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkTexture * gdk_texture_new_from_filename (const char *path,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkTexture * gdk_texture_new_from_bytes (GBytes *bytes,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gdk_texture_get_width (GdkTexture *texture) G_GNUC_PURE;
|
||||
@@ -89,20 +59,9 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gdk_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
void gdk_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_texture_save_to_png (GdkTexture *texture,
|
||||
const char *filename);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GBytes * gdk_texture_save_to_png_bytes (GdkTexture *texture);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
gboolean gdk_texture_save_to_tiff (GdkTexture *texture,
|
||||
const char *filename);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GBytes * gdk_texture_save_to_tiff_bytes (GdkTexture *texture);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -24,23 +24,21 @@ struct _GdkTexture
|
||||
struct _GdkTextureClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* mandatory: Download into a GdkMemoryTexture */
|
||||
GdkTexture * (* download_texture) (GdkTexture *texture);
|
||||
/* optional */
|
||||
void (* download) (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
void (* download_float) (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride);
|
||||
};
|
||||
|
||||
gboolean gdk_texture_can_load (GBytes *bytes);
|
||||
|
||||
gpointer gdk_texture_new (const GdkTextureClass *klass,
|
||||
int width,
|
||||
int height);
|
||||
GdkTexture * gdk_texture_new_for_surface (cairo_surface_t *surface);
|
||||
cairo_surface_t * gdk_texture_download_surface (GdkTexture *texture);
|
||||
/* NB: GdkMemoryTexture */
|
||||
GdkTexture * gdk_texture_download_texture (GdkTexture *texture);
|
||||
void gdk_texture_download_area (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
|
||||
gboolean gdk_texture_set_render_data (GdkTexture *self,
|
||||
gpointer key,
|
||||
|
||||
@@ -1,329 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 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 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/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkjpegprivate.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
/* {{{ Error handling */
|
||||
|
||||
/* No sigsetjmp on Windows */
|
||||
#ifndef HAVE_SIGSETJMP
|
||||
#define sigjmp_buf jmp_buf
|
||||
#define sigsetjmp(jb, x) setjmp(jb)
|
||||
#define siglongjmp longjmp
|
||||
#endif
|
||||
|
||||
struct error_handler_data {
|
||||
struct jpeg_error_mgr pub;
|
||||
sigjmp_buf setjmp_buffer;
|
||||
GError **error;
|
||||
};
|
||||
|
||||
static void
|
||||
fatal_error_handler (j_common_ptr cinfo)
|
||||
{
|
||||
struct error_handler_data *errmgr;
|
||||
char buffer[JMSG_LENGTH_MAX];
|
||||
|
||||
errmgr = (struct error_handler_data *) cinfo->err;
|
||||
|
||||
cinfo->err->format_message (cinfo, buffer);
|
||||
|
||||
if (errmgr->error && *errmgr->error == NULL)
|
||||
g_set_error (errmgr->error,
|
||||
GDK_TEXTURE_ERROR,
|
||||
GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
|
||||
_("Error interpreting JPEG image file (%s)"), buffer);
|
||||
|
||||
siglongjmp (errmgr->setjmp_buffer, 1);
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
output_message_handler (j_common_ptr cinfo)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Format conversion */
|
||||
|
||||
static void
|
||||
convert_rgba_to_rgb (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, y;
|
||||
guchar *src, *dest;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = data;
|
||||
dest = data;
|
||||
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
guint32 pixel;
|
||||
|
||||
memcpy (&pixel, src, sizeof (guint32));
|
||||
|
||||
dest[0] = (pixel & 0x00ff0000) >> 16;
|
||||
dest[1] = (pixel & 0x0000ff00) >> 8;
|
||||
dest[2] = (pixel & 0x000000ff) >> 0;
|
||||
|
||||
dest += 3;
|
||||
src += 4;
|
||||
}
|
||||
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_grayscale_to_rgb (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, y;
|
||||
guchar *dest, *src;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = data + width;
|
||||
dest = data + 3 * width;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
dest -= 3;
|
||||
src -= 1;
|
||||
dest[0] = *src;
|
||||
dest[1] = *src;
|
||||
dest[2] = *src;
|
||||
}
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_cmyk_to_rgba (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, r;
|
||||
guchar *dest;
|
||||
|
||||
for (r = 0; r < height; r++)
|
||||
{
|
||||
dest = data;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
int c, m, y, k;
|
||||
|
||||
c = dest[0];
|
||||
m = dest[1];
|
||||
y = dest[2];
|
||||
k = dest[3];
|
||||
dest[0] = k * c / 255;
|
||||
dest[1] = k * m / 255;
|
||||
dest[2] = k * y / 255;
|
||||
dest[3] = 255;
|
||||
dest += 4;
|
||||
}
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
GdkTexture *
|
||||
gdk_load_jpeg (GBytes *input_bytes,
|
||||
GError **error)
|
||||
{
|
||||
struct jpeg_decompress_struct info;
|
||||
struct error_handler_data jerr;
|
||||
guint width, height, stride;
|
||||
unsigned char *data;
|
||||
unsigned char *row[1];
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
|
||||
info.err = jpeg_std_error (&jerr.pub);
|
||||
jerr.pub.error_exit = fatal_error_handler;
|
||||
jerr.pub.output_message = output_message_handler;
|
||||
jerr.error = error;
|
||||
|
||||
if (sigsetjmp (jerr.setjmp_buffer, 1))
|
||||
{
|
||||
jpeg_destroy_decompress (&info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jpeg_create_decompress (&info);
|
||||
|
||||
jpeg_mem_src (&info,
|
||||
g_bytes_get_data (input_bytes, NULL),
|
||||
g_bytes_get_size (input_bytes));
|
||||
|
||||
jpeg_read_header (&info, TRUE);
|
||||
jpeg_start_decompress (&info);
|
||||
|
||||
width = info.output_width;
|
||||
height = info.output_height;
|
||||
|
||||
switch ((int)info.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
case JCS_RGB:
|
||||
stride = 3 * width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
stride = 4 * width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT,
|
||||
_("Unsupported JPEG colorspace (%d)"), info.out_color_space);
|
||||
jpeg_destroy_decompress (&info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!data)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_TOO_LARGE,
|
||||
_("Not enough memory for image size %ux%u"), width, height);
|
||||
jpeg_destroy_decompress (&info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (info.output_scanline < info.output_height)
|
||||
{
|
||||
row[0] = (unsigned char *)(&data[stride * info.output_scanline]);
|
||||
jpeg_read_scanlines (&info, row, 1);
|
||||
}
|
||||
|
||||
switch ((int)info.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
convert_grayscale_to_rgb (data, width, height, stride);
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
break;
|
||||
case JCS_RGB:
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
convert_cmyk_to_rgba (data, width, height, stride);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
jpeg_finish_decompress (&info);
|
||||
jpeg_destroy_decompress (&info);
|
||||
|
||||
bytes = g_bytes_new_take (data, stride * height);
|
||||
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
format,
|
||||
bytes, stride);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
GBytes *
|
||||
gdk_save_jpeg (GdkTexture *texture)
|
||||
{
|
||||
struct jpeg_compress_struct info;
|
||||
struct error_handler_data jerr;
|
||||
struct jpeg_error_mgr err;
|
||||
guchar *data = NULL;
|
||||
gulong size = 0;
|
||||
guchar *input = NULL;
|
||||
guchar *row;
|
||||
int width, height, stride;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
info.err = jpeg_std_error (&jerr.pub);
|
||||
jerr.pub.error_exit = fatal_error_handler;
|
||||
jerr.pub.output_message = output_message_handler;
|
||||
jerr.error = NULL;
|
||||
|
||||
if (sigsetjmp (jerr.setjmp_buffer, 1))
|
||||
{
|
||||
free (data);
|
||||
g_free (input);
|
||||
jpeg_destroy_compress (&info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info.err = jpeg_std_error (&err);
|
||||
jpeg_create_compress (&info);
|
||||
info.image_width = width;
|
||||
info.image_height = height;
|
||||
info.input_components = 3;
|
||||
info.in_color_space = JCS_RGB;
|
||||
|
||||
jpeg_set_defaults (&info);
|
||||
jpeg_set_quality (&info, 75, TRUE);
|
||||
|
||||
jpeg_mem_dest (&info, &data, &size);
|
||||
|
||||
stride = width * 4;
|
||||
input = g_malloc (stride * height);
|
||||
gdk_texture_download (texture, input, stride);
|
||||
convert_rgba_to_rgb (data, width, height, stride);
|
||||
|
||||
jpeg_start_compress (&info, TRUE);
|
||||
|
||||
while (info.next_scanline < info.image_height)
|
||||
{
|
||||
row = &input[info.next_scanline * stride];
|
||||
jpeg_write_scanlines (&info, &row, 1);
|
||||
}
|
||||
|
||||
jpeg_finish_compress (&info);
|
||||
|
||||
g_free (input);
|
||||
jpeg_destroy_compress (&info);
|
||||
|
||||
return g_bytes_new_with_free_func (data, size, (GDestroyNotify) free, NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
@@ -1,43 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 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 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_JPEG_PRIVATE_H__
|
||||
#define __GDK_JPEG_PRIVATE_H__
|
||||
|
||||
#include "gdkmemorytexture.h"
|
||||
#include <gio/gio.h>
|
||||
|
||||
#define JPEG_SIGNATURE "\xff\xd8"
|
||||
|
||||
GdkTexture *gdk_load_jpeg (GBytes *bytes,
|
||||
GError **error);
|
||||
|
||||
GBytes *gdk_save_jpeg (GdkTexture *texture);
|
||||
|
||||
static inline gboolean
|
||||
gdk_is_jpeg (GBytes *bytes)
|
||||
{
|
||||
const char *data;
|
||||
gsize size;
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
|
||||
return size > strlen (JPEG_SIGNATURE) &&
|
||||
memcmp (data, JPEG_SIGNATURE, strlen (JPEG_SIGNATURE)) == 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,568 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 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 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/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkpngprivate.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdktextureprivate.h"
|
||||
#include "gsk/ngl/fp16private.h"
|
||||
#include <png.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* The main difference between the png load/save code here and
|
||||
* gdk-pixbuf is that we can support loading 16-bit data in the
|
||||
* future, and we can extract gamma and colorspace information
|
||||
* to produce linear, color-corrected data.
|
||||
*/
|
||||
|
||||
/* {{{ Callbacks */
|
||||
|
||||
/* No sigsetjmp on Windows */
|
||||
#ifndef HAVE_SIGSETJMP
|
||||
#define sigjmp_buf jmp_buf
|
||||
#define sigsetjmp(jb, x) setjmp(jb)
|
||||
#define siglongjmp longjmp
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guchar *data;
|
||||
gsize size;
|
||||
gsize position;
|
||||
} png_io;
|
||||
|
||||
|
||||
static void
|
||||
png_read_func (png_structp png,
|
||||
png_bytep data,
|
||||
png_size_t size)
|
||||
{
|
||||
png_io *io;
|
||||
|
||||
io = png_get_io_ptr (png);
|
||||
|
||||
if (io->position + size > io->size)
|
||||
png_error (png, "Read past EOF");
|
||||
|
||||
memcpy (data, io->data + io->position, size);
|
||||
io->position += size;
|
||||
}
|
||||
|
||||
static void
|
||||
png_write_func (png_structp png,
|
||||
png_bytep data,
|
||||
png_size_t size)
|
||||
{
|
||||
png_io *io;
|
||||
|
||||
io = png_get_io_ptr (png);
|
||||
|
||||
if (io->position > io->size ||
|
||||
io->size - io->position < size)
|
||||
{
|
||||
io->size = io->position + size;
|
||||
io->data = g_realloc (io->data, io->size);
|
||||
}
|
||||
|
||||
memcpy (io->data + io->position, data, size);
|
||||
io->position += size;
|
||||
}
|
||||
|
||||
static void
|
||||
png_flush_func (png_structp png)
|
||||
{
|
||||
}
|
||||
|
||||
static png_voidp
|
||||
png_malloc_callback (png_structp o,
|
||||
png_size_t size)
|
||||
{
|
||||
return g_try_malloc (size);
|
||||
}
|
||||
|
||||
static void
|
||||
png_free_callback (png_structp o,
|
||||
png_voidp x)
|
||||
{
|
||||
g_free (x);
|
||||
}
|
||||
|
||||
static void
|
||||
png_simple_error_callback (png_structp png,
|
||||
png_const_charp error_msg)
|
||||
{
|
||||
GError **error = png_get_error_ptr (png);
|
||||
|
||||
if (error && !*error)
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
|
||||
_("Error reading png (%s)"), error_msg);
|
||||
|
||||
longjmp (png_jmpbuf (png), 1);
|
||||
}
|
||||
|
||||
static void
|
||||
png_simple_warning_callback (png_structp png,
|
||||
png_const_charp error_msg)
|
||||
{
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Format conversion */
|
||||
|
||||
static void
|
||||
unpremultiply (guchar *data,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
gsize x, y;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
guchar *b = &data[x * 4];
|
||||
guint32 pixel;
|
||||
guchar alpha;
|
||||
|
||||
memcpy (&pixel, b, sizeof (guint32));
|
||||
alpha = (pixel & 0xff000000) >> 24;
|
||||
if (alpha == 0)
|
||||
{
|
||||
b[0] = 0;
|
||||
b[1] = 0;
|
||||
b[2] = 0;
|
||||
b[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
b[0] = (((pixel & 0x00ff0000) >> 16) * 255 + alpha / 2) / alpha;
|
||||
b[1] = (((pixel & 0x0000ff00) >> 8) * 255 + alpha / 2) / alpha;
|
||||
b[2] = (((pixel & 0x000000ff) >> 0) * 255 + alpha / 2) / alpha;
|
||||
b[3] = alpha;
|
||||
}
|
||||
}
|
||||
data += width * 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unpremultiply_float_to_16bit (guchar *data,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
gsize x, y;
|
||||
float *src = (float *)data;;
|
||||
guint16 *dest = (guint16 *)data;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
float r, g, b, a;
|
||||
|
||||
r = src[0];
|
||||
g = src[1];
|
||||
b = src[2];
|
||||
a = src[3];
|
||||
if (a == 0)
|
||||
{
|
||||
dest[0] = 0;
|
||||
dest[1] = 0;
|
||||
dest[2] = 0;
|
||||
dest[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = (guint16) CLAMP (65536.f * r / a, 0.f, 65535.f);
|
||||
dest[1] = (guint16) CLAMP (65536.f * g / a, 0.f, 65535.f);
|
||||
dest[2] = (guint16) CLAMP (65536.f * b / a, 0.f, 65535.f);
|
||||
dest[3] = (guint16) CLAMP (65536.f * a, 0.f, 65535.f);
|
||||
}
|
||||
|
||||
dest += 4;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
multiply_alpha (int alpha, int color)
|
||||
{
|
||||
int temp = (alpha * color) + 0x80;
|
||||
return ((temp + (temp >> 8)) >> 8);
|
||||
}
|
||||
|
||||
static void
|
||||
premultiply_data (png_structp png,
|
||||
png_row_infop row_info,
|
||||
png_bytep data)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < row_info->rowbytes; i += 4)
|
||||
{
|
||||
uint8_t *base = &data[i];
|
||||
uint8_t alpha = base[3];
|
||||
uint32_t p;
|
||||
|
||||
if (alpha == 0)
|
||||
{
|
||||
p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t red = base[0];
|
||||
uint8_t green = base[1];
|
||||
uint8_t blue = base[2];
|
||||
|
||||
if (alpha != 0xff)
|
||||
{
|
||||
red = multiply_alpha (alpha, red);
|
||||
green = multiply_alpha (alpha, green);
|
||||
blue = multiply_alpha (alpha, blue);
|
||||
}
|
||||
p = ((uint32_t)alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
|
||||
}
|
||||
memcpy (base, &p, sizeof (uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_bytes_to_data (png_structp png,
|
||||
png_row_infop row_info,
|
||||
png_bytep data)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < row_info->rowbytes; i += 4)
|
||||
{
|
||||
uint8_t *base = &data[i];
|
||||
uint8_t red = base[0];
|
||||
uint8_t green = base[1];
|
||||
uint8_t blue = base[2];
|
||||
uint32_t pixel;
|
||||
|
||||
pixel = (0xffu << 24) | (red << 16) | (green << 8) | (blue << 0);
|
||||
memcpy (base, &pixel, sizeof (uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
premultiply_16bit (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, y;
|
||||
guint16 *src;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = (guint16 *)data;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
float alpha = src[x * 4 + 3] / 65535.f;
|
||||
src[x * 4 ] = (guint16) CLAMP (src[x * 4 ] * alpha, 0.f, 65535.f);
|
||||
src[x * 4 + 1] = (guint16) CLAMP (src[x * 4 + 1] * alpha, 0.f, 65535.f);
|
||||
src[x * 4 + 2] = (guint16) CLAMP (src[x * 4 + 2] * alpha, 0.f, 65535.f);
|
||||
}
|
||||
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
GdkTexture *
|
||||
gdk_load_png (GBytes *bytes,
|
||||
GError **error)
|
||||
{
|
||||
png_io io;
|
||||
png_struct *png = NULL;
|
||||
png_info *info;
|
||||
guint width, height;
|
||||
int depth, color_type;
|
||||
int interlace, stride;
|
||||
GdkMemoryFormat format;
|
||||
guchar *buffer = NULL;
|
||||
guchar **row_pointers = NULL;
|
||||
GBytes *out_bytes;
|
||||
GdkTexture *texture;
|
||||
int bpp;
|
||||
|
||||
io.data = (guchar *)g_bytes_get_data (bytes, &io.size);
|
||||
io.position = 0;
|
||||
|
||||
png = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING,
|
||||
error,
|
||||
png_simple_error_callback,
|
||||
png_simple_warning_callback,
|
||||
NULL,
|
||||
png_malloc_callback,
|
||||
png_free_callback);
|
||||
if (png == NULL)
|
||||
g_error ("Out of memory");
|
||||
|
||||
info = png_create_info_struct (png);
|
||||
if (info == NULL)
|
||||
g_error ("Out of memory");
|
||||
|
||||
png_set_read_fn (png, &io, png_read_func);
|
||||
|
||||
if (sigsetjmp (png_jmpbuf (png), 1))
|
||||
{
|
||||
g_free (buffer);
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_read_info (png, info);
|
||||
|
||||
png_get_IHDR (png, info,
|
||||
&width, &height, &depth,
|
||||
&color_type, &interlace, NULL, NULL);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb (png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY)
|
||||
png_set_expand_gray_1_2_4_to_8 (png);
|
||||
|
||||
if (png_get_valid (png, info, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha (png);
|
||||
|
||||
if (depth == 8)
|
||||
png_set_filler (png, 0xff, PNG_FILLER_AFTER);
|
||||
|
||||
if (depth < 8)
|
||||
png_set_packing (png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb (png);
|
||||
|
||||
if (interlace != PNG_INTERLACE_NONE)
|
||||
png_set_interlace_handling (png);
|
||||
|
||||
png_read_update_info (png, info);
|
||||
png_get_IHDR (png, info,
|
||||
&width, &height, &depth,
|
||||
&color_type, &interlace, NULL, NULL);
|
||||
if ((depth != 8 && depth != 16) ||
|
||||
!(color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_RGB_ALPHA))
|
||||
{
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT,
|
||||
_("Failed to parse png image"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (color_type)
|
||||
{
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
if (depth == 8)
|
||||
{
|
||||
format = GDK_MEMORY_DEFAULT;
|
||||
png_set_read_user_transform_fn (png, premultiply_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
png_set_swap (png);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
if (depth == 8)
|
||||
{
|
||||
format = GDK_MEMORY_DEFAULT;
|
||||
png_set_read_user_transform_fn (png, convert_bytes_to_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
format = GDK_MEMORY_R16G16B16;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
png_set_swap (png);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
stride = width * bpp;
|
||||
if (stride % 8)
|
||||
stride += 8 - stride % 8;
|
||||
|
||||
buffer = g_try_malloc_n (height, stride);
|
||||
row_pointers = g_try_malloc_n (height, sizeof (char *));
|
||||
|
||||
if (!buffer || !row_pointers)
|
||||
{
|
||||
g_free (buffer);
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_TOO_LARGE,
|
||||
_("Not enough memory for image size %ux%u"), width, height);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
row_pointers[i] = &buffer[i * stride];
|
||||
|
||||
png_read_image (png, row_pointers);
|
||||
png_read_end (png, info);
|
||||
|
||||
if (format == GDK_MEMORY_R16G16B16A16_PREMULTIPLIED)
|
||||
premultiply_16bit (buffer, width, height, stride);
|
||||
|
||||
out_bytes = g_bytes_new_take (buffer, height * stride);
|
||||
texture = gdk_memory_texture_new (width, height, format, out_bytes, stride);
|
||||
g_bytes_unref (out_bytes);
|
||||
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
GBytes *
|
||||
gdk_save_png (GdkTexture *texture)
|
||||
{
|
||||
png_struct *png = NULL;
|
||||
png_info *info;
|
||||
png_io io = { NULL, 0, 0 };
|
||||
guint width, height, stride;
|
||||
guchar *data = NULL;
|
||||
guchar *row;
|
||||
int y;
|
||||
GdkTexture *mtexture;
|
||||
GdkMemoryFormat format;
|
||||
int png_format;
|
||||
int depth;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
mtexture = gdk_texture_download_texture (texture);
|
||||
format = gdk_memory_texture_get_format (GDK_MEMORY_TEXTURE (mtexture));
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
stride = width * 4;
|
||||
data = g_malloc_n (stride, height);
|
||||
gdk_texture_download (mtexture, data, stride);
|
||||
unpremultiply (data, width, height);
|
||||
|
||||
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
depth = 8;
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
data = g_malloc_n (width * 16, height);
|
||||
gdk_texture_download_float (mtexture, (float *)data, width * 4);
|
||||
unpremultiply_float_to_16bit (data, width, height);
|
||||
|
||||
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
stride = width * 8;
|
||||
depth = 16;
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
png = png_create_write_struct_2 (PNG_LIBPNG_VER_STRING, NULL,
|
||||
png_simple_error_callback,
|
||||
png_simple_warning_callback,
|
||||
NULL,
|
||||
png_malloc_callback,
|
||||
png_free_callback);
|
||||
if (!png)
|
||||
return NULL;
|
||||
|
||||
info = png_create_info_struct (png);
|
||||
if (!info)
|
||||
{
|
||||
png_destroy_read_struct (&png, NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sigsetjmp (png_jmpbuf (png), 1))
|
||||
{
|
||||
g_free (data);
|
||||
g_free (io.data);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_set_write_fn (png, &io, png_write_func, png_flush_func);
|
||||
|
||||
png_set_IHDR (png, info, width, height, depth,
|
||||
png_format,
|
||||
PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
png_write_info (png, info);
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
png_set_swap (png);
|
||||
#endif
|
||||
|
||||
for (y = 0, row = data; y < height; y++, row += stride)
|
||||
png_write_rows (png, &row, 1);
|
||||
|
||||
png_write_end (png, info);
|
||||
|
||||
png_destroy_write_struct (&png, &info);
|
||||
|
||||
g_free (data);
|
||||
|
||||
return g_bytes_new_take (io.data, io.size);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
@@ -1,43 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 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 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_PNG_PRIVATE_H__
|
||||
#define __GDK_PNG_PRIVATE_H__
|
||||
|
||||
#include "gdktexture.h"
|
||||
#include <gio/gio.h>
|
||||
|
||||
#define PNG_SIGNATURE "\x89PNG"
|
||||
|
||||
GdkTexture *gdk_load_png (GBytes *bytes,
|
||||
GError **error);
|
||||
|
||||
GBytes *gdk_save_png (GdkTexture *texture);
|
||||
|
||||
static inline gboolean
|
||||
gdk_is_png (GBytes *bytes)
|
||||
{
|
||||
const char *data;
|
||||
gsize size;
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
|
||||
return size > strlen (PNG_SIGNATURE) &&
|
||||
memcmp (data, PNG_SIGNATURE, strlen (PNG_SIGNATURE)) == 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,513 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 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 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/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdktiffprivate.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
#include <tiffio.h>
|
||||
|
||||
/* Our main interest in tiff as an image format is that it is
|
||||
* flexible enough to save all our texture formats without
|
||||
* lossy conversions.
|
||||
*
|
||||
* The loader isn't meant to be a very versatile. It just aims
|
||||
* to load the subset that we're saving ourselves. For anything
|
||||
* else, we fall back to TIFFRGBAImage, which is the same api
|
||||
* that gdk-pixbuf uses.
|
||||
*/
|
||||
|
||||
/* {{{ IO handling */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GBytes **out_bytes;
|
||||
gchar *data;
|
||||
gsize size;
|
||||
gsize position;
|
||||
} TiffIO;
|
||||
|
||||
static void
|
||||
tiff_io_warning (const char *module,
|
||||
const char *fmt,
|
||||
va_list ap) G_GNUC_PRINTF(2, 0);
|
||||
static void
|
||||
tiff_io_warning (const char *module,
|
||||
const char *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
|
||||
}
|
||||
|
||||
static void
|
||||
tiff_io_error (const char *module,
|
||||
const char *fmt,
|
||||
va_list ap) G_GNUC_PRINTF(2, 0);
|
||||
static void
|
||||
tiff_io_error (const char *module,
|
||||
const char *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
|
||||
}
|
||||
|
||||
static tsize_t
|
||||
tiff_io_no_read (thandle_t handle,
|
||||
tdata_t buffer,
|
||||
tsize_t size)
|
||||
{
|
||||
return (tsize_t) -1;
|
||||
}
|
||||
|
||||
static tsize_t
|
||||
tiff_io_read (thandle_t handle,
|
||||
tdata_t buffer,
|
||||
tsize_t size)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
gsize read;
|
||||
|
||||
if (io->position >= io->size)
|
||||
return 0;
|
||||
|
||||
read = MIN (size, io->size - io->position);
|
||||
|
||||
memcpy (buffer, io->data + io->position, read);
|
||||
io->position += read;
|
||||
|
||||
return (tsize_t) read;
|
||||
}
|
||||
|
||||
static tsize_t
|
||||
tiff_io_no_write (thandle_t handle,
|
||||
tdata_t buffer,
|
||||
tsize_t size)
|
||||
{
|
||||
return (tsize_t) -1;
|
||||
}
|
||||
|
||||
static tsize_t
|
||||
tiff_io_write (thandle_t handle,
|
||||
tdata_t buffer,
|
||||
tsize_t size)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
|
||||
if (io->position > io->size ||
|
||||
io->size - io->position < size)
|
||||
{
|
||||
io->size = io->position + size;
|
||||
io->data = g_realloc (io->data, io->size);
|
||||
}
|
||||
|
||||
memcpy (io->data + io->position, buffer, size);
|
||||
io->position += size;
|
||||
|
||||
return (tsize_t) size;
|
||||
}
|
||||
|
||||
static toff_t
|
||||
tiff_io_seek (thandle_t handle,
|
||||
toff_t offset,
|
||||
int whence)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
default:
|
||||
return -1;
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
offset += io->position;
|
||||
break;
|
||||
case SEEK_END:
|
||||
offset += io->size;
|
||||
break;
|
||||
}
|
||||
if (offset < 0)
|
||||
return -1;
|
||||
|
||||
io->position = offset;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static int
|
||||
tiff_io_close (thandle_t handle)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
|
||||
if (io->out_bytes)
|
||||
*io->out_bytes = g_bytes_new_take (io->data, io->size);
|
||||
|
||||
g_free (io);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static toff_t
|
||||
tiff_io_get_file_size (thandle_t handle)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
|
||||
return io->size;
|
||||
}
|
||||
|
||||
static TIFF *
|
||||
tiff_open_read (GBytes *bytes)
|
||||
{
|
||||
TiffIO *io;
|
||||
|
||||
TIFFSetWarningHandler ((TIFFErrorHandler) tiff_io_warning);
|
||||
TIFFSetErrorHandler ((TIFFErrorHandler) tiff_io_error);
|
||||
|
||||
io = g_new0 (TiffIO, 1);
|
||||
|
||||
io->data = (char *) g_bytes_get_data (bytes, &io->size);
|
||||
|
||||
return TIFFClientOpen ("GTK-read", "r",
|
||||
(thandle_t) io,
|
||||
tiff_io_read,
|
||||
tiff_io_no_write,
|
||||
tiff_io_seek,
|
||||
tiff_io_close,
|
||||
tiff_io_get_file_size,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static TIFF *
|
||||
tiff_open_write (GBytes **result)
|
||||
{
|
||||
TiffIO *io;
|
||||
|
||||
TIFFSetWarningHandler ((TIFFErrorHandler) tiff_io_warning);
|
||||
TIFFSetErrorHandler ((TIFFErrorHandler) tiff_io_error);
|
||||
|
||||
io = g_new0 (TiffIO, 1);
|
||||
|
||||
io->out_bytes = result;
|
||||
|
||||
return TIFFClientOpen ("GTK-write", "w",
|
||||
(thandle_t) io,
|
||||
tiff_io_no_read,
|
||||
tiff_io_write,
|
||||
tiff_io_seek,
|
||||
tiff_io_close,
|
||||
tiff_io_get_file_size,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Format conversion */
|
||||
|
||||
static void
|
||||
flip_02 (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, y;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
guchar tmp;
|
||||
tmp = data[x * 4];
|
||||
data[x * 4] = data[x * 4 + 2];
|
||||
data[x * 4 + 2] = tmp;
|
||||
}
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
static struct {
|
||||
GdkMemoryFormat format;
|
||||
guint16 bits_per_sample;
|
||||
guint16 samples_per_pixel;
|
||||
guint16 sample_format;
|
||||
} format_data[] = {
|
||||
{ GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT },
|
||||
{ GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT },
|
||||
{ GDK_MEMORY_R16G16B16, 16, 3, SAMPLEFORMAT_UINT },
|
||||
{ GDK_MEMORY_R16G16B16A16_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_UINT },
|
||||
{ GDK_MEMORY_R16G16B16_FLOAT, 16, 3, SAMPLEFORMAT_IEEEFP },
|
||||
{ GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_IEEEFP },
|
||||
{ GDK_MEMORY_R32G32B32_FLOAT, 32, 3, SAMPLEFORMAT_IEEEFP },
|
||||
{ GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, 32, 4, SAMPLEFORMAT_IEEEFP },
|
||||
};
|
||||
|
||||
GBytes *
|
||||
gdk_save_tiff (GdkTexture *texture)
|
||||
{
|
||||
TIFF *tif;
|
||||
int width, height, stride;
|
||||
guint16 bits_per_sample = 0;
|
||||
guint16 samples_per_pixel = 0;
|
||||
guint16 sample_format = 0;
|
||||
const guchar *line;
|
||||
const guchar *data;
|
||||
guchar *new_data = NULL;
|
||||
GBytes *result = NULL;
|
||||
GdkTexture *memory_texture;
|
||||
GdkMemoryFormat format;
|
||||
|
||||
tif = tiff_open_write (&result);
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
memory_texture = gdk_texture_download_texture (texture);
|
||||
format = gdk_memory_texture_get_format (GDK_MEMORY_TEXTURE (memory_texture));
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (format_data); i++)
|
||||
{
|
||||
if (format == format_data[i].format)
|
||||
{
|
||||
data = gdk_memory_texture_get_data (GDK_MEMORY_TEXTURE (memory_texture));
|
||||
stride = gdk_memory_texture_get_stride (GDK_MEMORY_TEXTURE (memory_texture));
|
||||
bits_per_sample = format_data[i].bits_per_sample;
|
||||
samples_per_pixel = format_data[i].samples_per_pixel;
|
||||
sample_format = format_data[i].sample_format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bits_per_sample == 0)
|
||||
{
|
||||
/* An 8-bit format we don't have in the table, handle
|
||||
* it by converting to R8G8B8A8_PREMULTIPLIED
|
||||
*/
|
||||
stride = width * 4;
|
||||
new_data = g_malloc (stride * height);
|
||||
gdk_texture_download (memory_texture, new_data, stride);
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
flip_02 (new_data, width, height, stride);
|
||||
#endif
|
||||
data = new_data;
|
||||
bits_per_sample = 8;
|
||||
samples_per_pixel = 4;
|
||||
sample_format = SAMPLEFORMAT_UINT;
|
||||
}
|
||||
|
||||
TIFFSetField (tif, TIFFTAG_SOFTWARE, "GTK");
|
||||
TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, width);
|
||||
TIFFSetField (tif, TIFFTAG_IMAGELENGTH, height);
|
||||
TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
|
||||
TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel);
|
||||
TIFFSetField (tif, TIFFTAG_SAMPLEFORMAT, sample_format);
|
||||
TIFFSetField (tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
TIFFSetField (tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
|
||||
// TODO: save gamma / colorspace
|
||||
|
||||
if (samples_per_pixel > 3)
|
||||
{
|
||||
guint16 extra_samples[] = { EXTRASAMPLE_ASSOCALPHA };
|
||||
TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples);
|
||||
}
|
||||
|
||||
TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
|
||||
TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
|
||||
line = (const guchar *)data;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
if (TIFFWriteScanline (tif, (void *)line, y, 0) == -1)
|
||||
{
|
||||
TIFFClose (tif);
|
||||
g_free (new_data);
|
||||
g_object_unref (memory_texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line += stride;
|
||||
}
|
||||
|
||||
TIFFFlushData (tif);
|
||||
TIFFClose (tif);
|
||||
|
||||
g_assert (result);
|
||||
|
||||
g_free (new_data);
|
||||
g_object_unref (memory_texture);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
load_fallback (TIFF *tif,
|
||||
GError **error)
|
||||
{
|
||||
int width, height;
|
||||
guchar *data;
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
|
||||
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &height);
|
||||
|
||||
data = g_malloc (width * height * 4);
|
||||
|
||||
if (!TIFFReadRGBAImageOriented (tif, width, height, (uint32 *)data, ORIENTATION_TOPLEFT, 1))
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
|
||||
_("Failed to load RGB data from TIFF file"));
|
||||
g_free (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes = g_bytes_new_take (data, width * height * 4);
|
||||
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
bytes,
|
||||
width * 4);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gdk_load_tiff (GBytes *input_bytes,
|
||||
GError **error)
|
||||
{
|
||||
TIFF *tif;
|
||||
guint16 samples_per_pixel;
|
||||
guint16 bits_per_sample;
|
||||
guint16 photometric;
|
||||
guint16 planarconfig;
|
||||
guint16 sample_format;
|
||||
guint16 orientation;
|
||||
guint32 width, height;
|
||||
GdkMemoryFormat format;
|
||||
guchar *data, *line;
|
||||
gsize stride;
|
||||
int bpp;
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
|
||||
tif = tiff_open_read (input_bytes);
|
||||
|
||||
TIFFSetDirectory (tif, 0);
|
||||
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLEFORMAT, &sample_format);
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_PHOTOMETRIC, &photometric);
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_PLANARCONFIG, &planarconfig);
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_ORIENTATION, &orientation);
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_IMAGELENGTH, &height);
|
||||
|
||||
if (samples_per_pixel == 4)
|
||||
{
|
||||
guint16 extra;
|
||||
guint16 *extra_types;
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types))
|
||||
extra = 0;
|
||||
|
||||
if (extra == 0 || extra_types[0] != EXTRASAMPLE_ASSOCALPHA)
|
||||
{
|
||||
texture = load_fallback (tif, error);
|
||||
TIFFClose (tif);
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
format = 0;
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (format_data); i++)
|
||||
{
|
||||
if (format_data[i].sample_format == sample_format &&
|
||||
format_data[i].bits_per_sample == bits_per_sample &&
|
||||
format_data[i].samples_per_pixel == samples_per_pixel)
|
||||
{
|
||||
format = format_data[i].format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (format == 0 ||
|
||||
photometric != PHOTOMETRIC_RGB ||
|
||||
planarconfig != PLANARCONFIG_CONTIG ||
|
||||
TIFFIsTiled (tif) ||
|
||||
orientation != ORIENTATION_TOPLEFT)
|
||||
{
|
||||
texture = load_fallback (tif, error);
|
||||
TIFFClose (tif);
|
||||
return texture;
|
||||
}
|
||||
|
||||
stride = width * gdk_memory_format_bytes_per_pixel (format);
|
||||
|
||||
g_assert (TIFFScanlineSize (tif) == stride);
|
||||
|
||||
data = g_try_malloc_n (height, stride);
|
||||
if (!data)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_TOO_LARGE,
|
||||
_("Not enough memory for image size %ux%u"), width, height);
|
||||
TIFFClose (tif);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = data;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
if (TIFFReadScanline (tif, line, y, 0) == -1)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
|
||||
_("Reading data failed at row %d"), y);
|
||||
TIFFClose (tif);
|
||||
g_free (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line += stride;
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
bytes = g_bytes_new_take (data, width * height * bpp);
|
||||
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
format,
|
||||
bytes, width * bpp);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
TIFFClose (tif);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
@@ -1,46 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 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 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_TIFF_PRIVATE_H__
|
||||
#define __GDK_TIFF_PRIVATE_H__
|
||||
|
||||
#include "gdktexture.h"
|
||||
#include <gio/gio.h>
|
||||
|
||||
#define TIFF_SIGNATURE1 "MM\x00\x2a"
|
||||
#define TIFF_SIGNATURE2 "II\x2a\x00"
|
||||
|
||||
GdkTexture *gdk_load_tiff (GBytes *bytes,
|
||||
GError **error);
|
||||
|
||||
GBytes * gdk_save_tiff (GdkTexture *texture);
|
||||
|
||||
static inline gboolean
|
||||
gdk_is_tiff (GBytes *bytes)
|
||||
{
|
||||
const char *data;
|
||||
gsize size;
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
|
||||
return (size > strlen (TIFF_SIGNATURE1) &&
|
||||
memcmp (data, TIFF_SIGNATURE1, strlen (TIFF_SIGNATURE1)) == 0) ||
|
||||
(size > strlen (TIFF_SIGNATURE2) &&
|
||||
memcmp (data, TIFF_SIGNATURE2, strlen (TIFF_SIGNATURE2)) == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -27,7 +27,6 @@ gdk_public_sources = files([
|
||||
'gdkglcontext.c',
|
||||
'gdkglobals.c',
|
||||
'gdkgltexture.c',
|
||||
'gdkhsla.c',
|
||||
'gdkkeys.c',
|
||||
'gdkkeyuni.c',
|
||||
'gdkmemorytexture.c',
|
||||
@@ -51,9 +50,6 @@ gdk_public_sources = files([
|
||||
'gdktoplevelsize.c',
|
||||
'gdktoplevel.c',
|
||||
'gdkdragsurface.c',
|
||||
'loaders/gdkpng.c',
|
||||
'loaders/gdktiff.c',
|
||||
'loaders/gdkjpeg.c',
|
||||
])
|
||||
|
||||
gdk_public_headers = files([
|
||||
@@ -111,7 +107,6 @@ gdk_sources = gdk_public_sources
|
||||
gdk_private_h_sources = files([
|
||||
'gdkeventsprivate.h',
|
||||
'gdkdevicetoolprivate.h',
|
||||
'gdkhslaprivate.h',
|
||||
'gdkmonitorprivate.h',
|
||||
'gdkseatdefaultprivate.h',
|
||||
'gdktoplevelsizeprivate.h',
|
||||
@@ -204,9 +199,6 @@ gdk_deps = [
|
||||
platform_gio_dep,
|
||||
pangocairo_dep,
|
||||
vulkan_dep,
|
||||
png_dep,
|
||||
tiff_dep,
|
||||
jpeg_dep,
|
||||
]
|
||||
|
||||
if profiler_enabled
|
||||
@@ -263,7 +255,7 @@ endif
|
||||
libgdk = static_library('gdk',
|
||||
sources: [gdk_sources, gdk_backends_gen_headers, gdkconfig],
|
||||
dependencies: gdk_deps + [libgtk_css_dep],
|
||||
link_with: [libgtk_css],
|
||||
link_with: [libgtk_css, ],
|
||||
include_directories: [confinc, gdkx11_inc, wlinc],
|
||||
c_args: libgdk_c_args + common_cflags,
|
||||
link_whole: gdk_backends,
|
||||
|
||||
@@ -39,7 +39,7 @@ typedef enum {
|
||||
void gsk_cairo_blur_surface (cairo_surface_t *surface,
|
||||
double radius,
|
||||
GskBlurFlags flags);
|
||||
int gsk_cairo_blur_compute_pixels (double radius) G_GNUC_CONST;
|
||||
int gsk_cairo_blur_compute_pixels (double radius);
|
||||
|
||||
cairo_t * gsk_cairo_blur_start_drawing (cairo_t *cr,
|
||||
float radius,
|
||||
|
||||
@@ -8,7 +8,7 @@ G_BEGIN_DECLS
|
||||
|
||||
void gsk_ensure_resources (void);
|
||||
|
||||
int pango_glyph_string_num_glyphs (PangoGlyphString *glyphs) G_GNUC_PURE;
|
||||
int pango_glyph_string_num_glyphs (PangoGlyphString *glyphs);
|
||||
|
||||
typedef struct _GskVulkanRender GskVulkanRender;
|
||||
typedef struct _GskVulkanRenderPass GskVulkanRenderPass;
|
||||
|
||||
@@ -4477,10 +4477,10 @@ gsk_text_node_new (PangoFont *font,
|
||||
self->num_glyphs = n;
|
||||
|
||||
graphene_rect_init (&node->bounds,
|
||||
offset->x + ink_rect.x,
|
||||
offset->y + ink_rect.y,
|
||||
ink_rect.width,
|
||||
ink_rect.height);
|
||||
offset->x + ink_rect.x - 1,
|
||||
offset->y + ink_rect.y - 1,
|
||||
ink_rect.width + 2,
|
||||
ink_rect.height + 2);
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -5674,7 +5674,7 @@ gsk_render_node_content_serializer_finish (GObject *source,
|
||||
GOutputStream *stream = G_OUTPUT_STREAM (source);
|
||||
GError *error = NULL;
|
||||
|
||||
if (g_output_stream_splice_finish (stream, result, &error) < 0)
|
||||
if (!g_output_stream_write_bytes_finish (stream, result, &error))
|
||||
gdk_content_serializer_return_error (serializer, error);
|
||||
else
|
||||
gdk_content_serializer_return_success (serializer);
|
||||
@@ -5683,7 +5683,6 @@ gsk_render_node_content_serializer_finish (GObject *source,
|
||||
static void
|
||||
gsk_render_node_content_serializer (GdkContentSerializer *serializer)
|
||||
{
|
||||
GInputStream *input;
|
||||
const GValue *value;
|
||||
GskRenderNode *node;
|
||||
GBytes *bytes;
|
||||
@@ -5691,16 +5690,13 @@ gsk_render_node_content_serializer (GdkContentSerializer *serializer)
|
||||
value = gdk_content_serializer_get_value (serializer);
|
||||
node = gsk_value_get_render_node (value);
|
||||
bytes = gsk_render_node_serialize (node);
|
||||
input = g_memory_input_stream_new_from_bytes (bytes);
|
||||
|
||||
g_output_stream_splice_async (gdk_content_serializer_get_output_stream (serializer),
|
||||
input,
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
|
||||
gdk_content_serializer_get_priority (serializer),
|
||||
gdk_content_serializer_get_cancellable (serializer),
|
||||
gsk_render_node_content_serializer_finish,
|
||||
serializer);
|
||||
g_object_unref (input);
|
||||
g_output_stream_write_bytes_async (gdk_content_serializer_get_output_stream (serializer),
|
||||
bytes,
|
||||
gdk_content_serializer_get_priority (serializer),
|
||||
gdk_content_serializer_get_cancellable (serializer),
|
||||
gsk_render_node_content_serializer_finish,
|
||||
serializer);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,17 +85,24 @@ parse_texture (GtkCssParser *parser,
|
||||
scheme = g_uri_parse_scheme (url);
|
||||
if (scheme && g_ascii_strcasecmp (scheme, "data") == 0)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GdkPixbuf *pixbuf;
|
||||
GBytes *bytes;
|
||||
|
||||
texture = NULL;
|
||||
|
||||
bytes = gtk_css_data_url_parse (url, NULL, &error);
|
||||
if (bytes)
|
||||
{
|
||||
texture = gdk_texture_new_from_bytes (bytes, &error);
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = NULL;
|
||||
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
|
||||
g_object_unref (stream);
|
||||
if (pixbuf != NULL)
|
||||
{
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -795,11 +802,6 @@ parse_glyphs (GtkCssParser *parser,
|
||||
gi.attr.is_cluster_start = 0;
|
||||
else
|
||||
gi.attr.is_cluster_start = 1;
|
||||
|
||||
if (gtk_css_parser_try_ident (parser, "color"))
|
||||
gi.attr.is_color = 1;
|
||||
else
|
||||
gi.attr.is_color = 0;
|
||||
}
|
||||
|
||||
pango_glyph_string_set_size (glyph_string, glyph_string->num_glyphs + 1);
|
||||
@@ -2334,8 +2336,7 @@ gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
||||
glyphs[i].geometry.width == ascii->glyphs[j].geometry.width &&
|
||||
glyphs[i].geometry.x_offset == 0 &&
|
||||
glyphs[i].geometry.y_offset == 0 &&
|
||||
glyphs[i].attr.is_cluster_start &&
|
||||
!glyphs[i].attr.is_color)
|
||||
glyphs[i].attr.is_cluster_start)
|
||||
{
|
||||
switch (j + MIN_ASCII_GLYPH)
|
||||
{
|
||||
@@ -2365,7 +2366,6 @@ gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
||||
g_string_append_printf (p, "%u ", glyphs[i].glyph);
|
||||
string_append_double (p, (double) glyphs[i].geometry.width / PANGO_SCALE);
|
||||
if (!glyphs[i].attr.is_cluster_start ||
|
||||
glyphs[i].attr.is_color ||
|
||||
glyphs[i].geometry.x_offset != 0 ||
|
||||
glyphs[i].geometry.y_offset != 0)
|
||||
{
|
||||
@@ -2375,8 +2375,6 @@ gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
||||
string_append_double (p, (double) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||
if (!glyphs[i].attr.is_cluster_start)
|
||||
g_string_append (p, " same-cluster");
|
||||
if (!glyphs[i].attr.is_color)
|
||||
g_string_append (p, " color");
|
||||
}
|
||||
|
||||
if (i + 1 < n_glyphs)
|
||||
@@ -2692,23 +2690,26 @@ render_node_print (Printer *p,
|
||||
case GSK_TEXTURE_NODE:
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
GBytes *bytes;
|
||||
cairo_surface_t *surface;
|
||||
GByteArray *array;
|
||||
|
||||
start_node (p, "texture");
|
||||
append_rect_param (p, "bounds", &node->bounds);
|
||||
|
||||
bytes = gdk_texture_save_to_png_bytes (texture);
|
||||
surface = gdk_texture_download_surface (texture);
|
||||
array = g_byte_array_new ();
|
||||
cairo_surface_write_to_png_stream (surface, cairo_write_array, array);
|
||||
|
||||
_indent (p);
|
||||
g_string_append (p->str, "texture: url(\"data:image/png;base64,");
|
||||
b64 = base64_encode_with_linebreaks (g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes));
|
||||
b64 = base64_encode_with_linebreaks (array->data, array->len);
|
||||
append_escaping_newlines (p->str, b64);
|
||||
g_free (b64);
|
||||
g_string_append (p->str, "\");\n");
|
||||
end_node (p);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
g_byte_array_free (array, TRUE);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ void gsk_rounded_rect_scale_affine (GskRoundedRect
|
||||
float dx,
|
||||
float dy);
|
||||
|
||||
gboolean gsk_rounded_rect_is_circular (const GskRoundedRect *self) G_GNUC_PURE;
|
||||
gboolean gsk_rounded_rect_is_circular (const GskRoundedRect *self);
|
||||
|
||||
void gsk_rounded_rect_path (const GskRoundedRect *self,
|
||||
cairo_t *cr);
|
||||
@@ -33,7 +33,7 @@ void gsk_rounded_rect_to_float (const GskRounde
|
||||
|
||||
gboolean gsk_rounded_rect_equal (gconstpointer rect1,
|
||||
gconstpointer rect2) G_GNUC_PURE;
|
||||
char * gsk_rounded_rect_to_string (const GskRoundedRect *self) G_GNUC_MALLOC;
|
||||
char * gsk_rounded_rect_to_string (const GskRoundedRect *self);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -1530,13 +1530,6 @@ gsk_transform_to_2d (GskTransform *self,
|
||||
*
|
||||
* Converts a `GskTransform` to 2D affine transformation factors.
|
||||
*
|
||||
* To recreate an equivalent transform from the factors returned
|
||||
* by this function, use
|
||||
*
|
||||
* gsk_transform_scale (gsk_transform_translate (NULL,
|
||||
* &GRAPHENE_POINT_T (dx, dy)),
|
||||
* sx, sy)
|
||||
*
|
||||
* @self must be a 2D transformation. If you are not
|
||||
* sure, use
|
||||
*
|
||||
|
||||
@@ -37,7 +37,7 @@ as_float (const guint x)
|
||||
// IEEE-754 16-bit floating-point format (without infinity): 1-5-10
|
||||
|
||||
static inline float
|
||||
half_to_float_one (const guint16 x)
|
||||
half_to_float (const guint16 x)
|
||||
{
|
||||
const guint e = (x&0x7C00)>>10; // exponent
|
||||
const guint m = (x&0x03FF)<<13; // mantissa
|
||||
@@ -46,7 +46,7 @@ half_to_float_one (const guint16 x)
|
||||
}
|
||||
|
||||
static inline guint16
|
||||
float_to_half_one (const float x)
|
||||
float_to_half (const float x)
|
||||
{
|
||||
const guint b = as_uint(x)+0x00001000; // round-to-nearest-even
|
||||
const guint e = (b&0x7F800000)>>23; // exponent
|
||||
@@ -58,38 +58,20 @@ void
|
||||
float_to_half4_c (const float f[4],
|
||||
guint16 h[4])
|
||||
{
|
||||
h[0] = float_to_half_one (f[0]);
|
||||
h[1] = float_to_half_one (f[1]);
|
||||
h[2] = float_to_half_one (f[2]);
|
||||
h[3] = float_to_half_one (f[3]);
|
||||
h[0] = float_to_half (f[0]);
|
||||
h[1] = float_to_half (f[1]);
|
||||
h[2] = float_to_half (f[2]);
|
||||
h[3] = float_to_half (f[3]);
|
||||
}
|
||||
|
||||
void
|
||||
half_to_float4_c (const guint16 h[4],
|
||||
float f[4])
|
||||
{
|
||||
f[0] = half_to_float_one (h[0]);
|
||||
f[1] = half_to_float_one (h[1]);
|
||||
f[2] = half_to_float_one (h[2]);
|
||||
f[3] = half_to_float_one (h[3]);
|
||||
}
|
||||
|
||||
void
|
||||
float_to_half_c (const float *f,
|
||||
guint16 *h,
|
||||
int n)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
h[i] = float_to_half_one (f[i]);
|
||||
}
|
||||
|
||||
void
|
||||
half_to_float_c (const guint16 *h,
|
||||
float *f,
|
||||
int n)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
f[i] = half_to_float_one (h[i]);
|
||||
f[0] = half_to_float (h[0]);
|
||||
f[1] = half_to_float (h[1]);
|
||||
f[2] = half_to_float (h[2]);
|
||||
f[3] = half_to_float (h[3]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_F16C
|
||||
@@ -140,30 +122,10 @@ half_to_float4 (const guint16 h[4], float f[4])
|
||||
half_to_float4_c (h, f);
|
||||
}
|
||||
|
||||
void
|
||||
float_to_half (const float *f, guint16 *h, int n)
|
||||
{
|
||||
if (have_f16c_msvc ())
|
||||
float_to_half_f16c (f, h, n);
|
||||
else
|
||||
float_to_half4_c (f, h, n);
|
||||
}
|
||||
|
||||
void
|
||||
half_to_float (const guint16 *h, float *f, int n)
|
||||
{
|
||||
if (have_f16c_msvc ())
|
||||
half_to_float_f16c (h, f, n);
|
||||
else
|
||||
half_to_float_c (h, f, n);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void float_to_half4 (const float f[4], guint16 h[4]) __attribute__((ifunc ("resolve_float_to_half4")));
|
||||
void half_to_float4 (const guint16 h[4], float f[4]) __attribute__((ifunc ("resolve_half_to_float4")));
|
||||
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 *
|
||||
resolve_float_to_half4 (void)
|
||||
@@ -185,26 +147,6 @@ resolve_half_to_float4 (void)
|
||||
return half_to_float4_c;
|
||||
}
|
||||
|
||||
static void *
|
||||
resolve_float_to_half (void)
|
||||
{
|
||||
__builtin_cpu_init ();
|
||||
if (__builtin_cpu_supports ("f16c"))
|
||||
return float_to_half_f16c;
|
||||
else
|
||||
return float_to_half_c;
|
||||
}
|
||||
|
||||
static void *
|
||||
resolve_half_to_float (void)
|
||||
{
|
||||
__builtin_cpu_init ();
|
||||
if (__builtin_cpu_supports ("f16c"))
|
||||
return half_to_float_f16c;
|
||||
else
|
||||
return half_to_float_c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#else /* ! HAVE_F16C */
|
||||
@@ -226,28 +168,10 @@ half_to_float4 (const guint16 h[4],
|
||||
half_to_float4_c (h, f);
|
||||
}
|
||||
|
||||
void
|
||||
float_to_half (const float *f,
|
||||
guint16 *h,
|
||||
int n)
|
||||
{
|
||||
float_to_half_c (f, h, n);
|
||||
}
|
||||
|
||||
void
|
||||
half_to_float (const guint16 *h,
|
||||
float *f,
|
||||
int n)
|
||||
{
|
||||
half_to_float_c (h, f, n);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void float_to_half4 (const float f[4], guint16 h[4]) __attribute__((alias ("float_to_half4_c")));
|
||||
void half_to_float4 (const guint16 h[4], float f[4]) __attribute__((alias ("half_to_float4_c")));
|
||||
void float_to_half (const float *f, guint16 *h, int n) __attribute__((alias ("float_to_half_c")));
|
||||
void half_to_float (const guint16 *h, float *f, int n) __attribute__((alias ("half_to_float_c")));
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#else
|
||||
#define CAST_M128I_P(a) (__m128i_u const *) a
|
||||
#endif
|
||||
|
||||
void
|
||||
float_to_half4_f16c (const float f[4],
|
||||
guint16 h[4])
|
||||
@@ -49,74 +50,4 @@ half_to_float4_f16c (const guint16 h[4],
|
||||
_mm_store_ps (f, s);
|
||||
}
|
||||
|
||||
#define ALIGNED(p, n) (GPOINTER_TO_UINT(p) % n == 0)
|
||||
void
|
||||
float_to_half_f16c (const float *f,
|
||||
guint16 *h,
|
||||
int n)
|
||||
{
|
||||
__m128 s;
|
||||
__m128i i;
|
||||
int j;
|
||||
const float *ff = f;
|
||||
guint16 *hh = h;
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
if (ALIGNED (ff, 16) && ALIGNED (hh, 16))
|
||||
break;
|
||||
ff++;
|
||||
hh++;
|
||||
}
|
||||
|
||||
float_to_half_c (f, h, j);
|
||||
|
||||
for (; j + 4 < n; j += 4)
|
||||
{
|
||||
s = _mm_loadu_ps (ff);
|
||||
i = _mm_cvtps_ph (s, 0);
|
||||
_mm_storel_epi64 ((__m128i*)hh, i);
|
||||
ff += 4;
|
||||
hh += 4;
|
||||
}
|
||||
|
||||
if (j < n)
|
||||
float_to_half_c (ff, hh, n - j);
|
||||
}
|
||||
|
||||
void
|
||||
half_to_float_f16c (const guint16 *h,
|
||||
float *f,
|
||||
int n)
|
||||
{
|
||||
__m128i i;
|
||||
__m128 s;
|
||||
int j;
|
||||
const guint16 *hh = h;
|
||||
float *ff = f;
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
if (ALIGNED (ff, 16) && ALIGNED (hh, 16))
|
||||
break;
|
||||
ff++;
|
||||
hh++;
|
||||
}
|
||||
|
||||
half_to_float_c (h, f, j);
|
||||
|
||||
for (; j + 4 < n; j += 4)
|
||||
{
|
||||
i = _mm_loadl_epi64 (CAST_M128I_P (hh));
|
||||
s = _mm_cvtph_ps (i);
|
||||
_mm_store_ps (ff, s);
|
||||
hh += 4;
|
||||
ff += 4;
|
||||
}
|
||||
|
||||
if (j < n)
|
||||
half_to_float_c (hh, ff, n - j);
|
||||
}
|
||||
|
||||
#endif /* HAVE_F16C */
|
||||
|
||||
|
||||
@@ -35,42 +35,18 @@ void float_to_half4 (const float f[4],
|
||||
void half_to_float4 (const guint16 h[4],
|
||||
float f[4]);
|
||||
|
||||
void float_to_half (const float *f,
|
||||
guint16 *h,
|
||||
int n);
|
||||
|
||||
void half_to_float (const guint16 *h,
|
||||
float *f,
|
||||
int n);
|
||||
|
||||
void float_to_half4_f16c (const float f[4],
|
||||
guint16 h[4]);
|
||||
|
||||
void half_to_float4_f16c (const guint16 h[4],
|
||||
float f[4]);
|
||||
|
||||
void float_to_half_f16c (const float *f,
|
||||
guint16 *h,
|
||||
int n);
|
||||
|
||||
void half_to_float_f16c (const guint16 *h,
|
||||
float *f,
|
||||
int n);
|
||||
|
||||
void float_to_half4_c (const float f[4],
|
||||
guint16 h[4]);
|
||||
|
||||
void half_to_float4_c (const guint16 h[4],
|
||||
float f[4]);
|
||||
|
||||
void float_to_half_c (const float *f,
|
||||
guint16 *h,
|
||||
int n);
|
||||
|
||||
void half_to_float_c (const guint16 *h,
|
||||
float *f,
|
||||
int n);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
@@ -197,10 +197,9 @@ gsk_ngl_command_queue_capture_png (GskNglCommandQueue *self,
|
||||
guint height,
|
||||
gboolean flip_y)
|
||||
{
|
||||
guint stride;
|
||||
cairo_surface_t *surface;
|
||||
guint8 *data;
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
guint stride;
|
||||
|
||||
g_assert (GSK_IS_NGL_COMMAND_QUEUE (self));
|
||||
g_assert (filename != NULL);
|
||||
@@ -223,12 +222,11 @@ gsk_ngl_command_queue_capture_png (GskNglCommandQueue *self,
|
||||
data = flipped;
|
||||
}
|
||||
|
||||
bytes = g_bytes_new_take (data, height * stride);
|
||||
texture = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
|
||||
g_bytes_unref (bytes);
|
||||
surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, width, height, stride);
|
||||
cairo_surface_write_to_png (surface, filename);
|
||||
|
||||
gdk_texture_save_to_png (texture, filename);
|
||||
g_object_unref (texture);
|
||||
cairo_surface_destroy (surface);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
|
||||
@@ -735,7 +735,8 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
|
||||
int mag_filter)
|
||||
{
|
||||
GdkGLContext *context;
|
||||
GdkTexture *downloaded_texture;
|
||||
GdkTexture *downloaded_texture = NULL;
|
||||
GdkTexture *source_texture;
|
||||
GskNglTexture *t;
|
||||
guint texture_id;
|
||||
int height;
|
||||
@@ -759,7 +760,21 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
downloaded_texture = gdk_texture_download_texture (texture);
|
||||
cairo_surface_t *surface;
|
||||
|
||||
/* In this case, we have to temporarily make the texture's
|
||||
* context the current one, download its data into our context
|
||||
* and then create a texture from it. */
|
||||
if (texture_context != NULL)
|
||||
gdk_gl_context_make_current (texture_context);
|
||||
|
||||
surface = gdk_texture_download_surface (texture);
|
||||
downloaded_texture = gdk_texture_new_for_surface (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
source_texture = downloaded_texture;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -770,17 +785,13 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
downloaded_texture = gdk_texture_download_texture (texture);
|
||||
source_texture = texture;
|
||||
}
|
||||
|
||||
/* The download_texture() call may have switched the GL context. Make sure
|
||||
* the right context is at work again. */
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
texture_id = gsk_ngl_command_queue_upload_texture (self->command_queue,
|
||||
downloaded_texture,
|
||||
source_texture,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
@@ -1131,18 +1142,20 @@ gsk_ngl_driver_lookup_shader (GskNglDriver *self,
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
static void
|
||||
write_atlas_to_png (GskNglDriver *driver,
|
||||
GskNglTextureAtlas *atlas,
|
||||
write_atlas_to_png (GskNglTextureAtlas *atlas,
|
||||
const char *filename)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
int stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, atlas->width);
|
||||
guchar *data = g_malloc (atlas->height * stride);
|
||||
cairo_surface_t *s;
|
||||
|
||||
texture = gdk_gl_texture_new (gsk_ngl_driver_get_context (driver),
|
||||
atlas->texture_id,
|
||||
atlas->width, atlas->height,
|
||||
NULL, NULL);
|
||||
gdk_texture_save_to_png (texture, filename);
|
||||
g_object_unref (texture);
|
||||
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
|
||||
glGetTexImage (GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
|
||||
s = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, atlas->width, atlas->height, stride);
|
||||
cairo_surface_write_to_png (s, filename);
|
||||
|
||||
cairo_surface_destroy (s);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1162,7 +1175,7 @@ gsk_ngl_driver_save_atlases_to_png (GskNglDriver *self,
|
||||
G_DIR_SEPARATOR_S,
|
||||
(int)self->current_frame_id,
|
||||
atlas->texture_id);
|
||||
write_atlas_to_png (self, atlas, filename);
|
||||
write_atlas_to_png (atlas, filename);
|
||||
g_free (filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ gsk_ngl_glyph_library_upload_glyph (GskNglGlyphLibrary *self,
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data,
|
||||
width * 4,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
cairo_image_surface_get_data (surface),
|
||||
width * 4,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
@@ -290,15 +290,9 @@ gsk_ngl_glyph_library_add (GskNglGlyphLibrary *self,
|
||||
pango_extents_to_pixels (&ink_rect, NULL);
|
||||
|
||||
if (key->xshift != 0)
|
||||
{
|
||||
ink_rect.x -= 1;
|
||||
ink_rect.width += 2;
|
||||
}
|
||||
ink_rect.width++;
|
||||
if (key->yshift != 0)
|
||||
{
|
||||
ink_rect.y -= 1;
|
||||
ink_rect.height += 2;
|
||||
}
|
||||
ink_rect.height++;
|
||||
|
||||
width = (int) ceil (ink_rect.width * key->scale / 1024.0);
|
||||
height = (int) ceil (ink_rect.height * key->scale / 1024.0);
|
||||
|
||||
@@ -115,7 +115,7 @@ gsk_ngl_icon_library_add (GskNglIconLibrary *self,
|
||||
{
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data, width * 4,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
surface_data, cairo_image_surface_get_stride (surface),
|
||||
GDK_MEMORY_DEFAULT, width, height);
|
||||
gl_format = GL_RGBA;
|
||||
|
||||
@@ -252,9 +252,6 @@ node_supports_transform (const GskRenderNode *node)
|
||||
case GSK_TEXT_NODE:
|
||||
return TRUE;
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
return node_supports_transform (gsk_shadow_node_get_child (node));
|
||||
|
||||
case GSK_TRANSFORM_NODE:
|
||||
return node_supports_transform (gsk_transform_node_get_child (node));
|
||||
|
||||
@@ -453,21 +450,10 @@ extract_matrix_metadata (GskNglRenderModelview *modelview)
|
||||
&modelview->dx, &modelview->dy);
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_CATEGORY_2D:
|
||||
{
|
||||
float xx, xy, yx, yy, dx, dy;
|
||||
|
||||
gsk_transform_to_2d (modelview->transform,
|
||||
&xx, &xy, &yx, &yy, &dx, &dy);
|
||||
|
||||
modelview->scale_x = sqrtf (xx * xx + xy * xy);
|
||||
modelview->scale_y = sqrtf (yx * yx + yy * yy);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_CATEGORY_UNKNOWN:
|
||||
case GSK_TRANSFORM_CATEGORY_ANY:
|
||||
case GSK_TRANSFORM_CATEGORY_3D:
|
||||
case GSK_TRANSFORM_CATEGORY_2D:
|
||||
{
|
||||
graphene_vec3_t col1;
|
||||
graphene_vec3_t col2;
|
||||
@@ -1748,7 +1734,7 @@ gsk_ngl_render_job_visit_rect_border_node (GskNglRenderJob *job,
|
||||
{
|
||||
rgba_to_half (&colors[2], color);
|
||||
gsk_ngl_render_job_draw_rect_with_color (job,
|
||||
&GRAPHENE_RECT_INIT (origin->x + widths[3], origin->y + size->height - widths[2], size->width - widths[3], widths[2]),
|
||||
&GRAPHENE_RECT_INIT (origin->x + widths[3], origin->y + size->height - widths[2], size->width - widths[1], widths[2]),
|
||||
color);
|
||||
}
|
||||
|
||||
@@ -2782,58 +2768,6 @@ gsk_ngl_render_job_visit_cross_fade_node (GskNglRenderJob *job,
|
||||
gsk_ngl_render_job_end_draw (job);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_non_branching (const GskRenderNode *node)
|
||||
{
|
||||
switch ((int)gsk_render_node_get_node_type (node))
|
||||
{
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_CONIC_GRADIENT_NODE:
|
||||
case GSK_BORDER_NODE:
|
||||
case GSK_TEXTURE_NODE:
|
||||
case GSK_INSET_SHADOW_NODE:
|
||||
case GSK_OUTSET_SHADOW_NODE:
|
||||
case GSK_TEXT_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
return TRUE;
|
||||
|
||||
case GSK_TRANSFORM_NODE:
|
||||
return is_non_branching (gsk_transform_node_get_child (node));
|
||||
|
||||
case GSK_OPACITY_NODE:
|
||||
return is_non_branching (gsk_opacity_node_get_child (node));
|
||||
|
||||
case GSK_COLOR_MATRIX_NODE:
|
||||
return is_non_branching (gsk_color_matrix_node_get_child (node));
|
||||
|
||||
case GSK_CLIP_NODE:
|
||||
return is_non_branching (gsk_clip_node_get_child (node));
|
||||
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
return is_non_branching (gsk_rounded_clip_node_get_child (node));
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
return is_non_branching (gsk_shadow_node_get_child (node));
|
||||
|
||||
case GSK_BLUR_NODE:
|
||||
return is_non_branching (gsk_shadow_node_get_child (node));
|
||||
|
||||
case GSK_DEBUG_NODE:
|
||||
return is_non_branching (gsk_debug_node_get_child (node));
|
||||
|
||||
case GSK_CONTAINER_NODE:
|
||||
return gsk_container_node_get_n_children (node) == 1 &&
|
||||
is_non_branching (gsk_container_node_get_child (node, 0));
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_ngl_render_job_visit_opacity_node (GskNglRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
@@ -2846,16 +2780,7 @@ gsk_ngl_render_job_visit_opacity_node (GskNglRenderJob *job,
|
||||
{
|
||||
float prev_alpha = gsk_ngl_render_job_set_alpha (job, new_alpha);
|
||||
|
||||
/* Handle a few easy cases without offscreen. We bail out
|
||||
* as soon as we see nodes with multiple children - in theory,
|
||||
* we would only need offscreens for overlapping children.
|
||||
*/
|
||||
if (is_non_branching (child))
|
||||
{
|
||||
gsk_ngl_render_job_visit_node (job, child);
|
||||
gsk_ngl_render_job_set_alpha (job, prev_alpha);
|
||||
}
|
||||
else
|
||||
if (gsk_render_node_get_node_type (child) == GSK_CONTAINER_NODE)
|
||||
{
|
||||
GskNglRenderOffscreen offscreen = {0};
|
||||
|
||||
@@ -2863,7 +2788,9 @@ gsk_ngl_render_job_visit_opacity_node (GskNglRenderJob *job,
|
||||
offscreen.force_offscreen = TRUE;
|
||||
offscreen.reset_clip = TRUE;
|
||||
|
||||
/* Note: offscreen rendering resets alpha to 1.0 */
|
||||
/* The semantics of an opacity node mandate that when, e.g., two
|
||||
* color nodes overlap, there may not be any blending between them.
|
||||
*/
|
||||
if (!gsk_ngl_render_job_visit_node_with_offscreen (job, child, &offscreen))
|
||||
return;
|
||||
|
||||
@@ -2878,6 +2805,10 @@ gsk_ngl_render_job_visit_opacity_node (GskNglRenderJob *job,
|
||||
gsk_ngl_render_job_draw_offscreen (job, &node->bounds, &offscreen);
|
||||
gsk_ngl_render_job_end_draw (job);
|
||||
}
|
||||
else
|
||||
{
|
||||
gsk_ngl_render_job_visit_node (job, child);
|
||||
}
|
||||
|
||||
gsk_ngl_render_job_set_alpha (job, prev_alpha);
|
||||
}
|
||||
@@ -3069,24 +3000,21 @@ gsk_ngl_render_job_visit_shadow_node (GskNglRenderJob *job,
|
||||
graphene_rect_t bounds;
|
||||
guint16 color[4];
|
||||
|
||||
if (shadow->radius == 0 &&
|
||||
gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
|
||||
{
|
||||
gsk_ngl_render_job_offset (job, dx, dy);
|
||||
gsk_ngl_render_job_visit_text_node (job, shadow_child, &shadow->color, TRUE);
|
||||
gsk_ngl_render_job_offset (job, -dx, -dy);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RGBA_IS_CLEAR (&shadow->color))
|
||||
continue;
|
||||
|
||||
if (node_is_invisible (shadow_child))
|
||||
continue;
|
||||
|
||||
if (shadow->radius == 0 &&
|
||||
gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
|
||||
{
|
||||
if (dx != 0 || dy != 0)
|
||||
{
|
||||
gsk_ngl_render_job_offset (job, dx, dy);
|
||||
gsk_ngl_render_job_visit_text_node (job, shadow_child, &shadow->color, TRUE);
|
||||
gsk_ngl_render_job_offset (job, -dx, -dy);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shadow->radius > 0)
|
||||
{
|
||||
float min_x;
|
||||
@@ -4071,7 +3999,7 @@ gsk_ngl_render_job_new (GskNglDriver *driver,
|
||||
job->scale_y = scale_factor;
|
||||
job->viewport = *viewport;
|
||||
|
||||
gsk_ngl_render_job_set_alpha (job, 1.0f);
|
||||
gsk_ngl_render_job_set_alpha (job, 1.0);
|
||||
gsk_ngl_render_job_set_projection_from_rect (job, viewport, NULL);
|
||||
gsk_ngl_render_job_set_modelview (job, gsk_transform_scale (NULL, scale_factor, scale_factor));
|
||||
|
||||
|
||||
@@ -204,22 +204,25 @@ gsk_ngl_shadow_library_lookup (GskNglShadowLibrary *self,
|
||||
|
||||
#if 0
|
||||
static void
|
||||
write_shadow_to_png (GskNglDriver *driver,
|
||||
const Shadow *shadow)
|
||||
write_shadow_to_png (const Shadow *shadow)
|
||||
{
|
||||
int width = shadow->outline.bounds.size.width + (shadow->outline.bounds.origin.x * 2);
|
||||
int height = shadow->outline.bounds.size.height + (shadow->outline.bounds.origin.y * 2);
|
||||
int stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width);
|
||||
guchar *data = g_malloc (height * stride);
|
||||
cairo_surface_t *s;
|
||||
char *filename = g_strdup_printf ("shadow_cache_%d_%d_%d.png",
|
||||
width, height, shadow->texture_id);
|
||||
GdkTexture *texture;
|
||||
|
||||
texture = gdk_gl_texture_new (gsk_ngl_driver_get_context (driver),
|
||||
shadow->texture_id,
|
||||
width, height,
|
||||
NULL, NULL);
|
||||
gdk_texture_save_to_png (texture, filename);
|
||||
glBindTexture (GL_TEXTURE_2D, shadow->texture_id);
|
||||
glGetTexImage (GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
|
||||
s = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32,
|
||||
width, height,
|
||||
stride);
|
||||
cairo_surface_write_to_png (s, filename);
|
||||
|
||||
g_object_unref (texture);
|
||||
cairo_surface_destroy (s);
|
||||
g_free (data);
|
||||
g_free (filename);
|
||||
}
|
||||
#endif
|
||||
@@ -237,7 +240,7 @@ gsk_ngl_shadow_library_begin_frame (GskNglShadowLibrary *self)
|
||||
for (i = 0, p = self->shadows->len; i < p; i++)
|
||||
{
|
||||
const Shadow *shadow = &g_array_index (self->shadows, Shadow, i);
|
||||
write_shadow_to_png (self->driver, shadow);
|
||||
write_shadow_to_png (shadow);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ gsk_ngl_uniform_state_get_value (GskNglUniformState *state,
|
||||
return gsk_ngl_uniform_state_init_value (state, program, format, array_count, key, out_mapping);
|
||||
}
|
||||
|
||||
G_GNUC_PURE static inline guint
|
||||
static inline guint
|
||||
gsk_ngl_uniform_state_align (guint current_pos,
|
||||
guint size)
|
||||
{
|
||||
|
||||
@@ -63,13 +63,13 @@ GtkCssParser * gtk_css_parser_new_for_bytes (GBytes
|
||||
GtkCssParser * gtk_css_parser_ref (GtkCssParser *self);
|
||||
void gtk_css_parser_unref (GtkCssParser *self);
|
||||
|
||||
GFile * gtk_css_parser_get_file (GtkCssParser *self) G_GNUC_PURE;
|
||||
GFile * gtk_css_parser_get_file (GtkCssParser *self);
|
||||
GFile * gtk_css_parser_resolve_url (GtkCssParser *self,
|
||||
const char *url);
|
||||
|
||||
const GtkCssLocation * gtk_css_parser_get_start_location (GtkCssParser *self) G_GNUC_PURE;
|
||||
const GtkCssLocation * gtk_css_parser_get_end_location (GtkCssParser *self) G_GNUC_PURE;
|
||||
const GtkCssLocation * gtk_css_parser_get_block_location (GtkCssParser *self) G_GNUC_PURE;
|
||||
const GtkCssLocation * gtk_css_parser_get_start_location (GtkCssParser *self);
|
||||
const GtkCssLocation * gtk_css_parser_get_end_location (GtkCssParser *self);
|
||||
const GtkCssLocation * gtk_css_parser_get_block_location (GtkCssParser *self);
|
||||
|
||||
const GtkCssToken * gtk_css_parser_peek_token (GtkCssParser *self);
|
||||
const GtkCssToken * gtk_css_parser_get_token (GtkCssParser *self);
|
||||
@@ -132,9 +132,9 @@ gboolean gtk_css_parser_try_at_keyword (GtkCssParser
|
||||
gboolean gtk_css_parser_try_token (GtkCssParser *self,
|
||||
GtkCssTokenType token_type);
|
||||
|
||||
char * gtk_css_parser_consume_ident (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
|
||||
char * gtk_css_parser_consume_string (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
|
||||
char * gtk_css_parser_consume_url (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
|
||||
char * gtk_css_parser_consume_ident (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
|
||||
char * gtk_css_parser_consume_string (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
|
||||
char * gtk_css_parser_consume_url (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
|
||||
gboolean gtk_css_parser_consume_number (GtkCssParser *self,
|
||||
double *number);
|
||||
gboolean gtk_css_parser_consume_integer (GtkCssParser *self,
|
||||
|
||||
@@ -129,7 +129,7 @@ GtkCssTokenizer * gtk_css_tokenizer_new (GBytes
|
||||
GtkCssTokenizer * gtk_css_tokenizer_ref (GtkCssTokenizer *tokenizer);
|
||||
void gtk_css_tokenizer_unref (GtkCssTokenizer *tokenizer);
|
||||
|
||||
const GtkCssLocation * gtk_css_tokenizer_get_location (GtkCssTokenizer *tokenizer) G_GNUC_CONST;
|
||||
const GtkCssLocation * gtk_css_tokenizer_get_location (GtkCssTokenizer *tokenizer);
|
||||
|
||||
gboolean gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer,
|
||||
GtkCssToken *token,
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#include "gdkpixbufutilsprivate.h"
|
||||
#include "gtkscalerprivate.h"
|
||||
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
|
||||
static GdkPixbuf *
|
||||
load_from_stream (GdkPixbufLoader *loader,
|
||||
GInputStream *stream,
|
||||
@@ -93,6 +91,7 @@ size_prepared_cb (GdkPixbufLoader *loader,
|
||||
*/
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_stream_scaled (GInputStream *stream,
|
||||
const char *format,
|
||||
double scale,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
@@ -100,7 +99,14 @@ _gdk_pixbuf_new_from_stream_scaled (GInputStream *stream,
|
||||
GdkPixbufLoader *loader;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
loader = gdk_pixbuf_loader_new ();
|
||||
if (format)
|
||||
{
|
||||
loader = gdk_pixbuf_loader_new_with_type (format, error);
|
||||
if (!loader)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
loader = gdk_pixbuf_loader_new ();
|
||||
|
||||
if (scale != 0)
|
||||
g_signal_connect (loader, "size-prepared",
|
||||
@@ -147,6 +153,7 @@ size_prepared_cb2 (GdkPixbufLoader *loader,
|
||||
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
|
||||
const char *format,
|
||||
int width,
|
||||
int height,
|
||||
gboolean aspect,
|
||||
@@ -157,7 +164,14 @@ _gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
|
||||
GdkPixbuf *pixbuf;
|
||||
int scales[3];
|
||||
|
||||
loader = gdk_pixbuf_loader_new ();
|
||||
if (format)
|
||||
{
|
||||
loader = gdk_pixbuf_loader_new_with_type (format, error);
|
||||
if (!loader)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
loader = gdk_pixbuf_loader_new ();
|
||||
|
||||
scales[0] = width;
|
||||
scales[1] = height;
|
||||
@@ -174,10 +188,11 @@ _gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
|
||||
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_stream (GInputStream *stream,
|
||||
const char *format,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return _gdk_pixbuf_new_from_stream_scaled (stream, 0, cancellable, error);
|
||||
return _gdk_pixbuf_new_from_stream_scaled (stream, format, 0, cancellable, error);
|
||||
}
|
||||
|
||||
/* Like gdk_pixbuf_new_from_resource_at_scale, but
|
||||
@@ -186,6 +201,7 @@ _gdk_pixbuf_new_from_stream (GInputStream *stream,
|
||||
*/
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_resource_scaled (const char *resource_path,
|
||||
const char *format,
|
||||
double scale,
|
||||
GError **error)
|
||||
{
|
||||
@@ -196,7 +212,7 @@ _gdk_pixbuf_new_from_resource_scaled (const char *resource_path,
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
pixbuf = _gdk_pixbuf_new_from_stream_scaled (stream, scale, NULL, error);
|
||||
pixbuf = _gdk_pixbuf_new_from_stream_scaled (stream, format, scale, NULL, error);
|
||||
g_object_unref (stream);
|
||||
|
||||
return pixbuf;
|
||||
@@ -204,13 +220,15 @@ _gdk_pixbuf_new_from_resource_scaled (const char *resource_path,
|
||||
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_resource (const char *resource_path,
|
||||
const char *format,
|
||||
GError **error)
|
||||
{
|
||||
return _gdk_pixbuf_new_from_resource_scaled (resource_path, 0, error);
|
||||
return _gdk_pixbuf_new_from_resource_scaled (resource_path, format, 0, error);
|
||||
}
|
||||
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_resource_at_scale (const char *resource_path,
|
||||
const char *format,
|
||||
int width,
|
||||
int height,
|
||||
gboolean preserve_aspect,
|
||||
@@ -223,7 +241,7 @@ _gdk_pixbuf_new_from_resource_at_scale (const char *resource_path,
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, width, height, preserve_aspect, NULL, error);
|
||||
pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, format, width, height, preserve_aspect, NULL, error);
|
||||
g_object_unref (stream);
|
||||
|
||||
return pixbuf;
|
||||
@@ -487,7 +505,14 @@ gtk_make_symbolic_pixbuf_from_file (GFile *file,
|
||||
GdkTexture *
|
||||
gtk_load_symbolic_texture_from_resource (const char *path)
|
||||
{
|
||||
return gdk_texture_new_from_resource (path);
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkTexture *texture;
|
||||
|
||||
pixbuf = _gdk_pixbuf_new_from_resource (path, "png", NULL);
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
@@ -521,7 +546,7 @@ gtk_load_symbolic_texture_from_file (GFile *file)
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
pixbuf = _gdk_pixbuf_new_from_stream (stream, NULL, NULL);
|
||||
pixbuf = _gdk_pixbuf_new_from_stream (stream, "png", NULL, NULL);
|
||||
g_object_unref (stream);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
@@ -579,44 +604,42 @@ GdkPaintable *
|
||||
gdk_paintable_new_from_bytes_scaled (GBytes *bytes,
|
||||
int scale_factor)
|
||||
{
|
||||
GdkPixbufLoader *loader;
|
||||
GdkPixbuf *pixbuf = NULL;
|
||||
LoaderData loader_data;
|
||||
GdkTexture *texture;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
loader_data.scale_factor = scale_factor;
|
||||
|
||||
if (gdk_texture_can_load (bytes))
|
||||
{
|
||||
/* We know these formats can't be scaled */
|
||||
texture = gdk_texture_new_from_bytes (bytes, NULL);
|
||||
if (texture == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkPixbufLoader *loader;
|
||||
gboolean success;
|
||||
loader = gdk_pixbuf_loader_new ();
|
||||
g_signal_connect (loader, "size-prepared",
|
||||
G_CALLBACK (on_loader_size_prepared), &loader_data);
|
||||
|
||||
loader = gdk_pixbuf_loader_new ();
|
||||
g_signal_connect (loader, "size-prepared",
|
||||
G_CALLBACK (on_loader_size_prepared), &loader_data);
|
||||
if (!gdk_pixbuf_loader_write_bytes (loader, bytes, NULL))
|
||||
goto out;
|
||||
|
||||
success = gdk_pixbuf_loader_write_bytes (loader, bytes, NULL);
|
||||
/* close even when writing failed */
|
||||
success &= gdk_pixbuf_loader_close (loader, NULL);
|
||||
if (!gdk_pixbuf_loader_close (loader, NULL))
|
||||
goto out;
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
|
||||
if (pixbuf != NULL)
|
||||
g_object_ref (pixbuf);
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_loader_get_pixbuf (loader));
|
||||
g_object_unref (loader);
|
||||
}
|
||||
out:
|
||||
gdk_pixbuf_loader_close (loader, NULL);
|
||||
g_object_unref (loader);
|
||||
|
||||
if (!pixbuf)
|
||||
return NULL;
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
if (loader_data.scale_factor != 1)
|
||||
paintable = gtk_scaler_new (GDK_PAINTABLE (texture), loader_data.scale_factor);
|
||||
else
|
||||
paintable = g_object_ref ((GdkPaintable *)texture);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
g_object_unref (texture);
|
||||
|
||||
return paintable;
|
||||
|
||||
@@ -23,26 +23,32 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_stream (GInputStream *stream,
|
||||
const char *format,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
|
||||
const char *format,
|
||||
int width,
|
||||
int height,
|
||||
gboolean aspect,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_stream_scaled (GInputStream *stream,
|
||||
const char *format,
|
||||
double scale,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_resource (const char *resource_path,
|
||||
const char *format,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_resource_at_scale (const char *resource_path,
|
||||
const char *format,
|
||||
int width,
|
||||
int height,
|
||||
gboolean preserve_aspect,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_resource_scaled (const char *resource_path,
|
||||
const char *format,
|
||||
double scale,
|
||||
GError **error);
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ char * gtk_accelerator_get_label_with_keycode (GdkDisplay *display,
|
||||
guint keycode,
|
||||
GdkModifierType accelerator_mods);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkModifierType gtk_accelerator_get_default_mod_mask (void) G_GNUC_CONST;
|
||||
GdkModifierType gtk_accelerator_get_default_mod_mask (void);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -1032,7 +1032,7 @@ gtk_at_context_get_description_accumulate (GtkATContext *self,
|
||||
|
||||
GList *list = gtk_reference_list_accessible_value_get (value);
|
||||
|
||||
for (GList *l = list; l != NULL; l = l->next)
|
||||
for (GList *l = list; l != NULL; l = l->data)
|
||||
{
|
||||
GtkAccessible *rel = GTK_ACCESSIBLE (l->data);
|
||||
GtkATContext *rel_context = gtk_accessible_get_at_context (rel);
|
||||
|
||||
146
gtk/gtkbuilder.c
146
gtk/gtkbuilder.c
@@ -65,6 +65,14 @@
|
||||
* using `dgettext()` in the domain specified. This can also be done by
|
||||
* calling [method@Gtk.Builder.set_translation_domain] on the builder.
|
||||
*
|
||||
* The target toolkit version(s) are described by `<requires>` elements,
|
||||
* the “lib” attribute specifies the widget library in question (currently
|
||||
* the only supported value is “gtk”) and the “version” attribute specifies
|
||||
* the target version in the form “`<major>`.`<minor>`”. `GtkBuilder` will
|
||||
* error out if the version requirements are not met.
|
||||
*
|
||||
* ### Objects
|
||||
*
|
||||
* Objects are described by `<object>` elements, which can contain
|
||||
* `<property>` elements to set properties, `<signal>` elements which
|
||||
* connect signals to handlers, and `<child>` elements, which describe
|
||||
@@ -72,16 +80,10 @@
|
||||
* actions in an action group, or columns in a tree model). A `<child>`
|
||||
* element contains an `<object>` element which describes the child object.
|
||||
*
|
||||
* The target toolkit version(s) are described by `<requires>` elements,
|
||||
* the “lib” attribute specifies the widget library in question (currently
|
||||
* the only supported value is “gtk”) and the “version” attribute specifies
|
||||
* the target version in the form “`<major>`.`<minor>`”. `GtkBuilder` will
|
||||
* error out if the version requirements are not met.
|
||||
*
|
||||
* Typically, the specific kind of object represented by an `<object>`
|
||||
* element is specified by the “class” attribute. If the type has not
|
||||
* been loaded yet, GTK tries to find the `get_type()` function from the
|
||||
* class name by applying heuristics. This works in most cases, but if
|
||||
* class name by applying heuristics; this works in most cases, but if
|
||||
* necessary, it is possible to specify the name of the `get_type()`
|
||||
* function explicitly with the "type-func" attribute.
|
||||
*
|
||||
@@ -92,6 +94,8 @@
|
||||
* reserves ids starting and ending with `___` (three consecutive
|
||||
* underscores) for its own purposes.
|
||||
*
|
||||
* ### Properties and values
|
||||
*
|
||||
* Setting properties of objects is pretty straightforward with the
|
||||
* `<property>` element: the “name” attribute specifies the name of the
|
||||
* property, and the content of the element specifies the value.
|
||||
@@ -125,12 +129,27 @@
|
||||
* exception to this rule is that an object has to be constructed before
|
||||
* it can be used as the value of a construct-only property.
|
||||
*
|
||||
* It is also possible to bind a property value to another object's
|
||||
* ### Property bindings
|
||||
*
|
||||
* It is possible to bind a property value to another object's
|
||||
* property value using the attributes "bind-source" to specify the
|
||||
* source object of the binding, and optionally, "bind-property" and
|
||||
* "bind-flags" to specify the source property and source binding flags
|
||||
* respectively. Internally, `GtkBuilder` implements this using `GBinding`
|
||||
* objects. For more information see g_object_bind_property().
|
||||
* objects. For more information see the documentation for
|
||||
* [method@GObject.Object.bind_property].
|
||||
*
|
||||
* ### Settings bindings
|
||||
*
|
||||
* It is possible to bind a property value to a [class@Gio.Settings] key
|
||||
* inside a schema, by using the attributes "bind-settings-schema" to
|
||||
* define the schema, and "bind-settings-key" to define the key. If either
|
||||
* attribute is set, the other is mandatory. Additionally, you can use
|
||||
* the "bind-flags" attribute to specify the [enum@Gio.SettingsBindFlags]
|
||||
* to be used by the binding. For more information see the documentation
|
||||
* for [method@Gio.Settings.bind].
|
||||
*
|
||||
* ### Internal children
|
||||
*
|
||||
* Sometimes it is necessary to refer to widgets which have implicitly
|
||||
* been constructed by GTK as part of a composite widget, to set
|
||||
@@ -146,7 +165,7 @@
|
||||
* The possible values for the “type” attribute are described in the
|
||||
* sections describing the widget-specific portions of UI definitions.
|
||||
*
|
||||
* # Signal handlers and function pointers
|
||||
* ### Signal handlers and function pointers
|
||||
*
|
||||
* Signal handlers are set up with the `<signal>` element. The “name”
|
||||
* attribute specifies the name of the signal, and the “handler” attribute
|
||||
@@ -161,9 +180,9 @@
|
||||
* the following details should be noted:
|
||||
*
|
||||
* When compiling applications for Windows, you must declare signal callbacks
|
||||
* with %G_MODULE_EXPORT, or they will not be put in the symbol table.
|
||||
* with `G_MODULE_EXPORT`, or they will not be put in the symbol table.
|
||||
* On Linux and Unix, this is not necessary; applications should instead
|
||||
* be compiled with the -Wl,--export-dynamic `CFLAGS`, and linked against
|
||||
* be compiled with the `-Wl,--export-dynamic` `CFLAGS`, and linked against
|
||||
* `gmodule-export-2.0`.
|
||||
*
|
||||
* # A GtkBuilder UI Definition
|
||||
@@ -191,10 +210,10 @@
|
||||
* ```
|
||||
*
|
||||
* Beyond this general structure, several object classes define their
|
||||
* own XML DTD fragments for filling in the ANY placeholders in the DTD
|
||||
* above. Note that a custom element in a <child> element gets parsed by
|
||||
* own XML DTD fragments for filling in the `ANY` placeholders in the DTD
|
||||
* above. Note that a custom element in a `<child>` element gets parsed by
|
||||
* the custom tag handler of the parent object, while a custom element in
|
||||
* an <object> element gets parsed by the custom tag handler of the object.
|
||||
* an `<object>` element gets parsed by the custom tag handler of the object.
|
||||
*
|
||||
* These XML fragments are explained in the documentation of the
|
||||
* respective objects.
|
||||
@@ -210,6 +229,7 @@
|
||||
|
||||
#include "gtkbuilderprivate.h"
|
||||
|
||||
#include "gdkpixbufutilsprivate.h"
|
||||
#include "gtkbuildableprivate.h"
|
||||
#include "gtkbuilderlistitemfactory.h"
|
||||
#include "gtkbuilderscopeprivate.h"
|
||||
@@ -225,6 +245,7 @@
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkicontheme.h"
|
||||
#include "gtkiconthemeprivate.h"
|
||||
#include "gdkpixbufutilsprivate.h"
|
||||
#include "gtkdebug.h"
|
||||
|
||||
|
||||
@@ -717,6 +738,11 @@ gtk_builder_take_bindings (GtkBuilder *builder,
|
||||
BindingExpressionInfo *info = l->data;
|
||||
info->target = target;
|
||||
}
|
||||
else if (common_info->tag_type == TAG_BINDING_SETTING)
|
||||
{
|
||||
BindingSettingsInfo *info = l->data;
|
||||
info->target = target;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
@@ -1144,6 +1170,17 @@ gtk_builder_create_bindings (GtkBuilder *builder,
|
||||
|
||||
free_binding_expression_info (info);
|
||||
}
|
||||
else if (common_info->tag_type == TAG_BINDING_SETTING)
|
||||
{
|
||||
BindingSettingsInfo *info = l->data;
|
||||
GSettings *settings;
|
||||
|
||||
settings = g_settings_new (info->schema);
|
||||
g_settings_bind (settings, info->key, info->target, info->target_pspec->name, info->flags);
|
||||
g_object_unref (settings);
|
||||
|
||||
free_binding_settings_info (info);
|
||||
}
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
@@ -2294,63 +2331,9 @@ gtk_builder_value_from_string_type (GtkBuilder *builder,
|
||||
break;
|
||||
case G_TYPE_OBJECT:
|
||||
case G_TYPE_INTERFACE:
|
||||
if (G_VALUE_HOLDS (value, GDK_TYPE_PAINTABLE) ||
|
||||
if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF) ||
|
||||
G_VALUE_HOLDS (value, GDK_TYPE_PAINTABLE) ||
|
||||
G_VALUE_HOLDS (value, GDK_TYPE_TEXTURE))
|
||||
{
|
||||
GObject *object = g_hash_table_lookup (priv->objects, string);
|
||||
char *filename;
|
||||
GError *tmp_error = NULL;
|
||||
GdkTexture *texture = NULL;
|
||||
|
||||
if (object)
|
||||
{
|
||||
if (g_type_is_a (G_OBJECT_TYPE (object), G_VALUE_TYPE (value)))
|
||||
{
|
||||
g_value_set_object (value, object);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_VALUE,
|
||||
"Could not load image '%s': "
|
||||
" '%s' is already used as object id for a %s",
|
||||
string, string, G_OBJECT_TYPE_NAME (object));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
filename = _gtk_builder_get_resource_path (builder, string);
|
||||
if (filename != NULL)
|
||||
{
|
||||
texture = gdk_texture_new_from_resource (filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
filename = _gtk_builder_get_absolute_filename (builder, string);
|
||||
file = g_file_new_for_path (filename);
|
||||
texture = gdk_texture_new_from_file (file, &tmp_error);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
|
||||
if (!texture)
|
||||
{
|
||||
g_warning ("Could not load image '%s': %s", string, tmp_error->message);
|
||||
g_error_free (tmp_error);
|
||||
|
||||
texture = gdk_texture_new_from_resource (IMAGE_MISSING_RESOURCE_PATH);
|
||||
}
|
||||
|
||||
g_value_take_object (value, texture);
|
||||
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
|
||||
{
|
||||
char *filename;
|
||||
GError *tmp_error = NULL;
|
||||
@@ -2396,13 +2379,28 @@ gtk_builder_value_from_string_type (GtkBuilder *builder,
|
||||
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
g_warning ("Could not load image '%s': %s", string, tmp_error->message);
|
||||
g_warning ("Could not load image '%s': %s",
|
||||
string, tmp_error->message);
|
||||
g_error_free (tmp_error);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_resource (IMAGE_MISSING_RESOURCE_PATH, NULL);
|
||||
pixbuf = _gdk_pixbuf_new_from_resource (IMAGE_MISSING_RESOURCE_PATH, "png", NULL);
|
||||
}
|
||||
|
||||
g_value_take_object (value, pixbuf);
|
||||
if (pixbuf)
|
||||
{
|
||||
if (G_VALUE_HOLDS (value, GDK_TYPE_TEXTURE) ||
|
||||
G_VALUE_HOLDS (value, GDK_TYPE_PAINTABLE))
|
||||
{
|
||||
GdkTexture *texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_value_set_object (value, texture);
|
||||
g_object_unref (texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_value_set_object (value, pixbuf);
|
||||
}
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
|
||||
|
||||
@@ -874,7 +874,8 @@ parse_property (ParserData *data,
|
||||
const char *bind_source = NULL;
|
||||
const char *bind_property = NULL;
|
||||
const char *bind_flags_str = NULL;
|
||||
GBindingFlags bind_flags = G_BINDING_DEFAULT;
|
||||
const char *bind_schema = NULL;
|
||||
const char *bind_key = NULL;
|
||||
gboolean translatable = FALSE;
|
||||
ObjectInfo *object_info;
|
||||
GParamSpec *pspec = NULL;
|
||||
@@ -897,6 +898,8 @@ parse_property (ParserData *data,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "bind-source", &bind_source,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "bind-property", &bind_property,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "bind-flags", &bind_flags_str,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "bind-settings-schema", &bind_schema,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "bind-settings-key", &bind_key,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
@@ -916,21 +919,59 @@ parse_property (ParserData *data,
|
||||
return;
|
||||
}
|
||||
|
||||
if (bind_flags_str)
|
||||
gtk_buildable_parse_context_get_position (&data->ctx, &line, &col);
|
||||
|
||||
if (bind_schema != NULL)
|
||||
{
|
||||
if (!_gtk_builder_flags_from_string (G_TYPE_BINDING_FLAGS, NULL, bind_flags_str, &bind_flags, error))
|
||||
GSettingsBindFlags bind_flags = G_SETTINGS_BIND_DEFAULT;
|
||||
|
||||
if (bind_flags_str)
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
if (!_gtk_builder_flags_from_string (G_TYPE_SETTINGS_BIND_FLAGS, NULL, bind_flags_str, &bind_flags, error))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (bind_key != NULL)
|
||||
{
|
||||
BindingSettingsInfo *binfo;
|
||||
|
||||
binfo = g_slice_new0 (BindingSettingsInfo);
|
||||
binfo->tag_type = TAG_BINDING_SETTING;
|
||||
binfo->target = NULL;
|
||||
binfo->target_pspec = pspec;
|
||||
binfo->schema = g_strdup (bind_schema);
|
||||
binfo->key = g_strdup (bind_key);
|
||||
binfo->flags = bind_flags;
|
||||
binfo->line = line;
|
||||
binfo->col = col;
|
||||
|
||||
object_info->bindings = g_slist_prepend (object_info->bindings, binfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_missing_attribute (data, element_name,
|
||||
"bind-settings-key",
|
||||
error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_buildable_parse_context_get_position (&data->ctx, &line, &col);
|
||||
|
||||
if (bind_source)
|
||||
else if (bind_source != NULL)
|
||||
{
|
||||
GBindingFlags bind_flags = G_BINDING_DEFAULT;
|
||||
BindingInfo *binfo;
|
||||
|
||||
if (bind_flags_str)
|
||||
{
|
||||
if (!_gtk_builder_flags_from_string (G_TYPE_BINDING_FLAGS, NULL, bind_flags_str, &bind_flags, error))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
binfo = g_slice_new0 (BindingInfo);
|
||||
binfo->tag_type = TAG_BINDING;
|
||||
binfo->target = NULL;
|
||||
@@ -943,7 +984,14 @@ parse_property (ParserData *data,
|
||||
|
||||
object_info->bindings = g_slist_prepend (object_info->bindings, binfo);
|
||||
}
|
||||
else if (bind_property)
|
||||
else if (bind_key != NULL)
|
||||
{
|
||||
error_missing_attribute (data, element_name,
|
||||
"bind-settings-schema",
|
||||
error);
|
||||
return;
|
||||
}
|
||||
else if (bind_property != NULL)
|
||||
{
|
||||
error_missing_attribute (data, element_name,
|
||||
"bind-source",
|
||||
@@ -956,7 +1004,7 @@ parse_property (ParserData *data,
|
||||
info->pspec = pspec;
|
||||
info->text = g_string_new ("");
|
||||
info->translatable = translatable;
|
||||
info->bound = bind_source != NULL;
|
||||
info->bound = bind_source != NULL || bind_schema != NULL;
|
||||
info->context = g_strdup (context);
|
||||
info->line = line;
|
||||
info->col = col;
|
||||
@@ -1563,6 +1611,14 @@ free_binding_expression_info (BindingExpressionInfo *info)
|
||||
g_slice_free (BindingExpressionInfo, info);
|
||||
}
|
||||
|
||||
void
|
||||
free_binding_settings_info (BindingSettingsInfo *info)
|
||||
{
|
||||
g_free (info->schema);
|
||||
g_free (info->key);
|
||||
g_slice_free (BindingSettingsInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
free_requires_info (RequiresInfo *info,
|
||||
gpointer user_data)
|
||||
|
||||
@@ -27,6 +27,7 @@ enum {
|
||||
TAG_PROPERTY,
|
||||
TAG_BINDING,
|
||||
TAG_BINDING_EXPRESSION,
|
||||
TAG_BINDING_SETTING,
|
||||
TAG_REQUIRES,
|
||||
TAG_OBJECT,
|
||||
TAG_CHILD,
|
||||
@@ -141,6 +142,18 @@ typedef struct
|
||||
int col;
|
||||
} BindingExpressionInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint tag_type;
|
||||
GObject *target;
|
||||
GParamSpec *target_pspec;
|
||||
char *schema;
|
||||
char *key;
|
||||
GSettingsBindFlags flags;
|
||||
int line;
|
||||
int col;
|
||||
} BindingSettingsInfo;
|
||||
|
||||
typedef struct {
|
||||
guint tag_type;
|
||||
char *library;
|
||||
@@ -228,6 +241,7 @@ void _free_signal_info (SignalInfo *info,
|
||||
void _free_binding_info (BindingInfo *info,
|
||||
gpointer user_data);
|
||||
void free_binding_expression_info (BindingExpressionInfo *info);
|
||||
void free_binding_settings_info (BindingSettingsInfo *info);
|
||||
GtkExpression * expression_info_construct (GtkBuilder *builder,
|
||||
ExpressionInfo *info,
|
||||
GError **error);
|
||||
@@ -250,9 +264,9 @@ const char * _gtk_builder_parser_translate (const char *domain,
|
||||
const char *context,
|
||||
const char *text);
|
||||
char * _gtk_builder_get_resource_path (GtkBuilder *builder,
|
||||
const char *string) G_GNUC_MALLOC;
|
||||
const char *string);
|
||||
char * _gtk_builder_get_absolute_filename (GtkBuilder *builder,
|
||||
const char *string) G_GNUC_MALLOC;
|
||||
const char *string);
|
||||
|
||||
void _gtk_builder_menu_start (ParserData *parser_data,
|
||||
const char *element_name,
|
||||
|
||||
@@ -193,7 +193,7 @@ gtk_color_button_class_init (GtkColorButtonClass *klass)
|
||||
*
|
||||
* Note that this signal is only emitted when the user changes the color.
|
||||
* If you need to react to programmatic color changes as well, use
|
||||
* the notify::rgba signal.
|
||||
* the notify::color signal.
|
||||
*/
|
||||
color_button_signals[COLOR_SET] = g_signal_new (I_("color-set"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
#include "gtkcsscolorvalueprivate.h"
|
||||
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
#include "gtkhslaprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkstylepropertyprivate.h"
|
||||
|
||||
#include "gdk/gdkhslaprivate.h"
|
||||
#include "gdk/gdkrgbaprivate.h"
|
||||
|
||||
typedef enum {
|
||||
@@ -309,10 +309,10 @@ apply_shade (const GdkRGBA *in,
|
||||
GdkRGBA *out,
|
||||
double factor)
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
GtkHSLA hsla;
|
||||
|
||||
_gdk_hsla_init_from_rgba (&hsla, in);
|
||||
_gdk_hsla_shade (&hsla, &hsla, factor);
|
||||
_gtk_hsla_init_from_rgba (&hsla, in);
|
||||
_gtk_hsla_shade (&hsla, &hsla, factor);
|
||||
|
||||
_gdk_rgba_init_from_hsla (out, &hsla);
|
||||
}
|
||||
@@ -699,8 +699,6 @@ gtk_css_color_value_can_parse (GtkCssParser *parser)
|
||||
|| gtk_css_parser_has_function (parser, "shade")
|
||||
|| gtk_css_parser_has_function (parser, "alpha")
|
||||
|| gtk_css_parser_has_function (parser, "mix")
|
||||
|| gtk_css_parser_has_function (parser, "hsl")
|
||||
|| gtk_css_parser_has_function (parser, "hsla")
|
||||
|| gtk_css_parser_has_function (parser, "rgb")
|
||||
|| gtk_css_parser_has_function (parser, "rgba");
|
||||
}
|
||||
|
||||
@@ -26,8 +26,9 @@
|
||||
#include "gtkcssimageinvalidprivate.h"
|
||||
#include "gtkcssimagepaintableprivate.h"
|
||||
#include "gtkstyleproviderprivate.h"
|
||||
#include "gtk/css/gtkcssdataurlprivate.h"
|
||||
#include "gdkpixbufutilsprivate.h"
|
||||
|
||||
#include "gtk/css/gtkcssdataurlprivate.h"
|
||||
|
||||
G_DEFINE_TYPE (GtkCssImageUrl, _gtk_css_image_url, GTK_TYPE_CSS_IMAGE)
|
||||
|
||||
@@ -180,28 +181,28 @@ gtk_css_image_url_parse (GtkCssImage *image,
|
||||
if (scheme && g_ascii_strcasecmp (scheme, "data") == 0)
|
||||
{
|
||||
GBytes *bytes;
|
||||
GdkPaintable *paintable;
|
||||
GError *error = NULL;
|
||||
|
||||
bytes = gtk_css_data_url_parse (url, NULL, &error);
|
||||
if (bytes)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
|
||||
texture = gdk_texture_new_from_bytes (bytes, &error);
|
||||
paintable = gdk_paintable_new_from_bytes_scaled (bytes, 1);
|
||||
g_bytes_unref (bytes);
|
||||
if (texture)
|
||||
{
|
||||
GdkPaintable *paintable = GDK_PAINTABLE (texture);
|
||||
self->loaded_image = gtk_css_image_paintable_new (paintable, paintable);
|
||||
}
|
||||
else
|
||||
if (paintable == NULL)
|
||||
{
|
||||
error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to load image from '%s'", url);
|
||||
gtk_css_parser_emit_error (parser,
|
||||
gtk_css_parser_get_start_location (parser),
|
||||
gtk_css_parser_get_end_location (parser),
|
||||
error);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->loaded_image = gtk_css_image_paintable_new (paintable, paintable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -22,6 +22,68 @@
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
|
||||
GtkCssChange
|
||||
_gtk_css_change_for_sibling (GtkCssChange match)
|
||||
{
|
||||
#define BASE_STATES ( GTK_CSS_CHANGE_CLASS \
|
||||
| GTK_CSS_CHANGE_NAME \
|
||||
| GTK_CSS_CHANGE_ID \
|
||||
| GTK_CSS_CHANGE_FIRST_CHILD \
|
||||
| GTK_CSS_CHANGE_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_STATE \
|
||||
| GTK_CSS_CHANGE_HOVER \
|
||||
| GTK_CSS_CHANGE_DISABLED \
|
||||
| GTK_CSS_CHANGE_SELECTED \
|
||||
| GTK_CSS_CHANGE_BACKDROP)
|
||||
|
||||
#define KEEP_STATES ( ~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE) \
|
||||
| GTK_CSS_CHANGE_NTH_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_LAST_CHILD)
|
||||
|
||||
return (match & KEEP_STATES) | ((match & BASE_STATES) << GTK_CSS_CHANGE_SIBLING_SHIFT);
|
||||
|
||||
#undef BASE_STATES
|
||||
#undef KEEP_STATES
|
||||
}
|
||||
|
||||
GtkCssChange
|
||||
_gtk_css_change_for_child (GtkCssChange match)
|
||||
{
|
||||
#define BASE_STATES ( GTK_CSS_CHANGE_CLASS \
|
||||
| GTK_CSS_CHANGE_NAME \
|
||||
| GTK_CSS_CHANGE_ID \
|
||||
| GTK_CSS_CHANGE_FIRST_CHILD \
|
||||
| GTK_CSS_CHANGE_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_STATE \
|
||||
| GTK_CSS_CHANGE_HOVER \
|
||||
| GTK_CSS_CHANGE_DISABLED \
|
||||
| GTK_CSS_CHANGE_BACKDROP \
|
||||
| GTK_CSS_CHANGE_SELECTED \
|
||||
| GTK_CSS_CHANGE_SIBLING_CLASS \
|
||||
| GTK_CSS_CHANGE_SIBLING_NAME \
|
||||
| GTK_CSS_CHANGE_SIBLING_ID \
|
||||
| GTK_CSS_CHANGE_SIBLING_FIRST_CHILD \
|
||||
| GTK_CSS_CHANGE_SIBLING_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_SIBLING_NTH_CHILD \
|
||||
| GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_SIBLING_STATE \
|
||||
| GTK_CSS_CHANGE_SIBLING_HOVER \
|
||||
| GTK_CSS_CHANGE_SIBLING_DISABLED \
|
||||
| GTK_CSS_CHANGE_SIBLING_BACKDROP \
|
||||
| GTK_CSS_CHANGE_SIBLING_SELECTED)
|
||||
|
||||
#define KEEP_STATES (~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE))
|
||||
|
||||
return (match & KEEP_STATES) | ((match & BASE_STATES) << GTK_CSS_CHANGE_PARENT_SHIFT);
|
||||
|
||||
#undef BASE_STATES
|
||||
#undef KEEP_STATES
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_change_print (GtkCssChange change,
|
||||
GString *string)
|
||||
|
||||
@@ -452,75 +452,16 @@ typedef enum /*< skip >*/ {
|
||||
GTK_CSS_FONT_VARIANT_EAST_ASIAN_RUBY = 1 << 9
|
||||
} GtkCssFontVariantEastAsian;
|
||||
|
||||
static inline GtkCssChange
|
||||
_gtk_css_change_for_sibling (GtkCssChange match)
|
||||
{
|
||||
#define BASE_STATES ( GTK_CSS_CHANGE_CLASS \
|
||||
| GTK_CSS_CHANGE_NAME \
|
||||
| GTK_CSS_CHANGE_ID \
|
||||
| GTK_CSS_CHANGE_FIRST_CHILD \
|
||||
| GTK_CSS_CHANGE_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_STATE \
|
||||
| GTK_CSS_CHANGE_HOVER \
|
||||
| GTK_CSS_CHANGE_DISABLED \
|
||||
| GTK_CSS_CHANGE_SELECTED \
|
||||
| GTK_CSS_CHANGE_BACKDROP)
|
||||
GtkCssChange _gtk_css_change_for_sibling (GtkCssChange match);
|
||||
GtkCssChange _gtk_css_change_for_child (GtkCssChange match);
|
||||
|
||||
#define KEEP_STATES ( ~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE) \
|
||||
| GTK_CSS_CHANGE_NTH_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_LAST_CHILD)
|
||||
GtkCssDimension gtk_css_unit_get_dimension (GtkCssUnit unit);
|
||||
|
||||
return (match & KEEP_STATES) | ((match & BASE_STATES) << GTK_CSS_CHANGE_SIBLING_SHIFT);
|
||||
|
||||
#undef BASE_STATES
|
||||
#undef KEEP_STATES
|
||||
}
|
||||
|
||||
static inline GtkCssChange
|
||||
_gtk_css_change_for_child (GtkCssChange match)
|
||||
{
|
||||
#define BASE_STATES ( GTK_CSS_CHANGE_CLASS \
|
||||
| GTK_CSS_CHANGE_NAME \
|
||||
| GTK_CSS_CHANGE_ID \
|
||||
| GTK_CSS_CHANGE_FIRST_CHILD \
|
||||
| GTK_CSS_CHANGE_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_CHILD \
|
||||
| GTK_CSS_CHANGE_NTH_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_STATE \
|
||||
| GTK_CSS_CHANGE_HOVER \
|
||||
| GTK_CSS_CHANGE_DISABLED \
|
||||
| GTK_CSS_CHANGE_BACKDROP \
|
||||
| GTK_CSS_CHANGE_SELECTED \
|
||||
| GTK_CSS_CHANGE_SIBLING_CLASS \
|
||||
| GTK_CSS_CHANGE_SIBLING_NAME \
|
||||
| GTK_CSS_CHANGE_SIBLING_ID \
|
||||
| GTK_CSS_CHANGE_SIBLING_FIRST_CHILD \
|
||||
| GTK_CSS_CHANGE_SIBLING_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_SIBLING_NTH_CHILD \
|
||||
| GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD \
|
||||
| GTK_CSS_CHANGE_SIBLING_STATE \
|
||||
| GTK_CSS_CHANGE_SIBLING_HOVER \
|
||||
| GTK_CSS_CHANGE_SIBLING_DISABLED \
|
||||
| GTK_CSS_CHANGE_SIBLING_BACKDROP \
|
||||
| GTK_CSS_CHANGE_SIBLING_SELECTED)
|
||||
|
||||
#define KEEP_STATES (~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE))
|
||||
|
||||
return (match & KEEP_STATES) | ((match & BASE_STATES) << GTK_CSS_CHANGE_PARENT_SHIFT);
|
||||
|
||||
#undef BASE_STATES
|
||||
#undef KEEP_STATES
|
||||
}
|
||||
|
||||
GtkCssDimension gtk_css_unit_get_dimension (GtkCssUnit unit) G_GNUC_CONST;
|
||||
|
||||
char * gtk_css_change_to_string (GtkCssChange change) G_GNUC_MALLOC;
|
||||
char * gtk_css_change_to_string (GtkCssChange change);
|
||||
void gtk_css_change_print (GtkCssChange change,
|
||||
GString *string);
|
||||
|
||||
const char * gtk_css_pseudoclass_name (GtkStateFlags flags) G_GNUC_CONST;
|
||||
const char * gtk_css_pseudoclass_name (GtkStateFlags flags);
|
||||
|
||||
/* These hash functions are selected so they achieve 2 things:
|
||||
* 1. collision free among each other
|
||||
|
||||
@@ -87,7 +87,7 @@ void gtk_editable_set_text (GtkEditable *editable,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
char * gtk_editable_get_chars (GtkEditable *editable,
|
||||
int start_pos,
|
||||
int end_pos) G_GNUC_MALLOC;
|
||||
int end_pos);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_editable_insert_text (GtkEditable *editable,
|
||||
const char *text,
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkhslaprivate.h"
|
||||
#include "gtkhslaprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
void
|
||||
_gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
_gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
float min;
|
||||
@@ -31,21 +31,21 @@ _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
float green;
|
||||
float blue;
|
||||
float delta;
|
||||
|
||||
|
||||
g_return_if_fail (hsla != NULL);
|
||||
g_return_if_fail (rgba != NULL);
|
||||
|
||||
red = rgba->red;
|
||||
green = rgba->green;
|
||||
blue = rgba->blue;
|
||||
|
||||
|
||||
if (red > green)
|
||||
{
|
||||
if (red > blue)
|
||||
max = red;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
|
||||
if (green < blue)
|
||||
min = green;
|
||||
else
|
||||
@@ -57,25 +57,25 @@ _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
max = green;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
|
||||
if (red < blue)
|
||||
min = red;
|
||||
else
|
||||
min = blue;
|
||||
}
|
||||
|
||||
|
||||
hsla->lightness = (max + min) / 2;
|
||||
hsla->saturation = 0;
|
||||
hsla->hue = 0;
|
||||
hsla->alpha = rgba->alpha;
|
||||
|
||||
|
||||
if (max != min)
|
||||
{
|
||||
if (hsla->lightness <= 0.5)
|
||||
hsla->saturation = (max - min) / (max + min);
|
||||
else
|
||||
hsla->saturation = (max - min) / (2 - max - min);
|
||||
|
||||
|
||||
delta = max -min;
|
||||
if (red == max)
|
||||
hsla->hue = (green - blue) / delta;
|
||||
@@ -83,7 +83,7 @@ _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
hsla->hue = 2 + (blue - red) / delta;
|
||||
else if (blue == max)
|
||||
hsla->hue = 4 + (red - green) / delta;
|
||||
|
||||
|
||||
hsla->hue *= 60;
|
||||
if (hsla->hue < 0.0)
|
||||
hsla->hue += 360;
|
||||
@@ -92,22 +92,22 @@ _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
|
||||
void
|
||||
_gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
const GdkHSLA *hsla)
|
||||
const GtkHSLA *hsla)
|
||||
{
|
||||
float hue;
|
||||
float lightness;
|
||||
float saturation;
|
||||
float m1, m2;
|
||||
|
||||
|
||||
lightness = hsla->lightness;
|
||||
saturation = hsla->saturation;
|
||||
|
||||
|
||||
if (lightness <= 0.5)
|
||||
m2 = lightness * (1 + saturation);
|
||||
else
|
||||
m2 = lightness + saturation - lightness * saturation;
|
||||
m1 = 2 * lightness - m2;
|
||||
|
||||
|
||||
rgba->alpha = hsla->alpha;
|
||||
|
||||
if (saturation == 0)
|
||||
@@ -123,7 +123,7 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
|
||||
if (hue < 60)
|
||||
rgba->red = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
@@ -132,13 +132,13 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
rgba->red = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->red = m1;
|
||||
|
||||
|
||||
hue = hsla->hue;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
|
||||
if (hue < 60)
|
||||
rgba->green = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
@@ -147,13 +147,13 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
rgba->green = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->green = m1;
|
||||
|
||||
|
||||
hue = hsla->hue - 120;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
|
||||
if (hue < 60)
|
||||
rgba->blue = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
@@ -166,8 +166,8 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_hsla_shade (GdkHSLA *dest,
|
||||
const GdkHSLA *src,
|
||||
_gtk_hsla_shade (GtkHSLA *dest,
|
||||
const GtkHSLA *src,
|
||||
float factor)
|
||||
{
|
||||
g_return_if_fail (dest != NULL);
|
||||
@@ -22,23 +22,23 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GdkHSLA GdkHSLA;
|
||||
typedef struct _GtkHSLA GtkHSLA;
|
||||
|
||||
struct _GdkHSLA {
|
||||
struct _GtkHSLA {
|
||||
float hue;
|
||||
float saturation;
|
||||
float lightness;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
void _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
void _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
const GdkRGBA *rgba);
|
||||
/* Yes, I can name that function like this! */
|
||||
void _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
const GdkHSLA *hsla);
|
||||
const GtkHSLA *hsla);
|
||||
|
||||
void _gdk_hsla_shade (GdkHSLA *dest,
|
||||
const GdkHSLA *src,
|
||||
void _gtk_hsla_shade (GtkHSLA *dest,
|
||||
const GtkHSLA *src,
|
||||
float factor);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -3742,6 +3742,31 @@ gtk_icon_paintable_is_symbolic (GtkIconPaintable *icon)
|
||||
return icon->is_symbolic;
|
||||
}
|
||||
|
||||
static GLoadableIcon *
|
||||
icon_get_loadable (GtkIconPaintable *icon)
|
||||
{
|
||||
GFile *file;
|
||||
GLoadableIcon *loadable;
|
||||
|
||||
if (icon->loadable)
|
||||
return g_object_ref (icon->loadable);
|
||||
|
||||
if (icon->is_resource)
|
||||
{
|
||||
char *uri = g_strconcat ("resource://", icon->filename, NULL);
|
||||
file = g_file_new_for_uri (uri);
|
||||
g_free (uri);
|
||||
}
|
||||
else
|
||||
file = g_file_new_for_path (icon->filename);
|
||||
|
||||
loadable = G_LOADABLE_ICON (g_file_icon_new (file));
|
||||
|
||||
g_object_unref (file);
|
||||
|
||||
return loadable;
|
||||
}
|
||||
|
||||
/* This function contains the complicated logic for deciding
|
||||
* on the size at which to load the icon and loading it at
|
||||
* that size.
|
||||
@@ -3750,6 +3775,7 @@ static void
|
||||
icon_ensure_texture__locked (GtkIconPaintable *icon,
|
||||
gboolean in_thread)
|
||||
{
|
||||
GdkPixbuf *source_pixbuf;
|
||||
gint64 before;
|
||||
int pixel_size;
|
||||
GError *load_error = NULL;
|
||||
@@ -3769,10 +3795,11 @@ icon_ensure_texture__locked (GtkIconPaintable *icon,
|
||||
/* At this point, we need to actually get the icon; either from the
|
||||
* builtin image or by loading the file
|
||||
*/
|
||||
source_pixbuf = NULL;
|
||||
#ifdef G_OS_WIN32
|
||||
if (icon->win32_icon)
|
||||
{
|
||||
icon->texture = gdk_texture_new_for_pixbuf (icon->win32_icon);
|
||||
source_pixbuf = g_object_ref (icon->win32_icon);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -3780,8 +3807,6 @@ icon_ensure_texture__locked (GtkIconPaintable *icon,
|
||||
{
|
||||
if (icon->is_svg)
|
||||
{
|
||||
GdkPixbuf *source_pixbuf;
|
||||
|
||||
if (gtk_icon_paintable_is_symbolic (icon))
|
||||
source_pixbuf = gtk_make_symbolic_pixbuf_from_resource (icon->filename,
|
||||
pixel_size, pixel_size,
|
||||
@@ -3789,67 +3814,33 @@ icon_ensure_texture__locked (GtkIconPaintable *icon,
|
||||
&load_error);
|
||||
else
|
||||
source_pixbuf = _gdk_pixbuf_new_from_resource_at_scale (icon->filename,
|
||||
"svg",
|
||||
pixel_size, pixel_size,
|
||||
TRUE, &load_error);
|
||||
if (source_pixbuf)
|
||||
{
|
||||
icon->texture = gdk_texture_new_for_pixbuf (source_pixbuf);
|
||||
g_object_unref (source_pixbuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
icon->texture = gdk_texture_new_from_resource (icon->filename);
|
||||
}
|
||||
else if (icon->filename)
|
||||
{
|
||||
if (icon->is_svg)
|
||||
{
|
||||
GdkPixbuf *source_pixbuf;
|
||||
source_pixbuf = _gdk_pixbuf_new_from_resource (icon->filename,
|
||||
g_str_has_suffix (icon->filename, ".xpm") ? "xpm" : "png",
|
||||
&load_error);
|
||||
|
||||
if (gtk_icon_paintable_is_symbolic (icon))
|
||||
source_pixbuf = gtk_make_symbolic_pixbuf_from_path (icon->filename,
|
||||
pixel_size, pixel_size,
|
||||
icon->desired_scale,
|
||||
&load_error);
|
||||
else
|
||||
{
|
||||
GFile *file = g_file_new_for_path (icon->filename);
|
||||
GInputStream *stream = G_INPUT_STREAM (g_file_read (file, NULL, &load_error));
|
||||
|
||||
g_object_unref (file);
|
||||
if (stream)
|
||||
{
|
||||
source_pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream,
|
||||
pixel_size, pixel_size,
|
||||
TRUE, NULL,
|
||||
&load_error);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
else
|
||||
source_pixbuf = NULL;
|
||||
}
|
||||
if (source_pixbuf)
|
||||
{
|
||||
icon->texture = gdk_texture_new_for_pixbuf (source_pixbuf);
|
||||
g_object_unref (source_pixbuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (source_pixbuf == NULL)
|
||||
{
|
||||
icon->texture = gdk_texture_new_from_filename (icon->filename, &load_error);
|
||||
g_warning ("Failed to load icon %s: %s", icon->filename, load_error->message);
|
||||
g_clear_error (&load_error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GLoadableIcon *loadable;
|
||||
GInputStream *stream;
|
||||
GdkPixbuf *source_pixbuf;
|
||||
|
||||
g_assert (icon->loadable);
|
||||
|
||||
stream = g_loadable_icon_load (icon->loadable,
|
||||
loadable = icon_get_loadable (icon);
|
||||
stream = g_loadable_icon_load (loadable,
|
||||
pixel_size,
|
||||
NULL, NULL,
|
||||
&load_error);
|
||||
g_object_unref (loadable);
|
||||
|
||||
if (stream)
|
||||
{
|
||||
/* SVG icons are a special case - we just immediately scale them
|
||||
@@ -3857,32 +3848,46 @@ icon_ensure_texture__locked (GtkIconPaintable *icon,
|
||||
*/
|
||||
if (icon->is_svg)
|
||||
{
|
||||
source_pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream,
|
||||
if (gtk_icon_paintable_is_symbolic (icon))
|
||||
source_pixbuf = gtk_make_symbolic_pixbuf_from_path (icon->filename,
|
||||
pixel_size, pixel_size,
|
||||
TRUE, NULL,
|
||||
icon->desired_scale,
|
||||
&load_error);
|
||||
else
|
||||
source_pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream,
|
||||
"svg",
|
||||
pixel_size, pixel_size,
|
||||
TRUE, NULL,
|
||||
&load_error);
|
||||
}
|
||||
else
|
||||
source_pixbuf = _gdk_pixbuf_new_from_stream (stream,
|
||||
g_str_has_suffix (icon->filename, ".xpm") ? "xpm" : "png",
|
||||
NULL, &load_error);
|
||||
g_object_unref (stream);
|
||||
if (source_pixbuf)
|
||||
{
|
||||
icon->texture = gdk_texture_new_for_pixbuf (source_pixbuf);
|
||||
g_object_unref (source_pixbuf);
|
||||
}
|
||||
}
|
||||
|
||||
if (source_pixbuf == NULL)
|
||||
{
|
||||
g_warning ("Failed to load icon %s: %s", icon->filename, load_error->message);
|
||||
g_clear_error (&load_error);
|
||||
}
|
||||
}
|
||||
|
||||
if (!icon->texture)
|
||||
if (!source_pixbuf)
|
||||
{
|
||||
g_warning ("Failed to load icon %s: %s", icon->filename, load_error->message);
|
||||
g_clear_error (&load_error);
|
||||
icon->texture = gdk_texture_new_from_resource (IMAGE_MISSING_RESOURCE_PATH);
|
||||
source_pixbuf = _gdk_pixbuf_new_from_resource (IMAGE_MISSING_RESOURCE_PATH, "png", NULL);
|
||||
icon->icon_name = g_strdup ("image-missing");
|
||||
icon->is_symbolic = FALSE;
|
||||
g_assert (source_pixbuf != NULL);
|
||||
}
|
||||
|
||||
/* Actual scaling is done during rendering, so just keep the source pixbuf as a texture */
|
||||
icon->texture = gdk_texture_new_for_pixbuf (source_pixbuf);
|
||||
g_object_unref (source_pixbuf);
|
||||
|
||||
g_assert (icon->texture != NULL);
|
||||
|
||||
if (GDK_PROFILER_IS_RUNNING)
|
||||
{
|
||||
gint64 end = GDK_PROFILER_CURRENT_TIME;
|
||||
@@ -4084,6 +4089,28 @@ gtk_icon_paintable_new_for_file (GFile *file,
|
||||
return icon;
|
||||
}
|
||||
|
||||
static GtkIconPaintable *
|
||||
gtk_icon_paintable_new_for_pixbuf (GtkIconTheme *icon_theme,
|
||||
GdkPixbuf *pixbuf,
|
||||
int size,
|
||||
int scale)
|
||||
{
|
||||
GtkIconPaintable *icon;
|
||||
int width, height;
|
||||
|
||||
if (size <= 0)
|
||||
{
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
size = MAX (width, height);
|
||||
}
|
||||
|
||||
icon = icon_paintable_new (NULL, size, scale);
|
||||
icon->texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_icon_theme_lookup_by_gicon:
|
||||
* @self: a `GtkIconTheme`
|
||||
@@ -4109,56 +4136,50 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *self,
|
||||
GtkTextDirection direction,
|
||||
GtkIconLookupFlags flags)
|
||||
{
|
||||
GtkIconPaintable *paintable = NULL;
|
||||
GtkIconPaintable *icon = NULL;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
|
||||
g_return_val_if_fail (G_IS_ICON (gicon), NULL);
|
||||
g_return_val_if_fail (size > 0, NULL);
|
||||
g_return_val_if_fail (scale > 0, NULL);
|
||||
|
||||
/* We can't render emblemed icons atm, but at least render the base */
|
||||
while (G_IS_EMBLEMED_ICON (gicon))
|
||||
gicon = g_emblemed_icon_get_icon (G_EMBLEMED_ICON (gicon));
|
||||
g_assert (gicon); /* shut up gcc -Wnull-dereference */
|
||||
|
||||
if (GDK_IS_TEXTURE (gicon))
|
||||
if (GDK_IS_PIXBUF (gicon))
|
||||
{
|
||||
paintable = icon_paintable_new (NULL, size, scale);
|
||||
paintable->texture = g_object_ref (GDK_TEXTURE (gicon));
|
||||
}
|
||||
else if (GDK_IS_PIXBUF (gicon))
|
||||
{
|
||||
paintable = icon_paintable_new (NULL, size, scale);
|
||||
paintable->texture = gdk_texture_new_for_pixbuf (GDK_PIXBUF (gicon));
|
||||
GdkPixbuf *pixbuf = GDK_PIXBUF (gicon);
|
||||
|
||||
icon = gtk_icon_paintable_new_for_pixbuf (self, pixbuf, size, scale);
|
||||
}
|
||||
else if (G_IS_FILE_ICON (gicon))
|
||||
{
|
||||
GFile *file = g_file_icon_get_file (G_FILE_ICON (gicon));
|
||||
|
||||
paintable = gtk_icon_paintable_new_for_file (file, size, scale);
|
||||
icon = gtk_icon_paintable_new_for_file (file, size, scale);
|
||||
}
|
||||
else if (G_IS_LOADABLE_ICON (gicon))
|
||||
{
|
||||
paintable = icon_paintable_new (NULL, size, scale);
|
||||
paintable->loadable = G_LOADABLE_ICON (g_object_ref (gicon));
|
||||
paintable->is_svg = FALSE;
|
||||
icon = icon_paintable_new (NULL, size, scale);
|
||||
icon->loadable = G_LOADABLE_ICON (g_object_ref (gicon));
|
||||
icon->is_svg = FALSE;
|
||||
}
|
||||
else if (G_IS_THEMED_ICON (gicon))
|
||||
{
|
||||
const char **names;
|
||||
|
||||
names = (const char **) g_themed_icon_get_names (G_THEMED_ICON (gicon));
|
||||
paintable = gtk_icon_theme_lookup_icon (self, names[0], &names[1], size, scale, direction, flags);
|
||||
icon = gtk_icon_theme_lookup_icon (self, names[0], &names[1], size, scale, direction, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Unhandled GIcon type %s", G_OBJECT_TYPE_NAME (gicon));
|
||||
paintable = icon_paintable_new ("image-missing", size, scale);
|
||||
paintable->filename = g_strdup (IMAGE_MISSING_RESOURCE_PATH);
|
||||
paintable->is_resource = TRUE;
|
||||
icon = icon_paintable_new ("image-missing", size, scale);
|
||||
icon->filename = g_strdup (IMAGE_MISSING_RESOURCE_PATH);
|
||||
icon->is_resource = TRUE;
|
||||
}
|
||||
|
||||
return paintable;
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -84,7 +84,7 @@ gboolean gtk_init_check_abi_check (int num_checks,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_disable_setlocale (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
PangoLanguage * gtk_get_default_language (void) G_GNUC_CONST;
|
||||
PangoLanguage * gtk_get_default_language (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkTextDirection gtk_get_locale_direction (void);
|
||||
|
||||
|
||||
@@ -669,11 +669,6 @@ gtk_menu_button_init (GtkMenuButton *self)
|
||||
gtk_widget_set_sensitive (self->button, FALSE);
|
||||
|
||||
gtk_widget_add_css_class (GTK_WIDGET (self), "popup");
|
||||
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (self->button),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, self, NULL,
|
||||
GTK_ACCESSIBLE_RELATION_DESCRIBED_BY, self, NULL,
|
||||
-1);
|
||||
}
|
||||
|
||||
static GtkBuildableIface *parent_buildable_iface;
|
||||
@@ -1022,14 +1017,6 @@ gtk_menu_button_set_icon_name (GtkMenuButton *menu_button,
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
|
||||
|
||||
/* Because we are setting only an icon, let the inner button be labelled by us
|
||||
* so the accessible label can be overridden from, for example, an UI file
|
||||
* using GtkMenuButton as a child of something.
|
||||
*/
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (menu_button->button),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, menu_button, NULL,
|
||||
-1);
|
||||
|
||||
image_widget = g_object_new (GTK_TYPE_IMAGE,
|
||||
"accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION,
|
||||
"icon-name", icon_name,
|
||||
@@ -1162,10 +1149,6 @@ gtk_menu_button_set_label (GtkMenuButton *menu_button,
|
||||
gtk_button_set_child (GTK_BUTTON (menu_button->button), box);
|
||||
menu_button->label_widget = label_widget;
|
||||
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (menu_button->button),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, menu_button->label_widget, NULL,
|
||||
-1);
|
||||
|
||||
menu_button->image_widget = NULL;
|
||||
menu_button->child = NULL;
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
#include "gtkcssrepeatvalueprivate.h"
|
||||
#include "gtkcsscolorvalueprivate.h"
|
||||
#include "gtkcssstyleprivate.h"
|
||||
#include "gtkhslaprivate.h"
|
||||
#include "gtkroundedboxprivate.h"
|
||||
#include "gtksnapshotprivate.h"
|
||||
|
||||
#include "gdk/gdkhslaprivate.h"
|
||||
#include "gsk/gskroundedrectprivate.h"
|
||||
|
||||
typedef struct _GtkBorderImage GtkBorderImage;
|
||||
@@ -513,10 +513,10 @@ color_shade (const GdkRGBA *color,
|
||||
double factor,
|
||||
GdkRGBA *color_return)
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
GtkHSLA hsla;
|
||||
|
||||
_gdk_hsla_init_from_rgba (&hsla, color);
|
||||
_gdk_hsla_shade (&hsla, &hsla, factor);
|
||||
_gtk_hsla_init_from_rgba (&hsla, color);
|
||||
_gtk_hsla_shade (&hsla, &hsla, factor);
|
||||
_gdk_rgba_init_from_hsla (color_return, &hsla);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,17 +87,6 @@ gtk_render_node_paintable_paintable_get_intrinsic_height (GdkPaintable *paintabl
|
||||
return ceilf (self->bounds.size.height);
|
||||
}
|
||||
|
||||
static double
|
||||
gtk_render_node_paintable_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
|
||||
{
|
||||
GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
|
||||
|
||||
if (self->bounds.size.height != 0)
|
||||
return self->bounds.size.width / self->bounds.size.height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_render_node_paintable_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
@@ -105,7 +94,6 @@ gtk_render_node_paintable_paintable_init (GdkPaintableInterface *iface)
|
||||
iface->get_flags = gtk_render_node_paintable_paintable_get_flags;
|
||||
iface->get_intrinsic_width = gtk_render_node_paintable_paintable_get_intrinsic_width;
|
||||
iface->get_intrinsic_height = gtk_render_node_paintable_paintable_get_intrinsic_height;
|
||||
iface->get_intrinsic_aspect_ratio = gtk_render_node_paintable_paintable_get_intrinsic_aspect_ratio;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (GtkRenderNodePaintable, gtk_render_node_paintable, G_TYPE_OBJECT, 0,
|
||||
|
||||
@@ -366,7 +366,6 @@ gtk_search_bar_init (GtkSearchBar *bar)
|
||||
gtk_widget_set_hexpand (bar->box_center, TRUE);
|
||||
|
||||
bar->close_button = gtk_button_new_from_icon_name ("window-close-symbolic");
|
||||
gtk_widget_set_valign (bar->close_button, GTK_ALIGN_CENTER);
|
||||
gtk_widget_add_css_class (bar->close_button, "close");
|
||||
gtk_center_box_set_end_widget (GTK_CENTER_BOX (bar->box_center), bar->close_button);
|
||||
gtk_widget_hide (bar->close_button);
|
||||
|
||||
@@ -690,14 +690,13 @@ gtk_stack_dispose (GObject *obj)
|
||||
GtkStack *stack = GTK_STACK (obj);
|
||||
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
|
||||
GtkWidget *child;
|
||||
guint n_pages = g_list_length (priv->children);
|
||||
|
||||
if (priv->pages)
|
||||
g_list_model_items_changed (G_LIST_MODEL (priv->pages), 0, g_list_length (priv->children), 0);
|
||||
|
||||
while ((child = gtk_widget_get_first_child (GTK_WIDGET (stack))))
|
||||
stack_remove (stack, child, TRUE);
|
||||
|
||||
if (priv->pages)
|
||||
g_list_model_items_changed (G_LIST_MODEL (priv->pages), 0, n_pages, 0);
|
||||
|
||||
G_OBJECT_CLASS (gtk_stack_parent_class)->dispose (obj);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ gtk_private_sources = files([
|
||||
'gtkfilechooserutils.c',
|
||||
'gtkfilesystemmodel.c',
|
||||
'gtkgizmo.c',
|
||||
'gtkhsla.c',
|
||||
'gtkiconcache.c',
|
||||
'gtkiconcachevalidator.c',
|
||||
'gtkiconhelper.c',
|
||||
|
||||
@@ -897,8 +897,13 @@ modelbutton.flat arrow {
|
||||
|
||||
.toolbar button {
|
||||
margin: 1px;
|
||||
@extend %undecorated_button;
|
||||
|
||||
@extend %button_basic_flat;
|
||||
&:hover { @include button('hover'); }
|
||||
&:active { @include button('active'); }
|
||||
&:disabled { @include button('insensitive'); }
|
||||
&:backdrop { @include button('backdrop'); }
|
||||
&:backdrop:disabled { @include button('backdrop-insensitive'); }
|
||||
}
|
||||
|
||||
button.color {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<property name="receives-default">1</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="has-frame">0</property>
|
||||
<property name="icon-name">media-playback-start-symbolic</property>
|
||||
<signal name="clicked" handler="play_button_clicked" object="GtkMediaControls" swapped="no"/>
|
||||
</object>
|
||||
|
||||
30
meson.build
30
meson.build
@@ -150,6 +150,11 @@ cdata.set_quoted('GTK_DATADIR', gtk_datadir)
|
||||
cdata.set_quoted('GTK_LIBDIR', gtk_libdir)
|
||||
cdata.set_quoted('GTK_SYSCONFDIR', gtk_sysconfdir)
|
||||
cdata.set_quoted('GETTEXT_PACKAGE', 'gtk40')
|
||||
cdata.set('GTK_MAJOR_VERSION', gtk_major_version)
|
||||
cdata.set('GTK_MINOR_VERSION', gtk_minor_version)
|
||||
cdata.set('GTK_MICRO_VERSION', gtk_micro_version)
|
||||
cdata.set('GTK_BINARY_AGE', gtk_binary_age)
|
||||
cdata.set('GTK_INTERFACE_AGE', gtk_interface_age)
|
||||
|
||||
check_headers = [
|
||||
'crt/externs.h',
|
||||
@@ -207,17 +212,6 @@ foreach func : check_functions
|
||||
endif
|
||||
endforeach
|
||||
|
||||
# We use links() because sigsetjmp() is often a macro hidden behind other macros
|
||||
cdata.set('HAVE_SIGSETJMP',
|
||||
cc.links('''#define _POSIX_SOURCE
|
||||
#include <setjmp.h>
|
||||
int main (void) {
|
||||
sigjmp_buf env;
|
||||
sigsetjmp (env, 0);
|
||||
return 0;
|
||||
}''', name: 'sigsetjmp'),
|
||||
)
|
||||
|
||||
# Check for __uint128_t (gcc) by checking for 128-bit division
|
||||
uint128_t_src = '''int main() {
|
||||
static __uint128_t v1 = 100;
|
||||
@@ -400,16 +394,6 @@ pangocairo_dep = dependency('pangocairo', version: pango_req,
|
||||
pixbuf_dep = dependency('gdk-pixbuf-2.0', version: gdk_pixbuf_req,
|
||||
fallback : ['gdk-pixbuf', 'gdkpixbuf_dep'],
|
||||
default_options: ['png=enabled', 'jpeg=enabled', 'builtin_loaders=png,jpeg', 'man=false'])
|
||||
png_dep = dependency('libpng',
|
||||
fallback: ['libpng', 'libpng_dep'],
|
||||
required: true)
|
||||
tiff_dep = dependency('libtiff-4',
|
||||
fallback: ['libtiff', 'libtiff4_dep'],
|
||||
required: true)
|
||||
jpeg_dep = dependency('libjpeg',
|
||||
fallback: ['libjpeg-turbo', 'jpeg_dep'],
|
||||
required: true)
|
||||
|
||||
epoxy_dep = dependency('epoxy', version: epoxy_req,
|
||||
fallback: ['libepoxy', 'libepoxy_dep'])
|
||||
harfbuzz_dep = dependency('harfbuzz', version: '>= 2.1.0', required: false,
|
||||
@@ -499,6 +483,7 @@ if wayland_enabled
|
||||
|
||||
wayland_pkgs = [
|
||||
'wayland-client @0@'.format(wayland_req),
|
||||
'wayland-protocols @0@'.format(wayland_proto_req),
|
||||
'xkbcommon @0@'.format(xkbcommon_req),
|
||||
'wayland-egl',
|
||||
]
|
||||
@@ -762,7 +747,8 @@ if get_option('build-examples')
|
||||
endif
|
||||
|
||||
# config.h
|
||||
configure_file(output: 'config.h',
|
||||
configure_file(input: 'config.h.meson',
|
||||
output: 'config.h',
|
||||
configuration: cdata)
|
||||
|
||||
# Requires
|
||||
|
||||
3458
po-properties/de.po
3458
po-properties/de.po
File diff suppressed because it is too large
Load Diff
3519
po-properties/fr.po
3519
po-properties/fr.po
File diff suppressed because it is too large
Load Diff
1960
po-properties/hu.po
1960
po-properties/hu.po
File diff suppressed because it is too large
Load Diff
@@ -21,9 +21,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gtk-properties master\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
|
||||
"POT-Creation-Date: 2021-09-15 15:29+0000\n"
|
||||
"PO-Revision-Date: 2021-09-15 14:39-0400\n"
|
||||
"Last-Translator: Boyuan Yang <073plan@gmail.com>\n"
|
||||
"POT-Creation-Date: 2021-09-03 14:49+0000\n"
|
||||
"PO-Revision-Date: 2021-09-04 13:36-0400\n"
|
||||
"Last-Translator: Dingzhong Chen <wsxy162@gmail.com>\n"
|
||||
"Language-Team: Chinese - China <i18n-zh@googlegroups.com>\n"
|
||||
"Language: zh_CN\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -219,11 +219,11 @@ msgstr "表面"
|
||||
msgid "The GDK surface bound to the context"
|
||||
msgstr "绑定到上下文的 GDK 表面"
|
||||
|
||||
#: gdk/gdkglcontext.c:449
|
||||
#: gdk/gdkglcontext.c:430
|
||||
msgid "Shared context"
|
||||
msgstr "共享上下文"
|
||||
|
||||
#: gdk/gdkglcontext.c:450
|
||||
#: gdk/gdkglcontext.c:431
|
||||
msgid "The GL context this context shares data with"
|
||||
msgstr "与这个上下文分享数据的 GL 上下文"
|
||||
|
||||
@@ -761,7 +761,7 @@ msgstr "使用首栏"
|
||||
msgid "Use Header Bar for actions."
|
||||
msgstr "使用首栏提供操作。"
|
||||
|
||||
#: gtk/gtkassistant.c:621 gtk/gtknotebook.c:1212 gtk/gtkstack.c:901
|
||||
#: gtk/gtkassistant.c:621 gtk/gtknotebook.c:1212 gtk/gtkstack.c:900
|
||||
msgid "Pages"
|
||||
msgstr "页面"
|
||||
|
||||
@@ -946,7 +946,7 @@ msgstr "年"
|
||||
|
||||
#: gtk/gtkcalendar.c:377
|
||||
msgid "The selected year"
|
||||
msgstr "选中的年份"
|
||||
msgstr "选中的年"
|
||||
|
||||
#: gtk/gtkcalendar.c:391
|
||||
msgid "Month"
|
||||
@@ -961,8 +961,10 @@ msgid "Day"
|
||||
msgstr "日"
|
||||
|
||||
#: gtk/gtkcalendar.c:405
|
||||
#, fuzzy
|
||||
#| msgid "The selected month (as a number between 0 and 11)"
|
||||
msgid "The selected day (as a number between 1 and 31)"
|
||||
msgstr "选中的日(0 到 31 之间的数字)"
|
||||
msgstr "选中的月份(0 到 11 之间的数字)"
|
||||
|
||||
#: gtk/gtkcalendar.c:417
|
||||
msgid "Show Heading"
|
||||
@@ -1471,11 +1473,11 @@ msgid "Foreground color as a GdkRGBA"
|
||||
msgstr "以 GdkRGBA 方式表示的前景色"
|
||||
|
||||
#: gtk/gtkcellrenderertext.c:319 gtk/gtkeditable.c:433 gtk/gtktexttag.c:316
|
||||
#: gtk/gtktextview.c:895
|
||||
#: gtk/gtktextview.c:891
|
||||
msgid "Editable"
|
||||
msgstr "可编辑"
|
||||
|
||||
#: gtk/gtkcellrenderertext.c:320 gtk/gtktexttag.c:317 gtk/gtktextview.c:896
|
||||
#: gtk/gtkcellrenderertext.c:320 gtk/gtktexttag.c:317 gtk/gtktextview.c:892
|
||||
msgid "Whether the text can be modified by the user"
|
||||
msgstr "用户是否可以修改文字"
|
||||
|
||||
@@ -2116,12 +2118,16 @@ msgid "Entry Text Column"
|
||||
msgstr "输入文本列"
|
||||
|
||||
#: gtk/gtkcombobox.c:732
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The column in the combo box’s model to associate with strings from the "
|
||||
#| "entry if the combo was created with #GtkComboBox:has-entry = %TRUE"
|
||||
msgid ""
|
||||
"The column in the combo box’s model to associate with strings from the entry "
|
||||
"if the combo was created with GtkComboBox:has-entry = %TRUE"
|
||||
msgstr ""
|
||||
"若组合框是通过 GtkComboBox:has-entry = %TRUE 创建的,组合框模型中的这个列将关"
|
||||
"联到输入区域中的字符串"
|
||||
"若组合框是通过 #GtkComboBox:has-entry = %TRUE 创建的,组合框模型中的这个列将"
|
||||
"关联到输入区域中的字符串"
|
||||
|
||||
#: gtk/gtkcombobox.c:747
|
||||
msgid "ID Column"
|
||||
@@ -2581,7 +2587,7 @@ msgstr "截断多行"
|
||||
msgid "Whether to truncate multiline pastes to one line."
|
||||
msgstr "是否将多行粘贴截断到第一行。"
|
||||
|
||||
#: gtk/gtkentry.c:586 gtk/gtktext.c:835 gtk/gtktextview.c:1064
|
||||
#: gtk/gtkentry.c:586 gtk/gtktext.c:835 gtk/gtktextview.c:1060
|
||||
msgid "Overwrite mode"
|
||||
msgstr "覆盖模式"
|
||||
|
||||
@@ -2744,11 +2750,11 @@ msgstr "主图标工具提示标记"
|
||||
msgid "Secondary icon tooltip markup"
|
||||
msgstr "次图标工具提示标记"
|
||||
|
||||
#: gtk/gtkentry.c:901 gtk/gtktext.c:878 gtk/gtktextview.c:1095
|
||||
#: gtk/gtkentry.c:901 gtk/gtktext.c:878 gtk/gtktextview.c:1091
|
||||
msgid "IM module"
|
||||
msgstr "输入法模块"
|
||||
|
||||
#: gtk/gtkentry.c:902 gtk/gtktext.c:879 gtk/gtktextview.c:1096
|
||||
#: gtk/gtkentry.c:902 gtk/gtktext.c:879 gtk/gtktextview.c:1092
|
||||
msgid "Which IM module should be used"
|
||||
msgstr "使用哪个输入法模块"
|
||||
|
||||
@@ -2761,22 +2767,22 @@ msgid "The auxiliary completion object"
|
||||
msgstr "辅助补全对象"
|
||||
|
||||
#: gtk/gtkentry.c:932 gtk/gtkimcontext.c:336 gtk/gtktext.c:897
|
||||
#: gtk/gtktextview.c:1111
|
||||
#: gtk/gtktextview.c:1107
|
||||
msgid "Purpose"
|
||||
msgstr "用途"
|
||||
|
||||
#: gtk/gtkentry.c:933 gtk/gtkimcontext.c:337 gtk/gtktext.c:898
|
||||
#: gtk/gtktextview.c:1112
|
||||
#: gtk/gtktextview.c:1108
|
||||
msgid "Purpose of the text field"
|
||||
msgstr "文本区域的用途"
|
||||
|
||||
#: gtk/gtkentry.c:947 gtk/gtkimcontext.c:350 gtk/gtktext.c:911
|
||||
#: gtk/gtktextview.c:1127
|
||||
#: gtk/gtktextview.c:1123
|
||||
msgid "hints"
|
||||
msgstr "微调"
|
||||
|
||||
#: gtk/gtkentry.c:948 gtk/gtkimcontext.c:351 gtk/gtktext.c:912
|
||||
#: gtk/gtktextview.c:1128
|
||||
#: gtk/gtktextview.c:1124
|
||||
msgid "Hints for the text field behaviour"
|
||||
msgstr "用于微调文本区域行为"
|
||||
|
||||
@@ -2785,7 +2791,7 @@ msgid "A list of style attributes to apply to the text of the entry"
|
||||
msgstr "应用于输入框文本的样式属性列表"
|
||||
|
||||
#: gtk/gtkentry.c:977 gtk/gtktext.c:941 gtk/gtktexttag.c:735
|
||||
#: gtk/gtktextview.c:1025
|
||||
#: gtk/gtktextview.c:1021
|
||||
msgid "Tabs"
|
||||
msgstr "制表位"
|
||||
|
||||
@@ -2802,7 +2808,7 @@ msgid "Whether to show an icon for Emoji"
|
||||
msgstr "是否显示表情符号的图标"
|
||||
|
||||
#: gtk/gtkentry.c:1002 gtk/gtklabel.c:2455 gtk/gtkpasswordentry.c:504
|
||||
#: gtk/gtktext.c:990 gtk/gtktextview.c:1158
|
||||
#: gtk/gtktext.c:990 gtk/gtktextview.c:1154
|
||||
msgid "Extra menu"
|
||||
msgstr "额外菜单"
|
||||
|
||||
@@ -3645,7 +3651,7 @@ msgstr "标签的文本"
|
||||
msgid "A list of style attributes to apply to the text of the label"
|
||||
msgstr "要应用于标签文本的样式属性的列表"
|
||||
|
||||
#: gtk/gtklabel.c:2250 gtk/gtktexttag.c:475 gtk/gtktextview.c:922
|
||||
#: gtk/gtklabel.c:2250 gtk/gtktexttag.c:475 gtk/gtktextview.c:918
|
||||
msgid "Justification"
|
||||
msgstr "两端对齐"
|
||||
|
||||
@@ -3728,7 +3734,7 @@ msgstr "行数"
|
||||
msgid "The desired number of lines, when ellipsizing a wrapping label"
|
||||
msgstr "标签换行超过指定的行数时省略显示"
|
||||
|
||||
#: gtk/gtklabel.c:2456 gtk/gtktext.c:991 gtk/gtktextview.c:1159
|
||||
#: gtk/gtklabel.c:2456 gtk/gtktext.c:991 gtk/gtktextview.c:1155
|
||||
msgid "Menu model to append to the context menu"
|
||||
msgstr "要附加到右键菜单上的菜单模型"
|
||||
|
||||
@@ -4040,7 +4046,7 @@ msgstr "弹出菜单的模型。"
|
||||
|
||||
#: gtk/gtkmenubutton.c:428
|
||||
msgid "The direction the arrow should point."
|
||||
msgstr "箭头应指向的方向。"
|
||||
msgstr "箭头所指方向。"
|
||||
|
||||
#: gtk/gtkmenubutton.c:440 gtk/gtkmodelbutton.c:1243
|
||||
msgid "Popover"
|
||||
@@ -4051,13 +4057,15 @@ msgid "The popover"
|
||||
msgstr "弹出框"
|
||||
|
||||
#: gtk/gtkmenubutton.c:466
|
||||
#, fuzzy
|
||||
#| msgid "Always enable arrows"
|
||||
msgid "Always Show Arrow"
|
||||
msgstr "总是显示箭头"
|
||||
msgstr "总是启用方向键"
|
||||
|
||||
#: gtk/gtkmenubutton.c:467
|
||||
msgid ""
|
||||
"Whether to show a dropdown arrow even when using an icon or a custom child"
|
||||
msgstr "是否在使用图标或自定义子部件的同时显示一个下拉箭头"
|
||||
msgstr ""
|
||||
|
||||
#: gtk/gtkmenubutton.c:479
|
||||
msgid "The label for the button"
|
||||
@@ -4068,12 +4076,16 @@ msgid "Has frame"
|
||||
msgstr "有边框"
|
||||
|
||||
#: gtk/gtkmenubutton.c:518
|
||||
#, fuzzy
|
||||
#| msgid "Primary GIcon"
|
||||
msgid "Primary"
|
||||
msgstr "主菜单"
|
||||
msgstr "主 GIcon"
|
||||
|
||||
#: gtk/gtkmenubutton.c:519
|
||||
#, fuzzy
|
||||
#| msgid "Whether the button has a frame"
|
||||
msgid "Whether the menubutton acts as a primary menu"
|
||||
msgstr "菜单按钮是否充当主菜单"
|
||||
msgstr "按钮是否有边框"
|
||||
|
||||
#: gtk/gtkmessagedialog.c:373
|
||||
msgid "Message Buttons"
|
||||
@@ -5147,19 +5159,19 @@ msgstr "用来存储和读取列表的文件的完整路径"
|
||||
msgid "The size of the recently used resources list"
|
||||
msgstr "最近使用资源列表的大小"
|
||||
|
||||
#: gtk/gtkrevealer.c:319 gtk/gtkstack.c:871
|
||||
#: gtk/gtkrevealer.c:319 gtk/gtkstack.c:870
|
||||
msgid "Transition type"
|
||||
msgstr "过渡类型"
|
||||
|
||||
#: gtk/gtkrevealer.c:320 gtk/gtkstack.c:871
|
||||
#: gtk/gtkrevealer.c:320 gtk/gtkstack.c:870
|
||||
msgid "The type of animation used to transition"
|
||||
msgstr "要使用的过渡动画类型"
|
||||
|
||||
#: gtk/gtkrevealer.c:332 gtk/gtkstack.c:861
|
||||
#: gtk/gtkrevealer.c:332 gtk/gtkstack.c:860
|
||||
msgid "Transition duration"
|
||||
msgstr "过渡时长"
|
||||
|
||||
#: gtk/gtkrevealer.c:333 gtk/gtkstack.c:861
|
||||
#: gtk/gtkrevealer.c:333 gtk/gtkstack.c:860
|
||||
msgid "The animation duration, in milliseconds"
|
||||
msgstr "动画时长,以毫秒计算"
|
||||
|
||||
@@ -5517,12 +5529,16 @@ msgid "Resolution for Xft, in 1024 * dots/inch. -1 to use default value"
|
||||
msgstr "Xft 的解析度,以 1024×每英寸点数为单位。-1 代表使用默认值"
|
||||
|
||||
#: gtk/gtksettings.c:589
|
||||
#, fuzzy
|
||||
#| msgid "Font Features"
|
||||
msgid "Hint Font Metrics"
|
||||
msgstr "微调字体规格"
|
||||
msgstr "字体特性"
|
||||
|
||||
#: gtk/gtksettings.c:590
|
||||
#, fuzzy
|
||||
#| msgid "Whether the items should be displayed with a number"
|
||||
msgid "Whether hinting should be applied to font metrics"
|
||||
msgstr "是否要应用微调到字体规格(metrics)上"
|
||||
msgstr "是否项目要附加一个数字一起显示"
|
||||
|
||||
#: gtk/gtksettings.c:605
|
||||
msgid "Cursor theme name"
|
||||
@@ -5756,7 +5772,7 @@ msgstr "允许首项粘贴"
|
||||
msgid ""
|
||||
"Whether a middle click on a mouse should paste the “PRIMARY” clipboard "
|
||||
"content at the cursor location."
|
||||
msgstr "点击鼠标中键能否将“主要”剪贴板的内容粘贴至光标所在位置。"
|
||||
msgstr "点击鼠标中键能否将“首项”剪贴板的内容粘贴至光标所在位置。"
|
||||
|
||||
#: gtk/gtksettings.c:1113
|
||||
msgid "Recent Files Enabled"
|
||||
@@ -6096,57 +6112,57 @@ msgid ""
|
||||
"used for the mnemonic accelerator key"
|
||||
msgstr "如果设置的话,标题中的下划线表示下一个字符将被用作助记快捷键"
|
||||
|
||||
#: gtk/gtkstack.c:821
|
||||
#: gtk/gtkstack.c:820
|
||||
msgid "Horizontally homogeneous"
|
||||
msgstr "水平统一"
|
||||
|
||||
#: gtk/gtkstack.c:821
|
||||
#: gtk/gtkstack.c:820
|
||||
msgid "Horizontally homogeneous sizing"
|
||||
msgstr "水平统一大小"
|
||||
|
||||
#: gtk/gtkstack.c:831
|
||||
#: gtk/gtkstack.c:830
|
||||
msgid "Vertically homogeneous"
|
||||
msgstr "垂直统一"
|
||||
|
||||
#: gtk/gtkstack.c:831
|
||||
#: gtk/gtkstack.c:830
|
||||
msgid "Vertically homogeneous sizing"
|
||||
msgstr "垂直统一大小"
|
||||
|
||||
#: gtk/gtkstack.c:841
|
||||
#: gtk/gtkstack.c:840
|
||||
msgid "Visible child"
|
||||
msgstr "可见的子部件"
|
||||
|
||||
#: gtk/gtkstack.c:841
|
||||
#: gtk/gtkstack.c:840
|
||||
msgid "The widget currently visible in the stack"
|
||||
msgstr "堆放容器中当前可见的部件"
|
||||
|
||||
#: gtk/gtkstack.c:851
|
||||
#: gtk/gtkstack.c:850
|
||||
msgid "Name of visible child"
|
||||
msgstr "可见子部件的名称"
|
||||
|
||||
#: gtk/gtkstack.c:851
|
||||
#: gtk/gtkstack.c:850
|
||||
msgid "The name of the widget currently visible in the stack"
|
||||
msgstr "堆放容器中当前可见部件的名称"
|
||||
|
||||
#: gtk/gtkstack.c:881
|
||||
#: gtk/gtkstack.c:880
|
||||
msgid "Transition running"
|
||||
msgstr "过渡动画运行中"
|
||||
|
||||
#: gtk/gtkstack.c:881
|
||||
#: gtk/gtkstack.c:880
|
||||
msgid "Whether or not the transition is currently running"
|
||||
msgstr "过渡动画是否正在运行"
|
||||
|
||||
#: gtk/gtkstack.c:891
|
||||
#: gtk/gtkstack.c:890
|
||||
msgid "Interpolate size"
|
||||
msgstr "尺寸插值"
|
||||
|
||||
#: gtk/gtkstack.c:891
|
||||
#: gtk/gtkstack.c:890
|
||||
msgid ""
|
||||
"Whether or not the size should smoothly change when changing between "
|
||||
"differently sized children"
|
||||
msgstr "子部件在不同尺寸之间改变时,该尺寸是否要平滑地改变"
|
||||
|
||||
#: gtk/gtkstack.c:901
|
||||
#: gtk/gtkstack.c:900
|
||||
msgid "A selection model with the stacks pages"
|
||||
msgstr "堆放页面的选择模型"
|
||||
|
||||
@@ -6368,7 +6384,7 @@ msgstr ""
|
||||
"以相对于默认字体大小的缩放比例表示的字体大小。这适用于主题更改等情况,所以推"
|
||||
"荐使用。Pango 预先定义了一些缩放比例,如 PANGO_SCALE_X_LARGE"
|
||||
|
||||
#: gtk/gtktexttag.c:476 gtk/gtktextview.c:923
|
||||
#: gtk/gtktexttag.c:476 gtk/gtktextview.c:919
|
||||
msgid "Left, right, or center justification"
|
||||
msgstr "左对齐、右对齐或是居中对齐"
|
||||
|
||||
@@ -6384,7 +6400,7 @@ msgstr ""
|
||||
msgid "Left margin"
|
||||
msgstr "左边距"
|
||||
|
||||
#: gtk/gtktexttag.c:509 gtk/gtktextview.c:943
|
||||
#: gtk/gtktexttag.c:509 gtk/gtktextview.c:939
|
||||
msgid "Width of the left margin in pixels"
|
||||
msgstr "左边距的宽度,以像素计算"
|
||||
|
||||
@@ -6392,15 +6408,15 @@ msgstr "左边距的宽度,以像素计算"
|
||||
msgid "Right margin"
|
||||
msgstr "右边距"
|
||||
|
||||
#: gtk/gtktexttag.c:524 gtk/gtktextview.c:962
|
||||
#: gtk/gtktexttag.c:524 gtk/gtktextview.c:958
|
||||
msgid "Width of the right margin in pixels"
|
||||
msgstr "右边距的宽度,以像素计算"
|
||||
|
||||
#: gtk/gtktexttag.c:538 gtk/gtktextview.c:1012
|
||||
#: gtk/gtktexttag.c:538 gtk/gtktextview.c:1008
|
||||
msgid "Indent"
|
||||
msgstr "缩进"
|
||||
|
||||
#: gtk/gtktexttag.c:539 gtk/gtktextview.c:1013
|
||||
#: gtk/gtktexttag.c:539 gtk/gtktextview.c:1009
|
||||
msgid "Amount to indent the paragraph, in pixels"
|
||||
msgstr "段落的缩进量,以像素计算"
|
||||
|
||||
@@ -6414,7 +6430,7 @@ msgstr "文字与下方(如果间距为负则上方)水平基线的距离,
|
||||
msgid "Pixels above lines"
|
||||
msgstr "行上像素数"
|
||||
|
||||
#: gtk/gtktexttag.c:571 gtk/gtktextview.c:857
|
||||
#: gtk/gtktexttag.c:571 gtk/gtktextview.c:853
|
||||
msgid "Pixels of blank space above paragraphs"
|
||||
msgstr "段落顶部的间距的像素数目"
|
||||
|
||||
@@ -6422,7 +6438,7 @@ msgstr "段落顶部的间距的像素数目"
|
||||
msgid "Pixels below lines"
|
||||
msgstr "行下像素数"
|
||||
|
||||
#: gtk/gtktexttag.c:586 gtk/gtktextview.c:870
|
||||
#: gtk/gtktexttag.c:586 gtk/gtktextview.c:866
|
||||
msgid "Pixels of blank space below paragraphs"
|
||||
msgstr "段落底部的间距的像素数目"
|
||||
|
||||
@@ -6430,17 +6446,21 @@ msgstr "段落底部的间距的像素数目"
|
||||
msgid "Pixels inside wrap"
|
||||
msgstr "换行内像素数"
|
||||
|
||||
#: gtk/gtktexttag.c:601 gtk/gtktextview.c:883
|
||||
#: gtk/gtktexttag.c:601 gtk/gtktextview.c:879
|
||||
msgid "Pixels of blank space between wrapped lines in a paragraph"
|
||||
msgstr "段落内部换行间距的像素数目"
|
||||
|
||||
#: gtk/gtktexttag.c:617
|
||||
#, fuzzy
|
||||
#| msgid "List Factory"
|
||||
msgid "Line height factor"
|
||||
msgstr "行高度系数"
|
||||
msgstr "列表工厂"
|
||||
|
||||
#: gtk/gtktexttag.c:618
|
||||
#, fuzzy
|
||||
#| msgid "The action to take on titlebar right-click"
|
||||
msgid "The factor to apply to line height"
|
||||
msgstr "要应用于行高度的系数"
|
||||
msgstr "右击标题栏时触发的操作"
|
||||
|
||||
#: gtk/gtktexttag.c:663
|
||||
msgid "Underline RGBA"
|
||||
@@ -6474,12 +6494,12 @@ msgstr "删除线 RGBA"
|
||||
msgid "Color of strikethrough for this text"
|
||||
msgstr "文字删除线颜色"
|
||||
|
||||
#: gtk/gtktexttag.c:722 gtk/gtktextview.c:909
|
||||
#: gtk/gtktexttag.c:722 gtk/gtktextview.c:905
|
||||
msgid ""
|
||||
"Whether to wrap lines never, at word boundaries, or at character boundaries"
|
||||
msgstr "选择永远不换行、词边界换行或是字符边界换行"
|
||||
|
||||
#: gtk/gtktexttag.c:736 gtk/gtktextview.c:1026
|
||||
#: gtk/gtktexttag.c:736 gtk/gtktextview.c:1022
|
||||
msgid "Custom tabs for this text"
|
||||
msgstr "自定义文本的制表位"
|
||||
|
||||
@@ -6552,28 +6572,40 @@ msgid "Whether to insert hyphens at breaks."
|
||||
msgstr "是否在断行处插入连字符。"
|
||||
|
||||
#: gtk/gtktexttag.c:875
|
||||
#, fuzzy
|
||||
#| msgid "transform"
|
||||
msgid "Text Transform"
|
||||
msgstr "文本变换"
|
||||
msgstr "转换"
|
||||
|
||||
#: gtk/gtktexttag.c:876
|
||||
#, fuzzy
|
||||
#| msgid "Whether the stream is playing"
|
||||
msgid "Whether to transform text for display."
|
||||
msgstr "是否变换用于显示的文本。"
|
||||
msgstr "媒体流是否正在播放"
|
||||
|
||||
#: gtk/gtktexttag.c:893
|
||||
#, fuzzy
|
||||
#| msgid "Word Wrap"
|
||||
msgid "Word"
|
||||
msgstr "单词"
|
||||
msgstr "词回绕"
|
||||
|
||||
#: gtk/gtktexttag.c:894
|
||||
#, fuzzy
|
||||
#| msgid "Whether this text is hidden."
|
||||
msgid "Whether this is a word."
|
||||
msgstr "此文本是否为单词。"
|
||||
msgstr "此文本是否隐藏"
|
||||
|
||||
#: gtk/gtktexttag.c:910
|
||||
#, fuzzy
|
||||
#| msgid "Centered"
|
||||
msgid "Sentence"
|
||||
msgstr "句子"
|
||||
msgstr "居中"
|
||||
|
||||
#: gtk/gtktexttag.c:911
|
||||
#, fuzzy
|
||||
#| msgid "Whether this row can be selected"
|
||||
msgid "Whether this is a sentence."
|
||||
msgstr "此文本是否为句子。"
|
||||
msgstr "此列是否可选中"
|
||||
|
||||
#: gtk/gtktexttag.c:927
|
||||
msgid "Margin Accumulates"
|
||||
@@ -6636,12 +6668,16 @@ msgid "Whether this tag affects the number of pixels between wrapped lines"
|
||||
msgstr "此标记是否影响换行间距"
|
||||
|
||||
#: gtk/gtktexttag.c:1013
|
||||
#, fuzzy
|
||||
#| msgid "Font weight set"
|
||||
msgid "Line height set"
|
||||
msgstr "行高度设置"
|
||||
msgstr "字体粗细设置"
|
||||
|
||||
#: gtk/gtktexttag.c:1014
|
||||
#, fuzzy
|
||||
#| msgid "Whether this tag affects the right margin"
|
||||
msgid "Whether this tag affects the height of lines"
|
||||
msgstr "此标记是否影响行的高度"
|
||||
msgstr "此标记是否影响右边距"
|
||||
|
||||
#: gtk/gtktexttag.c:1021
|
||||
msgid "Right margin set"
|
||||
@@ -6764,102 +6800,114 @@ msgid "Whether this tag affects insertion of hyphens"
|
||||
msgstr "此标记是否影响连字符的插入"
|
||||
|
||||
#: gtk/gtktexttag.c:1095
|
||||
#, fuzzy
|
||||
#| msgid "transform"
|
||||
msgid "Text transform set"
|
||||
msgstr "文本变换设置"
|
||||
msgstr "转换"
|
||||
|
||||
#: gtk/gtktexttag.c:1096
|
||||
#, fuzzy
|
||||
#| msgid "Whether this tag affects indentation"
|
||||
msgid "Whether this tag affects text transformation"
|
||||
msgstr "此标记是否影响文本变换"
|
||||
msgstr "此标记是否影响缩进"
|
||||
|
||||
#: gtk/gtktexttag.c:1099
|
||||
#, fuzzy
|
||||
#| msgid "Wrap mode set"
|
||||
msgid "Word set"
|
||||
msgstr "单词设置"
|
||||
msgstr "换行模式设置"
|
||||
|
||||
#: gtk/gtktexttag.c:1100
|
||||
#, fuzzy
|
||||
#| msgid "Whether this tag affects line wrap mode"
|
||||
msgid "Whether this tag represents a single word"
|
||||
msgstr "此标记是否代表单个字词"
|
||||
msgstr "此标记是否影响换行模式"
|
||||
|
||||
#: gtk/gtktexttag.c:1103
|
||||
#, fuzzy
|
||||
#| msgid "Underline set"
|
||||
msgid "Sentence set"
|
||||
msgstr "句子设置"
|
||||
msgstr "下划线设置"
|
||||
|
||||
#: gtk/gtktexttag.c:1104
|
||||
#, fuzzy
|
||||
#| msgid "Whether the row represents a network location"
|
||||
msgid "Whether this tag represents a single sentence"
|
||||
msgstr "此标记是否代表单个句子"
|
||||
msgstr "此行是否代表网络位置"
|
||||
|
||||
#: gtk/gtktextview.c:856
|
||||
#: gtk/gtktextview.c:852
|
||||
msgid "Pixels Above Lines"
|
||||
msgstr "行上像素数"
|
||||
|
||||
#: gtk/gtktextview.c:869
|
||||
#: gtk/gtktextview.c:865
|
||||
msgid "Pixels Below Lines"
|
||||
msgstr "行下像素数"
|
||||
|
||||
#: gtk/gtktextview.c:882
|
||||
#: gtk/gtktextview.c:878
|
||||
msgid "Pixels Inside Wrap"
|
||||
msgstr "换行内像素数"
|
||||
|
||||
#: gtk/gtktextview.c:908
|
||||
#: gtk/gtktextview.c:904
|
||||
msgid "Wrap Mode"
|
||||
msgstr "换行模式"
|
||||
|
||||
#: gtk/gtktextview.c:942
|
||||
#: gtk/gtktextview.c:938
|
||||
msgid "Left Margin"
|
||||
msgstr "左边距"
|
||||
|
||||
#: gtk/gtktextview.c:961
|
||||
#: gtk/gtktextview.c:957
|
||||
msgid "Right Margin"
|
||||
msgstr "右边距"
|
||||
|
||||
#: gtk/gtktextview.c:980
|
||||
#: gtk/gtktextview.c:976
|
||||
msgid "Top Margin"
|
||||
msgstr "顶边距"
|
||||
|
||||
#: gtk/gtktextview.c:981
|
||||
#: gtk/gtktextview.c:977
|
||||
msgid "Height of the top margin in pixels"
|
||||
msgstr "顶边距的高度,以像素计算"
|
||||
|
||||
#: gtk/gtktextview.c:999
|
||||
#: gtk/gtktextview.c:995
|
||||
msgid "Bottom Margin"
|
||||
msgstr "底边距"
|
||||
|
||||
#: gtk/gtktextview.c:1000
|
||||
#: gtk/gtktextview.c:996
|
||||
msgid "Height of the bottom margin in pixels"
|
||||
msgstr "底边距的高度,以像素计算"
|
||||
|
||||
#: gtk/gtktextview.c:1038
|
||||
#: gtk/gtktextview.c:1034
|
||||
msgid "Cursor Visible"
|
||||
msgstr "光标可见"
|
||||
|
||||
#: gtk/gtktextview.c:1039
|
||||
#: gtk/gtktextview.c:1035
|
||||
msgid "If the insertion cursor is shown"
|
||||
msgstr "是否显示插入光标"
|
||||
|
||||
#: gtk/gtktextview.c:1051
|
||||
#: gtk/gtktextview.c:1047
|
||||
msgid "Buffer"
|
||||
msgstr "缓冲区"
|
||||
|
||||
#: gtk/gtktextview.c:1052
|
||||
#: gtk/gtktextview.c:1048
|
||||
msgid "The buffer which is displayed"
|
||||
msgstr "显示的缓冲区"
|
||||
|
||||
#: gtk/gtktextview.c:1065
|
||||
#: gtk/gtktextview.c:1061
|
||||
msgid "Whether entered text overwrites existing contents"
|
||||
msgstr "输入的文字是否覆盖已有内容"
|
||||
|
||||
#: gtk/gtktextview.c:1077
|
||||
#: gtk/gtktextview.c:1073
|
||||
msgid "Accepts tab"
|
||||
msgstr "接受制表符"
|
||||
|
||||
#: gtk/gtktextview.c:1078
|
||||
#: gtk/gtktextview.c:1074
|
||||
msgid "Whether Tab will result in a tab character being entered"
|
||||
msgstr "按下跳格键是否会输入制表符"
|
||||
|
||||
#: gtk/gtktextview.c:1145
|
||||
#: gtk/gtktextview.c:1141
|
||||
msgid "Monospace"
|
||||
msgstr "等宽"
|
||||
|
||||
#: gtk/gtktextview.c:1146
|
||||
#: gtk/gtktextview.c:1142
|
||||
msgid "Whether to use a monospace font"
|
||||
msgstr "是否使用等宽字体"
|
||||
|
||||
@@ -6892,13 +6940,15 @@ msgid "The list row to track for expander state"
|
||||
msgstr "用于跟踪扩展器状态的列表行"
|
||||
|
||||
#: gtk/gtktreeexpander.c:570
|
||||
#, fuzzy
|
||||
#| msgid "Indent Expanders"
|
||||
msgid "Indent without expander"
|
||||
msgstr "无扩展器缩进"
|
||||
msgstr "缩进扩展器"
|
||||
|
||||
#: gtk/gtktreeexpander.c:571
|
||||
msgid ""
|
||||
"If the TreeExpander should indent the child if no expander-icon is shown"
|
||||
msgstr "树形扩展器(TreeExpander)是否要在未显示扩展器图标时对子部件进行缩进"
|
||||
msgstr ""
|
||||
|
||||
#: gtk/gtktreelistmodel.c:690
|
||||
msgid "autoexpand"
|
||||
@@ -6962,7 +7012,7 @@ msgstr "子模型"
|
||||
|
||||
#: gtk/gtktreemodelfilter.c:532
|
||||
msgid "The model for the filtermodel to filter"
|
||||
msgstr "filtermodel 的过滤模型"
|
||||
msgstr "filtermodel 的过滤模型。"
|
||||
|
||||
#: gtk/gtktreemodelfilter.c:539
|
||||
msgid "The virtual root"
|
||||
|
||||
94
po/sv.po
94
po/sv.po
@@ -10,8 +10,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gtk\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
|
||||
"POT-Creation-Date: 2021-09-05 14:13+0000\n"
|
||||
"PO-Revision-Date: 2021-09-08 22:23+0200\n"
|
||||
"POT-Creation-Date: 2021-09-03 00:57+0000\n"
|
||||
"PO-Revision-Date: 2021-09-04 13:03+0200\n"
|
||||
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
|
||||
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
|
||||
"Language: sv\n"
|
||||
@@ -459,54 +459,42 @@ msgstr "Inget kompatibelt överföringsformat hittades"
|
||||
msgid "Failed to decode contents with mime-type of '%s'"
|
||||
msgstr "Misslyckades med att avkoda innehåll med mime-typen ”%s”"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:191
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:190
|
||||
#: gdk/win32/gdkglcontext-win32-egl.c:399
|
||||
#: gdk/win32/gdkglcontext-win32-wgl.c:628 gdk/x11/gdkglcontext-egl.c:600
|
||||
#: gdk/x11/gdkglcontext-glx.c:613
|
||||
msgid "Unable to create a GL context"
|
||||
msgstr "Kan inte skapa en GL-kontext"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:484
|
||||
msgid "libEGL not available in this sandbox"
|
||||
msgstr "libEGL är inte tillgängligt i denna sandlåda"
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:484 gdk/x11/gdkglcontext-egl.c:688
|
||||
msgid "Failed to create EGL display"
|
||||
msgstr "Misslyckades med att skapa EGL-display"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:485
|
||||
msgid "libEGL not available"
|
||||
msgstr "libEGL inte tillgängligt"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:498
|
||||
msgid "Sandbox does not provide an OpenGL implementation"
|
||||
msgstr "Sandlådan tillhandahåller ingen OpenGL-implementation"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:499
|
||||
msgid "No OpenGL implementation available"
|
||||
msgstr "Ingen OpenGL-implementation tillgänglig"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:508 gdk/x11/gdkglcontext-egl.c:697
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:493 gdk/x11/gdkglcontext-egl.c:697
|
||||
msgid "Could not initialize EGL display"
|
||||
msgstr "Kunde inte initiera EGL-display"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:519 gdk/x11/gdkglcontext-egl.c:707
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:504 gdk/x11/gdkglcontext-egl.c:707
|
||||
#, c-format
|
||||
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
|
||||
msgstr "EGL-version %d.%d är för gammal. GTK kräver %d.%d"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:530
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:515
|
||||
#: gdk/win32/gdkglcontext-win32-egl.c:273
|
||||
#: gdk/win32/gdkglcontext-win32-wgl.c:286
|
||||
#: gdk/win32/gdkglcontext-win32-wgl.c:304
|
||||
msgid "No GL implementation is available"
|
||||
msgstr "Ingen GL-implementation tillgänglig"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:540
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:525
|
||||
msgid "Core GL is not available on EGL implementation"
|
||||
msgstr "Kärn-GL är inte tillgängligt på EGL-implementation"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:549 gdk/x11/gdkglcontext-egl.c:718
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:534 gdk/x11/gdkglcontext-egl.c:718
|
||||
msgid "Surfaceless contexts are not supported on this EGL implementation"
|
||||
msgstr "Ytlösa kontexter stöds inte på denna EGL-implementation"
|
||||
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:561
|
||||
#: gdk/wayland/gdkglcontext-wayland.c:546
|
||||
#: gdk/win32/gdkglcontext-win32-egl.c:216
|
||||
#: gdk/win32/gdkglcontext-win32-egl.c:226
|
||||
#: gdk/win32/gdkglcontext-win32-wgl.c:594
|
||||
@@ -729,10 +717,6 @@ msgstr "Ingen perfekt EGL-konfiguration hittades"
|
||||
msgid "EGL is not supported"
|
||||
msgstr "EGL stöds inte"
|
||||
|
||||
#: gdk/x11/gdkglcontext-egl.c:688
|
||||
msgid "Failed to create EGL display"
|
||||
msgstr "Misslyckades med att skapa EGL-display"
|
||||
|
||||
#: gdk/x11/gdkglcontext-glx.c:770
|
||||
msgid "No GLX configurations available"
|
||||
msgstr "Inga GLX-konfigurationer tillgängliga"
|
||||
@@ -1010,7 +994,7 @@ msgstr ""
|
||||
#. * translated on keyboards used for your language, don't translate
|
||||
#. * this.
|
||||
#.
|
||||
#: gtk/gtkaccelgroup.c:837 gtk/gtkshortcutlabel.c:100
|
||||
#: gtk/gtkaccelgroup.c:826 gtk/gtkshortcutlabel.c:100
|
||||
#: gtk/gtkshortcutlabel.c:136
|
||||
msgctxt "keyboard label"
|
||||
msgid "Shift"
|
||||
@@ -1021,7 +1005,7 @@ msgstr "Skift"
|
||||
#. * translated on keyboards used for your language, don't translate
|
||||
#. * this.
|
||||
#.
|
||||
#: gtk/gtkaccelgroup.c:856 gtk/gtkshortcutlabel.c:103
|
||||
#: gtk/gtkaccelgroup.c:845 gtk/gtkshortcutlabel.c:103
|
||||
#: gtk/gtkshortcutlabel.c:138
|
||||
msgctxt "keyboard label"
|
||||
msgid "Ctrl"
|
||||
@@ -1032,7 +1016,7 @@ msgstr "Ctrl"
|
||||
#. * translated on keyboards used for your language, don't translate
|
||||
#. * this.
|
||||
#.
|
||||
#: gtk/gtkaccelgroup.c:875 gtk/gtkshortcutlabel.c:106
|
||||
#: gtk/gtkaccelgroup.c:864 gtk/gtkshortcutlabel.c:106
|
||||
#: gtk/gtkshortcutlabel.c:140
|
||||
msgctxt "keyboard label"
|
||||
msgid "Alt"
|
||||
@@ -1043,7 +1027,7 @@ msgstr "Alt"
|
||||
#. * translated on keyboards used for your language, don't translate
|
||||
#. * this.
|
||||
#.
|
||||
#: gtk/gtkaccelgroup.c:893 gtk/gtkshortcutlabel.c:112
|
||||
#: gtk/gtkaccelgroup.c:882 gtk/gtkshortcutlabel.c:112
|
||||
#: gtk/gtkshortcutlabel.c:142
|
||||
msgctxt "keyboard label"
|
||||
msgid "Super"
|
||||
@@ -1054,7 +1038,7 @@ msgstr "Super"
|
||||
#. * translated on keyboards used for your language, don't translate
|
||||
#. * this.
|
||||
#.
|
||||
#: gtk/gtkaccelgroup.c:907 gtk/gtkshortcutlabel.c:115
|
||||
#: gtk/gtkaccelgroup.c:896 gtk/gtkshortcutlabel.c:115
|
||||
#: gtk/gtkshortcutlabel.c:144
|
||||
msgctxt "keyboard label"
|
||||
msgid "Hyper"
|
||||
@@ -1065,7 +1049,7 @@ msgstr "Hyper"
|
||||
#. * translated on keyboards used for your language, don't translate
|
||||
#. * this.
|
||||
#.
|
||||
#: gtk/gtkaccelgroup.c:922 gtk/gtkshortcutlabel.c:109
|
||||
#: gtk/gtkaccelgroup.c:911 gtk/gtkshortcutlabel.c:109
|
||||
#: gtk/gtkshortcutlabel.c:146
|
||||
msgctxt "keyboard label"
|
||||
msgid "Meta"
|
||||
@@ -1075,17 +1059,17 @@ msgstr "Meta"
|
||||
#. * be used in accelerators such as "Ctrl+Shift+KP 1" in menus,
|
||||
#. * and therefore the translation needs to be very short.
|
||||
#.
|
||||
#: gtk/gtkaccelgroup.c:942
|
||||
#: gtk/gtkaccelgroup.c:931
|
||||
msgctxt "keyboard label"
|
||||
msgid "KP"
|
||||
msgstr "NUM"
|
||||
|
||||
#: gtk/gtkaccelgroup.c:949
|
||||
#: gtk/gtkaccelgroup.c:938
|
||||
msgctxt "keyboard label"
|
||||
msgid "Space"
|
||||
msgstr "Blanksteg"
|
||||
|
||||
#: gtk/gtkaccelgroup.c:952 gtk/gtkshortcutlabel.c:171
|
||||
#: gtk/gtkaccelgroup.c:941 gtk/gtkshortcutlabel.c:171
|
||||
msgctxt "keyboard label"
|
||||
msgid "Backslash"
|
||||
msgstr "Omvänt snedstreck"
|
||||
@@ -1992,7 +1976,7 @@ msgstr "_Höger:"
|
||||
msgid "Paper Margins"
|
||||
msgstr "Pappersmarginaler"
|
||||
|
||||
#: gtk/gtkentry.c:3743
|
||||
#: gtk/gtkentry.c:3726
|
||||
msgid "Insert Emoji"
|
||||
msgstr "Infoga emoji"
|
||||
|
||||
@@ -2063,7 +2047,7 @@ msgstr "Det finns redan en fil med det namnet"
|
||||
#: gtk/gtkprintbackend.c:642 gtk/gtkprinteroptionwidget.c:713
|
||||
#: gtk/gtkprintunixdialog.c:667 gtk/gtkprintunixdialog.c:823
|
||||
#: gtk/gtkwindow.c:6140 gtk/inspector/css-editor.c:248
|
||||
#: gtk/inspector/recorder.c:1271 gtk/ui/gtkappchooserdialog.ui:45
|
||||
#: gtk/inspector/recorder.c:1245 gtk/ui/gtkappchooserdialog.ui:45
|
||||
#: gtk/ui/gtkassistant.ui:52 gtk/ui/gtkcolorchooserdialog.ui:33
|
||||
#: gtk/ui/gtkfontchooserdialog.ui:24
|
||||
msgid "_Cancel"
|
||||
@@ -2076,7 +2060,7 @@ msgid "_Open"
|
||||
msgstr "_Öppna"
|
||||
|
||||
#: gtk/gtkfilechoosernative.c:574 gtk/inspector/css-editor.c:249
|
||||
#: gtk/inspector/recorder.c:1272
|
||||
#: gtk/inspector/recorder.c:1246
|
||||
msgid "_Save"
|
||||
msgstr "_Spara"
|
||||
|
||||
@@ -2154,7 +2138,7 @@ msgid "If you delete an item, it will be permanently lost."
|
||||
msgstr "Om du tar bort ett objekt är det borta för alltid."
|
||||
|
||||
#: gtk/gtkfilechooserwidget.c:1210 gtk/gtkfilechooserwidget.c:1826
|
||||
#: gtk/gtklabel.c:5483 gtk/gtktext.c:6062 gtk/gtktextview.c:8886
|
||||
#: gtk/gtklabel.c:5483 gtk/gtktext.c:6060 gtk/gtktextview.c:8847
|
||||
msgid "_Delete"
|
||||
msgstr "_Ta bort"
|
||||
|
||||
@@ -2426,19 +2410,19 @@ msgstr "Teckenvarianter"
|
||||
msgid "OpenGL context creation failed"
|
||||
msgstr "Skapande av OpenGL-kontext misslyckades"
|
||||
|
||||
#: gtk/gtklabel.c:5480 gtk/gtktext.c:6050 gtk/gtktextview.c:8874
|
||||
#: gtk/gtklabel.c:5480 gtk/gtktext.c:6048 gtk/gtktextview.c:8835
|
||||
msgid "Cu_t"
|
||||
msgstr "Klipp _ut"
|
||||
|
||||
#: gtk/gtklabel.c:5481 gtk/gtktext.c:6054 gtk/gtktextview.c:8878
|
||||
#: gtk/gtklabel.c:5481 gtk/gtktext.c:6052 gtk/gtktextview.c:8839
|
||||
msgid "_Copy"
|
||||
msgstr "_Kopiera"
|
||||
|
||||
#: gtk/gtklabel.c:5482 gtk/gtktext.c:6058 gtk/gtktextview.c:8882
|
||||
#: gtk/gtklabel.c:5482 gtk/gtktext.c:6056 gtk/gtktextview.c:8843
|
||||
msgid "_Paste"
|
||||
msgstr "Klistra _in"
|
||||
|
||||
#: gtk/gtklabel.c:5488 gtk/gtktext.c:6071 gtk/gtktextview.c:8907
|
||||
#: gtk/gtklabel.c:5488 gtk/gtktext.c:6069 gtk/gtktextview.c:8868
|
||||
msgid "Select _All"
|
||||
msgstr "Markera _allt"
|
||||
|
||||
@@ -2726,19 +2710,19 @@ msgstr ""
|
||||
msgid "Page Setup"
|
||||
msgstr "Sidinställning"
|
||||
|
||||
#: gtk/gtkpasswordentry.c:173
|
||||
#: gtk/gtkpasswordentry.c:167
|
||||
msgid "Hide Text"
|
||||
msgstr "Dölj text"
|
||||
|
||||
#: gtk/gtkpasswordentry.c:178 gtk/gtkpasswordentry.c:629
|
||||
#: gtk/gtkpasswordentry.c:172 gtk/gtkpasswordentry.c:606
|
||||
msgid "Show Text"
|
||||
msgstr "Visa text"
|
||||
|
||||
#: gtk/gtkpasswordentry.c:216
|
||||
#: gtk/gtkpasswordentry.c:199
|
||||
msgid "Caps Lock is on"
|
||||
msgstr "Caps Lock är aktiverad"
|
||||
|
||||
#: gtk/gtkpasswordentry.c:705
|
||||
#: gtk/gtkpasswordentry.c:680
|
||||
msgid "_Show Text"
|
||||
msgstr "_Visa text"
|
||||
|
||||
@@ -3328,7 +3312,7 @@ msgid "No registered application with name “%s” for item with URI “%s” f
|
||||
msgstr ""
|
||||
"Inget registrerat program med namnet ”%s” hittades för objekt med URI ”%s”"
|
||||
|
||||
#: gtk/gtksearchentry.c:619
|
||||
#: gtk/gtksearchentry.c:599
|
||||
msgid "Clear entry"
|
||||
msgstr "Töm sökruta"
|
||||
|
||||
@@ -3417,19 +3401,19 @@ msgstr "Försök med en annan sökning"
|
||||
msgid "Could not show link"
|
||||
msgstr "Kunde inte visa länken"
|
||||
|
||||
#: gtk/gtktext.c:6076 gtk/gtktextview.c:8912
|
||||
#: gtk/gtktext.c:6074 gtk/gtktextview.c:8873
|
||||
msgid "Insert _Emoji"
|
||||
msgstr "Infoga _emoji"
|
||||
|
||||
#: gtk/gtktextview.c:8894
|
||||
#: gtk/gtktextview.c:8855
|
||||
msgid "_Undo"
|
||||
msgstr "_Ångra"
|
||||
|
||||
#: gtk/gtktextview.c:8898
|
||||
#: gtk/gtktextview.c:8859
|
||||
msgid "_Redo"
|
||||
msgstr "_Gör om"
|
||||
|
||||
#: gtk/gtktreeexpander.c:205
|
||||
#: gtk/gtktreeexpander.c:196
|
||||
msgid "Expand"
|
||||
msgstr "Expandera"
|
||||
|
||||
@@ -3908,7 +3892,7 @@ msgstr "Källa:"
|
||||
msgid "Defined At"
|
||||
msgstr "Definierad vid"
|
||||
|
||||
#: gtk/inspector/recorder.c:1242
|
||||
#: gtk/inspector/recorder.c:1216
|
||||
#, c-format
|
||||
msgid "Saving RenderNode failed"
|
||||
msgstr "Sparande av RenderNode misslyckades"
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
[wrap-file]
|
||||
directory = libpng-1.6.37
|
||||
source_url = https://github.com/glennrp/libpng/archive/v1.6.37.tar.gz
|
||||
source_filename = libpng-1.6.37.tar.gz
|
||||
source_hash = ca74a0dace179a8422187671aee97dd3892b53e168627145271cad5b5ac81307
|
||||
patch_url = https://wrapdb.mesonbuild.com/v2/libpng_1.6.37-3/get_patch
|
||||
patch_filename = libpng-1.6.37-3-wrap.zip
|
||||
patch_hash = 6c9f32fd9150b3a96ab89be52af664e32207e10aa9f5fb9aa015989ee2dd7100
|
||||
|
||||
[provide]
|
||||
libpng = libpng_dep
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
[wrap-file]
|
||||
directory = tiff-4.1.0
|
||||
source_url = http://download.osgeo.org/libtiff/tiff-4.1.0.zip
|
||||
source_filename = tiff-4.1.0.zip
|
||||
source_hash = 6f3dbed9d2ecfed33c7192b5c01884078970657fa21b4ad28e3cdf3438eb2419
|
||||
patch_filename = libtiff_4.1.0-4_patch.zip
|
||||
patch_url = https://wrapdb.mesonbuild.com/v2/libtiff_4.1.0-4/get_patch
|
||||
patch_hash = c0fe078d06e5a7f2480a96c3897a7b3b9fa9a42c08fb76ae5f1dd59e0519a14e
|
||||
|
||||
[provide]
|
||||
libtiff-4 = libtiff4_dep
|
||||
|
||||
@@ -49,7 +49,6 @@ main(int argc, char **argv)
|
||||
gsize len;
|
||||
int run;
|
||||
GOptionContext *context;
|
||||
GdkTexture *texture;
|
||||
|
||||
context = g_option_context_new ("NODE-FILE PNG-FILE");
|
||||
g_option_context_add_main_entries (context, options, NULL);
|
||||
@@ -110,16 +109,9 @@ main(int argc, char **argv)
|
||||
{
|
||||
graphene_rect_t bounds;
|
||||
cairo_t *cr;
|
||||
int width, height, stride;
|
||||
guchar *pixels;
|
||||
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
width = ceil (bounds.size.width);
|
||||
height = ceil (bounds.size.height);
|
||||
stride = width * 4;
|
||||
pixels = g_malloc0_n (stride, height);
|
||||
|
||||
surface = cairo_image_surface_create_for_data (pixels, CAIRO_FORMAT_ARGB32, width, height, stride);
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ceil (bounds.size.width), ceil (bounds.size.height));
|
||||
cr = cairo_create (surface);
|
||||
|
||||
cairo_translate (cr, - bounds.origin.x, - bounds.origin.y);
|
||||
@@ -140,23 +132,15 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
bytes = g_bytes_new_take (pixels, stride * height);
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
bytes,
|
||||
stride);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
GskRenderer *renderer;
|
||||
GdkSurface *window;
|
||||
GdkTexture *texture = NULL;
|
||||
|
||||
window = gdk_surface_new_toplevel (gdk_display_get_default());
|
||||
renderer = gsk_renderer_new_for_surface (window);
|
||||
texture = NULL; /* poor gcc can't see that runs > 0 */
|
||||
|
||||
for (run = 0; run < runs; run++)
|
||||
{
|
||||
@@ -169,7 +153,15 @@ main(int argc, char **argv)
|
||||
g_print ("Run %u: Rendered using %s in %.4gs\n", run, G_OBJECT_TYPE_NAME (renderer), (double) (end - start) / G_USEC_PER_SEC);
|
||||
}
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
gdk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_mark_dirty (surface);
|
||||
gsk_renderer_unrealize (renderer);
|
||||
g_object_unref (texture);
|
||||
g_object_unref (window);
|
||||
g_object_unref (renderer);
|
||||
}
|
||||
@@ -178,15 +170,19 @@ main(int argc, char **argv)
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
if (!gdk_texture_save_to_png (texture, argv[2]))
|
||||
cairo_status_t status;
|
||||
|
||||
status = cairo_surface_write_to_png (surface, argv[2]);
|
||||
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
{
|
||||
g_object_unref (texture);
|
||||
g_print ("Failed to save PNG file\n");
|
||||
cairo_surface_destroy (surface);
|
||||
g_print ("Failed to save PNG file: %s\n", cairo_status_to_string (status));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (texture);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
static const char *format_name[] = {
|
||||
"BGRAp", "ARGBp", "RGBAp",
|
||||
"BGRA", "ARGB", "RGBA", "ABGR",
|
||||
"RGB", "BGR", NULL
|
||||
"RGB", "BGR",
|
||||
};
|
||||
|
||||
static const char *
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
a {
|
||||
color: hsl(0, 0%, 0%);
|
||||
}
|
||||
|
||||
b {
|
||||
color: hsl(120, 100%, 50%);
|
||||
}
|
||||
|
||||
c {
|
||||
color: hsl(360, 100%, 50%);
|
||||
}
|
||||
|
||||
d {
|
||||
color: hsl(-314.159, 50%, 50%);
|
||||
}
|
||||
|
||||
e {
|
||||
color: hsl(0, 0%, 0%, 0.5);
|
||||
}
|
||||
|
||||
f {
|
||||
color: hsl(1, 2, 3);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
hsl.css:22:17-18: error: GTK_CSS_PARSER_ERROR_SYNTAX
|
||||
@@ -1,19 +0,0 @@
|
||||
a {
|
||||
color: rgb(0,0,0);
|
||||
}
|
||||
|
||||
b {
|
||||
color: rgb(0,255,0);
|
||||
}
|
||||
|
||||
c {
|
||||
color: rgb(255,0,0);
|
||||
}
|
||||
|
||||
d {
|
||||
color: rgb(191,161,64);
|
||||
}
|
||||
|
||||
e {
|
||||
color: rgba(0,0,0,0.5);
|
||||
}
|
||||
@@ -358,9 +358,6 @@ test_data = [
|
||||
'freed-string-in-error-messages.css',
|
||||
'freed-string-in-error-messages.errors',
|
||||
'freed-string-in-error-messages.ref.css',
|
||||
'hsl.css',
|
||||
'hsl.errors',
|
||||
'hsl.ref.css',
|
||||
'import-cyclic-1.css',
|
||||
'import-cyclic-1.errors',
|
||||
'import-cyclic-1.ref.css',
|
||||
|
||||
@@ -30,49 +30,6 @@ compare_rgba_values (GValue *v1, GValue *v2)
|
||||
(GdkRGBA *)g_value_get_boxed (v2));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
textures_equal (GdkTexture *t1, GdkTexture *t2)
|
||||
{
|
||||
guchar *d1, *d2;
|
||||
int width, height;
|
||||
gboolean ret;
|
||||
|
||||
width = gdk_texture_get_width (t1);
|
||||
height = gdk_texture_get_height (t1);
|
||||
|
||||
if (width != gdk_texture_get_width (t2))
|
||||
return FALSE;
|
||||
if (height != gdk_texture_get_height (t2))
|
||||
return FALSE;
|
||||
|
||||
d1 = g_malloc (width * height * 4);
|
||||
d2 = g_malloc (width * height * 4);
|
||||
|
||||
gdk_texture_download (t1, d1, width * 4);
|
||||
gdk_texture_download (t2, d2, width * 4);
|
||||
|
||||
ret = memcmp (d1, d2, width * height * 4) == 0;
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
gdk_texture_save_to_png (t1, "texture1.png");
|
||||
gdk_texture_save_to_png (t2, "texture2.png");
|
||||
}
|
||||
g_free (d1);
|
||||
g_free (d2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
compare_texture_values (GValue *v1, GValue *v2)
|
||||
{
|
||||
return G_VALUE_TYPE (v1) == GDK_TYPE_TEXTURE &&
|
||||
G_VALUE_TYPE (v2) == GDK_TYPE_TEXTURE &&
|
||||
textures_equal ((GdkTexture *)g_value_get_object (v1),
|
||||
(GdkTexture *)g_value_get_object (v2));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
compare_file_values (GValue *v1, GValue *v2)
|
||||
{
|
||||
@@ -168,7 +125,7 @@ test_content_roundtrip (const GValue *value,
|
||||
TestData data = { 0, };
|
||||
|
||||
data.ostream = g_memory_output_stream_new_resizable ();
|
||||
data.mime_type = mime_type;
|
||||
data.mime_type = g_strdup (mime_type);
|
||||
g_value_init (&data.value, G_VALUE_TYPE (value));
|
||||
g_value_copy (value, &data.value);
|
||||
data.compare = compare;
|
||||
@@ -225,30 +182,6 @@ test_content_color (void)
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
static void
|
||||
test_content_texture (gconstpointer data)
|
||||
{
|
||||
const char *mimetype = data;
|
||||
GValue value = G_VALUE_INIT;
|
||||
char *path;
|
||||
GFile *file;
|
||||
GdkTexture *texture;
|
||||
GError *error = NULL;
|
||||
|
||||
path = g_test_build_filename (G_TEST_DIST, "image-data", "image.png", NULL);
|
||||
file = g_file_new_for_path (path);
|
||||
texture = gdk_texture_new_from_file (file, &error);
|
||||
g_assert_no_error (error);
|
||||
g_object_unref (file);
|
||||
g_free (path);
|
||||
|
||||
g_value_init (&value, GDK_TYPE_TEXTURE);
|
||||
g_value_set_object (&value, texture);
|
||||
test_content_roundtrip (&value, mimetype, compare_texture_values);
|
||||
g_value_unset (&value);
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
test_content_file (void)
|
||||
{
|
||||
@@ -473,8 +406,6 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/content/text_plain_utf8", test_content_text_plain_utf8);
|
||||
g_test_add_func ("/content/text_plain", test_content_text_plain);
|
||||
g_test_add_func ("/content/color", test_content_color);
|
||||
g_test_add_data_func ("/content/texture/png", "image/png", test_content_texture);
|
||||
g_test_add_data_func ("/content/texture/tiff", "image/tiff", test_content_texture);
|
||||
g_test_add_func ("/content/file", test_content_file);
|
||||
g_test_add_func ("/content/files", test_content_files);
|
||||
g_test_add_func ("/content/custom", test_custom_format);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
@@ -1,129 +0,0 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "gdk/loaders/gdkpngprivate.h"
|
||||
#include "gdk/loaders/gdktiffprivate.h"
|
||||
#include "gdk/loaders/gdkjpegprivate.h"
|
||||
|
||||
static void
|
||||
assert_texture_equal (GdkTexture *t1,
|
||||
GdkTexture *t2)
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int stride;
|
||||
guchar *d1;
|
||||
guchar *d2;
|
||||
|
||||
width = gdk_texture_get_width (t1);
|
||||
height = gdk_texture_get_height (t1);
|
||||
stride = 4 * width;
|
||||
|
||||
g_assert_cmpint (width, ==, gdk_texture_get_width (t2));
|
||||
g_assert_cmpint (height, ==, gdk_texture_get_height (t2));
|
||||
|
||||
d1 = g_malloc (stride * height);
|
||||
d2 = g_malloc (stride * height);
|
||||
|
||||
gdk_texture_download (t1, d1, stride);
|
||||
gdk_texture_download (t2, d2, stride);
|
||||
|
||||
g_assert_cmpmem (d1, stride * height, d2, stride * height);
|
||||
|
||||
g_free (d1);
|
||||
g_free (d2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_load_image (gconstpointer data)
|
||||
{
|
||||
const char *filename = data;
|
||||
GdkTexture *texture;
|
||||
char *path;
|
||||
GFile *file;
|
||||
GBytes *bytes;
|
||||
GError *error = NULL;
|
||||
|
||||
path = g_test_build_filename (G_TEST_DIST, "image-data", filename, NULL);
|
||||
file = g_file_new_for_path (path);
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
if (g_str_has_suffix (filename, ".png"))
|
||||
texture = gdk_load_png (bytes, &error);
|
||||
else if (g_str_has_suffix (filename, ".tiff"))
|
||||
texture = gdk_load_tiff (bytes, &error);
|
||||
else if (g_str_has_suffix (filename, ".jpeg"))
|
||||
texture = gdk_load_jpeg (bytes, &error);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (GDK_IS_TEXTURE (texture));
|
||||
g_assert_cmpint (gdk_texture_get_width (texture), ==, 32);
|
||||
g_assert_cmpint (gdk_texture_get_height (texture), ==, 32);
|
||||
|
||||
g_object_unref (texture);
|
||||
g_bytes_unref (bytes);
|
||||
g_object_unref (file);
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_save_image (gconstpointer test_data)
|
||||
{
|
||||
const char *filename = test_data;
|
||||
char *path;
|
||||
GFile *file;
|
||||
GdkTexture *texture;
|
||||
GFile *file2;
|
||||
GdkTexture *texture2;
|
||||
GError *error = NULL;
|
||||
GBytes *bytes = NULL;
|
||||
GIOStream *stream;
|
||||
|
||||
path = g_test_build_filename (G_TEST_DIST, "image-data", filename, NULL);
|
||||
file = g_file_new_for_path (path);
|
||||
texture = gdk_texture_new_from_file (file, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
if (g_str_has_suffix (filename, ".png"))
|
||||
bytes = gdk_save_png (texture);
|
||||
else if (g_str_has_suffix (filename, ".tiff"))
|
||||
bytes = gdk_save_tiff (texture);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
file2 = g_file_new_tmp ("imageXXXXXX", (GFileIOStream **)&stream, NULL);
|
||||
g_object_unref (stream);
|
||||
g_file_replace_contents (file2,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes),
|
||||
NULL, FALSE, 0,
|
||||
NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
texture2 = gdk_texture_new_from_file (file2, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
assert_texture_equal (texture, texture2);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
g_object_unref (texture2);
|
||||
g_object_unref (file2);
|
||||
g_object_unref (texture);
|
||||
g_object_unref (file);
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
(g_test_init) (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_data_func ("/image/load/png", "image.png", test_load_image);
|
||||
g_test_add_data_func ("/image/load/tiff", "image.tiff", test_load_image);
|
||||
g_test_add_data_func ("/image/load/jpeg", "image.jpeg", test_load_image);
|
||||
g_test_add_data_func ("/image/save/png", "image.png", test_save_image);
|
||||
g_test_add_data_func ("/image/save/tiff", "image.tiff", test_save_image);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -1,695 +1,230 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <locale.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "gsk/ngl/gsknglrenderer.h"
|
||||
|
||||
#define N 20
|
||||
|
||||
static GskRenderer *gl_renderer = NULL;
|
||||
|
||||
typedef struct _TextureBuilder TextureBuilder;
|
||||
/* maximum bytes per pixel */
|
||||
#define MAX_BPP 4
|
||||
|
||||
typedef enum {
|
||||
TEXTURE_METHOD_LOCAL,
|
||||
TEXTURE_METHOD_GL,
|
||||
TEXTURE_METHOD_GL_RELEASED,
|
||||
TEXTURE_METHOD_PNG,
|
||||
TEXTURE_METHOD_PNG_PIXBUF,
|
||||
TEXTURE_METHOD_TIFF,
|
||||
TEXTURE_METHOD_TIFF_PIXBUF,
|
||||
BLUE,
|
||||
GREEN,
|
||||
RED,
|
||||
TRANSPARENT,
|
||||
ALMOST_OPAQUE_REBECCAPURPLE,
|
||||
N_COLORS
|
||||
} Color;
|
||||
|
||||
N_TEXTURE_METHODS
|
||||
} TextureMethod;
|
||||
|
||||
struct _TextureBuilder
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
guchar *pixels;
|
||||
gsize stride;
|
||||
gsize offset;
|
||||
const char * color_names[N_COLORS] = {
|
||||
"blue",
|
||||
"green",
|
||||
"red",
|
||||
"transparent",
|
||||
"almost_opaque_rebeccapurple"
|
||||
};
|
||||
|
||||
static gsize
|
||||
gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
return 3;
|
||||
typedef struct _MemoryData {
|
||||
gsize bytes_per_pixel;
|
||||
guint opaque : 1;
|
||||
guchar data[N_COLORS][MAX_BPP];
|
||||
} MemoryData;
|
||||
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
return 4;
|
||||
typedef struct _TestData {
|
||||
GdkMemoryFormat format;
|
||||
Color color;
|
||||
} TestData;
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
return 6;
|
||||
#define RGBA(a, b, c, d) { 0x ## a, 0x ## b, 0x ## c, 0x ## d }
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return 8;
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
return 12;
|
||||
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return 16;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_memory_format_has_alpha (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
return FALSE;
|
||||
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return TRUE;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
encode (GdkMemoryFormat format,
|
||||
TextureMethod method)
|
||||
{
|
||||
return GSIZE_TO_POINTER (method * GDK_MEMORY_N_FORMATS + format);
|
||||
}
|
||||
static MemoryData tests[GDK_MEMORY_N_FORMATS] = {
|
||||
{ 4, FALSE, { RGBA(FF,00,00,FF), RGBA(00,FF,00,FF), RGBA(00,00,FF,FF), RGBA(00,00,00,00), RGBA(66,22,44,AA) } },
|
||||
{ 4, FALSE, { RGBA(FF,00,00,FF), RGBA(FF,00,FF,00), RGBA(FF,FF,00,00), RGBA(00,00,00,00), RGBA(AA,44,22,66) } },
|
||||
{ 4, FALSE, { RGBA(00,00,FF,FF), RGBA(00,FF,00,FF), RGBA(FF,00,00,FF), RGBA(00,00,00,00), RGBA(44,22,66,AA) } },
|
||||
{ 4, FALSE, { RGBA(FF,00,00,FF), RGBA(00,FF,00,FF), RGBA(00,00,FF,FF), RGBA(00,00,00,00), RGBA(99,33,66,AA) } },
|
||||
{ 4, FALSE, { RGBA(FF,00,00,FF), RGBA(FF,00,FF,00), RGBA(FF,FF,00,00), RGBA(00,00,00,00), RGBA(AA,66,33,99) } },
|
||||
{ 4, FALSE, { RGBA(00,00,FF,FF), RGBA(00,FF,00,FF), RGBA(FF,00,00,FF), RGBA(00,00,00,00), RGBA(66,33,99,AA) } },
|
||||
{ 4, FALSE, { RGBA(FF,FF,00,00), RGBA(FF,00,FF,00), RGBA(FF,00,00,FF), RGBA(00,00,00,00), RGBA(AA,99,33,66) } },
|
||||
{ 3, TRUE, { RGBA(00,00,FF,00), RGBA(00,FF,00,00), RGBA(FF,00,00,00), RGBA(00,00,00,00), RGBA(44,22,66,00) } },
|
||||
{ 3, TRUE, { RGBA(FF,00,00,00), RGBA(00,FF,00,00), RGBA(00,00,FF,00), RGBA(00,00,00,00), RGBA(66,22,44,00) } },
|
||||
};
|
||||
|
||||
static void
|
||||
decode (gconstpointer data,
|
||||
GdkMemoryFormat *format,
|
||||
TextureMethod *method)
|
||||
compare_textures (GdkTexture *expected,
|
||||
GdkTexture *test,
|
||||
gboolean ignore_alpha)
|
||||
{
|
||||
gsize value = GPOINTER_TO_SIZE (data);
|
||||
guchar *expected_data, *test_data;
|
||||
int width, height;
|
||||
int x, y;
|
||||
|
||||
*format = value % GDK_MEMORY_N_FORMATS;
|
||||
value /= GDK_MEMORY_N_FORMATS;
|
||||
g_assert_cmpint (gdk_texture_get_width (expected), ==, gdk_texture_get_width (test));
|
||||
g_assert_cmpint (gdk_texture_get_height (expected), ==, gdk_texture_get_height (test));
|
||||
|
||||
*method = value;
|
||||
}
|
||||
|
||||
static void
|
||||
texture_builder_init (TextureBuilder *builder,
|
||||
GdkMemoryFormat format,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
gsize extra_stride;
|
||||
width = gdk_texture_get_width (expected);
|
||||
height = gdk_texture_get_height (expected);
|
||||
|
||||
builder->format = format;
|
||||
builder->width = width;
|
||||
builder->height = height;
|
||||
expected_data = g_malloc (width * height * 4);
|
||||
gdk_texture_download (expected, expected_data, width * 4);
|
||||
|
||||
extra_stride = g_test_rand_bit() ? g_test_rand_int_range (0, 16) : 0;
|
||||
builder->offset = g_test_rand_bit() ? g_test_rand_int_range (0, 128) : 0;
|
||||
builder->stride = width * gdk_memory_format_bytes_per_pixel (format) + extra_stride;
|
||||
builder->pixels = g_malloc0 (builder->offset + builder->stride * height);
|
||||
test_data = g_malloc (width * height * 4);
|
||||
gdk_texture_download (test, test_data, width * 4);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
if (ignore_alpha)
|
||||
g_assert_cmphex (*(guint32 *) &expected_data[y * width + x * 4] & 0xFFFFFF, ==, *(guint32 *) &test_data[y * width + x * 4] & 0xFFFFFF);
|
||||
else
|
||||
g_assert_cmphex (*(guint32 *) &expected_data[y * width + x * 4], ==, *(guint32 *) &test_data[y * width + x * 4]);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (expected_data);
|
||||
g_free (test_data);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
texture_builder_finish (TextureBuilder *builder)
|
||||
create_texture (GdkMemoryFormat format,
|
||||
Color color,
|
||||
int width,
|
||||
int height,
|
||||
gsize stride)
|
||||
{
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GBytes *bytes;
|
||||
guchar *data;
|
||||
int x, y;
|
||||
|
||||
bytes = g_bytes_new_with_free_func (builder->pixels + builder->offset,
|
||||
builder->height * builder->stride,
|
||||
g_free,
|
||||
builder->pixels);
|
||||
texture = gdk_memory_texture_new (builder->width,
|
||||
builder->height,
|
||||
builder->format,
|
||||
data = g_malloc (height * MAX (stride, tests[format].bytes_per_pixel));
|
||||
for (y = 0; y < height; y++)
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
memcpy (&data[y * stride + x * tests[format].bytes_per_pixel],
|
||||
&tests[format].data[color],
|
||||
tests[format].bytes_per_pixel);
|
||||
}
|
||||
|
||||
bytes = g_bytes_new_take (data, height * MAX (stride, tests[format].bytes_per_pixel));
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
format,
|
||||
bytes,
|
||||
builder->stride);
|
||||
stride);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_pixel_u8 (guchar *data,
|
||||
int r,
|
||||
int g,
|
||||
int b,
|
||||
int a,
|
||||
gboolean premultiply,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
if (a >= 0)
|
||||
data[a] = CLAMP (color->alpha * 256.f, 0.f, 255.f);
|
||||
if (premultiply)
|
||||
{
|
||||
data[r] = CLAMP (color->red * color->alpha * 256.f, 0.f, 255.f);
|
||||
data[g] = CLAMP (color->green * color->alpha * 256.f, 0.f, 255.f);
|
||||
data[b] = CLAMP (color->blue * color->alpha * 256.f, 0.f, 255.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
data[r] = CLAMP (color->red * 256.f, 0.f, 255.f);
|
||||
data[g] = CLAMP (color->green * 256.f, 0.f, 255.f);
|
||||
data[b] = CLAMP (color->blue * 256.f, 0.f, 255.f);
|
||||
}
|
||||
}
|
||||
|
||||
static inline guint16
|
||||
float_to_half (const float x)
|
||||
{
|
||||
const guint b = *(guint*)&x+0x00001000; // round-to-nearest-even
|
||||
const guint e = (b&0x7F800000)>>23; // exponent
|
||||
const guint m = b&0x007FFFFF; // mantissa
|
||||
return (b&0x80000000)>>16 | (e>112)*((((e-112)<<10)&0x7C00)|m>>13) | ((e<113)&(e>101))*((((0x007FF000+m)>>(125-e))+1)>>1) | (e>143)*0x7FFF; // sign : normalized : denormalized : saturate
|
||||
}
|
||||
|
||||
static void
|
||||
texture_builder_set_pixel (TextureBuilder *builder,
|
||||
int x,
|
||||
int y,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
guchar *data;
|
||||
|
||||
g_assert_cmpint (x, >=, 0);
|
||||
g_assert_cmpint (x, <, builder->width);
|
||||
g_assert_cmpint (y, >=, 0);
|
||||
g_assert_cmpint (y, <, builder->height);
|
||||
|
||||
data = builder->pixels
|
||||
+ builder->offset
|
||||
+ y * builder->stride
|
||||
+ x * gdk_memory_format_bytes_per_pixel (builder->format);
|
||||
|
||||
switch (builder->format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
set_pixel_u8 (data, 2, 1, 0, 3, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
set_pixel_u8 (data, 1, 2, 3, 0, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
set_pixel_u8 (data, 0, 1, 2, 3, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
set_pixel_u8 (data, 2, 1, 0, 3, FALSE, color);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
set_pixel_u8 (data, 1, 2, 3, 0, FALSE, color);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
set_pixel_u8 (data, 0, 1, 2, 3, FALSE, color);
|
||||
break;
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
set_pixel_u8 (data, 3, 2, 1, 0, FALSE, color);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
set_pixel_u8 (data, 2, 1, 0, -1, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
{
|
||||
guint16 pixels[3] = {
|
||||
CLAMP (color->red * color->alpha * 65536.f, 0, 65535.f),
|
||||
CLAMP (color->green * color->alpha * 65536.f, 0, 65535.f),
|
||||
CLAMP (color->blue * color->alpha * 65536.f, 0, 65535.f),
|
||||
};
|
||||
memcpy (data, pixels, 3 * sizeof (guint16));
|
||||
}
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
{
|
||||
guint16 pixels[4] = {
|
||||
CLAMP (color->red * color->alpha * 65536.f, 0, 65535.f),
|
||||
CLAMP (color->green * color->alpha * 65536.f, 0, 65535.f),
|
||||
CLAMP (color->blue * color->alpha * 65536.f, 0, 65535.f),
|
||||
CLAMP (color->alpha * 65536.f, 0, 65535.f),
|
||||
};
|
||||
memcpy (data, pixels, 4 * sizeof (guint16));
|
||||
}
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
{
|
||||
guint16 pixels[3] = {
|
||||
float_to_half (color->red * color->alpha),
|
||||
float_to_half (color->green * color->alpha),
|
||||
float_to_half (color->blue * color->alpha)
|
||||
};
|
||||
memcpy (data, pixels, 3 * sizeof (guint16));
|
||||
}
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
{
|
||||
guint16 pixels[4] = {
|
||||
float_to_half (color->red * color->alpha),
|
||||
float_to_half (color->green * color->alpha),
|
||||
float_to_half (color->blue * color->alpha),
|
||||
float_to_half (color->alpha)
|
||||
};
|
||||
memcpy (data, pixels, 4 * sizeof (guint16));
|
||||
}
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
{
|
||||
float pixels[3] = {
|
||||
color->red * color->alpha,
|
||||
color->green * color->alpha,
|
||||
color->blue * color->alpha
|
||||
};
|
||||
memcpy (data, pixels, 3 * sizeof (float));
|
||||
}
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
{
|
||||
float pixels[4] = {
|
||||
color->red * color->alpha,
|
||||
color->green * color->alpha,
|
||||
color->blue * color->alpha,
|
||||
color->alpha
|
||||
};
|
||||
memcpy (data, pixels, 4 * sizeof (float));
|
||||
}
|
||||
break;
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
texture_builder_fill (TextureBuilder *builder,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < builder->height; y++)
|
||||
for (x = 0; x < builder->width; x++)
|
||||
texture_builder_set_pixel (builder, x, y, color);
|
||||
}
|
||||
|
||||
static void
|
||||
compare_textures (GdkTexture *expected,
|
||||
GdkTexture *test,
|
||||
gboolean has_alpha)
|
||||
{
|
||||
guint32 *expected_data, *test_data;
|
||||
int width, height;
|
||||
int x, y;
|
||||
|
||||
g_assert_cmpint (gdk_texture_get_width (expected), ==, gdk_texture_get_width (test));
|
||||
g_assert_cmpint (gdk_texture_get_height (expected), ==, gdk_texture_get_height (test));
|
||||
|
||||
width = gdk_texture_get_width (expected);
|
||||
height = gdk_texture_get_height (expected);
|
||||
|
||||
expected_data = g_new (guint32, width * height);
|
||||
gdk_texture_download (expected, (guchar *) expected_data, width * 4);
|
||||
|
||||
test_data = g_new (guint32, width * height);
|
||||
gdk_texture_download (test, (guchar *) test_data, width * 4);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
if (has_alpha)
|
||||
g_assert_cmphex (expected_data[y * width + x], ==, test_data[y * width + x]);
|
||||
else
|
||||
g_assert_cmphex (expected_data[y * width + x] | 0xFF000000, ==, test_data[y * width + x]);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (expected_data);
|
||||
g_free (test_data);
|
||||
}
|
||||
|
||||
static void
|
||||
compare_textures_float (GdkTexture *expected,
|
||||
GdkTexture *test,
|
||||
float eps,
|
||||
gboolean has_alpha)
|
||||
{
|
||||
static int R = 0;
|
||||
static int G = 1;
|
||||
static int B = 2;
|
||||
static int A = 3;
|
||||
float *expected_data, *test_data;
|
||||
int width, height;
|
||||
int x, y;
|
||||
|
||||
g_assert_cmpint (gdk_texture_get_width (expected), ==, gdk_texture_get_width (test));
|
||||
g_assert_cmpint (gdk_texture_get_height (expected), ==, gdk_texture_get_height (test));
|
||||
|
||||
width = gdk_texture_get_width (expected);
|
||||
height = gdk_texture_get_height (expected);
|
||||
|
||||
expected_data = g_new (float, width * height * 4);
|
||||
gdk_texture_download_float (expected, expected_data, width * 4);
|
||||
|
||||
test_data = g_new (float, width * height * 4);
|
||||
gdk_texture_download_float (test, test_data, width * 4);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
g_assert_cmpfloat_with_epsilon (expected_data[y * width + 4 * x + R], test_data[y * width + 4 * x + R], eps);
|
||||
g_assert_cmpfloat_with_epsilon (expected_data[y * width + 4 * x + G], test_data[y * width + 4 * x + G], eps);
|
||||
g_assert_cmpfloat_with_epsilon (expected_data[y * width + 4 * x + B], test_data[y * width + 4 * x + B], eps);
|
||||
if (has_alpha)
|
||||
g_assert_cmpfloat_with_epsilon (expected_data[y * width + 4 * x + A], test_data[y * width + 4 * x + A], eps);
|
||||
else
|
||||
g_assert_cmpfloat (1.0, ==, test_data[y * width + 4 * x + A]);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (expected_data);
|
||||
g_free (test_data);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
upload_to_gl (GdkTexture *texture)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
GdkTexture *result;
|
||||
|
||||
if (gl_renderer == NULL)
|
||||
return texture;
|
||||
|
||||
node = gsk_texture_node_new (texture,
|
||||
&GRAPHENE_RECT_INIT(
|
||||
0, 0,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture)
|
||||
));
|
||||
result = gsk_renderer_render_texture (gl_renderer, node, NULL);
|
||||
gsk_render_node_unref (node);
|
||||
g_object_unref (texture);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
create_texture (GdkMemoryFormat format,
|
||||
TextureMethod method,
|
||||
int width,
|
||||
int height,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
TextureBuilder builder;
|
||||
GdkTexture *texture;
|
||||
|
||||
texture_builder_init (&builder, format, width, height);
|
||||
texture_builder_fill (&builder, color);
|
||||
|
||||
texture = texture_builder_finish (&builder);
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case TEXTURE_METHOD_LOCAL:
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_GL:
|
||||
texture = upload_to_gl (texture);
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_GL_RELEASED:
|
||||
texture = upload_to_gl (texture);
|
||||
gdk_gl_texture_release (GDK_GL_TEXTURE (texture));
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_PNG:
|
||||
{
|
||||
GBytes *bytes = gdk_texture_save_to_png_bytes (texture);
|
||||
g_assert (bytes);
|
||||
g_object_unref (texture);
|
||||
texture = gdk_texture_new_from_bytes (bytes, NULL);
|
||||
g_assert (texture);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_PNG_PIXBUF:
|
||||
{
|
||||
GInputStream *stream;
|
||||
GdkPixbuf *pixbuf;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_texture_save_to_png_bytes (texture);
|
||||
g_assert (bytes);
|
||||
g_object_unref (texture);
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL);
|
||||
g_object_unref (stream);
|
||||
g_assert (pixbuf);
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_assert (texture);
|
||||
g_object_unref (pixbuf);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_TIFF:
|
||||
{
|
||||
GBytes *bytes = gdk_texture_save_to_tiff_bytes (texture);
|
||||
g_assert (bytes);
|
||||
g_object_unref (texture);
|
||||
texture = gdk_texture_new_from_bytes (bytes, NULL);
|
||||
g_assert (texture);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_TIFF_PIXBUF:
|
||||
{
|
||||
GInputStream *stream;
|
||||
GdkPixbuf *pixbuf;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_texture_save_to_png_bytes (texture);
|
||||
g_assert (bytes);
|
||||
g_object_unref (texture);
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL);
|
||||
g_object_unref (stream);
|
||||
g_assert (pixbuf);
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_assert (texture);
|
||||
g_object_unref (pixbuf);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
break;
|
||||
|
||||
case N_TEXTURE_METHODS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static void
|
||||
create_random_color (GdkRGBA *color)
|
||||
{
|
||||
/* Generate colors so that premultiplying will result in values in steps of 1/15th */
|
||||
color->red = g_test_rand_int_range (0, 6) / 5.f;
|
||||
color->green = g_test_rand_int_range (0, 6) / 5.f;
|
||||
color->blue = g_test_rand_int_range (0, 6) / 5.f;
|
||||
color->alpha = g_test_rand_int_range (0, 4) / 3.f;
|
||||
}
|
||||
|
||||
static void
|
||||
test_download_1x1 (gconstpointer data)
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
TextureMethod method;
|
||||
const TestData *test_data = data;
|
||||
GdkTexture *expected, *test;
|
||||
gsize i;
|
||||
|
||||
decode (data, &format, &method);
|
||||
expected = create_texture (GDK_MEMORY_DEFAULT, test_data->color, 1, 1, tests[test_data->format].bytes_per_pixel);
|
||||
test = create_texture (test_data->format, test_data->color, 1, 1, tests[test_data->format].bytes_per_pixel);
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
GdkRGBA color;
|
||||
compare_textures (expected, test, tests[test_data->format].opaque);
|
||||
|
||||
create_random_color (&color);
|
||||
expected = create_texture (GDK_MEMORY_DEFAULT, TEXTURE_METHOD_LOCAL, 1, 1, &color);
|
||||
test = create_texture (format, method, 1, 1, &color);
|
||||
|
||||
compare_textures (expected, test, gdk_memory_format_has_alpha (format));
|
||||
g_object_unref (expected);
|
||||
g_object_unref (test);
|
||||
}
|
||||
|
||||
g_object_unref (expected);
|
||||
g_object_unref (test);
|
||||
}
|
||||
static void
|
||||
test_download_1x1_with_stride (gconstpointer data)
|
||||
{
|
||||
const TestData *test_data = data;
|
||||
GdkTexture *expected, *test;
|
||||
|
||||
expected = create_texture (GDK_MEMORY_DEFAULT, test_data->color, 1, 1, 4);
|
||||
test = create_texture (test_data->format, test_data->color, 1, 1, 2 * MAX_BPP);
|
||||
|
||||
compare_textures (expected, test, tests[test_data->format].opaque);
|
||||
|
||||
g_object_unref (expected);
|
||||
g_object_unref (test);
|
||||
}
|
||||
|
||||
static void
|
||||
test_download_4x4 (gconstpointer data)
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
TextureMethod method;
|
||||
const TestData *test_data = data;
|
||||
GdkTexture *expected, *test;
|
||||
gsize i;
|
||||
|
||||
decode (data, &format, &method);
|
||||
expected = create_texture (GDK_MEMORY_DEFAULT, test_data->color, 4, 4, 16);
|
||||
test = create_texture (test_data->format, test_data->color, 4, 4, 4 * tests[test_data->format].bytes_per_pixel);
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
GdkRGBA color;
|
||||
compare_textures (expected, test, tests[test_data->format].opaque);
|
||||
|
||||
create_random_color (&color);
|
||||
expected = create_texture (GDK_MEMORY_DEFAULT, TEXTURE_METHOD_LOCAL, 4, 4, &color);
|
||||
test = create_texture (format, method, 4, 4, &color);
|
||||
|
||||
compare_textures (expected, test, gdk_memory_format_has_alpha (format));
|
||||
|
||||
g_object_unref (expected);
|
||||
g_object_unref (test);
|
||||
}
|
||||
g_object_unref (expected);
|
||||
g_object_unref (test);
|
||||
}
|
||||
|
||||
static void
|
||||
test_download_float_1x1 (gconstpointer data)
|
||||
test_download_4x4_with_stride (gconstpointer data)
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
TextureMethod method;
|
||||
const TestData *test_data = data;
|
||||
GdkTexture *expected, *test;
|
||||
gsize i;
|
||||
|
||||
decode (data, &format, &method);
|
||||
expected = create_texture (GDK_MEMORY_DEFAULT, test_data->color, 4, 4, 16);
|
||||
test = create_texture (test_data->format, test_data->color, 4, 4, 4 * MAX_BPP);
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
GdkRGBA color;
|
||||
compare_textures (expected, test, tests[test_data->format].opaque);
|
||||
|
||||
create_random_color (&color);
|
||||
expected = create_texture (GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, TEXTURE_METHOD_LOCAL, 1, 1, &color);
|
||||
test = create_texture (format, method, 1, 1, &color);
|
||||
|
||||
compare_textures_float (expected, test,
|
||||
G_MINFLOAT,
|
||||
gdk_memory_format_has_alpha (format));
|
||||
|
||||
g_object_unref (expected);
|
||||
g_object_unref (test);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_download_float_4x4 (gconstpointer data)
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
TextureMethod method;
|
||||
GdkTexture *expected, *test;
|
||||
gsize i;
|
||||
|
||||
decode (data, &format, &method);
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
GdkRGBA color;
|
||||
|
||||
create_random_color (&color);
|
||||
expected = create_texture (GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, TEXTURE_METHOD_LOCAL, 4, 4, &color);
|
||||
test = create_texture (format, method, 4, 4, &color);
|
||||
|
||||
compare_textures_float (expected, test, G_MINFLOAT, gdk_memory_format_has_alpha (format));
|
||||
|
||||
g_object_unref (expected);
|
||||
g_object_unref (test);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_test (const char *name,
|
||||
GTestDataFunc func)
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
TextureMethod method;
|
||||
GEnumClass *enum_class;
|
||||
|
||||
enum_class = g_type_class_ref (GDK_TYPE_MEMORY_FORMAT);
|
||||
|
||||
for (format = 0; format < GDK_MEMORY_N_FORMATS; format++)
|
||||
{
|
||||
for (method = 0; method < N_TEXTURE_METHODS; method++)
|
||||
{
|
||||
const char *method_names[N_TEXTURE_METHODS] = { "local", "gl", "gl-released", "png", "png-pixbuf", "tiff", "tiff-pixbuf" };
|
||||
char *test_name = g_strdup_printf ("%s/%s/%s",
|
||||
name,
|
||||
g_enum_get_value (enum_class, format)->value_nick,
|
||||
method_names[method]);
|
||||
g_test_add_data_func_full (test_name, encode (format, method), test_download_1x1, NULL);
|
||||
g_free (test_name);
|
||||
}
|
||||
}
|
||||
g_object_unref (expected);
|
||||
g_object_unref (test);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GdkSurface *surface;
|
||||
int result;
|
||||
GdkMemoryFormat format;
|
||||
Color color;
|
||||
GEnumClass *enum_class;
|
||||
|
||||
gtk_test_init (&argc, &argv, NULL);
|
||||
(g_test_init) (&argc, &argv, NULL);
|
||||
|
||||
add_test ("/memorytexture/download_1x1", test_download_1x1);
|
||||
add_test ("/memorytexture/download_4x4", test_download_4x4);
|
||||
add_test ("/memorytexture/download_float_1x1", test_download_float_1x1);
|
||||
add_test ("/memorytexture/download_float_4x4", test_download_float_4x4);
|
||||
enum_class = g_type_class_ref (GDK_TYPE_MEMORY_FORMAT);
|
||||
|
||||
surface = gdk_surface_new_toplevel (gdk_display_get_default());
|
||||
gl_renderer = gsk_ngl_renderer_new ();
|
||||
if (!gsk_renderer_realize (gl_renderer, surface, NULL))
|
||||
for (format = 0; format < GDK_MEMORY_N_FORMATS; format++)
|
||||
{
|
||||
g_clear_object (&gl_renderer);
|
||||
g_clear_object (&surface);
|
||||
for (color = 0; color < N_COLORS; color++)
|
||||
{
|
||||
TestData *test_data = g_new (TestData, 1);
|
||||
char *test_name = g_strdup_printf ("/memorytexture/download_1x1/%s/%s",
|
||||
g_enum_get_value (enum_class, format)->value_nick,
|
||||
color_names[color]);
|
||||
test_data->format = format;
|
||||
test_data->color = color;
|
||||
g_test_add_data_func_full (test_name, test_data, test_download_1x1, g_free);
|
||||
g_free (test_name);
|
||||
|
||||
test_data = g_new (TestData, 1);
|
||||
test_name = g_strdup_printf ("/memorytexture/download_1x1_with_stride/%s/%s",
|
||||
g_enum_get_value (enum_class, format)->value_nick,
|
||||
color_names[color]);
|
||||
test_data->format = format;
|
||||
test_data->color = color;
|
||||
g_test_add_data_func_full (test_name, test_data, test_download_1x1_with_stride, g_free);
|
||||
g_free (test_name);
|
||||
|
||||
test_data = g_new (TestData, 1);
|
||||
test_name = g_strdup_printf ("/memorytexture/download_4x4/%s/%s",
|
||||
g_enum_get_value (enum_class, format)->value_nick,
|
||||
color_names[color]);
|
||||
test_data->format = format;
|
||||
test_data->color = color;
|
||||
g_test_add_data_func_full (test_name, test_data, test_download_4x4, g_free);
|
||||
g_free (test_name);
|
||||
|
||||
test_data = g_new (TestData, 1);
|
||||
test_name = g_strdup_printf ("/memorytexture/download_4x4_with_stride/%s/%s",
|
||||
g_enum_get_value (enum_class, format)->value_nick,
|
||||
color_names[color]);
|
||||
test_data->format = format;
|
||||
test_data->color = color;
|
||||
g_test_add_data_func_full (test_name, test_data, test_download_4x4_with_stride, g_free);
|
||||
g_free (test_name);
|
||||
}
|
||||
}
|
||||
|
||||
result = g_test_run ();
|
||||
|
||||
if (gl_renderer)
|
||||
{
|
||||
gsk_renderer_unrealize (gl_renderer);
|
||||
g_clear_object (&gl_renderer);
|
||||
}
|
||||
g_clear_object (&surface);
|
||||
|
||||
return result;
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user