Tizen 2.0 Release
[framework/graphics/cairo.git] / src / cairo-image-mask-compositor.c
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
3  *
4  * Copyright © 2003 University of Southern California
5  * Copyright © 2009,2010,2011 Intel Corporation
6  *
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.
14  *
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
20  *
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/
25  *
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.
29  *
30  * The Original Code is the cairo graphics library.
31  *
32  * The Initial Developer of the Original Code is University of Southern
33  * California.
34  *
35  * Contributor(s):
36  *      Carl D. Worth <cworth@cworth.org>
37  *      Chris Wilson <chris@chris-wilson.co.uk>
38  */
39
40 /* This compositor is slightly pointless. Just exists for testing
41  * and as skeleton code.
42  */
43
44 #include "cairoint.h"
45
46 #include "cairo-image-surface-private.h"
47
48 #include "cairo-compositor-private.h"
49 #include "cairo-region-private.h"
50
51 static cairo_int_status_t
52 acquire (void *abstract_dst)
53 {
54     return CAIRO_STATUS_SUCCESS;
55 }
56
57 static cairo_int_status_t
58 release (void *abstract_dst)
59 {
60     return CAIRO_STATUS_SUCCESS;
61 }
62
63 static cairo_int_status_t
64 set_clip_region (void *_surface,
65                  cairo_region_t *region)
66 {
67     cairo_image_surface_t *surface = _surface;
68     pixman_region32_t *rgn = region ? &region->rgn : NULL;
69
70     if (! pixman_image_set_clip_region32 (surface->pixman_image, rgn))
71         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
72
73     return CAIRO_STATUS_SUCCESS;
74 }
75
76 static cairo_bool_t
77 has_snapshot (void *_dst,
78               const cairo_pattern_t *pattern)
79 {
80     return FALSE;
81 }
82
83 static cairo_int_status_t
84 draw_image (void *_dst,
85             cairo_image_surface_t *image,
86             int src_x, int src_y,
87             int width, int height,
88             int dst_x, int dst_y)
89 {
90     cairo_image_surface_t *dst = (cairo_image_surface_t *)_dst;
91
92     pixman_image_composite32 (PIXMAN_OP_SRC,
93                               image->pixman_image, NULL, dst->pixman_image,
94                               src_x, src_y,
95                               0, 0,
96                               dst_x, dst_y,
97                               width, height);
98     return CAIRO_STATUS_SUCCESS;
99 }
100
101 static inline uint32_t
102 color_to_uint32 (const cairo_color_t *color)
103 {
104     return
105         (color->alpha_short >> 8 << 24) |
106         (color->red_short >> 8 << 16)   |
107         (color->green_short & 0xff00)   |
108         (color->blue_short >> 8);
109 }
110
111 static inline cairo_bool_t
112 color_to_pixel (const cairo_color_t     *color,
113                 double opacity,
114                 pixman_format_code_t     format,
115                 uint32_t                *pixel)
116 {
117     cairo_color_t opacity_color;
118     uint32_t c;
119
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))
129     {
130         return FALSE;
131     }
132
133     if (opacity != 1.0) {
134         _cairo_color_init_rgba (&opacity_color,
135                                 color->red,
136                                 color->green,
137                                 color->blue,
138                                 color->alpha * opacity);
139         color = &opacity_color;
140     }
141     c = color_to_uint32 (color);
142
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);
148     }
149
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);
155     }
156
157     if (format == PIXMAN_a8) {
158         c = c >> 24;
159     } else if (format == PIXMAN_r5g6b5 || format == PIXMAN_b5g6r5) {
160         c = ((((c) >> 3) & 0x001f) |
161              (((c) >> 5) & 0x07e0) |
162              (((c) >> 8) & 0xf800));
163     }
164
165     *pixel = c;
166     return TRUE;
167 }
168
169 static cairo_int_status_t
170 fill_rectangles (void                   *_dst,
171                  cairo_operator_t        op,
172                  const cairo_color_t    *color,
173                  cairo_rectangle_int_t  *rects,
174                  int                     num_rects)
175 {
176     cairo_image_surface_t *dst = _dst;
177     uint32_t pixel;
178     int i;
179
180     if (! color_to_pixel (color, 1.0, dst->pixman_format, &pixel))
181         return CAIRO_INT_STATUS_UNSUPPORTED;
182
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,
188                      pixel);
189     }
190
191     return CAIRO_STATUS_SUCCESS;
192 }
193
194 static cairo_int_status_t
195 fill_boxes (void                *_dst,
196             cairo_operator_t     op,
197             const cairo_color_t *color,
198             cairo_boxes_t       *boxes)
199 {
200     cairo_image_surface_t *dst = _dst;
201     struct _cairo_boxes_chunk *chunk;
202     uint32_t pixel;
203     int i;
204
205     assert (boxes->is_pixel_aligned);
206
207     if (! color_to_pixel (color, 1.0, dst->pixman_format, &pixel))
208         return CAIRO_INT_STATUS_UNSUPPORTED;
209
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,
219                          pixel);
220         }
221     }
222
223     return CAIRO_STATUS_SUCCESS;
224 }
225
226 static pixman_op_t
227 _pixman_operator (cairo_operator_t op)
228 {
229     switch ((int) op) {
230     case CAIRO_OPERATOR_CLEAR:
231         return PIXMAN_OP_CLEAR;
232
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:
238         return PIXMAN_OP_IN;
239     case CAIRO_OPERATOR_OUT:
240         return PIXMAN_OP_OUT;
241     case CAIRO_OPERATOR_ATOP:
242         return PIXMAN_OP_ATOP;
243
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;
254
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;
261
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;
292
293     default:
294         ASSERT_NOT_REACHED;
295         return PIXMAN_OP_OVER;
296     }
297 }
298
299 static cairo_int_status_t
300 composite (void                 *_dst,
301            cairo_operator_t     op,
302            cairo_surface_t      *abstract_src,
303            cairo_surface_t      *abstract_mask,
304            int                  src_x,
305            int                  src_y,
306            int                  mask_x,
307            int                  mask_y,
308            int                  dst_x,
309            int                  dst_y,
310            unsigned int         width,
311            unsigned int         height)
312 {
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;
316     if (mask) {
317         pixman_image_composite32 (_pixman_operator (op),
318                                   src->pixman_image, mask->pixman_image, dst->pixman_image,
319                                   src_x, src_y,
320                                   mask_x, mask_y,
321                                   dst_x, dst_y,
322                                   width, height);
323     } else {
324         pixman_image_composite32 (_pixman_operator (op),
325                                   src->pixman_image, NULL, dst->pixman_image,
326                                   src_x, src_y,
327                                   0, 0,
328                                   dst_x, dst_y,
329                                   width, height);
330     }
331
332     return CAIRO_STATUS_SUCCESS;
333 }
334
335 static cairo_int_status_t
336 composite_boxes (void                   *_dst,
337                  cairo_operator_t       op,
338                  cairo_surface_t        *abstract_src,
339                  cairo_surface_t        *abstract_mask,
340                  int                    src_x,
341                  int                    src_y,
342                  int                    mask_x,
343                  int                    mask_y,
344                  int                    dst_x,
345                  int                    dst_y,
346                  cairo_boxes_t          *boxes)
347 {
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;
352     int i;
353
354     assert (boxes->is_pixel_aligned);
355
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);
363
364             if (mask) {
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,
370                                           x2 - x1, y2 - y1);
371             } else {
372                 pixman_image_composite32 (op,
373                                           src->pixman_image, NULL, dst->pixman_image,
374                                           x1 + src_x, y1 + src_y,
375                                           0, 0,
376                                           x1 + dst_x, y1 + dst_y,
377                                           x2 - x1, y2 - y1);
378             }
379         }
380     }
381
382     return CAIRO_STATUS_SUCCESS;
383 }
384
385 const cairo_compositor_t *
386 _cairo_image_mask_compositor_get (void)
387 {
388     static cairo_mask_compositor_t compositor;
389
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;
405     }
406
407     return &compositor.base;
408 }