static cairo_int_status_t _analyze_meta_surface_pattern (cairo_analysis_surface_t *surface, const cairo_pattern_t *pattern) { cairo_surface_t *analysis = &surface->base; const cairo_surface_pattern_t *surface_pattern; cairo_status_t status; cairo_bool_t old_has_ctm; cairo_matrix_t old_ctm, p2d; cairo_rectangle_int_t old_clip; cairo_rectangle_int_t meta_extents; int old_width; int old_height; assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); surface_pattern = (const cairo_surface_pattern_t *) pattern; assert (_cairo_surface_is_meta (surface_pattern->surface)); old_width = surface->width; old_height = surface->height; old_clip = surface->current_clip; status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents); if (_cairo_status_is_error (status)) return status; surface->width = meta_extents.width; surface->height = meta_extents.height; surface->current_clip.x = 0; surface->current_clip.y = 0; surface->current_clip.width = surface->width; surface->current_clip.height = surface->height; old_ctm = surface->ctm; old_has_ctm = surface->has_ctm; p2d = pattern->matrix; status = cairo_matrix_invert (&p2d); /* _cairo_pattern_set_matrix guarantees invertibility */ assert (status == CAIRO_STATUS_SUCCESS); cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm); surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface, analysis); if (status == CAIRO_STATUS_SUCCESS) status = analysis->status; surface->ctm = old_ctm; surface->has_ctm = old_has_ctm; surface->current_clip = old_clip; surface->width = old_width; surface->height = old_height; return status; }
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); }