diff options
Diffstat (limited to 'src/cairo-traps-compositor.c')
-rw-r--r--[-rwxr-xr-x] | src/cairo-traps-compositor.c | 267 |
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; } |