8 #ifdef HAVE_GETTIMEOFDAY
18 #ifdef HAVE_SYS_MMAN_H
30 /* Random number generator state
33 prng_t prng_state_data;
36 /*----------------------------------------------------------------------------*\
37 * CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
39 * This program generates the CRC-32 values for the files named in the
40 * command-line arguments. These are the same CRC-32 values used by GZIP,
41 * PKZIP, and ZMODEM. The Crc32_ComputeBuf () can also be detached and
44 * THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
46 * Based on the byte-oriented implementation "File Verification Using CRC"
47 * by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
49 * v1.0.0: original release.
50 * v1.0.1: fixed printf formats.
51 * v1.0.2: fixed something else.
52 * v1.0.3: replaced CRC constant table by generator function.
53 * v1.0.4: reformatted code, made ANSI C. 1994-12-05.
54 * v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
55 \*----------------------------------------------------------------------------*/
57 /*----------------------------------------------------------------------------*\
59 * Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
61 * Computes or accumulates the CRC-32 value for a memory buffer.
62 * The 'inCrc32' gives a previously accumulated CRC-32 value to allow
63 * a CRC to be generated for multiple sequential buffer-fuls of data.
64 * The 'inCrc32' for the first buffer must be zero.
66 * inCrc32 - accumulated CRC-32 value, must be 0 on first call
67 * buf - buffer to compute CRC-32 value for
68 * bufLen - number of bytes in buffer
70 * crc32 - computed CRC-32 value
72 * (no errors are possible)
73 \*----------------------------------------------------------------------------*/
76 compute_crc32 (uint32_t in_crc32,
80 static const uint32_t crc_table[256] = {
81 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
82 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
83 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
84 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
85 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
86 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
87 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
88 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
89 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
90 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
91 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
92 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
93 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
94 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
95 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
96 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
97 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
98 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
99 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
100 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
101 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
102 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
103 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
104 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
105 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
106 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
107 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
108 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
109 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
110 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
111 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
112 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
113 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
114 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
115 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
116 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
117 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
118 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
119 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
120 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
121 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
122 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
123 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
127 unsigned char * byte_buf;
130 /* accumulate crc32 for buffer */
131 crc32 = in_crc32 ^ 0xFFFFFFFF;
132 byte_buf = (unsigned char*) buf;
134 for (i = 0; i < buf_len; i++)
135 crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
137 return (crc32 ^ 0xFFFFFFFF);
141 compute_crc32_for_image_internal (uint32_t crc32,
143 pixman_bool_t remove_alpha,
144 pixman_bool_t remove_rgb)
146 pixman_format_code_t fmt = pixman_image_get_format (img);
147 uint32_t *data = pixman_image_get_data (img);
148 int stride = pixman_image_get_stride (img);
149 int height = pixman_image_get_height (img);
150 uint32_t mask = 0xffffffff;
155 data += (stride / 4) * (height - 1);
159 /* mask unused 'x' part */
160 if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
161 PIXMAN_FORMAT_DEPTH (fmt) != 0)
163 uint32_t m = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
165 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
166 PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
168 m <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
174 /* mask alpha channel */
175 if (remove_alpha && PIXMAN_FORMAT_A (fmt))
179 if (PIXMAN_FORMAT_BPP (fmt) == 32)
182 m = (1 << PIXMAN_FORMAT_BPP (fmt)) - 1;
184 m >>= PIXMAN_FORMAT_A (fmt);
186 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
187 PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA ||
188 PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_A)
190 /* Alpha is at the bottom of the pixel */
191 m <<= PIXMAN_FORMAT_A (fmt);
197 /* mask rgb channels */
198 if (remove_rgb && PIXMAN_FORMAT_RGB (fmt))
200 uint32_t m = ((uint32_t)~0) >> (32 - PIXMAN_FORMAT_BPP (fmt));
201 uint32_t size = PIXMAN_FORMAT_R (fmt) + PIXMAN_FORMAT_G (fmt) + PIXMAN_FORMAT_B (fmt);
203 m &= ~((1 << size) - 1);
205 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
206 PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
208 /* RGB channels are at the top of the pixel */
215 for (i = 0; i * PIXMAN_FORMAT_BPP (fmt) < 32; i++)
216 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
218 for (i = 0; i < stride * height / 4; i++)
221 /* swap endiannes in order to provide identical results on both big
222 * and litte endian systems
224 image_endian_swap (img);
226 return compute_crc32 (crc32, data, stride * height);
230 compute_crc32_for_image (uint32_t crc32,
233 if (img->common.alpha_map)
235 crc32 = compute_crc32_for_image_internal (crc32, img, TRUE, FALSE);
236 crc32 = compute_crc32_for_image_internal (
237 crc32, (pixman_image_t *)img->common.alpha_map, FALSE, TRUE);
241 crc32 = compute_crc32_for_image_internal (crc32, img, FALSE, FALSE);
248 print_image (pixman_image_t *image)
251 int width, height, stride;
252 pixman_format_code_t format;
256 width = pixman_image_get_width (image);
257 height = pixman_image_get_height (image);
258 stride = pixman_image_get_stride (image);
259 format = pixman_image_get_format (image);
260 buffer = (uint8_t *)pixman_image_get_data (image);
262 s = (stride >= 0)? stride : - stride;
265 for (i = 0; i < height; i++)
267 for (j = 0; j < s; j++)
269 if (j == (width * PIXMAN_FORMAT_BPP (format) + 7) / 8)
272 printf ("%02X ", *((uint8_t *)buffer + i * stride + j));
279 /* perform endian conversion of pixel data
282 image_endian_swap (pixman_image_t *img)
284 int stride = pixman_image_get_stride (img);
285 uint32_t *data = pixman_image_get_data (img);
286 int height = pixman_image_get_height (img);
287 int bpp = PIXMAN_FORMAT_BPP (pixman_image_get_format (img));
290 /* swap bytes only on big endian systems */
291 if (is_little_endian())
297 for (i = 0; i < height; i++)
299 uint8_t *line_data = (uint8_t *)data + stride * i;
300 int s = (stride >= 0)? stride : - stride;
305 for (j = 0; j < s; j++)
308 ((line_data[j] & 0x80) >> 7) |
309 ((line_data[j] & 0x40) >> 5) |
310 ((line_data[j] & 0x20) >> 3) |
311 ((line_data[j] & 0x10) >> 1) |
312 ((line_data[j] & 0x08) << 1) |
313 ((line_data[j] & 0x04) << 3) |
314 ((line_data[j] & 0x02) << 5) |
315 ((line_data[j] & 0x01) << 7);
319 for (j = 0; j < s; j++)
321 line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
325 for (j = 0; j + 2 <= s; j += 2)
327 char t1 = line_data[j + 0];
328 char t2 = line_data[j + 1];
330 line_data[j + 1] = t1;
331 line_data[j + 0] = t2;
335 for (j = 0; j + 3 <= s; j += 3)
337 char t1 = line_data[j + 0];
338 char t2 = line_data[j + 1];
339 char t3 = line_data[j + 2];
341 line_data[j + 2] = t1;
342 line_data[j + 1] = t2;
343 line_data[j + 0] = t3;
347 for (j = 0; j + 4 <= s; j += 4)
349 char t1 = line_data[j + 0];
350 char t2 = line_data[j + 1];
351 char t3 = line_data[j + 2];
352 char t4 = line_data[j + 3];
354 line_data[j + 3] = t1;
355 line_data[j + 2] = t2;
356 line_data[j + 1] = t3;
357 line_data[j + 0] = t4;
367 #define N_LEADING_PROTECTED 10
368 #define N_TRAILING_PROTECTED 10
378 #if defined(HAVE_MPROTECT) && defined(HAVE_GETPAGESIZE) && defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
380 /* This is apparently necessary on at least OS X */
381 #ifndef MAP_ANONYMOUS
382 #define MAP_ANONYMOUS MAP_ANON
386 fence_malloc (int64_t len)
388 unsigned long page_size = getpagesize();
389 unsigned long page_mask = page_size - 1;
390 uint32_t n_payload_bytes = (len + page_mask) & ~page_mask;
392 (page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) +
393 n_payload_bytes) & ~page_mask;
394 uint8_t *initial_page;
395 uint8_t *leading_protected;
396 uint8_t *trailing_protected;
403 addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
406 if (addr == MAP_FAILED)
408 printf ("mmap failed on %lld %u\n", (long long int)len, n_bytes);
412 initial_page = (uint8_t *)(((uintptr_t)addr + page_mask) & ~page_mask);
413 leading_protected = initial_page + page_size;
414 payload = leading_protected + N_LEADING_PROTECTED * page_size;
415 trailing_protected = payload + n_payload_bytes;
417 ((info_t *)initial_page)->addr = addr;
418 ((info_t *)initial_page)->len = len;
419 ((info_t *)initial_page)->trailing = trailing_protected;
420 ((info_t *)initial_page)->n_bytes = n_bytes;
422 if ((mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
424 (mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size,
427 munmap (addr, n_bytes);
435 fence_free (void *data)
437 uint32_t page_size = getpagesize();
438 uint8_t *payload = data;
439 uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size;
440 uint8_t *initial_page = leading_protected - page_size;
441 info_t *info = (info_t *)initial_page;
443 munmap (info->addr, info->n_bytes);
449 fence_malloc (int64_t len)
455 fence_free (void *data)
463 make_random_bytes (int n_bytes)
465 uint8_t *bytes = fence_malloc (n_bytes);
470 prng_randmemset (bytes, n_bytes, 0);
476 a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels)
478 uint8_t *dst8 = (uint8_t *)dst;
481 for (i = 0; i < n_pixels; ++i)
486 a = (p & 0xff000000) >> 24;
487 r = (p & 0x00ff0000) >> 16;
488 g = (p & 0x0000ff00) >> 8;
489 b = (p & 0x000000ff) >> 0;
493 #define DIVIDE(c, a) \
496 int t = ((c) * 255) / a; \
497 (c) = t < 0? 0 : t > 255? 255 : t; \
515 write_png (pixman_image_t *image, const char *filename)
517 int width = pixman_image_get_width (image);
518 int height = pixman_image_get_height (image);
519 int stride = width * 4;
520 uint32_t *data = malloc (height * stride);
521 pixman_image_t *copy;
522 png_struct *write_struct;
523 png_info *info_struct;
524 pixman_bool_t result = FALSE;
525 FILE *f = fopen (filename, "wb");
526 png_bytep *row_pointers;
532 row_pointers = malloc (height * sizeof (png_bytep));
534 copy = pixman_image_create_bits (
535 PIXMAN_a8r8g8b8, width, height, data, stride);
537 pixman_image_composite32 (
538 PIXMAN_OP_SRC, image, NULL, copy, 0, 0, 0, 0, 0, 0, width, height);
540 a8r8g8b8_to_rgba_np (data, data, height * width);
542 for (i = 0; i < height; ++i)
543 row_pointers[i] = (png_bytep)(data + i * width);
545 if (!(write_struct = png_create_write_struct (
546 PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
549 if (!(info_struct = png_create_info_struct (write_struct)))
552 png_init_io (write_struct, f);
554 png_set_IHDR (write_struct, info_struct, width, height,
555 8, PNG_COLOR_TYPE_RGB_ALPHA,
556 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
557 PNG_FILTER_TYPE_BASE);
559 png_write_info (write_struct, info_struct);
561 png_write_image (write_struct, row_pointers);
563 png_write_end (write_struct, NULL);
568 png_destroy_write_struct (&write_struct, &info_struct);
574 pixman_image_unref (copy);
580 #else /* no libpng */
583 write_png (pixman_image_t *image, const char *filename)
591 color8_to_color16 (uint32_t color8, pixman_color_t *color16)
593 color16->alpha = ((color8 & 0xff000000) >> 24);
594 color16->red = ((color8 & 0x00ff0000) >> 16);
595 color16->green = ((color8 & 0x0000ff00) >> 8);
596 color16->blue = ((color8 & 0x000000ff) >> 0);
598 color16->alpha |= color16->alpha << 8;
599 color16->red |= color16->red << 8;
600 color16->blue |= color16->blue << 8;
601 color16->green |= color16->green << 8;
605 draw_checkerboard (pixman_image_t *image,
607 uint32_t color1, uint32_t color2)
609 pixman_color_t check1, check2;
610 pixman_image_t *c1, *c2;
611 int n_checks_x, n_checks_y;
614 color8_to_color16 (color1, &check1);
615 color8_to_color16 (color2, &check2);
617 c1 = pixman_image_create_solid_fill (&check1);
618 c2 = pixman_image_create_solid_fill (&check2);
621 pixman_image_get_width (image) + check_size - 1) / check_size;
623 pixman_image_get_height (image) + check_size - 1) / check_size;
625 for (j = 0; j < n_checks_y; j++)
627 for (i = 0; i < n_checks_x; i++)
636 pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image,
638 i * check_size, j * check_size,
639 check_size, check_size);
645 call_test_function (uint32_t (*test_function)(int testnum, int verbose),
651 #if defined (__GNUC__) && defined (_WIN32) && (defined (__i386) || defined (__i386__))
653 /* Deliberately avoid aligning the stack to 16 bytes */
662 : "edx", "ecx"); /* caller save registers */
664 retval = test_function (testnum, verbose);
671 * A function, which can be used as a core part of the test programs,
672 * intended to detect various problems with the help of fuzzing input
673 * to pixman API (according to some templates, aka "smart" fuzzing).
674 * Some general information about such testing can be found here:
675 * http://en.wikipedia.org/wiki/Fuzz_testing
677 * It may help detecting:
678 * - crashes on bad handling of valid or reasonably invalid input to
680 * - deviations from the behavior of older pixman releases.
681 * - deviations from the behavior of the same pixman release, but
682 * configured in a different way (for example with SIMD optimizations
683 * disabled), or running on a different OS or hardware.
685 * The test is performed by calling a callback function a huge number
686 * of times. The callback function is expected to run some snippet of
687 * pixman code with pseudorandom variations to the data feeded to
688 * pixman API. A result of running each callback function should be
689 * some deterministic value which depends on test number (test number
690 * can be used as a seed for PRNG). When 'verbose' argument is nonzero,
691 * callback function is expected to print to stdout some information
692 * about what it does.
694 * Return values from many small tests are accumulated together and
695 * used as final checksum, which can be compared to some expected
696 * value. Running the tests not individually, but in a batch helps
697 * to reduce process start overhead and also allows to parallelize
698 * testing and utilize multiple CPU cores.
700 * The resulting executable can be run without any arguments. In
701 * this case it runs a batch of tests starting from 1 and up to
702 * 'default_number_of_iterations'. The resulting checksum is
703 * compared with 'expected_checksum' and FAIL or PASS verdict
704 * depends on the result of this comparison.
706 * If the executable is run with 2 numbers provided as command line
707 * arguments, they specify the starting and ending numbers for a test
710 * If the executable is run with only one number provided as a command
711 * line argument, then this number is used to call the callback function
712 * once, and also with verbose flag set.
715 fuzzer_test_main (const char *test_name,
716 int default_number_of_iterations,
717 uint32_t expected_checksum,
718 uint32_t (*test_function)(int testnum, int verbose),
722 int i, n1 = 1, n2 = 0;
723 uint32_t checksum = 0;
724 int verbose = getenv ("VERBOSE") != NULL;
732 printf ("invalid test range\n");
740 checksum = call_test_function (test_function, n2, 1);
742 printf ("%d: checksum=%08X\n", n2, checksum);
748 n2 = default_number_of_iterations;
752 #pragma omp parallel for reduction(+:checksum) default(none) \
753 shared(n1, n2, test_function, verbose)
755 for (i = n1; i <= n2; i++)
757 uint32_t crc = call_test_function (test_function, i, 0);
759 printf ("%d: %08X\n", i, crc);
763 if (n1 == 1 && n2 == default_number_of_iterations)
765 if (checksum == expected_checksum)
767 printf ("%s test passed (checksum=%08X)\n",
768 test_name, checksum);
772 printf ("%s test failed! (checksum=%08X, expected %08X)\n",
773 test_name, checksum, expected_checksum);
779 printf ("%d-%d: checksum=%08X\n", n1, n2, checksum);
785 /* Try to obtain current time in seconds */
789 #ifdef HAVE_GETTIMEOFDAY
792 gettimeofday (&tv, NULL);
793 return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.;
795 return (double)clock() / (double)CLOCKS_PER_SEC;
800 get_random_seed (void)
802 union { double d; uint32_t u32; } t;
809 #ifdef HAVE_SIGACTION
811 static const char *global_msg;
816 printf ("%s\n", global_msg);
823 fail_after (int seconds, const char *msg)
825 #ifdef HAVE_SIGACTION
827 struct sigaction action;
831 memset (&action, 0, sizeof (action));
832 action.sa_handler = on_alarm;
836 sigaction (SIGALRM, &action, NULL);
842 enable_divbyzero_exceptions (void)
845 #ifdef HAVE_FEENABLEEXCEPT
846 feenableexcept (FE_DIVBYZERO);
852 aligned_malloc (size_t align, size_t size)
856 #ifdef HAVE_POSIX_MEMALIGN
857 if (posix_memalign (&result, align, size) != 0)
860 result = malloc (size);
866 #define CONVERT_15(c, is_rgb) \
868 ((((c) >> 3) & 0x001f) | \
869 (((c) >> 6) & 0x03e0) | \
870 (((c) >> 9) & 0x7c00)) : \
871 (((((c) >> 16) & 0xff) * 153 + \
872 (((c) >> 8) & 0xff) * 301 + \
873 (((c) ) & 0xff) * 58) >> 2))
876 convert_srgb_to_linear (double c)
881 return pow ((c + 0.055) / 1.055, 2.4);
885 convert_linear_to_srgb (double c)
890 return 1.055 * pow (c, 1.0/2.4) - 0.055;
894 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
897 uint32_t mask = (1 << depth) - 1;
899 for (i = 0; i < 32768; ++i)
900 palette->ent[i] = prng_rand() & mask;
902 memset (palette->rgba, 0, sizeof (palette->rgba));
904 for (i = 0; i < mask + 1; ++i)
910 /* We filled the rgb->index map with random numbers, but we
911 * do need the ability to round trip, that is if some indexed
912 * color expands to an argb24, then the 15 bit version of that
913 * color must map back to the index. Anything else, we don't
914 * care about too much.
920 rgba24 = prng_rand();
921 i15 = CONVERT_15 (rgba24, is_rgb);
923 old_idx = palette->ent[i15];
924 if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15)
930 palette->rgba[i] = rgba24;
931 palette->ent[i15] = i;
934 for (i = 0; i < mask + 1; ++i)
936 assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i);
941 operator_name (pixman_op_t op)
945 case PIXMAN_OP_CLEAR: return "PIXMAN_OP_CLEAR";
946 case PIXMAN_OP_SRC: return "PIXMAN_OP_SRC";
947 case PIXMAN_OP_DST: return "PIXMAN_OP_DST";
948 case PIXMAN_OP_OVER: return "PIXMAN_OP_OVER";
949 case PIXMAN_OP_OVER_REVERSE: return "PIXMAN_OP_OVER_REVERSE";
950 case PIXMAN_OP_IN: return "PIXMAN_OP_IN";
951 case PIXMAN_OP_IN_REVERSE: return "PIXMAN_OP_IN_REVERSE";
952 case PIXMAN_OP_OUT: return "PIXMAN_OP_OUT";
953 case PIXMAN_OP_OUT_REVERSE: return "PIXMAN_OP_OUT_REVERSE";
954 case PIXMAN_OP_ATOP: return "PIXMAN_OP_ATOP";
955 case PIXMAN_OP_ATOP_REVERSE: return "PIXMAN_OP_ATOP_REVERSE";
956 case PIXMAN_OP_XOR: return "PIXMAN_OP_XOR";
957 case PIXMAN_OP_ADD: return "PIXMAN_OP_ADD";
958 case PIXMAN_OP_SATURATE: return "PIXMAN_OP_SATURATE";
960 case PIXMAN_OP_DISJOINT_CLEAR: return "PIXMAN_OP_DISJOINT_CLEAR";
961 case PIXMAN_OP_DISJOINT_SRC: return "PIXMAN_OP_DISJOINT_SRC";
962 case PIXMAN_OP_DISJOINT_DST: return "PIXMAN_OP_DISJOINT_DST";
963 case PIXMAN_OP_DISJOINT_OVER: return "PIXMAN_OP_DISJOINT_OVER";
964 case PIXMAN_OP_DISJOINT_OVER_REVERSE: return "PIXMAN_OP_DISJOINT_OVER_REVERSE";
965 case PIXMAN_OP_DISJOINT_IN: return "PIXMAN_OP_DISJOINT_IN";
966 case PIXMAN_OP_DISJOINT_IN_REVERSE: return "PIXMAN_OP_DISJOINT_IN_REVERSE";
967 case PIXMAN_OP_DISJOINT_OUT: return "PIXMAN_OP_DISJOINT_OUT";
968 case PIXMAN_OP_DISJOINT_OUT_REVERSE: return "PIXMAN_OP_DISJOINT_OUT_REVERSE";
969 case PIXMAN_OP_DISJOINT_ATOP: return "PIXMAN_OP_DISJOINT_ATOP";
970 case PIXMAN_OP_DISJOINT_ATOP_REVERSE: return "PIXMAN_OP_DISJOINT_ATOP_REVERSE";
971 case PIXMAN_OP_DISJOINT_XOR: return "PIXMAN_OP_DISJOINT_XOR";
973 case PIXMAN_OP_CONJOINT_CLEAR: return "PIXMAN_OP_CONJOINT_CLEAR";
974 case PIXMAN_OP_CONJOINT_SRC: return "PIXMAN_OP_CONJOINT_SRC";
975 case PIXMAN_OP_CONJOINT_DST: return "PIXMAN_OP_CONJOINT_DST";
976 case PIXMAN_OP_CONJOINT_OVER: return "PIXMAN_OP_CONJOINT_OVER";
977 case PIXMAN_OP_CONJOINT_OVER_REVERSE: return "PIXMAN_OP_CONJOINT_OVER_REVERSE";
978 case PIXMAN_OP_CONJOINT_IN: return "PIXMAN_OP_CONJOINT_IN";
979 case PIXMAN_OP_CONJOINT_IN_REVERSE: return "PIXMAN_OP_CONJOINT_IN_REVERSE";
980 case PIXMAN_OP_CONJOINT_OUT: return "PIXMAN_OP_CONJOINT_OUT";
981 case PIXMAN_OP_CONJOINT_OUT_REVERSE: return "PIXMAN_OP_CONJOINT_OUT_REVERSE";
982 case PIXMAN_OP_CONJOINT_ATOP: return "PIXMAN_OP_CONJOINT_ATOP";
983 case PIXMAN_OP_CONJOINT_ATOP_REVERSE: return "PIXMAN_OP_CONJOINT_ATOP_REVERSE";
984 case PIXMAN_OP_CONJOINT_XOR: return "PIXMAN_OP_CONJOINT_XOR";
986 case PIXMAN_OP_MULTIPLY: return "PIXMAN_OP_MULTIPLY";
987 case PIXMAN_OP_SCREEN: return "PIXMAN_OP_SCREEN";
988 case PIXMAN_OP_OVERLAY: return "PIXMAN_OP_OVERLAY";
989 case PIXMAN_OP_DARKEN: return "PIXMAN_OP_DARKEN";
990 case PIXMAN_OP_LIGHTEN: return "PIXMAN_OP_LIGHTEN";
991 case PIXMAN_OP_COLOR_DODGE: return "PIXMAN_OP_COLOR_DODGE";
992 case PIXMAN_OP_COLOR_BURN: return "PIXMAN_OP_COLOR_BURN";
993 case PIXMAN_OP_HARD_LIGHT: return "PIXMAN_OP_HARD_LIGHT";
994 case PIXMAN_OP_SOFT_LIGHT: return "PIXMAN_OP_SOFT_LIGHT";
995 case PIXMAN_OP_DIFFERENCE: return "PIXMAN_OP_DIFFERENCE";
996 case PIXMAN_OP_EXCLUSION: return "PIXMAN_OP_EXCLUSION";
997 case PIXMAN_OP_HSL_HUE: return "PIXMAN_OP_HSL_HUE";
998 case PIXMAN_OP_HSL_SATURATION: return "PIXMAN_OP_HSL_SATURATION";
999 case PIXMAN_OP_HSL_COLOR: return "PIXMAN_OP_HSL_COLOR";
1000 case PIXMAN_OP_HSL_LUMINOSITY: return "PIXMAN_OP_HSL_LUMINOSITY";
1002 case PIXMAN_OP_NONE:
1003 return "<invalid operator 'none'>";
1006 return "<unknown operator>";
1010 format_name (pixman_format_code_t format)
1015 case PIXMAN_a8r8g8b8: return "a8r8g8b8";
1016 case PIXMAN_x8r8g8b8: return "x8r8g8b8";
1017 case PIXMAN_a8b8g8r8: return "a8b8g8r8";
1018 case PIXMAN_x8b8g8r8: return "x8b8g8r8";
1019 case PIXMAN_b8g8r8a8: return "b8g8r8a8";
1020 case PIXMAN_b8g8r8x8: return "b8g8r8x8";
1021 case PIXMAN_r8g8b8a8: return "r8g8b8a8";
1022 case PIXMAN_r8g8b8x8: return "r8g8b8x8";
1023 case PIXMAN_x14r6g6b6: return "x14r6g6b6";
1024 case PIXMAN_x2r10g10b10: return "x2r10g10b10";
1025 case PIXMAN_a2r10g10b10: return "a2r10g10b10";
1026 case PIXMAN_x2b10g10r10: return "x2b10g10r10";
1027 case PIXMAN_a2b10g10r10: return "a2b10g10r10";
1030 case PIXMAN_a8r8g8b8_sRGB: return "a8r8g8b8_sRGB";
1033 case PIXMAN_r8g8b8: return "r8g8b8";
1034 case PIXMAN_b8g8r8: return "b8g8r8";
1037 case PIXMAN_r5g6b5: return "r5g6b5";
1038 case PIXMAN_b5g6r5: return "b5g6r5";
1040 case PIXMAN_a1r5g5b5: return "a1r5g5b5";
1041 case PIXMAN_x1r5g5b5: return "x1r5g5b5";
1042 case PIXMAN_a1b5g5r5: return "a1b5g5r5";
1043 case PIXMAN_x1b5g5r5: return "x1b5g5r5";
1044 case PIXMAN_a4r4g4b4: return "a4r4g4b4";
1045 case PIXMAN_x4r4g4b4: return "x4r4g4b4";
1046 case PIXMAN_a4b4g4r4: return "a4b4g4r4";
1047 case PIXMAN_x4b4g4r4: return "x4b4g4r4";
1050 case PIXMAN_a8: return "a8";
1051 case PIXMAN_r3g3b2: return "r3g3b2";
1052 case PIXMAN_b2g3r3: return "b2g3r3";
1053 case PIXMAN_a2r2g2b2: return "a2r2g2b2";
1054 case PIXMAN_a2b2g2r2: return "a2b2g2r2";
1057 case PIXMAN_x4c4: return "x4c4";
1058 case PIXMAN_g8: return "g8";
1060 case PIXMAN_c8: return "x4c4 / c8";
1061 case PIXMAN_x4g4: return "x4g4 / g8";
1063 case PIXMAN_x4a4: return "x4a4";
1066 case PIXMAN_a4: return "a4";
1067 case PIXMAN_r1g2b1: return "r1g2b1";
1068 case PIXMAN_b1g2r1: return "b1g2r1";
1069 case PIXMAN_a1r1g1b1: return "a1r1g1b1";
1070 case PIXMAN_a1b1g1r1: return "a1b1g1r1";
1072 case PIXMAN_c4: return "c4";
1073 case PIXMAN_g4: return "g4";
1076 case PIXMAN_a1: return "a1";
1078 case PIXMAN_g1: return "g1";
1081 case PIXMAN_yuy2: return "yuy2";
1082 case PIXMAN_yv12: return "yv12";
1087 * This is separate switch to prevent GCC from complaining
1088 * that the values are not in the pixman_format_code_t enum.
1090 switch ((uint32_t)format)
1092 case PIXMAN_null: return "null";
1093 case PIXMAN_solid: return "solid";
1094 case PIXMAN_pixbuf: return "pixbuf";
1095 case PIXMAN_rpixbuf: return "rpixbuf";
1096 case PIXMAN_unknown: return "unknown";
1099 return "<unknown format>";
1103 calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
1105 #define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0)
1111 case PIXMAN_OP_CLEAR:
1112 case PIXMAN_OP_DISJOINT_CLEAR:
1113 case PIXMAN_OP_CONJOINT_CLEAR:
1114 return mult_chan (src, dst, 0.0, 0.0);
1117 case PIXMAN_OP_DISJOINT_SRC:
1118 case PIXMAN_OP_CONJOINT_SRC:
1119 return mult_chan (src, dst, 1.0, 0.0);
1122 case PIXMAN_OP_DISJOINT_DST:
1123 case PIXMAN_OP_CONJOINT_DST:
1124 return mult_chan (src, dst, 0.0, 1.0);
1126 case PIXMAN_OP_OVER:
1127 return mult_chan (src, dst, 1.0, 1.0 - srca);
1129 case PIXMAN_OP_OVER_REVERSE:
1130 return mult_chan (src, dst, 1.0 - dsta, 1.0);
1133 return mult_chan (src, dst, dsta, 0.0);
1135 case PIXMAN_OP_IN_REVERSE:
1136 return mult_chan (src, dst, 0.0, srca);
1139 return mult_chan (src, dst, 1.0 - dsta, 0.0);
1141 case PIXMAN_OP_OUT_REVERSE:
1142 return mult_chan (src, dst, 0.0, 1.0 - srca);
1144 case PIXMAN_OP_ATOP:
1145 return mult_chan (src, dst, dsta, 1.0 - srca);
1147 case PIXMAN_OP_ATOP_REVERSE:
1148 return mult_chan (src, dst, 1.0 - dsta, srca);
1151 return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
1154 return mult_chan (src, dst, 1.0, 1.0);
1156 case PIXMAN_OP_SATURATE:
1157 case PIXMAN_OP_DISJOINT_OVER_REVERSE:
1161 Fa = MIN (1.0, (1.0 - dsta) / srca);
1162 return mult_chan (src, dst, Fa, 1.0);
1164 case PIXMAN_OP_DISJOINT_OVER:
1168 Fb = MIN (1.0, (1.0 - srca) / dsta);
1169 return mult_chan (src, dst, 1.0, Fb);
1171 case PIXMAN_OP_DISJOINT_IN:
1175 Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
1176 return mult_chan (src, dst, Fa, 0.0);
1178 case PIXMAN_OP_DISJOINT_IN_REVERSE:
1182 Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
1183 return mult_chan (src, dst, 0.0, Fb);
1185 case PIXMAN_OP_DISJOINT_OUT:
1189 Fa = MIN (1.0, (1.0 - dsta) / srca);
1190 return mult_chan (src, dst, Fa, 0.0);
1192 case PIXMAN_OP_DISJOINT_OUT_REVERSE:
1196 Fb = MIN (1.0, (1.0 - srca) / dsta);
1197 return mult_chan (src, dst, 0.0, Fb);
1199 case PIXMAN_OP_DISJOINT_ATOP:
1203 Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
1207 Fb = MIN (1.0, (1.0 - srca) / dsta);
1208 return mult_chan (src, dst, Fa, Fb);
1210 case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
1214 Fa = MIN (1.0, (1.0 - dsta) / srca);
1218 Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
1219 return mult_chan (src, dst, Fa, Fb);
1221 case PIXMAN_OP_DISJOINT_XOR:
1225 Fa = MIN (1.0, (1.0 - dsta) / srca);
1229 Fb = MIN (1.0, (1.0 - srca) / dsta);
1230 return mult_chan (src, dst, Fa, Fb);
1232 case PIXMAN_OP_CONJOINT_OVER:
1236 Fb = MAX (0.0, 1.0 - srca / dsta);
1237 return mult_chan (src, dst, 1.0, Fb);
1239 case PIXMAN_OP_CONJOINT_OVER_REVERSE:
1243 Fa = MAX (0.0, 1.0 - dsta / srca);
1244 return mult_chan (src, dst, Fa, 1.0);
1246 case PIXMAN_OP_CONJOINT_IN:
1250 Fa = MIN (1.0, dsta / srca);
1251 return mult_chan (src, dst, Fa, 0.0);
1253 case PIXMAN_OP_CONJOINT_IN_REVERSE:
1257 Fb = MIN (1.0, srca / dsta);
1258 return mult_chan (src, dst, 0.0, Fb);
1260 case PIXMAN_OP_CONJOINT_OUT:
1264 Fa = MAX (0.0, 1.0 - dsta / srca);
1265 return mult_chan (src, dst, Fa, 0.0);
1267 case PIXMAN_OP_CONJOINT_OUT_REVERSE:
1271 Fb = MAX (0.0, 1.0 - srca / dsta);
1272 return mult_chan (src, dst, 0.0, Fb);
1274 case PIXMAN_OP_CONJOINT_ATOP:
1278 Fa = MIN (1.0, dsta / srca);
1282 Fb = MAX (0.0, 1.0 - srca / dsta);
1283 return mult_chan (src, dst, Fa, Fb);
1285 case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
1289 Fa = MAX (0.0, 1.0 - dsta / srca);
1293 Fb = MIN (1.0, srca / dsta);
1294 return mult_chan (src, dst, Fa, Fb);
1296 case PIXMAN_OP_CONJOINT_XOR:
1300 Fa = MAX (0.0, 1.0 - dsta / srca);
1304 Fb = MAX (0.0, 1.0 - srca / dsta);
1305 return mult_chan (src, dst, Fa, Fb);
1307 case PIXMAN_OP_MULTIPLY:
1308 case PIXMAN_OP_SCREEN:
1309 case PIXMAN_OP_OVERLAY:
1310 case PIXMAN_OP_DARKEN:
1311 case PIXMAN_OP_LIGHTEN:
1312 case PIXMAN_OP_COLOR_DODGE:
1313 case PIXMAN_OP_COLOR_BURN:
1314 case PIXMAN_OP_HARD_LIGHT:
1315 case PIXMAN_OP_SOFT_LIGHT:
1316 case PIXMAN_OP_DIFFERENCE:
1317 case PIXMAN_OP_EXCLUSION:
1318 case PIXMAN_OP_HSL_HUE:
1319 case PIXMAN_OP_HSL_SATURATION:
1320 case PIXMAN_OP_HSL_COLOR:
1321 case PIXMAN_OP_HSL_LUMINOSITY:
1324 return 0; /* silence MSVC */
1330 do_composite (pixman_op_t op,
1332 const color_t *mask,
1335 pixman_bool_t component_alpha)
1337 color_t srcval, srcalpha;
1343 srcalpha.r = src->a;
1344 srcalpha.g = src->a;
1345 srcalpha.b = src->a;
1346 srcalpha.a = src->a;
1348 else if (component_alpha)
1350 srcval.r = src->r * mask->r;
1351 srcval.g = src->g * mask->g;
1352 srcval.b = src->b * mask->b;
1353 srcval.a = src->a * mask->a;
1355 srcalpha.r = src->a * mask->r;
1356 srcalpha.g = src->a * mask->g;
1357 srcalpha.b = src->a * mask->b;
1358 srcalpha.a = src->a * mask->a;
1362 srcval.r = src->r * mask->a;
1363 srcval.g = src->g * mask->a;
1364 srcval.b = src->b * mask->a;
1365 srcval.a = src->a * mask->a;
1367 srcalpha.r = src->a * mask->a;
1368 srcalpha.g = src->a * mask->a;
1369 srcalpha.b = src->a * mask->a;
1370 srcalpha.a = src->a * mask->a;
1373 result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
1374 result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
1375 result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
1376 result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
1380 round_channel (double p, int m)
1388 r = t / (double)((1 << m) - 1);
1394 round_color (pixman_format_code_t format, color_t *color)
1396 if (PIXMAN_FORMAT_R (format) == 0)
1404 color->r = round_channel (color->r, PIXMAN_FORMAT_R (format));
1405 color->g = round_channel (color->g, PIXMAN_FORMAT_G (format));
1406 color->b = round_channel (color->b, PIXMAN_FORMAT_B (format));
1409 if (PIXMAN_FORMAT_A (format) == 0)
1412 color->a = round_channel (color->a, PIXMAN_FORMAT_A (format));
1415 /* Check whether @pixel is a valid quantization of the a, r, g, b
1416 * parameters. Some slack is permitted.
1419 pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
1421 assert (PIXMAN_FORMAT_VIS (format));
1423 checker->format = format;
1425 switch (PIXMAN_FORMAT_TYPE (format))
1434 case PIXMAN_TYPE_ARGB:
1435 case PIXMAN_TYPE_ARGB_SRGB:
1437 checker->gs = checker->bs + PIXMAN_FORMAT_B (format);
1438 checker->rs = checker->gs + PIXMAN_FORMAT_G (format);
1439 checker->as = checker->rs + PIXMAN_FORMAT_R (format);
1442 case PIXMAN_TYPE_ABGR:
1444 checker->gs = checker->rs + PIXMAN_FORMAT_R (format);
1445 checker->bs = checker->gs + PIXMAN_FORMAT_G (format);
1446 checker->as = checker->bs + PIXMAN_FORMAT_B (format);
1449 case PIXMAN_TYPE_BGRA:
1450 /* With BGRA formats we start counting at the high end of the pixel */
1451 checker->bs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
1452 checker->gs = checker->bs - PIXMAN_FORMAT_B (format);
1453 checker->rs = checker->gs - PIXMAN_FORMAT_G (format);
1454 checker->as = checker->rs - PIXMAN_FORMAT_R (format);
1457 case PIXMAN_TYPE_RGBA:
1458 /* With BGRA formats we start counting at the high end of the pixel */
1459 checker->rs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
1460 checker->gs = checker->rs - PIXMAN_FORMAT_R (format);
1461 checker->bs = checker->gs - PIXMAN_FORMAT_G (format);
1462 checker->as = checker->bs - PIXMAN_FORMAT_B (format);
1470 checker->am = ((1 << PIXMAN_FORMAT_A (format)) - 1) << checker->as;
1471 checker->rm = ((1 << PIXMAN_FORMAT_R (format)) - 1) << checker->rs;
1472 checker->gm = ((1 << PIXMAN_FORMAT_G (format)) - 1) << checker->gs;
1473 checker->bm = ((1 << PIXMAN_FORMAT_B (format)) - 1) << checker->bs;
1475 checker->aw = PIXMAN_FORMAT_A (format);
1476 checker->rw = PIXMAN_FORMAT_R (format);
1477 checker->gw = PIXMAN_FORMAT_G (format);
1478 checker->bw = PIXMAN_FORMAT_B (format);
1482 pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
1483 int *a, int *r, int *g, int *b)
1485 *a = (pixel & checker->am) >> checker->as;
1486 *r = (pixel & checker->rm) >> checker->rs;
1487 *g = (pixel & checker->gm) >> checker->gs;
1488 *b = (pixel & checker->bm) >> checker->bs;
1492 pixel_checker_get_masks (const pixel_checker_t *checker,
1509 pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker,
1510 uint32_t pixel, color_t *color)
1514 pixel_checker_split_pixel (checker, pixel, &a, &r, &g, &b);
1516 if (checker->am == 0)
1519 color->a = a / (double)(checker->am >> checker->as);
1521 if (checker->rm == 0)
1524 color->r = r / (double)(checker->rm >> checker->rs);
1526 if (checker->gm == 0)
1529 color->g = g / (double)(checker->gm >> checker->gs);
1531 if (checker->bm == 0)
1534 color->b = b / (double)(checker->bm >> checker->bs);
1536 if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
1538 color->r = convert_srgb_to_linear (color->r);
1539 color->g = convert_srgb_to_linear (color->g);
1540 color->b = convert_srgb_to_linear (color->b);
1545 convert (double v, uint32_t width, uint32_t mask, uint32_t shift, double def)
1552 r = (v * ((mask >> shift) + 1));
1559 get_limits (const pixel_checker_t *checker, double limit,
1561 int *ao, int *ro, int *go, int *bo)
1565 if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
1568 tmp.r = convert_linear_to_srgb (color->r);
1569 tmp.g = convert_linear_to_srgb (color->g);
1570 tmp.b = convert_linear_to_srgb (color->b);
1575 *ao = convert (color->a + limit, checker->aw, checker->am, checker->as, 1.0);
1576 *ro = convert (color->r + limit, checker->rw, checker->rm, checker->rs, 0.0);
1577 *go = convert (color->g + limit, checker->gw, checker->gm, checker->gs, 0.0);
1578 *bo = convert (color->b + limit, checker->bw, checker->bm, checker->bs, 0.0);
1581 /* The acceptable deviation in units of [0.0, 1.0]
1583 #define DEVIATION (0.0064)
1586 pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
1587 int *am, int *rm, int *gm, int *bm)
1589 get_limits (checker, DEVIATION, color, am, rm, gm, bm);
1593 pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
1594 int *am, int *rm, int *gm, int *bm)
1596 get_limits (checker, - DEVIATION, color, am, rm, gm, bm);
1600 pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
1603 int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi;
1604 int32_t ai, ri, gi, bi;
1605 pixman_bool_t result;
1607 pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo);
1608 pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi);
1609 pixel_checker_split_pixel (checker, pixel, &ai, &ri, &gi, &bi);
1612 a_lo <= ai && ai <= a_hi &&
1613 r_lo <= ri && ri <= r_hi &&
1614 g_lo <= gi && gi <= g_hi &&
1615 b_lo <= bi && bi <= b_hi;