summaryrefslogtreecommitdiff
path: root/src/cairo-traps-compositor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-traps-compositor.c')
-rw-r--r--[-rwxr-xr-x]src/cairo-traps-compositor.c267
1 files changed, 138 insertions, 129 deletions
diff --git a/src/cairo-traps-compositor.c b/src/cairo-traps-compositor.c
index 5d561f2be..c26a5df6f 100755..100644
--- a/src/cairo-traps-compositor.c
+++ b/src/cairo-traps-compositor.c
@@ -209,18 +209,18 @@ combine_clip_as_traps (const cairo_traps_compositor_t *compositor,
return src->status;
}
- if (draw_color_glyph)
- status = compositor->composite_traps (mask, CAIRO_OPERATOR_IN, mask,
- 0, 0,
- extents->x, extents->y,
- extents,
- antialias, &traps);
- else
+ if (draw_color_glyph)
+ status = compositor->composite_traps (mask, CAIRO_OPERATOR_IN, mask,
+ 0, 0,
+ extents->x, extents->y,
+ extents,
+ antialias, &traps);
+ else
status = compositor->composite_traps (mask, CAIRO_OPERATOR_IN, src,
- src_x, src_y,
- extents->x, extents->y,
- extents,
- antialias, &traps);
+ src_x, src_y,
+ extents->x, extents->y,
+ extents,
+ antialias, &traps);
_cairo_traps_extents (&traps, &box);
_cairo_box_round_to_rectangle (&box, &fixup);
@@ -315,10 +315,11 @@ __clip_to_surface (const cairo_traps_compositor_t *compositor,
if (unlikely (status))
return status;
- mask = _cairo_surface_create_similar_scratch (composite->surface,
- CAIRO_CONTENT_ALPHA,
- extents->width,
- extents->height);
+ mask = _cairo_surface_create_scratch (composite->surface,
+ CAIRO_CONTENT_ALPHA,
+ extents->width,
+ extents->height,
+ NULL);
if (unlikely (mask->status)) {
_cairo_traps_fini (&traps);
return status;
@@ -379,11 +380,11 @@ traps_get_clip_surface (const cairo_traps_compositor_t *compositor,
status = __clip_to_surface (compositor, composite, extents, &surface);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
- surface = _cairo_surface_create_similar_solid (composite->surface,
- CAIRO_CONTENT_ALPHA,
- extents->width,
- extents->height,
- CAIRO_COLOR_WHITE);
+ surface = _cairo_surface_create_scratch (composite->surface,
+ CAIRO_CONTENT_ALPHA,
+ extents->width,
+ extents->height,
+ CAIRO_COLOR_WHITE);
if (unlikely (surface->status))
return surface;
@@ -435,21 +436,22 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
cairo_surface_t *surface, *src;
cairo_int_status_t status;
int src_x, src_y;
- cairo_bool_t draw_color_glyph = FALSE;
+ cairo_bool_t draw_color_glyph = FALSE;
TRACE ((stderr, "%s\n", __FUNCTION__));
- surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_ALPHA,
- extents->bounded.width,
- extents->bounded.height);
+ surface = _cairo_surface_create_scratch (dst, CAIRO_CONTENT_ALPHA,
+ extents->bounded.width,
+ extents->bounded.height,
+ NULL);
if (unlikely (surface->status))
return surface;
- /* FIXME: This is more like an ugly hack and wasteful. Reason
- for this code is that we don't know whether the mask surface
- should alpha-only or argb32 before we render a glyph.
- */
- redo:
+ /* FIXME: This is more like an ugly hack and wasteful. Reason
+ for this code is that we don't know whether the mask surface
+ should alpha-only or argb32 before we render a glyph.
+ */
+redo:
src = compositor->pattern_to_surface (surface,
&_cairo_pattern_white.base,
FALSE,
@@ -503,22 +505,22 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
CAIRO_OPERATOR_ADD, src, src_x, src_y,
extents->bounded.x, extents->bounded.y,
&extents->bounded, NULL);
- if (unlikely (status)){
- if (cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA)
- goto error;
- else {
- compositor->release (surface);
- cairo_surface_destroy (surface);
- cairo_surface_destroy (src);
- surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_COLOR_ALPHA,
- extents->bounded.width,
- extents->bounded.height);
- if (unlikely (surface->status))
- return surface;
- /* we are drawing color glyph */
- draw_color_glyph = TRUE;
- goto redo;
- }
+ if (unlikely (status)) {
+ if (cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA)
+ goto error;
+ else {
+ compositor->release (surface);
+ cairo_surface_destroy (surface);
+ cairo_surface_destroy (src);
+ surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_COLOR_ALPHA,
+ extents->bounded.width,
+ extents->bounded.height);
+ if (unlikely (surface->status))
+ return surface;
+ /* we are drawing color glyph */
+ draw_color_glyph = TRUE;
+ goto redo;
+ }
}
surface->is_clear = FALSE;
@@ -582,30 +584,31 @@ clip_and_composite_with_mask (const cairo_traps_compositor_t *compositor,
if (mask->is_clear)
goto skip;
- if (mask->content == CAIRO_CONTENT_ALPHA) {
- /* This is real mask */
- if (src != NULL || dst->content != CAIRO_CONTENT_ALPHA) {
- compositor->composite (dst, op, src, mask,
- extents->bounded.x + src_x,
- extents->bounded.y + src_y,
- 0, 0,
- extents->bounded.x, extents->bounded.y,
- extents->bounded.width, extents->bounded.height);
- } else {
- compositor->composite (dst, op, mask, NULL,
- 0, 0,
- 0, 0,
- extents->bounded.x, extents->bounded.y,
- extents->bounded.width, extents->bounded.height);
- }
+ if (mask->content == CAIRO_CONTENT_ALPHA) {
+ /* This is real mask */
+ if (src != NULL || dst->content != CAIRO_CONTENT_ALPHA) {
+ compositor->composite (dst, op, src, mask,
+ extents->bounded.x + src_x,
+ extents->bounded.y + src_y,
+ 0, 0,
+ extents->bounded.x, extents->bounded.y,
+ extents->bounded.width, extents->bounded.height);
} else {
- compositor->composite (dst, op, mask, NULL,
- 0, 0,
- extents->bounded.x + src_x,
- extents->bounded.y + src_y,
- extents->bounded.x, extents->bounded.y,
- extents->bounded.width, extents->bounded.height);
+ compositor->composite (dst, op, mask, NULL,
+ 0, 0,
+ 0, 0,
+ extents->bounded.x, extents->bounded.y,
+ extents->bounded.width, extents->bounded.height);
}
+ }
+ else {
+ compositor->composite (dst, op, mask, NULL,
+ 0, 0,
+ extents->bounded.x + src_x,
+ extents->bounded.y + src_y,
+ extents->bounded.x, extents->bounded.y,
+ extents->bounded.width, extents->bounded.height);
+ }
skip:
cairo_surface_destroy (mask);
return CAIRO_STATUS_SUCCESS;
@@ -629,9 +632,10 @@ clip_and_composite_combine (const cairo_traps_compositor_t *compositor,
TRACE ((stderr, "%s\n", __FUNCTION__));
- tmp = _cairo_surface_create_similar_scratch (dst, dst->content,
- extents->bounded.width,
- extents->bounded.height);
+ tmp = _cairo_surface_create_scratch (dst, dst->content,
+ extents->bounded.width,
+ extents->bounded.height,
+ NULL);
if (unlikely (tmp->status)) {
status = tmp->status;
cairo_surface_destroy (tmp);
@@ -701,15 +705,15 @@ clip_and_composite_source (const cairo_traps_compositor_t *compositor,
const cairo_composite_rectangles_t *extents)
{
cairo_surface_t *mask = NULL;
- /* create a white color pattern */
- cairo_pattern_t *white_pattern = _cairo_pattern_create_solid (CAIRO_COLOR_WHITE);
- cairo_surface_t *white_mask =
- compositor->pattern_to_surface (dst, white_pattern, TRUE,
- &extents->bounded,
- &extents->source_sample_area,
- &src_x, &src_y);
- if (unlikely (white_mask->status))
- goto skip;
+ /* create a white color pattern */
+ cairo_pattern_t *white_pattern = _cairo_pattern_create_solid (CAIRO_COLOR_WHITE);
+ cairo_surface_t *white_mask =
+ compositor->pattern_to_surface (dst, white_pattern, TRUE,
+ &extents->bounded,
+ &extents->source_sample_area,
+ &src_x, &src_y);
+ if (unlikely (white_mask->status))
+ goto skip;
TRACE ((stderr, "%s\n", __FUNCTION__));
@@ -731,22 +735,22 @@ clip_and_composite_source (const cairo_traps_compositor_t *compositor,
extents->bounded.width, extents->bounded.height);
} else {
if (mask->content == CAIRO_CONTENT_ALPHA)
- compositor->lerp (dst, src, mask,
- extents->bounded.x + src_x, extents->bounded.y + src_y,
+ compositor->lerp (dst, src, mask,
+ extents->bounded.x + src_x, extents->bounded.y + src_y,
+ 0, 0,
+ extents->bounded.x, extents->bounded.y,
+ extents->bounded.width, extents->bounded.height);
+ else
+ compositor->lerp_color_glyph (dst, mask, white_mask,
0, 0,
+ extents->bounded.x + src_x, extents->bounded.y + src_y,
extents->bounded.x, extents->bounded.y,
extents->bounded.width, extents->bounded.height);
- else
- compositor->lerp_color_glyph (dst, mask, white_mask,
- 0, 0,
- extents->bounded.x + src_x, extents->bounded.y + src_y,
- extents->bounded.x, extents->bounded.y,
- extents->bounded.width, extents->bounded.height);
- }
+ }
skip:
cairo_surface_destroy (mask);
- cairo_surface_destroy (white_mask);
+ cairo_surface_destroy (white_mask);
cairo_pattern_destroy (white_pattern);
return CAIRO_STATUS_SUCCESS;
@@ -988,12 +992,20 @@ need_bounded_clip (cairo_composite_rectangles_t *extents)
{
unsigned int flags = 0;
- if (extents->unbounded.width < extents->destination.width ||
- extents->unbounded.height < extents->destination.height)
+ if (extents->clip->num_boxes > 1 ||
+ extents->mask.width > extents->unbounded.width ||
+ extents->mask.height > extents->unbounded.height)
{
flags |= NEED_CLIP_REGION;
}
+ if (extents->clip->num_boxes > 1 ||
+ extents->mask.width > extents->bounded.width ||
+ extents->mask.height > extents->bounded.height)
+ {
+ flags |= FORCE_CLIP_REGION;
+ }
+
if (! _cairo_clip_is_region (extents->clip))
flags |= NEED_CLIP_SURFACE;
@@ -1258,7 +1270,9 @@ composite_aligned_boxes (const cairo_traps_compositor_t *compositor,
&extents->source_sample_area))
{
cairo_clip_t *recording_clip;
- cairo_pattern_t *source = &extents->source_pattern.base;
+ const cairo_pattern_t *source = &extents->source_pattern.base;
+ const cairo_matrix_t *m;
+ cairo_matrix_t matrix;
/* XXX could also do tiling repeat modes... */
@@ -1277,10 +1291,17 @@ composite_aligned_boxes (const cairo_traps_compositor_t *compositor,
return status;
}
+ m = &source->matrix;
+ if (_cairo_surface_has_device_transform (dst)) {
+ cairo_matrix_multiply (&matrix,
+ &source->matrix,
+ &dst->device_transform);
+ m = &matrix;
+ }
+
recording_clip = _cairo_clip_from_boxes (boxes);
status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (source),
- &source->matrix,
- dst, recording_clip);
+ m, dst, recording_clip);
_cairo_clip_destroy (recording_clip);
return status;
@@ -1433,7 +1454,7 @@ boxes_for_traps (cairo_boxes_t *boxes,
cairo_traps_t *traps,
cairo_antialias_t antialias)
{
- int i;
+ int i, j;
/* first check that the traps are rectilinear */
if (antialias == CAIRO_ANTIALIAS_NONE) {
@@ -1457,23 +1478,25 @@ boxes_for_traps (cairo_boxes_t *boxes,
_cairo_boxes_init (boxes);
- boxes->num_boxes = traps->num_traps;
boxes->chunks.base = (cairo_box_t *) traps->traps;
- boxes->chunks.count = traps->num_traps;
boxes->chunks.size = traps->num_traps;
if (antialias != CAIRO_ANTIALIAS_NONE) {
- for (i = 0; i < traps->num_traps; i++) {
+ for (i = j = 0; i < traps->num_traps; i++) {
/* Note the traps and boxes alias so we need to take the local copies first. */
cairo_fixed_t x1 = traps->traps[i].left.p1.x;
cairo_fixed_t x2 = traps->traps[i].right.p1.x;
cairo_fixed_t y1 = traps->traps[i].top;
cairo_fixed_t y2 = traps->traps[i].bottom;
- boxes->chunks.base[i].p1.x = x1;
- boxes->chunks.base[i].p1.y = y1;
- boxes->chunks.base[i].p2.x = x2;
- boxes->chunks.base[i].p2.y = y2;
+ if (x1 == x2 || y1 == y2)
+ continue;
+
+ boxes->chunks.base[j].p1.x = x1;
+ boxes->chunks.base[j].p1.y = y1;
+ boxes->chunks.base[j].p2.x = x2;
+ boxes->chunks.base[j].p2.y = y2;
+ j++;
if (boxes->is_pixel_aligned) {
boxes->is_pixel_aligned =
@@ -1484,7 +1507,7 @@ boxes_for_traps (cairo_boxes_t *boxes,
} else {
boxes->is_pixel_aligned = TRUE;
- for (i = 0; i < traps->num_traps; i++) {
+ for (i = j = 0; i < traps->num_traps; i++) {
/* Note the traps and boxes alias so we need to take the local copies first. */
cairo_fixed_t x1 = traps->traps[i].left.p1.x;
cairo_fixed_t x2 = traps->traps[i].right.p1.x;
@@ -1492,12 +1515,16 @@ boxes_for_traps (cairo_boxes_t *boxes,
cairo_fixed_t y2 = traps->traps[i].bottom;
/* round down here to match Pixman's behavior when using traps. */
- boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
- boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
- boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
- boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
+ boxes->chunks.base[j].p1.x = _cairo_fixed_round_down (x1);
+ boxes->chunks.base[j].p1.y = _cairo_fixed_round_down (y1);
+ boxes->chunks.base[j].p2.x = _cairo_fixed_round_down (x2);
+ boxes->chunks.base[j].p2.y = _cairo_fixed_round_down (y2);
+ j += (boxes->chunks.base[j].p1.x != boxes->chunks.base[j].p2.x &&
+ boxes->chunks.base[j].p1.y != boxes->chunks.base[j].p2.y);
}
}
+ boxes->chunks.count = j;
+ boxes->num_boxes = j;
return CAIRO_INT_STATUS_SUCCESS;
}
@@ -2220,18 +2247,14 @@ _cairo_traps_compositor_stroke (const cairo_compositor_t *_compositor,
double tolerance,
cairo_traps_t *traps);
composite_traps_info_t info;
- unsigned flags = 0;
+ unsigned flags;
if (antialias == CAIRO_ANTIALIAS_BEST || antialias == CAIRO_ANTIALIAS_GOOD) {
func = _cairo_path_fixed_stroke_polygon_to_traps;
+ flags = 0;
} else {
func = _cairo_path_fixed_stroke_to_traps;
- if (extents->clip->num_boxes > 1 ||
- extents->mask.width > extents->unbounded.width ||
- extents->mask.height > extents->unbounded.height)
- {
- flags = NEED_CLIP_REGION | FORCE_CLIP_REGION;
- }
+ flags = need_bounded_clip (extents) & ~NEED_CLIP_SURFACE;
}
info.antialias = antialias;
@@ -2353,16 +2376,12 @@ _cairo_traps_compositor_glyphs (const cairo_compositor_t *_compositor,
if (unlikely (status))
return status;
-#if ! CAIRO_HAS_TG_SURFACE
_cairo_scaled_font_freeze_cache (scaled_font);
-#endif
-
status = compositor->check_composite_glyphs (extents,
scaled_font, glyphs,
&num_glyphs);
if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
cairo_composite_glyphs_info_t info;
- unsigned flags = 0;
info.font = scaled_font;
info.glyphs = glyphs;
@@ -2370,21 +2389,11 @@ _cairo_traps_compositor_glyphs (const cairo_compositor_t *_compositor,
info.use_mask = overlap || ! extents->is_bounded;
info.extents = extents->bounded;
- if (extents->mask.width > extents->bounded.width ||
- extents->mask.height > extents->bounded.height)
- {
- flags |= FORCE_CLIP_REGION;
- }
-
status = clip_and_composite (compositor, extents,
composite_glyphs, NULL, &info,
- need_bounded_clip (extents) |
- flags);
+ need_bounded_clip (extents) | FORCE_CLIP_REGION);
}
-
-#if ! CAIRO_HAS_TG_SURFACE
_cairo_scaled_font_thaw_cache (scaled_font);
-#endif
return status;
}