Merge branch 'modern-testsuite' into 'master'

testsuite: modernize image handling

Closes #4261

See merge request GNOME/gtk!3955
This commit is contained in:
Benjamin Otte 2021-09-16 22:22:56 +00:00
commit 698b3542a1
29 changed files with 376 additions and 734 deletions

View File

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

View File

@ -441,6 +441,39 @@ gdk_texture_new_from_bytes (GBytes *bytes,
return texture;
}
/**
* gdk_texture_new_from_filename:
* @path: (type filename): the filename to load
* @error: Return location for an error
*
* Creates a new texture by loading an image from a file.
*
* The file format is detected automatically. The supported formats
* are PNG and JPEG, though more formats might be available.
*
* If %NULL is returned, then @error will be set.
*
* Return value: A newly-created `GdkTexture`
*/
GdkTexture *
gdk_texture_new_from_filename (const char *path,
GError **error)
{
GdkTexture *texture;
GFile *file;
g_return_val_if_fail (path, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
file = g_file_new_for_path (path);
texture = gdk_texture_new_from_file (file, error);
g_object_unref (file);
return texture;
}
/**
* gdk_texture_get_width: (attributes org.gtk.Method.get_property=width)
* @texture: a `GdkTexture`

View File

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

@ -802,6 +802,11 @@ 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);
@ -2336,7 +2341,8 @@ 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_cluster_start &&
!glyphs[i].attr.is_color)
{
switch (j + MIN_ASCII_GLYPH)
{
@ -2366,6 +2372,7 @@ 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,6 +2382,8 @@ 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

@ -252,6 +252,9 @@ 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));
@ -1734,7 +1737,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[1], widths[2]),
&GRAPHENE_RECT_INIT (origin->x + widths[3], origin->y + size->height - widths[2], size->width - widths[3], widths[2]),
color);
}
@ -2768,6 +2771,58 @@ 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)
@ -2780,7 +2835,16 @@ gsk_ngl_render_job_visit_opacity_node (GskNglRenderJob *job,
{
float prev_alpha = gsk_ngl_render_job_set_alpha (job, new_alpha);
if (gsk_render_node_get_node_type (child) == GSK_CONTAINER_NODE)
/* 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
{
GskNglRenderOffscreen offscreen = {0};
@ -2788,9 +2852,7 @@ gsk_ngl_render_job_visit_opacity_node (GskNglRenderJob *job,
offscreen.force_offscreen = TRUE;
offscreen.reset_clip = TRUE;
/* The semantics of an opacity node mandate that when, e.g., two
* color nodes overlap, there may not be any blending between them.
*/
/* Note: offscreen rendering resets alpha to 1.0 */
if (!gsk_ngl_render_job_visit_node_with_offscreen (job, child, &offscreen))
return;
@ -2805,10 +2867,6 @@ 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);
}
@ -3000,21 +3058,24 @@ 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;
@ -3999,7 +4060,7 @@ gsk_ngl_render_job_new (GskNglDriver *driver,
job->scale_y = scale_factor;
job->viewport = *viewport;
gsk_ngl_render_job_set_alpha (job, 1.0);
gsk_ngl_render_job_set_alpha (job, 1.0f);
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

@ -49,6 +49,7 @@ 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);
@ -109,9 +110,16 @@ 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);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ceil (bounds.size.width), ceil (bounds.size.height));
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);
cr = cairo_create (surface);
cairo_translate (cr, - bounds.origin.x, - bounds.origin.y);
@ -132,15 +140,23 @@ 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++)
{
@ -153,15 +169,7 @@ 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);
}
@ -170,19 +178,15 @@ main(int argc, char **argv)
if (argc > 2)
{
cairo_status_t status;
status = cairo_surface_write_to_png (surface, argv[2]);
if (status != CAIRO_STATUS_SUCCESS)
if (!gdk_texture_save_to_png (texture, argv[2]))
{
cairo_surface_destroy (surface);
g_print ("Failed to save PNG file: %s\n", cairo_status_to_string (status));
g_object_unref (texture);
g_print ("Failed to save PNG file\n");
return 1;
}
}
cairo_surface_destroy (surface);
g_object_unref (texture);
return 0;
}

View File

@ -11,6 +11,7 @@ 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);
@ -25,6 +26,8 @@ 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
@ -43,8 +46,18 @@ 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);
}
@ -76,20 +89,26 @@ texture_threads (void)
ensure_texture_access (texture);
g_assert_nonnull (gdk_gl_context_get_current ());
/* 4. Run a thread trying to download the texture */
/* 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 */
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);
/* 5. Run the main loop waiting for the thread to return */
/* 6. Run the main loop waiting for the thread to return */
g_main_loop_run (loop);
/* 6. All good */
/* 7. 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 (cairo_surface_t *surface,
const char *test_name,
const char *extension)
save_image (GdkTexture *texture,
const char *test_name,
const char *extension)
{
char *filename = get_output_file (test_name, ".node", extension);
int status;
gboolean result;
g_print ("Storing test result image at %s\n", filename);
status = cairo_surface_write_to_png (surface, filename);
g_assert_true (status == CAIRO_STATUS_SUCCESS);
result = gdk_texture_save_to_png (texture, filename);
g_assert_true (result);
g_free (filename);
}
@ -149,10 +149,8 @@ static const GOptionEntry options[] = {
int
main (int argc, char **argv)
{
cairo_surface_t *reference_surface = NULL;
cairo_surface_t *rendered_surface = NULL;
cairo_surface_t *diff_surface = NULL;
GdkTexture *texture;
GdkTexture *reference_texture;
GdkTexture *rendered_texture;
GskRenderer *renderer;
GdkSurface *window;
GskRenderNode *node;
@ -215,43 +213,36 @@ main (int argc, char **argv)
}
/* Render the .node file and download to cairo surface */
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);
rendered_texture = gsk_renderer_render_texture (renderer, node, NULL);
g_assert_nonnull (rendered_texture);
/* Load the given reference png file */
reference_surface = cairo_image_surface_create_from_png (png_file);
if (cairo_surface_status (reference_surface))
reference_texture = gdk_texture_new_from_filename (png_file, &error);
if (reference_texture == NULL)
{
g_print ("Error loading reference surface: %s\n",
cairo_status_to_string (cairo_surface_status (reference_surface)));
g_print ("Error loading reference surface: %s\n", error->message);
g_clear_error (&error);
success = FALSE;
}
else
{
/* Now compare the two */
diff_surface = reftest_compare_surfaces (rendered_surface, reference_surface);
GdkTexture *diff_texture;
if (diff_surface)
/* Now compare the two */
diff_texture = reftest_compare_textures (rendered_texture, reference_texture);
if (diff_texture)
{
save_image (diff_surface, node_file, ".diff.png");
cairo_surface_destroy (diff_surface);
save_image (diff_texture, node_file, ".diff.png");
g_object_unref (diff_texture);
success = FALSE;
}
}
save_image (rendered_surface, node_file, ".out.png");
save_image (rendered_texture, node_file, ".out.png");
cairo_surface_destroy (reference_surface);
cairo_surface_destroy (rendered_surface);
g_object_unref (texture);
g_object_unref (reference_texture);
g_object_unref (rendered_texture);
gsk_render_node_unref (node);

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

View File

@ -0,0 +1,15 @@
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.

After

Width:  |  Height:  |  Size: 127 B

View File

@ -23,6 +23,7 @@ compare_render_tests = [
'blend-difference',
'blend-invisible-child',
'blend-normal',
'border-bottom-right',
'borders-rotated',
'borders-scaled',
'clip-coordinates-2d',
@ -62,6 +63,7 @@ compare_render_tests = [
'issue-3615',
'nested-rounded-clips',
'opacity_clip',
'opacity-overdraw',
'opacity-overlapping-children',
'outset_shadow_offset_both',
'outset_shadow_offset_x',

View File

@ -1,17 +1,17 @@
@import "reset-to-defaults.css";
#button1 {
background-image: linear-gradient(alpha(red, 0.50),alpha(red,0.50)), linear-gradient(lime,lime);
background-image: linear-gradient(alpha(red, 0.60),alpha(red,0.60)), linear-gradient(lime,lime);
}
#button2 {
background-color: lime;
background-image: linear-gradient(alpha(red, 0.50),alpha(red,0.50)), linear-gradient(transparent,transparent);
background-image: linear-gradient(alpha(red, 0.60),alpha(red,0.60)), linear-gradient(transparent,transparent);
}
#button3 {
padding: 12px;
background-image: linear-gradient(alpha(red, 0.50),alpha(red,0.50)), linear-gradient(lime,lime);
background-image: linear-gradient(alpha(red, 0.60),alpha(red,0.60)), linear-gradient(lime,lime);
background-clip: content-box;
}
@ -30,12 +30,12 @@
#ref1,
#ref2 {
background-color: #807f00;
background-color: #996600;
}
#ref3 {
padding: 12px;
background-color: #807f00;
background-color: #996600;
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.5);
border-color: rgba(255,0,0,0.6);
padding: 10px;
background-color: rgb(0,0,255);

View File

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

View File

@ -1,32 +0,0 @@
* {
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

@ -1,225 +0,0 @@
<?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

@ -1,245 +0,0 @@
<?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

@ -269,13 +269,13 @@ remove_extra_css (GtkStyleProvider *provider)
}
static void
save_image (cairo_surface_t *surface,
const char *test_name,
const char *extension)
save_image (GdkTexture *texture,
const char *test_name,
const char *extension)
{
GError *error = NULL;
char *filename;
int ret;
gboolean ret;
filename = get_output_file (test_name, extension, &error);
if (filename == NULL)
@ -286,8 +286,8 @@ save_image (cairo_surface_t *surface,
}
g_test_message ("Storing test result image at %s", filename);
ret = cairo_surface_write_to_png (surface, filename);
g_assert_true (ret == CAIRO_STATUS_SUCCESS);
ret = gdk_texture_save_to_png (texture, filename);
g_assert_true (ret);
g_free (filename);
}
@ -296,7 +296,7 @@ static void
test_ui_file (GFile *file)
{
char *ui_file, *reference_file;
cairo_surface_t *ui_image, *reference_image, *diff_image;
GdkTexture *ui_image, *reference_image, *diff_image;
GtkStyleProvider *provider;
ui_file = g_file_get_path (file);
@ -306,25 +306,37 @@ test_ui_file (GFile *file)
ui_image = reftest_snapshot_ui_file (ui_file);
if ((reference_file = get_reference_image (ui_file)) != NULL)
reference_image = cairo_image_surface_create_from_png (reference_file);
{
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 ();
}
}
else if ((reference_file = get_test_file (ui_file, ".ref.ui", TRUE)) != NULL)
reference_image = reftest_snapshot_ui_file (reference_file);
else
{
reference_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
reference_image = NULL;
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_surfaces (ui_image, reference_image);
diff_image = reftest_compare_textures (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");
cairo_surface_destroy (diff_image);
g_object_unref (diff_image);
g_test_fail ();
}
@ -332,8 +344,8 @@ test_ui_file (GFile *file)
g_free (ui_file);
cairo_surface_destroy (ui_image);
cairo_surface_destroy (reference_image);
g_clear_object (&ui_image);
g_clear_object (&reference_image);
}
static int

View File

@ -10,9 +10,9 @@ static gboolean opt_quiet;
int
main (int argc, char **argv)
{
cairo_surface_t *image1;
cairo_surface_t *image2;
cairo_surface_t *diff;
GdkTexture *image1;
GdkTexture *image2;
GdkTexture *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,13 +38,29 @@ main (int argc, char **argv)
exit (1);
}
image1 = cairo_image_surface_create_from_png (argv[1]);
image2 = cairo_image_surface_create_from_png (argv[2]);
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);
}
diff = reftest_compare_surfaces (image1, image2);
diff = reftest_compare_textures (image1, image2);
if (opt_filename && diff)
cairo_surface_write_to_png (diff, opt_filename);
{
if (!gdk_texture_save_to_png (diff, opt_filename))
{
g_printerr ("Could not save diff image to %s\n", opt_filename);
exit (1);
}
}
if (!opt_quiet)
{
@ -59,7 +75,5 @@ 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="#000080000000" start="1" end="3"></attribute>
<attribute name="foreground" value="#000099990000" 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="#ffff80008000" start="10" end="14"></attribute>
<attribute name="foreground" value="#8000ffff8000" start="14" end="16"></attribute>
<attribute name="foreground" value="#ffff99999999" start="10" end="14"></attribute>
<attribute name="foreground" value="#9999ffff9999" 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;#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>
<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>
<attributes>
<attribute name="foreground" value="#ffff00000000" start="3" end="8"></attribute>
<attribute name="foreground" value="#ffff80008000" start="10" end="14"></attribute>
<attribute name="foreground" value="#ffff99999999" start="10" end="14"></attribute>
</attributes>
</object>
</child>

View File

@ -150,9 +150,6 @@ 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',
@ -466,11 +463,12 @@ 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')

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 Red Hat Inc.
* Copyright (C) 2011,2021 Red Hat Inc.
*
* Author:
* Benjamin Otte <otte@gnome.org>
@ -22,62 +22,14 @@
#include "reftest-compare.h"
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
/* Compares two GDK_MEMORY_DEFAULT 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 cairo_surface_t *
static GdkTexture *
buffer_diff_core (const guchar *buf_a,
int stride_a,
const guchar *buf_b,
@ -88,7 +40,7 @@ buffer_diff_core (const guchar *buf_a,
int x, y;
guchar *buf_diff = NULL;
int stride_diff = 0;
cairo_surface_t *diff = NULL;
GdkTexture *diff = NULL;
for (y = 0; y < height; y++)
{
@ -112,12 +64,15 @@ buffer_diff_core (const guchar *buf_a,
if (diff == NULL)
{
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);
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);
row = (guint32 *) (buf_diff + y * stride_diff);
}
@ -143,6 +98,8 @@ 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;
}
@ -151,29 +108,28 @@ buffer_diff_core (const guchar *buf_a,
return diff;
}
cairo_surface_t *
reftest_compare_surfaces (cairo_surface_t *surface1,
cairo_surface_t *surface2)
GdkTexture *
reftest_compare_textures (GdkTexture *texture1,
GdkTexture *texture2)
{
int w1, h1, w2, h2, w, h;
cairo_surface_t *coerced1, *coerced2, *diff;
int w, h;
guchar *data1, *data2;
GdkTexture *diff;
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);
w = MAX (gdk_texture_get_width (texture1), gdk_texture_get_width (texture2));
h = MAX (gdk_texture_get_height (texture1), gdk_texture_get_height (texture2));
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),
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,
w, h);
cairo_surface_destroy (coerced1);
cairo_surface_destroy (coerced2);
g_free (data1);
g_free (data2);
return diff;
}

View File

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

View File

@ -215,12 +215,12 @@ reftest_uninhibit_snapshot (void)
static void
draw_paintable (GdkPaintable *paintable,
gpointer out_surface)
gpointer out_texture)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
cairo_surface_t *surface;
cairo_t *cr;
GdkTexture *texture;
GskRenderer *renderer;
if (inhibit_count > 0)
return;
@ -238,27 +238,30 @@ draw_paintable (GdkPaintable *paintable,
if (node == NULL)
return;
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);
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)
));
gsk_render_node_unref (node);
g_signal_handlers_disconnect_by_func (paintable, draw_paintable, out_surface);
g_signal_handlers_disconnect_by_func (paintable, draw_paintable, out_texture);
*(cairo_surface_t **) out_surface = surface;
*(GdkTexture **) out_texture = texture;
g_idle_add (quit_when_idle, loop);
}
static cairo_surface_t *
static GdkTexture *
snapshot_widget (GtkWidget *widget)
{
GdkPaintable *paintable;
cairo_surface_t *surface;
GdkTexture *texture = NULL;
g_assert_true (gtk_widget_get_realized (widget));
@ -270,17 +273,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), &surface);
g_signal_connect (paintable, "invalidate-contents", G_CALLBACK (draw_paintable), &texture);
g_main_loop_run (loop);
g_main_loop_unref (loop);
g_object_unref (paintable);
gtk_window_destroy (GTK_WINDOW (widget));
return surface;
return texture;
}
cairo_surface_t *
GdkTexture *
reftest_snapshot_ui_file (const char *ui_file)
{
GtkWidget *window;

View File

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