mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 22:48:07 +02:00
clip: consider gstate target extents in _cairo_gstate_copy_clip_rectangle_list
Fixes https://bugs.freedesktop.org/show_bug.cgi?id=29125 To be consistent with _cairo_gstate_clip_extents, the context's clip should be intersected with the target surface extents (instead of only using them when there is no clip). Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
b79ea8a6ca
commit
108b1c7825
3 changed files with 57 additions and 49 deletions
|
|
@ -1495,7 +1495,7 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status)
|
|||
cairo_rectangle_list_t *
|
||||
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
|
||||
{
|
||||
#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S));
|
||||
#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S))
|
||||
|
||||
cairo_rectangle_list_t *list;
|
||||
cairo_rectangle_t *rectangles = NULL;
|
||||
|
|
@ -1507,57 +1507,37 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
|
|||
if (clip->all_clipped)
|
||||
goto DONE;
|
||||
|
||||
if (clip->path != NULL) {
|
||||
status = _cairo_clip_get_region (clip, ®ion);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
|
||||
goto DONE;
|
||||
} else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
|
||||
} else if (unlikely (status)) {
|
||||
return ERROR_LIST (status);
|
||||
}
|
||||
if (!clip->path)
|
||||
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
|
||||
|
||||
status = _cairo_clip_get_region (clip, ®ion);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
|
||||
goto DONE;
|
||||
} else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
|
||||
} else if (unlikely (status)) {
|
||||
return ERROR_LIST (status);
|
||||
}
|
||||
|
||||
if (region != NULL) {
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
if (n_rects) {
|
||||
rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
|
||||
if (unlikely (rectangles == NULL)) {
|
||||
return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_rects; ++i) {
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &clip_rect);
|
||||
|
||||
if (! _cairo_clip_int_rect_to_user (gstate,
|
||||
&clip_rect,
|
||||
&rectangles[i]))
|
||||
{
|
||||
free (rectangles);
|
||||
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
if (! _cairo_surface_get_extents (_cairo_gstate_get_target (gstate),
|
||||
&extents))
|
||||
{
|
||||
/* unbounded surface -> unclipped */
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
n_rects = 1;
|
||||
rectangles = malloc(sizeof (cairo_rectangle_t));
|
||||
if (unlikely (rectangles == NULL))
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
if (n_rects) {
|
||||
rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
|
||||
if (unlikely (rectangles == NULL)) {
|
||||
return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
if (! _cairo_clip_int_rect_to_user (gstate, &extents, rectangles)) {
|
||||
free (rectangles);
|
||||
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
|
||||
for (i = 0; i < n_rects; ++i) {
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &clip_rect);
|
||||
|
||||
if (! _cairo_clip_int_rect_to_user (gstate,
|
||||
&clip_rect,
|
||||
&rectangles[i]))
|
||||
{
|
||||
free (rectangles);
|
||||
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1555,7 +1555,19 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
|
|||
cairo_rectangle_list_t*
|
||||
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
|
||||
{
|
||||
return _cairo_clip_copy_rectangle_list (&gstate->clip, gstate);
|
||||
cairo_clip_t clip;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_rectangle_list_t *list;
|
||||
|
||||
_cairo_clip_init_copy (&clip, &gstate->clip);
|
||||
|
||||
if (_cairo_surface_get_extents (gstate->target, &extents))
|
||||
_cairo_clip_rectangle (&clip, &extents);
|
||||
|
||||
list = _cairo_clip_copy_rectangle_list (&clip, gstate);
|
||||
_cairo_clip_fini (&clip);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -120,6 +120,22 @@ preamble (cairo_test_context_t *ctx)
|
|||
}
|
||||
cairo_rectangle_list_destroy (rectangle_list);
|
||||
|
||||
/* We should get the same results after applying a clip that contains the
|
||||
existing clip. */
|
||||
phase = "Clip beyond surface extents";
|
||||
cairo_save (cr);
|
||||
cairo_rectangle (cr, -10, -10, SIZE + 20 , SIZE + 20);
|
||||
cairo_clip (cr);
|
||||
rectangle_list = cairo_copy_clip_rectangle_list (cr);
|
||||
if (! check_count (ctx, phase, rectangle_list, 1) ||
|
||||
! check_clip_extents (ctx, phase, cr, 0, 0, SIZE, SIZE) ||
|
||||
! check_rectangles_contain (ctx, phase, rectangle_list, 0, 0, SIZE, SIZE))
|
||||
{
|
||||
goto FAIL;
|
||||
}
|
||||
cairo_rectangle_list_destroy (rectangle_list);
|
||||
cairo_restore (cr);
|
||||
|
||||
/* Test simple clip rect. */
|
||||
phase = "Simple clip rect";
|
||||
cairo_save (cr);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue