1#include <stdlib.h>
2#include <stdio.h>
3#include "utils.h"
4
5static void
6make_random_region (pixman_region32_t *region)
7{
8    int n_boxes;
9
10    pixman_region32_init (region);
11
12    n_boxes = prng_rand_n (64);
13    while (n_boxes--)
14    {
15	int32_t x, y;
16	uint32_t w, h;
17
18	x = (int32_t)prng_rand() >> 2;
19	y = (int32_t)prng_rand() >> 2;
20	w = prng_rand() >> 2;
21	h = prng_rand() >> 2;
22
23	pixman_region32_union_rect (region, region, x, y, w, h);
24    }
25}
26
27static void
28print_box (pixman_box32_t *box)
29{
30    printf ("    %d %d %d %d\n", box->x1, box->y1, box->x2, box->y2);
31}
32
33static int32_t
34random_coord (pixman_region32_t *region, pixman_bool_t x)
35{
36    pixman_box32_t *b, *bb;
37    int n_boxes;
38    int begin, end;
39
40    if (prng_rand_n (14))
41    {
42	bb = pixman_region32_rectangles (region, &n_boxes);
43	if (n_boxes == 0)
44	    goto use_extent;
45	b = bb + prng_rand_n (n_boxes);
46    }
47    else
48    {
49    use_extent:
50	b = pixman_region32_extents (region);
51	n_boxes = 1;
52    }
53
54    if (x)
55    {
56	begin = b->x1;
57	end = b->x2;
58    }
59    else
60    {
61	begin = b->y1;
62	end = b->y2;
63    }
64
65    switch (prng_rand_n (5))
66    {
67    case 0:
68	return begin - prng_rand();
69    case 1:
70	return end + prng_rand ();
71    case 2:
72	return end;
73    case 3:
74	return begin;
75    default:
76	return (end - begin) / 2 + begin;
77    }
78    return 0;
79}
80
81static uint32_t
82compute_crc32_u32 (uint32_t crc32, uint32_t v)
83{
84    if (!is_little_endian())
85    {
86	v = ((v & 0xff000000) >> 24)	|
87	    ((v & 0x00ff0000) >> 8)	|
88	    ((v & 0x0000ff00) << 8)	|
89	    ((v & 0x000000ff) << 24);
90    }
91
92    return compute_crc32 (crc32, &v, sizeof (int32_t));
93}
94
95static uint32_t
96crc32_box32 (uint32_t crc32, pixman_box32_t *box)
97{
98    crc32 = compute_crc32_u32 (crc32, box->x1);
99    crc32 = compute_crc32_u32 (crc32, box->y1);
100    crc32 = compute_crc32_u32 (crc32, box->x2);
101    crc32 = compute_crc32_u32 (crc32, box->y2);
102
103    return crc32;
104}
105
106static uint32_t
107test_region_contains_rectangle (int i, int verbose)
108{
109    pixman_box32_t box;
110    pixman_box32_t rbox = { 0, 0, 0, 0 };
111    pixman_region32_t region;
112    uint32_t r, r1, r2, r3, r4, crc32;
113
114    prng_srand (i);
115
116    make_random_region (&region);
117
118    box.x1 = random_coord (&region, TRUE);
119    box.x2 = box.x1 + prng_rand ();
120    box.y1 = random_coord (&region, FALSE);
121    box.y2 = box.y1 + prng_rand ();
122
123    if (verbose)
124    {
125	int n_rects;
126	pixman_box32_t *boxes;
127
128	boxes = pixman_region32_rectangles (&region, &n_rects);
129
130	printf ("region:\n");
131	while (n_rects--)
132	    print_box (boxes++);
133	printf ("box:\n");
134	print_box (&box);
135    }
136
137    crc32 = 0;
138
139    r1 = pixman_region32_contains_point (&region, box.x1, box.y1, &rbox);
140    crc32 = crc32_box32 (crc32, &rbox);
141    r2 = pixman_region32_contains_point (&region, box.x1, box.y2, &rbox);
142    crc32 = crc32_box32 (crc32, &rbox);
143    r3 = pixman_region32_contains_point (&region, box.x2, box.y1, &rbox);
144    crc32 = crc32_box32 (crc32, &rbox);
145    r4 = pixman_region32_contains_point (&region, box.x2, box.y2, &rbox);
146    crc32 = crc32_box32 (crc32, &rbox);
147
148    r = pixman_region32_contains_rectangle (&region, &box);
149    r = (i << 8) | (r << 4) | (r1 << 3) | (r2 << 2) | (r3 << 1) | (r4 << 0);
150
151    crc32 = compute_crc32_u32 (crc32, r);
152
153    if (verbose)
154	printf ("results: %d %d %d %d %d\n", (r & 0xf0) >> 4, r1, r2, r3, r4);
155
156    pixman_region32_fini (&region);
157
158    return crc32;
159}
160
161int
162main (int argc, const char *argv[])
163{
164    return fuzzer_test_main ("region_contains",
165			     1000000,
166			     0x548E0F3F,
167			     test_region_contains_rectangle,
168			     argc, argv);
169}
170