mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 22:20:24 +00:00
Merge branch 'modern-testsuite' into 'master'
testsuite: modernize image handling Closes #4261 See merge request GNOME/gtk!3955
This commit is contained in:
commit
698b3542a1
@ -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
|
||||
|
@ -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`
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
5
testsuite/gsk/compare/border-bottom-right.node
Normal file
5
testsuite/gsk/compare/border-bottom-right.node
Normal file
@ -0,0 +1,5 @@
|
||||
border {
|
||||
colors: red;
|
||||
outline: 0 0 20 20;
|
||||
widths: 0 10 10 0;
|
||||
}
|
BIN
testsuite/gsk/compare/border-bottom-right.png
Normal file
BIN
testsuite/gsk/compare/border-bottom-right.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 103 B |
15
testsuite/gsk/compare/opacity-overdraw.node
Normal file
15
testsuite/gsk/compare/opacity-overdraw.node
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
testsuite/gsk/compare/opacity-overdraw.png
Normal file
BIN
testsuite/gsk/compare/opacity-overdraw.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 127 B |
@ -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',
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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>
|
@ -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>
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -5,10 +5,10 @@
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="use-markup">1</property>
|
||||
<property name="label" translatable="yes">H<span color="#008000">ell</span>o <a href="http://example.com">l<span color="#00FF00">in</span>ky</a> <span color="#80FF80">Worl</span>d</property>
|
||||
<property name="label" translatable="yes">H<span color="#009900">ell</span>o <a href="http://example.com">l<span color="#00FF00">in</span>ky</a> <span color="#99FF99">Worl</span>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>
|
||||
|
@ -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 |
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user