1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2002 University of Southern California
5 * Copyright © 2005 Red Hat, Inc.
6 * Copyright © 2011 Intel Corporation
8 * This library is free software; you can redistribute it and/or
9 * modify it either under the terms of the GNU Lesser General Public
10 * License version 2.1 as published by the Free Software Foundation
11 * (the "LGPL") or, at your option, under the terms of the Mozilla
12 * Public License Version 1.1 (the "MPL"). If you do not alter this
13 * notice, a recipient may use your version of this file under either
14 * the MPL or the LGPL.
16 * You should have received a copy of the LGPL along with this library
17 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19 * You should have received a copy of the MPL along with this library
20 * in the file COPYING-MPL-1.1
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License at
25 * http://www.mozilla.org/MPL/
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29 * the specific language governing rights and limitations.
31 * The Original Code is the cairo graphics library.
33 * The Initial Developer of the Original Code is University of Southern
37 * Carl D. Worth <cworth@cworth.org>
38 * Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
39 * Chris Wilson <chris@chris-wilson.co.uk>
44 #include "test-compositor-surface-private.h"
46 #include "cairo-clip-private.h"
47 #include "cairo-composite-rectangles-private.h"
48 #include "cairo-compositor-private.h"
49 #include "cairo-error-private.h"
50 #include "cairo-image-surface-private.h"
51 #include "cairo-region-private.h"
52 #include "cairo-traps-private.h"
54 /* The intention is that this is a surface that just works, and most
55 * important of all does not try to be clever!
58 typedef cairo_int_status_t
59 (*draw_func_t) (cairo_image_surface_t *dst,
62 const cairo_pattern_t *pattern,
65 const cairo_rectangle_int_t *extents);
68 _pixman_operator (cairo_operator_t op)
71 case CAIRO_OPERATOR_CLEAR:
72 return PIXMAN_OP_CLEAR;
74 case CAIRO_OPERATOR_SOURCE:
76 case CAIRO_OPERATOR_OVER:
77 return PIXMAN_OP_OVER;
78 case CAIRO_OPERATOR_IN:
80 case CAIRO_OPERATOR_OUT:
82 case CAIRO_OPERATOR_ATOP:
83 return PIXMAN_OP_ATOP;
85 case CAIRO_OPERATOR_DEST:
87 case CAIRO_OPERATOR_DEST_OVER:
88 return PIXMAN_OP_OVER_REVERSE;
89 case CAIRO_OPERATOR_DEST_IN:
90 return PIXMAN_OP_IN_REVERSE;
91 case CAIRO_OPERATOR_DEST_OUT:
92 return PIXMAN_OP_OUT_REVERSE;
93 case CAIRO_OPERATOR_DEST_ATOP:
94 return PIXMAN_OP_ATOP_REVERSE;
96 case CAIRO_OPERATOR_XOR:
98 case CAIRO_OPERATOR_ADD:
100 case CAIRO_OPERATOR_SATURATE:
101 return PIXMAN_OP_SATURATE;
103 case CAIRO_OPERATOR_MULTIPLY:
104 return PIXMAN_OP_MULTIPLY;
105 case CAIRO_OPERATOR_SCREEN:
106 return PIXMAN_OP_SCREEN;
107 case CAIRO_OPERATOR_OVERLAY:
108 return PIXMAN_OP_OVERLAY;
109 case CAIRO_OPERATOR_DARKEN:
110 return PIXMAN_OP_DARKEN;
111 case CAIRO_OPERATOR_LIGHTEN:
112 return PIXMAN_OP_LIGHTEN;
113 case CAIRO_OPERATOR_COLOR_DODGE:
114 return PIXMAN_OP_COLOR_DODGE;
115 case CAIRO_OPERATOR_COLOR_BURN:
116 return PIXMAN_OP_COLOR_BURN;
117 case CAIRO_OPERATOR_HARD_LIGHT:
118 return PIXMAN_OP_HARD_LIGHT;
119 case CAIRO_OPERATOR_SOFT_LIGHT:
120 return PIXMAN_OP_SOFT_LIGHT;
121 case CAIRO_OPERATOR_DIFFERENCE:
122 return PIXMAN_OP_DIFFERENCE;
123 case CAIRO_OPERATOR_EXCLUSION:
124 return PIXMAN_OP_EXCLUSION;
125 case CAIRO_OPERATOR_HSL_HUE:
126 return PIXMAN_OP_HSL_HUE;
127 case CAIRO_OPERATOR_HSL_SATURATION:
128 return PIXMAN_OP_HSL_SATURATION;
129 case CAIRO_OPERATOR_HSL_COLOR:
130 return PIXMAN_OP_HSL_COLOR;
131 case CAIRO_OPERATOR_HSL_LUMINOSITY:
132 return PIXMAN_OP_HSL_LUMINOSITY;
136 return PIXMAN_OP_OVER;
140 static cairo_image_surface_t *
141 create_composite_mask (cairo_image_surface_t *dst,
143 draw_func_t draw_func,
144 const cairo_composite_rectangles_t *extents)
146 cairo_image_surface_t *surface;
147 cairo_int_status_t status;
149 TRACE ((stderr, "%s\n", __FUNCTION__));
151 surface = (cairo_image_surface_t *)
152 _cairo_image_surface_create_with_pixman_format (NULL, PIXMAN_a8,
153 extents->bounded.width,
154 extents->bounded.height,
156 if (unlikely (surface->base.status))
159 status = draw_func (surface, draw_closure,
160 CAIRO_OPERATOR_ADD, &_cairo_pattern_white.base,
161 extents->bounded.x, extents->bounded.y,
163 if (unlikely (status))
166 status = _cairo_clip_combine_with_surface (extents->clip,
170 if (unlikely (status))
176 cairo_surface_destroy (&surface->base);
177 return (cairo_image_surface_t *)_cairo_surface_create_in_error (status);
180 /* Handles compositing with a clip surface when the operator allows
181 * us to combine the clip with the mask
183 static cairo_status_t
184 clip_and_composite_with_mask (const cairo_composite_rectangles_t*extents,
185 draw_func_t draw_func,
188 cairo_image_surface_t *dst = (cairo_image_surface_t *)extents->surface;
189 cairo_image_surface_t *mask;
191 cairo_status_t status = CAIRO_STATUS_SUCCESS;
194 TRACE ((stderr, "%s\n", __FUNCTION__));
196 mask = create_composite_mask (dst, draw_closure, draw_func, extents);
197 if (unlikely (mask->base.status))
198 return mask->base.status;
200 src = _pixman_image_for_pattern (dst,
201 &extents->source_pattern.base, FALSE,
203 &extents->source_sample_area,
205 if (unlikely (src == NULL)) {
206 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
210 pixman_image_composite32 (_pixman_operator (extents->op),
211 src, mask->pixman_image, dst->pixman_image,
212 extents->bounded.x + src_x,
213 extents->bounded.y + src_y,
215 extents->bounded.x, extents->bounded.y,
216 extents->bounded.width, extents->bounded.height);
218 pixman_image_unref (src);
220 cairo_surface_destroy (&mask->base);
224 /* Handles compositing with a clip surface when we have to do the operation
225 * in two pieces and combine them together.
227 static cairo_status_t
228 clip_and_composite_combine (const cairo_composite_rectangles_t*extents,
229 draw_func_t draw_func,
232 cairo_image_surface_t *dst = (cairo_image_surface_t *)extents->surface;
233 cairo_image_surface_t *tmp, *clip;
235 cairo_status_t status;
237 TRACE ((stderr, "%s\n", __FUNCTION__));
239 tmp = (cairo_image_surface_t *)
240 _cairo_image_surface_create_with_pixman_format (NULL,
242 extents->bounded.width,
243 extents->bounded.height,
245 if (unlikely (tmp->base.status))
246 return tmp->base.status;
248 pixman_image_composite32 (PIXMAN_OP_SRC,
249 dst->pixman_image, NULL, tmp->pixman_image,
250 extents->bounded.x, extents->bounded.y,
253 extents->bounded.width, extents->bounded.height);
255 status = draw_func (tmp, draw_closure,
256 extents->op, &extents->source_pattern.base,
257 extents->bounded.x, extents->bounded.y,
259 if (unlikely (status))
262 clip = (cairo_image_surface_t *)
263 _cairo_clip_get_surface (extents->clip, &dst->base, &clip_x, &clip_y);
264 if (unlikely (clip->base.status))
267 pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
268 clip->pixman_image, NULL, dst->pixman_image,
269 extents->bounded.x - clip_x, extents->bounded.y - clip_y,
271 extents->bounded.x, extents->bounded.y,
272 extents->bounded.width, extents->bounded.height);
273 pixman_image_composite32 (PIXMAN_OP_ADD,
274 tmp->pixman_image, clip->pixman_image, dst->pixman_image,
276 extents->bounded.x - clip_x, extents->bounded.y - clip_y,
277 extents->bounded.x, extents->bounded.y,
278 extents->bounded.width, extents->bounded.height);
280 cairo_surface_destroy (&clip->base);
283 cairo_surface_destroy (&tmp->base);
288 /* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
289 * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
291 static cairo_status_t
292 clip_and_composite_source (const cairo_composite_rectangles_t *extents,
293 draw_func_t draw_func,
296 cairo_image_surface_t *dst = (cairo_image_surface_t *)extents->surface;
297 cairo_image_surface_t *mask;
300 cairo_status_t status = CAIRO_STATUS_SUCCESS;
302 TRACE ((stderr, "%s\n", __FUNCTION__));
304 mask = create_composite_mask (dst, draw_closure, draw_func, extents);
305 if (unlikely (mask->base.status))
306 return mask->base.status;
308 pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
309 mask->pixman_image, NULL, dst->pixman_image,
312 extents->bounded.x, extents->bounded.y,
313 extents->bounded.width, extents->bounded.height);
315 src = _pixman_image_for_pattern (dst,
316 &extents->source_pattern.base, FALSE,
318 &extents->source_sample_area,
320 if (unlikely (src == NULL)) {
321 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
325 pixman_image_composite32 (PIXMAN_OP_ADD,
326 src, mask->pixman_image, dst->pixman_image,
327 extents->bounded.x + src_x, extents->bounded.y + src_y,
329 extents->bounded.x, extents->bounded.y,
330 extents->bounded.width, extents->bounded.height);
332 pixman_image_unref (src);
335 cairo_surface_destroy (&mask->base);
339 static cairo_status_t
340 fixup_unbounded (const cairo_composite_rectangles_t *extents)
342 cairo_image_surface_t *dst = (cairo_image_surface_t *)extents->surface;
343 pixman_image_t *mask;
346 TRACE ((stderr, "%s\n", __FUNCTION__));
348 if (! _cairo_clip_is_region (extents->clip)) {
349 cairo_image_surface_t *clip;
351 clip = (cairo_image_surface_t *)
352 _cairo_clip_get_surface (extents->clip, &dst->base,
354 if (unlikely (clip->base.status))
355 return clip->base.status;
357 mask = pixman_image_ref (clip->pixman_image);
358 cairo_surface_destroy (&clip->base);
361 mask = _pixman_image_for_color (CAIRO_COLOR_WHITE);
362 if (unlikely (mask == NULL))
363 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
367 if (extents->bounded.y != extents->unbounded.y) {
368 int x = extents->unbounded.x;
369 int y = extents->unbounded.y;
370 int width = extents->unbounded.width;
371 int height = extents->bounded.y - y;
373 pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
374 mask, NULL, dst->pixman_image,
375 x - mask_x, y - mask_y,
382 if (extents->bounded.x != extents->unbounded.x) {
383 int x = extents->unbounded.x;
384 int y = extents->bounded.y;
385 int width = extents->bounded.x - x;
386 int height = extents->bounded.height;
388 pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
389 mask, NULL, dst->pixman_image,
390 x - mask_x, y - mask_y,
397 if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
398 int x = extents->bounded.x + extents->bounded.width;
399 int y = extents->bounded.y;
400 int width = extents->unbounded.x + extents->unbounded.width - x;
401 int height = extents->bounded.height;
403 pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
404 mask, NULL, dst->pixman_image,
405 x - mask_x, y - mask_y,
412 if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
413 int x = extents->unbounded.x;
414 int y = extents->bounded.y + extents->bounded.height;
415 int width = extents->unbounded.width;
416 int height = extents->unbounded.y + extents->unbounded.height - y;
418 pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
419 mask, NULL, dst->pixman_image,
420 x - mask_x, y - mask_y,
426 pixman_image_unref (mask);
428 return CAIRO_STATUS_SUCCESS;
431 static cairo_int_status_t
432 set_clip_region (cairo_composite_rectangles_t *extents)
434 cairo_image_surface_t *dst = (cairo_image_surface_t *) extents->surface;
435 cairo_region_t *region = _cairo_clip_get_region (extents->clip);
436 pixman_region32_t *rgn = region ? ®ion->rgn : NULL;
437 if (! pixman_image_set_clip_region32 (dst->pixman_image, rgn))
438 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
440 return CAIRO_STATUS_SUCCESS;
443 static cairo_status_t
444 clip_and_composite (cairo_composite_rectangles_t *extents,
445 draw_func_t draw_func,
448 cairo_status_t status;
450 status = set_clip_region (extents);
451 if (unlikely (status))
454 if (extents->op == CAIRO_OPERATOR_SOURCE) {
455 status = clip_and_composite_source (extents, draw_func, draw_closure);
457 if (extents->op == CAIRO_OPERATOR_CLEAR) {
458 extents->source_pattern.solid = _cairo_pattern_white;
459 extents->op = CAIRO_OPERATOR_DEST_OUT;
461 if (! _cairo_clip_is_region (extents->clip)) {
462 if (extents->is_bounded)
463 status = clip_and_composite_with_mask (extents, draw_func, draw_closure);
465 status = clip_and_composite_combine (extents, draw_func, draw_closure);
467 status = draw_func ((cairo_image_surface_t *) extents->surface,
470 &extents->source_pattern.base,
476 if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded)
477 status = fixup_unbounded (extents);
482 /* high-level compositor interface */
484 static cairo_int_status_t
485 composite_paint (cairo_image_surface_t *dst,
488 const cairo_pattern_t *pattern,
491 const cairo_rectangle_int_t *extents)
493 cairo_rectangle_int_t sample;
497 TRACE ((stderr, "%s\n", __FUNCTION__));
499 _cairo_pattern_sampled_area (pattern, extents, &sample);
500 src = _pixman_image_for_pattern (dst,
504 if (unlikely (src == NULL))
505 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
507 TRACE ((stderr, "%s: src=(%d, %d), dst=(%d, %d) size=%dx%d\n", __FUNCTION__,
508 extents->x + src_x, extents->y + src_y,
509 extents->x - dst_x, extents->y - dst_y,
510 extents->width, extents->height));
512 pixman_image_composite32 (_pixman_operator (op),
513 src, NULL, dst->pixman_image,
514 extents->x + src_x, extents->y + src_y,
516 extents->x - dst_x, extents->y - dst_y,
517 extents->width, extents->height);
519 pixman_image_unref (src);
521 return CAIRO_STATUS_SUCCESS;
524 static cairo_int_status_t
525 base_compositor_paint (const cairo_compositor_t *_compositor,
526 cairo_composite_rectangles_t *extents)
528 TRACE ((stderr, "%s\n", __FUNCTION__));
529 return clip_and_composite (extents, composite_paint, NULL);
532 static cairo_int_status_t
533 composite_mask (cairo_image_surface_t *dst,
536 const cairo_pattern_t *pattern,
539 const cairo_rectangle_int_t *extents)
541 cairo_rectangle_int_t sample;
542 pixman_image_t *src, *mask;
546 TRACE ((stderr, "%s\n", __FUNCTION__));
548 _cairo_pattern_sampled_area (pattern, extents, &sample);
549 src = _pixman_image_for_pattern (dst, pattern, FALSE,
552 if (unlikely (src == NULL))
553 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
555 _cairo_pattern_sampled_area (closure, extents, &sample);
556 mask = _pixman_image_for_pattern (dst, closure, TRUE,
559 if (unlikely (mask == NULL)) {
560 pixman_image_unref (src);
561 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
564 pixman_image_composite32 (_pixman_operator (op),
565 src, mask, dst->pixman_image,
566 extents->x + src_x, extents->y + src_y,
567 extents->x + mask_x, extents->y + mask_y,
568 extents->x - dst_x, extents->y - dst_y,
569 extents->width, extents->height);
571 pixman_image_unref (mask);
572 pixman_image_unref (src);
574 return CAIRO_STATUS_SUCCESS;
577 static cairo_int_status_t
578 base_compositor_mask (const cairo_compositor_t *_compositor,
579 cairo_composite_rectangles_t *extents)
581 TRACE ((stderr, "%s\n", __FUNCTION__));
582 return clip_and_composite (extents, composite_mask, &extents->mask_pattern.base);
587 cairo_antialias_t antialias;
588 } composite_traps_info_t;
590 static cairo_int_status_t
591 composite_traps (cairo_image_surface_t *dst,
594 const cairo_pattern_t *pattern,
597 const cairo_rectangle_int_t *extents)
599 composite_traps_info_t *info = closure;
600 cairo_rectangle_int_t sample;
601 pixman_image_t *src, *mask;
604 TRACE ((stderr, "%s\n", __FUNCTION__));
606 _cairo_pattern_sampled_area (pattern, extents, &sample);
607 src = _pixman_image_for_pattern (dst, pattern, FALSE,
610 if (unlikely (src == NULL))
611 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
613 mask = pixman_image_create_bits (info->antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8,
614 extents->width, extents->height,
616 if (unlikely (mask == NULL)) {
617 pixman_image_unref (src);
618 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
621 _pixman_image_add_traps (mask, extents->x, extents->y, &info->traps);
622 pixman_image_composite32 (_pixman_operator (op),
623 src, mask, dst->pixman_image,
624 extents->x + src_x - dst_x, extents->y + src_y - dst_y,
626 extents->x - dst_x, extents->y - dst_y,
627 extents->width, extents->height);
629 pixman_image_unref (mask);
630 pixman_image_unref (src);
632 return CAIRO_STATUS_SUCCESS;
635 static cairo_int_status_t
636 trim_extents_to_traps (cairo_composite_rectangles_t *extents,
637 cairo_traps_t *traps)
641 /* X trims the affected area to the extents of the trapezoids, so
642 * we need to compensate when fixing up the unbounded area.
644 _cairo_traps_extents (traps, &box);
645 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
648 static cairo_int_status_t
649 base_compositor_stroke (const cairo_compositor_t *_compositor,
650 cairo_composite_rectangles_t *extents,
651 const cairo_path_fixed_t *path,
652 const cairo_stroke_style_t *style,
653 const cairo_matrix_t *ctm,
654 const cairo_matrix_t *ctm_inverse,
656 cairo_antialias_t antialias)
658 composite_traps_info_t info;
659 cairo_int_status_t status;
661 TRACE ((stderr, "%s\n", __FUNCTION__));
663 info.antialias = antialias;
664 _cairo_traps_init_with_clip (&info.traps, extents->clip);
665 status = _cairo_path_fixed_stroke_to_traps (path, style,
669 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
670 status = trim_extents_to_traps (extents, &info.traps);
671 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
672 status = clip_and_composite (extents, composite_traps, &info);
673 _cairo_traps_fini (&info.traps);
678 static cairo_int_status_t
679 base_compositor_fill (const cairo_compositor_t *_compositor,
680 cairo_composite_rectangles_t *extents,
681 const cairo_path_fixed_t *path,
682 cairo_fill_rule_t fill_rule,
684 cairo_antialias_t antialias)
686 composite_traps_info_t info;
687 cairo_int_status_t status;
689 TRACE ((stderr, "%s\n", __FUNCTION__));
691 info.antialias = antialias;
692 _cairo_traps_init_with_clip (&info.traps, extents->clip);
693 status = _cairo_path_fixed_fill_to_traps (path,
694 fill_rule, tolerance,
696 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
697 status = trim_extents_to_traps (extents, &info.traps);
698 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
699 status = clip_and_composite (extents, composite_traps, &info);
700 _cairo_traps_fini (&info.traps);
705 static cairo_int_status_t
706 composite_glyphs (cairo_image_surface_t *dst,
709 const cairo_pattern_t *pattern,
712 const cairo_rectangle_int_t *extents)
714 cairo_composite_glyphs_info_t *info = closure;
715 pixman_image_t *mask;
716 cairo_status_t status;
719 TRACE ((stderr, "%s\n", __FUNCTION__));
721 mask = pixman_image_create_bits (PIXMAN_a8,
722 extents->width, extents->height,
724 if (unlikely (mask == NULL))
725 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
727 status = CAIRO_STATUS_SUCCESS;
728 _cairo_scaled_font_freeze_cache (info->font);
729 for (i = 0; i < info->num_glyphs; i++) {
730 cairo_image_surface_t *glyph_surface;
731 cairo_scaled_glyph_t *scaled_glyph;
732 unsigned long glyph_index = info->glyphs[i].index;
735 status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
736 CAIRO_SCALED_GLYPH_INFO_SURFACE,
739 if (unlikely (status))
742 glyph_surface = scaled_glyph->surface;
743 if (glyph_surface->width && glyph_surface->height) {
744 /* round glyph locations to the nearest pixel */
745 /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
746 x = _cairo_lround (info->glyphs[i].x -
747 glyph_surface->base.device_transform.x0);
748 y = _cairo_lround (info->glyphs[i].y -
749 glyph_surface->base.device_transform.y0);
751 pixman_image_composite32 (PIXMAN_OP_ADD,
752 glyph_surface->pixman_image, NULL, mask,
755 x - extents->x, y - extents->y,
756 glyph_surface->width,
757 glyph_surface->height);
760 _cairo_scaled_font_thaw_cache (info->font);
762 if (status == CAIRO_STATUS_SUCCESS) {
763 cairo_rectangle_int_t sample;
767 _cairo_pattern_sampled_area (pattern, extents, &sample);
768 src = _pixman_image_for_pattern (dst, pattern, FALSE,
772 dst_x = extents->x - dst_x;
773 dst_y = extents->y - dst_y;
774 pixman_image_composite32 (_pixman_operator (op),
775 src, mask, dst->pixman_image,
776 src_x + dst_x, src_y + dst_y,
779 extents->width, extents->height);
780 pixman_image_unref (src);
782 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
784 pixman_image_unref (mask);
789 static cairo_int_status_t
790 base_compositor_glyphs (const cairo_compositor_t *_compositor,
791 cairo_composite_rectangles_t *extents,
792 cairo_scaled_font_t *scaled_font,
793 cairo_glyph_t *glyphs,
795 cairo_bool_t overlap)
797 cairo_composite_glyphs_info_t info;
799 info.font = scaled_font;
800 info.glyphs = glyphs;
801 info.num_glyphs = num_glyphs;
803 TRACE ((stderr, "%s\n", __FUNCTION__));
804 return clip_and_composite (extents, composite_glyphs, &info);
807 static const cairo_compositor_t base_compositor = {
808 &__cairo_no_compositor,
810 base_compositor_paint,
811 base_compositor_mask,
812 base_compositor_stroke,
813 base_compositor_fill,
814 base_compositor_glyphs,
818 _cairo_test_base_compositor_surface_create (cairo_content_t content,
822 return test_compositor_surface_create (&base_compositor,
823 content, width, height);