static cairo_int_status_t composite_paint (cairo_image_surface_t *dst, void *closure, cairo_operator_t op, const cairo_pattern_t *pattern, int dst_x, int dst_y, const cairo_rectangle_int_t *extents) { cairo_rectangle_int_t sample; pixman_image_t *src; int src_x, src_y; _cairo_pattern_sampled_area (pattern, extents, &sample); src = _pixman_image_for_pattern (dst, pattern, FALSE, extents, &sample, &src_x, &src_y); if (unlikely (src == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); pixman_image_composite32 (_pixman_operator (op), src, NULL, dst->pixman_image, extents->x + src_x, extents->y + src_y, 0, 0, extents->x - dst_x, extents->y - dst_y, extents->width, extents->height); pixman_image_unref (src); return CAIRO_STATUS_SUCCESS; }
static cairo_int_status_t composite_mask (cairo_image_surface_t *dst, void *closure, cairo_operator_t op, const cairo_pattern_t *pattern, int dst_x, int dst_y, const cairo_rectangle_int_t *extents) { cairo_rectangle_int_t sample; pixman_image_t *src, *mask; int src_x, src_y; int mask_x, mask_y; TRACE ((stderr, "%s\n", __FUNCTION__)); _cairo_pattern_sampled_area (pattern, extents, &sample); src = _pixman_image_for_pattern (dst, pattern, FALSE, extents, &sample, &src_x, &src_y); if (unlikely (src == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); _cairo_pattern_sampled_area (closure, extents, &sample); mask = _pixman_image_for_pattern (dst, closure, TRUE, extents, &sample, &mask_x, &mask_y); if (unlikely (mask == NULL)) { pixman_image_unref (src); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } pixman_image_composite32 (_pixman_operator (op), src, mask, dst->pixman_image, extents->x + src_x, extents->y + src_y, extents->x + mask_x, extents->y + mask_y, extents->x - dst_x, extents->y - dst_y, extents->width, extents->height); pixman_image_unref (mask); pixman_image_unref (src); return CAIRO_STATUS_SUCCESS; }
/* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip)) */ static cairo_status_t clip_and_composite_source (const cairo_composite_rectangles_t *extents, draw_func_t draw_func, void *draw_closure) { cairo_image_surface_t *dst = (cairo_image_surface_t *)extents->surface; cairo_image_surface_t *mask; pixman_image_t *src; int src_x, src_y; cairo_status_t status = CAIRO_STATUS_SUCCESS; TRACE ((stderr, "%s\n", __FUNCTION__)); mask = create_composite_mask (dst, draw_closure, draw_func, extents); if (unlikely (mask->base.status)) return mask->base.status; pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE, mask->pixman_image, NULL, dst->pixman_image, 0, 0, 0, 0, extents->bounded.x, extents->bounded.y, extents->bounded.width, extents->bounded.height); src = _pixman_image_for_pattern (dst, &extents->source_pattern.base, FALSE, &extents->bounded, &extents->source_sample_area, &src_x, &src_y); if (unlikely (src == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto error; } pixman_image_composite32 (PIXMAN_OP_ADD, src, mask->pixman_image, dst->pixman_image, extents->bounded.x + src_x, extents->bounded.y + src_y, 0, 0, extents->bounded.x, extents->bounded.y, extents->bounded.width, extents->bounded.height); pixman_image_unref (src); error: cairo_surface_destroy (&mask->base); return status; }
static cairo_int_status_t composite_traps (cairo_image_surface_t *dst, void *closure, cairo_operator_t op, const cairo_pattern_t *pattern, int dst_x, int dst_y, const cairo_rectangle_int_t *extents) { composite_traps_info_t *info = closure; cairo_rectangle_int_t sample; pixman_image_t *src, *mask; int src_x, src_y; TRACE ((stderr, "%s\n", __FUNCTION__)); _cairo_pattern_sampled_area (pattern, extents, &sample); src = _pixman_image_for_pattern (dst, pattern, FALSE, extents, &sample, &src_x, &src_y); if (unlikely (src == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); mask = pixman_image_create_bits (info->antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8, extents->width, extents->height, NULL, 0); if (unlikely (mask == NULL)) { pixman_image_unref (src); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } _pixman_image_add_traps (mask, extents->x, extents->y, &info->traps); pixman_image_composite32 (_pixman_operator (op), src, mask, dst->pixman_image, extents->x + src_x - dst_x, extents->y + src_y - dst_y, 0, 0, extents->x - dst_x, extents->y - dst_y, extents->width, extents->height); pixman_image_unref (mask); pixman_image_unref (src); return CAIRO_STATUS_SUCCESS; }
static cairo_int_status_t composite_glyphs (cairo_image_surface_t *dst, void *closure, cairo_operator_t op, const cairo_pattern_t *pattern, int dst_x, int dst_y, const cairo_rectangle_int_t *extents) { cairo_composite_glyphs_info_t *info = closure; pixman_image_t *mask; cairo_status_t status; int i; mask = pixman_image_create_bits (PIXMAN_a8, extents->width, extents->height, NULL, 0); if (unlikely (mask == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); status = CAIRO_STATUS_SUCCESS; _cairo_scaled_font_freeze_cache (info->font); for (i = 0; i < info->num_glyphs; i++) { cairo_image_surface_t *glyph_surface; cairo_scaled_glyph_t *scaled_glyph; unsigned long glyph_index = info->glyphs[i].index; int x, y; status = _cairo_scaled_glyph_lookup (info->font, glyph_index, CAIRO_SCALED_GLYPH_INFO_SURFACE, &scaled_glyph); if (unlikely (status)) break; glyph_surface = scaled_glyph->surface; if (glyph_surface->width && glyph_surface->height) { /* round glyph locations to the nearest pixel */ /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */ x = _cairo_lround (info->glyphs[i].x - glyph_surface->base.device_transform.x0); y = _cairo_lround (info->glyphs[i].y - glyph_surface->base.device_transform.y0); pixman_image_composite32 (PIXMAN_OP_ADD, glyph_surface->pixman_image, NULL, mask, 0, 0, 0, 0, x - extents->x, y - extents->y, glyph_surface->width, glyph_surface->height); } } _cairo_scaled_font_thaw_cache (info->font); if (status == CAIRO_STATUS_SUCCESS) { cairo_rectangle_int_t sample; pixman_image_t *src; int src_x, src_y; _cairo_pattern_sampled_area (pattern, extents, &sample); src = _pixman_image_for_pattern (dst, pattern, FALSE, extents, &sample, &src_x, &src_y); if (src != NULL) { dst_x = extents->x - dst_x; dst_y = extents->y - dst_y; pixman_image_composite32 (_pixman_operator (op), src, mask, dst->pixman_image, src_x + dst_x, src_y + dst_y, 0, 0, dst_x, dst_y, extents->width, extents->height); pixman_image_unref (src); } else status = _cairo_error (CAIRO_STATUS_NO_MEMORY); } pixman_image_unref (mask); return status; }