beta-0.89.2
[luatex.git] / source / libs / pixman / pixman-src / pixman / pixman.c
blobf932eac3c1b6fbf82033c5aa4a5c8c80484d5837
1 /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
2 /*
3 * Copyright © 2000 SuSE, Inc.
4 * Copyright © 2007 Red Hat, Inc.
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of SuSE not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. SuSE makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: Keith Packard, SuSE, Inc.
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 #include "pixman-private.h"
31 #include <stdlib.h>
33 pixman_implementation_t *global_implementation;
35 #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
36 static void __attribute__((constructor))
37 pixman_constructor (void)
39 global_implementation = _pixman_choose_implementation ();
41 #endif
43 typedef struct operator_info_t operator_info_t;
45 struct operator_info_t
47 uint8_t opaque_info[4];
50 #define PACK(neither, src, dest, both) \
51 {{ (uint8_t)PIXMAN_OP_ ## neither, \
52 (uint8_t)PIXMAN_OP_ ## src, \
53 (uint8_t)PIXMAN_OP_ ## dest, \
54 (uint8_t)PIXMAN_OP_ ## both }}
56 static const operator_info_t operator_table[] =
58 /* Neither Opaque Src Opaque Dst Opaque Both Opaque */
59 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
60 PACK (SRC, SRC, SRC, SRC),
61 PACK (DST, DST, DST, DST),
62 PACK (OVER, SRC, OVER, SRC),
63 PACK (OVER_REVERSE, OVER_REVERSE, DST, DST),
64 PACK (IN, IN, SRC, SRC),
65 PACK (IN_REVERSE, DST, IN_REVERSE, DST),
66 PACK (OUT, OUT, CLEAR, CLEAR),
67 PACK (OUT_REVERSE, CLEAR, OUT_REVERSE, CLEAR),
68 PACK (ATOP, IN, OVER, SRC),
69 PACK (ATOP_REVERSE, OVER_REVERSE, IN_REVERSE, DST),
70 PACK (XOR, OUT, OUT_REVERSE, CLEAR),
71 PACK (ADD, ADD, ADD, ADD),
72 PACK (SATURATE, OVER_REVERSE, DST, DST),
74 {{ 0 /* 0x0e */ }},
75 {{ 0 /* 0x0f */ }},
77 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
78 PACK (SRC, SRC, SRC, SRC),
79 PACK (DST, DST, DST, DST),
80 PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER),
81 PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
82 PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN),
83 PACK (DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE),
84 PACK (DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT),
85 PACK (DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE),
86 PACK (DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP),
87 PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
88 PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR),
90 {{ 0 /* 0x1c */ }},
91 {{ 0 /* 0x1d */ }},
92 {{ 0 /* 0x1e */ }},
93 {{ 0 /* 0x1f */ }},
95 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
96 PACK (SRC, SRC, SRC, SRC),
97 PACK (DST, DST, DST, DST),
98 PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER),
99 PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
100 PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN),
101 PACK (CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE),
102 PACK (CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT),
103 PACK (CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE),
104 PACK (CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP),
105 PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
106 PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR),
108 {{ 0 /* 0x2c */ }},
109 {{ 0 /* 0x2d */ }},
110 {{ 0 /* 0x2e */ }},
111 {{ 0 /* 0x2f */ }},
113 PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY),
114 PACK (SCREEN, SCREEN, SCREEN, SCREEN),
115 PACK (OVERLAY, OVERLAY, OVERLAY, OVERLAY),
116 PACK (DARKEN, DARKEN, DARKEN, DARKEN),
117 PACK (LIGHTEN, LIGHTEN, LIGHTEN, LIGHTEN),
118 PACK (COLOR_DODGE, COLOR_DODGE, COLOR_DODGE, COLOR_DODGE),
119 PACK (COLOR_BURN, COLOR_BURN, COLOR_BURN, COLOR_BURN),
120 PACK (HARD_LIGHT, HARD_LIGHT, HARD_LIGHT, HARD_LIGHT),
121 PACK (SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT),
122 PACK (DIFFERENCE, DIFFERENCE, DIFFERENCE, DIFFERENCE),
123 PACK (EXCLUSION, EXCLUSION, EXCLUSION, EXCLUSION),
124 PACK (HSL_HUE, HSL_HUE, HSL_HUE, HSL_HUE),
125 PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION),
126 PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR),
127 PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY),
131 * Optimize the current operator based on opacity of source or destination
132 * The output operator should be mathematically equivalent to the source.
134 static pixman_op_t
135 optimize_operator (pixman_op_t op,
136 uint32_t src_flags,
137 uint32_t mask_flags,
138 uint32_t dst_flags)
140 pixman_bool_t is_source_opaque, is_dest_opaque;
142 #define OPAQUE_SHIFT 13
144 COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
146 is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
147 is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
149 is_dest_opaque >>= OPAQUE_SHIFT - 1;
150 is_source_opaque >>= OPAQUE_SHIFT;
152 return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
156 * Computing composite region
158 static inline pixman_bool_t
159 clip_general_image (pixman_region32_t * region,
160 pixman_region32_t * clip,
161 int dx,
162 int dy)
164 if (pixman_region32_n_rects (region) == 1 &&
165 pixman_region32_n_rects (clip) == 1)
167 pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL);
168 pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL);
169 int v;
171 if (rbox->x1 < (v = cbox->x1 + dx))
172 rbox->x1 = v;
173 if (rbox->x2 > (v = cbox->x2 + dx))
174 rbox->x2 = v;
175 if (rbox->y1 < (v = cbox->y1 + dy))
176 rbox->y1 = v;
177 if (rbox->y2 > (v = cbox->y2 + dy))
178 rbox->y2 = v;
179 if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
181 pixman_region32_init (region);
182 return FALSE;
185 else if (!pixman_region32_not_empty (clip))
187 return FALSE;
189 else
191 if (dx || dy)
192 pixman_region32_translate (region, -dx, -dy);
194 if (!pixman_region32_intersect (region, region, clip))
195 return FALSE;
197 if (dx || dy)
198 pixman_region32_translate (region, dx, dy);
201 return pixman_region32_not_empty (region);
204 static inline pixman_bool_t
205 clip_source_image (pixman_region32_t * region,
206 pixman_image_t * image,
207 int dx,
208 int dy)
210 /* Source clips are ignored, unless they are explicitly turned on
211 * and the clip in question was set by an X client. (Because if
212 * the clip was not set by a client, then it is a hierarchy
213 * clip and those should always be ignored for sources).
215 if (!image->common.clip_sources || !image->common.client_clip)
216 return TRUE;
218 return clip_general_image (region,
219 &image->common.clip_region,
220 dx, dy);
224 * returns FALSE if the final region is empty. Indistinguishable from
225 * an allocation failure, but rendering ignores those anyways.
227 pixman_bool_t
228 _pixman_compute_composite_region32 (pixman_region32_t * region,
229 pixman_image_t * src_image,
230 pixman_image_t * mask_image,
231 pixman_image_t * dest_image,
232 int32_t src_x,
233 int32_t src_y,
234 int32_t mask_x,
235 int32_t mask_y,
236 int32_t dest_x,
237 int32_t dest_y,
238 int32_t width,
239 int32_t height)
241 region->extents.x1 = dest_x;
242 region->extents.x2 = dest_x + width;
243 region->extents.y1 = dest_y;
244 region->extents.y2 = dest_y + height;
246 region->extents.x1 = MAX (region->extents.x1, 0);
247 region->extents.y1 = MAX (region->extents.y1, 0);
248 region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
249 region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
251 region->data = 0;
253 /* Check for empty operation */
254 if (region->extents.x1 >= region->extents.x2 ||
255 region->extents.y1 >= region->extents.y2)
257 region->extents.x1 = 0;
258 region->extents.x2 = 0;
259 region->extents.y1 = 0;
260 region->extents.y2 = 0;
261 return FALSE;
264 if (dest_image->common.have_clip_region)
266 if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
267 return FALSE;
270 if (dest_image->common.alpha_map)
272 if (!pixman_region32_intersect_rect (region, region,
273 dest_image->common.alpha_origin_x,
274 dest_image->common.alpha_origin_y,
275 dest_image->common.alpha_map->width,
276 dest_image->common.alpha_map->height))
278 return FALSE;
280 if (!pixman_region32_not_empty (region))
281 return FALSE;
282 if (dest_image->common.alpha_map->common.have_clip_region)
284 if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
285 -dest_image->common.alpha_origin_x,
286 -dest_image->common.alpha_origin_y))
288 return FALSE;
293 /* clip against src */
294 if (src_image->common.have_clip_region)
296 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
297 return FALSE;
299 if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
301 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
302 dest_x - (src_x - src_image->common.alpha_origin_x),
303 dest_y - (src_y - src_image->common.alpha_origin_y)))
305 return FALSE;
308 /* clip against mask */
309 if (mask_image && mask_image->common.have_clip_region)
311 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
312 return FALSE;
314 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
316 if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
317 dest_x - (mask_x - mask_image->common.alpha_origin_x),
318 dest_y - (mask_y - mask_image->common.alpha_origin_y)))
320 return FALSE;
325 return TRUE;
328 typedef struct box_48_16 box_48_16_t;
330 struct box_48_16
332 pixman_fixed_48_16_t x1;
333 pixman_fixed_48_16_t y1;
334 pixman_fixed_48_16_t x2;
335 pixman_fixed_48_16_t y2;
338 static pixman_bool_t
339 compute_transformed_extents (pixman_transform_t *transform,
340 const pixman_box32_t *extents,
341 box_48_16_t *transformed)
343 pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
344 pixman_fixed_t x1, y1, x2, y2;
345 int i;
347 x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
348 y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
349 x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
350 y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
352 if (!transform)
354 transformed->x1 = x1;
355 transformed->y1 = y1;
356 transformed->x2 = x2;
357 transformed->y2 = y2;
359 return TRUE;
362 tx1 = ty1 = INT64_MAX;
363 tx2 = ty2 = INT64_MIN;
365 for (i = 0; i < 4; ++i)
367 pixman_fixed_48_16_t tx, ty;
368 pixman_vector_t v;
370 v.vector[0] = (i & 0x01)? x1 : x2;
371 v.vector[1] = (i & 0x02)? y1 : y2;
372 v.vector[2] = pixman_fixed_1;
374 if (!pixman_transform_point (transform, &v))
375 return FALSE;
377 tx = (pixman_fixed_48_16_t)v.vector[0];
378 ty = (pixman_fixed_48_16_t)v.vector[1];
380 if (tx < tx1)
381 tx1 = tx;
382 if (ty < ty1)
383 ty1 = ty;
384 if (tx > tx2)
385 tx2 = tx;
386 if (ty > ty2)
387 ty2 = ty;
390 transformed->x1 = tx1;
391 transformed->y1 = ty1;
392 transformed->x2 = tx2;
393 transformed->y2 = ty2;
395 return TRUE;
398 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
399 #define ABS(f) (((f) < 0)? (-(f)) : (f))
400 #define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
402 static pixman_bool_t
403 analyze_extent (pixman_image_t *image,
404 const pixman_box32_t *extents,
405 uint32_t *flags)
407 pixman_transform_t *transform;
408 pixman_fixed_t x_off, y_off;
409 pixman_fixed_t width, height;
410 pixman_fixed_t *params;
411 box_48_16_t transformed;
412 pixman_box32_t exp_extents;
414 if (!image)
415 return TRUE;
417 /* Some compositing functions walk one step
418 * outside the destination rectangle, so we
419 * check here that the expanded-by-one source
420 * extents in destination space fits in 16 bits
422 if (!IS_16BIT (extents->x1 - 1) ||
423 !IS_16BIT (extents->y1 - 1) ||
424 !IS_16BIT (extents->x2 + 1) ||
425 !IS_16BIT (extents->y2 + 1))
427 return FALSE;
430 transform = image->common.transform;
431 if (image->common.type == BITS)
433 /* During repeat mode calculations we might convert the
434 * width/height of an image to fixed 16.16, so we need
435 * them to be smaller than 16 bits.
437 if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
438 return FALSE;
440 if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
441 extents->x1 >= 0 &&
442 extents->y1 >= 0 &&
443 extents->x2 <= image->bits.width &&
444 extents->y2 <= image->bits.height)
446 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
447 return TRUE;
450 switch (image->common.filter)
452 case PIXMAN_FILTER_CONVOLUTION:
453 params = image->common.filter_params;
454 x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
455 y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
456 width = params[0];
457 height = params[1];
458 break;
460 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
461 params = image->common.filter_params;
462 x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
463 y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
464 width = params[0];
465 height = params[1];
466 break;
468 case PIXMAN_FILTER_GOOD:
469 case PIXMAN_FILTER_BEST:
470 case PIXMAN_FILTER_BILINEAR:
471 x_off = - pixman_fixed_1 / 2;
472 y_off = - pixman_fixed_1 / 2;
473 width = pixman_fixed_1;
474 height = pixman_fixed_1;
475 break;
477 case PIXMAN_FILTER_FAST:
478 case PIXMAN_FILTER_NEAREST:
479 x_off = - pixman_fixed_e;
480 y_off = - pixman_fixed_e;
481 width = 0;
482 height = 0;
483 break;
485 default:
486 return FALSE;
489 else
491 x_off = 0;
492 y_off = 0;
493 width = 0;
494 height = 0;
497 if (!compute_transformed_extents (transform, extents, &transformed))
498 return FALSE;
500 if (image->common.type == BITS)
502 if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_e) >= 0 &&
503 pixman_fixed_to_int (transformed.y1 - pixman_fixed_e) >= 0 &&
504 pixman_fixed_to_int (transformed.x2 - pixman_fixed_e) < image->bits.width &&
505 pixman_fixed_to_int (transformed.y2 - pixman_fixed_e) < image->bits.height)
507 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
510 if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0 &&
511 pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0 &&
512 pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
513 pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
515 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
519 /* Check we don't overflow when the destination extents are expanded by one.
520 * This ensures that compositing functions can simply walk the source space
521 * using 16.16 variables without worrying about overflow.
523 exp_extents = *extents;
524 exp_extents.x1 -= 1;
525 exp_extents.y1 -= 1;
526 exp_extents.x2 += 1;
527 exp_extents.y2 += 1;
529 if (!compute_transformed_extents (transform, &exp_extents, &transformed))
530 return FALSE;
532 if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e) ||
533 !IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e) ||
534 !IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width) ||
535 !IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
537 return FALSE;
540 return TRUE;
544 * Work around GCC bug causing crashes in Mozilla with SSE2
546 * When using -msse, gcc generates movdqa instructions assuming that
547 * the stack is 16 byte aligned. Unfortunately some applications, such
548 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
549 * causes the movdqa instructions to fail.
551 * The __force_align_arg_pointer__ makes gcc generate a prologue that
552 * realigns the stack pointer to 16 bytes.
554 * On x86-64 this is not necessary because the standard ABI already
555 * calls for a 16 byte aligned stack.
557 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
559 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
560 __attribute__((__force_align_arg_pointer__))
561 #endif
562 PIXMAN_EXPORT void
563 pixman_image_composite32 (pixman_op_t op,
564 pixman_image_t * src,
565 pixman_image_t * mask,
566 pixman_image_t * dest,
567 int32_t src_x,
568 int32_t src_y,
569 int32_t mask_x,
570 int32_t mask_y,
571 int32_t dest_x,
572 int32_t dest_y,
573 int32_t width,
574 int32_t height)
576 pixman_format_code_t src_format, mask_format, dest_format;
577 pixman_region32_t region;
578 pixman_box32_t extents;
579 pixman_implementation_t *imp;
580 pixman_composite_func_t func;
581 pixman_composite_info_t info;
582 const pixman_box32_t *pbox;
583 int n;
585 _pixman_image_validate (src);
586 if (mask)
587 _pixman_image_validate (mask);
588 _pixman_image_validate (dest);
590 src_format = src->common.extended_format_code;
591 info.src_flags = src->common.flags;
593 if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE))
595 mask_format = mask->common.extended_format_code;
596 info.mask_flags = mask->common.flags;
598 else
600 mask_format = PIXMAN_null;
601 info.mask_flags = FAST_PATH_IS_OPAQUE | FAST_PATH_NO_ALPHA_MAP;
604 dest_format = dest->common.extended_format_code;
605 info.dest_flags = dest->common.flags;
607 /* Check for pixbufs */
608 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
609 (src->type == BITS && src->bits.bits == mask->bits.bits) &&
610 (src->common.repeat == mask->common.repeat) &&
611 (info.src_flags & info.mask_flags & FAST_PATH_ID_TRANSFORM) &&
612 (src_x == mask_x && src_y == mask_y))
614 if (src_format == PIXMAN_x8b8g8r8)
615 src_format = mask_format = PIXMAN_pixbuf;
616 else if (src_format == PIXMAN_x8r8g8b8)
617 src_format = mask_format = PIXMAN_rpixbuf;
620 pixman_region32_init (&region);
622 if (!_pixman_compute_composite_region32 (
623 &region, src, mask, dest,
624 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
626 goto out;
629 extents = *pixman_region32_extents (&region);
631 extents.x1 -= dest_x - src_x;
632 extents.y1 -= dest_y - src_y;
633 extents.x2 -= dest_x - src_x;
634 extents.y2 -= dest_y - src_y;
636 if (!analyze_extent (src, &extents, &info.src_flags))
637 goto out;
639 extents.x1 -= src_x - mask_x;
640 extents.y1 -= src_y - mask_y;
641 extents.x2 -= src_x - mask_x;
642 extents.y2 -= src_y - mask_y;
644 if (!analyze_extent (mask, &extents, &info.mask_flags))
645 goto out;
647 /* If the clip is within the source samples, and the samples are
648 * opaque, then the source is effectively opaque.
650 #define NEAREST_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
651 FAST_PATH_NEAREST_FILTER | \
652 FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
653 #define BILINEAR_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
654 FAST_PATH_BILINEAR_FILTER | \
655 FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
657 if ((info.src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
658 (info.src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
660 info.src_flags |= FAST_PATH_IS_OPAQUE;
663 if ((info.mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
664 (info.mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
666 info.mask_flags |= FAST_PATH_IS_OPAQUE;
670 * Check if we can replace our operator by a simpler one
671 * if the src or dest are opaque. The output operator should be
672 * mathematically equivalent to the source.
674 info.op = optimize_operator (op, info.src_flags, info.mask_flags, info.dest_flags);
676 _pixman_implementation_lookup_composite (
677 get_implementation (), info.op,
678 src_format, info.src_flags,
679 mask_format, info.mask_flags,
680 dest_format, info.dest_flags,
681 &imp, &func);
683 info.src_image = src;
684 info.mask_image = mask;
685 info.dest_image = dest;
687 pbox = pixman_region32_rectangles (&region, &n);
689 while (n--)
691 info.src_x = pbox->x1 + src_x - dest_x;
692 info.src_y = pbox->y1 + src_y - dest_y;
693 info.mask_x = pbox->x1 + mask_x - dest_x;
694 info.mask_y = pbox->y1 + mask_y - dest_y;
695 info.dest_x = pbox->x1;
696 info.dest_y = pbox->y1;
697 info.width = pbox->x2 - pbox->x1;
698 info.height = pbox->y2 - pbox->y1;
700 func (imp, &info);
702 pbox++;
705 out:
706 pixman_region32_fini (&region);
709 PIXMAN_EXPORT void
710 pixman_image_composite (pixman_op_t op,
711 pixman_image_t * src,
712 pixman_image_t * mask,
713 pixman_image_t * dest,
714 int16_t src_x,
715 int16_t src_y,
716 int16_t mask_x,
717 int16_t mask_y,
718 int16_t dest_x,
719 int16_t dest_y,
720 uint16_t width,
721 uint16_t height)
723 pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
724 mask_x, mask_y, dest_x, dest_y, width, height);
727 PIXMAN_EXPORT pixman_bool_t
728 pixman_blt (uint32_t *src_bits,
729 uint32_t *dst_bits,
730 int src_stride,
731 int dst_stride,
732 int src_bpp,
733 int dst_bpp,
734 int src_x,
735 int src_y,
736 int dest_x,
737 int dest_y,
738 int width,
739 int height)
741 return _pixman_implementation_blt (get_implementation(),
742 src_bits, dst_bits, src_stride, dst_stride,
743 src_bpp, dst_bpp,
744 src_x, src_y,
745 dest_x, dest_y,
746 width, height);
749 PIXMAN_EXPORT pixman_bool_t
750 pixman_fill (uint32_t *bits,
751 int stride,
752 int bpp,
753 int x,
754 int y,
755 int width,
756 int height,
757 uint32_t filler)
759 return _pixman_implementation_fill (
760 get_implementation(), bits, stride, bpp, x, y, width, height, filler);
763 static uint32_t
764 color_to_uint32 (const pixman_color_t *color)
766 return
767 (color->alpha >> 8 << 24) |
768 (color->red >> 8 << 16) |
769 (color->green & 0xff00) |
770 (color->blue >> 8);
773 static pixman_bool_t
774 color_to_pixel (const pixman_color_t *color,
775 uint32_t * pixel,
776 pixman_format_code_t format)
778 uint32_t c = color_to_uint32 (color);
780 if (!(format == PIXMAN_a8r8g8b8 ||
781 format == PIXMAN_x8r8g8b8 ||
782 format == PIXMAN_a8b8g8r8 ||
783 format == PIXMAN_x8b8g8r8 ||
784 format == PIXMAN_b8g8r8a8 ||
785 format == PIXMAN_b8g8r8x8 ||
786 format == PIXMAN_r8g8b8a8 ||
787 format == PIXMAN_r8g8b8x8 ||
788 format == PIXMAN_r5g6b5 ||
789 format == PIXMAN_b5g6r5 ||
790 format == PIXMAN_a8 ||
791 format == PIXMAN_a1))
793 return FALSE;
796 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
798 c = ((c & 0xff000000) >> 0) |
799 ((c & 0x00ff0000) >> 16) |
800 ((c & 0x0000ff00) >> 0) |
801 ((c & 0x000000ff) << 16);
803 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
805 c = ((c & 0xff000000) >> 24) |
806 ((c & 0x00ff0000) >> 8) |
807 ((c & 0x0000ff00) << 8) |
808 ((c & 0x000000ff) << 24);
810 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
811 c = ((c & 0xff000000) >> 24) | (c << 8);
813 if (format == PIXMAN_a1)
814 c = c >> 31;
815 else if (format == PIXMAN_a8)
816 c = c >> 24;
817 else if (format == PIXMAN_r5g6b5 ||
818 format == PIXMAN_b5g6r5)
819 c = convert_8888_to_0565 (c);
821 #if 0
822 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
823 printf ("pixel: %x\n", c);
824 #endif
826 *pixel = c;
827 return TRUE;
830 PIXMAN_EXPORT pixman_bool_t
831 pixman_image_fill_rectangles (pixman_op_t op,
832 pixman_image_t * dest,
833 const pixman_color_t * color,
834 int n_rects,
835 const pixman_rectangle16_t *rects)
837 pixman_box32_t stack_boxes[6];
838 pixman_box32_t *boxes;
839 pixman_bool_t result;
840 int i;
842 if (n_rects > 6)
844 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
845 if (boxes == NULL)
846 return FALSE;
848 else
850 boxes = stack_boxes;
853 for (i = 0; i < n_rects; ++i)
855 boxes[i].x1 = rects[i].x;
856 boxes[i].y1 = rects[i].y;
857 boxes[i].x2 = boxes[i].x1 + rects[i].width;
858 boxes[i].y2 = boxes[i].y1 + rects[i].height;
861 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
863 if (boxes != stack_boxes)
864 free (boxes);
866 return result;
869 PIXMAN_EXPORT pixman_bool_t
870 pixman_image_fill_boxes (pixman_op_t op,
871 pixman_image_t * dest,
872 const pixman_color_t *color,
873 int n_boxes,
874 const pixman_box32_t *boxes)
876 pixman_image_t *solid;
877 pixman_color_t c;
878 int i;
880 _pixman_image_validate (dest);
882 if (color->alpha == 0xffff)
884 if (op == PIXMAN_OP_OVER)
885 op = PIXMAN_OP_SRC;
888 if (op == PIXMAN_OP_CLEAR)
890 c.red = 0;
891 c.green = 0;
892 c.blue = 0;
893 c.alpha = 0;
895 color = &c;
897 op = PIXMAN_OP_SRC;
900 if (op == PIXMAN_OP_SRC)
902 uint32_t pixel;
904 if (color_to_pixel (color, &pixel, dest->bits.format))
906 pixman_region32_t fill_region;
907 int n_rects, j;
908 pixman_box32_t *rects;
910 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
911 return FALSE;
913 if (dest->common.have_clip_region)
915 if (!pixman_region32_intersect (&fill_region,
916 &fill_region,
917 &dest->common.clip_region))
918 return FALSE;
921 rects = pixman_region32_rectangles (&fill_region, &n_rects);
922 for (j = 0; j < n_rects; ++j)
924 const pixman_box32_t *rect = &(rects[j]);
925 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
926 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
927 pixel);
930 pixman_region32_fini (&fill_region);
931 return TRUE;
935 solid = pixman_image_create_solid_fill (color);
936 if (!solid)
937 return FALSE;
939 for (i = 0; i < n_boxes; ++i)
941 const pixman_box32_t *box = &(boxes[i]);
943 pixman_image_composite32 (op, solid, NULL, dest,
944 0, 0, 0, 0,
945 box->x1, box->y1,
946 box->x2 - box->x1, box->y2 - box->y1);
949 pixman_image_unref (solid);
951 return TRUE;
955 * pixman_version:
957 * Returns the version of the pixman library encoded in a single
958 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
959 * later versions compare greater than earlier versions.
961 * A run-time comparison to check that pixman's version is greater than
962 * or equal to version X.Y.Z could be performed as follows:
964 * <informalexample><programlisting>
965 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
966 * </programlisting></informalexample>
968 * See also pixman_version_string() as well as the compile-time
969 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
971 * Return value: the encoded version.
973 PIXMAN_EXPORT int
974 pixman_version (void)
976 return PIXMAN_VERSION;
980 * pixman_version_string:
982 * Returns the version of the pixman library as a human-readable string
983 * of the form "X.Y.Z".
985 * See also pixman_version() as well as the compile-time equivalents
986 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
988 * Return value: a string containing the version.
990 PIXMAN_EXPORT const char*
991 pixman_version_string (void)
993 return PIXMAN_VERSION_STRING;
997 * pixman_format_supported_source:
998 * @format: A pixman_format_code_t format
1000 * Return value: whether the provided format code is a supported
1001 * format for a pixman surface used as a source in
1002 * rendering.
1004 * Currently, all pixman_format_code_t values are supported.
1006 PIXMAN_EXPORT pixman_bool_t
1007 pixman_format_supported_source (pixman_format_code_t format)
1009 switch (format)
1011 /* 32 bpp formats */
1012 case PIXMAN_a2b10g10r10:
1013 case PIXMAN_x2b10g10r10:
1014 case PIXMAN_a2r10g10b10:
1015 case PIXMAN_x2r10g10b10:
1016 case PIXMAN_a8r8g8b8:
1017 case PIXMAN_a8r8g8b8_sRGB:
1018 case PIXMAN_x8r8g8b8:
1019 case PIXMAN_a8b8g8r8:
1020 case PIXMAN_x8b8g8r8:
1021 case PIXMAN_b8g8r8a8:
1022 case PIXMAN_b8g8r8x8:
1023 case PIXMAN_r8g8b8a8:
1024 case PIXMAN_r8g8b8x8:
1025 case PIXMAN_r8g8b8:
1026 case PIXMAN_b8g8r8:
1027 case PIXMAN_r5g6b5:
1028 case PIXMAN_b5g6r5:
1029 case PIXMAN_x14r6g6b6:
1030 /* 16 bpp formats */
1031 case PIXMAN_a1r5g5b5:
1032 case PIXMAN_x1r5g5b5:
1033 case PIXMAN_a1b5g5r5:
1034 case PIXMAN_x1b5g5r5:
1035 case PIXMAN_a4r4g4b4:
1036 case PIXMAN_x4r4g4b4:
1037 case PIXMAN_a4b4g4r4:
1038 case PIXMAN_x4b4g4r4:
1039 /* 8bpp formats */
1040 case PIXMAN_a8:
1041 case PIXMAN_r3g3b2:
1042 case PIXMAN_b2g3r3:
1043 case PIXMAN_a2r2g2b2:
1044 case PIXMAN_a2b2g2r2:
1045 case PIXMAN_c8:
1046 case PIXMAN_g8:
1047 case PIXMAN_x4a4:
1048 /* Collides with PIXMAN_c8
1049 case PIXMAN_x4c4:
1051 /* Collides with PIXMAN_g8
1052 case PIXMAN_x4g4:
1054 /* 4bpp formats */
1055 case PIXMAN_a4:
1056 case PIXMAN_r1g2b1:
1057 case PIXMAN_b1g2r1:
1058 case PIXMAN_a1r1g1b1:
1059 case PIXMAN_a1b1g1r1:
1060 case PIXMAN_c4:
1061 case PIXMAN_g4:
1062 /* 1bpp formats */
1063 case PIXMAN_a1:
1064 case PIXMAN_g1:
1065 /* YUV formats */
1066 case PIXMAN_yuy2:
1067 case PIXMAN_yv12:
1068 return TRUE;
1070 default:
1071 return FALSE;
1076 * pixman_format_supported_destination:
1077 * @format: A pixman_format_code_t format
1079 * Return value: whether the provided format code is a supported
1080 * format for a pixman surface used as a destination in
1081 * rendering.
1083 * Currently, all pixman_format_code_t values are supported
1084 * except for the YUV formats.
1086 PIXMAN_EXPORT pixman_bool_t
1087 pixman_format_supported_destination (pixman_format_code_t format)
1089 /* YUV formats cannot be written to at the moment */
1090 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1091 return FALSE;
1093 return pixman_format_supported_source (format);
1096 PIXMAN_EXPORT pixman_bool_t
1097 pixman_compute_composite_region (pixman_region16_t * region,
1098 pixman_image_t * src_image,
1099 pixman_image_t * mask_image,
1100 pixman_image_t * dest_image,
1101 int16_t src_x,
1102 int16_t src_y,
1103 int16_t mask_x,
1104 int16_t mask_y,
1105 int16_t dest_x,
1106 int16_t dest_y,
1107 uint16_t width,
1108 uint16_t height)
1110 pixman_region32_t r32;
1111 pixman_bool_t retval;
1113 pixman_region32_init (&r32);
1115 retval = _pixman_compute_composite_region32 (
1116 &r32, src_image, mask_image, dest_image,
1117 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1118 width, height);
1120 if (retval)
1122 if (!pixman_region16_copy_from_region32 (region, &r32))
1123 retval = FALSE;
1126 pixman_region32_fini (&r32);
1127 return retval;