[cairo-commit] 3 commits - src/cairo-composite-rectangles.c src/cairo-composite-rectangles-private.h src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-recording-surface.c
Chris Wilson
ickle at kemper.freedesktop.org
Sat Aug 13 05:15:57 PDT 2011
src/cairo-composite-rectangles-private.h | 12 -
src/cairo-composite-rectangles.c | 26 ++
src/cairo-pdf-surface.c | 359 ++++++++++++++++++-------------
src/cairo-ps-surface.c | 18 -
src/cairo-recording-surface.c | 7
5 files changed, 254 insertions(+), 168 deletions(-)
New commits:
commit 279f6ceb595412bef165a808f05caa3044ef102c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Aug 13 12:33:21 2011 +0100
Only reduce the clip if it is not in active use for the operation
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-composite-rectangles-private.h b/src/cairo-composite-rectangles-private.h
index c6dac30..dd5bd41 100644
--- a/src/cairo-composite-rectangles-private.h
+++ b/src/cairo-composite-rectangles-private.h
@@ -53,11 +53,13 @@ CAIRO_BEGIN_DECLS
struct _cairo_composite_rectangles {
cairo_rectangle_int_t source;
cairo_rectangle_int_t mask;
- cairo_rectangle_int_t bounded; /* dst */
- cairo_rectangle_int_t unbounded; /* clip */
+ cairo_rectangle_int_t destination;
+
+ cairo_rectangle_int_t bounded; /* source? IN mask? IN unbounded */
+ cairo_rectangle_int_t unbounded; /* destination IN clip */
uint32_t is_bounded;
- cairo_clip_t *clip;
+ cairo_clip_t *clip; /* clip will be reduced to the minimal container */
};
cairo_private cairo_int_status_t
@@ -108,6 +110,10 @@ cairo_private cairo_int_status_t
_cairo_composite_rectangles_intersect_mask_extents (cairo_composite_rectangles_t *extents,
const cairo_box_t *box);
+cairo_private cairo_bool_t
+_cairo_composite_rectangles_can_reduce_clip (cairo_composite_rectangles_t *composite,
+ cairo_clip_t *clip);
+
cairo_private void
_cairo_composite_rectangles_fini (cairo_composite_rectangles_t *extents);
diff --git a/src/cairo-composite-rectangles.c b/src/cairo-composite-rectangles.c
index 439f453..6083973 100644
--- a/src/cairo-composite-rectangles.c
+++ b/src/cairo-composite-rectangles.c
@@ -54,11 +54,12 @@ _cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
const cairo_clip_t *clip)
{
extents->clip = NULL;
+ extents->destination = *unbounded;
if (_cairo_clip_is_all_clipped (clip))
return FALSE;
- extents->unbounded = *unbounded;
+ extents->unbounded = extents->destination;
if (clip != NULL) {
if (! _cairo_rectangle_intersect (&extents->unbounded,
_cairo_clip_get_extents (clip)))
@@ -247,3 +248,26 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
return _cairo_composite_rectangles_intersect (extents, clip);
}
+
+cairo_bool_t
+_cairo_composite_rectangles_can_reduce_clip (cairo_composite_rectangles_t *composite,
+ cairo_clip_t *clip)
+{
+ cairo_rectangle_int_t extents;
+
+ if (clip == NULL)
+ return TRUE;
+
+ /* XXX In the not a region case, we could still search through the boxes */
+ if (! _cairo_clip_is_region (clip))
+ return FALSE;
+
+ extents = composite->destination;
+ if (composite->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE)
+ _cairo_rectangle_intersect (&extents, &composite->source);
+ if (composite->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
+ _cairo_rectangle_intersect (&extents, &composite->mask);
+
+ return cairo_region_contains_rectangle (_cairo_clip_get_region (clip),
+ &extents) == CAIRO_REGION_OVERLAP_IN;
+}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ca3a4d2..dd5f68c 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -5793,22 +5793,13 @@ _cairo_pdf_surface_set_clip (cairo_pdf_surface_t *surface,
{
cairo_clip_t *clip = composite->clip;
- if (_cairo_clip_is_region (clip) &&
- cairo_region_contains_rectangle (_cairo_clip_get_region (clip),
- &composite->unbounded) == CAIRO_REGION_OVERLAP_IN)
- {
- clip = NULL;
- }
+ if (_cairo_composite_rectangles_can_reduce_clip (composite, clip))
+ clip = NULL;
if (clip == NULL) {
- cairo_clip_t *current = surface->clipper.clip;
-
- if (current && _cairo_clip_is_region (current) &&
- cairo_region_contains_rectangle (_cairo_clip_get_region (current),
- &composite->unbounded) == CAIRO_REGION_OVERLAP_IN)
- {
+ if (_cairo_composite_rectangles_can_reduce_clip (composite,
+ surface->clipper.clip))
return CAIRO_STATUS_SUCCESS;
- }
}
return _cairo_surface_clipper_set_clip (&surface->clipper, clip);
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 267fd59..a9961fe 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -3617,28 +3617,18 @@ _cairo_ps_surface_set_clip (cairo_ps_surface_t *surface,
{
cairo_clip_t *clip = composite->clip;
- if (_cairo_clip_is_region (clip) &&
- cairo_region_contains_rectangle (_cairo_clip_get_region (clip),
- &composite->unbounded) == CAIRO_REGION_OVERLAP_IN)
- {
- clip = NULL;
- }
+ if (_cairo_composite_rectangles_can_reduce_clip (composite, clip))
+ clip = NULL;
if (clip == NULL) {
- cairo_clip_t *current = surface->clipper.clip;
-
- if (current && _cairo_clip_is_region (current) &&
- cairo_region_contains_rectangle (_cairo_clip_get_region (current),
- &composite->unbounded) == CAIRO_REGION_OVERLAP_IN)
- {
+ if (_cairo_composite_rectangles_can_reduce_clip (composite,
+ surface->clipper.clip))
return CAIRO_STATUS_SUCCESS;
- }
}
return _cairo_surface_clipper_set_clip (&surface->clipper, clip);
}
-
static cairo_int_status_t
_cairo_ps_surface_paint (void *abstract_surface,
cairo_operator_t op,
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index 87b9119..0daf675 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -587,11 +587,8 @@ _command_init (cairo_recording_surface_t *surface,
/* steal the clip */
command->clip = NULL;
- if (! _cairo_clip_is_region (composite->clip) ||
- composite->mask.width > composite->unbounded.width ||
- composite->mask.height > composite->unbounded.height ||
- cairo_region_contains_rectangle (_cairo_clip_get_region (composite->clip),
- &composite->unbounded) != CAIRO_REGION_OVERLAP_IN)
+ if (! _cairo_composite_rectangles_can_reduce_clip (composite,
+ composite->clip))
{
command->clip = composite->clip;
composite->clip = NULL;
commit d391f0908c404344aa6873fbca2b7bd6499009e0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Aug 13 12:26:30 2011 +0100
pdf: composite-rectangles now require freeing after use
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index da6e8f5..ca3a4d2 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -5834,26 +5834,27 @@ _cairo_pdf_surface_paint (void *abstract_surface,
return status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
- return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
+ status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
+ goto cleanup;
} else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
status = _cairo_pdf_surface_start_fallback (surface);
if (unlikely (status))
- return status;
+ goto cleanup;
}
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
status = _cairo_pdf_surface_set_clip (surface, &extents);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_select_operator (surface, op);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
- return status;
+ goto cleanup;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
source->extend == CAIRO_EXTEND_NONE)
@@ -5863,9 +5864,10 @@ _cairo_pdf_surface_paint (void *abstract_surface,
(cairo_surface_pattern_t *) source,
FALSE);
if (unlikely (status))
- return status;
+ goto cleanup;
_cairo_output_stream_printf (surface->output, "Q\n");
+ _cairo_composite_rectangles_fini (&extents);
return _cairo_output_stream_get_status (surface->output);
}
@@ -5875,33 +5877,35 @@ _cairo_pdf_surface_paint (void *abstract_surface,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
if (gstate_res.id != 0) {
group = _cairo_pdf_surface_create_smask_group (surface);
- if (unlikely (group == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (unlikely (group == NULL)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
+ }
group->operation = PDF_PAINT;
status = _cairo_pattern_create_copy (&group->source, source);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
group->source_res = pattern_res;
status = _cairo_pdf_surface_add_smask_group (surface, group);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
if (unlikely (status))
- return status;
+ goto cleanup;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
@@ -5911,7 +5915,7 @@ _cairo_pdf_surface_paint (void *abstract_surface,
status = _cairo_pdf_surface_select_pattern (surface, source,
pattern_res, FALSE);
if (unlikely (status))
- return status;
+ goto cleanup;
_cairo_output_stream_printf (surface->output,
"0 0 %f %f re f\n",
@@ -5919,10 +5923,15 @@ _cairo_pdf_surface_paint (void *abstract_surface,
status = _cairo_pdf_surface_unselect_pattern (surface);
if (unlikely (status))
- return status;
+ goto cleanup;
}
+ _cairo_composite_rectangles_fini (&extents);
return _cairo_output_stream_get_status (surface->output);
+
+cleanup:
+ _cairo_composite_rectangles_fini (&extents);
+ return status;
}
static cairo_int_status_t
@@ -5947,24 +5956,27 @@ _cairo_pdf_surface_mask (void *abstract_surface,
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, &extents.bounded);
- if (_cairo_status_is_error (source_status))
- return source_status;
+ status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
+ if (_cairo_status_is_error (status))
+ goto cleanup;
+ source_status = status;
if (mask->has_component_alpha) {
- mask_status = CAIRO_INT_STATUS_UNSUPPORTED;
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
} else {
- mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask, &extents.bounded);
- if (_cairo_status_is_error (mask_status))
- return mask_status;
+ status = _cairo_pdf_surface_analyze_operation (surface, op, mask, &extents.bounded);
+ if (_cairo_status_is_error (status))
+ goto cleanup;
}
+ mask_status = status;
+ _cairo_composite_rectangles_fini (&extents);
return _cairo_analysis_surface_merge_status (source_status,
mask_status);
} else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
status = _cairo_pdf_surface_start_fallback (surface);
if (unlikely (status))
- return status;
+ goto cleanup;
}
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
@@ -5972,62 +5984,70 @@ _cairo_pdf_surface_mask (void *abstract_surface,
status = _cairo_pdf_surface_set_clip (surface, &extents);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_select_operator (surface, op);
if (unlikely (status))
- return status;
+ goto cleanup;
/* Check if we can use a stencil mask */
status = _cairo_pdf_surface_emit_stencil_mask (surface, source, mask);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ goto cleanup;
group = _cairo_pdf_surface_create_smask_group (surface);
- if (unlikely (group == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (unlikely (group == NULL)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
+ }
group->operation = PDF_MASK;
status = _cairo_pattern_create_copy (&group->source, source);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
status = _cairo_pattern_create_copy (&group->mask, mask);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
group->source_res = _cairo_pdf_surface_new_object (surface);
if (group->source_res.id == 0) {
_cairo_pdf_smask_group_destroy (group);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
}
status = _cairo_pdf_surface_add_smask_group (surface, group);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
status = _cairo_pdf_surface_add_smask (surface, group->group_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
- return status;
+ goto cleanup;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
group->group_res.id,
group->source_res.id);
+ _cairo_composite_rectangles_fini (&extents);
return _cairo_output_stream_get_status (surface->output);
+
+cleanup:
+ _cairo_composite_rectangles_fini (&extents);
+ return status;
}
static cairo_int_status_t
@@ -6059,25 +6079,33 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
/* use the more accurate extents */
if (extents.is_bounded) {
+ cairo_rectangle_int_t mask;
+ cairo_box_t box;
+
status = _cairo_path_fixed_stroke_extents (path, style,
ctm, ctm_inverse,
tolerance,
- &extents.mask);
+ &mask);
if (unlikely (status))
- return status;
+ goto cleanup;
- if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
- return CAIRO_INT_STATUS_SUCCESS;
+ _cairo_box_from_rectangle (&box, &mask);
+ status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
+ &box);
+ if (unlikely (status))
+ goto cleanup;
}
- if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
- return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+ status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
+ goto cleanup;
+ }
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
status = _cairo_pdf_surface_set_clip (surface, &extents);
if (unlikely (status))
- return status;
+ goto cleanup;
pattern_res.id = 0;
gstate_res.id = 0;
@@ -6085,28 +6113,30 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_select_operator (surface, op);
if (unlikely (status))
- return status;
+ goto cleanup;
if (gstate_res.id != 0) {
group = _cairo_pdf_surface_create_smask_group (surface);
- if (unlikely (group == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (unlikely (group == NULL)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
+ }
group->operation = PDF_STROKE;
status = _cairo_pattern_create_copy (&group->source, source);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
group->source_res = pattern_res;
status = _cairo_path_fixed_init_copy (&group->path, path);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
group->style = *style;
@@ -6115,20 +6145,20 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
status = _cairo_pdf_surface_add_smask_group (surface, group);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
- return status;
+ goto cleanup;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
@@ -6137,7 +6167,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
} else {
status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
path,
@@ -6145,14 +6175,19 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
ctm,
ctm_inverse);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_unselect_pattern (surface);
if (unlikely (status))
- return status;
+ goto cleanup;
}
+ _cairo_composite_rectangles_fini (&extents);
return _cairo_output_stream_get_status (surface->output);
+
+cleanup:
+ _cairo_composite_rectangles_fini (&extents);
+ return status;
}
static cairo_int_status_t
@@ -6181,55 +6216,63 @@ _cairo_pdf_surface_fill (void *abstract_surface,
/* use the more accurate extents */
if (extents.is_bounded) {
+ cairo_rectangle_int_t mask;
+ cairo_box_t box;
+
_cairo_path_fixed_fill_extents (path,
fill_rule,
tolerance,
- &extents.mask);
+ &mask);
- if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
- return CAIRO_INT_STATUS_SUCCESS;
+ _cairo_box_from_rectangle (&box, &mask);
+ status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
+ &box);
+ if (unlikely (status))
+ goto cleanup;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
- return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
+ status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
+ goto cleanup;
} else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
status = _cairo_pdf_surface_start_fallback (surface);
if (unlikely (status))
- return status;
+ goto cleanup;
}
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
status = _cairo_pdf_surface_set_clip (surface, &extents);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_select_operator (surface, op);
if (unlikely (status))
- return status;
+ goto cleanup;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
source->extend == CAIRO_EXTEND_NONE)
{
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
- return status;
+ goto cleanup;
_cairo_output_stream_printf (surface->output, "q\n");
status = _cairo_pdf_operators_clip (&surface->pdf_operators,
path,
fill_rule);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_paint_surface_pattern (surface,
(cairo_surface_pattern_t *) source,
FALSE);
if (unlikely (status))
- return status;
+ goto cleanup;
_cairo_output_stream_printf (surface->output, "Q\n");
- return _cairo_output_stream_get_status (surface->output);
+ status = _cairo_output_stream_get_status (surface->output);
+ goto cleanup;
}
pattern_res.id = 0;
@@ -6238,44 +6281,46 @@ _cairo_pdf_surface_fill (void *abstract_surface,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
if (gstate_res.id != 0) {
group = _cairo_pdf_surface_create_smask_group (surface);
- if (unlikely (group == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (unlikely (group == NULL)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
+ }
group->operation = PDF_FILL;
status = _cairo_pattern_create_copy (&group->source, source);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
group->source_res = pattern_res;
status = _cairo_path_fixed_init_copy (&group->path, path);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
group->fill_rule = fill_rule;
status = _cairo_pdf_surface_add_smask_group (surface, group);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
- return status;
+ goto cleanup;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
@@ -6284,20 +6329,25 @@ _cairo_pdf_surface_fill (void *abstract_surface,
} else {
status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_operators_fill (&surface->pdf_operators,
path,
fill_rule);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_unselect_pattern (surface);
if (unlikely (status))
- return status;
+ goto cleanup;
}
+ _cairo_composite_rectangles_fini (&extents);
return _cairo_output_stream_get_status (surface->output);
+
+cleanup:
+ _cairo_composite_rectangles_fini (&extents);
+ return status;
}
static cairo_int_status_t
@@ -6358,32 +6408,46 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
/* use the more accurate extents */
if (extents.is_bounded) {
+ cairo_rectangle_int_t mask;
+ cairo_box_t box;
+
status = _cairo_path_fixed_stroke_extents (path, stroke_style,
stroke_ctm, stroke_ctm_inverse,
stroke_tolerance,
- &extents.mask);
+ &mask);
if (unlikely (status))
- return status;
+ goto cleanup;
- _cairo_rectangle_intersect (&extents.bounded, &extents.mask);
+ _cairo_box_from_rectangle (&box, &mask);
+ status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
+ &box);
+ if (unlikely (status))
+ goto cleanup;
}
status = _cairo_pdf_surface_set_clip (surface, &extents);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_select_operator (surface, fill_op);
if (unlikely (status))
- return status;
+ goto cleanup;
/* use the more accurate extents */
if (extents.is_bounded) {
+ cairo_rectangle_int_t mask;
+ cairo_box_t box;
+
_cairo_path_fixed_fill_extents (path,
fill_rule,
fill_tolerance,
- &extents.mask);
+ &mask);
- _cairo_rectangle_intersect (&extents.bounded, &extents.mask);
+ _cairo_box_from_rectangle (&box, &mask);
+ status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
+ &box);
+ if (unlikely (status))
+ goto cleanup;
}
fill_pattern_res.id = 0;
@@ -6393,7 +6457,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
&fill_pattern_res,
&gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
assert (gstate_res.id == 0);
@@ -6405,7 +6469,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
&stroke_pattern_res,
&gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
assert (gstate_res.id == 0);
@@ -6414,12 +6478,12 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
status = _cairo_pdf_surface_select_pattern (surface, fill_source,
fill_pattern_res, FALSE);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
stroke_pattern_res, TRUE);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
path,
@@ -6428,13 +6492,18 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
stroke_ctm,
stroke_ctm_inverse);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_unselect_pattern (surface);
if (unlikely (status))
- return status;
+ goto cleanup;
+ _cairo_composite_rectangles_fini (&extents);
return _cairo_output_stream_get_status (surface->output);
+
+cleanup:
+ _cairo_composite_rectangles_fini (&extents);
+ return status;
}
static cairo_bool_t
@@ -6475,14 +6544,16 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
if (unlikely (status))
return status;
- if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
- return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+ status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
+ goto cleanup;
+ }
assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
status = _cairo_pdf_surface_set_clip (surface, &extents);
if (unlikely (status))
- return status;
+ goto cleanup;
pattern_res.id = 0;
gstate_res.id = 0;
@@ -6490,22 +6561,24 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_select_operator (surface, op);
if (unlikely (status))
- return status;
+ goto cleanup;
if (gstate_res.id != 0) {
group = _cairo_pdf_surface_create_smask_group (surface);
- if (unlikely (group == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (unlikely (group == NULL)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
+ }
group->operation = PDF_SHOW_GLYPHS;
status = _cairo_pattern_create_copy (&group->source, source);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
group->source_res = pattern_res;
@@ -6513,7 +6586,8 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
group->utf8 = malloc (utf8_len);
if (unlikely (group->utf8 == NULL)) {
_cairo_pdf_smask_group_destroy (group);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
}
memcpy (group->utf8, utf8, utf8_len);
}
@@ -6523,7 +6597,8 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (unlikely (group->glyphs == NULL)) {
_cairo_pdf_smask_group_destroy (group);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
}
memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
}
@@ -6533,7 +6608,8 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
if (unlikely (group->clusters == NULL)) {
_cairo_pdf_smask_group_destroy (group);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
}
memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
}
@@ -6543,20 +6619,20 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
status = _cairo_pdf_surface_add_smask_group (surface, group);
if (unlikely (status)) {
_cairo_pdf_smask_group_destroy (group);
- return status;
+ goto cleanup;
}
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
- return status;
+ goto cleanup;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
@@ -6565,7 +6641,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
} else {
status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
if (unlikely (status))
- return status;
+ goto cleanup;
/* Each call to show_glyphs() with a transclucent pattern must
* be in a separate text object otherwise overlapping text
@@ -6574,7 +6650,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
if (! _cairo_pattern_is_opaque (source, &extents.bounded)) {
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
- return status;
+ goto cleanup;
}
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
@@ -6584,14 +6660,19 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
cluster_flags,
scaled_font);
if (unlikely (status))
- return status;
+ goto cleanup;
status = _cairo_pdf_surface_unselect_pattern (surface);
if (unlikely (status))
- return status;
+ goto cleanup;
}
+ _cairo_composite_rectangles_fini (&extents);
return _cairo_output_stream_get_status (surface->output);
+
+cleanup:
+ _cairo_composite_rectangles_fini (&extents);
+ return status;
}
commit afe84fa77f392a9748319efee01db6b3c6d870fb
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Aug 13 12:09:08 2011 +0100
pdf: Compute fill-stroke extents first before trying to use it to set the clip
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 3a10ef3..da6e8f5 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -6345,18 +6345,34 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
if (fill_op != stroke_op)
return CAIRO_INT_STATUS_UNSUPPORTED;
- status = _cairo_pdf_surface_set_clip (surface, &extents);
+ /* Compute the operation extents using the stroke which will naturally
+ * be larger than the fill extents.
+ */
+ _cairo_pdf_surface_get_extents (surface, &unbounded);
+ status = _cairo_composite_rectangles_init_for_stroke (&extents, &unbounded,
+ stroke_op, stroke_source,
+ path, stroke_style, stroke_ctm,
+ clip);
if (unlikely (status))
return status;
- status = _cairo_pdf_surface_select_operator (surface, fill_op);
+ /* use the more accurate extents */
+ if (extents.is_bounded) {
+ status = _cairo_path_fixed_stroke_extents (path, stroke_style,
+ stroke_ctm, stroke_ctm_inverse,
+ stroke_tolerance,
+ &extents.mask);
+ if (unlikely (status))
+ return status;
+
+ _cairo_rectangle_intersect (&extents.bounded, &extents.mask);
+ }
+
+ status = _cairo_pdf_surface_set_clip (surface, &extents);
if (unlikely (status))
return status;
- _cairo_pdf_surface_get_extents (surface, &unbounded);
- status = _cairo_composite_rectangles_init_for_fill (&extents, &unbounded,
- fill_op, fill_source, path,
- clip);
+ status = _cairo_pdf_surface_select_operator (surface, fill_op);
if (unlikely (status))
return status;
@@ -6381,25 +6397,6 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
assert (gstate_res.id == 0);
- status = _cairo_composite_rectangles_init_for_stroke (&extents, &unbounded,
- stroke_op, stroke_source,
- path, stroke_style, stroke_ctm,
- clip);
- if (unlikely (status))
- return status;
-
- /* use the more accurate extents */
- if (extents.is_bounded) {
- status = _cairo_path_fixed_stroke_extents (path, stroke_style,
- stroke_ctm, stroke_ctm_inverse,
- stroke_tolerance,
- &extents.mask);
- if (unlikely (status))
- return status;
-
- _cairo_rectangle_intersect (&extents.bounded, &extents.mask);
- }
-
stroke_pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface,
More information about the cairo-commit
mailing list