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 © 2003 University of Southern California
5 * Copyright © 2009,2010,2011 Intel Corporation
7 * This library is free software; you can redistribute it and/or
8 * modify it either under the terms of the GNU Lesser General Public
9 * License version 2.1 as published by the Free Software Foundation
10 * (the "LGPL") or, at your option, under the terms of the Mozilla
11 * Public License Version 1.1 (the "MPL"). If you do not alter this
12 * notice, a recipient may use your version of this file under either
13 * the MPL or the LGPL.
15 * You should have received a copy of the LGPL along with this library
16 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
21 * The contents of this file are subject to the Mozilla Public License
22 * Version 1.1 (the "License"); you may not use this file except in
23 * compliance with the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
26 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28 * the specific language governing rights and limitations.
30 * The Original Code is the cairo graphics library.
32 * The Initial Developer of the Original Code is University of Southern
36 * Carl D. Worth <cworth@cworth.org>
37 * Chris Wilson <chris@chris-wilson.co.uk>
40 /* This compositor is slightly pointless. Just exists for testing
41 * and as skeleton code.
46 #include "cairo-image-surface-private.h"
48 #include "cairo-compositor-private.h"
49 #include "cairo-region-private.h"
51 static cairo_int_status_t
52 acquire (void *abstract_dst)
54 return CAIRO_STATUS_SUCCESS;
57 static cairo_int_status_t
58 release (void *abstract_dst)
60 return CAIRO_STATUS_SUCCESS;
63 static cairo_int_status_t
64 set_clip_region (void *_surface,
65 cairo_region_t *region)
67 cairo_image_surface_t *surface = _surface;
68 pixman_region32_t *rgn = region ? ®ion->rgn : NULL;
70 if (! pixman_image_set_clip_region32 (surface->pixman_image, rgn))
71 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
73 return CAIRO_STATUS_SUCCESS;
77 has_snapshot (void *_dst,
78 const cairo_pattern_t *pattern)
83 static cairo_int_status_t
84 draw_image (void *_dst,
85 cairo_image_surface_t *image,
87 int width, int height,
90 cairo_image_surface_t *dst = (cairo_image_surface_t *)_dst;
92 pixman_image_composite32 (PIXMAN_OP_SRC,
93 image->pixman_image, NULL, dst->pixman_image,
98 return CAIRO_STATUS_SUCCESS;
101 static inline uint32_t
102 color_to_uint32 (const cairo_color_t *color)
105 (color->alpha_short >> 8 << 24) |
106 (color->red_short >> 8 << 16) |
107 (color->green_short & 0xff00) |
108 (color->blue_short >> 8);
111 static inline cairo_bool_t
112 color_to_pixel (const cairo_color_t *color,
114 pixman_format_code_t format,
117 cairo_color_t opacity_color;
120 if (!(format == PIXMAN_a8r8g8b8 ||
121 format == PIXMAN_x8r8g8b8 ||
122 format == PIXMAN_a8b8g8r8 ||
123 format == PIXMAN_x8b8g8r8 ||
124 format == PIXMAN_b8g8r8a8 ||
125 format == PIXMAN_b8g8r8x8 ||
126 format == PIXMAN_r5g6b5 ||
127 format == PIXMAN_b5g6r5 ||
128 format == PIXMAN_a8))
133 if (opacity != 1.0) {
134 _cairo_color_init_rgba (&opacity_color,
138 color->alpha * opacity);
139 color = &opacity_color;
141 c = color_to_uint32 (color);
143 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) {
144 c = ((c & 0xff000000) >> 0) |
145 ((c & 0x00ff0000) >> 16) |
146 ((c & 0x0000ff00) >> 0) |
147 ((c & 0x000000ff) << 16);
150 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA) {
151 c = ((c & 0xff000000) >> 24) |
152 ((c & 0x00ff0000) >> 8) |
153 ((c & 0x0000ff00) << 8) |
154 ((c & 0x000000ff) << 24);
157 if (format == PIXMAN_a8) {
159 } else if (format == PIXMAN_r5g6b5 || format == PIXMAN_b5g6r5) {
160 c = ((((c) >> 3) & 0x001f) |
161 (((c) >> 5) & 0x07e0) |
162 (((c) >> 8) & 0xf800));
169 static cairo_int_status_t
170 fill_rectangles (void *_dst,
172 const cairo_color_t *color,
173 cairo_rectangle_int_t *rects,
176 cairo_image_surface_t *dst = _dst;
180 if (! color_to_pixel (color, 1.0, dst->pixman_format, &pixel))
181 return CAIRO_INT_STATUS_UNSUPPORTED;
183 for (i = 0; i < num_rects; i++) {
184 pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
185 PIXMAN_FORMAT_BPP (dst->pixman_format),
186 rects[i].x, rects[i].y,
187 rects[i].width, rects[i].height,
191 return CAIRO_STATUS_SUCCESS;
194 static cairo_int_status_t
195 fill_boxes (void *_dst,
197 const cairo_color_t *color,
198 cairo_boxes_t *boxes)
200 cairo_image_surface_t *dst = _dst;
201 struct _cairo_boxes_chunk *chunk;
205 assert (boxes->is_pixel_aligned);
207 if (! color_to_pixel (color, 1.0, dst->pixman_format, &pixel))
208 return CAIRO_INT_STATUS_UNSUPPORTED;
210 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
211 for (i = 0; i < chunk->count; i++) {
212 int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
213 int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
214 int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
215 int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
216 pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
217 PIXMAN_FORMAT_BPP (dst->pixman_format),
218 x1, y1, x2 - x1, y2 - y1,
223 return CAIRO_STATUS_SUCCESS;
227 _pixman_operator (cairo_operator_t op)
230 case CAIRO_OPERATOR_CLEAR:
231 return PIXMAN_OP_CLEAR;
233 case CAIRO_OPERATOR_SOURCE:
234 return PIXMAN_OP_SRC;
235 case CAIRO_OPERATOR_OVER:
236 return PIXMAN_OP_OVER;
237 case CAIRO_OPERATOR_IN:
239 case CAIRO_OPERATOR_OUT:
240 return PIXMAN_OP_OUT;
241 case CAIRO_OPERATOR_ATOP:
242 return PIXMAN_OP_ATOP;
244 case CAIRO_OPERATOR_DEST:
245 return PIXMAN_OP_DST;
246 case CAIRO_OPERATOR_DEST_OVER:
247 return PIXMAN_OP_OVER_REVERSE;
248 case CAIRO_OPERATOR_DEST_IN:
249 return PIXMAN_OP_IN_REVERSE;
250 case CAIRO_OPERATOR_DEST_OUT:
251 return PIXMAN_OP_OUT_REVERSE;
252 case CAIRO_OPERATOR_DEST_ATOP:
253 return PIXMAN_OP_ATOP_REVERSE;
255 case CAIRO_OPERATOR_XOR:
256 return PIXMAN_OP_XOR;
257 case CAIRO_OPERATOR_ADD:
258 return PIXMAN_OP_ADD;
259 case CAIRO_OPERATOR_SATURATE:
260 return PIXMAN_OP_SATURATE;
262 case CAIRO_OPERATOR_MULTIPLY:
263 return PIXMAN_OP_MULTIPLY;
264 case CAIRO_OPERATOR_SCREEN:
265 return PIXMAN_OP_SCREEN;
266 case CAIRO_OPERATOR_OVERLAY:
267 return PIXMAN_OP_OVERLAY;
268 case CAIRO_OPERATOR_DARKEN:
269 return PIXMAN_OP_DARKEN;
270 case CAIRO_OPERATOR_LIGHTEN:
271 return PIXMAN_OP_LIGHTEN;
272 case CAIRO_OPERATOR_COLOR_DODGE:
273 return PIXMAN_OP_COLOR_DODGE;
274 case CAIRO_OPERATOR_COLOR_BURN:
275 return PIXMAN_OP_COLOR_BURN;
276 case CAIRO_OPERATOR_HARD_LIGHT:
277 return PIXMAN_OP_HARD_LIGHT;
278 case CAIRO_OPERATOR_SOFT_LIGHT:
279 return PIXMAN_OP_SOFT_LIGHT;
280 case CAIRO_OPERATOR_DIFFERENCE:
281 return PIXMAN_OP_DIFFERENCE;
282 case CAIRO_OPERATOR_EXCLUSION:
283 return PIXMAN_OP_EXCLUSION;
284 case CAIRO_OPERATOR_HSL_HUE:
285 return PIXMAN_OP_HSL_HUE;
286 case CAIRO_OPERATOR_HSL_SATURATION:
287 return PIXMAN_OP_HSL_SATURATION;
288 case CAIRO_OPERATOR_HSL_COLOR:
289 return PIXMAN_OP_HSL_COLOR;
290 case CAIRO_OPERATOR_HSL_LUMINOSITY:
291 return PIXMAN_OP_HSL_LUMINOSITY;
295 return PIXMAN_OP_OVER;
299 static cairo_int_status_t
300 composite (void *_dst,
302 cairo_surface_t *abstract_src,
303 cairo_surface_t *abstract_mask,
313 cairo_image_surface_t *dst = _dst;
314 cairo_pixman_source_t *src = (cairo_pixman_source_t *)abstract_src;
315 cairo_pixman_source_t *mask = (cairo_pixman_source_t *)abstract_mask;
317 pixman_image_composite32 (_pixman_operator (op),
318 src->pixman_image, mask->pixman_image, dst->pixman_image,
324 pixman_image_composite32 (_pixman_operator (op),
325 src->pixman_image, NULL, dst->pixman_image,
332 return CAIRO_STATUS_SUCCESS;
335 static cairo_int_status_t
336 composite_boxes (void *_dst,
338 cairo_surface_t *abstract_src,
339 cairo_surface_t *abstract_mask,
346 cairo_boxes_t *boxes)
348 cairo_image_surface_t *dst = _dst;
349 cairo_pixman_source_t *src = (cairo_pixman_source_t *)abstract_src;
350 cairo_pixman_source_t *mask = (cairo_pixman_source_t *)abstract_mask;
351 struct _cairo_boxes_chunk *chunk;
354 assert (boxes->is_pixel_aligned);
356 op = _pixman_operator (op);
357 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
358 for (i = 0; i < chunk->count; i++) {
359 int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
360 int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
361 int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
362 int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
365 pixman_image_composite32 (op,
366 src->pixman_image, mask->pixman_image, dst->pixman_image,
367 x1 + src_x, y1 + src_y,
368 x1 + mask_x, y1 + mask_y,
369 x1 + dst_x, y1 + dst_y,
372 pixman_image_composite32 (op,
373 src->pixman_image, NULL, dst->pixman_image,
374 x1 + src_x, y1 + src_y,
376 x1 + dst_x, y1 + dst_y,
382 return CAIRO_STATUS_SUCCESS;
385 const cairo_compositor_t *
386 _cairo_image_mask_compositor_get (void)
388 static cairo_mask_compositor_t compositor;
390 if (compositor.base.delegate == NULL) {
391 _cairo_mask_compositor_init (&compositor,
392 _cairo_image_traps_compositor_get ());
393 compositor.acquire = acquire;
394 compositor.release = release;
395 compositor.set_clip_region = set_clip_region;
396 compositor.pattern_to_surface = _cairo_pixman_source_create_for_pattern;
397 compositor.has_snapshot = has_snapshot;
398 compositor.draw_image = draw_image;
399 compositor.fill_rectangles = fill_rectangles;
400 compositor.fill_boxes = fill_boxes;
401 //compositor.check_composite = check_composite;
402 compositor.composite = composite;
403 //compositor.check_composite_boxes = check_composite_boxes;
404 compositor.composite_boxes = composite_boxes;
407 return &compositor.base;