Пример #1
0
static cairo_int_status_t
_cairo_gl_msaa_compositor_fill (const cairo_compositor_t	*compositor,
				cairo_composite_rectangles_t	*composite,
				const cairo_path_fixed_t	*path,
				cairo_fill_rule_t		 fill_rule,
				double				 tolerance,
				cairo_antialias_t		 antialias)
{
    cairo_gl_composite_t setup;
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
    cairo_gl_context_t *ctx = NULL;
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
    cairo_traps_t traps;
    cairo_bool_t use_color_attr = FALSE;

    if (! can_use_msaa_compositor (dst, antialias))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (composite->is_bounded == FALSE) {
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);

	if (unlikely (surface == NULL))
	    return CAIRO_INT_STATUS_UNSUPPORTED;


	status = _cairo_compositor_fill (compositor, surface,
					 CAIRO_OPERATOR_SOURCE,
					 &composite->source_pattern.base,
					 path, fill_rule, tolerance,
					 antialias, NULL);

	if (unlikely (status)) {
	    cairo_surface_destroy (surface);
	    return status;
	}

	return _paint_back_unbounded_surface (compositor, composite, surface);
    }

    if (_cairo_path_fixed_fill_is_rectilinear (path) &&
	composite->clip != NULL &&
	composite->clip->num_boxes == 1 &&
	composite->clip->path == NULL) {
	cairo_clip_t *clip = _cairo_clip_copy (composite->clip);
	clip = _cairo_clip_intersect_rectilinear_path (clip,
						       path,
						       fill_rule,
						       antialias);
	if (clip->num_boxes)
		status = _cairo_gl_msaa_compositor_fill_rectilinear (compositor,
								     composite,
								     path,
								     fill_rule,
								     tolerance,
								     antialias,
								     clip);
	_cairo_clip_destroy (clip);

	return status;
    }

    status = _cairo_gl_composite_init (&setup,
				       composite->op,
				       dst,
				       FALSE /* assume_component_alpha */);
    if (unlikely (status)) {
        _cairo_gl_composite_fini (&setup);
	return status;
    }

    _cairo_traps_init (&traps);

    if (_cairo_path_fixed_fill_is_rectilinear (path)) {
	status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
							      fill_rule,
							      antialias,
							      &traps);
	use_color_attr = TRUE;
    } else
	status = _cairo_path_fixed_fill_to_traps (path, fill_rule,
						  tolerance, &traps);
    if (unlikely (status))
	goto cleanup_traps;

    status = _cairo_gl_composite_set_source (&setup,
					     composite->original_source_pattern,
					     &composite->source_sample_area,
					     &composite->bounded,
					     use_color_attr);
    if (unlikely (status))
	goto cleanup_setup;

    _cairo_gl_msaa_compositor_set_clip (composite, &setup);

    status = _cairo_gl_composite_begin_multisample (&setup, &ctx,
	antialias != CAIRO_ANTIALIAS_NONE);
    if (unlikely (status))
	goto cleanup_setup;

    status = _draw_traps (ctx, &setup, &traps);
    if (unlikely (status))
        goto cleanup_setup;

cleanup_setup:
    _cairo_gl_composite_fini (&setup);

    if (ctx)
	status = _cairo_gl_context_release (ctx, status);

cleanup_traps:
    _cairo_traps_fini (&traps);

    return status;
}
Пример #2
0
static cairo_status_t
_rectilinear_clip_to_boxes (const cairo_path_fixed_t *path,
			    cairo_fill_rule_t fill_rule,
			    cairo_box_t **boxes,
			    int *num_boxes,
			    int *size_boxes)
{
    cairo_polygon_t polygon;
    cairo_traps_t traps;
    cairo_status_t status;

    _cairo_traps_init (&traps);
    _cairo_traps_limit (&traps, *boxes, *num_boxes);

    _cairo_polygon_init (&polygon);
    _cairo_polygon_limit (&polygon, *boxes, *num_boxes);

    status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
							  fill_rule,
							  &traps);
    if (unlikely (_cairo_status_is_error (status)))
	goto CLEANUP;
    if (status == CAIRO_STATUS_SUCCESS)
	goto BOXES;

    /* tolerance will be ignored as the path is rectilinear */
    status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon);
    if (unlikely (status))
	goto CLEANUP;

    if (polygon.num_edges == 0) {
	*num_boxes = 0;
    } else {
	status = _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps,
									&polygon,
									fill_rule);
	if (likely (status == CAIRO_STATUS_SUCCESS)) {
	    int i;

          BOXES:
	    i = *size_boxes;
	    if (i < 0)
		i = -i;

	    if (traps.num_traps > i) {
		cairo_box_t *new_boxes;
		int new_size;

		new_size = pot (traps.num_traps);
		new_boxes = _cairo_malloc_ab (new_size, sizeof (cairo_box_t));
		if (unlikely (new_boxes == NULL)) {
		    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
		    goto CLEANUP;
		}

		if (*size_boxes > 0)
		    free (*boxes);

		*boxes = new_boxes;
		*size_boxes = new_size;
	    }

	    for (i = 0; i < traps.num_traps; i++) {
		(*boxes)[i].p1.x = traps.traps[i].left.p1.x;
		(*boxes)[i].p1.y = traps.traps[i].top;
		(*boxes)[i].p2.x = traps.traps[i].right.p1.x;
		(*boxes)[i].p2.y = traps.traps[i].bottom;
	    }
	    *num_boxes = i;
	}
    }

  CLEANUP:
    _cairo_polygon_fini (&polygon);
    _cairo_traps_fini (&traps);

    return status;
}
static cairo_region_t *
_cairo_path_fixed_fill_rectilinear_tessellate_to_region (const cairo_path_fixed_t	*path,
							 cairo_fill_rule_t	 fill_rule,
							 const cairo_rectangle_int_t *extents)
{
    cairo_box_t box;
    cairo_polygon_t polygon;
    cairo_traps_t traps;
    cairo_status_t status;
    cairo_region_t *region;

    /* first try to bypass fill-to-polygon */
    _cairo_traps_init (&traps);
    status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
							  fill_rule,
							  &traps);
    if (_cairo_status_is_error (status))
	goto CLEANUP_TRAPS;

    if (status == CAIRO_STATUS_SUCCESS) {
	status = _cairo_traps_extract_region (&traps, &region);
	goto CLEANUP_TRAPS;
    }

    /* path is not rectangular, try extracting clipped rectilinear edges */
    _cairo_polygon_init (&polygon);
    if (extents != NULL) {
	_cairo_box_from_rectangle (&box, extents);
	_cairo_polygon_limit (&polygon, &box, 1);
    }

    /* tolerance will be ignored as the path is rectilinear */
    status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon);
    if (unlikely (status))
	goto CLEANUP_POLYGON;

    if (polygon.num_edges == 0) {
	region = cairo_region_create ();
    } else {
	status =
	    _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps,
								   &polygon,
								   fill_rule);
	if (likely (status == CAIRO_STATUS_SUCCESS))
	    status = _cairo_traps_extract_region (&traps, &region);
    }

  CLEANUP_POLYGON:
    _cairo_polygon_fini (&polygon);

  CLEANUP_TRAPS:
    _cairo_traps_fini (&traps);

    if (unlikely (status)) { /* XXX _cairo_region_create_in_error() */
	region = cairo_region_create ();
	if (likely (region->status) == CAIRO_STATUS_SUCCESS)
	    region->status = status;
    }

    return region;
}
Пример #4
0
static cairo_int_status_t
_cairo_clip_path_to_region_geometric (cairo_clip_path_t *clip_path)
{
    cairo_traps_t traps;
    cairo_box_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_t)];
    cairo_box_t *boxes = stack_boxes;
    cairo_status_t status;
    int n;

    /* If we have nothing to intersect with this path, then it cannot
     * magically be reduced into a region.
     */
    if (clip_path->prev == NULL)
	goto UNSUPPORTED;

    /* Start simple... Intersect some boxes with an arbitrary path. */
    if (! clip_path->path.is_rectilinear)
	goto UNSUPPORTED;
    if (clip_path->prev->prev != NULL)
	goto UNSUPPORTED;

    _cairo_traps_init (&traps);
    _cairo_box_from_rectangle (&boxes[0], &clip_path->extents);
    _cairo_traps_limit (&traps, boxes, 1);

    status = _cairo_path_fixed_fill_rectilinear_to_traps (&clip_path->path,
							  clip_path->fill_rule,
							  &traps);
    if (unlikely (_cairo_status_is_error (status)))
	return status;
    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
	goto UNSUPPORTED;

    if (traps.num_traps > ARRAY_LENGTH (stack_boxes)) {
	boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t));
	if (unlikely (boxes == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    for (n = 0; n < traps.num_traps; n++) {
	boxes[n].p1.x = traps.traps[n].left.p1.x;
	boxes[n].p1.y = traps.traps[n].top;
	boxes[n].p2.x = traps.traps[n].right.p1.x;
	boxes[n].p2.y = traps.traps[n].bottom;
    }

    _cairo_traps_clear (&traps);
    _cairo_traps_limit (&traps, boxes, n);
    status = _cairo_path_fixed_fill_to_traps (&clip_path->prev->path,
					      clip_path->prev->fill_rule,
					      clip_path->prev->tolerance,
					      &traps);
    if (boxes != stack_boxes)
	free (boxes);

    if (unlikely (status))
	return status;

    status = _cairo_traps_extract_region (&traps, &clip_path->region);
    _cairo_traps_fini (&traps);

    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
	goto UNSUPPORTED;
    if (unlikely (status))
	return status;

    clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
    return CAIRO_STATUS_SUCCESS;

UNSUPPORTED:
    clip_path->flags |= CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED;
    return CAIRO_INT_STATUS_UNSUPPORTED;
}