예제 #1
0
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);
}
예제 #2
0
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;
}