static VALUE cr_clip_rectangle_list (VALUE self) { VALUE rb_rectangles; cairo_rectangle_list_t *rectangles; int i; rectangles = cairo_copy_clip_rectangle_list (_SELF); rb_cairo_check_status (rectangles->status); rb_rectangles = rb_ary_new2 (rectangles->num_rectangles); for (i = 0; i < rectangles->num_rectangles; i++) { VALUE argv[4]; cairo_rectangle_t rectangle = rectangles->rectangles[i]; argv[0] = rb_float_new (rectangle.x); argv[1] = rb_float_new (rectangle.y); argv[2] = rb_float_new (rectangle.width); argv[3] = rb_float_new (rectangle.height); rb_ary_push (rb_rectangles, rb_class_new_instance (4, argv, rb_cCairo_Rectangle)); } cairo_rectangle_list_destroy (rectangles); return rb_rectangles; }
static PyObject * pycairo_copy_clip_rectangle_list (PycairoContext *o) { int i; PyObject *rv = NULL; cairo_rectangle_t *r; cairo_rectangle_list_t *rlist = cairo_copy_clip_rectangle_list (o->ctx); if (rlist->status != CAIRO_STATUS_SUCCESS) { Pycairo_Check_Status (rlist->status); goto exit; } rv = PyTuple_New(rlist->num_rectangles); if (rv == NULL) goto exit; for (i = 0, r = rlist->rectangles; i < rlist->num_rectangles; i++, r++) { PyObject *py_rect = Py_BuildValue("(dddd)", r->x, r->y, r->width, r->height); if (py_rect == NULL) { Py_CLEAR(rv); goto exit; } PyTuple_SET_ITEM (rv, i, py_rect); } exit: cairo_rectangle_list_destroy(rlist); return rv; }
bool gfxContext::ClipContainsRect(const gfxRect& aRect) { cairo_rectangle_list_t *clip = cairo_copy_clip_rectangle_list(mCairo); bool result = false; if (clip->status == CAIRO_STATUS_SUCCESS) { for (int i = 0; i < clip->num_rectangles; i++) { gfxRect rect(clip->rectangles[i].x, clip->rectangles[i].y, clip->rectangles[i].width, clip->rectangles[i].height); if (rect.Contains(aRect)) { result = PR_TRUE; break; } } } cairo_rectangle_list_destroy(clip); return result; }
static bool _get_rectangular_clip (cairo_t *cr, const nsIntRect& bounds, bool *need_clip, nsIntRect *rectangles, int max_rectangles, int *num_rectangles) { cairo_rectangle_list_t *cliplist; cairo_rectangle_t *clips; int i; bool retval = true; cliplist = cairo_copy_clip_rectangle_list (cr); if (cliplist->status != CAIRO_STATUS_SUCCESS) { retval = false; NATIVE_DRAWING_NOTE("FALLBACK: non-rectangular clip"); goto FINISH; } /* the clip is always in surface backend coordinates (i.e. native backend coords) */ clips = cliplist->rectangles; for (i = 0; i < cliplist->num_rectangles; ++i) { nsIntRect rect; if (!_convert_coord_to_int (clips[i].x, &rect.x) || !_convert_coord_to_int (clips[i].y, &rect.y) || !_convert_coord_to_int (clips[i].width, &rect.width) || !_convert_coord_to_int (clips[i].height, &rect.height)) { retval = false; NATIVE_DRAWING_NOTE("FALLBACK: non-integer clip"); goto FINISH; } if (rect.IsEqualInterior(bounds)) { /* the bounds are entirely inside the clip region so we don't need to clip. */ *need_clip = false; goto FINISH; } NS_ASSERTION(bounds.Contains(rect), "Was expecting to be clipped to bounds"); if (i >= max_rectangles) { retval = false; NATIVE_DRAWING_NOTE("FALLBACK: unsupported clip rectangle count"); goto FINISH; } rectangles[i] = rect; } *need_clip = true; *num_rectangles = cliplist->num_rectangles; FINISH: cairo_rectangle_list_destroy (cliplist); return retval; }
static void gimp_display_shell_canvas_draw_image (GimpDisplayShell *shell, cairo_t *cr) { cairo_rectangle_list_t *clip_rectangles; cairo_rectangle_int_t image_rect; image_rect.x = - shell->offset_x; image_rect.y = - shell->offset_y; gimp_display_shell_scale_get_image_size (shell, &image_rect.width, &image_rect.height); /* first, clear the exposed part of the region that is outside the * image, which is the exposed region minus the image rectangle */ cairo_save (cr); if (shell->rotate_transform) cairo_transform (cr, shell->rotate_transform); cairo_rectangle (cr, image_rect.x, image_rect.y, image_rect.width, image_rect.height); cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); cairo_clip (cr); if (gdk_cairo_get_clip_rectangle (cr, NULL)) gimp_display_shell_draw_background (shell, cr); cairo_restore (cr); /* then, draw the exposed part of the region that is inside the * image */ cairo_save (cr); clip_rectangles = cairo_copy_clip_rectangle_list (cr); if (shell->rotate_transform) cairo_transform (cr, shell->rotate_transform); cairo_rectangle (cr, image_rect.x, image_rect.y, image_rect.width, image_rect.height); cairo_clip (cr); if (gdk_cairo_get_clip_rectangle (cr, NULL)) { gint i; cairo_save (cr); gimp_display_shell_draw_checkerboard (shell, cr); cairo_restore (cr); for (i = 0; i < clip_rectangles->num_rectangles; i++) { cairo_rectangle_t rect = clip_rectangles->rectangles[i]; gimp_display_shell_draw_image (shell, cr, floor (rect.x), floor (rect.y), ceil (rect.width), ceil (rect.height)); } } cairo_rectangle_list_destroy (clip_rectangles); cairo_restore (cr); /* finally, draw all the remaining image window stuff on top */ /* draw canvas items */ cairo_save (cr); if (shell->rotate_transform) cairo_transform (cr, shell->rotate_transform); gimp_canvas_item_draw (shell->canvas_item, cr); cairo_restore (cr); gimp_canvas_item_draw (shell->unrotated_item, cr); /* restart (and recalculate) the selection boundaries */ gimp_display_shell_selection_restart (shell); }
static cairo_test_status_t preamble (cairo_test_context_t *ctx) { cairo_surface_t *surface; cairo_t *cr; cairo_rectangle_list_t *rectangle_list; const char *phase; cairo_status_t status; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); cr = cairo_create (surface); cairo_surface_destroy (surface); /* first, test basic stuff. This should not be clipped, it should return the surface rectangle. */ phase = "No clip set"; rectangle_list = cairo_copy_clip_rectangle_list (cr); if (! check_count (ctx, phase, rectangle_list, 1) || ! check_clip_extents (ctx, phase, cr, 0, 0, 100, 100) || ! check_rectangles_contain (ctx, phase, rectangle_list, 0, 0, 100, 100)) { goto FAIL; } cairo_rectangle_list_destroy (rectangle_list); /* Test simple clip rect. */ phase = "Simple clip rect"; cairo_save (cr); cairo_rectangle (cr, 10, 10, 80, 80); 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, 10, 10, 80, 80) || ! check_rectangles_contain (ctx, phase, rectangle_list, 10, 10, 80, 80)) { goto FAIL; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr); /* Test everything clipped out. */ phase = "All clipped out"; cairo_save (cr); cairo_clip (cr); rectangle_list = cairo_copy_clip_rectangle_list (cr); if (! check_count (ctx, phase, rectangle_list, 0)) { goto FAIL; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr); /* test two clip rects */ phase = "Two clip rects"; cairo_save (cr); cairo_rectangle (cr, 10, 10, 10, 10); cairo_rectangle (cr, 20, 20, 10, 10); cairo_clip (cr); cairo_rectangle (cr, 15, 15, 10, 10); cairo_clip (cr); rectangle_list = cairo_copy_clip_rectangle_list (cr); if (! check_count (ctx, phase, rectangle_list, 2) || ! check_clip_extents (ctx, phase, cr, 15, 15, 10, 10) || ! check_rectangles_contain (ctx, phase, rectangle_list, 15, 15, 5, 5) || ! check_rectangles_contain (ctx, phase, rectangle_list, 20, 20, 5, 5)) { goto FAIL; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr); /* test non-rectangular clip */ phase = "Nonrectangular clip"; cairo_save (cr); cairo_move_to (cr, 0, 0); cairo_line_to (cr, 100, 100); cairo_line_to (cr, 100, 0); cairo_close_path (cr); cairo_clip (cr); rectangle_list = cairo_copy_clip_rectangle_list (cr); /* can't get this in one tight user-space rectangle */ if (! check_unrepresentable (ctx, phase, rectangle_list) || ! check_clip_extents (ctx, phase, cr, 0, 0, 100, 100)) { goto FAIL; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr); phase = "User space, simple scale, getting clip with same transform"; cairo_save (cr); cairo_scale (cr, 2, 2); cairo_rectangle (cr, 5, 5, 40, 40); 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, 5, 5, 40, 40) || ! check_rectangles_contain (ctx, phase, rectangle_list, 5, 5, 40, 40)) { goto FAIL; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr); phase = "User space, simple scale, getting clip with no transform"; cairo_save (cr); cairo_save (cr); cairo_scale (cr, 2, 2); cairo_rectangle (cr, 5, 5, 40, 40); cairo_restore (cr); 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, 10, 10, 80, 80) || ! check_rectangles_contain (ctx, phase, rectangle_list, 10, 10, 80, 80)) { goto FAIL; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr); phase = "User space, rotation, getting clip with no transform"; cairo_save (cr); cairo_save (cr); cairo_rotate (cr, 12); cairo_rectangle (cr, 5, 5, 40, 40); cairo_restore (cr); cairo_clip (cr); rectangle_list = cairo_copy_clip_rectangle_list (cr); if (! check_unrepresentable (ctx, phase, rectangle_list)) goto FAIL; FAIL: cairo_rectangle_list_destroy (rectangle_list); status = cairo_status (cr); cairo_destroy (cr); return cairo_test_status_from_status (ctx, status); }
static gboolean goc_canvas_draw (GtkWidget *widget, cairo_t *cr) { double x0, y0, x1, y1; double ax0, ay0, ax1, ay1; double clip_x1, clip_y1, clip_x2, clip_y2; GocCanvas *canvas = GOC_CANVAS (widget); GdkEventExpose *event = (GdkEventExpose *) gtk_get_current_event (); GocCanvasPrivate *priv = (GocCanvasPrivate *) canvas->priv; cairo_rectangle_list_t *l = cairo_copy_clip_rectangle_list (cr); int i, x, y; if (GOC_IS_ITEM (priv->invalidated_item) && priv->invalid_region) { /* evaluate the cairo clipped region and compare with the saved one */ cairo_region_t *region; cairo_rectangle_int_t rect[l->num_rectangles]; for (i= 0; i < l->num_rectangles; i++) { rect[i].x = l->rectangles[i].x; rect[i].y = l->rectangles[i].y; rect[i].width = l->rectangles[i].width; rect[i].height = l->rectangles[i].height; } region = cairo_region_create_rectangles (rect, l->num_rectangles); if (cairo_region_equal (priv->invalid_region, region)) { cairo_rectangle_list_destroy (l); cairo_region_destroy (region); /* looks like each time we call gtk_widget_queue_draw*, the draw event is fired twice */ if (priv->done) { priv->invalidated_item = NULL; cairo_region_destroy (priv->invalid_region); priv->invalid_region = NULL; } else { goc_item_draw (priv->invalidated_item, cr); priv->done = TRUE; } return TRUE; } cairo_region_destroy (region); } x = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas))); y = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas))); cairo_translate (cr, -x, -y); goc_item_get_bounds (GOC_ITEM (canvas->root),&x0, &y0, &x1, &y1); for (i= 0; i < l->num_rectangles; i++) { cairo_save (cr); cairo_rectangle (cr, l->rectangles[i].x, l->rectangles[i].y, l->rectangles[i].width, l->rectangles[i].height); cairo_clip (cr); clip_x1 = l->rectangles[i].x; clip_y1 = l->rectangles[i].y; clip_x2 = clip_x1 + l->rectangles[i].width; clip_y2 = clip_y1 + l->rectangles[i].height; if (canvas->direction == GOC_DIRECTION_RTL) { ax1 = (double) (canvas->width - clip_x1) / canvas->pixels_per_unit + canvas->scroll_x1; ax0 = (double) (canvas->width - clip_x2) / canvas->pixels_per_unit + canvas->scroll_x1; } else { ax0 = (double) clip_x1 / canvas->pixels_per_unit + canvas->scroll_x1; ax1 = ((double) clip_x1 + event->area.width) / canvas->pixels_per_unit + canvas->scroll_x1; } ay0 = (double) clip_y1 / canvas->pixels_per_unit + canvas->scroll_y1; ay1 = (double) clip_y2 / canvas->pixels_per_unit + canvas->scroll_y1; if (x0 <= ax1 && x1 >= ax0 && y0 <= ay1 && y1 >= ay0) { canvas->cur_event = (GdkEvent *) event; goc_item_draw_region (GOC_ITEM (canvas->root), cr, ax0, ay0, ax1, ay1); } cairo_restore (cr); } cairo_rectangle_list_destroy (l); return TRUE; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); cairo_surface_t *surface; cairo_t *cr2; cairo_rectangle_list_t *rectangle_list; const char *phase; cairo_bool_t uses_clip_rects; surface = cairo_surface_create_similar (cairo_get_group_target (cr), CAIRO_CONTENT_COLOR, 100, 100); /* don't use cr accidentally */ cr = NULL; cr2 = cairo_create (surface); cairo_surface_destroy (surface); /* Check the surface type so we ignore cairo_copy_clip_rectangle_list failures * on surface types that don't use rectangle lists for clipping. * Default to FALSE for the internal surface types, (meta, test-fallback, etc.) */ switch (cairo_surface_get_type (surface)) { case CAIRO_SURFACE_TYPE_IMAGE: case CAIRO_SURFACE_TYPE_XLIB: case CAIRO_SURFACE_TYPE_XCB: case CAIRO_SURFACE_TYPE_GLITZ: case CAIRO_SURFACE_TYPE_WIN32: case CAIRO_SURFACE_TYPE_BEOS: case CAIRO_SURFACE_TYPE_DIRECTFB: uses_clip_rects = TRUE; break; case CAIRO_SURFACE_TYPE_QUARTZ: case CAIRO_SURFACE_TYPE_PDF: case CAIRO_SURFACE_TYPE_PS: case CAIRO_SURFACE_TYPE_SVG: case CAIRO_SURFACE_TYPE_OS2: default: uses_clip_rects = FALSE; break; } /* first, test basic stuff. This should not be clipped, it should return the surface rectangle. */ phase = "No clip set"; rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 0, 0, 100, 100) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 0, 0, 100, 100)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); /* Test simple clip rect. */ phase = "Simple clip rect"; cairo_save (cr2); cairo_rectangle (cr2, 10, 10, 80, 80); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 10, 10, 80, 80) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); /* Test everything clipped out. */ phase = "All clipped out"; cairo_save (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 0)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); /* test two clip rects */ phase = "Two clip rects"; cairo_save (cr2); cairo_rectangle (cr2, 10, 10, 10, 10); cairo_rectangle (cr2, 20, 20, 10, 10); cairo_clip (cr2); cairo_rectangle (cr2, 15, 15, 10, 10); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 2) || !check_clip_extents (ctx, phase, cr2, 15, 15, 10, 10) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 15, 15, 5, 5) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 20, 20, 5, 5)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); /* test non-rectangular clip */ phase = "Nonrectangular clip"; cairo_save (cr2); cairo_move_to (cr2, 0, 0); cairo_line_to (cr2, 100, 100); cairo_line_to (cr2, 100, 0); cairo_close_path (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); /* can't get this in one tight user-space rectangle */ if (!check_unrepresentable (ctx, phase, rectangle_list) || !check_clip_extents (ctx, phase, cr2, 0, 0, 100, 100)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); phase = "User space, simple scale, getting clip with same transform"; cairo_save (cr2); cairo_scale (cr2, 2, 2); cairo_rectangle (cr2, 5, 5, 40, 40); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 5, 5, 40, 40) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 5, 5, 40, 40)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); phase = "User space, simple scale, getting clip with no transform"; cairo_save (cr2); cairo_save (cr2); cairo_scale (cr2, 2, 2); cairo_rectangle (cr2, 5, 5, 40, 40); cairo_restore (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 10, 10, 80, 80) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); phase = "User space, rotation, getting clip with no transform"; cairo_save (cr2); cairo_save (cr2); cairo_rotate (cr2, 12); cairo_rectangle (cr2, 5, 5, 40, 40); cairo_restore (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_unrepresentable (ctx, phase, rectangle_list)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); cairo_destroy (cr2); return CAIRO_TEST_SUCCESS; }
static cairo_bool_t _get_rectangular_clip (cairo_t *cr, int bounds_x, int bounds_y, int bounds_width, int bounds_height, cairo_bool_t *need_clip, XRectangle *rectangles, int max_rectangles, int *num_rectangles) { cairo_rectangle_list_t *cliplist; cairo_rectangle_t *clips; int i; double b_x = bounds_x; double b_y = bounds_y; double b_x_most = bounds_x + bounds_width; double b_y_most = bounds_y + bounds_height; int rect_count = 0; cairo_bool_t retval = True; cliplist = cairo_copy_clip_rectangle_list (cr); if (cliplist->status != CAIRO_STATUS_SUCCESS) { retval = False; goto FINISH; } if (cliplist->num_rectangles == 0) { *num_rectangles = 0; *need_clip = True; goto FINISH; } clips = cliplist->rectangles; for (i = 0; i < cliplist->num_rectangles; ++i) { double intersect_x, intersect_y, intersect_x_most, intersect_y_most; /* the clip is always in surface backend coordinates (i.e. native backend coords) */ if (b_x >= clips[i].x && b_x_most <= clips[i].x + clips[i].width && b_y >= clips[i].y && b_y_most <= clips[i].y + clips[i].height) { /* the bounds are entirely inside the clip region so we don't need to clip. */ *need_clip = False; goto FINISH; } if (_intersect_interval (b_x, b_x_most, clips[i].x, clips[i].x + clips[i].width, &intersect_x, &intersect_x_most) && _intersect_interval (b_y, b_y_most, clips[i].y, clips[i].y + clips[i].height, &intersect_y, &intersect_y_most)) { XRectangle *rect = &rectangles[rect_count]; if (rect_count >= max_rectangles) { retval = False; goto FINISH; } if (!_convert_coord_to_short (intersect_x, &rect->x) || !_convert_coord_to_short (intersect_y, &rect->y) || !_convert_coord_to_unsigned_short (intersect_x_most - intersect_x, &rect->width) || !_convert_coord_to_unsigned_short (intersect_y_most - intersect_y, &rect->height)) { retval = False; goto FINISH; } ++rect_count; } } *need_clip = True; *num_rectangles = rect_count; FINISH: cairo_rectangle_list_destroy (cliplist); return retval; }