mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-14 04:31:09 +00:00
Merge branch 'gsk-flip-tests' into 'main'
more gsk tests See merge request GNOME/gtk!5811
This commit is contained in:
commit
64f9d82506
@ -50,6 +50,7 @@ case "${backend}" in
|
||||
--suite=gtk \
|
||||
--no-suite=failing \
|
||||
--no-suite=flaky \
|
||||
--no-suite=${backend}_failing \
|
||||
--no-suite=gsk-compare-broadway
|
||||
exit_code=$?
|
||||
|
||||
|
@ -356,7 +356,8 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
|
||||
for (x = 0; x < width; x += max_size)
|
||||
{
|
||||
texture = gsk_gl_renderer_render_texture (renderer, root,
|
||||
&GRAPHENE_RECT_INIT (x, y,
|
||||
&GRAPHENE_RECT_INIT (viewport->origin.x + x,
|
||||
viewport->origin.y + y,
|
||||
MIN (max_size, viewport->size.width - x),
|
||||
MIN (max_size, viewport->size.height - y)));
|
||||
gdk_texture_download (texture,
|
||||
|
@ -54,27 +54,6 @@
|
||||
/* Make sure gradient stops fits in packed array_count */
|
||||
G_STATIC_ASSERT ((MAX_GRADIENT_STOPS * 5) < (1 << GSK_GL_UNIFORM_ARRAY_BITS));
|
||||
|
||||
#define rounded_rect_top_left(r) \
|
||||
(GRAPHENE_RECT_INIT(r->bounds.origin.x, \
|
||||
r->bounds.origin.y, \
|
||||
r->corner[0].width, r->corner[0].height))
|
||||
#define rounded_rect_top_right(r) \
|
||||
(GRAPHENE_RECT_INIT(r->bounds.origin.x + r->bounds.size.width - r->corner[1].width, \
|
||||
r->bounds.origin.y, \
|
||||
r->corner[1].width, r->corner[1].height))
|
||||
#define rounded_rect_bottom_right(r) \
|
||||
(GRAPHENE_RECT_INIT(r->bounds.origin.x + r->bounds.size.width - r->corner[2].width, \
|
||||
r->bounds.origin.y + r->bounds.size.height - r->corner[2].height, \
|
||||
r->corner[2].width, r->corner[2].height))
|
||||
#define rounded_rect_bottom_left(r) \
|
||||
(GRAPHENE_RECT_INIT(r->bounds.origin.x, \
|
||||
r->bounds.origin.y + r->bounds.size.height - r->corner[2].height, \
|
||||
r->corner[3].width, r->corner[3].height))
|
||||
#define rounded_rect_corner0(r) rounded_rect_top_left(r)
|
||||
#define rounded_rect_corner1(r) rounded_rect_top_right(r)
|
||||
#define rounded_rect_corner2(r) rounded_rect_bottom_right(r)
|
||||
#define rounded_rect_corner3(r) rounded_rect_bottom_left(r)
|
||||
#define rounded_rect_corner(r, i) (rounded_rect_corner##i(r))
|
||||
#define ALPHA_IS_CLEAR(alpha) ((alpha) < ((float) 0x00ff / (float) 0xffff))
|
||||
#define RGBA_IS_CLEAR(rgba) ALPHA_IS_CLEAR((rgba)->alpha)
|
||||
|
||||
@ -429,70 +408,6 @@ rect_intersects (const graphene_rect_t *r1,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
rounded_rect_has_corner (const GskRoundedRect *r,
|
||||
guint i)
|
||||
{
|
||||
return r->corner[i].width > 0 && r->corner[i].height > 0;
|
||||
}
|
||||
|
||||
/* Current clip is NOT rounded but new one is definitely! */
|
||||
static inline gboolean
|
||||
intersect_rounded_rectilinear (const graphene_rect_t *non_rounded,
|
||||
const GskRoundedRect *rounded,
|
||||
GskRoundedRect *result)
|
||||
{
|
||||
gboolean corners[4];
|
||||
|
||||
/* Intersects with top left corner? */
|
||||
corners[0] = rounded_rect_has_corner (rounded, 0) &&
|
||||
rect_intersects (non_rounded,
|
||||
&rounded_rect_corner (rounded, 0));
|
||||
if (corners[0] && !rect_contains_rect (non_rounded,
|
||||
&rounded_rect_corner (rounded, 0)))
|
||||
return FALSE;
|
||||
|
||||
/* top right ? */
|
||||
corners[1] = rounded_rect_has_corner (rounded, 1) &&
|
||||
rect_intersects (non_rounded,
|
||||
&rounded_rect_corner (rounded, 1));
|
||||
if (corners[1] && !rect_contains_rect (non_rounded,
|
||||
&rounded_rect_corner (rounded, 1)))
|
||||
return FALSE;
|
||||
|
||||
/* bottom right ? */
|
||||
corners[2] = rounded_rect_has_corner (rounded, 2) &&
|
||||
rect_intersects (non_rounded,
|
||||
&rounded_rect_corner (rounded, 2));
|
||||
if (corners[2] && !rect_contains_rect (non_rounded,
|
||||
&rounded_rect_corner (rounded, 2)))
|
||||
return FALSE;
|
||||
|
||||
/* bottom left ? */
|
||||
corners[3] = rounded_rect_has_corner (rounded, 3) &&
|
||||
rect_intersects (non_rounded,
|
||||
&rounded_rect_corner (rounded, 3));
|
||||
if (corners[3] && !rect_contains_rect (non_rounded,
|
||||
&rounded_rect_corner (rounded, 3)))
|
||||
return FALSE;
|
||||
|
||||
/* We do intersect with at least one of the corners, but in such a way that the
|
||||
* intersection between the two clips can still be represented by a single rounded
|
||||
* rect in a trivial way. do that.
|
||||
*/
|
||||
graphene_rect_intersection (non_rounded, &rounded->bounds, &result->bounds);
|
||||
|
||||
for (guint i = 0; i < 4; i++)
|
||||
{
|
||||
if (corners[i])
|
||||
result->corner[i] = rounded->corner[i];
|
||||
else
|
||||
result->corner[i].width = result->corner[i].height = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_projection_matrix (graphene_matrix_t *projection,
|
||||
const graphene_rect_t *viewport)
|
||||
@ -551,13 +466,14 @@ extract_matrix_metadata (GskGLRenderModelview *modelview)
|
||||
|
||||
case GSK_TRANSFORM_CATEGORY_2D:
|
||||
{
|
||||
float xx, xy, yx, yy, dx, dy;
|
||||
float skew_x, skew_y, angle, dx, dy;
|
||||
|
||||
gsk_transform_to_2d (modelview->transform,
|
||||
&xx, &xy, &yx, &yy, &dx, &dy);
|
||||
|
||||
modelview->scale_x = sqrtf (xx * xx + xy * xy);
|
||||
modelview->scale_y = sqrtf (yx * yx + yy * yy);
|
||||
gsk_transform_to_2d_components (modelview->transform,
|
||||
&skew_x, &skew_y,
|
||||
&modelview->scale_x, &modelview->scale_y,
|
||||
&angle, &dx, &dy);
|
||||
modelview->dx = 0;
|
||||
modelview->dy = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -918,7 +834,7 @@ gsk_gl_render_job_untransform_bounds (GskGLRenderJob *job,
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_transform_rounded_rect (GskGLRenderJob *job,
|
||||
gsk_gl_render_job_translate_rounded_rect (GskGLRenderJob *job,
|
||||
const GskRoundedRect *rect,
|
||||
GskRoundedRect *out_rect)
|
||||
{
|
||||
@ -929,6 +845,52 @@ gsk_gl_render_job_transform_rounded_rect (GskGLRenderJob *job,
|
||||
memcpy (out_rect->corner, rect->corner, sizeof rect->corner);
|
||||
}
|
||||
|
||||
static inline void
|
||||
rounded_rect_scale_corners (const GskRoundedRect *rect,
|
||||
GskRoundedRect *out_rect,
|
||||
float scale_x,
|
||||
float scale_y)
|
||||
{
|
||||
for (guint i = 0; i < G_N_ELEMENTS (out_rect->corner); i++)
|
||||
{
|
||||
out_rect->corner[i].width = rect->corner[i].width * fabs (scale_x);
|
||||
out_rect->corner[i].height = rect->corner[i].height * fabs (scale_y);
|
||||
}
|
||||
|
||||
if (scale_x < 0)
|
||||
{
|
||||
graphene_size_t p;
|
||||
|
||||
p = out_rect->corner[GSK_CORNER_TOP_LEFT];
|
||||
out_rect->corner[GSK_CORNER_TOP_LEFT] = out_rect->corner[GSK_CORNER_TOP_RIGHT];
|
||||
out_rect->corner[GSK_CORNER_TOP_RIGHT] = p;
|
||||
p = out_rect->corner[GSK_CORNER_BOTTOM_LEFT];
|
||||
out_rect->corner[GSK_CORNER_BOTTOM_LEFT] = out_rect->corner[GSK_CORNER_BOTTOM_RIGHT];
|
||||
out_rect->corner[GSK_CORNER_BOTTOM_RIGHT] = p;
|
||||
}
|
||||
|
||||
if (scale_y < 0)
|
||||
{
|
||||
graphene_size_t p;
|
||||
|
||||
p = out_rect->corner[GSK_CORNER_TOP_LEFT];
|
||||
out_rect->corner[GSK_CORNER_TOP_LEFT] = out_rect->corner[GSK_CORNER_BOTTOM_LEFT];
|
||||
out_rect->corner[GSK_CORNER_BOTTOM_LEFT] = p;
|
||||
p = out_rect->corner[GSK_CORNER_TOP_RIGHT];
|
||||
out_rect->corner[GSK_CORNER_TOP_RIGHT] = out_rect->corner[GSK_CORNER_BOTTOM_RIGHT];
|
||||
out_rect->corner[GSK_CORNER_BOTTOM_RIGHT] = p;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_gl_render_job_transform_rounded_rect (GskGLRenderJob *job,
|
||||
const GskRoundedRect *rect,
|
||||
GskRoundedRect *out_rect)
|
||||
{
|
||||
gsk_gl_render_job_transform_bounds (job, &rect->bounds, &out_rect->bounds);
|
||||
rounded_rect_scale_corners (rect, out_rect, job->scale_x, job->scale_y);
|
||||
}
|
||||
|
||||
static inline void
|
||||
rounded_rect_get_inner (const GskRoundedRect *rect,
|
||||
graphene_rect_t *inner)
|
||||
@ -1231,13 +1193,12 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
|
||||
{
|
||||
float scale_x = job->scale_x;
|
||||
float scale_y = job->scale_y;
|
||||
int surface_width = ceilf (node->bounds.size.width * scale_x);
|
||||
int surface_height = ceilf (node->bounds.size.height * scale_y);
|
||||
int surface_width = ceilf (node->bounds.size.width * fabs (scale_x));
|
||||
int surface_height = ceilf (node->bounds.size.height * fabs (scale_y));
|
||||
GdkTexture *texture;
|
||||
cairo_surface_t *surface;
|
||||
cairo_surface_t *rendered_surface;
|
||||
cairo_t *cr;
|
||||
int cached_id;
|
||||
int texture_id;
|
||||
GskTextureKey key;
|
||||
|
||||
@ -1249,18 +1210,10 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
|
||||
key.scale_x = scale_x;
|
||||
key.scale_y = scale_y;
|
||||
|
||||
cached_id = gsk_gl_driver_lookup_texture (job->driver, &key);
|
||||
texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
|
||||
|
||||
if (cached_id != 0)
|
||||
{
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
GL_TEXTURE_2D, GL_TEXTURE0, cached_id);
|
||||
gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds);
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
return;
|
||||
}
|
||||
if (texture_id != 0)
|
||||
goto done;
|
||||
|
||||
/* We first draw the recording surface on an image surface,
|
||||
* just because the scaleY(-1) later otherwise screws up the
|
||||
@ -1270,7 +1223,7 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
|
||||
surface_width,
|
||||
surface_height);
|
||||
|
||||
cairo_surface_set_device_scale (rendered_surface, scale_x, scale_y);
|
||||
cairo_surface_set_device_scale (rendered_surface, fabs (scale_x), fabs (scale_y));
|
||||
cr = cairo_create (rendered_surface);
|
||||
|
||||
cairo_save (cr);
|
||||
@ -1284,15 +1237,16 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
surface_width,
|
||||
surface_height);
|
||||
cairo_surface_set_device_scale (surface, scale_x, scale_y);
|
||||
cairo_surface_set_device_scale (surface, fabs (scale_x), fabs (scale_y));
|
||||
cr = cairo_create (surface);
|
||||
|
||||
/* We draw upside down here, so it matches what GL does. */
|
||||
cairo_save (cr);
|
||||
cairo_scale (cr, 1, -1);
|
||||
cairo_translate (cr, 0, - surface_height / scale_y);
|
||||
cairo_scale (cr, scale_x < 0 ? -1 : 1, scale_y < 0 ? 1 : -1);
|
||||
cairo_translate (cr, scale_x < 0 ? - surface_width / fabs (scale_x) : 0,
|
||||
scale_y < 0 ? 0 : - surface_height / fabs (scale_y));
|
||||
cairo_set_source_surface (cr, rendered_surface, 0, 0);
|
||||
cairo_rectangle (cr, 0, 0, surface_width / scale_x, surface_height / scale_y);
|
||||
cairo_rectangle (cr, 0, 0, surface_width / fabs (scale_x), surface_height / fabs (scale_y));
|
||||
cairo_fill (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
@ -1331,6 +1285,16 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
|
||||
|
||||
gsk_gl_driver_cache_texture (job->driver, &key, texture_id);
|
||||
|
||||
done:
|
||||
if (scale_x < 0 || scale_y < 0)
|
||||
{
|
||||
GskTransform *transform = gsk_transform_translate (NULL,
|
||||
&GRAPHENE_POINT_INIT (scale_x < 0 ? - surface_width : 0,
|
||||
scale_y < 0 ? - surface_height : 0));
|
||||
gsk_gl_render_job_push_modelview (job, transform);
|
||||
gsk_transform_unref (transform);
|
||||
}
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
@ -1339,6 +1303,9 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
|
||||
texture_id);
|
||||
gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds);
|
||||
gsk_gl_render_job_end_draw (job);
|
||||
|
||||
if (scale_x < 0 || scale_y < 0)
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
}
|
||||
|
||||
static guint
|
||||
@ -1493,10 +1460,10 @@ blur_node (GskGLRenderJob *job,
|
||||
|
||||
offscreen->texture_id = blur_offscreen (job,
|
||||
offscreen,
|
||||
texture_width * scale_x,
|
||||
texture_height * scale_y,
|
||||
blur_radius * scale_x,
|
||||
blur_radius * scale_y);
|
||||
texture_width * fabs (scale_x),
|
||||
texture_height * fabs (scale_y),
|
||||
blur_radius * fabs (scale_x),
|
||||
blur_radius * fabs (scale_y));
|
||||
init_full_texture_region (offscreen);
|
||||
}
|
||||
|
||||
@ -1678,6 +1645,7 @@ gsk_gl_render_job_visit_clipped_child (GskGLRenderJob *job,
|
||||
{
|
||||
graphene_rect_t transformed_clip;
|
||||
GskRoundedRect intersection;
|
||||
GskRoundedRectIntersection result;
|
||||
|
||||
gsk_gl_render_job_transform_bounds (job, clip, &transformed_clip);
|
||||
|
||||
@ -1691,10 +1659,17 @@ gsk_gl_render_job_visit_clipped_child (GskGLRenderJob *job,
|
||||
gsk_gl_render_job_push_clip (job, &intersection);
|
||||
gsk_gl_render_job_visit_node (job, child);
|
||||
gsk_gl_render_job_pop_clip (job);
|
||||
return;
|
||||
}
|
||||
else if (intersect_rounded_rectilinear (&transformed_clip,
|
||||
&job->current_clip->rect,
|
||||
&intersection))
|
||||
|
||||
result = gsk_rounded_rect_intersect_with_rect (&job->current_clip->rect,
|
||||
&transformed_clip,
|
||||
&intersection);
|
||||
|
||||
if (result == GSK_INTERSECTION_EMPTY)
|
||||
return;
|
||||
|
||||
if (result == GSK_INTERSECTION_NONEMPTY)
|
||||
{
|
||||
gsk_gl_render_job_push_clip (job, &intersection);
|
||||
gsk_gl_render_job_visit_node (job, child);
|
||||
@ -1741,28 +1716,26 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job,
|
||||
const GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
|
||||
const GskRoundedRect *clip = gsk_rounded_clip_node_get_clip (node);
|
||||
GskRoundedRect transformed_clip;
|
||||
float scale_x = job->scale_x;
|
||||
float scale_y = job->scale_y;
|
||||
gboolean need_offscreen;
|
||||
|
||||
if (node_is_invisible (child))
|
||||
return;
|
||||
|
||||
gsk_gl_render_job_transform_bounds (job, &clip->bounds, &transformed_clip.bounds);
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS (transformed_clip.corner); i++)
|
||||
{
|
||||
transformed_clip.corner[i].width = clip->corner[i].width * scale_x;
|
||||
transformed_clip.corner[i].height = clip->corner[i].height * scale_y;
|
||||
}
|
||||
gsk_gl_render_job_transform_rounded_rect (job, clip, &transformed_clip);
|
||||
|
||||
if (job->current_clip->is_rectilinear)
|
||||
{
|
||||
GskRoundedRect intersected_clip;
|
||||
GskRoundedRectIntersection result;
|
||||
|
||||
if (intersect_rounded_rectilinear (&job->current_clip->rect.bounds,
|
||||
&transformed_clip,
|
||||
&intersected_clip))
|
||||
result = gsk_rounded_rect_intersect_with_rect (&transformed_clip,
|
||||
&job->current_clip->rect.bounds,
|
||||
&intersected_clip);
|
||||
|
||||
if (result == GSK_INTERSECTION_EMPTY)
|
||||
return;
|
||||
|
||||
if (result == GSK_INTERSECTION_NONEMPTY)
|
||||
{
|
||||
gsk_gl_render_job_push_clip (job, &intersected_clip);
|
||||
gsk_gl_render_job_visit_node (job, child);
|
||||
@ -1914,7 +1887,7 @@ gsk_gl_render_job_visit_border_node (GskGLRenderJob *job,
|
||||
sizes[3].w = MAX (widths[3], rounded_outline->corner[3].width);
|
||||
}
|
||||
|
||||
gsk_gl_render_job_transform_rounded_rect (job, rounded_outline, &outline);
|
||||
gsk_gl_render_job_translate_rounded_rect (job, rounded_outline, &outline);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, border));
|
||||
|
||||
@ -2018,7 +1991,7 @@ gsk_gl_render_job_visit_css_background (GskGLRenderJob *job,
|
||||
rgba_to_half (&gsk_border_node_get_colors (node2)[0], color);
|
||||
rgba_to_half (gsk_color_node_get_color (child), color2);
|
||||
|
||||
gsk_gl_render_job_transform_rounded_rect (job, rounded_outline, &outline);
|
||||
gsk_gl_render_job_translate_rounded_rect (job, rounded_outline, &outline);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, filled_border));
|
||||
|
||||
@ -2159,6 +2132,7 @@ gsk_gl_render_job_visit_transform_node (GskGLRenderJob *job,
|
||||
scale = gsk_transform_translate (gsk_transform_scale (NULL, sx, sy), &GRAPHENE_POINT_INIT (tx, ty));
|
||||
gsk_gl_render_job_push_modelview (job, scale);
|
||||
transform = gsk_transform_transform (gsk_transform_invert (scale), transform);
|
||||
gsk_transform_unref (scale);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2209,7 +2183,7 @@ gsk_gl_render_job_visit_unblurred_inset_shadow_node (GskGLRenderJob *job,
|
||||
GskRoundedRect transformed_outline;
|
||||
guint16 color[4];
|
||||
|
||||
gsk_gl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
|
||||
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow));
|
||||
gsk_gl_program_set_uniform_rounded_rect (job->current_program,
|
||||
@ -2309,7 +2283,7 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
|
||||
prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
|
||||
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
|
||||
|
||||
gsk_gl_render_job_transform_rounded_rect (job, &outline_to_blur, &transformed_outline);
|
||||
gsk_gl_render_job_translate_rounded_rect (job, &outline_to_blur, &transformed_outline);
|
||||
|
||||
/* Actual inset shadow outline drawing */
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow));
|
||||
@ -2342,8 +2316,8 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
|
||||
&offscreen,
|
||||
texture_width,
|
||||
texture_height,
|
||||
blur_radius * scale_x,
|
||||
blur_radius * scale_y);
|
||||
blur_radius * fabs (scale_x),
|
||||
blur_radius * fabs (scale_y));
|
||||
|
||||
gsk_gl_driver_release_render_target (job->driver, render_target, TRUE);
|
||||
|
||||
@ -2365,14 +2339,7 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
|
||||
{
|
||||
GskRoundedRect node_clip;
|
||||
|
||||
gsk_gl_render_job_transform_bounds (job, &node_outline->bounds, &node_clip.bounds);
|
||||
|
||||
for (guint i = 0; i < 4; i ++)
|
||||
{
|
||||
node_clip.corner[i].width = node_outline->corner[i].width * scale_x;
|
||||
node_clip.corner[i].height = node_outline->corner[i].height * scale_y;
|
||||
}
|
||||
|
||||
gsk_gl_render_job_translate_rounded_rect (job, node_outline, &node_clip);
|
||||
gsk_gl_render_job_push_clip (job, &node_clip);
|
||||
}
|
||||
|
||||
@ -2422,7 +2389,7 @@ gsk_gl_render_job_visit_unblurred_outset_shadow_node (GskGLRenderJob *job,
|
||||
|
||||
rgba_to_half (gsk_outset_shadow_node_get_color (node), color);
|
||||
|
||||
gsk_gl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
|
||||
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, unblurred_outset_shadow));
|
||||
gsk_gl_program_set_uniform_rounded_rect (job->current_program,
|
||||
@ -2615,8 +2582,8 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
|
||||
&offscreen,
|
||||
texture_width,
|
||||
texture_height,
|
||||
blur_radius * scale_x,
|
||||
blur_radius * scale_y);
|
||||
blur_radius * fabs (scale_x),
|
||||
blur_radius * fabs (scale_y));
|
||||
|
||||
gsk_gl_shadow_library_insert (job->driver->shadows_library,
|
||||
&scaled_outline,
|
||||
@ -2630,7 +2597,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
|
||||
blurred_texture_id = cached_tid;
|
||||
}
|
||||
|
||||
gsk_gl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
|
||||
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
|
||||
|
||||
if (!do_slicing)
|
||||
{
|
||||
@ -2866,8 +2833,12 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
|
||||
offscreen_end.reset_clip = TRUE;
|
||||
offscreen_end.bounds = &node->bounds;
|
||||
|
||||
gsk_gl_render_job_set_modelview (job, NULL);
|
||||
|
||||
if (!gsk_gl_render_job_visit_node_with_offscreen (job, start_node, &offscreen_start))
|
||||
{
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
|
||||
gsk_gl_render_job_visit_node (job, end_node);
|
||||
return;
|
||||
}
|
||||
@ -2876,12 +2847,18 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
|
||||
|
||||
if (!gsk_gl_render_job_visit_node_with_offscreen (job, end_node, &offscreen_end))
|
||||
{
|
||||
float prev_alpha = gsk_gl_render_job_set_alpha (job, job->alpha * progress);
|
||||
float prev_alpha;
|
||||
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
|
||||
prev_alpha = gsk_gl_render_job_set_alpha (job, job->alpha * progress);
|
||||
gsk_gl_render_job_visit_node (job, start_node);
|
||||
gsk_gl_render_job_set_alpha (job, prev_alpha);
|
||||
return;
|
||||
}
|
||||
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
|
||||
g_assert (offscreen_end.texture_id);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, cross_fade));
|
||||
@ -3275,10 +3252,14 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
|
||||
bottom_offscreen.force_offscreen = TRUE;
|
||||
bottom_offscreen.reset_clip = TRUE;
|
||||
|
||||
gsk_gl_render_job_set_modelview (job, NULL);
|
||||
|
||||
/* TODO: We create 2 textures here as big as the blend node, but both the
|
||||
* start and the end node might be a lot smaller than that. */
|
||||
if (!gsk_gl_render_job_visit_node_with_offscreen (job, bottom_child, &bottom_offscreen))
|
||||
{
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
|
||||
gsk_gl_render_job_visit_node (job, top_child);
|
||||
return;
|
||||
}
|
||||
@ -3287,6 +3268,8 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
|
||||
|
||||
if (!gsk_gl_render_job_visit_node_with_offscreen (job, top_child, &top_offscreen))
|
||||
{
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
@ -3300,6 +3283,8 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
|
||||
|
||||
g_assert (top_offscreen.was_offscreen);
|
||||
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blend));
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
@ -3336,11 +3321,14 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
|
||||
mask_offscreen.reset_clip = TRUE;
|
||||
mask_offscreen.do_not_cache = TRUE;
|
||||
|
||||
gsk_gl_render_job_set_modelview (job, NULL);
|
||||
|
||||
/* TODO: We create 2 textures here as big as the mask node, but both
|
||||
* nodes might be a lot smaller than that.
|
||||
*/
|
||||
if (!gsk_gl_render_job_visit_node_with_offscreen (job, source, &source_offscreen))
|
||||
{
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
gsk_gl_render_job_visit_node (job, source);
|
||||
return;
|
||||
}
|
||||
@ -3349,11 +3337,14 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
|
||||
|
||||
if (!gsk_gl_render_job_visit_node_with_offscreen (job, mask, &mask_offscreen))
|
||||
{
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (mask_offscreen.was_offscreen);
|
||||
|
||||
gsk_gl_render_job_pop_modelview (job);
|
||||
|
||||
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, mask));
|
||||
gsk_gl_program_set_uniform_texture (job->current_program,
|
||||
UNIFORM_SHARED_SOURCE, 0,
|
||||
@ -3587,8 +3578,8 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job,
|
||||
float scale_y = bounds->size.height / texture->height;
|
||||
gboolean use_mipmap;
|
||||
|
||||
use_mipmap = (scale_x * job->scale_x) < 0.5 ||
|
||||
(scale_y * job->scale_y) < 0.5;
|
||||
use_mipmap = (scale_x * fabs (job->scale_x)) < 0.5 ||
|
||||
(scale_y * fabs (job->scale_y)) < 0.5;
|
||||
|
||||
if G_LIKELY (texture->width <= max_texture_size &&
|
||||
texture->height <= max_texture_size)
|
||||
@ -4120,7 +4111,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
}
|
||||
|
||||
if (gsk_render_node_get_node_type (node) == GSK_TEXTURE_NODE &&
|
||||
offscreen->force_offscreen == FALSE)
|
||||
!offscreen->force_offscreen)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
gsk_gl_render_job_upload_texture (job, texture, FALSE, offscreen);
|
||||
@ -4138,6 +4129,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
gboolean flipped_x = job->scale_x < 0;
|
||||
gboolean flipped_y = job->scale_y < 0;
|
||||
graphene_rect_t viewport;
|
||||
gboolean reset_clip = FALSE;
|
||||
|
||||
if (flipped_x || flipped_y)
|
||||
{
|
||||
@ -4185,6 +4177,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
gsk_gl_render_job_push_modelview (job, transform);
|
||||
gsk_transform_unref (transform);
|
||||
gsk_gl_render_job_transform_bounds (job, offscreen->bounds, &viewport);
|
||||
graphene_rect_scale (&viewport, downscale_x, downscale_y, &viewport);
|
||||
}
|
||||
|
||||
if (downscale_x == 1)
|
||||
@ -4268,11 +4261,25 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
|
||||
|
||||
if (offscreen->reset_clip)
|
||||
{
|
||||
gsk_gl_render_job_push_clip (job, &GSK_ROUNDED_RECT_INIT_FROM_RECT (job->viewport));
|
||||
reset_clip = TRUE;
|
||||
}
|
||||
else if (flipped_x || flipped_y || downscale_x != 1 || downscale_y != 1)
|
||||
{
|
||||
GskRoundedRect new_clip;
|
||||
float scale_x = flipped_x ? - downscale_x : downscale_x;
|
||||
float scale_y = flipped_y ? - downscale_y : downscale_y;
|
||||
|
||||
graphene_rect_scale (&job->current_clip->rect.bounds, scale_x, scale_y, &new_clip.bounds);
|
||||
rounded_rect_scale_corners (&job->current_clip->rect, &new_clip, scale_x, scale_y);
|
||||
gsk_gl_render_job_push_clip (job, &new_clip);
|
||||
reset_clip = TRUE;
|
||||
}
|
||||
|
||||
gsk_gl_render_job_visit_node (job, node);
|
||||
|
||||
if (offscreen->reset_clip)
|
||||
if (reset_clip)
|
||||
gsk_gl_render_job_pop_clip (job);
|
||||
|
||||
if (downscale_x != 1 || downscale_y != 1)
|
||||
|
@ -19,6 +19,9 @@ void main() {
|
||||
gsk_rounded_rect_transform(outside, u_modelview);
|
||||
gsk_rounded_rect_transform(inside, u_modelview);
|
||||
|
||||
gsk_rounded_rect_normalize(outside);
|
||||
gsk_rounded_rect_normalize(inside);
|
||||
|
||||
gsk_rounded_rect_encode(outside, transformed_outside_outline);
|
||||
gsk_rounded_rect_encode(inside, transformed_inside_outline);
|
||||
}
|
||||
@ -34,10 +37,9 @@ _IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
|
||||
|
||||
void main() {
|
||||
vec2 frag = gsk_get_frag_coord();
|
||||
|
||||
float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) -
|
||||
gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag),
|
||||
0.0, 1.0);
|
||||
float outer_coverage = gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag);
|
||||
float inner_coverage = gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag);
|
||||
float alpha = clamp(outer_coverage - inner_coverage, 0.0, 1.0);
|
||||
|
||||
gskSetScaledOutputColor(final_color, alpha);
|
||||
}
|
||||
|
@ -21,6 +21,9 @@ void main() {
|
||||
gsk_rounded_rect_transform(outside, u_modelview);
|
||||
gsk_rounded_rect_transform(inside, u_modelview);
|
||||
|
||||
gsk_rounded_rect_normalize(outside);
|
||||
gsk_rounded_rect_normalize(inside);
|
||||
|
||||
gsk_rounded_rect_encode(outside, transformed_outside_outline);
|
||||
gsk_rounded_rect_encode(inside, transformed_inside_outline);
|
||||
}
|
||||
|
@ -22,6 +22,9 @@ void main() {
|
||||
gsk_rounded_rect_transform(outside, u_modelview);
|
||||
gsk_rounded_rect_transform(inside, u_modelview);
|
||||
|
||||
gsk_rounded_rect_normalize(outside);
|
||||
gsk_rounded_rect_normalize(inside);
|
||||
|
||||
gsk_rounded_rect_encode(outside, transformed_outside_outline);
|
||||
gsk_rounded_rect_encode(inside, transformed_inside_outline);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ void main() {
|
||||
|
||||
GskRoundedRect outline = gsk_create_rect(u_outline_rect);
|
||||
gsk_rounded_rect_transform(outline, u_modelview);
|
||||
gsk_rounded_rect_normalize(outline);
|
||||
gsk_rounded_rect_encode(outline, transformed_outline);
|
||||
}
|
||||
|
||||
|
@ -16,11 +16,15 @@ _IN_ vec2 vUv;
|
||||
|
||||
GskRoundedRect gsk_decode_rect(_GSK_ROUNDED_RECT_UNIFORM_ r)
|
||||
{
|
||||
GskRoundedRect rect;
|
||||
#if defined(GSK_GLES) || defined(GSK_LEGACY)
|
||||
return GskRoundedRect(r[0], r[1], r[2]);
|
||||
rect = GskRoundedRect(r[0], r[1], r[2]);
|
||||
#else
|
||||
return r;
|
||||
rect = r;
|
||||
#endif
|
||||
gsk_rounded_rect_normalize (rect);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
float
|
||||
|
@ -22,6 +22,55 @@ struct GskRoundedRect
|
||||
vec4 corner_points2; // xy = bottom right, zw = bottom left
|
||||
};
|
||||
|
||||
void gsk_rounded_rect_normalize(inout GskRoundedRect r)
|
||||
{
|
||||
if (r.bounds.x > r.bounds.z)
|
||||
{
|
||||
float t = r.bounds.x;
|
||||
r.bounds.x = r.bounds.z;
|
||||
r.bounds.z = t;
|
||||
|
||||
vec2 c = r.corner_points1.xy;
|
||||
r.corner_points1.xy = r.corner_points1.zw;
|
||||
r.corner_points1.zw = c;
|
||||
|
||||
c = r.corner_points2.xy;
|
||||
r.corner_points2.xy = r.corner_points2.zw;
|
||||
r.corner_points2.zw = c;
|
||||
}
|
||||
|
||||
if (r.bounds.y > r.bounds.w)
|
||||
{
|
||||
float t = r.bounds.y;
|
||||
r.bounds.y = r.bounds.w;
|
||||
r.bounds.w = t;
|
||||
|
||||
vec2 c = r.corner_points1.xy;
|
||||
r.corner_points1.xy = r.corner_points2.xy;
|
||||
r.corner_points2.xy = c;
|
||||
|
||||
c = r.corner_points1.zw;
|
||||
r.corner_points1.zw = r.corner_points2.zw;
|
||||
r.corner_points2.zw = c;
|
||||
}
|
||||
}
|
||||
|
||||
void gsk_bounds_normalize (inout vec4 bounds)
|
||||
{
|
||||
if (bounds.x > bounds.z)
|
||||
{
|
||||
float t = bounds.x;
|
||||
bounds.x = bounds.z;
|
||||
bounds.z = t;
|
||||
}
|
||||
if (bounds.y > bounds.w)
|
||||
{
|
||||
float t = bounds.y;
|
||||
bounds.y = bounds.w;
|
||||
bounds.w = t;
|
||||
}
|
||||
}
|
||||
|
||||
// Transform from a C GskRoundedRect to what we need.
|
||||
GskRoundedRect
|
||||
gsk_create_rect(vec4[3] data)
|
||||
@ -33,13 +82,21 @@ gsk_create_rect(vec4[3] data)
|
||||
vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
|
||||
bounds.xw + vec2(data[2].zw * vec2(1, -1)));
|
||||
|
||||
return GskRoundedRect(bounds, corner_points1, corner_points2);
|
||||
GskRoundedRect rect = GskRoundedRect(bounds, corner_points1, corner_points2);
|
||||
|
||||
gsk_rounded_rect_normalize (rect);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
vec4
|
||||
gsk_get_bounds(vec4[3] data)
|
||||
{
|
||||
return vec4(data[0].xy, data[0].xy + data[0].zw);
|
||||
vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
|
||||
|
||||
gsk_bounds_normalize (bounds);
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
vec4 gsk_premultiply(vec4 c) {
|
||||
|
@ -519,10 +519,176 @@ gsk_rounded_rect_intersects_rect (const GskRoundedRect *self,
|
||||
gsk_rounded_rect_locate_point (self, &GRAPHENE_POINT_INIT (rect->origin.x, rect->origin.y + rect->size.height)) == OUTSIDE_TOP_RIGHT ||
|
||||
gsk_rounded_rect_locate_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, rect->origin.y + rect->size.height)) == OUTSIDE_TOP_LEFT)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define rect_point0(r) ((r)->origin)
|
||||
#define rect_point1(r) (GRAPHENE_POINT_INIT ((r)->origin.x + (r)->size.width, (r)->origin.y))
|
||||
#define rect_point2(r) (GRAPHENE_POINT_INIT ((r)->origin.x + (r)->size.width, (r)->origin.y + (r)->size.height))
|
||||
#define rect_point3(r) (GRAPHENE_POINT_INIT ((r)->origin.x, (r)->origin.y + (r)->size.height))
|
||||
|
||||
#define rounded_rect_corner0(r) \
|
||||
(GRAPHENE_RECT_INIT((r)->bounds.origin.x, \
|
||||
(r)->bounds.origin.y, \
|
||||
(r)->corner[0].width, (r)->corner[0].height))
|
||||
#define rounded_rect_corner1(r) \
|
||||
(GRAPHENE_RECT_INIT((r)->bounds.origin.x + (r)->bounds.size.width - (r)->corner[1].width, \
|
||||
(r)->bounds.origin.y, \
|
||||
(r)->corner[1].width, (r)->corner[1].height))
|
||||
#define rounded_rect_corner2(r) \
|
||||
(GRAPHENE_RECT_INIT((r)->bounds.origin.x + (r)->bounds.size.width - (r)->corner[2].width, \
|
||||
(r)->bounds.origin.y + (r)->bounds.size.height - (r)->corner[2].height, \
|
||||
(r)->corner[2].width, (r)->corner[2].height))
|
||||
#define rounded_rect_corner3(r) \
|
||||
(GRAPHENE_RECT_INIT((r)->bounds.origin.x, \
|
||||
(r)->bounds.origin.y + (r)->bounds.size.height - (r)->corner[3].height, \
|
||||
(r)->corner[3].width, (r)->corner[3].height))
|
||||
|
||||
enum {
|
||||
BELOW,
|
||||
INNER,
|
||||
ABOVE
|
||||
};
|
||||
|
||||
static inline void
|
||||
classify_point (const graphene_point_t *p, const graphene_rect_t *rect, int *px, int *py)
|
||||
{
|
||||
if (p->x <= rect->origin.x)
|
||||
*px = BELOW;
|
||||
else if (p->x >= rect->origin.x + rect->size.width)
|
||||
*px = ABOVE;
|
||||
else
|
||||
*px = INNER;
|
||||
|
||||
if (p->y <= rect->origin.y)
|
||||
*py = BELOW;
|
||||
else if (p->y >= rect->origin.y + rect->size.height)
|
||||
*py = ABOVE;
|
||||
else
|
||||
*py = INNER;
|
||||
}
|
||||
|
||||
GskRoundedRectIntersection
|
||||
gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
|
||||
const graphene_rect_t *rect,
|
||||
GskRoundedRect *result)
|
||||
{
|
||||
int px, py, qx, qy;
|
||||
|
||||
if (!graphene_rect_intersection (&self->bounds, rect, &result->bounds))
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
|
||||
classify_point (&rect_point0 (rect), &rounded_rect_corner0 (self), &px, &py);
|
||||
|
||||
if (px == BELOW && py == BELOW)
|
||||
{
|
||||
classify_point (&rect_point2 (rect), &rounded_rect_corner0 (self), &qx, &qy);
|
||||
|
||||
if (qx == BELOW || qy == BELOW)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == INNER && qy == INNER &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) != INSIDE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == ABOVE && qy == ABOVE)
|
||||
result->corner[0] = self->corner[0];
|
||||
else
|
||||
return GSK_INTERSECTION_NOT_REPRESENTABLE;
|
||||
}
|
||||
else if ((px == INNER || py == INNER) &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) != INSIDE)
|
||||
{
|
||||
if (gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) == OUTSIDE_TOP_LEFT)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else
|
||||
return GSK_INTERSECTION_NOT_REPRESENTABLE;
|
||||
}
|
||||
else
|
||||
result->corner[0].width = result->corner[0].height = 0;
|
||||
|
||||
classify_point (&rect_point1 (rect), &rounded_rect_corner1 (self), &px, &py);
|
||||
|
||||
if (px == ABOVE && py == BELOW)
|
||||
{
|
||||
classify_point (&rect_point3 (rect), &rounded_rect_corner1 (self), &qx, &qy);
|
||||
|
||||
if (qx == ABOVE || qy == BELOW)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == INNER && qy == INNER &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) != INSIDE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == BELOW && qy == ABOVE)
|
||||
result->corner[1] = self->corner[1];
|
||||
else
|
||||
return GSK_INTERSECTION_NOT_REPRESENTABLE;
|
||||
}
|
||||
else if ((px == INNER || py == INNER) &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) != INSIDE)
|
||||
{
|
||||
if (gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) == OUTSIDE_TOP_RIGHT)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else
|
||||
return GSK_INTERSECTION_NOT_REPRESENTABLE;
|
||||
}
|
||||
else
|
||||
result->corner[1].width = result->corner[1].height = 0;
|
||||
|
||||
classify_point (&rect_point2 (rect), &rounded_rect_corner2 (self), &px, &py);
|
||||
|
||||
if (px == ABOVE && py == ABOVE)
|
||||
{
|
||||
classify_point (&rect_point0 (rect), &rounded_rect_corner2 (self), &qx, &qy);
|
||||
|
||||
if (qx == ABOVE || qy == ABOVE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == INNER && qy == INNER &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) != INSIDE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == BELOW && qy == BELOW)
|
||||
result->corner[2] = self->corner[2];
|
||||
else
|
||||
return GSK_INTERSECTION_NOT_REPRESENTABLE;
|
||||
}
|
||||
else if ((px == INNER || py == INNER) &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) != INSIDE)
|
||||
{
|
||||
if (gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) == OUTSIDE_BOTTOM_RIGHT)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else
|
||||
return GSK_INTERSECTION_NOT_REPRESENTABLE;
|
||||
}
|
||||
else
|
||||
result->corner[2].width = result->corner[2].height = 0;
|
||||
|
||||
classify_point (&rect_point3 (rect), &rounded_rect_corner3 (self), &px, &py);
|
||||
|
||||
if (px == BELOW && py == ABOVE)
|
||||
{
|
||||
classify_point (&rect_point1 (rect), &rounded_rect_corner3 (self), &qx, &qy);
|
||||
|
||||
if (qx == BELOW || qy == ABOVE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == INNER && qy == INNER &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) != INSIDE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == ABOVE && qy == BELOW)
|
||||
result->corner[3] = self->corner[3];
|
||||
else
|
||||
return GSK_INTERSECTION_NOT_REPRESENTABLE;
|
||||
}
|
||||
else if ((px == INNER || py == INNER) &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) != INSIDE)
|
||||
{
|
||||
if (gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) == OUTSIDE_BOTTOM_LEFT)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else
|
||||
return GSK_INTERSECTION_NOT_REPRESENTABLE;
|
||||
}
|
||||
else
|
||||
result->corner[3].width = result->corner[3].height = 0;
|
||||
|
||||
return GSK_INTERSECTION_NONEMPTY;
|
||||
}
|
||||
|
||||
static void
|
||||
append_arc (cairo_t *cr, double angle1, double angle2, gboolean negative)
|
||||
{
|
||||
@ -649,5 +815,4 @@ gsk_rounded_rect_to_string (const GskRoundedRect *self)
|
||||
self->corner[2].height,
|
||||
self->corner[3].width,
|
||||
self->corner[3].height);
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,16 @@ gboolean gsk_rounded_rect_equal (gconstpointer
|
||||
gconstpointer rect2) G_GNUC_PURE;
|
||||
char * gsk_rounded_rect_to_string (const GskRoundedRect *self) G_GNUC_MALLOC;
|
||||
|
||||
typedef enum {
|
||||
GSK_INTERSECTION_EMPTY,
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
GSK_INTERSECTION_NOT_REPRESENTABLE
|
||||
} GskRoundedRectIntersection;
|
||||
|
||||
GskRoundedRectIntersection gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
|
||||
const graphene_rect_t *rect,
|
||||
GskRoundedRect *result) G_GNUC_PURE;
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -5,6 +5,9 @@
|
||||
#include "../reftests/reftest-compare.h"
|
||||
|
||||
static char *arg_output_dir = NULL;
|
||||
static gboolean flip = FALSE;
|
||||
static gboolean rotate = FALSE;
|
||||
static gboolean repeat = FALSE;
|
||||
|
||||
static const char *
|
||||
get_output_dir (void)
|
||||
@ -112,6 +115,20 @@ save_image (GdkTexture *texture,
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
static void
|
||||
save_node (GskRenderNode *node,
|
||||
const char *test_name,
|
||||
const char *extension)
|
||||
{
|
||||
char *filename = get_output_file (test_name, ".node", extension);
|
||||
gboolean result;
|
||||
|
||||
g_print ("Storing modified nodes at %s\n", filename);
|
||||
result = gsk_render_node_write_to_file (node, filename, NULL);
|
||||
g_assert_true (result);
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
static void
|
||||
deserialize_error_func (const GskParseLocation *start,
|
||||
const GskParseLocation *end,
|
||||
@ -136,11 +153,39 @@ deserialize_error_func (const GskParseLocation *start,
|
||||
}
|
||||
|
||||
static const GOptionEntry options[] = {
|
||||
{ "output", 0, 0, G_OPTION_ARG_FILENAME, &arg_output_dir,
|
||||
"Directory to save image files to", "DIR" },
|
||||
{ "output", 0, 0, G_OPTION_ARG_FILENAME, &arg_output_dir, "Directory to save image files to", "DIR" },
|
||||
{ "flip", 0, 0, G_OPTION_ARG_NONE, &flip, "Do flipped test", NULL },
|
||||
{ "rotate", 0, 0, G_OPTION_ARG_NONE, &rotate, "Do rotated test", NULL },
|
||||
{ "repeat", 0, 0, G_OPTION_ARG_NONE, &repeat, "Do repeat test", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static GskRenderNode *
|
||||
load_node_file (const char *node_file)
|
||||
{
|
||||
GBytes *bytes;
|
||||
gsize len;
|
||||
char *contents;
|
||||
GError *error = NULL;
|
||||
GskRenderNode *node;
|
||||
|
||||
if (!g_file_get_contents (node_file, &contents, &len, &error))
|
||||
{
|
||||
g_print ("Could not open node file: %s\n", error->message);
|
||||
g_clear_error (&error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes = g_bytes_new_take (contents, len);
|
||||
node = gsk_render_node_deserialize (bytes, deserialize_error_func, NULL);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-option arguments:
|
||||
* 1) .node file to compare
|
||||
@ -159,6 +204,7 @@ main (int argc, char **argv)
|
||||
gboolean success = TRUE;
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
GdkTexture *diff_texture;
|
||||
|
||||
(g_test_init) (&argc, &argv, NULL);
|
||||
|
||||
@ -185,64 +231,182 @@ main (int argc, char **argv)
|
||||
node_file = argv[1];
|
||||
png_file = argv[2];
|
||||
|
||||
window = gdk_surface_new_toplevel (gdk_display_get_default());
|
||||
renderer = gsk_renderer_new_for_surface (window);
|
||||
|
||||
g_print ("Node file: '%s'\n", node_file);
|
||||
g_print ("PNG file: '%s'\n", png_file);
|
||||
|
||||
window = gdk_surface_new_toplevel (gdk_display_get_default());
|
||||
renderer = gsk_renderer_new_for_surface (window);
|
||||
|
||||
/* Load the render node from the given .node file */
|
||||
{
|
||||
GBytes *bytes;
|
||||
gsize len;
|
||||
char *contents;
|
||||
|
||||
if (!g_file_get_contents (node_file, &contents, &len, &error))
|
||||
{
|
||||
g_print ("Could not open node file: %s\n", error->message);
|
||||
g_clear_error (&error);
|
||||
node = load_node_file (node_file);
|
||||
if (!node)
|
||||
return 1;
|
||||
}
|
||||
|
||||
bytes = g_bytes_new_take (contents, len);
|
||||
node = gsk_render_node_deserialize (bytes, deserialize_error_func, &success);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (node);
|
||||
}
|
||||
|
||||
/* Render the .node file and download to cairo surface */
|
||||
rendered_texture = gsk_renderer_render_texture (renderer, node, NULL);
|
||||
g_assert_nonnull (rendered_texture);
|
||||
|
||||
save_image (rendered_texture, node_file, ".out.png");
|
||||
|
||||
/* Load the given reference png file */
|
||||
reference_texture = gdk_texture_new_from_filename (png_file, &error);
|
||||
if (reference_texture == NULL)
|
||||
{
|
||||
g_print ("Error loading reference surface: %s\n", error->message);
|
||||
g_clear_error (&error);
|
||||
success = FALSE;
|
||||
save_image (rendered_texture, node_file, ".out.png");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkTexture *diff_texture;
|
||||
|
||||
/* Now compare the two */
|
||||
diff_texture = reftest_compare_textures (rendered_texture, reference_texture);
|
||||
|
||||
if (diff_texture)
|
||||
{
|
||||
save_image (diff_texture, node_file, ".diff.png");
|
||||
g_object_unref (diff_texture);
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
g_clear_object (&reference_texture);
|
||||
g_clear_object (&rendered_texture);
|
||||
|
||||
if (flip)
|
||||
{
|
||||
GskRenderNode *node2;
|
||||
GdkPixbuf *pixbuf, *pixbuf2;
|
||||
|
||||
node2 = gsk_transform_node_new (node, gsk_transform_scale (NULL, -1, 1));
|
||||
rendered_texture = gsk_renderer_render_texture (renderer, node2, NULL);
|
||||
|
||||
save_image (rendered_texture, node_file, "-flipped.out.png");
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_file (png_file, &error);
|
||||
pixbuf2 = gdk_pixbuf_flip (pixbuf, TRUE);
|
||||
reference_texture = gdk_texture_new_for_pixbuf (pixbuf2);
|
||||
g_object_unref (pixbuf2);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
save_image (reference_texture, node_file, "-flipped.ref.png");
|
||||
|
||||
diff_texture = reftest_compare_textures (rendered_texture, reference_texture);
|
||||
|
||||
if (diff_texture)
|
||||
{
|
||||
save_node (node2, node_file, "-flipped.node");
|
||||
save_image (diff_texture, node_file, "-flipped.diff.png");
|
||||
g_object_unref (diff_texture);
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
save_image (rendered_texture, node_file, ".out.png");
|
||||
g_clear_object (&rendered_texture);
|
||||
g_clear_object (&reference_texture);
|
||||
gsk_render_node_unref (node2);
|
||||
}
|
||||
|
||||
g_object_unref (reference_texture);
|
||||
g_object_unref (rendered_texture);
|
||||
if (repeat)
|
||||
{
|
||||
GskRenderNode *node2;
|
||||
GdkPixbuf *pixbuf, *pixbuf2, *pixbuf3;
|
||||
int width, height;
|
||||
graphene_rect_t node_bounds;
|
||||
graphene_rect_t bounds;
|
||||
float offset_x, offset_y;
|
||||
|
||||
gsk_render_node_get_bounds (node, &node_bounds);
|
||||
|
||||
if (node_bounds.size.width > 32768. || node_bounds.size.height > 32768.)
|
||||
{
|
||||
g_print ("Avoiding repeat test that exceeds cairo image surface dimensions");
|
||||
exit (77);
|
||||
}
|
||||
|
||||
bounds.origin.x = 0.;
|
||||
bounds.origin.y = 0.;
|
||||
bounds.size.width = 2 * node_bounds.size.width;
|
||||
bounds.size.height = 2 * node_bounds.size.height;
|
||||
|
||||
offset_x = floorf (fmodf (node_bounds.origin.x, node_bounds.size.width));
|
||||
offset_y = floorf (fmodf (node_bounds.origin.y, node_bounds.size.height));
|
||||
if (offset_x < 0)
|
||||
offset_x += node_bounds.size.width;
|
||||
if (offset_y < 0)
|
||||
offset_y += node_bounds.size.height;
|
||||
|
||||
node2 = gsk_repeat_node_new (&bounds, node, &node_bounds);
|
||||
rendered_texture = gsk_renderer_render_texture (renderer, node2, NULL);
|
||||
save_image (rendered_texture, node_file, "-repeated.out.png");
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_file (png_file, &error);
|
||||
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
pixbuf2 = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (pixbuf),
|
||||
gdk_pixbuf_get_has_alpha (pixbuf),
|
||||
gdk_pixbuf_get_bits_per_sample (pixbuf),
|
||||
width * 3,
|
||||
height * 3);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++)
|
||||
gdk_pixbuf_copy_area (pixbuf, 0, 0, width, height, pixbuf2, i * width, j * height);
|
||||
|
||||
pixbuf3 = gdk_pixbuf_new_subpixbuf (pixbuf2, width - (int) offset_x, height - (int) offset_y, 2 * width, 2 * height);
|
||||
|
||||
reference_texture = gdk_texture_new_for_pixbuf (pixbuf3);
|
||||
|
||||
g_object_unref (pixbuf3);
|
||||
g_object_unref (pixbuf2);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
save_image (reference_texture, node_file, "-repeated.ref.png");
|
||||
|
||||
diff_texture = reftest_compare_textures (rendered_texture, reference_texture);
|
||||
|
||||
if (diff_texture)
|
||||
{
|
||||
save_node (node2, node_file, "-repeated.node");
|
||||
save_image (diff_texture, node_file, "-repeated.diff.png");
|
||||
g_object_unref (diff_texture);
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
g_clear_object (&rendered_texture);
|
||||
g_clear_object (&reference_texture);
|
||||
gsk_render_node_unref (node2);
|
||||
}
|
||||
|
||||
if (rotate)
|
||||
{
|
||||
GskRenderNode *node2;
|
||||
GdkPixbuf *pixbuf, *pixbuf2;
|
||||
|
||||
node2 = gsk_transform_node_new (node, gsk_transform_rotate (NULL, 90));
|
||||
rendered_texture = gsk_renderer_render_texture (renderer, node2, NULL);
|
||||
|
||||
save_image (rendered_texture, node_file, "-rotated.out.png");
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_file (png_file, &error);
|
||||
pixbuf2 = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
|
||||
reference_texture = gdk_texture_new_for_pixbuf (pixbuf2);
|
||||
g_object_unref (pixbuf2);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
save_image (reference_texture, node_file, "-rotated.ref.png");
|
||||
|
||||
diff_texture = reftest_compare_textures (rendered_texture, reference_texture);
|
||||
|
||||
if (diff_texture)
|
||||
{
|
||||
save_node (node2, node_file, "-rotated.node");
|
||||
save_image (diff_texture, node_file, "-rotated.diff.png");
|
||||
g_object_unref (diff_texture);
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
g_clear_object (&rendered_texture);
|
||||
g_clear_object (&reference_texture);
|
||||
gsk_render_node_unref (node2);
|
||||
}
|
||||
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
|
BIN
testsuite/gsk/compare/big-glyph-wrapped.png
Normal file
BIN
testsuite/gsk/compare/big-glyph-wrapped.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
13
testsuite/gsk/compare/blend-in-rotate.node
Normal file
13
testsuite/gsk/compare/blend-in-rotate.node
Normal file
@ -0,0 +1,13 @@
|
||||
transform {
|
||||
transform: rotate(90);
|
||||
child: blend {
|
||||
bottom: color {
|
||||
bounds: 0 0 100 100;
|
||||
color: rgb(255,0,0);
|
||||
}
|
||||
top: color {
|
||||
bounds: 50 50 100 100;
|
||||
color: rgb(0,0,255);
|
||||
}
|
||||
}
|
||||
}
|
BIN
testsuite/gsk/compare/blend-in-rotate.png
Normal file
BIN
testsuite/gsk/compare/blend-in-rotate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 489 B |
23
testsuite/gsk/compare/blend-modes.node
Normal file
23
testsuite/gsk/compare/blend-modes.node
Normal file
@ -0,0 +1,23 @@
|
||||
blend {
|
||||
mode: difference;
|
||||
bottom: color {
|
||||
bounds: 0 0 100 100;
|
||||
color: red;
|
||||
}
|
||||
top: color {
|
||||
bounds: 50 50 100 100;
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
|
||||
blend {
|
||||
mode: normal;
|
||||
bottom: color {
|
||||
bounds: 150 0 100 100;
|
||||
color: red;
|
||||
}
|
||||
top: color {
|
||||
bounds: 200 50 100 100;
|
||||
color: blue;
|
||||
}
|
||||
}
|
BIN
testsuite/gsk/compare/blend-modes.png
Normal file
BIN
testsuite/gsk/compare/blend-modes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 626 B |
23
testsuite/gsk/compare/border-one-rounded.node
Normal file
23
testsuite/gsk/compare/border-one-rounded.node
Normal file
@ -0,0 +1,23 @@
|
||||
border {
|
||||
outline: 0 0 50 50 / 0 0 0 20;
|
||||
}
|
||||
color {
|
||||
bounds: 0 29 4 11;
|
||||
color: rgb(255,192,203);
|
||||
}
|
||||
color {
|
||||
bounds: 2 40 4 4;
|
||||
color: rgb(255,192,203);
|
||||
}
|
||||
color {
|
||||
bounds: 4 42 4 4;
|
||||
color: rgb(255,192,203);
|
||||
}
|
||||
color {
|
||||
bounds: 6 44 4 4;
|
||||
color: rgb(255,192,203);
|
||||
}
|
||||
color {
|
||||
bounds: 9 46 11 4;
|
||||
color: rgb(255,192,203);
|
||||
}
|
BIN
testsuite/gsk/compare/border-one-rounded.png
Normal file
BIN
testsuite/gsk/compare/border-one-rounded.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 223 B |
14
testsuite/gsk/compare/cross-fade-in-rotate.node
Normal file
14
testsuite/gsk/compare/cross-fade-in-rotate.node
Normal file
@ -0,0 +1,14 @@
|
||||
transform {
|
||||
transform: rotate(90);
|
||||
child: cross-fade {
|
||||
progress: 0;
|
||||
start: color {
|
||||
bounds: 25 0 25 50;
|
||||
color: rgb(255,0,0);
|
||||
}
|
||||
end: color {
|
||||
bounds: 0 0 25 50;
|
||||
color: rgb(0,0,0);
|
||||
}
|
||||
}
|
||||
}
|
BIN
testsuite/gsk/compare/cross-fade-in-rotate.png
Normal file
BIN
testsuite/gsk/compare/cross-fade-in-rotate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 127 B |
@ -15,9 +15,12 @@ compare_render_tests = [
|
||||
'big-checkerboard-scaled-down-nearest',
|
||||
'big-checkerboard-scaled-down2',
|
||||
'blend-difference',
|
||||
'blend-modes',
|
||||
'blend-invisible-child',
|
||||
'blend-in-rotate',
|
||||
'blend-normal',
|
||||
'border-bottom-right',
|
||||
'border-one-rounded',
|
||||
'borders-rotated',
|
||||
'borders-scaled',
|
||||
'clip-coordinates-2d',
|
||||
@ -32,6 +35,7 @@ compare_render_tests = [
|
||||
'color-matrix-identity',
|
||||
'color-matrix-parsing',
|
||||
'cross-fade-in-opacity',
|
||||
'cross-fade-in-rotate',
|
||||
'css-background',
|
||||
'empty-blend',
|
||||
'empty-blur',
|
||||
@ -44,8 +48,7 @@ compare_render_tests = [
|
||||
'empty-cross-fade',
|
||||
'empty-debug',
|
||||
'empty-inset-shadow',
|
||||
# this test fails for some of the backends
|
||||
# 'empty-linear-gradient',
|
||||
'empty-linear-gradient',
|
||||
'empty-mask',
|
||||
'empty-opacity',
|
||||
'empty-outset-shadow',
|
||||
@ -74,7 +77,6 @@ compare_render_tests = [
|
||||
'repeat-no-repeat',
|
||||
'repeat-negative-coords',
|
||||
'repeat-texture',
|
||||
'rounded-clip-in-clip-3d', # not really 3d, but cairo fails it
|
||||
'scale-textures-negative-ngl',
|
||||
'scale-up-down',
|
||||
'scaled-cairo',
|
||||
@ -94,6 +96,7 @@ informative_render_tests = [
|
||||
'big-glyph',
|
||||
'empty-text',
|
||||
'huge-glyph',
|
||||
'rounded-clip-in-clip-3d', # both cairo and gl fail this one
|
||||
]
|
||||
|
||||
renderers = [
|
||||
@ -104,10 +107,16 @@ renderers = [
|
||||
|
||||
compare_xfails = [
|
||||
# Both tests fail because of some font rendering issue
|
||||
'empty-linear-gradient',
|
||||
'unaligned-offscreen',
|
||||
'upside-down-label-3d', # not really 3d, but cairo fails it
|
||||
]
|
||||
|
||||
compare_xfails_small_texture = [
|
||||
'big-checkerboard',
|
||||
'big-checkerboard-scaled-down'
|
||||
]
|
||||
|
||||
foreach renderer : renderers
|
||||
foreach testname : compare_render_tests
|
||||
|
||||
@ -125,6 +134,10 @@ foreach renderer : renderers
|
||||
suites += 'failing'
|
||||
endif
|
||||
|
||||
if compare_xfails_small_texture.contains(testname)
|
||||
suites += 'wayland_smalltexture_failing'
|
||||
endif
|
||||
|
||||
if ((exclude_term == '' or not testname.contains(exclude_term)) and
|
||||
(renderer_name != 'broadway' or broadway_enabled))
|
||||
test(renderer_name + ' ' + testname, compare_render,
|
||||
@ -141,6 +154,51 @@ foreach renderer : renderers
|
||||
],
|
||||
suite: suites,
|
||||
)
|
||||
test(renderer_name + ' ' + testname + ' flipped', compare_render,
|
||||
args: [
|
||||
'--flip',
|
||||
'--output', join_paths(meson.current_build_dir(), 'compare', renderer_name),
|
||||
join_paths(meson.current_source_dir(), 'compare', testname + '.node'),
|
||||
join_paths(meson.current_source_dir(), 'compare', testname + '.png'),
|
||||
],
|
||||
env: [
|
||||
'GSK_RENDERER=' + renderer_name,
|
||||
'GTK_A11Y=test',
|
||||
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
|
||||
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
|
||||
],
|
||||
suite: suites + [ 'gsk-compare-flipped-' + renderer_name ],
|
||||
)
|
||||
test(renderer_name + ' ' + testname + ' repeated', compare_render,
|
||||
args: [
|
||||
'--repeat',
|
||||
'--output', join_paths(meson.current_build_dir(), 'compare', renderer_name),
|
||||
join_paths(meson.current_source_dir(), 'compare', testname + '.node'),
|
||||
join_paths(meson.current_source_dir(), 'compare', testname + '.png'),
|
||||
],
|
||||
env: [
|
||||
'GSK_RENDERER=' + renderer_name,
|
||||
'GTK_A11Y=test',
|
||||
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
|
||||
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
|
||||
],
|
||||
suite: suites + [ 'gsk-compare-repeated-' + renderer_name ],
|
||||
)
|
||||
test(renderer_name + ' ' + testname + ' rotated', compare_render,
|
||||
args: [
|
||||
'--rotate',
|
||||
'--output', join_paths(meson.current_build_dir(), 'compare', renderer_name),
|
||||
join_paths(meson.current_source_dir(), 'compare', testname + '.node'),
|
||||
join_paths(meson.current_source_dir(), 'compare', testname + '.png'),
|
||||
],
|
||||
env: [
|
||||
'GSK_RENDERER=' + renderer_name,
|
||||
'GTK_A11Y=test',
|
||||
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
|
||||
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
|
||||
],
|
||||
suite: suites + [ 'gsk-compare-rotated-' + renderer_name ],
|
||||
)
|
||||
endif
|
||||
endforeach
|
||||
endforeach
|
||||
|
@ -160,6 +160,80 @@ test_to_float (void)
|
||||
g_assert_true (flt[10] == 9. && flt[11] == 11.);
|
||||
}
|
||||
|
||||
#define ROUNDED_RECT_INIT_FULL(x,y,w,h,w0,h0,w1,h1,w2,h2,w3,h3) \
|
||||
(GskRoundedRect) { .bounds = GRAPHENE_RECT_INIT (x, y, w, h), \
|
||||
.corner = { \
|
||||
GRAPHENE_SIZE_INIT (w0, h0), \
|
||||
GRAPHENE_SIZE_INIT (w1, h1), \
|
||||
GRAPHENE_SIZE_INIT (w2, h2), \
|
||||
GRAPHENE_SIZE_INIT (w3, h3), \
|
||||
}}
|
||||
|
||||
#define ROUNDED_RECT_INIT(x,y,w,h,r) \
|
||||
ROUNDED_RECT_INIT_FULL (x, y, w, h, r, r, r, r, r, r, r, r)
|
||||
|
||||
#define ROUNDED_RECT_INIT_UNIFORM(x,y,w,h,r1,r2,r3,r4) \
|
||||
ROUNDED_RECT_INIT_FULL (x, y, w, h, r1, r1, r2, r2, r3, r3, r4, r4)
|
||||
|
||||
|
||||
static void
|
||||
test_intersect_with_rect (void)
|
||||
{
|
||||
struct {
|
||||
GskRoundedRect rounded;
|
||||
graphene_rect_t rect;
|
||||
GskRoundedRect expected;
|
||||
GskRoundedRectIntersection result;
|
||||
} test[] = {
|
||||
{ ROUNDED_RECT_INIT (20, 50, 100, 100, 50), GRAPHENE_RECT_INIT (60, 80, 60, 70),
|
||||
ROUNDED_RECT_INIT (0, 0, 0, 0, 0), GSK_INTERSECTION_NOT_REPRESENTABLE },
|
||||
{ ROUNDED_RECT_INIT (0, 0, 100, 100, 10), GRAPHENE_RECT_INIT (0, 0, 100, 100),
|
||||
ROUNDED_RECT_INIT (0, 0, 100, 100, 10), GSK_INTERSECTION_NONEMPTY },
|
||||
{ ROUNDED_RECT_INIT (0, 0, 100, 100, 10), GRAPHENE_RECT_INIT (0, 0, 80, 80),
|
||||
ROUNDED_RECT_INIT_UNIFORM (0, 0, 80, 80, 10, 0, 0, 0), GSK_INTERSECTION_NONEMPTY },
|
||||
{ ROUNDED_RECT_INIT (0, 0, 100, 100, 10), GRAPHENE_RECT_INIT (10, 10, 80, 80),
|
||||
ROUNDED_RECT_INIT (10, 10, 80, 80, 0), GSK_INTERSECTION_NONEMPTY },
|
||||
{ ROUNDED_RECT_INIT (0, 0, 100, 100, 10), GRAPHENE_RECT_INIT (10, 15, 100, 70),
|
||||
ROUNDED_RECT_INIT (10, 15, 90, 70, 0), GSK_INTERSECTION_NONEMPTY },
|
||||
{ ROUNDED_RECT_INIT (0, 0, 100, 100, 10), GRAPHENE_RECT_INIT (110, 0, 10, 10),
|
||||
ROUNDED_RECT_INIT (0, 0, 0, 0, 0), GSK_INTERSECTION_EMPTY },
|
||||
{ ROUNDED_RECT_INIT (0, 0, 100, 100, 10), GRAPHENE_RECT_INIT (5, 5, 90, 90),
|
||||
ROUNDED_RECT_INIT (5, 5, 90, 90, 0), GSK_INTERSECTION_NONEMPTY },
|
||||
{ ROUNDED_RECT_INIT (0, 0, 100, 100, 10), GRAPHENE_RECT_INIT (1, 1, 1, 1),
|
||||
ROUNDED_RECT_INIT (0, 0, 0, 0, 0), GSK_INTERSECTION_EMPTY },
|
||||
{ ROUNDED_RECT_INIT (0, 0, 100, 100, 10), GRAPHENE_RECT_INIT (5, -5, 10, 20),
|
||||
ROUNDED_RECT_INIT (0, 0, 0, 0, 0), GSK_INTERSECTION_NOT_REPRESENTABLE },
|
||||
{ ROUNDED_RECT_INIT_UNIFORM (-200, 0, 200, 100, 0, 0, 0, 40), GRAPHENE_RECT_INIT (-200, 0, 160, 100),
|
||||
ROUNDED_RECT_INIT_UNIFORM (-200, 0, 160, 100, 0, 0, 0, 40), GSK_INTERSECTION_NONEMPTY },
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < G_N_ELEMENTS (test); i++)
|
||||
{
|
||||
GskRoundedRect out;
|
||||
GskRoundedRectIntersection res;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_test_message ("intersection test %u", i);
|
||||
|
||||
memset (&out, 0, sizeof (GskRoundedRect));
|
||||
|
||||
res = gsk_rounded_rect_intersect_with_rect (&test[i].rounded, &test[i].rect, &out);
|
||||
g_assert_true (res == test[i].result);
|
||||
if (res == GSK_INTERSECTION_NONEMPTY)
|
||||
{
|
||||
if (!gsk_rounded_rect_equal (&out, &test[i].expected))
|
||||
{
|
||||
char *s = gsk_rounded_rect_to_string (&test[i].expected);
|
||||
char *s2 = gsk_rounded_rect_to_string (&out);
|
||||
g_test_message ("expected %s, got %s\n", s, s2);
|
||||
}
|
||||
g_assert_true (gsk_rounded_rect_equal (&out, &test[i].expected));
|
||||
}
|
||||
|
||||
g_assert_true ((res != GSK_INTERSECTION_EMPTY) == gsk_rounded_rect_intersects_rect (&test[i].rounded, &test[i].rect));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -171,6 +245,7 @@ main (int argc,
|
||||
g_test_add_func ("/rounded-rect/contains-point", test_contains_point);
|
||||
g_test_add_func ("/rounded-rect/is-circular", test_is_circular);
|
||||
g_test_add_func ("/rounded-rect/to-float", test_to_float);
|
||||
g_test_add_func ("/rounded-rect/intersect-with-rect", test_intersect_with_rect);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
@ -582,6 +582,14 @@ test_transform_bounds (void)
|
||||
t = gsk_transform_translate (t, &GRAPHENE_POINT_INIT (-50, -50));
|
||||
gsk_transform_transform_bounds (t, &bounds, &out);
|
||||
g_assert_true (graphene_rect_equal (&out, &GRAPHENE_RECT_INIT(0, 0, 100, 100)));
|
||||
|
||||
t = gsk_transform_scale (NULL, -1, 1);
|
||||
gsk_transform_transform_bounds (t, &bounds, &out);
|
||||
g_assert_true (graphene_rect_equal (&out, &GRAPHENE_RECT_INIT(-100, 0, 100, 100)));
|
||||
|
||||
t = gsk_transform_scale (NULL, -1, -2);
|
||||
gsk_transform_transform_bounds (t, &bounds, &out);
|
||||
g_assert_true (graphene_rect_equal (&out, &GRAPHENE_RECT_INIT(-100, -200, 100, 200)));
|
||||
}
|
||||
|
||||
#define DEG_TO_RAD(x) ((x) / 180.0 * G_PI)
|
||||
|
@ -25,7 +25,7 @@ setups = [
|
||||
{ 'backend': 'broadway', 'if': broadway_enabled, },
|
||||
{ 'name': 'wayland_smalltexture',
|
||||
'backend': 'wayland', 'if': wayland_enabled,
|
||||
'env': ['GSK_MAX_TEXTURE_SIZE=1024'], },
|
||||
'env': ['GSK_MAX_TEXTURE_SIZE=1024'] },
|
||||
{ 'backend': 'win32', 'if': os_win32 },
|
||||
]
|
||||
|
||||
@ -39,6 +39,10 @@ foreach setup : setups
|
||||
exclude += 'gsk-compare-broadway'
|
||||
endif
|
||||
|
||||
if name == 'wayland_smalltexture'
|
||||
exclude += 'wayland_smalltexture_failing'
|
||||
endif
|
||||
|
||||
env = common_env + [
|
||||
'GDK_BACKEND=@0@'.format(backend),
|
||||
] + setup.get('env', [])
|
||||
|
Loading…
Reference in New Issue
Block a user