Compare commits

..

27 Commits

Author SHA1 Message Date
Matthias Clasen
91e19bc36d jpeg: Set errors 2021-09-13 21:08:39 -04:00
Matthias Clasen
30d21ef791 png: loader set error 2021-09-13 21:08:34 -04:00
Matthias Clasen
57b419ebb1 texture: Add error enum 2021-09-13 21:08:27 -04:00
Matthias Clasen
9d303723b0 rendernodeparser: Avoid gdk_texture_new_for_pixbuf
We can just use gdk_texture_new_from_bytes here now.

Update affected test output.
2021-09-13 21:08:21 -04:00
Benjamin Otte
08bd1129ad !fixup gdk_pixbuf_save_to_png_bytes() documentation 2021-09-14 02:46:39 +02:00
Benjamin Otte
0cb0fc8317 testsuite: Add png and tiff methods
We encode the texture to a PNG or TIFF and then decode it again.
2021-09-14 02:46:39 +02:00
Benjamin Otte
874a3837d9 texture: Add gdk_texture_save_to_tiff_bytes() 2021-09-14 02:46:39 +02:00
Benjamin Otte
31fc5a5a54 !fixup tiff save can't fail 2021-09-14 02:46:39 +02:00
Benjamin Otte
40d81f5959 !fixup can't fail 2021-09-14 02:46:39 +02:00
Benjamin Otte
4fad97d8ab Redo tiff load/save without streams
Less code.
2021-09-14 02:46:39 +02:00
Julian Sparber
f1a8c95ca4 stack: Dispose children before emitting items-changed
This makes sure that the `GListModel` returned by
`gtk_stack_get_pages()` actually has the items removed before
`items-changed` is emitted.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4255
2021-09-14 02:46:39 +02:00
Matthias Clasen
65a1804f05 rendernodeparser: Use gdk_texture_save_to_png_bytes
Avoid cairo, and use our own api for saving png data.

Update affected test output.
2021-09-13 16:39:09 -04:00
Matthias Clasen
92873e62ed Add tests for the jpeg loader 2021-09-13 15:15:20 -04:00
Matthias Clasen
0f7c33f894 Load jpegs without gdk-pixbuf
Use our own loader for jpeg files.
2021-09-13 15:15:20 -04:00
Matthias Clasen
6a83d38e7b Add code to load jpegs
This lets us avoid gdk-pixbuf for loading
textures from the common image formats.

As a consequence, we are now linking against libjpeg.
2021-09-13 15:15:20 -04:00
Matthias Clasen
f89be80562 Add contentserializer tests for textures 2021-09-13 15:15:20 -04:00
Matthias Clasen
b66fa84161 Use our own loaders for content (de)serialization
Use our own loader to (de)serialiaze textures
to and from png and tiff.

We still fall back to gdk-pixbuf for handling all
the other image formats, and for pixbufs.
2021-09-13 15:15:20 -04:00
Matthias Clasen
ee7f2f9702 Add gdk_texture_save_to_tiff
This is a companion to gdk_texture_save_to_png, using
the tiff format, which will let us avoid lossy conversion
of HDR data, since we can store floating point data.
2021-09-13 15:15:20 -04:00
Matthias Clasen
900011808a Add tests for the tiff loader 2021-09-13 15:15:20 -04:00
Matthias Clasen
b8ee9873f3 Load tiffs without gdk-pixbuf
This will let us load floating point data, in
the future.
2021-09-13 15:15:20 -04:00
Matthias Clasen
0c9faea358 Add code to load and save tiff files
Add support for the tiff format, which is flexible
enough to handle all our memory texture formats
without loss.

As a consequence, we are now linking against libtiff.
2021-09-13 15:15:20 -04:00
Matthias Clasen
2568611a8c Add gdk_texture_save_to_png_bytes
Just expose what we already have available
internally, so e.g. tests can use it without
static linking.
2021-09-13 15:15:20 -04:00
Matthias Clasen
4c64111b5b Add tests for the png loader 2021-09-13 15:15:20 -04:00
Matthias Clasen
4f18a34dfa Save pngs without cairo
Use our own loader for pngs, which will allow
us to save e.g. 16-bit data in the future.
2021-09-13 15:15:20 -04:00
Matthias Clasen
bc0d315e6c Load pngs without gdk-pixbuf
Use our own loader for pngs, which will allow
us to get e.g. 16-bit data in the future.
2021-09-13 15:15:20 -04:00
Matthias Clasen
13d72eed2d Add code to load and save pngs
Using libpng instead of the lowest-common-denominator
gdk-pixbuf loader. This will allow us to load >8bit data,
and apply gamma and color correction in the future.
For now, this still just provides RGBA8 data.

As a consequence, we are now linking against libpng.
2021-09-13 15:15:20 -04:00
Matthias Clasen
7bafbeffcf Add gdk_texture_new_from_bytes
Add this new api, and make gdk_texture_new_from_file
a wrapper around it.
2021-09-13 14:03:15 -04:00
97 changed files with 1817 additions and 2475 deletions

View File

@@ -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:

View File

@@ -53,7 +53,6 @@ RUN dnf -y install \
libpng-devel \
librsvg2 \
libselinux-devel \
libtiff-devel \
libubsan \
libXcomposite-devel \
libXcursor-devel \

View File

@@ -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
-------------

View File

@@ -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),

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);

View File

@@ -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);

View File

@@ -659,52 +659,84 @@ pixbuf_deserializer (GdkContentDeserializer *deserializer)
static void
texture_deserializer_finish (GObject *source,
GAsyncResult *result,
gpointer deserializer)
GAsyncResult *res,
gpointer data)
{
GOutputStream *stream = G_OUTPUT_STREAM (source);
GBytes *bytes;
GdkContentDeserializer *deserializer = GDK_CONTENT_DESERIALIZER (source);
GdkTexture *texture;
GValue *value;
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);
texture = g_task_propagate_pointer (G_TASK (res), &error);
if (texture == NULL)
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
g_value_take_object (gdk_content_deserializer_get_value (deserializer), texture);
value = gdk_content_deserializer_get_value (deserializer);
g_value_take_object (value, texture);
gdk_content_deserializer_return_success (deserializer);
}
static GBytes *
read_all_data (GInputStream *source,
GError **error)
{
GOutputStream *output;
gssize size;
GBytes *bytes;
output = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
size = g_output_stream_splice (output, source, 0, NULL, error);
if (size == -1)
{
g_object_unref (output);
return NULL;
}
g_output_stream_close (output, NULL, NULL);
bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output));
g_object_unref (output);
return bytes;
}
static void
deserialize_texture_in_thread (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
GdkContentDeserializer *deserializer = source_object;
GBytes *bytes;
GError *error = NULL;
GdkTexture *texture = NULL;
bytes = read_all_data (gdk_content_deserializer_get_input_stream (deserializer), &error);
if (bytes)
{
texture = gdk_texture_new_from_bytes (bytes, &error);
g_bytes_unref (bytes);
}
if (texture)
g_task_return_pointer (task, texture, g_object_unref);
else
g_task_return_error (task, error);
}
static void
texture_deserializer (GdkContentDeserializer *deserializer)
{
GOutputStream *output;
GTask *task;
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);
task = g_task_new (deserializer,
gdk_content_deserializer_get_cancellable (deserializer),
texture_deserializer_finish,
NULL);
g_task_run_in_thread (task, deserialize_texture_in_thread);
g_object_unref (task);
}
static void
@@ -920,17 +952,12 @@ init (void)
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 ();
@@ -963,9 +990,8 @@ init (void)
mimes = gdk_pixbuf_format_get_mime_types (fmt);
for (m = mimes; *m; m++)
{
/* Turning pngs, jpegs and tiffs into textures is handled above */
/* Turning pngs 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,

View File

@@ -28,7 +28,6 @@
#include "gdkrgba.h"
#include "loaders/gdkpngprivate.h"
#include "loaders/gdktiffprivate.h"
#include "loaders/gdkjpegprivate.h"
#include "gdkmemorytextureprivate.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -689,8 +688,6 @@ serialize_texture_in_thread (GTask *task,
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);
@@ -699,21 +696,28 @@ serialize_texture_in_thread (GTask *task,
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);
if (bytes)
{
GInputStream *input = g_memory_input_stream_new_from_bytes (bytes);
gssize spliced;
result = spliced != -1;
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;
}
else
g_set_error_literal (&error,
G_IO_ERROR, G_IO_ERROR_FAILED,
"Saving png failed");
if (result)
g_task_return_boolean (task, result);
@@ -963,11 +967,6 @@ init (void)
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 */
@@ -1002,10 +1001,9 @@ init (void)
mimes = gdk_pixbuf_format_get_mime_types (fmt);
for (m = mimes; *m; m++)
{
/* Turning textures into pngs, tiffs or jpegs is handled above */
/* Turning textures into pngs or tiffs is handled above */
if (!g_str_equal (name, "png") &&
!g_str_equal (name, "tiff") &&
!g_str_equal (name, "jpeg"))
!g_str_equal (name, "tiff"))
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
*m,
pixbuf_serializer,

View File

@@ -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,

View File

@@ -108,37 +108,6 @@ gdk_gl_texture_run (GdkGLTexture *self,
while (g_atomic_int_get (&invoke.spinlock) == 0);
}
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))
{
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);
}
else
{
glGetTexImage (GL_TEXTURE_2D,
0,
gl_format,
gl_type,
data);
}
}
static void
gdk_gl_texture_do_download_texture (gpointer texture_,
gpointer result_)
@@ -216,10 +185,11 @@ gdk_gl_texture_do_download_texture (gpointer texture_,
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);
glGetTexImage (GL_TEXTURE_2D,
0,
gl_format,
gl_type,
data);
bytes = g_bytes_new_take (data, stride * texture->height);
*result = gdk_memory_texture_new (texture->width,
@@ -260,6 +230,7 @@ gdk_gl_texture_do_download (gpointer texture,
#error "Unknown byte order for gdk_gl_texture_download()"
#endif
data);
}
static void
@@ -302,6 +273,8 @@ gdk_gl_texture_download_float (GdkTexture *texture,
gsize stride)
{
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
int width, height, y;
float *copy;
if (self->saved)
{
@@ -309,14 +282,22 @@ gdk_gl_texture_download_float (GdkTexture *texture,
return;
}
if (gdk_gl_context_get_use_es (self->context) ||
stride != texture->width * 4)
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
if (stride == width * 4)
{
GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download_float (texture, data, stride);
gdk_gl_texture_run (self, gdk_gl_texture_do_download_float, data);
return;
}
gdk_gl_texture_run (self, gdk_gl_texture_do_download_float, data);
copy = g_new (float, width * height * 4);
gdk_gl_texture_run (self, gdk_gl_texture_do_download_float, copy);
for (y = 0; y < height; y++)
memcpy (data + y * stride, copy + y * 4 * width, 4 * width);
g_free (copy);
}
static void

View File

@@ -603,7 +603,7 @@ convert_rgba16_to_float (float *dest, const guchar *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;
dest[3] = 1.0;
}
static inline void

View File

@@ -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

View File

@@ -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,7 +41,6 @@
#include "gdktextureprivate.h"
#include "gdkinternals.h"
#include "gdkintl.h"
#include "gdkmemorytextureprivate.h"
#include "gdkpaintable.h"
#include "gdksnapshot.h"
@@ -114,110 +113,9 @@ 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))
@@ -456,23 +354,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;
}
@@ -512,59 +405,6 @@ gdk_texture_new_from_file (GFile *file,
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)
return NULL;
texture = gdk_texture_new_for_pixbuf (pixbuf);
g_object_unref (pixbuf);
return texture;
}
/**
* gdk_texture_new_from_bytes:
@@ -586,59 +426,52 @@ GdkTexture *
gdk_texture_new_from_bytes (GBytes *bytes,
GError **error)
{
GdkTexture *texture;
GError *internal_error = NULL;
const char *data;
gsize size;
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;
data = g_bytes_get_data (bytes, &size);
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))
if (size > strlen (PNG_SIGNATURE) &&
memcmp (data, PNG_SIGNATURE, strlen (PNG_SIGNATURE)) == 0)
{
g_propagate_error (error, internal_error);
return NULL;
return gdk_load_png (bytes, error);
}
else if ((size > strlen (TIFF_SIGNATURE1) &&
memcmp (data, TIFF_SIGNATURE1, strlen (TIFF_SIGNATURE1)) == 0) ||
(size > strlen (TIFF_SIGNATURE2) &&
memcmp (data, TIFF_SIGNATURE2, strlen (TIFF_SIGNATURE2)) == 0))
{
return gdk_load_tiff (bytes, error);
}
else if (size > strlen (JPEG_SIGNATURE) &&
memcmp (data, JPEG_SIGNATURE, strlen (JPEG_SIGNATURE)) == 0)
{
return gdk_load_jpeg (bytes, error);
}
else
{
GInputStream *stream;
GdkPixbuf *pixbuf;
stream = g_memory_input_stream_new_from_bytes (bytes);
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, error);
g_object_unref (stream);
if (pixbuf)
{
GdkTexture *texture;
texture = gdk_texture_new_for_pixbuf (pixbuf);
g_object_unref (pixbuf);
return texture;
}
}
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;
return NULL;
}
/**
@@ -838,7 +671,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
* use gdk_texture_save_to_png_bytes() or look into the
* gdk-pixbuf library.
*
* Returns: %TRUE if saving succeeded, %FALSE on failure.
@@ -868,7 +701,7 @@ gdk_texture_save_to_png (GdkTexture *texture,
* @texture: a `GdkTexture`
*
* Store the given @texture in memory as a PNG file.
* Use [ctor@Gdk.Texture.new_from_bytes] to read it back.
* Use 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.
@@ -878,7 +711,7 @@ gdk_texture_save_to_png (GdkTexture *texture,
* 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]
* might also want to consider gdk_texture_save_to_tiff_bytes()
* instead.
*
* Returns: a newly allocated `GBytes` containing PNG data
@@ -930,8 +763,7 @@ gdk_texture_save_to_tiff (GdkTexture *texture,
* @texture: a `GdkTexture`
*
* Store the given @texture in memory as a TIFF file.
*
* Use [ctor@Gdk.Texture.new_from_bytes] to read it back.
* Use 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
@@ -940,7 +772,7 @@ gdk_texture_save_to_tiff (GdkTexture *texture,
*
* 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].
* use gdk_texture_save_to_png_bytes().
*
* Returns: a newly allocated `GBytes` containing TIFF data
*

View File

@@ -45,22 +45,17 @@ GQuark gdk_texture_error_quark (void);
/**
* GdkTextureError:
* @GDK_TEXTURE_ERROR_TOO_LARGE: Not enough memory to handle this image
* @GDK_TEXTURE_ERROR_INSUFFICIENT_MEMORY: 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
* @GDK_TEXTURE_ERROR_UNSUPPORTED: 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_INSUFFICIENT_MEMORY,
GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT,
GDK_TEXTURE_ERROR_UNSUPPORTED_FORMAT,
GDK_TEXTURE_ERROR_UNSUPPORTED,
} GdkTextureError;
GDK_AVAILABLE_IN_ALL
@@ -74,9 +69,6 @@ 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);

View File

@@ -35,8 +35,9 @@ struct _GdkTextureClass {
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 */

View File

@@ -19,10 +19,8 @@
#include "gdkjpegprivate.h"
#include "gdkintl.h"
#include "gdktexture.h"
#include "gdkmemorytextureprivate.h"
#include <jpeglib.h>
#include <jerror.h>
#include <setjmp.h>
@@ -55,8 +53,10 @@ fatal_error_handler (j_common_ptr cinfo)
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);
cinfo->err->msg_code == JERR_OUT_OF_MEMORY
? GDK_TEXTURE_ERROR_INSUFFICIENT_MEMORY
: GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
"Error interpreting JPEG image file (%s)", buffer);
siglongjmp (errmgr->setjmp_buffer, 1);
@@ -70,97 +70,7 @@ output_message_handler (j_common_ptr cinfo)
}
/* }}} */
/* {{{ 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 */
/* {{{ Public API */
GdkTexture *
gdk_load_jpeg (GBytes *input_bytes,
@@ -168,12 +78,13 @@ gdk_load_jpeg (GBytes *input_bytes,
{
struct jpeg_decompress_struct info;
struct error_handler_data jerr;
guint width, height, stride;
struct jpeg_error_mgr err;
int width, height;
int size;
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;
@@ -186,6 +97,7 @@ gdk_load_jpeg (GBytes *input_bytes,
return NULL;
}
info.err = jpeg_std_error (&err);
jpeg_create_decompress (&info);
jpeg_mem_src (&info,
@@ -198,132 +110,37 @@ gdk_load_jpeg (GBytes *input_bytes,
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;
}
size = width * height * 3;
data = g_try_malloc_n (width * 3, height);
if (!data)
{
g_set_error (error,
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_TOO_LARGE,
_("Not enough memory for image size %ux%u"), width, height);
g_set_error_literal (error,
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_INSUFFICIENT_MEMORY,
"Not enough memory to load jpeg");
jpeg_destroy_decompress (&info);
return NULL;
}
while (info.output_scanline < info.output_height)
{
row[0] = (unsigned char *)(&data[stride * info.output_scanline]);
row[0] = (unsigned char *)(&data[3 *info.output_width * 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);
bytes = g_bytes_new_take (data, size);
texture = gdk_memory_texture_new (width, height,
format,
bytes, stride);
GDK_MEMORY_R8G8B8,
bytes, width * 3);
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: */

View File

@@ -26,18 +26,4 @@
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

View File

@@ -19,10 +19,9 @@
#include "gdkpngprivate.h"
#include "gdkintl.h"
#include "gdkmemorytextureprivate.h"
#include "gdktexture.h"
#include "gdktextureprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gsk/ngl/fp16private.h"
#include <png.h>
#include <stdio.h>
@@ -33,105 +32,13 @@
* 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)
flip_02 (guchar *data,
int width,
int height,
int stride)
{
gsize x, y;
@@ -139,157 +46,37 @@ unpremultiply (guchar *data,
{
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;
}
guchar tmp;
tmp = data[x * 4];
data[x * 4] = data[x * 4 + 2];
data[x * 4 + 2] = tmp;
}
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;
}
}
static void
convert_float_to_16bit_inplace (float *src,
int width,
int height)
{
gsize x, y;
guint16 *dest = (guint16 *)src;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
dest[4 * x ] = (guint16) CLAMP(65536.f * src[x * 4 ], 0.f, 65535.f);
dest[4 * x + 1] = (guint16) CLAMP(65536.f * src[x * 4 + 1], 0.f, 65535.f);
dest[4 * x + 2] = (guint16) CLAMP(65536.f * src[x * 4 + 2], 0.f, 65535.f);
dest[4 * x + 3] = (guint16) CLAMP(65536.f * src[x * 4 + 3], 0.f, 65535.f);
}
dest += width * 4;
src += width * 4;
}
}
/* }}} */
/* {{{ Public API */
@@ -297,157 +84,63 @@ 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;
png_image image = { NULL, PNG_IMAGE_VERSION, 0, };
gsize size;
gsize stride;
guchar *buffer;
GdkTexture *texture;
int bpp;
GBytes *out_bytes;
io.data = (guchar *)g_bytes_get_data (bytes, &io.size);
io.position = 0;
png_image_begin_read_from_memory (&image,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes));
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))
if (PNG_IMAGE_FAILED (image))
{
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"));
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED,
"Failed to parse png image (%s)", image.message);
png_image_free (&image);
return NULL;
}
switch (color_type)
image.format = PNG_FORMAT_RGBA;
stride = PNG_IMAGE_ROW_STRIDE (image);
size = PNG_IMAGE_BUFFER_SIZE (image, stride);
buffer = g_try_malloc (size);
if (!buffer)
{
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 ();
g_set_error_literal (error,
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_INSUFFICIENT_MEMORY,
"Not enough memory to load png");
png_image_free (&image);
return NULL;
}
bpp = gdk_memory_format_bytes_per_pixel (format);
stride = width * bpp;
if (stride % 8)
stride += 8 - stride % 8;
png_image_finish_read (&image, NULL, buffer, stride, NULL);
buffer = g_try_malloc_n (height, stride);
row_pointers = g_try_malloc_n (height, sizeof (char *));
if (!buffer || !row_pointers)
if (PNG_IMAGE_FAILED (image))
{
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);
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED,
"Failed to parse png image (%s)", image.message);
png_image_free (&image);
return NULL;
}
for (int i = 0; i < height; i++)
row_pointers[i] = &buffer[i * stride];
if (image.format & PNG_FORMAT_FLAG_LINEAR)
stride *= 2;
png_read_image (png, row_pointers);
png_read_end (png, info);
out_bytes = g_bytes_new_take (buffer, size);
if (format == GDK_MEMORY_R16G16B16A16_PREMULTIPLIED)
premultiply_16bit (buffer, width, height, stride);
texture = gdk_memory_texture_new (image.width, image.height,
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
out_bytes, 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);
png_image_free (&image);
return texture;
}
@@ -455,57 +148,71 @@ gdk_load_png (GBytes *bytes,
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;
png_image image = { NULL, PNG_IMAGE_VERSION, 0, };
int stride;
const guchar *data;
guchar *new_data = NULL;
png_alloc_size_t size;
gpointer buffer;
GdkTexture *memory_texture;
GdkMemoryFormat format;
int png_format;
int depth;
gboolean result G_GNUC_UNUSED;
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
image.width = gdk_texture_get_width (texture);
image.height = gdk_texture_get_height (texture);
mtexture = gdk_texture_download_texture (texture);
format = gdk_memory_texture_get_format (GDK_MEMORY_TEXTURE (mtexture));
memory_texture = gdk_texture_download_texture (texture);
format = gdk_memory_texture_get_format (GDK_MEMORY_TEXTURE (memory_texture));
switch (format)
{
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
data = gdk_memory_texture_get_data (GDK_MEMORY_TEXTURE (memory_texture));
stride = gdk_memory_texture_get_stride (GDK_MEMORY_TEXTURE (memory_texture));
image.format = PNG_FORMAT_RGBA;
break;
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;
stride = image.width * 4;
new_data = g_malloc (stride * image.height);
gdk_texture_download (memory_texture, new_data, stride);
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
flip_02 (new_data, image.width, image.height, stride);
#endif
data = new_data;
image.format = PNG_FORMAT_RGBA;
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);
data = gdk_memory_texture_get_data (GDK_MEMORY_TEXTURE (memory_texture));
stride = gdk_memory_texture_get_stride (GDK_MEMORY_TEXTURE (memory_texture));
image.format = PNG_FORMAT_LINEAR_RGB;
break;
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
stride = width * 8;
depth = 16;
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
data = gdk_memory_texture_get_data (GDK_MEMORY_TEXTURE (memory_texture));
stride = gdk_memory_texture_get_stride (GDK_MEMORY_TEXTURE (memory_texture));
image.format = PNG_FORMAT_LINEAR_RGB_ALPHA;
break;
case GDK_MEMORY_R16G16B16_FLOAT:
case GDK_MEMORY_R32G32B32_FLOAT:
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
/* This isn't very efficient */
new_data = g_malloc (image.width * image.height * 16);
gdk_texture_download_float (memory_texture, (float *)new_data, image.width * 16);
convert_float_to_16bit_inplace ((float *)new_data, image.width, image.height);
data = new_data;
stride = image.width * 8;
image.format = PNG_FORMAT_LINEAR_RGB_ALPHA;
break;
case GDK_MEMORY_N_FORMATS:
@@ -513,54 +220,21 @@ gdk_save_png (GdkTexture *texture)
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;
if (image.format & PNG_FORMAT_FLAG_LINEAR)
stride /= 2;
info = png_create_info_struct (png);
if (!info)
{
png_destroy_read_struct (&png, NULL, NULL);
return NULL;
}
png_image_write_get_memory_size (image, size, FALSE, data, stride, NULL);
if (sigsetjmp (png_jmpbuf (png), 1))
{
g_free (data);
g_free (io.data);
png_destroy_read_struct (&png, &info, NULL);
return NULL;
}
buffer = g_malloc (size);
result = png_image_write_to_memory (&image, buffer, &size, FALSE, data, stride, NULL);
png_set_write_fn (png, &io, png_write_func, png_flush_func);
g_assert (result);
png_set_IHDR (png, info, width, height, depth,
png_format,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
g_object_unref (memory_texture);
png_image_free (&image);
g_free (new_data);
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);
return g_bytes_new_take (buffer, size);
}
/* }}} */

View File

@@ -28,16 +28,4 @@ GdkTexture *gdk_load_png (GBytes *bytes,
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

View File

@@ -19,11 +19,9 @@
#include "gdktiffprivate.h"
#include "gdkintl.h"
#include "gdkmemorytextureprivate.h"
#include "gdktexture.h"
#include "gdktextureprivate.h"
#include "gdkmemorytextureprivate.h"
#include <tiffio.h>
/* Our main interest in tiff as an image format is that it is
@@ -70,14 +68,6 @@ tiff_io_error (const char *module,
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,
@@ -86,9 +76,6 @@ tiff_io_read (thandle_t handle,
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);
@@ -102,6 +89,7 @@ tiff_io_no_write (thandle_t handle,
tdata_t buffer,
tsize_t size)
{
errno = EINVAL;
return (tsize_t) -1;
}
@@ -112,8 +100,7 @@ tiff_io_write (thandle_t handle,
{
TiffIO *io = (TiffIO *) handle;
if (io->position > io->size ||
io->size - io->position < size)
if (io->size - io->position < size)
{
io->size = io->position + size;
io->data = g_realloc (io->data, io->size);
@@ -135,6 +122,7 @@ tiff_io_seek (thandle_t handle,
switch (whence)
{
default:
errno = EINVAL;
return -1;
case SEEK_SET:
break;
@@ -146,7 +134,16 @@ tiff_io_seek (thandle_t handle,
break;
}
if (offset < 0)
return -1;
{
errno = EINVAL;
return -1;
}
if (offset > io->size)
{
/* Linux apparently can do that */
errno = EINVAL;
return -1;
}
io->position = offset;
@@ -210,7 +207,7 @@ tiff_open_write (GBytes **result)
return TIFFClientOpen ("GTK-write", "w",
(thandle_t) io,
tiff_io_no_read,
tiff_io_read,
tiff_io_write,
tiff_io_seek,
tiff_io_close,
@@ -375,8 +372,8 @@ load_fallback (TIFF *tif,
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_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to load RGB data from TIFF file");
g_free (data);
return NULL;
}
@@ -469,15 +466,7 @@ gdk_load_tiff (GBytes *input_bytes,
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;
}
data = g_new (guchar, height * stride);
line = data;
for (int y = 0; y < height; y++)
@@ -485,8 +474,8 @@ gdk_load_tiff (GBytes *input_bytes,
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);
G_IO_ERROR, G_IO_ERROR_FAILED,
"Reading data failed at row %d", y);
TIFFClose (tif);
g_free (data);
return NULL;

View File

@@ -29,18 +29,4 @@ GdkTexture *gdk_load_tiff (GBytes *bytes,
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

View File

@@ -204,9 +204,6 @@ gdk_deps = [
platform_gio_dep,
pangocairo_dep,
vulkan_dep,
png_dep,
tiff_dep,
jpeg_dep,
]
if profiler_enabled
@@ -262,7 +259,7 @@ endif
libgdk = static_library('gdk',
sources: [gdk_sources, gdk_backends_gen_headers, gdkconfig],
dependencies: gdk_deps + [libgtk_css_dep],
dependencies: gdk_deps + [libgtk_css_dep, png_dep, tiff_dep, jpeg_dep],
link_with: [libgtk_css],
include_directories: [confinc, gdkx11_inc, wlinc],
c_args: libgdk_c_args + common_cflags,

View File

@@ -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,

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -85,18 +85,18 @@ 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);
g_bytes_unref (bytes);
}
else
{
texture = NULL;
}
}
else
{
@@ -795,11 +795,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 +2329,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 +2359,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 +2368,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)

View File

@@ -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

View File

@@ -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
*

View File

@@ -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

View File

@@ -1131,18 +1131,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 +1164,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);
}
}

View File

@@ -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);

View File

@@ -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));

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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,

View File

@@ -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,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -210,6 +210,7 @@
#include "gtkbuilderprivate.h"
#include "gdkpixbufutilsprivate.h"
#include "gtkbuildableprivate.h"
#include "gtkbuilderlistitemfactory.h"
#include "gtkbuilderscopeprivate.h"
@@ -225,6 +226,7 @@
#include "gtktypebuiltins.h"
#include "gtkicontheme.h"
#include "gtkiconthemeprivate.h"
#include "gdkpixbufutilsprivate.h"
#include "gtkdebug.h"
@@ -2294,63 +2296,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 +2344,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);

View File

@@ -250,9 +250,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,

View File

@@ -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),

View File

@@ -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
{

View File

@@ -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)

View File

@@ -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

View File

@@ -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,

View File

@@ -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;
}
/**

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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>

View File

@@ -499,6 +499,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',
]

View File

@@ -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 boxs model to associate with strings from the "
#| "entry if the combo was created with #GtkComboBox:has-entry = %TRUE"
msgid ""
"The column in the combo boxs 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"

View File

@@ -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;
}

View File

@@ -13,9 +13,7 @@ typedef enum {
TEXTURE_METHOD_GL,
TEXTURE_METHOD_GL_RELEASED,
TEXTURE_METHOD_PNG,
TEXTURE_METHOD_PNG_PIXBUF,
TEXTURE_METHOD_TIFF,
TEXTURE_METHOD_TIFF_PIXBUF,
N_TEXTURE_METHODS
} TextureMethod;
@@ -463,26 +461,6 @@ create_texture (GdkMemoryFormat format,
}
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);
@@ -494,26 +472,6 @@ create_texture (GdkMemoryFormat format,
}
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 ();
@@ -650,7 +608,7 @@ add_test (const char *name,
{
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" };
const char *method_names[N_TEXTURE_METHODS] = { "local", "gl", "gl-released", "png", "tiff" };
char *test_name = g_strdup_printf ("%s/%s/%s",
name,
g_enum_get_value (enum_class, format)->value_nick,

View File

@@ -10,39 +10,36 @@ clipboard_client = executable('clipboard-client',
install_dir: testexecdir)
tests = [
{ 'name': 'array' },
{ 'name': 'cairo' },
{ 'name': 'clipboard', 'parallel': false, },
{ 'name': 'contentformats' },
{ 'name': 'contentserializer' },
{ 'name': 'cursor' },
{ 'name': 'display' },
{ 'name': 'displaymanager' },
{ 'name': 'encoding' },
{ 'name': 'keysyms' },
{ 'name': 'memorytexture' },
{ 'name': 'pixbuf' },
{ 'name': 'rectangle' },
{ 'name': 'rgba' },
{ 'name': 'seat' },
{ 'name': 'texture' },
{ 'name': 'texture-threads' },
'array',
'cairo',
'clipboard',
'contentformats',
'contentserializer',
'cursor',
'display',
'displaymanager',
'encoding',
'keysyms',
'memorytexture',
'pixbuf',
'rectangle',
'rgba',
'seat',
'texture',
'texture-threads',
]
foreach t : tests
test_name = t.get('name')
test_exe = executable(test_name,
sources: '@0@.c'.format(test_name),
test_exe = executable(t, '@0@.c'.format(t),
c_args: common_cflags,
dependencies: libgtk_dep,
install: get_option('install-tests'),
install_dir: testexecdir,
)
test(test_name, test_exe,
test(t, test_exe,
args: [ '--tap', '-k' ],
protocol: 'tap',
is_parallel: t.get('parallel', false),
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
@@ -79,10 +76,9 @@ endforeach
if get_option('install-tests')
foreach t : tests
test_name = t.get('name')
test_cdata = configuration_data()
test_cdata.set('testexecdir', testexecdir)
test_cdata.set('test', test_name)
test_cdata.set('test', t)
configure_file(input: 'gdk.test.in',
output: '@0@.test'.format(t),
configuration: test_cdata,

View File

@@ -11,7 +11,6 @@ ensure_texture_access (GdkTexture *texture)
guint32 pixel = 0;
float float_pixel[4] = { INFINITY, INFINITY, INFINITY, INFINITY };
g_test_message ("Checking texture access in thread %p...", g_thread_self());
/* Just to be sure */
g_assert_cmpint (gdk_texture_get_width (texture), ==, 1);
g_assert_cmpint (gdk_texture_get_height (texture), ==, 1);
@@ -26,8 +25,6 @@ ensure_texture_access (GdkTexture *texture)
g_assert_cmpfloat (float_pixel[1], ==, 0.0);
g_assert_cmpfloat (float_pixel[2], ==, 0.0);
g_assert_cmpfloat (float_pixel[3], ==, 1.0);
g_test_message ("...done in thread %p", g_thread_self());
}
static void
@@ -46,18 +43,8 @@ texture_download_thread (GTask *task,
gpointer unused,
GCancellable *cancellable)
{
g_test_message ("Starting thread %p.", g_thread_self());
/* not sure this can happen, but if it does, we
* should clear_current() here. */
g_assert_null (gdk_gl_context_get_current ());
ensure_texture_access (GDK_TEXTURE (texture));
/* Makes sure the GL context is still NULL, because all the
* GL stuff should have happened in the main thread. */
g_assert_null (gdk_gl_context_get_current ());
g_test_message ("Returning from thread %p.", g_thread_self());
g_task_return_boolean (task, TRUE);
}
@@ -89,26 +76,20 @@ texture_threads (void)
ensure_texture_access (texture);
g_assert_nonnull (gdk_gl_context_get_current ());
/* 4. Acquire the main loop, so the run_in_thread() doesn't
* try to acquire it if it manages to outrace this thread.
*/
g_assert_true (g_main_context_acquire (NULL));
/* 5. Run a thread trying to download the texture */
/* 4. Run a thread trying to download the texture */
loop = g_main_loop_new (NULL, TRUE);
task = g_task_new (texture, NULL, texture_download_done, loop);
g_task_run_in_thread (task, texture_download_thread);
g_clear_object (&task);
/* 6. Run the main loop waiting for the thread to return */
/* 5. Run the main loop waiting for the thread to return */
g_main_loop_run (loop);
/* 7. All good */
/* 6. All good */
gsk_renderer_unrealize (gl_renderer);
g_clear_pointer (&loop, g_main_loop_unref);
g_clear_object (&gl_renderer);
g_clear_object (&surface);
g_main_context_release (NULL);
}
int

View File

@@ -99,16 +99,16 @@ get_output_file (const char *file,
}
static void
save_image (GdkTexture *texture,
const char *test_name,
const char *extension)
save_image (cairo_surface_t *surface,
const char *test_name,
const char *extension)
{
char *filename = get_output_file (test_name, ".node", extension);
gboolean result;
int status;
g_print ("Storing test result image at %s\n", filename);
result = gdk_texture_save_to_png (texture, filename);
g_assert_true (result);
status = cairo_surface_write_to_png (surface, filename);
g_assert_true (status == CAIRO_STATUS_SUCCESS);
g_free (filename);
}
@@ -149,8 +149,10 @@ static const GOptionEntry options[] = {
int
main (int argc, char **argv)
{
GdkTexture *reference_texture;
GdkTexture *rendered_texture;
cairo_surface_t *reference_surface = NULL;
cairo_surface_t *rendered_surface = NULL;
cairo_surface_t *diff_surface = NULL;
GdkTexture *texture;
GskRenderer *renderer;
GdkSurface *window;
GskRenderNode *node;
@@ -160,8 +162,6 @@ main (int argc, char **argv)
GError *error = NULL;
GOptionContext *context;
(g_test_init) (&argc, &argv, NULL);
context = g_option_context_new ("NODE REF - run GSK node tests");
g_option_context_add_main_entries (context, options, NULL);
g_option_context_set_ignore_unknown_options (context, TRUE);
@@ -213,36 +213,43 @@ main (int argc, char **argv)
}
/* Render the .node file and download to cairo surface */
rendered_texture = gsk_renderer_render_texture (renderer, node, NULL);
g_assert_nonnull (rendered_texture);
texture = gsk_renderer_render_texture (renderer, node, NULL);
g_assert_nonnull (texture);
rendered_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 (rendered_surface),
cairo_image_surface_get_stride (rendered_surface));
cairo_surface_mark_dirty (rendered_surface);
/* Load the given reference png file */
reference_texture = gdk_texture_new_from_filename (png_file, &error);
if (reference_texture == NULL)
reference_surface = cairo_image_surface_create_from_png (png_file);
if (cairo_surface_status (reference_surface))
{
g_print ("Error loading reference surface: %s\n", error->message);
g_clear_error (&error);
g_print ("Error loading reference surface: %s\n",
cairo_status_to_string (cairo_surface_status (reference_surface)));
success = FALSE;
}
else
{
GdkTexture *diff_texture;
/* Now compare the two */
diff_texture = reftest_compare_textures (rendered_texture, reference_texture);
diff_surface = reftest_compare_surfaces (rendered_surface, reference_surface);
if (diff_texture)
if (diff_surface)
{
save_image (diff_texture, node_file, ".diff.png");
g_object_unref (diff_texture);
save_image (diff_surface, node_file, ".diff.png");
cairo_surface_destroy (diff_surface);
success = FALSE;
}
}
save_image (rendered_texture, node_file, ".out.png");
save_image (rendered_surface, node_file, ".out.png");
g_object_unref (reference_texture);
g_object_unref (rendered_texture);
cairo_surface_destroy (reference_surface);
cairo_surface_destroy (rendered_surface);
g_object_unref (texture);
gsk_render_node_unref (node);

View File

@@ -1,5 +0,0 @@
border {
colors: red;
outline: 0 0 20 20;
widths: 0 10 10 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 B

View File

@@ -1,15 +0,0 @@
opacity {
child: transform {
transform: translate(15, 15);
child: container {
color {
bounds: -15 -15 30 30;
color: rgb(0,0,255);
}
color {
bounds: -10 -10 20 20;
color: rgb(255,0,0);
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 B

View File

@@ -23,7 +23,6 @@ compare_render_tests = [
'blend-difference',
'blend-invisible-child',
'blend-normal',
'border-bottom-right',
'borders-rotated',
'borders-scaled',
'clip-coordinates-2d',
@@ -63,7 +62,6 @@ compare_render_tests = [
'issue-3615',
'nested-rounded-clips',
'opacity_clip',
'opacity-overdraw',
'opacity-overlapping-children',
'outset_shadow_offset_both',
'outset_shadow_offset_x',
@@ -94,6 +92,7 @@ informative_render_tests = [
renderers = [
# name exclude term
[ 'gl', '-ngl' ],
[ 'ngl', '' ],
[ 'broadway', '-3d' ],
[ 'cairo', '-3d' ],

View File

@@ -1,6 +1,6 @@
texture {
bounds: 0 0 50 50;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAKUlEQVQYlWP8z3DmPwMaYGQwYUQX\
Y0IXwAUGUCGGoxkYGBiweXAoeAYAz44F3e3U1xUAAAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAClJREFUGJVj\
/M9w5j8DGmBkMGFEF2NCF8AFBlAhhqMZGBgYsHlwKHgGAM+OBd3t1NcVAAAAAElFTkSuQmCC\
");
}

View File

@@ -39,129 +39,129 @@ transform {
offset: 0.180392 0.203922 0.211765 0;
child: texture {
bounds: 1068.6 0 256 256;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAbAUlEQVR4nO2deZRfRZXHP+nOvhBI\
MBDWDAFMwBDWyCDIDoNA2B13FBhAZQTEASIiAZ1RBBf0jA6KolFU8CCIiBoggLJEAwFDWBICISGb\
IQsJWZpsPX/cbtJp+vf7vaWqbr337uec7+mcpPPqVr2qeu9V3boXDMMwDMMwDMMwDMOoAs3aBhiG\
B44CHgOOAHYBugGLgI2KNhmGEYhHgdZOehN4EBgPHIhMCoZhlIwTeOfg70qLgQnAyUAvFUsNw3BK\
N2AKySaAjnoD+KWCvYYRJQcANwF/A7ZStiUNp5F+8LdrlYK9hhEN/YDPAM+x5cAoypOxG/APsk8A\
i8KbbBj67AR8A1hG7cFxoZp1yRlL9sHfCswKb7Jh6LEr8pq/lsaDowXYX8fMxDxGvgng6fAmG0Z4\
dgJ+DKwn3QB5CRioYG8SjiTf4G8F/hrcasMIyNbA9cAasg+S24JbnYyJ5J8A7gtutWEE5JPkHySt\
wEcD292I/YBN5K/Xz0Mbbhgh2RM3E8AbwLCwptflTtzU66bQhhtGSLoh3m8uBsujxHGOZCTi3++i\
Tl8KbHsUNGkbYASjFZjs6FrvA8Y5ulYersJdH17q6DqGES3jcPO0bAXWAWPCmr8Fw0m/k1FPHwxr\
fhzYG0C1eMLhtXogXoIDHF4zDVcC3R1e73WH1zKMKOmLOPW4emq2ArcErYGwE/BWRntraXTQGhiG\
Eo/gduC0IodwQvI9h7a3a6egNTAMJa7F/eBZBuwcyP5huH+LaQX6BLLfMFQ5AveDpxXxxguxpjTB\
g+1rAthtGFHQi3zuwPV0lWfbR+Fu37+j5nq22zCiYhJ+JoCNwDEe7b7Xk92VPQnochvFKA4PISfo\
XNOEvKLvB/yzwe82A9shi2/bt6kbcmipCdnj/ycwH3gFOb58ogebAZZ7um702ARQTR7yeO2hyKnB\
45BDOk3ACCQS714dNIw43ImhwuHAbAKoJn8HViNhwHxwNHJIpw9wMPHGEWinRdsALWwCqCbrgMeB\
Yz2WcarHa7tmrbYBWpgrcHXx+RlQNCr7BmATQHWxCWAz9gZgVI4nkXRZhpwrqCSxrMIa4dmEbAUO\
1zYkAkYjC5VPUbHPAZsAqs1wxDW46vQEDgXORxbGn0YWSmOgCfF/WEmFtysNPxyPH8+6omsx8Gl0\
P5HfhcQ8mN1m0/3K9hglZCB+fOvLosnAvplbNxuHAL+g6xOPvs9aGBVkGvoDLWZtBG7Gb5LUJiRN\
+eMNbFmPfKoYhjNuRn+QFUGzgfdmbONaDAT+CzmNmNSOucBgx3YYFeVQYAH6g6soWocM2G5ZGrsD\
uwHfQRb2sthxjwMbjIpzPu7j6lVFDyCnF9NyAHJa0kU0449nKN8w6IdE89UeREXXa8A+Cdq7JzJY\
n3Jc/uvAtgnKN4y3GYL7jlhlrUCOPXfFrsBX8PuJ9dMaZRvGO9gFeBH9QVM2bQAubGvjJiQi0h24\
TVpSTz4jMBklYS/klVV7sJRZdyi18UygN4ZRg9HAEvQHiMmfzsAwumA4sBD9Dmrypx+QAzsMFIaJ\
iF/3aGAQcgzXdyDKHYCHCZewwwjPXcCnkInAiJST6Hrmngv8CllAGuG4zEHAszXKNZVDf0K2GI2I\
aSb5QFyARNM9D9g9R5nd8Rf33xSHHsdfQFfDIR8j+02eC/wM+CQSQjsp38hRpil+PQVsgxE9TcDz\
uLvxrwA/Bj5B7TeEM5BIP9qd1ORHz+D4IJAdKPDHWcjesC8WA08gr4OPI9Fi/gIM8Fimocd04CjE\
BdgZNgH4YyqSIssw8vICEr+xUbq11FiIIT8cgQ1+ww0zkUxLzgc/2ATgi0u0DTBKwRzksNFCXwXY\
J4B7dkNmbXOyMvIwBzi87ac37A3APedgg9/Ixzzktd/r4Ad7A3BNM/AqkvPeSMZ6ZItzJrKzsRpY\
0/Zv/YC+SByDPZG3qx4KNoZkIbKGNDNEYZYd2C3HYYO/EUuQMwqTgEeAl5BJIAk9kIngcGRV/EjK\
FSBzKXK+P8jgN9yzLeKjre0wEptagN8jvhEun+DNyICZgPhBaNczj9YgOQGMgtMNuAKJFKPdqbS1\
EriJbAE00zIYGI88RbXrnVYbgFOdt4ihyjHI3q1259LQWuBa/CbTqMVWwHVtNmi3QxJtAs720hKG\
Ou1n8rU7WUj9kTgyDu9BMT7HrvDVAEYcdAMupvwx+Fva6hkbn0B2FrTbp5bG+Ku6ERMHATPQ73A+\
NJPwSTTTsB8wC/126ko/8lhvIzL6IIti2p3OpaYgqaxjZxCNk29q6E101koMRU6jHJF6JwL9HbeN\
T/oD96Pfbp31Hz4rbcTJDsTZGZPqL8gbTdHoA/wV/fbrqMlea2xES/sCYQv6nTCNnqXYYakGItF1\
tNuxXZuAHb3W2Iia0cBz6HfEJHqdcrg770JcTkP2GVBx+gA3o98RGz2pPuCrARQ4mXhiKN7lua5G\
QfgIsjKs3SG70o0e663Ft9Fv11bknvfyXFejIIwApqHfKTtqNnI0t2z0Q87da7dvKxIDwDAAyfga\
k8/AWL/VVeV09Nu3FbjKd0WNYrEz+p2yFdmuLDsPod/Od3uvpVEo/h39TtmKBOAoO0ej384LvNfS\
KBTfQb9TPuG9lvHwKPrtHXSL1YKCxs3B2gYgk1BV+L62AcD+2gYYcdAN/e3AFRTT3TcrfYA30G3z\
y7zXsgP2BhAvu6B/0OZ2JLJOVViLvkNO0GAqNgHEywhtA4B7tA1QQLvONgEYALxbufwNyKm5qvEw\
sFGx/Fqp371gE0C87Kxc/lRkDaBqLAeeVix/F2T7N0iQEJsA4iVEKO16TFEuXxPNuncHfo1kSboP\
OB+PfcEmgHgZqlz+i8rlaxJD3XsBJyAnROcjPgpXIkfHLaVfBZiO7nbUsf6rGC3Ho+8QVE/zgVuA\
M4GtPbWBocyr6HayPb3XMF5GoD/Ik2o9Ep5tHBL92N4OSoJ2ViHtNQhNdkB/YGfVYuAOJB9CkcO2\
VZ6V6HYkbSckTQagP5BdaAOyrXkxsGtXFbXXhXhZi8QE0KI7uvvhmjQjg6dsTEU8He9CYlDaBBAx\
85FXUS0GICm3q8gA5A2srLQik1yrbQPGyyLl8gcol69J2evenqfS/AAiZo5y+WUfBPUoe6qulvY/\
2AQQL7OVy+9y0agiDNM2wDNvn/C0CSA++iI54z+lbIf2YSRNyl73t98AumtaYWxBd+Ac4MvEkSYq\
huPIWtgEYASjG3AG8FXi6nhjtA1QpOx1b2n8K4ZvmpDUVFPQdxip5URSRT/zrZG6a7e/T70d5t3W\
AMLTBJyFHPa5BzhQ15yaNAOHaRuhwFFI3cvMvPY/2AQQjl7AhcAsxFd7pK45iThV2wAFTtE2IADz\
Gv+K4Yp+iC/2a+i/+qXVCsqZD7AWfdE/gxFCloo8AIOAa4Al6N/wPPqw64aJmI+i394hdIKrBjPe\
yXbADejH9Helx902T9RMRr+9Q2iUqwYzNjMIGI+8NmvfYNc60l0zRctx6LdzKA1sr7SdBszPQODz\
wCWU14f8IWR1vMw8Arxf2whHrEUW+uYALwOvdNDLdIj2bBNAPo5BVvSrEHnldPSz5vjiTOA32kYk\
4C3klOj8Dj8Xdvq5AElvlgibAPJxJDBJ24hAzAX2AlZrG+KY/sALBM7KW4M3kFiQszv8bP/zImRB\
2YiIfkhQRu1vulD6lptmi4qb0G/XVmCG74oafngS/c4TSpsol6PMSUidtNu1Ffi657oanvgu+p0n\
pJYg6auKzjBgGfrt2a5DvNbW8MaH0O88oTUd2fYsKoOB59Fvx3YtwtzyC8vO6HcgDT1KMd2E+yLO\
Tdrt11E/9Fpjwzsz0e9EGnqAYsUO3Ap4EP1266wqOFqVmhvQ70RamoZu+PKkbAc8hX57ddZs7PW/\
8ByKfkfS1CvEG9cA4CBkoGm3U1ca76/aRiiaEE8s7c6kqXVIMNPYnMvOZ3Mc/Ni0CRjur+pGSH6M\
foeKQQ8QR2zDEcT5vd9RD3qrfUJim62LzMlIiK9GrEAyuC5F9tSXIvvRHX8uafu9NcjTay0SyHEt\
cACyAh8z64BvImsjywOXvQ3yJnIp0DNw2Wk5CfiDpgE2AbijDxL5Z3Wb3kQG8Sokykz7YF/voKz7\
KEZQh5XA/wLfBl73XNYQZNB/lmLsTEwD9kXeBAwjFQcQjwtrErUAv0eCobp8KjcjJzInIJOudj3T\
6CMO28GoIHei34mzaDlwN/A5YB/STQg9gdHIm9bvkNNz2vXJoleIJCeHfQIUl72BZ4ikI+VgI7JF\
NxP5TFqFfD6BvMr3B7ZFFhaHUY6Q3ecAt2obYRSfb6P/NDOl0xTM8ScYQ4FzkW/EOWy+CR/QNMoh\
A5DQT9qd2pRMGyl/2jF1tkXi8z2GNHhXN2IW0FvLQMechX7HNiXT/9W4h0ZOmti8GryGZDfjahVL\
/fBH9Du3qbH2qnUDjeychMRMS3sz1gD/Et5cL+xE8ROQVEF31LqBRnbGk/2G3B3eXG/EFN7KVFtn\
1LqBGpRhNbI1x/89BTjRlSHK3It9YxaBHwDv0jainTJMAJty/v+biGNBsBvydOiT4xqfB/7hxhzD\
E+8CbtQ2okxcTf7Xsi8Ft3pL+rPZs+814BM5rrUnth5QBJVlK1qdq8h/M1YjXmYa7I4E2exs0++A\
7TNecwzF842vmhYgwUmNnHwRNzdEI+3V8dQPTb2E7Om5TwY21Lm2SV+/rXn3jMSMw90NCfladj7J\
swpNQLIQpeXChNc36SnrBG+0cQXubsZMoJdne3sDv8hg23RgZMqy9slQjimsliOh5Y2MXI7bGzLO\
o61Dgck5bHsTebVPyvdzlGUKp/uxk7mZuQy3N2MVfhYED8TNwZ0NwEUJyuuHRCTS7tymZPpM17fR\
aMSluL8Zf8Wtj8RZuF2VfyZBmec5LM/kX6uRLdygmCNQ1xxKsqdsI7ohaxS34zaN1s8S/M4FDssz\
/NMX+CnlCHgSlIvwNyPnOb21FbLN49qu9UiWm3rs76FcUxhd0cX9NOrwGfzdjFeQ+AJpORB4yZNN\
9yYo/6eeyjb5Vwuye2Mk5AL83pCJJI+71wx8Ab+ZaD7YwIbtkU6k3ZFN2TWV4sd6DIbPN4B2/Z7G\
jjgHAU96tmM5jQ8uXRugPaqmJwmfWPTyzjfW6BrXfgC19He6DiCyB3ALtcOPuVSj4769gEWB2qMK\
WoaEIG9GnshXINmZQpS9BssbmIivEK5DtAC/QjrC9cDjhA3CcUiDtrCtPzfaiLhfd3Vuf3fg4UB2\
TMIchBpyE/odJoRmUL8zdEPSTWnbWWStQ+L1N3K5bkICz4Y4cZnnaHgluAv9jhNCX2zQDsdGYGNR\
tQrJsZDWJ38P4AnPtiVx+qo0z6LfgXxrI407Z4jIwLeTLQBrrHoGeZLnOZffHQkos86DfUuwSMJ1\
aSJ5GPAia2KDdtgbv2sRm5BwY+1tfgwS4dZHp/etZcDNiLenS0YhE4orO1fTeM2n8uyHfocKoUaZ\
ZH/ksewW4Mwa5Q5FnqAP4Nf3Ia/mAN8Djsbv/npv4Fvk3xFqQSZZowHXoN+5fOsN6gcKHYK/rak3\
gCPrlN2RrZCgpj9BPCi1260V+AOSSj00RyAJT7PYvIHaE67RgT5IAE3tTuZbP2zQDtd4KnchsG+D\
suuxLRJh6RrEfXk24UOUnZfD/rwMQPxD0ti7CV2bc3Mism3xfmTRyufJpu+iPzhDqN4TuAcw30OZ\
85B03K7p2XbdE4HPIavvPtvuaA91SMuJyGTayNYNSCLboLh0MhgMvAwM7PB365Cn9KvIE2BOm+a2\
aX7b76RhJHAd+V+TViEOHVORcFszgKXIItF6ZAbv16YRyCLPPsC/Iqm4QrAU8e3fUOPfz8J9uqnX\
gKOQBKq+uRM43eP1hyOfI9oMRrYZP17j3zcAZwO/DGZRGy4ngOtJ77+8CXFdnYN0vMVI2KsVbeqH\
LNpsjQzCA8gXP20l4sn3a8SLL+3kA9JmByEd90z8umv+DPhknX+fRPJv9CS8igz+2Q6vWY+PAT/3\
dO0NyBn79Z6un4VjEXfu3Tr83RrgQ8h5k8IyhLjj0L+KnBrMElm3Hk3Aacg5AR92n1an7JG43fqb\
TfhkqVvjb/cg1CSWlj5IPst1yBve+1StccR49Ad5V1qKhMbu6a3mmzkWeN6x/UPqlOdyDeRFYMe8\
DZCRiQltTKtJISuRgf0RT8LC0wd5ddce7J11G/UHkA96IesTLhxkGn2DP+agjFbgObJnIHLBp2vY\
lVcTQlaiypyL/mDvqNXIgoomo8m/F35bgzL6IYtGecqYRvhJsjM74MeL8eshK1FlfB+GSKN5xBNO\
aQiy0Ji1LtclLOcisjkCPU22cGc+mIr7vnBx0BpUlL3RH/TtmkX4RaxG9AZ+Q7b6XJKinL2RAZ30\
2k8Cg3LVzC3/g/v+cFbQGlSUb6A/8FuRbUStRaxG9AD+TPo6XZmynJ7IQGq0/vAQ4rYbE4fhvk+U\
YnU9dmahP/iXEf+Ryf7AFNLVK+si1ihqf3rcQ/1zBVp0R+IduuwXsb0Nlo7R6A/+TcAJvivqiO1I\
F69vBV2HpEpCE/BZtkwNditxR5q9A7d9o1HwVCMnpxI2Hl5XusF7Ld0ylnT1exB5e8jKjkhykhuI\
P7bcp3DXL5YGtr2ynIJeAsoXCOPg45pbSVfP6cDBKpaGZSjuHijTAtteaUYggzH0BHBciMp5YCAS\
6ilNXTch3+8foNy549LsZNTTn0IbXnW2Au4m3OBPkh4rZsaRve4LgBuRI9c9QhvuGVfbgT8Jbbgh\
35hfJkyCjKJv8QwAXid/O6xEJt7/BMZQzE+ijrjaDvxqaMONzZyM33WBR8NVxStfwn3btCBbgN8B\
PkzxtsJcbQd+NrThxpbshb/suOcErIdPdiXMLso/kfWDK5HPhr4hKpeDrJ6THXVKcKuNdzAIuB+3\
nXktW0YcKjp5zgpk1QbkBODNSPi2vb3XMh0utgNHBbfa6JLuuD23XvTFv85cTPgJoCtt47uiKRiM\
RPHJU588vhOGB87DTeSXy0Ib7plYDlO913dFUzKJ7HVZpGBvYWkKVM4twPHIqnUe/uLAlph4EYlf\
oM2e2gZ04q4c/zeGIKCFIdQEABKB9yhk+ysLrUjIrTKxkTiSP+6ubUAnfovc7yzYBJCCkBMAwFPA\
4WR7TZtHHE9L18TgthpbbLr5yOnJJKxCHgwTETfr4KG1i4zG6bAXkGQJDyMOMUmZ48UafZZoG0C4\
PAdpGIeEX29Bdn/WIQ+AjYifySLkobBCy0AjH8eRLnjmH3TM9M6l6C8Cvuy9lkaUhP4E6MhE4Jsp\
fn+VL0OUWa5tAPFFCDICoTkBgOQTeFHZBm1iOKfvOmGKURC0J4C3kLiCSSirc0cMTjhlXFw1EqA9\
AQD8MeHvlfU1dWttA5DUaUYFiWECSPptP8ynEYrEEJs/RCZgI0JimABGJ/y9HSnnt2rS+vvieeB2\
ZRuMCjOB5NtVY5Rs9EUz8gYUettvGhK8JfZw6kbJeQ/pIgh9QcdMb7yHcIP+OWTXZWSIihlGI5pJ\
f+qrbM5Al+BvwG8CJgOXA8NDVcgwkvLfpO/Ua4lj1dwVk3E76DciIdOuIL4DPobxNieRPXjouQr2\
+mAY7kKCPQZcgGQfMoyoOZh8C1+PhTfZC1eTb9C/jmT8sW96ozDsjaRtyvvEOzS04Y7pDywmW90X\
I4t5ZXWMMkrKSOSct4tX3qTeg7GSJTHIW8jAjz2qr2G8g9FIeGoXg79d/xa0Bu7IkhpsAeXzgTAq\
whhgGW4HfyswA+gVsB6uuJV09VyF+AsYRuE4DL9Zgr4VripOOIX0dfyaiqWGkZPjkGOmvgZ/K7KN\
dmKoCuVke7J9Br1fw1jDyMNYJJabz8HfruXE/4o8AAmImqV+sWXuMYy6fJB0sf5caC5xBrYEydg7\
kex1K/qWp1EhzkZyz4Uc/O16GdjNfxVT0Ru4k3z1Oj+41YaRgQvI7t7rSguA/XxXNCHbAU+Qv06/\
CG24YaTlUsKkuk6iNeinEN8PmI2b+ixHPiMMI0q+iP6g70q/RlbeQ9IL+Cru10BOCFkJw0iDRo77\
pFoGXEQYh6HjkaxHPurx8wD2G0YmzkR/oDfSXODTuA8t3tRW/yc9298CDHFsu2E4oRnJyKo9yJNo\
JZKq/BiyvxU0AYcAN+LuOz+Jrspor2HUxFVWmnORgVUkVgOPAE8DzwIvIWfslyBbmf0RB56+SPDM\
UW06BBiqYO88ZJtzvULZhlGXZmA6+k/4suu8pDfEMEKT5aCLKZ1eBnokvSGG0Yhmh9eagRz93cPh\
NY0t2QZZb3lG2xCjHLjOTLsHknSit4NrvYV8l89AIgmtRI4Wd0e+wYcBR1C90FizkOhKG7QNMYyu\
GE/6V9t1wN+A7wIfRSaSJG8n/ZDAmNqv5qH18QRtYxgq9ETeAup14NcQT71LkVX1vG8M1zcor2x6\
Ebefb4bhlP3Z7A67Adlq+x7wEWBnD+X1Qg4CaQ/MkPqwk5YzDE+MRaICDQhUXpZIu0XWdOLI7mwY\
UTAIcZLRHpghdYaTljOMkvAo4QfhOsQleKFC2VNxv5NjGIXlWsINvtXAZWz5ibM94hYd8oTkSTnb\
zDBKw5GEGXQrkRyH9TgMuBf/gVImp20kwygrgwjz5D8shU2HAFM823RsCnsMo9S4yj9YS1mCdDYh\
Ycpcp0dr1yMZbDKMUvJn/A3+3+W0bVvgNg92XZPTLsMoDd/Hz+BfhruoPGNx96byZUc2GUYpuAo/\
E8DnHNs5ELiZfIuENvgNoxNn437wv4C/c/jHA3My2HS1J3sMo9AcjfsJYKxnm7dCPl2SvA1sAi73\
bI9hFJZ343bwh/S2ex/1Q4u3IMelDcOoQT/cTgCnhDWfPkiMg845FhcgPgWGYTRgGW4G/zPo+drv\
y+aU4pPQiURsGIWkUUCSpNI+bdcTOB079msYqfgT+Qf/c9jAM0pOWTv4fAfXuA5ZcTeM0lLWCWBB\
zv//AvAbF4YYRszYBNA1X8ee/oZRWPJkKZqDZd8xKkJZ3wDyrAF8DUvAaRiFZgeyPf0XIo44hmEU\
mGbgViRYZ5oJ4DINYw1DiypElB2GxO8bDYxCzgrsyDuf9EvbfndVQNsMQ5UqTAC1GIy41+7S9nMh\
cJ+qRYZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIYh/D/GS6zN\
Wk3S1gAAAABJRU5ErkJggg==\
texture: url("data:image/png;base64,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\
YRiGYRiGIfw/xkuszVpN0tYAAAAASUVORK5CYII=\
");
}
}
@@ -277,8 +277,8 @@ Wk3S1gAAAABJRU5ErkJggg==\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 4 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAH0lEQVQ4jWNgGPKAEY3/n1R9TNRz\
y0CB0TAYDQOqAADB/QMKPEUKLAAAAABJRU5ErkJggg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAB9JREFUOI1j\
YBjygBGN/59UfUzUc8tAgdEwGA0DqgAAwf0DCjxFCiwAAAAASUVORK5CYII=\
");
}
}
@@ -294,10 +294,10 @@ y0CB0TAYDQOqAADB/QMKPEUKLAAAAABJRU5ErkJggg==\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAfUlEQVQ4je3RMQoCMRBG4Q+voEIK\
C/H+d7Cwd1GULSzEUyg2azOyQ1gxB9gHgcnknxdCmJliwAHr1FtiH2d/uUTwHJIVuuj1LYINbkly\
ivqObYuglgx4YDcVXPwQvPFM+1esJgquxjf3qS4tgmM1UJKkaxF8g/m2YvyJmYoPk2IlW2Wofj0A\
AAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAH1JREFUOI3t\
0TEKAjEQRuEPr6BCCgvx/newsHdRlC0sxFMoNmszskNYMQfYB4HJ5J8XQpiZYsAB69RbYh9nf7lE\
8BySFbro9S2CDW5Jcor6jm2LoJYMeGA3FVz8ELzxTPtXrCYKrsY396kuLYJjNVCSpGsRfIP5tmL8\
iZmKD5NiJVtlqH49AAAAAElFTkSuQmCC\
");
}
}
@@ -373,9 +373,9 @@ transform {
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAOklEQVQ4jWNgGAWDD5QzMDD8J4Dr\
KTGEoGZ8hhCtGZshODUz4zHgKAMDAyMDA8NBBgaGRlJtHwUkAACHZRnQomjWaAAAAABJRU5ErkJg\
gg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAADpJREFUOI1j\
YBgFgw+UMzAw/CeA6ykxhKBmfIYQrRmbITg1M+Mx4CgDAwMjAwPDQQYGhkZSbR8FJAAAh2UZ0KJo\
1mgAAAAASUVORK5CYII=\
");
}
}
@@ -430,9 +430,9 @@ gg==\
offset: 0.831373 0.811765 0.792157 0;
child: texture {
bounds: 0 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAOklEQVQ4jWNgGAWDD5QzMDD8J4Dr\
KTGEoGZ8hhCtGZshODUz4zHgKAMDAyMDA8NBBgaGRlJtHwUkAACHZRnQomjWaAAAAABJRU5ErkJg\
gg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAADpJREFUOI1j\
YBgFgw+UMzAw/CeA6ykxhKBmfIYQrRmbITg1M+Mx4CgDAwMjAwPDQQYGhkZSbR8FJAAAh2UZ0KJo\
1mgAAAAASUVORK5CYII=\
");
}
}
@@ -473,11 +473,11 @@ gg==\
offset: 0.654902 0.666667 0.666667 0;
child: texture {
bounds: 0 8 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAyklEQVQ4jc3S3UpCURAF4K8w8ypQ\
A1EfpkcI8SmEEh9STYzQQNCE3sELiQiiLhy1I/ucbl0wDHt+Fmv2DOeGCh4xxic2eIrYVdSM8JNq\
bmMeyZS9oPnnnUEZr5FY4h63aKCDdeSe8wgGEXxDNaGujvcTRRnsmTuJ5v3Mp5bBRwQbCYK8PwGl\
8N/hvxIEF4nYAZfhF+HvioqL8BCyVqgl8jVM5ewfrjGLgjW6uAnrOq5xWqSi5XgLeYfU+m+UMvqY\
YGt3ykP0QuUZ4hei9keg1mtPrwAAAABJRU5ErkJggg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAMpJREFUOI3N\
0t1KQlEQBeCvMPMqUANRH6ZHCPEphBIfUk2M0EDQhN7BC4kIoi4ctSP7nG5dMAx7fhZr9gznhgoe\
McYnNniK2FXUjPCTam5jHsmUvaD5551BGa+RWOIet2igg3XknvMIBhF8QzWhro73E0UZ7Jk7ieb9\
zKeWwUcEGwmCvD8BpfDf4b8SBBeJ2AGX4Rfh74qKi/AQslaoJfI1TOXsH64xi4I1urgJ6zqucVqk\
ouV4C3mH1PpvlDL6mGBrd8pD9ELlGeIXovZHoNZrT68AAAAASUVORK5CYII=\
");
}
}
@@ -557,10 +557,10 @@ YGt3ykP0QuUZ4hei9keg1mtPrwAAAABJRU5ErkJggg==\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 4 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAfUlEQVQ4je3RMQoCMRBG4Q+voEIK\
C/H+d7Cwd1GULSzEUyg2azOyQ1gxB9gHgcnknxdCmJliwAHr1FtiH2d/uUTwHJIVuuj1LYINbkly\
ivqObYuglgx4YDcVXPwQvPFM+1esJgquxjf3qS4tgmM1UJKkaxF8g/m2YvyJmYoPk2IlW2Wofj0A\
AAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAH1JREFUOI3t\
0TEKAjEQRuEPr6BCCgvx/newsHdRlC0sxFMoNmszskNYMQfYB4HJ5J8XQpiZYsAB69RbYh9nf7lE\
8BySFbro9S2CDW5Jcor6jm2LoJYMeGA3FVz8ELzxTPtXrCYKrsY396kuLYJjNVCSpGsRfIP5tmL8\
iZmKD5NiJVtlqH49AAAAAElFTkSuQmCC\
");
}
}
@@ -600,9 +600,9 @@ AAAASUVORK5CYII=\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAOklEQVQ4jWNgGAWDD5QzMDD8J4Dr\
KTGEoGZ8hhCtGZshODUz4zHgKAMDAyMDA8NBBgaGRlJtHwUkAACHZRnQomjWaAAAAABJRU5ErkJg\
gg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAADpJREFUOI1j\
YBgFgw+UMzAw/CeA6ykxhKBmfIYQrRmbITg1M+Mx4CgDAwMjAwPDQQYGhkZSbR8FJAAAh2UZ0KJo\
1mgAAAAASUVORK5CYII=\
");
}
}
@@ -638,9 +638,9 @@ gg==\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAOklEQVQ4jWNgGAWDD5QzMDD8J4Dr\
KTGEoGZ8hhCtGZshODUz4zHgKAMDAyMDA8NBBgaGRlJtHwUkAACHZRnQomjWaAAAAABJRU5ErkJg\
gg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAADpJREFUOI1j\
YBgFgw+UMzAw/CeA6ykxhKBmfIYQrRmbITg1M+Mx4CgDAwMjAwPDQQYGhkZSbR8FJAAAh2UZ0KJo\
1mgAAAAASUVORK5CYII=\
");
}
}
@@ -679,9 +679,9 @@ gg==\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAOklEQVQ4jWNgGAWDD5QzMDD8J4Dr\
KTGEoGZ8hhCtGZshODUz4zHgKAMDAyMDA8NBBgaGRlJtHwUkAACHZRnQomjWaAAAAABJRU5ErkJg\
gg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAADpJREFUOI1j\
YBgFgw+UMzAw/CeA6ykxhKBmfIYQrRmbITg1M+Mx4CgDAwMjAwPDQQYGhkZSbR8FJAAAh2UZ0KJo\
1mgAAAAASUVORK5CYII=\
");
}
}
@@ -747,8 +747,8 @@ gg==\
offset: 0.615686 0.623529 0.623529 0;
child: texture {
bounds: 4 8 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAHElEQVQ4jWNgGAXDADCi8f+Tqo+J\
em4ZBUMYAABDXwEEvj+CVwAAAABJRU5ErkJggg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAABxJREFUOI1j\
YBgFwwAwovH/k6qPiXpuGQVDGAAAQ18BBL4/glcAAAAASUVORK5CYII=\
");
}
}
@@ -767,8 +767,8 @@ em4ZBUMYAABDXwEEvj+CVwAAAABJRU5ErkJggg==\
offset: 0.615686 0.623529 0.623529 0;
child: texture {
bounds: 4 8 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAKElEQVQ4jWNgGPbgPxTjBEyU2jDw\
BjCi8fH6F5s+il1ACIyEWBgGAADypgUMy1PhdwAAAABJRU5ErkJggg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAChJREFUOI1j\
YBj24D8U4wRMlNow8AYwovHx+hebPopdQAiMhFgYBgAA8qYFDMtT4XcAAAAASUVORK5CYII=\
");
}
}
@@ -818,8 +818,8 @@ BjCi8fH6F5s+il1ACIyEWBgGAADypgUMy1PhdwAAAABJRU5ErkJggg==\
offset: 0.831373 0.811765 0.792157 0;
child: texture {
bounds: 4 8 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAHElEQVQ4jWNgGAXDADCi8f+Tqo+J\
em4ZBUMYAABDXwEEvj+CVwAAAABJRU5ErkJggg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAABxJREFUOI1j\
YBgFwwAwovH/k6qPiXpuGQVDGAAAQ18BBL4/glcAAAAASUVORK5CYII=\
");
}
}
@@ -845,8 +845,8 @@ em4ZBUMYAABDXwEEvj+CVwAAAABJRU5ErkJggg==\
offset: 0.831373 0.811765 0.792157 0;
child: texture {
bounds: 4 8 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAKElEQVQ4jWNgGPbgPxTjBEyU2jDw\
BjCi8fH6F5s+il1ACIyEWBgGAADypgUMy1PhdwAAAABJRU5ErkJggg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAChJREFUOI1j\
YBj24D8U4wRMlNow8AYwovHx+hebPopdQAiMhFgYBgAA8qYFDMtT4XcAAAAASUVORK5CYII=\
");
}
}
@@ -879,10 +879,10 @@ BjCi8fH6F5s+il1ACIyEWBgGAADypgUMy1PhdwAAAABJRU5ErkJggg==\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 0 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAeElEQVQokb3QXwpAQBDH8e9uzscR\
XEXyJFE8KFoXcxheVm1j0Cp+tQ87M5/2D/yc8g2qgC0GGKDzSIUpYBXUB+gEC19cAmyAQaAmRJlo\
OiABJlGv5WnWD4dDq9i32tuOa41i+FiT719Gw/MT0rDj/Mu3sUAei77LDp72K7jAZx9tAAAAAElF\
TkSuQmCC\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAHhJREFUKJG9\
0F8KQEAQx/Hvbs7HEVxF8iRRPChaF3MYXlZtY9AqfrUPOzOf9g/8nPINqoAtBhig80iFKWAV1Afo\
BAtfXAJsgEGgJkSZaDogASZRr+Vp1g+HQ6vYt9rbjmuNYvhYk+9fRsPzE9Kw4/zLt7FAHou+yw6e\
9iu4wGcfbQAAAABJRU5ErkJggg==\
");
}
}
@@ -945,9 +945,9 @@ TkSuQmCC\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 0 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAOUlEQVQokWNgGAVEAW8GBoYnDAwM\
/3HgxwwMDF7YND7GowmGH8EUM1HDqV4EbH3EwMDgSQ2Lhj0AABu4GmjkhFgCAAAAAElFTkSuQmCC\
\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAADlJREFUKJFj\
YBgFRAFvBgaGJwwMDP9x4McMDAxe2DQ+xqMJhh/BFDNRw6leBGx9xMDA4EkNi4Y9AAAbuBpo5IRY\
AgAAAABJRU5ErkJggg==\
");
}
}
@@ -983,10 +983,10 @@ TkSuQmCC\
offset: 0.831373 0.811765 0.792157 0;
child: texture {
bounds: 0 0 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAeElEQVQokb3QXwpAQBDH8e9uzscR\
XEXyJFE8KFoXcxheVm1j0Cp+tQ87M5/2D/yc8g2qgC0GGKDzSIUpYBXUB+gEC19cAmyAQaAmRJlo\
OiABJlGv5WnWD4dDq9i32tuOa41i+FiT719Gw/MT0rDj/Mu3sUAei77LDp72K7jAZx9tAAAAAElF\
TkSuQmCC\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAHhJREFUKJG9\
0F8KQEAQx/Hvbs7HEVxF8iRRPChaF3MYXlZtY9AqfrUPOzOf9g/8nPINqoAtBhig80iFKWAV1Afo\
BAtfXAJsgEGgJkSZaDogASZRr+Vp1g+HQ6vYt9rbjmuNYvhYk+9fRsPzE9Kw4/zLt7FAHou+yw6e\
9iu4wGcfbQAAAABJRU5ErkJggg==\
");
}
}
@@ -1049,9 +1049,9 @@ TkSuQmCC\
offset: 0.831373 0.811765 0.792157 0;
child: texture {
bounds: 0 0 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAOUlEQVQokWNgGAVEAW8GBoYnDAwM\
/3HgxwwMDF7YND7GowmGH8EUM1HDqV4EbH3EwMDgSQ2Lhj0AABu4GmjkhFgCAAAAAElFTkSuQmCC\
\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAADlJREFUKJFj\
YBgFRAFvBgaGJwwMDP9x4McMDAxe2DQ+xqMJhh/BFDNRw6leBGx9xMDA4EkNi4Y9AAAbuBpo5IRY\
AgAAAABJRU5ErkJggg==\
");
}
}
@@ -1150,9 +1150,9 @@ TkSuQmCC\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 0 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAOUlEQVQokWNgGAVEAW8GBoYnDAwM\
/3HgxwwMDF7YND7GowmGH8EUM1HDqV4EbH3EwMDgSQ2Lhj0AABu4GmjkhFgCAAAAAElFTkSuQmCC\
\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAADlJREFUKJFj\
YBgFRAFvBgaGJwwMDP9x4McMDAxe2DQ+xqMJhh/BFDNRw6leBGx9xMDA4EkNi4Y9AAAbuBpo5IRY\
AgAAAABJRU5ErkJggg==\
");
}
}
@@ -1191,9 +1191,9 @@ TkSuQmCC\
offset: 0.831373 0.811765 0.792157 0;
child: texture {
bounds: 0 0 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAASklEQVQokWNgGJmAjYGBoZWBgeER\
FLcwMDCwEqOxlYGB4T8abiZG42MsGh+iK2LCovE/MWLYNC4iUgwDsDJA/PQQihsZiAyc4QYASeYT\
s7b/ALUAAAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAEpJREFUKJFj\
YBiZgI2BgaGVgYHhERS3MDAwsBKjsZWBgeE/Gm4mRuNjLBofoitiwqLxPzFi2DQuIlIMA7AyQPz0\
EIobGYgMnOEGAEnmE7O2/wC1AAAAAElFTkSuQmCC\
");
}
}
@@ -1262,9 +1262,9 @@ s7b/ALUAAAAASUVORK5CYII=\
offset: 0.831373 0.811765 0.792157 0;
child: texture {
bounds: 0 0 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAOUlEQVQokWNgGAVEAW8GBoYnDAwM\
/3HgxwwMDF7YND7GowmGH8EUM1HDqV4EbH3EwMDgSQ2Lhj0AABu4GmjkhFgCAAAAAElFTkSuQmCC\
\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAADlJREFUKJFj\
YBgFRAFvBgaGJwwMDP9x4McMDAxe2DQ+xqMJhh/BFDNRw6leBGx9xMDA4EkNi4Y9AAAbuBpo5IRY\
AgAAAABJRU5ErkJggg==\
");
}
}
@@ -1290,12 +1290,13 @@ s7b/ALUAAAAASUVORK5CYII=\
transform: translate(8, 11.5) rotate(12.2788) translate(-8, -11.5);
child: texture {
bounds: 0 3.5 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABE0lEQVQ4jbXSPy9DURjH8U9bSqhE\
mog/A6PFJGGRCInRZrQZTN6B1XsysJgMRklJDRYGtVBtWkRr6HObG2muRuJJbnJynvP9nt9zc/iH\
KuEIZ3jEFeaHhbfwgO6P73AYeAftAfANFn+Dp1FLQffYx8yw0Y9T8B3mMs6OoYh8evMSnRDsZcCF\
kJf1fraRaCygFevzDEE3JBMYRSMR1CPaVwYsYk/Fup1swC2e0MBGhqAcgtlI0hecxjgNHKRuSVcR\
KyHJi5EL0axiNxodrEWiFsaxhE1MBvOOCjq51A3rOMFrSNp4RhMv+AhhHRfR6yeg9+4rWE0J8sjh\
LQTNgGsJlE6QVAnbWI65mzFOFdf4HMD8vb4BZVRHF0lPimAAAAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAARNJREFUOI21\
0j8vQ1EYx/FPW0qoRJqIPwOjxSRhkQiJ0Wa0GUzegdV7MrCYDEZJSQ0WBrVQbVpEa+hzmxtprkbi\
SW5ycp7z/Z7fc3P4hyrhCGd4xBXmh4W38IDuj+9wGHgH7QHwDRZ/g6dRS0H32MfMsNGPU/Ad5jLO\
jqGIfHrzEp0Q7GXAhZCX9X62kWgsoBXr8wxBNyQTGEUjEdQj2lcGLGJPxbqdbMAtntDARoagHILZ\
SNIXnMY4DRykbklXESshyYuRC9GsYjcaHaxFohbGsYRNTAbzjgo6udQN6zjBa0jaeEYTL/gIYR0X\
0esnoPfuK1hNCfLI4S0EzYBrCZROkFQJ21iOuZsxThXX+BzA/L2+AWVURxdJT4pgAAAAAElFTkSu\
QmCC\
");
}
}
@@ -1312,12 +1313,13 @@ LQTNgGsJlE6QVAnbWI65mzFOFdf4HMD8vb4BZVRHF0lPimAAAAAASUVORK5CYII=\
transform: translate(8, 11.5) rotate(12.2788) translate(-8, -11.5);
child: texture {
bounds: 0 3.5 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABE0lEQVQ4jbXSPy9DURjH8U9bSqhE\
mog/A6PFJGGRCInRZrQZTN6B1XsysJgMRklJDRYGtVBtWkRr6HObG2muRuJJbnJynvP9nt9zc/iH\
KuEIZ3jEFeaHhbfwgO6P73AYeAftAfANFn+Dp1FLQffYx8yw0Y9T8B3mMs6OoYh8evMSnRDsZcCF\
kJf1fraRaCygFevzDEE3JBMYRSMR1CPaVwYsYk/Fup1swC2e0MBGhqAcgtlI0hecxjgNHKRuSVcR\
KyHJi5EL0axiNxodrEWiFsaxhE1MBvOOCjq51A3rOMFrSNp4RhMv+AhhHRfR6yeg9+4rWE0J8sjh\
LQTNgGsJlE6QVAnbWI65mzFOFdf4HMD8vb4BZVRHF0lPimAAAAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAARNJREFUOI21\
0j8vQ1EYx/FPW0qoRJqIPwOjxSRhkQiJ0Wa0GUzegdV7MrCYDEZJSQ0WBrVQbVpEa+hzmxtprkbi\
SW5ycp7z/Z7fc3P4hyrhCGd4xBXmh4W38IDuj+9wGHgH7QHwDRZ/g6dRS0H32MfMsNGPU/Ad5jLO\
jqGIfHrzEp0Q7GXAhZCX9X62kWgsoBXr8wxBNyQTGEUjEdQj2lcGLGJPxbqdbMAtntDARoagHILZ\
SNIXnMY4DRykbklXESshyYuRC9GsYjcaHaxFohbGsYRNTAbzjgo6udQN6zjBa0jaeEYTL/gIYR0X\
0esnoPfuK1hNCfLI4S0EzYBrCZROkFQJ21iOuZsxThXX+BzA/L2+AWVURxdJT4pgAAAAAElFTkSu\
QmCC\
");
}
}
@@ -1455,9 +1457,9 @@ LQTNgGsJlE6QVAnbWI65mzFOFdf4HMD8vb4BZVRHF0lPimAAAAAASUVORK5CYII=\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAOklEQVQ4jWNgGAWDD5QzMDD8J4Dr\
KTGEoGZ8hhCtGZshODUz4zHgKAMDAyMDA8NBBgaGRlJtHwUkAACHZRnQomjWaAAAAABJRU5ErkJg\
gg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAADpJREFUOI1j\
YBgFgw+UMzAw/CeA6ykxhKBmfIYQrRmbITg1M+Mx4CgDAwMjAwPDQQYGhkZSbR8FJAAAh2UZ0KJo\
1mgAAAAASUVORK5CYII=\
");
}
}
@@ -1496,9 +1498,9 @@ gg==\
offset: 0.831373 0.811765 0.792157 0;
child: texture {
bounds: 0 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAOklEQVQ4jWNgGAWDD5QzMDD8J4Dr\
KTGEoGZ8hhCtGZshODUz4zHgKAMDAyMDA8NBBgaGRlJtHwUkAACHZRnQomjWaAAAAABJRU5ErkJg\
gg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAADpJREFUOI1j\
YBgFgw+UMzAw/CeA6ykxhKBmfIYQrRmbITg1M+Mx4CgDAwMjAwPDQQYGhkZSbR8FJAAAh2UZ0KJo\
1mgAAAAASUVORK5CYII=\
");
}
}
@@ -1611,10 +1613,10 @@ gg==\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 0 4 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAeUlEQVQ4jcWTQQqAIBBFn9HV6i4u\
OmaL7hF1hVbZRkF0tMmCPnwYdeahH4RcM+AEH4AV+jNJw8EnMGkBpf0MsiRDd4AAsdKBFhAywSTN\
8doIkBgGYLpKk0qvAVB+s0q9AHuk/zP4BLD7uiXIFWD0Re0TSd6Aof3uXhd1yT8mvMGiQgAAAABJ\
RU5ErkJggg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAHlJREFUOI3F\
k0EKgCAQRZ/R1eouLjpmi+4RdYVW2UZBdLTJgj58GHXmoR+EXDPgBB+AFfozScPBJzBpAaX9DLIk\
Q3eAALHSgRYQMsEkzfHaCJAYBmC6SpNKrwFQfrNKvQB7pP8z+ASw+7olyBVg9EXtE0negKH97l4X\
dck/JrzBokIAAAAASUVORK5CYII=\
");
}
}
@@ -2083,19 +2085,21 @@ RU5ErkJggg==\
transform: translate(225, -10);
child: texture {
bounds: 1 1 20 25;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAZCAYAAAAxFw7TAAAChklEQVQ4jbXVTWsTQRgH8P88u2my\
u4ZEKVJqEj9Ar0V6kIQtPRWs1EpAPfegiFD8Av0C4sVbz1qt2IMefUmTXhTzKbKbEhRslrCzsyYz\
46Ev1jRNX4L/47Dz22eGmXkYBqReryc6nfaSaZoPtMYNpdRlADAM7CrFvgHypeNkN6enp7v9c1n/\
QKVSuUuEF6lUys5mM2nLcpBImACAbrcLzjmCIOjEsQgB/bhYnH03ENR6lba33WdEbHly8ppj2/ag\
4g8TRRzNph9KqdaKxepTxlbVP2C1WnmeTCaXC4WCQ2QMxQ6ilESj0QjjOF4rldwVACAAqNW+LBkG\
nQsDACID+XzBMQxa3tr6vAgArF6vJzjvNHK5wsRpyzwpnIfwfX9HSn2dwrB9J5lMnrpnw2LbDsbG\
xtKMqUVizLyfyWTTF9b2k8lk04Zh3CPG1Mwo1R3EcRxojRnSGlnTTIwMmqYJpeQVUgqMHTveFwtj\
DEREu91ub2Ss1+uBiLUJYN+jiI8Mcs6hNX0lrbvrQRB0RgWDoN1RqveGxsd/vRVCRKNUyXmEOBaC\
83iTpqbKv7VWK81mM1RKnhuTUmJnxwsB+WR+fj4mACiVZl8pJdd93+eAPgen0Wz6XCn5qlicew3s\
Pw57f8JDIcSW53nh2VANz2tEcSyqUrJHB6OHoOu6vVbrx0IU8U+NRoNrPQzV8H2PCxFVLevSbdd1\
D88dHf2sXC7LVuvnkhDRR887Cd3DOOfblpVe6G8DA+/IxsaGMTFxdTOVSs3l8wX771XS8DwviiJe\
s+30rTP1lH7UslJzuVzBBgDfH44NBYG97sd554NtOze11iSEqFmWcyJ2KngEfQ8Atn18z/57/gBe\
lEdqMNUvpgAAAABJRU5ErkJggg==\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAZCAYAAAAxFw7TAAAAAXNSR0IArs4c6QAAAvFJREFUOI2t\
1c9r02AYB/DnTd60Td7Mdk06Z0FFrJhsdnhwoujamwqi4qZ40OsmsoF4U3ccKlLdEPwT/MHQ7WiR\
Wl2jh3TbYSJjk2VOelgug1prUl1/vB5GpZ2tutXvKQTeDw8vD98XQY1gjLlQqKvn+PFjFxVFOUgI\
aQYAsO1v6dnZuWQsFnusae/GC4VCfv1ZtP5HOBw+d+3a1Ydut1vw+7c18TwBjsMAAJDP58G2bTBN\
M5vJfLFGRh4MJBLaWOV5tvzBMIgZGBgY7uvrHVIUtdnv9ztdLh5YlgWEECCEgGUxuFw8+Hw+pyRJ\
YjC47+SWLW7f9PR0jFKgVWB/f/9wT093r6qqxOFw1rqJqnAcB7IsO1paWoKiKMqTk1Mvf4HhcKjn\
8uXeIVVVCcOwf5Yq7wsx4PV6HbLsDS4tfZ5LpVLzCGPMPX8+muro2N8qCMI/Y5WxbQtmZmaWz5+/\
sJMJhY52u91uslkMAEAQCHg8nqaurqNn2b6+3tudnQc7XC5+0yAAAMacc3X1B2ba29VDjUxXDiEE\
2traDjGEiB6MuYZBjDGIIvEylAJCv6335oIQAsayrHQ+X2gYKxQKYFnWF2Z+/uNULmc3DNq2DbOz\
czrz6lXsqWma2UZB01zOxuPxUWZiIvEsk8nkGpnStnOQzX79rmlvx9lSqVRcWVlZbm9vOyHLsgMh\
ZkNYsViEhYV56969+1cMY/E9CwDw6dPSh9bWrbtkWVYkSeJqtFqdUDCMBfvFi+iTR4+e3AGoaBtd\
T0YVZe9hnuf9kiQ5/o5SMIyFnK4nE0NDty5RSktVIKW0FI+/Hg0EdncSQnZ4vRJXf0HXJtN1Xbtx\
Y/BMsVj8tXdVXUUppW/eTDwLBHYfEMV6aBlLvr1+ffD0+mfgt/Iro3v2BDoJIdurUQqGYeTWsJun\
ar0pNdu0EhXFNRQAYHHRyOm6rtXD6oJlNJHQxlRVOSII/LZ0Ol1MJpN/xP4pGGMuErkbjUTuRvH/\
qKWN5ichVT1RK2aa7gAAAABJRU5ErkJggg==\
");
}
}
@@ -2438,10 +2442,10 @@ lEdqMNUvpgAAAABJRU5ErkJggg==\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 14 29 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAeElEQVQokb3QXwpAQBDH8e9uzscR\
XEXyJFE8KFoXcxheVm1j0Cp+tQ87M5/2D/yc8g2qgC0GGKDzSIUpYBXUB+gEC19cAmyAQaAmRJlo\
OiABJlGv5WnWD4dDq9i32tuOa41i+FiT719Gw/MT0rDj/Mu3sUAei77LDp72K7jAZx9tAAAAAElF\
TkSuQmCC\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAHhJREFUKJG9\
0F8KQEAQx/Hvbs7HEVxF8iRRPChaF3MYXlZtY9AqfrUPOzOf9g/8nPINqoAtBhig80iFKWAV1Afo\
BAtfXAJsgEGgJkSZaDogASZRr+Vp1g+HQ6vYt9rbjmuNYvhYk+9fRsPzE9Kw4/zLt7FAHou+yw6e\
9iu4wGcfbQAAAABJRU5ErkJggg==\
");
}
}
@@ -2455,12 +2459,12 @@ TkSuQmCC\
offset: 0.196078 0.196078 0.196078 0;
child: texture {
bounds: 54 28 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA8klEQVQ4jbXSwSrEURTH8Y/YsZiU\
hfIGnkFJUrKSlIeQJ5AaUlPWdrKUJ9DMwhMQyZKVhSxEg7Lwz1i4f925c/9jSk7dbuee8/3dczqH\
f7BxbOEcL3jFFeqY/A1exBM6FecZq1XwPD76wOUpMJvCY3gYAO7gCCOpwMaA8CGGc+W3Msmnib+P\
oYjpErpNkhvhfTf4ewlcw0kscBPBx0l1S4k/hWvf4/2xZiRQYC3XJ6ZxF/Iu48B60kJOZEb3jmzH\
wVHc9xFZxnsUa2MiLW9O7yIVOAh3+faJlYoWLeBR70jjnyvh0mrYxFkA3nCBnVzZf7Yvt2xyJ4TF\
GjYAAAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAPJJREFUOI21\
0sEqxFEUx/GP2LGYlIXyBp5BSVKykpSHkCeQGlJT1naylCfQzMITEMmSlYUsRIOy8M9YuH/duXP/\
Y0pO3W7nnvP93XM6h3+wcWzhHC94xRXqmPwNXsQTOhXnGatV8Dw++sDlKTCbwmN4GADu4AgjqcDG\
gPAhhnPltzLJp4m/j6GI6RK6TZIb4X03+HsJXMNJLHATwcdJdUuJP4Vr3+P9sWYkUGAt1yemcRfy\
LuPAetJCTmRG945sx8FR3PcRWcZ7FGtjIi1vTu8iFTgId/n2iZWKFi3gUe9I458r4dJq2MRZAN5w\
gZ1c2X+2L7dscieExRo2AAAAAElFTkSuQmCC\
");
}
}
@@ -2516,11 +2520,11 @@ GjYAAAAASUVORK5CYII=\
offset: 0.196078 0.196078 0.196078 0;
child: texture {
bounds: 54 51 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAz0lEQVQ4jbXSTU4CQRAF4A/iFlbK\
OVywMoRDGLyAe70D4o3kBqz9uQAXICxwcM2wmAY6Y3djjL6kku7qqtevfvgHDPCMd3wFe8MsvBVx\
hwp1xipMSsm7VsIYw5ZvlyIZZH4+oO3/xBV0Q8Ajeufqi9DHQ+z4SPxSUlBrGnvE9hcEVVxCHPxT\
1HARLktcJ4JG6GQIljHBPEOwKCh4iS+5Md4EFW3/BpecerDCve+96CZKqEPsOiVrolmS3CpvcFso\
C82GPeFVM95tOE8Psv8Ue0ISW4s5Tmr/AAAAAElFTkSuQmCC\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAM9JREFUOI21\
0k1OAkEQBeAP4hZWyjlcsDKEQxi8gHu9A+KN5Aas/bkAFyAscHDNsJgGOmN3Y4y+pJLu6qrXr374\
BwzwjHd8BXvDLLwVcYcKdcYqTErJu1bCGMOWb5ciGWR+PqDt/8QVdEPAI3rn6ovQx0Ps+Ej8UlJQ\
axp7xPYXBFVcQhz8U9RwES5LXCeCRuhkCJYxwTxDsCgoeIkvuTHeBBVt/waXnHqwwr3vvegmSqhD\
7Dola6JZktwqb3BbKAvNhj3hVTPebThPD7L/FHtCEluLOU5q/wAAAABJRU5ErkJggg==\
");
}
}
@@ -2571,10 +2575,10 @@ C82GPeFVM95tOE8Psv8Ue0ISW4s5Tmr/AAAAAElFTkSuQmCC\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 14 75 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAeElEQVQokb3QXwpAQBDH8e9uzscR\
XEXyJFE8KFoXcxheVm1j0Cp+tQ87M5/2D/yc8g2qgC0GGKDzSIUpYBXUB+gEC19cAmyAQaAmRJlo\
OiABJlGv5WnWD4dDq9i32tuOa41i+FiT719Gw/MT0rDj/Mu3sUAei77LDp72K7jAZx9tAAAAAElF\
TkSuQmCC\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAHhJREFUKJG9\
0F8KQEAQx/Hvbs7HEVxF8iRRPChaF3MYXlZtY9AqfrUPOzOf9g/8nPINqoAtBhig80iFKWAV1Afo\
BAtfXAJsgEGgJkSZaDogASZRr+Vp1g+HQ6vYt9rbjmuNYvhYk+9fRsPzE9Kw4/zLt7FAHou+yw6e\
9iu4wGcfbQAAAABJRU5ErkJggg==\
");
}
}
@@ -2588,12 +2592,12 @@ TkSuQmCC\
offset: 0.196078 0.196078 0.196078 0;
child: texture {
bounds: 54 74 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA/klEQVQ4jaXTzypFURTH8Q9CN2Fy\
XYmRjqmpiZkykoF0n+J6Bxl4CQ/gASTlAZjwApIRMhDiSkd0Dc6W3bHPPcmv1mCv/Vvf/W9t/qmB\
RG4aHYzhNORecIML5LF5qFTcxjFWcYQnDKKBFjI8hyBMxsX7mAzju8TuhrGMuTJgBnsl4FsCQHHs\
JYzGgC1MJIxVGsFCDFhLmMrAsmZjQJYwzNcAxmPAZ8KwXgPoxYCrhCHDYh9ANwYcVJg6aFbMXfNz\
0y1cCucq6QG7uI1yOQ6Rf3fiq6JNN/1+vgZW8BFWfccJHlPb2lC0b68i7hVN1FdN7OBc8Ym6OMM2\
puqK/6wvIccweWvwsr0AAAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAP5JREFUOI2l\
088qRVEUx/EPQjdhcl2JkY6pqYmZMpKBdJ/iegcZeAkP4AEk5QGY8AKSETIQ4kpHdA3Olt2xzz3J\
r9Zgr/1b3/1vbf6pgURuGh2M4TTkXnCDC+SxeahU3MYxVnGEJwyigRYyPIcgTMbF+5gM47vE7oax\
jLkyYAZ7JeBbAkBx7CWMxoAtTCSMVRrBQgxYS5jKwLJmY0CWMMzXAMZjwGfCsF4D6MWAq4Qhw2If\
QDcGHFSYOmhWzF3zc9MtXArnKukBu7iNcjkOkX934quiTTf9fr4GVvARVn3HCR5T29pQtG+vIu4V\
TdRXTezgXPGJujjDNqbqiv+sLyHHMHlr8LK9AAAAAElFTkSuQmCC\
");
}
}
@@ -2655,9 +2659,9 @@ puqK/6wvIccweWvwsr0AAAAASUVORK5CYII=\
offset: 0.572549 0.584314 0.584314 0;
child: texture {
bounds: 14 98 14 14;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAASklEQVQokWNgGJmAjYGBoZWBgeER\
FLcwMDCwEqOxlYGB4T8abiZG42MsGh+iK2LCovE/MWLYNC4iUgwDsDJA/PQQihsZiAyc4QYASeYT\
s7b/ALUAAAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAEpJREFUKJFj\
YBiZgI2BgaGVgYHhERS3MDAwsBKjsZWBgeE/Gm4mRuNjLBofoitiwqLxPzFi2DQuIlIMA7AyQPz0\
EIobGYgMnOEGAEnmE7O2/wC1AAAAAElFTkSuQmCC\
");
}
}
@@ -2671,13 +2675,14 @@ s7b/ALUAAAAASUVORK5CYII=\
offset: 0.196078 0.196078 0.196078 0;
child: texture {
bounds: 54 97 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABT0lEQVQ4jZXTv0vXcRDH8cdXzQQT\
EZFCUVAU1xZ/LCIYrrVkoTi6NLTpX+DoGrTnkoMgqOjk8hXBhqbAMALTSB1EpDQp/DF874Nvv4hf\
PTg4uHu+7n13n0+52+01/mAYu/hdov6atWIBS+i4D1iHSXzBRfgnvMWDUnAnfiZgsa+h+iawEhX4\
fAuc+TuUBwNe4BgHSdEpevG/KL7ACX4E8xw20Y+xRGAzxL8XxVn+FbqwAUeowkBS8Bft+FcUZ/mn\
McZuDrPIxUzdmMMytvAL52hAE/owGq86REUOtZjAXixxCD1oxuMQ2MdOXOFj7KQRU9ki67F4hwtk\
PoMaia1EYv0O8CrOYnRlCl9Xfwh9xXgInSYNjpHHG3wLbjB9wXzSIY8RtMVodWhR+LHySd2HVOAR\
pmNhpUY4w3s8pHC+1JrxEs+i65MQ3cO2qytsZcAlA5qEWoLbkBcAAAAASUVORK5CYII=\
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAU9JREFUOI2V\
079L13EQx/HHV80EExGRQlFQFNcWfywiGK61ZKE4ujS06V/g6Bq055KDIKjo5PIVwYamwDAC00gd\
RKQ0KfwxfO+Db7+IXz04OLh7vu59d59PudvtNf5gGLv4XaL+mrViAUvouA9Yh0l8wUX4J7zFg1Jw\
J34mYLGvofomsBIV+HwLnPk7lAcDXuAYB0nRKXrxvyi+wAl+BPMcNtGPsURgM8S/F8VZ/hW6sAFH\
qMJAUvAX7fhXFGf5pzHGbg6zyMVM3ZjDMrbwC+doQBP6MBqvOkRFDrWYwF4scQg9aMbjENjHTlzh\
Y+ykEVPZIuuxeIcLZD6DGomtRGL9DvAqzmJ0ZQpfV38IfcV4CJ0mDY6Rxxt8C24wfcF80iGPEbTF\
aHVoUfix8kndh1TgEaZjYaVGOMN7PKRwvtSa8RLPouuTEN3DtqsrbGXAJQOahFqC25AXAAAAAElF\
TkSuQmCC\
");
}
}

View File

@@ -565,25 +565,6 @@ test_to_affine (void)
g_assert_cmpfloat (dy, ==, 5.0);
}
static void
test_transform_bounds (void)
{
GskTransform *t = gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (50, 50));
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 100, 100);
graphene_rect_t out;
gsk_transform_transform_bounds (t, &bounds, &out);
g_assert_true (graphene_rect_equal (&out, &GRAPHENE_RECT_INIT(50, 50, 100, 100)));
t = gsk_transform_rotate (t, 180);
gsk_transform_transform_bounds (t, &bounds, &out);
g_assert_true (graphene_rect_equal (&out, &GRAPHENE_RECT_INIT(-50, -50, 100, 100)));
t = gsk_transform_translate (t, &GRAPHENE_POINT_INIT (-50, -50));
gsk_transform_transform_bounds (t, &bounds, &out);
g_assert_true (graphene_rect_equal (&out, &GRAPHENE_RECT_INIT(0, 0, 100, 100)));
}
int
main (int argc,
char *argv[])
@@ -598,7 +579,6 @@ main (int argc,
g_test_add_func ("/transform/print-parse", test_print_parse);
g_test_add_func ("/transform/check-axis-aligneness", test_axis_aligned);
g_test_add_func ("/transform/to-affine", test_to_affine);
g_test_add_func ("/transform/bounds", test_transform_bounds);
return g_test_run ();
}

View File

@@ -165,14 +165,12 @@ main (int argc, char *argv[])
{
char *path = g_strdup_printf ("/fnmatch/test%d", i);
g_test_add_data_func (path, &tests[i], test_fnmatch);
g_free (path);
}
for (int i = 0; i < G_N_ELEMENTS (citests); i++)
{
char *path = g_strdup_printf ("/ci-glob/test%d", i);
g_test_add_data_func (path, &citests[i], test_ci_glob);
g_free (path);
}
return g_test_run ();

View File

@@ -602,8 +602,6 @@ test14 (void)
run_test (commands, G_N_ELEMENTS (commands), 0);
g_free (fill);
g_free (fill_after);
g_free (fill_after_2);
}
int

View File

@@ -1,17 +1,17 @@
@import "reset-to-defaults.css";
#button1 {
background-image: linear-gradient(alpha(red, 0.60),alpha(red,0.60)), linear-gradient(lime,lime);
background-image: linear-gradient(alpha(red, 0.50),alpha(red,0.50)), linear-gradient(lime,lime);
}
#button2 {
background-color: lime;
background-image: linear-gradient(alpha(red, 0.60),alpha(red,0.60)), linear-gradient(transparent,transparent);
background-image: linear-gradient(alpha(red, 0.50),alpha(red,0.50)), linear-gradient(transparent,transparent);
}
#button3 {
padding: 12px;
background-image: linear-gradient(alpha(red, 0.60),alpha(red,0.60)), linear-gradient(lime,lime);
background-image: linear-gradient(alpha(red, 0.50),alpha(red,0.50)), linear-gradient(lime,lime);
background-clip: content-box;
}
@@ -30,12 +30,12 @@
#ref1,
#ref2 {
background-color: #996600;
background-color: #807f00;
}
#ref3 {
padding: 12px;
background-color: #996600;
background-color: #807f00;
background-clip: content-box;
}

View File

@@ -7,7 +7,7 @@ window {
button {
border-width: 5px;
border-style: solid;
border-color: rgba(255,0,0,0.6);
border-color: rgba(255,0,0,0.5);
padding: 10px;
background-color: rgb(0,0,255);

View File

@@ -3,7 +3,7 @@
}
.background {
background-color: yellow;
background-color: khaki;
color: purple;
}
@@ -13,21 +13,21 @@ button {
}
.top {
border-top: 5px solid yellow;
border-top: 5px solid khaki;
padding-top: 0px;
}
.right {
border-right: 5px solid yellow;
border-right: 5px solid khaki;
padding-right: 0px;
}
.bottom {
border-bottom: 5px solid yellow;
border-bottom: 5px solid khaki;
padding-bottom: 0px;
}
.left {
border-left: 5px solid yellow;
border-left: 5px solid khaki;
padding-left: 0px;
}

View File

@@ -0,0 +1,32 @@
* {
all: unset;
color: transparent;
}
GtkBox *:nth-child(1) {
background-color: red;
}
GtkBox *:nth-child(2) {
background-color: orange;
}
GtkBox *:nth-child(3) {
background-color: yellow;
}
GtkBox *:nth-child(4) {
background-color: lime;
}
GtkBox *:nth-child(5) {
background-color: blue;
}
GtkBox *:nth-child(6) {
background-color: indigo;
}
GtkBox *:nth-child(7) {
background-color: darkViolet;
}

View File

@@ -0,0 +1,225 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window1">
<property name="decorated">0</property>
<child>
<object class="GtkGrid" id="grid1">
<child>
<object class="GtkBox" id="box1">
<child>
<object class="GtkLabel" id="label1">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label5">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label6">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox" id="box2">
<child>
<object class="GtkLabel" id="label8">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label9">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label10">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label11">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label12">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label13">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label14">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox" id="box3">
<child>
<object class="GtkLabel" id="label15">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label16">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label17">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label18">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label19">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label20">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label21">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox" id="box4">
<child>
<object class="GtkLabel" id="label22">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label23">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label24">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label25">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label26">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label27">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label28">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox" id="box5">
<child>
<object class="GtkLabel" id="label29">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label30">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label31">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label32">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label33">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label34">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label35">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">4</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -0,0 +1,245 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window1">
<property name="decorated">0</property>
<child>
<object class="GtkGrid" id="grid1">
<child>
<object class="GtkBox" id="box1">
<child>
<object class="GtkLabel" id="label1">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label5">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label16">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label17">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox" id="box2">
<child>
<object class="GtkLabel" id="label6">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label8">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label9">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label10">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label11">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label12">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox" id="box3">
<child>
<object class="GtkLabel" id="label13">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label14">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label15">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label18">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label19">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label22">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label23">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label27">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label24">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label25">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label26">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox" id="box4">
<child>
<object class="GtkLabel" id="label28">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label29">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label30">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label31">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label32">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label33">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label34">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkBox" id="box5">
<child>
<object class="GtkLabel" id="label35">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label36">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label37">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label38">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label39">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label40">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<child>
<object class="GtkLabel" id="label41">
<property name="label" translatable="yes"> X X X </property>
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">4</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -1,55 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="width_request">600</property>
<property name="height_request">400</property>
<property name="title">What's my size?</property>
<child type="titlebar">
<object class="GtkHeaderBar" />
</child>
<child>
<object class="GtkGrid">
<property name="valign">center</property>
<property name="halign">center</property>
<property name="column-spacing">10</property>
<property name="row-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">default width:</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">600</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">default height:</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">400</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="width_request">600</property>
<property name="height_request">400</property>
<property name="title">What's my size?</property>
<child type="titlebar">
<object class="GtkHeaderBar" />
</child>
<child>
<object class="GtkGrid">
<property name="valign">center</property>
<property name="halign">center</property>
<property name="column-spacing">10</property>
<property name="row-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">default width:</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<!-- This binding should never do anything because the text is set to
the correct value from the start, all we do is make sure it doesn't change -->
<property name="label" bind-source="window" bind-property="default-width">600</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">default height:</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<!-- This binding should never do anything because the text is set to
the correct value from the start, all we do is make sure it doesn't change -->
<property name="label" bind-source="window" bind-property="default-height">400</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="width_request">600</property>
<property name="height_request">400</property>
<property name="decorated">0</property>
<child>
<object class="GtkGrid">
<property name="valign">center</property>
<property name="halign">center</property>
<property name="column-spacing">10</property>
<property name="row-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">default width:</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">600</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">default height:</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">400</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="width_request">600</property>
<property name="height_request">400</property>
<property name="decorated">0</property>
<child>
<object class="GtkGrid">
<property name="valign">center</property>
<property name="halign">center</property>
<property name="column-spacing">10</property>
<property name="row-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">default width:</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<!-- This binding should never do anything because the text is set to
the correct value from the start, all we do is make sure it doesn't change -->
<property name="label" bind-source="window" bind-property="default-width">600</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">default height:</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<!-- This binding should never do anything because the text is set to
the correct value from the start, all we do is make sure it doesn't change -->
<property name="label" bind-source="window" bind-property="default-height">400</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -269,13 +269,13 @@ remove_extra_css (GtkStyleProvider *provider)
}
static void
save_image (GdkTexture *texture,
const char *test_name,
const char *extension)
save_image (cairo_surface_t *surface,
const char *test_name,
const char *extension)
{
GError *error = NULL;
char *filename;
gboolean ret;
int ret;
filename = get_output_file (test_name, extension, &error);
if (filename == NULL)
@@ -286,8 +286,8 @@ save_image (GdkTexture *texture,
}
g_test_message ("Storing test result image at %s", filename);
ret = gdk_texture_save_to_png (texture, filename);
g_assert_true (ret);
ret = cairo_surface_write_to_png (surface, filename);
g_assert_true (ret == CAIRO_STATUS_SUCCESS);
g_free (filename);
}
@@ -296,7 +296,7 @@ static void
test_ui_file (GFile *file)
{
char *ui_file, *reference_file;
GdkTexture *ui_image, *reference_image, *diff_image;
cairo_surface_t *ui_image, *reference_image, *diff_image;
GtkStyleProvider *provider;
ui_file = g_file_get_path (file);
@@ -306,37 +306,25 @@ test_ui_file (GFile *file)
ui_image = reftest_snapshot_ui_file (ui_file);
if ((reference_file = get_reference_image (ui_file)) != NULL)
{
GError *error = NULL;
reference_image = gdk_texture_new_from_filename (reference_file, &error);
if (reference_image == NULL)
{
g_test_message ("Failed to load reference image: %s", error->message);
g_clear_error (&error);
g_test_fail ();
}
}
reference_image = cairo_image_surface_create_from_png (reference_file);
else if ((reference_file = get_test_file (ui_file, ".ref.ui", TRUE)) != NULL)
reference_image = reftest_snapshot_ui_file (reference_file);
else
{
reference_image = NULL;
reference_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
g_test_message ("No reference image.");
g_test_fail ();
}
g_free (reference_file);
if (reference_image == NULL)
reference_image = gdk_memory_texture_new (1, 1, GDK_MEMORY_DEFAULT, g_bytes_new ((guchar[4]) {0, 0, 0, 0}, 4), 4);
diff_image = reftest_compare_textures (ui_image, reference_image);
diff_image = reftest_compare_surfaces (ui_image, reference_image);
save_image (ui_image, ui_file, ".out.png");
save_image (reference_image, ui_file, ".ref.png");
if (diff_image)
{
save_image (diff_image, ui_file, ".diff.png");
g_object_unref (diff_image);
cairo_surface_destroy (diff_image);
g_test_fail ();
}
@@ -344,8 +332,8 @@ test_ui_file (GFile *file)
g_free (ui_file);
g_clear_object (&ui_image);
g_clear_object (&reference_image);
cairo_surface_destroy (ui_image);
cairo_surface_destroy (reference_image);
}
static int

View File

@@ -10,9 +10,9 @@ static gboolean opt_quiet;
int
main (int argc, char **argv)
{
GdkTexture *image1;
GdkTexture *image2;
GdkTexture *diff;
cairo_surface_t *image1;
cairo_surface_t *image2;
cairo_surface_t *diff;
GOptionEntry entries[] = {
{"output", 'o', 0, G_OPTION_ARG_FILENAME, &opt_filename, "Output location", "FILE" },
{"quiet", 'q', 0, G_OPTION_ARG_NONE, &opt_quiet, "Don't talk", NULL },
@@ -38,29 +38,13 @@ main (int argc, char **argv)
exit (1);
}
image1 = gdk_texture_new_from_filename (argv[1], &error);
if (image1 == NULL)
{
g_printerr ("Error loading %s: %s\n", argv[1], error->message);
exit (1);
}
image2 = gdk_texture_new_from_filename (argv[2], &error);
if (image2 == NULL)
{
g_printerr ("Error loading %s: %s\n", argv[2], error->message);
exit (1);
}
image1 = cairo_image_surface_create_from_png (argv[1]);
image2 = cairo_image_surface_create_from_png (argv[2]);
diff = reftest_compare_textures (image1, image2);
diff = reftest_compare_surfaces (image1, image2);
if (opt_filename && diff)
{
if (!gdk_texture_save_to_png (diff, opt_filename))
{
g_printerr ("Could not save diff image to %s\n", opt_filename);
exit (1);
}
}
cairo_surface_write_to_png (diff, opt_filename);
if (!opt_quiet)
{
@@ -75,5 +59,7 @@ main (int argc, char **argv)
g_print ("No differences.\n");
}
if (!opt_quiet)
return diff != NULL ? 1 : 0;
}

View File

@@ -6,12 +6,12 @@
<object class="GtkLabel" id="label1">
<property name="label" translatable="yes">Hello linky World</property>
<attributes>
<attribute name="foreground" value="#000099990000" start="1" end="3"></attribute>
<attribute name="foreground" value="#000080000000" start="1" end="3"></attribute>
<attribute name="foreground" value="#ffff00000000" start="3" end="8"></attribute>
<attribute name="foreground" value="#0000ffff0000" start="8" end="9"></attribute>
<attribute name="foreground" value="#00000000ffff" start="9" end="10"></attribute>
<attribute name="foreground" value="#ffff99999999" start="10" end="14"></attribute>
<attribute name="foreground" value="#9999ffff9999" start="14" end="16"></attribute>
<attribute name="foreground" value="#ffff80008000" start="10" end="14"></attribute>
<attribute name="foreground" value="#8000ffff8000" start="14" end="16"></attribute>
<attribute name="underline" value="True" start="6" end="11"></attribute>
</attributes>
</object>

View File

@@ -5,10 +5,10 @@
<child>
<object class="GtkLabel" id="label1">
<property name="use-markup">1</property>
<property name="label" translatable="yes">H&lt;span color=&quot;#009900&quot;&gt;ell&lt;/span&gt;o &lt;a href=&quot;http://example.com&quot;&gt;l&lt;span color=&quot;#00FF00&quot;&gt;in&lt;/span&gt;ky&lt;/a&gt; &lt;span color=&quot;#99FF99&quot;&gt;Worl&lt;/span&gt;d</property>
<property name="label" translatable="yes">H&lt;span color=&quot;#008000&quot;&gt;ell&lt;/span&gt;o &lt;a href=&quot;http://example.com&quot;&gt;l&lt;span color=&quot;#00FF00&quot;&gt;in&lt;/span&gt;ky&lt;/a&gt; &lt;span color=&quot;#80FF80&quot;&gt;Worl&lt;/span&gt;d</property>
<attributes>
<attribute name="foreground" value="#ffff00000000" start="3" end="8"></attribute>
<attribute name="foreground" value="#ffff99999999" start="10" end="14"></attribute>
<attribute name="foreground" value="#ffff80008000" start="10" end="14"></attribute>
</attributes>
</object>
</child>

View File

@@ -150,6 +150,9 @@ testdata = [
'border-style.ui',
'boxlayout-invisible-child.ref.ui',
'boxlayout-invisible-child.ui',
'box-order.css',
'box-order.ref.ui',
'box-order.ui',
'box-pseudo-classes.css',
'box-pseudo-classes.ref.ui',
'box-pseudo-classes.ui',
@@ -225,10 +228,6 @@ testdata = [
'data-url.css',
'data-url.ref.ui',
'data-url.ui',
'default-size.ui',
'default-size.ref.ui',
'default-size-with-title.ui',
'default-size-with-title.ref.ui',
'fixed-widget-stacking.ref.ui',
'fixed-widget-stacking.ui',
'flipping-icons.ref.ui',
@@ -374,8 +373,6 @@ testdata = [
'partial-rounded-border.ui',
'picture-load-invalid-file.ui',
'picture-load-invalid-file.ref.ui',
'pixbuf-icon.ref.ui',
'pixbuf-icon.ui',
'pseudoclass-on-box.css',
'pseudoclass-on-box.ref.ui',
'pseudoclass-on-box.ui',
@@ -429,8 +426,6 @@ testdata = [
'symbolic-icon-translucent-color.css',
'symbolic-icon-translucent-color.ref.ui',
'symbolic-icon-translucent-color.ui',
'texture-icon.ref.ui',
'texture-icon.ui',
'textview-border-windows.css',
'textview-border-windows.ref.ui',
'textview-border-windows.ui',
@@ -471,12 +466,11 @@ xfails = [
'sizegroups-evolution-identity-page.ui',
# these depend on details of text layout
'label-sizing.ui',
# the NGL renderer can't deal with non-integer sizes
'border-half-pixel.ui'
]
reftest_env = environment()
reftest_env.set('GTK_A11Y', 'test')
reftest_env.set('GSK_RENDERER', 'opengl')
reftest_env.set('G_TEST_SRCDIR', meson.current_source_dir())
reftest_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
reftest_env.set('GIO_USE_VFS', 'local')

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window1">
<property name="width_request">10</property>
<property name="height_request">10</property>
<property name="decorated">0</property>
<child>
<object class="GtkImage">
<property name="paintable">resource:///org/gtk/libgtk/icons/16x16/status/image-missing.png</property>
</object>
</child>
</object>
</interface>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkCellRendererPixbuf" id="just-creating-a-pixbuf">
<property name="pixbuf-expander-open">resource:///org/gtk/libgtk/icons/16x16/status/image-missing.png</property>
</object>
<object class="GtkWindow" id="window1">
<property name="width_request">10</property>
<property name="height_request">10</property>
<property name="decorated">0</property>
<child>
<object class="GtkImage">
<property name="gicon" bind-source="just-creating-a-pixbuf" bind-property="pixbuf-expander-open" bind-flags="sync-create"/>
</object>
</child>
</object>
</interface>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2011,2021 Red Hat Inc.
* Copyright (C) 2011 Red Hat Inc.
*
* Author:
* Benjamin Otte <otte@gnome.org>
@@ -22,14 +22,62 @@
#include "reftest-compare.h"
/* Compares two GDK_MEMORY_DEFAULT buffers, returning NULL if the
static void
get_surface_size (cairo_surface_t *surface,
int *width,
int *height)
{
cairo_t *cr;
double x1, x2, y1, y2;
cr = cairo_create (surface);
cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
cairo_destroy (cr);
g_assert_true (x1 == 0 && y1 == 0);
g_assert_true (x2 > 0 && y2 > 0);
g_assert_true ((int) x2 == x2 && (int) y2 == y2);
*width = x2;
*height = y2;
}
static cairo_surface_t *
coerce_surface_for_comparison (cairo_surface_t *surface,
int width,
int height)
{
cairo_surface_t *coerced;
cairo_t *cr;
coerced = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
width,
height);
cr = cairo_create (coerced);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
cairo_destroy (cr);
g_assert_true (cairo_surface_status (coerced) == CAIRO_STATUS_SUCCESS);
return coerced;
}
/* Compares two CAIRO_FORMAT_ARGB32 buffers, returning NULL if the
* buffers are equal or a surface containing a diff between the two
* surfaces.
*
* This function should be rewritten to compare all formats supported by
* cairo_format_t instead of taking a mask as a parameter.
*
* This function is originally from cairo:test/buffer-diff.c.
* Copyright © 2004 Richard D. Worth
*/
static GdkTexture *
static cairo_surface_t *
buffer_diff_core (const guchar *buf_a,
int stride_a,
const guchar *buf_b,
@@ -40,7 +88,7 @@ buffer_diff_core (const guchar *buf_a,
int x, y;
guchar *buf_diff = NULL;
int stride_diff = 0;
GdkTexture *diff = NULL;
cairo_surface_t *diff = NULL;
for (y = 0; y < height; y++)
{
@@ -64,15 +112,12 @@ buffer_diff_core (const guchar *buf_a,
if (diff == NULL)
{
GBytes *bytes;
stride_diff = 4 * width;
buf_diff = g_malloc0_n (stride_diff, height);
bytes = g_bytes_new_take (buf_diff, stride_diff * height);
diff = gdk_memory_texture_new (width, height,
GDK_MEMORY_DEFAULT,
bytes,
stride_diff);
diff = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
width,
height);
g_assert_true (cairo_surface_status (diff) == CAIRO_STATUS_SUCCESS);
buf_diff = cairo_image_surface_get_data (diff);
stride_diff = cairo_image_surface_get_stride (diff);
row = (guint32 *) (buf_diff + y * stride_diff);
}
@@ -98,8 +143,6 @@ buffer_diff_core (const guchar *buf_a,
guint8 alpha = diff_pixel >> 24;
diff_pixel = alpha * 0x010101;
}
/* make the pixel fully opaque */
diff_pixel |= 0xff000000;
row[x] = diff_pixel;
}
@@ -108,28 +151,29 @@ buffer_diff_core (const guchar *buf_a,
return diff;
}
GdkTexture *
reftest_compare_textures (GdkTexture *texture1,
GdkTexture *texture2)
cairo_surface_t *
reftest_compare_surfaces (cairo_surface_t *surface1,
cairo_surface_t *surface2)
{
int w, h;
guchar *data1, *data2;
GdkTexture *diff;
int w1, h1, w2, h2, w, h;
cairo_surface_t *coerced1, *coerced2, *diff;
w = MAX (gdk_texture_get_width (texture1), gdk_texture_get_width (texture2));
h = MAX (gdk_texture_get_height (texture1), gdk_texture_get_height (texture2));
get_surface_size (surface1, &w1, &h1);
get_surface_size (surface2, &w2, &h2);
w = MAX (w1, w2);
h = MAX (h1, h2);
coerced1 = coerce_surface_for_comparison (surface1, w, h);
coerced2 = coerce_surface_for_comparison (surface2, w, h);
data1 = g_malloc_n (w * 4, h);
gdk_texture_download (texture1, data1, w * 4);
data2 = g_malloc_n (w * 4, h);
gdk_texture_download (texture2, data2, w * 4);
diff = buffer_diff_core (data1, w * 4,
data2, w * 4,
diff = buffer_diff_core (cairo_image_surface_get_data (coerced1),
cairo_image_surface_get_stride (coerced1),
cairo_image_surface_get_data (coerced2),
cairo_image_surface_get_stride (coerced2),
w, h);
g_free (data1);
g_free (data2);
cairo_surface_destroy (coerced1);
cairo_surface_destroy (coerced2);
return diff;
}

View File

@@ -23,8 +23,8 @@
G_BEGIN_DECLS
G_MODULE_EXPORT
GdkTexture * reftest_compare_textures (GdkTexture *texture1,
GdkTexture *texture2);
cairo_surface_t * reftest_compare_surfaces (cairo_surface_t *surface1,
cairo_surface_t *surface2);
G_END_DECLS

View File

@@ -215,12 +215,12 @@ reftest_uninhibit_snapshot (void)
static void
draw_paintable (GdkPaintable *paintable,
gpointer out_texture)
gpointer out_surface)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
GdkTexture *texture;
GskRenderer *renderer;
cairo_surface_t *surface;
cairo_t *cr;
if (inhibit_count > 0)
return;
@@ -238,30 +238,27 @@ draw_paintable (GdkPaintable *paintable,
if (node == NULL)
return;
renderer = gtk_native_get_renderer (
gtk_widget_get_native (
gtk_widget_paintable_get_widget (GTK_WIDGET_PAINTABLE (paintable))));
texture = gsk_renderer_render_texture (renderer,
node,
&GRAPHENE_RECT_INIT (
0, 0,
gdk_paintable_get_intrinsic_width (paintable),
gdk_paintable_get_intrinsic_height (paintable)
));
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
gdk_paintable_get_intrinsic_width (paintable),
gdk_paintable_get_intrinsic_height (paintable));
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
g_signal_handlers_disconnect_by_func (paintable, draw_paintable, out_texture);
g_signal_handlers_disconnect_by_func (paintable, draw_paintable, out_surface);
*(GdkTexture **) out_texture = texture;
*(cairo_surface_t **) out_surface = surface;
g_idle_add (quit_when_idle, loop);
}
static GdkTexture *
static cairo_surface_t *
snapshot_widget (GtkWidget *widget)
{
GdkPaintable *paintable;
GdkTexture *texture = NULL;
cairo_surface_t *surface;
g_assert_true (gtk_widget_get_realized (widget));
@@ -273,17 +270,17 @@ snapshot_widget (GtkWidget *widget)
* to delay the snapshot.
*/
paintable = gtk_widget_paintable_new (widget);
g_signal_connect (paintable, "invalidate-contents", G_CALLBACK (draw_paintable), &texture);
g_signal_connect (paintable, "invalidate-contents", G_CALLBACK (draw_paintable), &surface);
g_main_loop_run (loop);
g_main_loop_unref (loop);
g_object_unref (paintable);
gtk_window_destroy (GTK_WINDOW (widget));
return texture;
return surface;
}
GdkTexture *
cairo_surface_t *
reftest_snapshot_ui_file (const char *ui_file)
{
GtkWidget *window;

View File

@@ -23,7 +23,7 @@
G_BEGIN_DECLS
G_MODULE_EXPORT
GdkTexture * reftest_snapshot_ui_file (const char *ui_file);
cairo_surface_t * reftest_snapshot_ui_file (const char *ui_file);
G_END_DECLS

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window1">
<property name="width_request">10</property>
<property name="height_request">10</property>
<property name="decorated">0</property>
<child>
<object class="GtkImage">
<property name="paintable">resource:///org/gtk/libgtk/icons/16x16/status/image-missing.png</property>
</object>
</child>
</object>
</interface>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkImage" id="just-creating-a-texture">
<property name="paintable">resource:///org/gtk/libgtk/icons/16x16/status/image-missing.png</property>
</object>
<object class="GtkWindow" id="window1">
<property name="width_request">10</property>
<property name="height_request">10</property>
<property name="decorated">0</property>
<child>
<object class="GtkImage">
<property name="gicon" bind-source="just-creating-a-texture" bind-property="paintable" bind-flags="sync-create"/>
</object>
</child>
</object>
</interface>