/* Composites a region representing a set of trapezoids. */ static cairo_status_t _composite_trap_region (cairo_clip_t *clip, cairo_pattern_t *src, cairo_operator_t op, cairo_surface_t *dst, cairo_region_t *trap_region, cairo_rectangle_int_t *extents) { cairo_status_t status; cairo_pattern_union_t solid_pattern; cairo_pattern_union_t mask; int num_rects = _cairo_region_num_boxes (trap_region); unsigned int clip_serial; cairo_surface_t *clip_surface = clip ? clip->surface : NULL; if (clip_surface && op == CAIRO_OPERATOR_CLEAR) { _cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR); src = &solid_pattern.base; op = CAIRO_OPERATOR_DEST_OUT; } if (num_rects == 0) return CAIRO_STATUS_SUCCESS; if (num_rects > 1) { if (_cairo_surface_get_clip_mode (dst) != CAIRO_CLIP_MODE_REGION) return CAIRO_INT_STATUS_UNSUPPORTED; clip_serial = _cairo_surface_allocate_clip_serial (dst); status = _cairo_surface_set_clip_region (dst, trap_region, clip_serial); if (status) return status; } if (clip_surface) _cairo_pattern_init_for_surface (&mask.surface, clip_surface); status = _cairo_surface_composite (op, src, clip_surface ? &mask.base : NULL, dst, extents->x, extents->y, extents->x - (clip_surface ? clip->surface_rect.x : 0), extents->y - (clip_surface ? clip->surface_rect.y : 0), extents->x, extents->y, extents->width, extents->height); /* Restore the original clip if we modified it temporarily. */ if (num_rects > 1) { cairo_status_t status2 = _cairo_surface_set_clip (dst, clip); if (status == CAIRO_STATUS_SUCCESS) status = status2; } if (clip_surface) _cairo_pattern_fini (&mask.base); if (src == &solid_pattern.base) _cairo_pattern_fini (&solid_pattern.base); return status; }
cairo_rectangle_list_t * _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) { cairo_rectangle_list_t *list; cairo_rectangle_t *rectangles = NULL; int n_boxes = 0; if (clip->all_clipped) goto DONE; if (clip->path || clip->surface) { _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; } if (clip->has_region) { int i; n_boxes = _cairo_region_num_boxes (&clip->region); if (n_boxes) { rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t)); if (unlikely (rectangles == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; } for (i = 0; i < n_boxes; ++i) { cairo_box_int_t box; cairo_rectangle_int_t clip_rect; _cairo_region_get_box (&clip->region, i, &box); clip_rect.x = box.p1.x; clip_rect.y = box.p1.y; clip_rect.width = box.p2.x - box.p1.x; clip_rect.height = box.p2.y - box.p1.y; if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) { _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); free (rectangles); return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; } } } } else { cairo_rectangle_int_t extents; n_boxes = 1; rectangles = malloc(sizeof (cairo_rectangle_t)); if (unlikely (rectangles == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; } if (_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents) || !_cairo_clip_int_rect_to_user(gstate, &extents, rectangles)) { _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); free (rectangles); return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; } } DONE: list = malloc (sizeof (cairo_rectangle_list_t)); if (unlikely (list == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); free (rectangles); return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; } list->status = CAIRO_STATUS_SUCCESS; list->rectangles = rectangles; list->num_rectangles = n_boxes; return list; }