pattern: An EXTEND_NONE surface is not opaque if we sample outside

Fixes test/clear-source as proposed by Benjamin Otte.
This commit is contained in:
Chris Wilson 2010-01-19 19:18:54 +00:00
parent b07de014eb
commit 3a5d71c431
6 changed files with 285 additions and 168 deletions

View file

@ -1010,7 +1010,7 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
if (_clipped (gstate))
return CAIRO_STATUS_SUCCESS;
if (_cairo_pattern_is_opaque (mask))
if (_cairo_pattern_is_opaque (mask, NULL))
return _cairo_gstate_paint (gstate);
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);

View file

@ -1738,6 +1738,34 @@ _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
return CAIRO_COLOR_IS_OPAQUE (&solid->color);
}
static cairo_bool_t
_surface_is_opaque (const cairo_surface_pattern_t *pattern,
const cairo_rectangle_int_t *r)
{
if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
return FALSE;
if (pattern->base.extend != CAIRO_EXTEND_NONE)
return TRUE;
if (r != NULL) {
cairo_rectangle_int_t extents;
if (! _cairo_surface_get_extents (pattern->surface, &extents))
return TRUE;
if (r->x >= extents.x &&
r->y >= extents.y &&
r->x + r->width <= extents.x + extents.width &&
r->y + r->height <= extents.y + extents.height)
{
return TRUE;
}
}
return FALSE;
}
static cairo_bool_t
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
{
@ -1760,7 +1788,8 @@ _gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
* Return value: %TRUE if the pattern is a opaque.
**/
cairo_bool_t
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
const cairo_rectangle_int_t *extents)
{
const cairo_pattern_union_t *pattern;
@ -1772,7 +1801,7 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
case CAIRO_PATTERN_TYPE_SOLID:
return _cairo_pattern_is_opaque_solid (abstract_pattern);
case CAIRO_PATTERN_TYPE_SURFACE:
return cairo_surface_get_content (pattern->surface.surface) == CAIRO_CONTENT_COLOR;
return _surface_is_opaque (&pattern->surface, extents);
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
return _gradient_is_opaque (&pattern->gradient.base);

View file

@ -45,6 +45,7 @@
#include "cairo-pdf-surface-private.h"
#include "cairo-pdf-operators-private.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-error-private.h"
#include "cairo-image-info-private.h"
#include "cairo-recording-surface-private.h"
@ -1179,25 +1180,6 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
{
cairo_gradient_pattern_t *gradient;
gradient = (cairo_gradient_pattern_t *) pattern;
/* Gradients with zero stops do not produce any output */
if (gradient->n_stops == 0)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
/* Gradients with one stop are the same as solid colors */
if (gradient->n_stops == 1) {
pattern_res->id = 0;
gstate_res->id = 0;
return CAIRO_STATUS_SUCCESS;
}
}
status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
if (unlikely (status))
return status;
@ -1212,8 +1194,9 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
/* gradient patterns require an smask object to implement transparency */
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
if (_cairo_pattern_is_opaque (pattern) == FALSE) {
pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
{
if (_cairo_pattern_is_opaque (pattern, extents) == FALSE) {
pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
if (pdf_pattern.gstate_res.id == 0) {
cairo_pattern_destroy (pdf_pattern.pattern);
@ -1222,14 +1205,14 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
}
}
pdf_pattern.width = surface->width;
pdf_pattern.width = surface->width;
pdf_pattern.height = surface->height;
if (extents != NULL) {
pdf_pattern.extents = *extents;
} else {
pdf_pattern.extents.x = 0;
pdf_pattern.extents.y = 0;
pdf_pattern.extents.width = surface->width;
pdf_pattern.extents.width = surface->width;
pdf_pattern.extents.height = surface->height;
}
@ -5214,7 +5197,8 @@ _pdf_operator_supported (cairo_operator_t op)
static cairo_int_status_t
_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *pattern)
const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *extents)
{
if (surface->force_fallbacks &&
surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@ -5248,7 +5232,7 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
if (_cairo_surface_is_recording (surface_pattern->surface)) {
if (_cairo_pattern_is_opaque (pattern)) {
if (_cairo_pattern_is_opaque (pattern, extents)) {
return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
} else {
/* FIXME: The analysis surface does not yet have
@ -5267,7 +5251,7 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
}
}
if (_cairo_pattern_is_opaque (pattern))
if (_cairo_pattern_is_opaque (pattern, extents))
return CAIRO_STATUS_SUCCESS;
else
return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
@ -5279,12 +5263,10 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
static cairo_bool_t
_cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *pattern)
const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *extents)
{
if (_cairo_pdf_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
return TRUE;
else
return FALSE;
return _cairo_pdf_surface_analyze_operation (surface, op, pattern, extents) != CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_int_status_t
@ -5314,17 +5296,27 @@ _cairo_pdf_surface_paint (void *abstract_surface,
cairo_status_t status;
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
cairo_rectangle_int_t extents;
cairo_composite_rectangles_t extents;
status = _cairo_composite_rectangles_init_for_paint (&extents,
surface->width, surface->height,
op, source, clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
return _cairo_pdf_surface_analyze_operation (surface, op, source);
return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
} else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
status = _cairo_pdf_surface_start_fallback (surface);
if (unlikely (status))
return status;
}
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
@ -5339,8 +5331,8 @@ _cairo_pdf_surface_paint (void *abstract_surface,
return status;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
source->extend == CAIRO_EXTEND_NONE) {
source->extend == CAIRO_EXTEND_NONE)
{
_cairo_output_stream_printf (surface->output, "q\n");
status = _cairo_pdf_surface_paint_surface_pattern (surface,
(cairo_surface_pattern_t *) source);
@ -5351,15 +5343,10 @@ _cairo_pdf_surface_paint (void *abstract_surface,
return _cairo_output_stream_get_status (surface->output);
}
status = _cairo_surface_paint_extents (&surface->base,
op, source, clip,
&extents);
if (unlikely (status))
return status;
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &extents,
status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
return CAIRO_STATUS_SUCCESS;
@ -5424,18 +5411,29 @@ _cairo_pdf_surface_mask (void *abstract_surface,
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_smask_group_t *group;
cairo_status_t status;
cairo_composite_rectangles_t extents;
status = _cairo_composite_rectangles_init_for_mask (&extents,
surface->width, surface->height,
op, source, mask, clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
cairo_status_t source_status, mask_status;
source_status = _cairo_pdf_surface_analyze_operation (surface, op, source);
source_status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
if (_cairo_status_is_error (source_status))
return source_status;
if (mask->has_component_alpha) {
mask_status = CAIRO_INT_STATUS_UNSUPPORTED;
} else {
mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask);
mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask, &extents.bounded);
if (_cairo_status_is_error (mask_status))
return mask_status;
}
@ -5448,8 +5446,8 @@ _cairo_pdf_surface_mask (void *abstract_surface,
return status;
}
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
assert (_cairo_pdf_surface_operation_supported (surface, op, mask));
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
assert (_cairo_pdf_surface_operation_supported (surface, op, mask, &extents.bounded));
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
@ -5519,31 +5517,50 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
cairo_clip_t *clip)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_status_t status;
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
cairo_rectangle_int_t extents;
cairo_composite_rectangles_t extents;
cairo_status_t status;
status = _cairo_composite_rectangles_init_for_stroke (&extents,
surface->width,
surface->height,
op, source,
path, style, ctm,
clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
}
/* use the more accurate extents */
if (extents.is_bounded) {
status = _cairo_path_fixed_stroke_extents (path, style,
ctm, ctm_inverse,
tolerance,
&extents.mask);
if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
return CAIRO_STATUS_SUCCESS;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
return status;
status = _cairo_surface_stroke_extents (&surface->base,
op, source, path,
style, ctm, ctm_inverse,
tolerance, antialias,
clip, &extents);
if (unlikely (status))
return status;
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &extents,
status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
return CAIRO_STATUS_SUCCESS;
@ -5632,17 +5649,39 @@ _cairo_pdf_surface_fill (void *abstract_surface,
cairo_status_t status;
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
cairo_rectangle_int_t extents;
cairo_composite_rectangles_t extents;
status = _cairo_composite_rectangles_init_for_fill (&extents,
surface->width,
surface->height,
op, source, path,
clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
}
/* use the more accurate extents */
if (extents.is_bounded) {
_cairo_path_fixed_fill_extents (path,
tolerance, fill_rule,
&extents.mask);
if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
return CAIRO_STATUS_SUCCESS;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
return _cairo_pdf_surface_analyze_operation (surface, op, source);
return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
} else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
status = _cairo_pdf_surface_start_fallback (surface);
if (unlikely (status))
return status;
}
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
@ -5653,8 +5692,8 @@ _cairo_pdf_surface_fill (void *abstract_surface,
return status;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
source->extend == CAIRO_EXTEND_NONE) {
source->extend == CAIRO_EXTEND_NONE)
{
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
return status;
@ -5675,16 +5714,10 @@ _cairo_pdf_surface_fill (void *abstract_surface,
return _cairo_output_stream_get_status (surface->output);
}
status = _cairo_surface_fill_extents (&surface->base,
op, source, path, fill_rule,
tolerance, antialias,
clip, &extents);
if (unlikely (status))
return status;
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &extents,
status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
return CAIRO_STATUS_SUCCESS;
@ -5786,8 +5819,8 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
/* PDF rendering of fill-stroke is not the same as cairo when
* either the fill or stroke is not opaque.
*/
if ( !_cairo_pattern_is_opaque (fill_source) ||
!_cairo_pattern_is_opaque (stroke_source))
if ( !_cairo_pattern_is_opaque (fill_source, NULL) ||
!_cairo_pattern_is_opaque (stroke_source, NULL))
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -5891,30 +5924,40 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
cairo_clip_t *clip)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_status_t status;
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
cairo_rectangle_int_t extents;
cairo_composite_rectangles_t extents;
cairo_bool_t overlap;
cairo_status_t status;
status = _cairo_composite_rectangles_init_for_glyphs (&extents,
surface->width,
surface->height,
op, source,
scaled_font,
glyphs, num_glyphs,
clip,
&overlap);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
return status;
status = _cairo_surface_glyphs_extents (&surface->base, op, source,
glyphs, num_glyphs,
scaled_font,
clip, &extents);
if (unlikely (status))
return status;
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &extents,
status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
return CAIRO_STATUS_SUCCESS;
@ -6000,7 +6043,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
* be in a separate text object otherwise overlapping text
* from separate calls to show_glyphs will not composite with
* each other. */
if (! _cairo_pattern_is_opaque (source)) {
if (! _cairo_pattern_is_opaque (source, &extents.bounded)) {
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
return status;

View file

@ -58,6 +58,7 @@
#include "cairo-ps.h"
#include "cairo-ps-surface-private.h"
#include "cairo-pdf-operators-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-error-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-paginated-private.h"
@ -1742,7 +1743,8 @@ pattern_supported (cairo_ps_surface_t *surface, const cairo_pattern_t *pattern)
static cairo_int_status_t
_cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *pattern)
const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *extents)
{
if (surface->force_fallbacks &&
surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@ -1788,7 +1790,7 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
surface_pattern);
}
if (_cairo_pattern_is_opaque (pattern))
if (_cairo_pattern_is_opaque (pattern, extents))
return CAIRO_STATUS_SUCCESS;
return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
@ -1797,12 +1799,10 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
static cairo_bool_t
_cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *pattern)
const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *extents)
{
if (_cairo_ps_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
return TRUE;
else
return FALSE;
return _cairo_ps_surface_analyze_operation (surface, op, pattern, extents) != CAIRO_INT_STATUS_UNSUPPORTED;
}
/* The "standard" implementation limit for PostScript string sizes is
@ -3437,28 +3437,32 @@ _cairo_ps_surface_paint (void *abstract_surface,
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_rectangle_int_t extents;
cairo_composite_rectangles_t extents;
cairo_status_t status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_ps_surface_analyze_operation (surface, op, source);
status = _cairo_composite_rectangles_init_for_paint (&extents,
surface->width, surface->height,
op, source, clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
assert (_cairo_ps_surface_operation_supported (surface, op, source));
return status;
}
if (! _cairo_rectangle_intersect (&extents.bounded, &surface->page_bbox))
return CAIRO_STATUS_SUCCESS;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_ps_surface_analyze_operation (surface, op, source, &extents.bounded);
assert (_cairo_ps_surface_operation_supported (surface, op, source, &extents.bounded));
#if DEBUG_PS
_cairo_output_stream_printf (stream,
"%% _cairo_ps_surface_paint\n");
#endif
status = _cairo_surface_paint_extents (&surface->base,
op, source, clip,
&extents);
if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &surface->page_bbox))
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
return status;
@ -3474,13 +3478,13 @@ _cairo_ps_surface_paint (void *abstract_surface,
_cairo_output_stream_printf (stream, "q\n");
status = _cairo_ps_surface_paint_surface (surface,
(cairo_surface_pattern_t *) source,
&extents, op);
&extents.bounded, op);
if (unlikely (status))
return status;
_cairo_output_stream_printf (stream, "Q\n");
} else {
status = _cairo_ps_surface_emit_pattern (surface, source, &extents, op);
status = _cairo_ps_surface_emit_pattern (surface, source, &extents.bounded, op);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
@ -3488,8 +3492,8 @@ _cairo_ps_surface_paint (void *abstract_surface,
return status;
_cairo_output_stream_printf (stream, "%d %d %d %d rectfill\n",
extents.x, extents.y,
extents.width, extents.height);
extents.bounded.x, extents.bounded.y,
extents.bounded.width, extents.bounded.height);
}
return CAIRO_STATUS_SUCCESS;
@ -3508,36 +3512,54 @@ _cairo_ps_surface_stroke (void *abstract_surface,
cairo_clip_t *clip)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
cairo_int_status_t status;
cairo_rectangle_int_t extents;
status = _cairo_composite_rectangles_init_for_stroke (&extents,
surface->width,
surface->height,
op, source,
path, style, ctm,
clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
}
if (! _cairo_rectangle_intersect (&extents.bounded, &surface->page_bbox))
return CAIRO_STATUS_SUCCESS;
/* use the more accurate extents */
if (extents.is_bounded) {
status = _cairo_path_fixed_stroke_extents (path, style,
ctm, ctm_inverse,
tolerance,
&extents.mask);
if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
return CAIRO_STATUS_SUCCESS;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_ps_surface_analyze_operation (surface, op, source);
return _cairo_ps_surface_analyze_operation (surface, op, source, &extents.bounded);
assert (_cairo_ps_surface_operation_supported (surface, op, source));
assert (_cairo_ps_surface_operation_supported (surface, op, source, &extents.bounded));
#if DEBUG_PS
_cairo_output_stream_printf (surface->stream,
"%% _cairo_ps_surface_stroke\n");
#endif
status = _cairo_surface_stroke_extents (&surface->base,
op, source,
path, style,
ctm, ctm_inverse,
tolerance, antialias,
clip, &extents);
if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &surface->page_bbox))
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
return status;
status = _cairo_ps_surface_emit_pattern (surface, source, &extents, op);
status = _cairo_ps_surface_emit_pattern (surface, source, &extents.bounded, op);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
@ -3562,13 +3584,38 @@ _cairo_ps_surface_fill (void *abstract_surface,
cairo_clip_t *clip)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
cairo_int_status_t status;
cairo_rectangle_int_t extents;
status = _cairo_composite_rectangles_init_for_fill (&extents,
surface->width,
surface->height,
op, source, path,
clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
}
if (! _cairo_rectangle_intersect (&extents.bounded, &surface->page_bbox))
return CAIRO_STATUS_SUCCESS;
/* use the more accurate extents */
if (extents.is_bounded) {
_cairo_path_fixed_fill_extents (path,
tolerance, fill_rule,
&extents.mask);
if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
return CAIRO_STATUS_SUCCESS;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_ps_surface_analyze_operation (surface, op, source);
return _cairo_ps_surface_analyze_operation (surface, op, source, &extents.bounded);
assert (_cairo_ps_surface_operation_supported (surface, op, source));
assert (_cairo_ps_surface_operation_supported (surface, op, source, &extents.bounded));
#if DEBUG_PS
_cairo_output_stream_printf (surface->stream,
@ -3579,17 +3626,6 @@ _cairo_ps_surface_fill (void *abstract_surface,
if (unlikely (status))
return status;
status = _cairo_surface_fill_extents (&surface->base,
op, source,
path, fill_rule,
tolerance, antialias,
clip, &extents);
if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &surface->page_bbox))
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
return status;
@ -3608,14 +3644,14 @@ _cairo_ps_surface_fill (void *abstract_surface,
status = _cairo_ps_surface_paint_surface (surface,
(cairo_surface_pattern_t *) source,
&extents, op);
&extents.bounded, op);
if (unlikely (status))
return status;
_cairo_output_stream_printf (surface->stream, "Q\n");
_cairo_pdf_operators_reset (&surface->pdf_operators);
} else {
status = _cairo_ps_surface_emit_pattern (surface, source, &extents, op);
status = _cairo_ps_surface_emit_pattern (surface, source, &extents.bounded, op);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
@ -3641,38 +3677,40 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
int *remaining_glyphs)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
cairo_bool_t overlap;
cairo_status_t status;
cairo_rectangle_int_t extents;
status = _cairo_composite_rectangles_init_for_glyphs (&extents,
surface->width,
surface->height,
op, source,
scaled_font,
glyphs, num_glyphs,
clip,
&overlap);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_ps_surface_analyze_operation (surface, op, source);
return _cairo_ps_surface_analyze_operation (surface, op, source, &extents.bounded);
assert (_cairo_ps_surface_operation_supported (surface, op, source));
assert (_cairo_ps_surface_operation_supported (surface, op, source, &extents.bounded));
#if DEBUG_PS
_cairo_output_stream_printf (surface->stream,
"%% _cairo_ps_surface_show_glyphs\n");
#endif
if (num_glyphs <= 0)
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_glyphs_extents (&surface->base,
op, source,
glyphs, num_glyphs,
scaled_font,
clip, &extents);
if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &surface->page_bbox))
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
return status;
status = _cairo_ps_surface_emit_pattern (surface, source, &extents, op);
status = _cairo_ps_surface_emit_pattern (surface, source, &extents.bounded, op);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
@ -3729,7 +3767,7 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
surface->page_bbox.x = x1;
surface->page_bbox.y = y1;
surface->page_bbox.width = x2 - x1;
surface->page_bbox.width = x2 - x1;
surface->page_bbox.height = y2 - y1;
_cairo_output_stream_printf (surface->stream,

View file

@ -2165,6 +2165,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
cairo_xlib_surface_t *src;
cairo_xlib_surface_t *mask;
cairo_int_status_t status;
cairo_rectangle_int_t src_extents;
composite_operation_t operation;
int itx, ity;
cairo_bool_t is_integer_translation;
@ -2181,10 +2182,15 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
X_DEBUG ((dst->dpy, "composite (dst=%x)", (unsigned int) dst->drawable));
src_extents.x = src_x;
src_extents.y = src_y;
src_extents.width = width;
src_extents.height = height;
needs_alpha_composite =
_operator_needs_alpha_composite (op,
_surface_has_alpha (dst),
! _cairo_pattern_is_opaque (src_pattern));
! _cairo_pattern_is_opaque (src_pattern,
&src_extents));
_cairo_xlib_display_notify (dst->display);

View file

@ -2527,7 +2527,8 @@ cairo_private cairo_bool_t
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern);
cairo_private cairo_bool_t
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern);
_cairo_pattern_is_opaque (const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *extents);
enum {
CAIRO_PATTERN_ACQUIRE_NONE = 0x0,