mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-04 14:08:29 +02:00
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:
parent
b07de014eb
commit
3a5d71c431
6 changed files with 285 additions and 168 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue