static cairo_int_status_t _paint_page (cairo_paginated_surface_t *surface) { cairo_surface_t *analysis; cairo_status_t status; cairo_bool_t has_supported, has_page_fallback, has_finegrained_fallback; if (surface->target->status) return surface->target->status; analysis = _cairo_analysis_surface_create (surface->target, surface->width, surface->height); if (analysis->status) return _cairo_surface_set_error (surface->target, analysis->status); surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); status = _cairo_meta_surface_replay_and_create_regions (surface->meta, analysis); if (status || analysis->status) { if (status == CAIRO_STATUS_SUCCESS) status = analysis->status; goto FAIL; } if (surface->backend->set_bounding_box) { cairo_box_t bbox; _cairo_analysis_surface_get_bounding_box (analysis, &bbox); status = surface->backend->set_bounding_box (surface->target, &bbox); if (status) goto FAIL; } if (surface->backend->set_fallback_images_required) { cairo_bool_t has_fallbacks = _cairo_analysis_surface_has_unsupported (analysis); status = surface->backend->set_fallback_images_required (surface->target, has_fallbacks); if (status) goto FAIL; } /* Finer grained fallbacks are currently only supported for some * surface types */ switch (surface->target->type) { case CAIRO_SURFACE_TYPE_PDF: case CAIRO_SURFACE_TYPE_PS: case CAIRO_SURFACE_TYPE_WIN32_PRINTING: has_supported = _cairo_analysis_surface_has_supported (analysis); has_page_fallback = FALSE; has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis); break; case CAIRO_SURFACE_TYPE_IMAGE: case CAIRO_SURFACE_TYPE_XLIB: case CAIRO_SURFACE_TYPE_XCB: case CAIRO_SURFACE_TYPE_GLITZ: case CAIRO_SURFACE_TYPE_QUARTZ: case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: case CAIRO_SURFACE_TYPE_WIN32: case CAIRO_SURFACE_TYPE_BEOS: case CAIRO_SURFACE_TYPE_DIRECTFB: case CAIRO_SURFACE_TYPE_SVG: case CAIRO_SURFACE_TYPE_OS2: default: if (_cairo_analysis_surface_has_unsupported (analysis)) { has_supported = FALSE; has_page_fallback = TRUE; } else { has_supported = TRUE; has_page_fallback = FALSE; } has_finegrained_fallback = FALSE; break; } if (has_supported) { surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); status = _cairo_meta_surface_replay_region (surface->meta, surface->target, CAIRO_META_REGION_NATIVE); assert (status != CAIRO_INT_STATUS_UNSUPPORTED); if (status) goto FAIL; } if (has_page_fallback) { cairo_box_int_t box; surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK); box.p1.x = 0; box.p1.y = 0; box.p2.x = surface->width; box.p2.y = surface->height; status = _paint_fallback_image (surface, &box); if (status) goto FAIL; } if (has_finegrained_fallback) { cairo_region_t *region; cairo_box_int_t *boxes; int num_boxes, i; surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK); /* Reset clip region before drawing the fall back images */ status = _cairo_surface_intersect_clip_path (surface->target, NULL, CAIRO_FILL_RULE_WINDING, CAIRO_GSTATE_TOLERANCE_DEFAULT, CAIRO_ANTIALIAS_DEFAULT); if (status) goto FAIL; region = _cairo_analysis_surface_get_unsupported (analysis); status = _cairo_region_get_boxes (region, &num_boxes, &boxes); if (status) goto FAIL; for (i = 0; i < num_boxes; i++) { status = _paint_fallback_image (surface, &boxes[i]); if (status) { _cairo_region_boxes_fini (region, boxes); goto FAIL; } } _cairo_region_boxes_fini (region, boxes); } FAIL: cairo_surface_destroy (analysis); return _cairo_surface_set_error (surface->target, 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) { cairo_box_int_t *boxes; int i; if (_cairo_region_get_boxes (&clip->region, &n_boxes, &boxes)) return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; if (n_boxes) { rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t)); if (rectangles == NULL) { _cairo_region_boxes_fini (&clip->region, boxes); _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; } for (i = 0; i < n_boxes; ++i) { cairo_rectangle_int_t clip_rect = { boxes[i].p1.x, boxes[i].p1.y, boxes[i].p2.x - boxes[i].p1.x, boxes[i].p2.y - boxes[i].p1.y }; if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) { _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); _cairo_region_boxes_fini (&clip->region, boxes); free (rectangles); return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; } } } _cairo_region_boxes_fini (&clip->region, boxes); } else { cairo_rectangle_int_t extents; n_boxes = 1; rectangles = malloc(sizeof (cairo_rectangle_t)); if (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 (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; }