gfx/cairo/libpixman/src/pixman.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial