Coverage Report

Created: 2025-07-23 08:13

/src/cairo/subprojects/pixman-0.44.2/pixman/pixman-region.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1987, 1988, 1989, 1998  The Open Group
3
 * 
4
 * Permission to use, copy, modify, distribute, and sell this software and its
5
 * documentation for any purpose is hereby granted without fee, provided that
6
 * the above copyright notice appear in all copies and that both that
7
 * copyright notice and this permission notice appear in supporting
8
 * documentation.
9
 * 
10
 * The above copyright notice and this permission notice shall be included in
11
 * all copies or substantial portions of the Software.
12
 * 
13
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
16
 * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
 * 
20
 * Except as contained in this notice, the name of The Open Group shall not be
21
 * used in advertising or otherwise to promote the sale, use or other dealings
22
 * in this Software without prior written authorization from The Open Group.
23
 * 
24
 * Copyright 1987, 1988, 1989 by
25
 * Digital Equipment Corporation, Maynard, Massachusetts.
26
 * 
27
 *                    All Rights Reserved
28
 * 
29
 * Permission to use, copy, modify, and distribute this software and its
30
 * documentation for any purpose and without fee is hereby granted,
31
 * provided that the above copyright notice appear in all copies and that
32
 * both that copyright notice and this permission notice appear in
33
 * supporting documentation, and that the name of Digital not be
34
 * used in advertising or publicity pertaining to distribution of the
35
 * software without specific, written prior permission.
36
 * 
37
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43
 * SOFTWARE.
44
 *
45
 * Copyright © 1998 Keith Packard
46
 *
47
 * Permission to use, copy, modify, distribute, and sell this software and its
48
 * documentation for any purpose is hereby granted without fee, provided that
49
 * the above copyright notice appear in all copies and that both that
50
 * copyright notice and this permission notice appear in supporting
51
 * documentation, and that the name of Keith Packard not be used in
52
 * advertising or publicity pertaining to distribution of the software without
53
 * specific, written prior permission.  Keith Packard makes no
54
 * representations about the suitability of this software for any purpose.  It
55
 * is provided "as is" without express or implied warranty.
56
 *
57
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
58
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
59
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
60
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
61
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
62
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
63
 * PERFORMANCE OF THIS SOFTWARE.
64
 */
65
66
#include <stdlib.h>
67
#include <limits.h>
68
#include <string.h>
69
#include <stdio.h>
70
#include "pixman-private.h"
71
72
998k
#define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects)
73
/* not a region */
74
66.6k
#define PIXREGION_NAR(reg)      ((reg)->data == pixman_broken_data)
75
543k
#define PIXREGION_NUMRECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)
76
0
#define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0)
77
#define PIXREGION_RECTS(reg) \
78
43.9k
    ((reg)->data ? (box_type_t *)((reg)->data + 1) \
79
43.9k
     : (box_type_t *)&(reg)->extents)
80
305k
#define PIXREGION_BOXPTR(reg) ((box_type_t *)((reg)->data + 1))
81
305k
#define PIXREGION_BOX(reg, i) (&PIXREGION_BOXPTR (reg)[i])
82
116k
#define PIXREGION_TOP(reg) PIXREGION_BOX (reg, (reg)->data->numRects)
83
0
#define PIXREGION_END(reg) PIXREGION_BOX (reg, (reg)->data->numRects - 1)
84
85
499k
#define GOOD_RECT(rect) ((rect)->x1 < (rect)->x2 && (rect)->y1 < (rect)->y2)
86
0
#define BAD_RECT(rect) ((rect)->x1 > (rect)->x2 || (rect)->y1 > (rect)->y2)
87
88
#ifdef DEBUG
89
90
#define GOOD(reg)             \
91
    do                  \
92
    {                 \
93
  if (!PREFIX (_selfcheck (reg)))         \
94
      _pixman_log_error (FUNC, "Malformed region " # reg);  \
95
    } while (0)
96
97
#else
98
99
#define GOOD(reg)
100
101
#endif
102
103
static const box_type_t PREFIX (_empty_box_) = { 0, 0, 0, 0 };
104
static const region_data_type_t PREFIX (_empty_data_) = { 0, 0 };
105
#if defined (__llvm__) && !defined (__clang__)
106
static const volatile region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
107
#else
108
static const region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
109
#endif
110
111
static box_type_t *pixman_region_empty_box =
112
    (box_type_t *)&PREFIX (_empty_box_);
113
static region_data_type_t *pixman_region_empty_data =
114
    (region_data_type_t *)&PREFIX (_empty_data_);
115
static region_data_type_t *pixman_broken_data =
116
    (region_data_type_t *)&PREFIX (_broken_data_);
117
118
static pixman_bool_t
119
pixman_break (region_type_t *region);
120
121
/*
122
 * The functions in this file implement the Region abstraction used extensively
123
 * throughout the X11 sample server. A Region is simply a set of disjoint
124
 * (non-overlapping) rectangles, plus an "extent" rectangle which is the
125
 * smallest single rectangle that contains all the non-overlapping rectangles.
126
 *
127
 * A Region is implemented as a "y-x-banded" array of rectangles.  This array
128
 * imposes two degrees of order.  First, all rectangles are sorted by top side
129
 * y coordinate first (y1), and then by left side x coordinate (x1).
130
 *
131
 * Furthermore, the rectangles are grouped into "bands".  Each rectangle in a
132
 * band has the same top y coordinate (y1), and each has the same bottom y
133
 * coordinate (y2).  Thus all rectangles in a band differ only in their left
134
 * and right side (x1 and x2).  Bands are implicit in the array of rectangles:
135
 * there is no separate list of band start pointers.
136
 *
137
 * The y-x band representation does not minimize rectangles.  In particular,
138
 * if a rectangle vertically crosses a band (the rectangle has scanlines in
139
 * the y1 to y2 area spanned by the band), then the rectangle may be broken
140
 * down into two or more smaller rectangles stacked one atop the other.
141
 *
142
 *  -----------           -----------
143
 *  |         |           |         |       band 0
144
 *  |         |  --------       -----------  --------
145
 *  |         |  |      |  in y-x banded    |         |  |      |   band 1
146
 *  |         |  |      |  form is      |         |  |      |
147
 *  -----------  |      |       -----------  --------
148
 *               |      |        |      |   band 2
149
 *               --------        --------
150
 *
151
 * An added constraint on the rectangles is that they must cover as much
152
 * horizontal area as possible: no two rectangles within a band are allowed
153
 * to touch.
154
 *
155
 * Whenever possible, bands will be merged together to cover a greater vertical
156
 * distance (and thus reduce the number of rectangles). Two bands can be merged
157
 * only if the bottom of one touches the top of the other and they have
158
 * rectangles in the same places (of the same width, of course).
159
 *
160
 * Adam de Boor wrote most of the original region code.  Joel McCormack
161
 * substantially modified or rewrote most of the core arithmetic routines, and
162
 * added pixman_region_validate in order to support several speed improvements
163
 * to pixman_region_validate_tree.  Bob Scheifler changed the representation
164
 * to be more compact when empty or a single rectangle, and did a bunch of
165
 * gratuitous reformatting. Carl Worth did further gratuitous reformatting
166
 * while re-merging the server and client region code into libpixregion.
167
 * Soren Sandmann did even more gratuitous reformatting.
168
 */
169
170
/*  true iff two Boxes overlap */
171
#define EXTENTCHECK(r1, r2)    \
172
0
    (!( ((r1)->x2 <= (r2)->x1)  || \
173
0
        ((r1)->x1 >= (r2)->x2)  || \
174
0
        ((r1)->y2 <= (r2)->y1)  || \
175
0
        ((r1)->y1 >= (r2)->y2) ) )
176
177
/* true iff (x,y) is in Box */
178
#define INBOX(r, x, y)  \
179
0
    ( ((r)->x2 >  x) && \
180
0
      ((r)->x1 <= x) && \
181
0
      ((r)->y2 >  y) && \
182
0
      ((r)->y1 <= y) )
183
184
/* true iff Box r1 contains Box r2 */
185
#define SUBSUMES(r1, r2)  \
186
498k
    ( ((r1)->x1 <= (r2)->x1) && \
187
498k
      ((r1)->x2 >= (r2)->x2) && \
188
498k
      ((r1)->y1 <= (r2)->y1) && \
189
498k
      ((r1)->y2 >= (r2)->y2) )
190
191
static size_t
192
PIXREGION_SZOF (size_t n)
193
22.1k
{
194
22.1k
    size_t size = n * sizeof(box_type_t);
195
    
196
22.1k
    if (n > UINT32_MAX / sizeof(box_type_t))
197
0
  return 0;
198
199
22.1k
    if (sizeof(region_data_type_t) > UINT32_MAX - size)
200
0
  return 0;
201
202
22.1k
    return size + sizeof(region_data_type_t);
203
22.1k
}
pixman-region32.c:PIXREGION_SZOF
Line
Count
Source
193
22.1k
{
194
22.1k
    size_t size = n * sizeof(box_type_t);
195
    
196
22.1k
    if (n > UINT32_MAX / sizeof(box_type_t))
197
0
  return 0;
198
199
22.1k
    if (sizeof(region_data_type_t) > UINT32_MAX - size)
200
0
  return 0;
201
202
22.1k
    return size + sizeof(region_data_type_t);
203
22.1k
}
Unexecuted instantiation: pixman-region16.c:PIXREGION_SZOF
204
205
static region_data_type_t *
206
alloc_data (size_t n)
207
21.8k
{
208
21.8k
    size_t sz = PIXREGION_SZOF (n);
209
210
21.8k
    if (!sz)
211
0
  return NULL;
212
213
21.8k
    return malloc (sz);
214
21.8k
}
pixman-region32.c:alloc_data
Line
Count
Source
207
21.8k
{
208
21.8k
    size_t sz = PIXREGION_SZOF (n);
209
210
21.8k
    if (!sz)
211
0
  return NULL;
212
213
21.8k
    return malloc (sz);
214
21.8k
}
Unexecuted instantiation: pixman-region16.c:alloc_data
215
216
523k
#define FREE_DATA(reg) if ((reg)->data && (reg)->data->size) free ((reg)->data)
217
218
#define RECTALLOC_BAIL(region, n, bail)         \
219
484
    do                  \
220
484
    {                 \
221
484
  if (!(region)->data ||           \
222
484
      (((region)->data->numRects + (n)) > (region)->data->size)) \
223
484
  {               \
224
0
      if (!pixman_rect_alloc (region, n))       \
225
0
    goto bail;           \
226
0
  }                \
227
484
    } while (0)
228
229
#define RECTALLOC(region, n)            \
230
94.1k
    do                  \
231
94.1k
    {                 \
232
94.1k
  if (!(region)->data ||           \
233
94.1k
      (((region)->data->numRects + (n)) > (region)->data->size)) \
234
94.1k
  {               \
235
125
      if (!pixman_rect_alloc (region, n)) {     \
236
0
    return FALSE;           \
237
0
      }                \
238
125
  }                \
239
94.1k
    } while (0)
240
241
#define ADDRECT(next_rect, nx1, ny1, nx2, ny2)      \
242
116k
    do                \
243
116k
    {               \
244
116k
  next_rect->x1 = nx1;                        \
245
116k
  next_rect->y1 = ny1;                        \
246
116k
  next_rect->x2 = nx2;                        \
247
116k
  next_rect->y2 = ny2;                        \
248
116k
  next_rect++;                                \
249
116k
    }                \
250
116k
    while (0)
251
252
#define NEWRECT(region, next_rect, nx1, ny1, nx2, ny2)      \
253
22.2k
    do                  \
254
22.2k
    {                 \
255
22.2k
  if (!(region)->data ||           \
256
22.2k
      ((region)->data->numRects == (region)->data->size))   \
257
22.2k
  {               \
258
2
      if (!pixman_rect_alloc (region, 1))       \
259
2
    return FALSE;           \
260
2
      next_rect = PIXREGION_TOP (region);        \
261
2
  }                \
262
22.2k
  ADDRECT (next_rect, nx1, ny1, nx2, ny2);     \
263
22.2k
  region->data->numRects++;         \
264
22.2k
  critical_if_fail (region->data->numRects <= region->data->size);    \
265
22.2k
    } while (0)
266
267
#define DOWNSIZE(reg, numRects)           \
268
21.8k
    do                  \
269
21.8k
    {                 \
270
21.8k
  if (((numRects) < ((reg)->data->size >> 1)) &&     \
271
21.8k
      ((reg)->data->size > 50))         \
272
21.8k
  {               \
273
0
      region_data_type_t * new_data;        \
274
0
      size_t data_size = PIXREGION_SZOF (numRects);   \
275
0
                  \
276
0
      if (!data_size)           \
277
0
      {               \
278
0
    new_data = NULL;          \
279
0
      }                \
280
0
      else              \
281
0
      {               \
282
0
    new_data = (region_data_type_t *)     \
283
0
        realloc ((reg)->data, data_size);     \
284
0
      }                \
285
0
                  \
286
0
      if (new_data)           \
287
0
      {               \
288
0
    new_data->size = (numRects);        \
289
0
    (reg)->data = new_data;         \
290
0
      }                \
291
0
  }                \
292
21.8k
    } while (0)
293
294
PIXMAN_EXPORT pixman_bool_t
295
PREFIX (_equal) (const region_type_t *reg1, const region_type_t *reg2)
296
0
{
297
0
    int i;
298
0
    box_type_t *rects1;
299
0
    box_type_t *rects2;
300
301
0
    if (reg1->extents.x1 != reg2->extents.x1)
302
0
  return FALSE;
303
    
304
0
    if (reg1->extents.x2 != reg2->extents.x2)
305
0
  return FALSE;
306
    
307
0
    if (reg1->extents.y1 != reg2->extents.y1)
308
0
  return FALSE;
309
    
310
0
    if (reg1->extents.y2 != reg2->extents.y2)
311
0
  return FALSE;
312
    
313
0
    if (PIXREGION_NUMRECTS (reg1) != PIXREGION_NUMRECTS (reg2))
314
0
  return FALSE;
315
316
0
    rects1 = PIXREGION_RECTS (reg1);
317
0
    rects2 = PIXREGION_RECTS (reg2);
318
    
319
0
    for (i = 0; i != PIXREGION_NUMRECTS (reg1); i++)
320
0
    {
321
0
  if (rects1[i].x1 != rects2[i].x1)
322
0
      return FALSE;
323
  
324
0
  if (rects1[i].x2 != rects2[i].x2)
325
0
      return FALSE;
326
  
327
0
  if (rects1[i].y1 != rects2[i].y1)
328
0
      return FALSE;
329
  
330
0
  if (rects1[i].y2 != rects2[i].y2)
331
0
      return FALSE;
332
0
    }
333
334
0
    return TRUE;
335
0
}
Unexecuted instantiation: pixman_region32_equal
Unexecuted instantiation: pixman_region_equal
336
337
int
338
PREFIX (_print) (region_type_t *rgn)
339
0
{
340
0
    int num, size;
341
0
    int i;
342
0
    box_type_t * rects;
343
344
0
    num = PIXREGION_NUMRECTS (rgn);
345
0
    size = PIXREGION_SIZE (rgn);
346
0
    rects = PIXREGION_RECTS (rgn);
347
348
0
    fprintf (stderr, "num: %d size: %d\n", num, size);
349
0
    fprintf (stderr, "extents: %d %d %d %d\n",
350
0
             rgn->extents.x1,
351
0
       rgn->extents.y1,
352
0
       rgn->extents.x2,
353
0
       rgn->extents.y2);
354
    
355
0
    for (i = 0; i < num; i++)
356
0
    {
357
0
  fprintf (stderr, "%d %d %d %d \n",
358
0
           rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
359
0
    }
360
    
361
0
    fprintf (stderr, "\n");
362
363
0
    return(num);
364
0
}
Unexecuted instantiation: pixman_region32_print
Unexecuted instantiation: pixman_region_print
365
366
367
PIXMAN_EXPORT void
368
PREFIX (_init) (region_type_t *region)
369
46.1k
{
370
46.1k
    region->extents = *pixman_region_empty_box;
371
46.1k
    region->data = pixman_region_empty_data;
372
46.1k
}
pixman_region32_init
Line
Count
Source
369
46.1k
{
370
46.1k
    region->extents = *pixman_region_empty_box;
371
46.1k
    region->data = pixman_region_empty_data;
372
46.1k
}
Unexecuted instantiation: pixman_region_init
373
374
PIXMAN_EXPORT void
375
PREFIX (_init_rect) (region_type_t *  region,
376
                     int    x,
377
         int    y,
378
         unsigned int width,
379
         unsigned int height)
380
499k
{
381
499k
    region->extents.x1 = x;
382
499k
    region->extents.y1 = y;
383
499k
    region->extents.x2 = x + width;
384
499k
    region->extents.y2 = y + height;
385
386
499k
    if (!GOOD_RECT (&region->extents))
387
0
    {
388
0
        if (BAD_RECT (&region->extents))
389
0
            _pixman_log_error (FUNC, "Invalid rectangle passed");
390
0
        PREFIX (_init) (region);
391
0
        return;
392
0
    }
393
394
499k
    region->data = NULL;
395
499k
}
pixman_region32_init_rect
Line
Count
Source
380
499k
{
381
499k
    region->extents.x1 = x;
382
499k
    region->extents.y1 = y;
383
499k
    region->extents.x2 = x + width;
384
499k
    region->extents.y2 = y + height;
385
386
499k
    if (!GOOD_RECT (&region->extents))
387
0
    {
388
0
        if (BAD_RECT (&region->extents))
389
0
            _pixman_log_error (FUNC, "Invalid rectangle passed");
390
0
        PREFIX (_init) (region);
391
0
        return;
392
0
    }
393
394
499k
    region->data = NULL;
395
499k
}
Unexecuted instantiation: pixman_region_init_rect
396
397
PIXMAN_EXPORT void
398
PREFIX (_init_with_extents) (region_type_t *region, const box_type_t *extents)
399
0
{
400
0
    if (!GOOD_RECT (extents))
401
0
    {
402
0
        if (BAD_RECT (extents))
403
0
            _pixman_log_error (FUNC, "Invalid rectangle passed");
404
0
        PREFIX (_init) (region);
405
0
        return;
406
0
    }
407
0
    region->extents = *extents;
408
409
0
    region->data = NULL;
410
0
}
Unexecuted instantiation: pixman_region32_init_with_extents
Unexecuted instantiation: pixman_region_init_with_extents
411
412
PIXMAN_EXPORT void
413
PREFIX (_fini) (region_type_t *region)
414
522k
{
415
522k
    GOOD (region);
416
522k
    FREE_DATA (region);
417
522k
}
pixman_region32_fini
Line
Count
Source
414
522k
{
415
522k
    GOOD (region);
416
522k
    FREE_DATA (region);
417
522k
}
Unexecuted instantiation: pixman_region_fini
418
419
PIXMAN_EXPORT int
420
PREFIX (_n_rects) (const region_type_t *region)
421
0
{
422
0
    return PIXREGION_NUMRECTS (region);
423
0
}
Unexecuted instantiation: pixman_region32_n_rects
Unexecuted instantiation: pixman_region_n_rects
424
425
PIXMAN_EXPORT box_type_t *
426
PREFIX (_rectangles) (const region_type_t *region,
427
                      int               *n_rects)
428
188
{
429
188
    if (n_rects)
430
188
  *n_rects = PIXREGION_NUMRECTS (region);
431
432
188
    return PIXREGION_RECTS (region);
433
188
}
pixman_region32_rectangles
Line
Count
Source
428
188
{
429
188
    if (n_rects)
430
188
  *n_rects = PIXREGION_NUMRECTS (region);
431
432
188
    return PIXREGION_RECTS (region);
433
188
}
Unexecuted instantiation: pixman_region_rectangles
434
435
static pixman_bool_t
436
pixman_break (region_type_t *region)
437
0
{
438
0
    FREE_DATA (region);
439
440
0
    region->extents = *pixman_region_empty_box;
441
0
    region->data = pixman_broken_data;
442
443
0
    return FALSE;
444
0
}
Unexecuted instantiation: pixman-region32.c:pixman_break
Unexecuted instantiation: pixman-region16.c:pixman_break
445
446
static pixman_bool_t
447
pixman_rect_alloc (region_type_t * region,
448
                   int             n)
449
21.9k
{
450
21.9k
    region_data_type_t *data;
451
452
21.9k
    if (!region->data)
453
0
    {
454
0
  n++;
455
0
  region->data = alloc_data (n);
456
457
0
  if (!region->data)
458
0
      return pixman_break (region);
459
460
0
  region->data->numRects = 1;
461
0
  *PIXREGION_BOXPTR (region) = region->extents;
462
0
    }
463
21.9k
    else if (!region->data->size)
464
21.8k
    {
465
21.8k
  region->data = alloc_data (n);
466
467
21.8k
  if (!region->data)
468
0
      return pixman_break (region);
469
470
21.8k
  region->data->numRects = 0;
471
21.8k
    }
472
127
    else
473
127
    {
474
127
  size_t data_size;
475
476
127
  if (n == 1)
477
127
  {
478
127
      n = region->data->numRects;
479
127
      if (n > 500) /* XXX pick numbers out of a hat */
480
0
    n = 250;
481
127
  }
482
483
127
  n += region->data->numRects;
484
127
  data_size = PIXREGION_SZOF (n);
485
486
127
  if (!data_size)
487
0
  {
488
0
      data = NULL;
489
0
  }
490
127
  else
491
127
  {
492
127
      data = (region_data_type_t *)
493
127
    realloc (region->data, PIXREGION_SZOF (n));
494
127
  }
495
  
496
127
  if (!data)
497
0
      return pixman_break (region);
498
  
499
127
  region->data = data;
500
127
    }
501
    
502
21.9k
    region->data->size = n;
503
504
21.9k
    return TRUE;
505
21.9k
}
pixman-region32.c:pixman_rect_alloc
Line
Count
Source
449
21.9k
{
450
21.9k
    region_data_type_t *data;
451
452
21.9k
    if (!region->data)
453
0
    {
454
0
  n++;
455
0
  region->data = alloc_data (n);
456
457
0
  if (!region->data)
458
0
      return pixman_break (region);
459
460
0
  region->data->numRects = 1;
461
0
  *PIXREGION_BOXPTR (region) = region->extents;
462
0
    }
463
21.9k
    else if (!region->data->size)
464
21.8k
    {
465
21.8k
  region->data = alloc_data (n);
466
467
21.8k
  if (!region->data)
468
0
      return pixman_break (region);
469
470
21.8k
  region->data->numRects = 0;
471
21.8k
    }
472
127
    else
473
127
    {
474
127
  size_t data_size;
475
476
127
  if (n == 1)
477
127
  {
478
127
      n = region->data->numRects;
479
127
      if (n > 500) /* XXX pick numbers out of a hat */
480
0
    n = 250;
481
127
  }
482
483
127
  n += region->data->numRects;
484
127
  data_size = PIXREGION_SZOF (n);
485
486
127
  if (!data_size)
487
0
  {
488
0
      data = NULL;
489
0
  }
490
127
  else
491
127
  {
492
127
      data = (region_data_type_t *)
493
127
    realloc (region->data, PIXREGION_SZOF (n));
494
127
  }
495
  
496
127
  if (!data)
497
0
      return pixman_break (region);
498
  
499
127
  region->data = data;
500
127
    }
501
    
502
21.9k
    region->data->size = n;
503
504
21.9k
    return TRUE;
505
21.9k
}
Unexecuted instantiation: pixman-region16.c:pixman_rect_alloc
506
507
PIXMAN_EXPORT pixman_bool_t
508
PREFIX (_copy) (region_type_t *dst, const region_type_t *src)
509
1.09k
{
510
1.09k
    GOOD (dst);
511
1.09k
    GOOD (src);
512
513
1.09k
    if (dst == src)
514
0
  return TRUE;
515
    
516
1.09k
    dst->extents = src->extents;
517
518
1.09k
    if (!src->data || !src->data->size)
519
1.09k
    {
520
1.09k
  FREE_DATA (dst);
521
1.09k
  dst->data = src->data;
522
1.09k
  return TRUE;
523
1.09k
    }
524
    
525
0
    if (!dst->data || (dst->data->size < src->data->numRects))
526
0
    {
527
0
  FREE_DATA (dst);
528
529
0
  dst->data = alloc_data (src->data->numRects);
530
531
0
  if (!dst->data)
532
0
      return pixman_break (dst);
533
534
0
  dst->data->size = src->data->numRects;
535
0
    }
536
537
0
    dst->data->numRects = src->data->numRects;
538
539
0
    memmove ((char *)PIXREGION_BOXPTR (dst), (char *)PIXREGION_BOXPTR (src),
540
0
             dst->data->numRects * sizeof(box_type_t));
541
542
0
    return TRUE;
543
0
}
pixman_region32_copy
Line
Count
Source
509
1.09k
{
510
1.09k
    GOOD (dst);
511
1.09k
    GOOD (src);
512
513
1.09k
    if (dst == src)
514
0
  return TRUE;
515
    
516
1.09k
    dst->extents = src->extents;
517
518
1.09k
    if (!src->data || !src->data->size)
519
1.09k
    {
520
1.09k
  FREE_DATA (dst);
521
1.09k
  dst->data = src->data;
522
1.09k
  return TRUE;
523
1.09k
    }
524
    
525
0
    if (!dst->data || (dst->data->size < src->data->numRects))
526
0
    {
527
0
  FREE_DATA (dst);
528
529
0
  dst->data = alloc_data (src->data->numRects);
530
531
0
  if (!dst->data)
532
0
      return pixman_break (dst);
533
534
0
  dst->data->size = src->data->numRects;
535
0
    }
536
537
0
    dst->data->numRects = src->data->numRects;
538
539
0
    memmove ((char *)PIXREGION_BOXPTR (dst), (char *)PIXREGION_BOXPTR (src),
540
0
             dst->data->numRects * sizeof(box_type_t));
541
542
0
    return TRUE;
543
0
}
Unexecuted instantiation: pixman_region_copy
544
545
/*======================================================================
546
 *      Generic Region Operator
547
 *====================================================================*/
548
549
/*-
550
 *-----------------------------------------------------------------------
551
 * pixman_coalesce --
552
 *  Attempt to merge the boxes in the current band with those in the
553
 *  previous one.  We are guaranteed that the current band extends to
554
 *      the end of the rects array.  Used only by pixman_op.
555
 *
556
 * Results:
557
 *  The new index for the previous band.
558
 *
559
 * Side Effects:
560
 *  If coalescing takes place:
561
 *      - rectangles in the previous band will have their y2 fields
562
 *        altered.
563
 *      - region->data->numRects will be decreased.
564
 *
565
 *-----------------------------------------------------------------------
566
 */
567
static inline int
568
pixman_coalesce (region_type_t * region,      /* Region to coalesce    */
569
     int             prev_start,  /* Index of start of previous band */
570
     int             cur_start)   /* Index of start of current band  */
571
94.1k
{
572
94.1k
    box_type_t *prev_box;       /* Current box in previous band      */
573
94.1k
    box_type_t *cur_box;        /* Current box in current band       */
574
94.1k
    int numRects;               /* Number rectangles in both bands   */
575
94.1k
    int y2;                     /* Bottom of current band      */
576
577
    /*
578
     * Figure out how many rectangles are in the band.
579
     */
580
94.1k
    numRects = cur_start - prev_start;
581
94.1k
    critical_if_fail (numRects == region->data->numRects - cur_start);
582
583
94.1k
    if (!numRects) return cur_start;
584
585
    /*
586
     * The bands may only be coalesced if the bottom of the previous
587
     * matches the top scanline of the current.
588
     */
589
94.1k
    prev_box = PIXREGION_BOX (region, prev_start);
590
94.1k
    cur_box = PIXREGION_BOX (region, cur_start);
591
94.1k
    if (prev_box->y2 != cur_box->y1) return cur_start;
592
593
    /*
594
     * Make sure the bands have boxes in the same places. This
595
     * assumes that boxes have been added in such a way that they
596
     * cover the most area possible. I.e. two boxes in a band must
597
     * have some horizontal space between them.
598
     */
599
79.3k
    y2 = cur_box->y2;
600
601
79.3k
    do
602
79.3k
    {
603
79.3k
  if ((prev_box->x1 != cur_box->x1) || (prev_box->x2 != cur_box->x2))
604
37.2k
      return (cur_start);
605
  
606
42.0k
  prev_box++;
607
42.0k
  cur_box++;
608
42.0k
  numRects--;
609
42.0k
    }
610
79.3k
    while (numRects);
611
612
    /*
613
     * The bands may be merged, so set the bottom y of each box
614
     * in the previous band to the bottom y of the current band.
615
     */
616
42.0k
    numRects = cur_start - prev_start;
617
42.0k
    region->data->numRects -= numRects;
618
619
42.0k
    do
620
42.0k
    {
621
42.0k
  prev_box--;
622
42.0k
  prev_box->y2 = y2;
623
42.0k
  numRects--;
624
42.0k
    }
625
42.0k
    while (numRects);
626
627
42.0k
    return prev_start;
628
79.3k
}
pixman-region32.c:pixman_coalesce
Line
Count
Source
571
94.1k
{
572
94.1k
    box_type_t *prev_box;       /* Current box in previous band      */
573
94.1k
    box_type_t *cur_box;        /* Current box in current band       */
574
94.1k
    int numRects;               /* Number rectangles in both bands   */
575
94.1k
    int y2;                     /* Bottom of current band      */
576
577
    /*
578
     * Figure out how many rectangles are in the band.
579
     */
580
94.1k
    numRects = cur_start - prev_start;
581
94.1k
    critical_if_fail (numRects == region->data->numRects - cur_start);
582
583
94.1k
    if (!numRects) return cur_start;
584
585
    /*
586
     * The bands may only be coalesced if the bottom of the previous
587
     * matches the top scanline of the current.
588
     */
589
94.1k
    prev_box = PIXREGION_BOX (region, prev_start);
590
94.1k
    cur_box = PIXREGION_BOX (region, cur_start);
591
94.1k
    if (prev_box->y2 != cur_box->y1) return cur_start;
592
593
    /*
594
     * Make sure the bands have boxes in the same places. This
595
     * assumes that boxes have been added in such a way that they
596
     * cover the most area possible. I.e. two boxes in a band must
597
     * have some horizontal space between them.
598
     */
599
79.3k
    y2 = cur_box->y2;
600
601
79.3k
    do
602
79.3k
    {
603
79.3k
  if ((prev_box->x1 != cur_box->x1) || (prev_box->x2 != cur_box->x2))
604
37.2k
      return (cur_start);
605
  
606
42.0k
  prev_box++;
607
42.0k
  cur_box++;
608
42.0k
  numRects--;
609
42.0k
    }
610
79.3k
    while (numRects);
611
612
    /*
613
     * The bands may be merged, so set the bottom y of each box
614
     * in the previous band to the bottom y of the current band.
615
     */
616
42.0k
    numRects = cur_start - prev_start;
617
42.0k
    region->data->numRects -= numRects;
618
619
42.0k
    do
620
42.0k
    {
621
42.0k
  prev_box--;
622
42.0k
  prev_box->y2 = y2;
623
42.0k
  numRects--;
624
42.0k
    }
625
42.0k
    while (numRects);
626
627
42.0k
    return prev_start;
628
79.3k
}
Unexecuted instantiation: pixman-region16.c:pixman_coalesce
629
630
/* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */
631
632
#define COALESCE(new_reg, prev_band, cur_band)                          \
633
116k
    do                  \
634
116k
    {                 \
635
116k
  if (cur_band - prev_band == new_reg->data->numRects - cur_band) \
636
116k
      prev_band = pixman_coalesce (new_reg, prev_band, cur_band); \
637
116k
  else                \
638
116k
      prev_band = cur_band;         \
639
116k
    } while (0)
640
641
/*-
642
 *-----------------------------------------------------------------------
643
 * pixman_region_append_non_o --
644
 *  Handle a non-overlapping band for the union and subtract operations.
645
 *      Just adds the (top/bottom-clipped) rectangles into the region.
646
 *      Doesn't have to check for subsumption or anything.
647
 *
648
 * Results:
649
 *  None.
650
 *
651
 * Side Effects:
652
 *  region->data->numRects is incremented and the rectangles overwritten
653
 *  with the rectangles we're passed.
654
 *
655
 *-----------------------------------------------------------------------
656
 */
657
static inline pixman_bool_t
658
pixman_region_append_non_o (region_type_t * region,
659
          box_type_t *    r,
660
          box_type_t *    r_end,
661
          int             y1,
662
          int             y2)
663
94.1k
{
664
94.1k
    box_type_t *next_rect;
665
94.1k
    int new_rects;
666
667
94.1k
    new_rects = r_end - r;
668
669
94.1k
    critical_if_fail (y1 < y2);
670
94.1k
    critical_if_fail (new_rects != 0);
671
672
    /* Make sure we have enough space for all rectangles to be added */
673
94.1k
    RECTALLOC (region, new_rects);
674
94.1k
    next_rect = PIXREGION_TOP (region);
675
94.1k
    region->data->numRects += new_rects;
676
677
94.1k
    do
678
94.2k
    {
679
94.2k
  critical_if_fail (r->x1 < r->x2);
680
94.2k
  ADDRECT (next_rect, r->x1, y1, r->x2, y2);
681
94.2k
  r++;
682
94.2k
    }
683
94.2k
    while (r != r_end);
684
685
94.1k
    return TRUE;
686
94.1k
}
pixman-region32.c:pixman_region_append_non_o
Line
Count
Source
663
94.1k
{
664
94.1k
    box_type_t *next_rect;
665
94.1k
    int new_rects;
666
667
94.1k
    new_rects = r_end - r;
668
669
94.1k
    critical_if_fail (y1 < y2);
670
94.1k
    critical_if_fail (new_rects != 0);
671
672
    /* Make sure we have enough space for all rectangles to be added */
673
94.1k
    RECTALLOC (region, new_rects);
674
94.1k
    next_rect = PIXREGION_TOP (region);
675
94.1k
    region->data->numRects += new_rects;
676
677
94.1k
    do
678
94.2k
    {
679
94.2k
  critical_if_fail (r->x1 < r->x2);
680
94.2k
  ADDRECT (next_rect, r->x1, y1, r->x2, y2);
681
94.2k
  r++;
682
94.2k
    }
683
94.2k
    while (r != r_end);
684
685
94.1k
    return TRUE;
686
94.1k
}
Unexecuted instantiation: pixman-region16.c:pixman_region_append_non_o
687
688
#define FIND_BAND(r, r_band_end, r_end, ry1)           \
689
168k
    do                     \
690
168k
    {                    \
691
168k
  ry1 = r->y1;                 \
692
168k
  r_band_end = r + 1;              \
693
168k
  while ((r_band_end != r_end) && (r_band_end->y1 == ry1)) {   \
694
135
      r_band_end++;              \
695
135
  }                   \
696
168k
    } while (0)
697
698
#define APPEND_REGIONS(new_reg, r, r_end)       \
699
21.8k
    do                  \
700
21.8k
    {                 \
701
21.8k
  int new_rects;              \
702
21.8k
  if ((new_rects = r_end - r)) {         \
703
484
      RECTALLOC_BAIL (new_reg, new_rects, bail);      \
704
484
      memmove ((char *)PIXREGION_TOP (new_reg), (char *)r,  \
705
484
         new_rects * sizeof(box_type_t));     \
706
484
      new_reg->data->numRects += new_rects;     \
707
484
  }                \
708
21.8k
    } while (0)
709
710
/*-
711
 *-----------------------------------------------------------------------
712
 * pixman_op --
713
 *  Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse,
714
 *  pixman_region_subtract, pixman_region_intersect....  Both regions MUST have at least one
715
 *      rectangle, and cannot be the same object.
716
 *
717
 * Results:
718
 *  TRUE if successful.
719
 *
720
 * Side Effects:
721
 *  The new region is overwritten.
722
 *  overlap set to TRUE if overlap_func ever returns TRUE.
723
 *
724
 * Notes:
725
 *  The idea behind this function is to view the two regions as sets.
726
 *  Together they cover a rectangle of area that this function divides
727
 *  into horizontal bands where points are covered only by one region
728
 *  or by both. For the first case, the non_overlap_func is called with
729
 *  each the band and the band's upper and lower extents. For the
730
 *  second, the overlap_func is called to process the entire band. It
731
 *  is responsible for clipping the rectangles in the band, though
732
 *  this function provides the boundaries.
733
 *  At the end of each band, the new region is coalesced, if possible,
734
 *  to reduce the number of rectangles in the region.
735
 *
736
 *-----------------------------------------------------------------------
737
 */
738
739
typedef pixman_bool_t (*overlap_proc_ptr) (region_type_t *region,
740
             box_type_t *   r1,
741
             box_type_t *   r1_end,
742
             box_type_t *   r2,
743
             box_type_t *   r2_end,
744
             int            y1,
745
             int            y2);
746
747
static pixman_bool_t
748
pixman_op (region_type_t *  new_reg,               /* Place to store result     */
749
     const region_type_t *  reg1,                  /* First region in operation     */
750
     const region_type_t *  reg2,                  /* 2d region in operation        */
751
     overlap_proc_ptr overlap_func,          /* Function to call for over-
752
                * lapping bands       */
753
     int              append_non1,           /* Append non-overlapping bands  
754
                * in region 1 ?
755
                */
756
     int              append_non2            /* Append non-overlapping bands
757
                * in region 2 ?
758
                */
759
    )
760
21.8k
{
761
21.8k
    box_type_t *r1;                 /* Pointer into first region     */
762
21.8k
    box_type_t *r2;                 /* Pointer into 2d region      */
763
21.8k
    box_type_t *r1_end;             /* End of 1st region       */
764
21.8k
    box_type_t *r2_end;             /* End of 2d region        */
765
21.8k
    int ybot;                       /* Bottom of intersection      */
766
21.8k
    int ytop;                       /* Top of intersection       */
767
21.8k
    region_data_type_t *old_data;   /* Old data for new_reg      */
768
21.8k
    int prev_band;                  /* Index of start of
769
             * previous band in new_reg       */
770
21.8k
    int cur_band;                   /* Index of start of current
771
             * band in new_reg         */
772
21.8k
    box_type_t * r1_band_end;       /* End of current band in r1     */
773
21.8k
    box_type_t * r2_band_end;       /* End of current band in r2     */
774
21.8k
    int top;                        /* Top of non-overlapping band   */
775
21.8k
    int bot;                        /* Bottom of non-overlapping band*/
776
21.8k
    int r1y1;                       /* Temps for r1->y1 and r2->y1   */
777
21.8k
    int r2y1;
778
21.8k
    int new_size;
779
21.8k
    int numRects;
780
781
    /*
782
     * Break any region computed from a broken region
783
     */
784
21.8k
    if (PIXREGION_NAR (reg1) || PIXREGION_NAR (reg2))
785
0
  return pixman_break (new_reg);
786
787
    /*
788
     * Initialization:
789
     *  set r1, r2, r1_end and r2_end appropriately, save the rectangles
790
     * of the destination region until the end in case it's one of
791
     * the two source regions, then mark the "new" region empty, allocating
792
     * another array of rectangles for it to use.
793
     */
794
795
21.8k
    r1 = PIXREGION_RECTS (reg1);
796
21.8k
    new_size = PIXREGION_NUMRECTS (reg1);
797
21.8k
    r1_end = r1 + new_size;
798
799
21.8k
    numRects = PIXREGION_NUMRECTS (reg2);
800
21.8k
    r2 = PIXREGION_RECTS (reg2);
801
21.8k
    r2_end = r2 + numRects;
802
    
803
21.8k
    critical_if_fail (r1 != r1_end);
804
21.8k
    critical_if_fail (r2 != r2_end);
805
806
21.8k
    old_data = (region_data_type_t *)NULL;
807
808
21.8k
    if (((new_reg == reg1) && (new_size > 1)) ||
809
21.8k
        ((new_reg == reg2) && (numRects > 1)))
810
21.7k
    {
811
21.7k
        old_data = new_reg->data;
812
21.7k
        new_reg->data = pixman_region_empty_data;
813
21.7k
    }
814
815
    /* guess at new size */
816
21.8k
    if (numRects > new_size)
817
3
  new_size = numRects;
818
819
21.8k
    new_size <<= 1;
820
821
21.8k
    if (!new_reg->data)
822
160
  new_reg->data = pixman_region_empty_data;
823
21.7k
    else if (new_reg->data->size)
824
0
  new_reg->data->numRects = 0;
825
826
21.8k
    if (new_size > new_reg->data->size)
827
21.8k
    {
828
21.8k
        if (!pixman_rect_alloc (new_reg, new_size))
829
0
        {
830
0
            free (old_data);
831
0
            return FALSE;
832
0
  }
833
21.8k
    }
834
835
    /*
836
     * Initialize ybot.
837
     * In the upcoming loop, ybot and ytop serve different functions depending
838
     * on whether the band being handled is an overlapping or non-overlapping
839
     * band.
840
     *  In the case of a non-overlapping band (only one of the regions
841
     * has points in the band), ybot is the bottom of the most recent
842
     * intersection and thus clips the top of the rectangles in that band.
843
     * ytop is the top of the next intersection between the two regions and
844
     * serves to clip the bottom of the rectangles in the current band.
845
     *  For an overlapping band (where the two regions intersect), ytop clips
846
     * the top of the rectangles of both regions and ybot clips the bottoms.
847
     */
848
849
21.8k
    ybot = MIN (r1->y1, r2->y1);
850
851
    /*
852
     * prev_band serves to mark the start of the previous band so rectangles
853
     * can be coalesced into larger rectangles. qv. pixman_coalesce, above.
854
     * In the beginning, there is no previous band, so prev_band == cur_band
855
     * (cur_band is set later on, of course, but the first band will always
856
     * start at index 0). prev_band and cur_band must be indices because of
857
     * the possible expansion, and resultant moving, of the new region's
858
     * array of rectangles.
859
     */
860
21.8k
    prev_band = 0;
861
862
21.8k
    do
863
73.2k
    {
864
        /*
865
   * This algorithm proceeds one source-band (as opposed to a
866
   * destination band, which is determined by where the two regions
867
   * intersect) at a time. r1_band_end and r2_band_end serve to mark the
868
   * rectangle after the last one in the current band for their
869
   * respective regions.
870
   */
871
73.2k
        critical_if_fail (r1 != r1_end);
872
73.2k
        critical_if_fail (r2 != r2_end);
873
874
73.2k
        FIND_BAND (r1, r1_band_end, r1_end, r1y1);
875
73.2k
        FIND_BAND (r2, r2_band_end, r2_end, r2y1);
876
877
        /*
878
   * First handle the band that doesn't intersect, if any.
879
   *
880
   * Note that attention is restricted to one band in the
881
   * non-intersecting region at once, so if a region has n
882
   * bands between the current position and the next place it overlaps
883
   * the other, this entire loop will be passed through n times.
884
   */
885
73.2k
        if (r1y1 < r2y1)
886
72.2k
        {
887
72.2k
            if (append_non1)
888
72.2k
            {
889
72.2k
                top = MAX (r1y1, ybot);
890
72.2k
                bot = MIN (r1->y2, r2y1);
891
72.2k
                if (top != bot)
892
72.2k
                {
893
72.2k
                    cur_band = new_reg->data->numRects;
894
72.2k
                    if (!pixman_region_append_non_o (new_reg, r1, r1_band_end, top, bot))
895
0
      goto bail;
896
72.2k
                    COALESCE (new_reg, prev_band, cur_band);
897
72.2k
    }
898
72.2k
      }
899
72.2k
            ytop = r2y1;
900
72.2k
  }
901
1.05k
        else if (r2y1 < r1y1)
902
397
        {
903
397
            if (append_non2)
904
397
            {
905
397
                top = MAX (r2y1, ybot);
906
397
                bot = MIN (r2->y2, r1y1);
907
    
908
397
                if (top != bot)
909
24
                {
910
24
                    cur_band = new_reg->data->numRects;
911
912
24
                    if (!pixman_region_append_non_o (new_reg, r2, r2_band_end, top, bot))
913
0
      goto bail;
914
915
24
                    COALESCE (new_reg, prev_band, cur_band);
916
24
    }
917
397
      }
918
397
            ytop = r1y1;
919
397
  }
920
660
        else
921
660
        {
922
660
            ytop = r1y1;
923
660
  }
924
925
        /*
926
   * Now see if we've hit an intersecting band. The two bands only
927
   * intersect if ybot > ytop
928
   */
929
73.2k
        ybot = MIN (r1->y2, r2->y2);
930
73.2k
        if (ybot > ytop)
931
22.1k
        {
932
22.1k
            cur_band = new_reg->data->numRects;
933
934
22.1k
            if (!(*overlap_func)(new_reg,
935
22.1k
                                 r1, r1_band_end,
936
22.1k
                                 r2, r2_band_end,
937
22.1k
                                 ytop, ybot))
938
0
      {
939
0
    goto bail;
940
0
      }
941
      
942
22.1k
            COALESCE (new_reg, prev_band, cur_band);
943
22.1k
  }
944
945
        /*
946
   * If we've finished with a band (y2 == ybot) we skip forward
947
   * in the region to the next band.
948
   */
949
73.2k
        if (r1->y2 == ybot)
950
52.0k
      r1 = r1_band_end;
951
952
73.2k
        if (r2->y2 == ybot)
953
21.7k
      r2 = r2_band_end;
954
955
73.2k
    }
956
73.2k
    while (r1 != r1_end && r2 != r2_end);
957
958
    /*
959
     * Deal with whichever region (if any) still has rectangles left.
960
     *
961
     * We only need to worry about banding and coalescing for the very first
962
     * band left.  After that, we can just group all remaining boxes,
963
     * regardless of how many bands, into one final append to the list.
964
     */
965
966
21.8k
    if ((r1 != r1_end) && append_non1)
967
21.7k
    {
968
        /* Do first non_overlap1Func call, which may be able to coalesce */
969
21.7k
        FIND_BAND (r1, r1_band_end, r1_end, r1y1);
970
  
971
21.7k
        cur_band = new_reg->data->numRects;
972
  
973
21.7k
        if (!pixman_region_append_non_o (new_reg,
974
21.7k
                                         r1, r1_band_end,
975
21.7k
                                         MAX (r1y1, ybot), r1->y2))
976
0
  {
977
0
      goto bail;
978
0
  }
979
  
980
21.7k
        COALESCE (new_reg, prev_band, cur_band);
981
982
        /* Just append the rest of the boxes  */
983
21.7k
        APPEND_REGIONS (new_reg, r1_band_end, r1_end);
984
21.7k
    }
985
78
    else if ((r2 != r2_end) && append_non2)
986
69
    {
987
        /* Do first non_overlap2Func call, which may be able to coalesce */
988
69
        FIND_BAND (r2, r2_band_end, r2_end, r2y1);
989
990
69
  cur_band = new_reg->data->numRects;
991
992
69
        if (!pixman_region_append_non_o (new_reg,
993
69
                                         r2, r2_band_end,
994
69
                                         MAX (r2y1, ybot), r2->y2))
995
0
  {
996
0
      goto bail;
997
0
  }
998
999
69
        COALESCE (new_reg, prev_band, cur_band);
1000
1001
        /* Append rest of boxes */
1002
69
        APPEND_REGIONS (new_reg, r2_band_end, r2_end);
1003
69
    }
1004
1005
21.8k
    free (old_data);
1006
1007
21.8k
    if (!(numRects = new_reg->data->numRects))
1008
0
    {
1009
0
        FREE_DATA (new_reg);
1010
0
        new_reg->data = pixman_region_empty_data;
1011
0
    }
1012
21.8k
    else if (numRects == 1)
1013
4
    {
1014
4
        new_reg->extents = *PIXREGION_BOXPTR (new_reg);
1015
4
        FREE_DATA (new_reg);
1016
4
        new_reg->data = (region_data_type_t *)NULL;
1017
4
    }
1018
21.8k
    else
1019
21.8k
    {
1020
21.8k
        DOWNSIZE (new_reg, numRects);
1021
21.8k
    }
1022
1023
21.8k
    return TRUE;
1024
1025
0
bail:
1026
0
    free (old_data);
1027
1028
0
    return pixman_break (new_reg);
1029
21.8k
}
pixman-region32.c:pixman_op
Line
Count
Source
760
21.8k
{
761
21.8k
    box_type_t *r1;                 /* Pointer into first region     */
762
21.8k
    box_type_t *r2;                 /* Pointer into 2d region      */
763
21.8k
    box_type_t *r1_end;             /* End of 1st region       */
764
21.8k
    box_type_t *r2_end;             /* End of 2d region        */
765
21.8k
    int ybot;                       /* Bottom of intersection      */
766
21.8k
    int ytop;                       /* Top of intersection       */
767
21.8k
    region_data_type_t *old_data;   /* Old data for new_reg      */
768
21.8k
    int prev_band;                  /* Index of start of
769
             * previous band in new_reg       */
770
21.8k
    int cur_band;                   /* Index of start of current
771
             * band in new_reg         */
772
21.8k
    box_type_t * r1_band_end;       /* End of current band in r1     */
773
21.8k
    box_type_t * r2_band_end;       /* End of current band in r2     */
774
21.8k
    int top;                        /* Top of non-overlapping band   */
775
21.8k
    int bot;                        /* Bottom of non-overlapping band*/
776
21.8k
    int r1y1;                       /* Temps for r1->y1 and r2->y1   */
777
21.8k
    int r2y1;
778
21.8k
    int new_size;
779
21.8k
    int numRects;
780
781
    /*
782
     * Break any region computed from a broken region
783
     */
784
21.8k
    if (PIXREGION_NAR (reg1) || PIXREGION_NAR (reg2))
785
0
  return pixman_break (new_reg);
786
787
    /*
788
     * Initialization:
789
     *  set r1, r2, r1_end and r2_end appropriately, save the rectangles
790
     * of the destination region until the end in case it's one of
791
     * the two source regions, then mark the "new" region empty, allocating
792
     * another array of rectangles for it to use.
793
     */
794
795
21.8k
    r1 = PIXREGION_RECTS (reg1);
796
21.8k
    new_size = PIXREGION_NUMRECTS (reg1);
797
21.8k
    r1_end = r1 + new_size;
798
799
21.8k
    numRects = PIXREGION_NUMRECTS (reg2);
800
21.8k
    r2 = PIXREGION_RECTS (reg2);
801
21.8k
    r2_end = r2 + numRects;
802
    
803
21.8k
    critical_if_fail (r1 != r1_end);
804
21.8k
    critical_if_fail (r2 != r2_end);
805
806
21.8k
    old_data = (region_data_type_t *)NULL;
807
808
21.8k
    if (((new_reg == reg1) && (new_size > 1)) ||
809
21.8k
        ((new_reg == reg2) && (numRects > 1)))
810
21.7k
    {
811
21.7k
        old_data = new_reg->data;
812
21.7k
        new_reg->data = pixman_region_empty_data;
813
21.7k
    }
814
815
    /* guess at new size */
816
21.8k
    if (numRects > new_size)
817
3
  new_size = numRects;
818
819
21.8k
    new_size <<= 1;
820
821
21.8k
    if (!new_reg->data)
822
160
  new_reg->data = pixman_region_empty_data;
823
21.7k
    else if (new_reg->data->size)
824
0
  new_reg->data->numRects = 0;
825
826
21.8k
    if (new_size > new_reg->data->size)
827
21.8k
    {
828
21.8k
        if (!pixman_rect_alloc (new_reg, new_size))
829
0
        {
830
0
            free (old_data);
831
0
            return FALSE;
832
0
  }
833
21.8k
    }
834
835
    /*
836
     * Initialize ybot.
837
     * In the upcoming loop, ybot and ytop serve different functions depending
838
     * on whether the band being handled is an overlapping or non-overlapping
839
     * band.
840
     *  In the case of a non-overlapping band (only one of the regions
841
     * has points in the band), ybot is the bottom of the most recent
842
     * intersection and thus clips the top of the rectangles in that band.
843
     * ytop is the top of the next intersection between the two regions and
844
     * serves to clip the bottom of the rectangles in the current band.
845
     *  For an overlapping band (where the two regions intersect), ytop clips
846
     * the top of the rectangles of both regions and ybot clips the bottoms.
847
     */
848
849
21.8k
    ybot = MIN (r1->y1, r2->y1);
850
851
    /*
852
     * prev_band serves to mark the start of the previous band so rectangles
853
     * can be coalesced into larger rectangles. qv. pixman_coalesce, above.
854
     * In the beginning, there is no previous band, so prev_band == cur_band
855
     * (cur_band is set later on, of course, but the first band will always
856
     * start at index 0). prev_band and cur_band must be indices because of
857
     * the possible expansion, and resultant moving, of the new region's
858
     * array of rectangles.
859
     */
860
21.8k
    prev_band = 0;
861
862
21.8k
    do
863
73.2k
    {
864
        /*
865
   * This algorithm proceeds one source-band (as opposed to a
866
   * destination band, which is determined by where the two regions
867
   * intersect) at a time. r1_band_end and r2_band_end serve to mark the
868
   * rectangle after the last one in the current band for their
869
   * respective regions.
870
   */
871
73.2k
        critical_if_fail (r1 != r1_end);
872
73.2k
        critical_if_fail (r2 != r2_end);
873
874
73.2k
        FIND_BAND (r1, r1_band_end, r1_end, r1y1);
875
73.2k
        FIND_BAND (r2, r2_band_end, r2_end, r2y1);
876
877
        /*
878
   * First handle the band that doesn't intersect, if any.
879
   *
880
   * Note that attention is restricted to one band in the
881
   * non-intersecting region at once, so if a region has n
882
   * bands between the current position and the next place it overlaps
883
   * the other, this entire loop will be passed through n times.
884
   */
885
73.2k
        if (r1y1 < r2y1)
886
72.2k
        {
887
72.2k
            if (append_non1)
888
72.2k
            {
889
72.2k
                top = MAX (r1y1, ybot);
890
72.2k
                bot = MIN (r1->y2, r2y1);
891
72.2k
                if (top != bot)
892
72.2k
                {
893
72.2k
                    cur_band = new_reg->data->numRects;
894
72.2k
                    if (!pixman_region_append_non_o (new_reg, r1, r1_band_end, top, bot))
895
0
      goto bail;
896
72.2k
                    COALESCE (new_reg, prev_band, cur_band);
897
72.2k
    }
898
72.2k
      }
899
72.2k
            ytop = r2y1;
900
72.2k
  }
901
1.05k
        else if (r2y1 < r1y1)
902
397
        {
903
397
            if (append_non2)
904
397
            {
905
397
                top = MAX (r2y1, ybot);
906
397
                bot = MIN (r2->y2, r1y1);
907
    
908
397
                if (top != bot)
909
24
                {
910
24
                    cur_band = new_reg->data->numRects;
911
912
24
                    if (!pixman_region_append_non_o (new_reg, r2, r2_band_end, top, bot))
913
0
      goto bail;
914
915
24
                    COALESCE (new_reg, prev_band, cur_band);
916
24
    }
917
397
      }
918
397
            ytop = r1y1;
919
397
  }
920
660
        else
921
660
        {
922
660
            ytop = r1y1;
923
660
  }
924
925
        /*
926
   * Now see if we've hit an intersecting band. The two bands only
927
   * intersect if ybot > ytop
928
   */
929
73.2k
        ybot = MIN (r1->y2, r2->y2);
930
73.2k
        if (ybot > ytop)
931
22.1k
        {
932
22.1k
            cur_band = new_reg->data->numRects;
933
934
22.1k
            if (!(*overlap_func)(new_reg,
935
22.1k
                                 r1, r1_band_end,
936
22.1k
                                 r2, r2_band_end,
937
22.1k
                                 ytop, ybot))
938
0
      {
939
0
    goto bail;
940
0
      }
941
      
942
22.1k
            COALESCE (new_reg, prev_band, cur_band);
943
22.1k
  }
944
945
        /*
946
   * If we've finished with a band (y2 == ybot) we skip forward
947
   * in the region to the next band.
948
   */
949
73.2k
        if (r1->y2 == ybot)
950
52.0k
      r1 = r1_band_end;
951
952
73.2k
        if (r2->y2 == ybot)
953
21.7k
      r2 = r2_band_end;
954
955
73.2k
    }
956
73.2k
    while (r1 != r1_end && r2 != r2_end);
957
958
    /*
959
     * Deal with whichever region (if any) still has rectangles left.
960
     *
961
     * We only need to worry about banding and coalescing for the very first
962
     * band left.  After that, we can just group all remaining boxes,
963
     * regardless of how many bands, into one final append to the list.
964
     */
965
966
21.8k
    if ((r1 != r1_end) && append_non1)
967
21.7k
    {
968
        /* Do first non_overlap1Func call, which may be able to coalesce */
969
21.7k
        FIND_BAND (r1, r1_band_end, r1_end, r1y1);
970
  
971
21.7k
        cur_band = new_reg->data->numRects;
972
  
973
21.7k
        if (!pixman_region_append_non_o (new_reg,
974
21.7k
                                         r1, r1_band_end,
975
21.7k
                                         MAX (r1y1, ybot), r1->y2))
976
0
  {
977
0
      goto bail;
978
0
  }
979
  
980
21.7k
        COALESCE (new_reg, prev_band, cur_band);
981
982
        /* Just append the rest of the boxes  */
983
21.7k
        APPEND_REGIONS (new_reg, r1_band_end, r1_end);
984
21.7k
    }
985
78
    else if ((r2 != r2_end) && append_non2)
986
69
    {
987
        /* Do first non_overlap2Func call, which may be able to coalesce */
988
69
        FIND_BAND (r2, r2_band_end, r2_end, r2y1);
989
990
69
  cur_band = new_reg->data->numRects;
991
992
69
        if (!pixman_region_append_non_o (new_reg,
993
69
                                         r2, r2_band_end,
994
69
                                         MAX (r2y1, ybot), r2->y2))
995
0
  {
996
0
      goto bail;
997
0
  }
998
999
69
        COALESCE (new_reg, prev_band, cur_band);
1000
1001
        /* Append rest of boxes */
1002
69
        APPEND_REGIONS (new_reg, r2_band_end, r2_end);
1003
69
    }
1004
1005
21.8k
    free (old_data);
1006
1007
21.8k
    if (!(numRects = new_reg->data->numRects))
1008
0
    {
1009
0
        FREE_DATA (new_reg);
1010
0
        new_reg->data = pixman_region_empty_data;
1011
0
    }
1012
21.8k
    else if (numRects == 1)
1013
4
    {
1014
4
        new_reg->extents = *PIXREGION_BOXPTR (new_reg);
1015
4
        FREE_DATA (new_reg);
1016
4
        new_reg->data = (region_data_type_t *)NULL;
1017
4
    }
1018
21.8k
    else
1019
21.8k
    {
1020
21.8k
        DOWNSIZE (new_reg, numRects);
1021
21.8k
    }
1022
1023
21.8k
    return TRUE;
1024
1025
0
bail:
1026
0
    free (old_data);
1027
1028
0
    return pixman_break (new_reg);
1029
21.8k
}
Unexecuted instantiation: pixman-region16.c:pixman_op
1030
1031
/*-
1032
 *-----------------------------------------------------------------------
1033
 * pixman_set_extents --
1034
 *  Reset the extents of a region to what they should be. Called by
1035
 *  pixman_region_subtract and pixman_region_intersect as they can't
1036
 *      figure it out along the way or do so easily, as pixman_region_union can.
1037
 *
1038
 * Results:
1039
 *  None.
1040
 *
1041
 * Side Effects:
1042
 *  The region's 'extents' structure is overwritten.
1043
 *
1044
 *-----------------------------------------------------------------------
1045
 */
1046
static void
1047
pixman_set_extents (region_type_t *region)
1048
0
{
1049
0
    box_type_t *box, *box_end;
1050
1051
0
    if (!region->data)
1052
0
  return;
1053
1054
0
    if (!region->data->size)
1055
0
    {
1056
0
        region->extents.x2 = region->extents.x1;
1057
0
        region->extents.y2 = region->extents.y1;
1058
0
        return;
1059
0
    }
1060
1061
0
    box = PIXREGION_BOXPTR (region);
1062
0
    box_end = PIXREGION_END (region);
1063
1064
    /*
1065
     * Since box is the first rectangle in the region, it must have the
1066
     * smallest y1 and since box_end is the last rectangle in the region,
1067
     * it must have the largest y2, because of banding. Initialize x1 and
1068
     * x2 from  box and box_end, resp., as good things to initialize them
1069
     * to...
1070
     */
1071
0
    region->extents.x1 = box->x1;
1072
0
    region->extents.y1 = box->y1;
1073
0
    region->extents.x2 = box_end->x2;
1074
0
    region->extents.y2 = box_end->y2;
1075
1076
0
    critical_if_fail (region->extents.y1 < region->extents.y2);
1077
1078
0
    while (box <= box_end)
1079
0
    {
1080
0
        if (box->x1 < region->extents.x1)
1081
0
      region->extents.x1 = box->x1;
1082
0
        if (box->x2 > region->extents.x2)
1083
0
      region->extents.x2 = box->x2;
1084
0
        box++;
1085
0
    }
1086
1087
0
    critical_if_fail (region->extents.x1 < region->extents.x2);
1088
0
}
Unexecuted instantiation: pixman-region32.c:pixman_set_extents
Unexecuted instantiation: pixman-region16.c:pixman_set_extents
1089
1090
/*======================================================================
1091
 *      Region Intersection
1092
 *====================================================================*/
1093
/*-
1094
 *-----------------------------------------------------------------------
1095
 * pixman_region_intersect_o --
1096
 *  Handle an overlapping band for pixman_region_intersect.
1097
 *
1098
 * Results:
1099
 *  TRUE if successful.
1100
 *
1101
 * Side Effects:
1102
 *  Rectangles may be added to the region.
1103
 *
1104
 *-----------------------------------------------------------------------
1105
 */
1106
/*ARGSUSED*/
1107
static pixman_bool_t
1108
pixman_region_intersect_o (region_type_t *region,
1109
                           box_type_t *   r1,
1110
                           box_type_t *   r1_end,
1111
                           box_type_t *   r2,
1112
                           box_type_t *   r2_end,
1113
                           int            y1,
1114
                           int            y2)
1115
0
{
1116
0
    int x1;
1117
0
    int x2;
1118
0
    box_type_t *        next_rect;
1119
1120
0
    next_rect = PIXREGION_TOP (region);
1121
1122
0
    critical_if_fail (y1 < y2);
1123
0
    critical_if_fail (r1 != r1_end && r2 != r2_end);
1124
1125
0
    do
1126
0
    {
1127
0
        x1 = MAX (r1->x1, r2->x1);
1128
0
        x2 = MIN (r1->x2, r2->x2);
1129
1130
        /*
1131
   * If there's any overlap between the two rectangles, add that
1132
   * overlap to the new region.
1133
   */
1134
0
        if (x1 < x2)
1135
0
      NEWRECT (region, next_rect, x1, y1, x2, y2);
1136
1137
        /*
1138
   * Advance the pointer(s) with the leftmost right side, since the next
1139
   * rectangle on that list may still overlap the other region's
1140
   * current rectangle.
1141
   */
1142
0
        if (r1->x2 == x2)
1143
0
        {
1144
0
            r1++;
1145
0
  }
1146
0
        if (r2->x2 == x2)
1147
0
        {
1148
0
            r2++;
1149
0
  }
1150
0
    }
1151
0
    while ((r1 != r1_end) && (r2 != r2_end));
1152
1153
0
    return TRUE;
1154
0
}
Unexecuted instantiation: pixman-region32.c:pixman_region_intersect_o
Unexecuted instantiation: pixman-region16.c:pixman_region_intersect_o
1155
1156
PIXMAN_EXPORT pixman_bool_t
1157
PREFIX (_intersect) (region_type_t *     new_reg,
1158
                     const region_type_t *        reg1,
1159
                     const region_type_t *        reg2)
1160
0
{
1161
0
    GOOD (reg1);
1162
0
    GOOD (reg2);
1163
0
    GOOD (new_reg);
1164
1165
    /* check for trivial reject */
1166
0
    if (PIXREGION_NIL (reg1) || PIXREGION_NIL (reg2) ||
1167
0
        !EXTENTCHECK (&reg1->extents, &reg2->extents))
1168
0
    {
1169
        /* Covers about 20% of all cases */
1170
0
        FREE_DATA (new_reg);
1171
0
        new_reg->extents.x2 = new_reg->extents.x1;
1172
0
        new_reg->extents.y2 = new_reg->extents.y1;
1173
0
        if (PIXREGION_NAR (reg1) || PIXREGION_NAR (reg2))
1174
0
        {
1175
0
            new_reg->data = pixman_broken_data;
1176
0
            return FALSE;
1177
0
  }
1178
0
        else
1179
0
  {
1180
0
      new_reg->data = pixman_region_empty_data;
1181
0
  }
1182
0
    }
1183
0
    else if (!reg1->data && !reg2->data)
1184
0
    {
1185
        /* Covers about 80% of cases that aren't trivially rejected */
1186
0
        new_reg->extents.x1 = MAX (reg1->extents.x1, reg2->extents.x1);
1187
0
        new_reg->extents.y1 = MAX (reg1->extents.y1, reg2->extents.y1);
1188
0
        new_reg->extents.x2 = MIN (reg1->extents.x2, reg2->extents.x2);
1189
0
        new_reg->extents.y2 = MIN (reg1->extents.y2, reg2->extents.y2);
1190
1191
0
        FREE_DATA (new_reg);
1192
1193
0
  new_reg->data = (region_data_type_t *)NULL;
1194
0
    }
1195
0
    else if (!reg2->data && SUBSUMES (&reg2->extents, &reg1->extents))
1196
0
    {
1197
0
        return PREFIX (_copy) (new_reg, reg1);
1198
0
    }
1199
0
    else if (!reg1->data && SUBSUMES (&reg1->extents, &reg2->extents))
1200
0
    {
1201
0
        return PREFIX (_copy) (new_reg, reg2);
1202
0
    }
1203
0
    else if (reg1 == reg2)
1204
0
    {
1205
0
        return PREFIX (_copy) (new_reg, reg1);
1206
0
    }
1207
0
    else
1208
0
    {
1209
        /* General purpose intersection */
1210
1211
0
        if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE))
1212
0
      return FALSE;
1213
  
1214
0
        pixman_set_extents (new_reg);
1215
0
    }
1216
1217
0
    GOOD (new_reg);
1218
0
    return(TRUE);
1219
0
}
Unexecuted instantiation: pixman_region32_intersect
Unexecuted instantiation: pixman_region_intersect
1220
1221
#define MERGERECT(r)              \
1222
22.1k
    do                  \
1223
22.1k
    {                 \
1224
22.1k
        if (r->x1 <= x2)           \
1225
22.1k
  {               \
1226
22.1k
            /* Merge with current rectangle */        \
1227
22.1k
            if (x2 < r->x2)           \
1228
22.1k
    x2 = r->x2;           \
1229
22.1k
  }                \
1230
22.1k
  else                \
1231
22.1k
  {               \
1232
37
            /* Add current rectangle, start new one */      \
1233
37
            NEWRECT (region, next_rect, x1, y1, x2, y2);   \
1234
37
            x1 = r->x1;             \
1235
37
            x2 = r->x2;             \
1236
37
  }                \
1237
22.1k
        r++;                \
1238
22.1k
    } while (0)
1239
1240
/*======================================================================
1241
 *      Region Union
1242
 *====================================================================*/
1243
1244
/*-
1245
 *-----------------------------------------------------------------------
1246
 * pixman_region_union_o --
1247
 *  Handle an overlapping band for the union operation. Picks the
1248
 *  left-most rectangle each time and merges it into the region.
1249
 *
1250
 * Results:
1251
 *  TRUE if successful.
1252
 *
1253
 * Side Effects:
1254
 *  region is overwritten.
1255
 *  overlap is set to TRUE if any boxes overlap.
1256
 *
1257
 *-----------------------------------------------------------------------
1258
 */
1259
static pixman_bool_t
1260
pixman_region_union_o (region_type_t *region,
1261
           box_type_t *   r1,
1262
           box_type_t *   r1_end,
1263
           box_type_t *   r2,
1264
           box_type_t *   r2_end,
1265
           int            y1,
1266
           int            y2)
1267
22.1k
{
1268
22.1k
    box_type_t *next_rect;
1269
22.1k
    int x1;            /* left and right side of current union */
1270
22.1k
    int x2;
1271
1272
22.1k
    critical_if_fail (y1 < y2);
1273
22.1k
    critical_if_fail (r1 != r1_end && r2 != r2_end);
1274
1275
22.1k
    next_rect = PIXREGION_TOP (region);
1276
1277
    /* Start off current rectangle */
1278
22.1k
    if (r1->x1 < r2->x1)
1279
21.8k
    {
1280
21.8k
        x1 = r1->x1;
1281
21.8k
        x2 = r1->x2;
1282
21.8k
        r1++;
1283
21.8k
    }
1284
340
    else
1285
340
    {
1286
340
        x1 = r2->x1;
1287
340
        x2 = r2->x2;
1288
340
        r2++;
1289
340
    }
1290
22.1k
    while (r1 != r1_end && r2 != r2_end)
1291
8
    {
1292
8
        if (r1->x1 < r2->x1)
1293
0
      MERGERECT (r1);
1294
8
  else
1295
8
      MERGERECT (r2);
1296
8
    }
1297
1298
    /* Finish off whoever (if any) is left */
1299
22.1k
    if (r1 != r1_end)
1300
348
    {
1301
348
        do
1302
356
        {
1303
356
            MERGERECT (r1);
1304
356
  }
1305
356
        while (r1 != r1_end);
1306
348
    }
1307
21.8k
    else if (r2 != r2_end)
1308
21.8k
    {
1309
21.8k
        do
1310
21.8k
        {
1311
21.8k
            MERGERECT (r2);
1312
21.8k
  }
1313
21.8k
        while (r2 != r2_end);
1314
21.8k
    }
1315
1316
    /* Add current rectangle */
1317
22.1k
    NEWRECT (region, next_rect, x1, y1, x2, y2);
1318
1319
22.1k
    return TRUE;
1320
22.1k
}
pixman-region32.c:pixman_region_union_o
Line
Count
Source
1267
22.1k
{
1268
22.1k
    box_type_t *next_rect;
1269
22.1k
    int x1;            /* left and right side of current union */
1270
22.1k
    int x2;
1271
1272
22.1k
    critical_if_fail (y1 < y2);
1273
22.1k
    critical_if_fail (r1 != r1_end && r2 != r2_end);
1274
1275
22.1k
    next_rect = PIXREGION_TOP (region);
1276
1277
    /* Start off current rectangle */
1278
22.1k
    if (r1->x1 < r2->x1)
1279
21.8k
    {
1280
21.8k
        x1 = r1->x1;
1281
21.8k
        x2 = r1->x2;
1282
21.8k
        r1++;
1283
21.8k
    }
1284
340
    else
1285
340
    {
1286
340
        x1 = r2->x1;
1287
340
        x2 = r2->x2;
1288
340
        r2++;
1289
340
    }
1290
22.1k
    while (r1 != r1_end && r2 != r2_end)
1291
8
    {
1292
8
        if (r1->x1 < r2->x1)
1293
0
      MERGERECT (r1);
1294
8
  else
1295
8
      MERGERECT (r2);
1296
8
    }
1297
1298
    /* Finish off whoever (if any) is left */
1299
22.1k
    if (r1 != r1_end)
1300
348
    {
1301
348
        do
1302
356
        {
1303
356
            MERGERECT (r1);
1304
356
  }
1305
356
        while (r1 != r1_end);
1306
348
    }
1307
21.8k
    else if (r2 != r2_end)
1308
21.8k
    {
1309
21.8k
        do
1310
21.8k
        {
1311
21.8k
            MERGERECT (r2);
1312
21.8k
  }
1313
21.8k
        while (r2 != r2_end);
1314
21.8k
    }
1315
1316
    /* Add current rectangle */
1317
22.1k
    NEWRECT (region, next_rect, x1, y1, x2, y2);
1318
1319
22.1k
    return TRUE;
1320
22.1k
}
Unexecuted instantiation: pixman-region16.c:pixman_region_union_o
1321
1322
PIXMAN_EXPORT pixman_bool_t
1323
PREFIX(_intersect_rect) (region_type_t *dest,
1324
       const region_type_t *source,
1325
       int x, int y,
1326
       unsigned int width,
1327
       unsigned int height)
1328
0
{
1329
0
    region_type_t region;
1330
1331
0
    region.data = NULL;
1332
0
    region.extents.x1 = x;
1333
0
    region.extents.y1 = y;
1334
0
    region.extents.x2 = x + width;
1335
0
    region.extents.y2 = y + height;
1336
1337
0
    return PREFIX(_intersect) (dest, source, &region);
1338
0
}
Unexecuted instantiation: pixman_region32_intersect_rect
Unexecuted instantiation: pixman_region_intersect_rect
1339
1340
/* Convenience function for performing union of region with a
1341
 * single rectangle
1342
 */
1343
PIXMAN_EXPORT pixman_bool_t
1344
PREFIX (_union_rect) (region_type_t *dest,
1345
                      const region_type_t *source,
1346
                      int            x,
1347
          int            y,
1348
                      unsigned int   width,
1349
          unsigned int   height)
1350
0
{
1351
0
    region_type_t region;
1352
1353
0
    region.extents.x1 = x;
1354
0
    region.extents.y1 = y;
1355
0
    region.extents.x2 = x + width;
1356
0
    region.extents.y2 = y + height;
1357
1358
0
    if (!GOOD_RECT (&region.extents))
1359
0
    {
1360
0
        if (BAD_RECT (&region.extents))
1361
0
            _pixman_log_error (FUNC, "Invalid rectangle passed");
1362
0
  return PREFIX (_copy) (dest, source);
1363
0
    }
1364
1365
0
    region.data = NULL;
1366
1367
0
    return PREFIX (_union) (dest, source, &region);
1368
0
}
Unexecuted instantiation: pixman_region32_union_rect
Unexecuted instantiation: pixman_region_union_rect
1369
1370
PIXMAN_EXPORT pixman_bool_t
1371
PREFIX (_union) (region_type_t *      new_reg,
1372
                 const region_type_t *reg1,
1373
                 const region_type_t *reg2)
1374
499k
{
1375
    /* Return TRUE if some overlap
1376
     * between reg1, reg2
1377
     */
1378
499k
    GOOD (reg1);
1379
499k
    GOOD (reg2);
1380
499k
    GOOD (new_reg);
1381
1382
    /*  checks all the simple cases */
1383
1384
    /*
1385
     * Region 1 and 2 are the same
1386
     */
1387
499k
    if (reg1 == reg2)
1388
0
        return PREFIX (_copy) (new_reg, reg1);
1389
1390
    /*
1391
     * Region 1 is empty
1392
     */
1393
499k
    if (PIXREGION_NIL (reg1))
1394
1.09k
    {
1395
1.09k
        if (PIXREGION_NAR (reg1))
1396
0
      return pixman_break (new_reg);
1397
1398
1.09k
        if (new_reg != reg2)
1399
1.09k
      return PREFIX (_copy) (new_reg, reg2);
1400
1401
0
  return TRUE;
1402
1.09k
    }
1403
1404
    /*
1405
     * Region 2 is empty
1406
     */
1407
498k
    if (PIXREGION_NIL (reg2))
1408
0
    {
1409
0
        if (PIXREGION_NAR (reg2))
1410
0
      return pixman_break (new_reg);
1411
1412
0
  if (new_reg != reg1)
1413
0
      return PREFIX (_copy) (new_reg, reg1);
1414
1415
0
  return TRUE;
1416
0
    }
1417
1418
    /*
1419
     * Region 1 completely subsumes region 2
1420
     */
1421
498k
    if (!reg1->data && SUBSUMES (&reg1->extents, &reg2->extents))
1422
476k
    {
1423
476k
        if (new_reg != reg1)
1424
0
      return PREFIX (_copy) (new_reg, reg1);
1425
1426
476k
  return TRUE;
1427
476k
    }
1428
1429
    /*
1430
     * Region 2 completely subsumes region 1
1431
     */
1432
21.8k
    if (!reg2->data && SUBSUMES (&reg2->extents, &reg1->extents))
1433
1
    {
1434
1
        if (new_reg != reg2)
1435
1
      return PREFIX (_copy) (new_reg, reg2);
1436
1437
0
  return TRUE;
1438
1
    }
1439
1440
21.8k
    if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE))
1441
0
  return FALSE;
1442
1443
21.8k
    new_reg->extents.x1 = MIN (reg1->extents.x1, reg2->extents.x1);
1444
21.8k
    new_reg->extents.y1 = MIN (reg1->extents.y1, reg2->extents.y1);
1445
21.8k
    new_reg->extents.x2 = MAX (reg1->extents.x2, reg2->extents.x2);
1446
21.8k
    new_reg->extents.y2 = MAX (reg1->extents.y2, reg2->extents.y2);
1447
    
1448
21.8k
    GOOD (new_reg);
1449
1450
21.8k
    return TRUE;
1451
21.8k
}
pixman_region32_union
Line
Count
Source
1374
499k
{
1375
    /* Return TRUE if some overlap
1376
     * between reg1, reg2
1377
     */
1378
499k
    GOOD (reg1);
1379
499k
    GOOD (reg2);
1380
499k
    GOOD (new_reg);
1381
1382
    /*  checks all the simple cases */
1383
1384
    /*
1385
     * Region 1 and 2 are the same
1386
     */
1387
499k
    if (reg1 == reg2)
1388
0
        return PREFIX (_copy) (new_reg, reg1);
1389
1390
    /*
1391
     * Region 1 is empty
1392
     */
1393
499k
    if (PIXREGION_NIL (reg1))
1394
1.09k
    {
1395
1.09k
        if (PIXREGION_NAR (reg1))
1396
0
      return pixman_break (new_reg);
1397
1398
1.09k
        if (new_reg != reg2)
1399
1.09k
      return PREFIX (_copy) (new_reg, reg2);
1400
1401
0
  return TRUE;
1402
1.09k
    }
1403
1404
    /*
1405
     * Region 2 is empty
1406
     */
1407
498k
    if (PIXREGION_NIL (reg2))
1408
0
    {
1409
0
        if (PIXREGION_NAR (reg2))
1410
0
      return pixman_break (new_reg);
1411
1412
0
  if (new_reg != reg1)
1413
0
      return PREFIX (_copy) (new_reg, reg1);
1414
1415
0
  return TRUE;
1416
0
    }
1417
1418
    /*
1419
     * Region 1 completely subsumes region 2
1420
     */
1421
498k
    if (!reg1->data && SUBSUMES (&reg1->extents, &reg2->extents))
1422
476k
    {
1423
476k
        if (new_reg != reg1)
1424
0
      return PREFIX (_copy) (new_reg, reg1);
1425
1426
476k
  return TRUE;
1427
476k
    }
1428
1429
    /*
1430
     * Region 2 completely subsumes region 1
1431
     */
1432
21.8k
    if (!reg2->data && SUBSUMES (&reg2->extents, &reg1->extents))
1433
1
    {
1434
1
        if (new_reg != reg2)
1435
1
      return PREFIX (_copy) (new_reg, reg2);
1436
1437
0
  return TRUE;
1438
1
    }
1439
1440
21.8k
    if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE))
1441
0
  return FALSE;
1442
1443
21.8k
    new_reg->extents.x1 = MIN (reg1->extents.x1, reg2->extents.x1);
1444
21.8k
    new_reg->extents.y1 = MIN (reg1->extents.y1, reg2->extents.y1);
1445
21.8k
    new_reg->extents.x2 = MAX (reg1->extents.x2, reg2->extents.x2);
1446
21.8k
    new_reg->extents.y2 = MAX (reg1->extents.y2, reg2->extents.y2);
1447
    
1448
21.8k
    GOOD (new_reg);
1449
1450
21.8k
    return TRUE;
1451
21.8k
}
Unexecuted instantiation: pixman_region_union
1452
1453
/*======================================================================
1454
 *      Batch Rectangle Union
1455
 *====================================================================*/
1456
1457
#define EXCHANGE_RECTS(a, b)  \
1458
0
    {                           \
1459
0
        box_type_t t;   \
1460
0
        t = rects[a];           \
1461
0
        rects[a] = rects[b];    \
1462
0
        rects[b] = t;           \
1463
0
    }
1464
1465
static void
1466
quick_sort_rects (
1467
    box_type_t rects[],
1468
    int        numRects)
1469
0
{
1470
0
    int y1;
1471
0
    int x1;
1472
0
    int i, j;
1473
0
    box_type_t *r;
1474
1475
    /* Always called with numRects > 1 */
1476
1477
0
    do
1478
0
    {
1479
0
        if (numRects == 2)
1480
0
        {
1481
0
            if (rects[0].y1 > rects[1].y1 ||
1482
0
                (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
1483
0
      {
1484
0
    EXCHANGE_RECTS (0, 1);
1485
0
      }
1486
1487
0
            return;
1488
0
  }
1489
1490
        /* Choose partition element, stick in location 0 */
1491
0
        EXCHANGE_RECTS (0, numRects >> 1);
1492
0
        y1 = rects[0].y1;
1493
0
        x1 = rects[0].x1;
1494
1495
        /* Partition array */
1496
0
        i = 0;
1497
0
        j = numRects;
1498
1499
0
        do
1500
0
        {
1501
0
            r = &(rects[i]);
1502
0
            do
1503
0
            {
1504
0
                r++;
1505
0
                i++;
1506
0
      }
1507
0
      while (i != numRects && (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
1508
1509
0
      r = &(rects[j]);
1510
0
            do
1511
0
            {
1512
0
                r--;
1513
0
                j--;
1514
0
      }
1515
0
            while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
1516
      
1517
0
            if (i < j)
1518
0
    EXCHANGE_RECTS (i, j);
1519
0
  }
1520
0
        while (i < j);
1521
1522
        /* Move partition element back to middle */
1523
0
        EXCHANGE_RECTS (0, j);
1524
1525
        /* Recurse */
1526
0
        if (numRects - j - 1 > 1)
1527
0
      quick_sort_rects (&rects[j + 1], numRects - j - 1);
1528
1529
0
        numRects = j;
1530
0
    }
1531
0
    while (numRects > 1);
1532
0
}
Unexecuted instantiation: pixman-region32.c:quick_sort_rects
Unexecuted instantiation: pixman-region16.c:quick_sort_rects
1533
1534
/*-
1535
 *-----------------------------------------------------------------------
1536
 * pixman_region_validate --
1537
 *
1538
 *      Take a ``region'' which is a non-y-x-banded random collection of
1539
 *      rectangles, and compute a nice region which is the union of all the
1540
 *      rectangles.
1541
 *
1542
 * Results:
1543
 *  TRUE if successful.
1544
 *
1545
 * Side Effects:
1546
 *      The passed-in ``region'' may be modified.
1547
 *  overlap set to TRUE if any retangles overlapped,
1548
 *      else FALSE;
1549
 *
1550
 * Strategy:
1551
 *      Step 1. Sort the rectangles into ascending order with primary key y1
1552
 *    and secondary key x1.
1553
 *
1554
 *      Step 2. Split the rectangles into the minimum number of proper y-x
1555
 *    banded regions.  This may require horizontally merging
1556
 *    rectangles, and vertically coalescing bands.  With any luck,
1557
 *    this step in an identity transformation (ala the Box widget),
1558
 *    or a coalescing into 1 box (ala Menus).
1559
 *
1560
 *  Step 3. Merge the separate regions down to a single region by calling
1561
 *    pixman_region_union.  Maximize the work each pixman_region_union call does by using
1562
 *    a binary merge.
1563
 *
1564
 *-----------------------------------------------------------------------
1565
 */
1566
1567
static pixman_bool_t
1568
validate (region_type_t * badreg)
1569
0
{
1570
    /* Descriptor for regions under construction  in Step 2. */
1571
0
    typedef struct
1572
0
    {
1573
0
        region_type_t reg;
1574
0
        int prev_band;
1575
0
        int cur_band;
1576
0
    } region_info_t;
1577
1578
0
    region_info_t stack_regions[64];
1579
1580
0
    int numRects;                   /* Original numRects for badreg     */
1581
0
    region_info_t *ri;              /* Array of current regions       */
1582
0
    int num_ri;                     /* Number of entries used in ri     */
1583
0
    int size_ri;                    /* Number of entries available in ri    */
1584
0
    int i;                          /* Index into rects         */
1585
0
    int j;                          /* Index into ri          */
1586
0
    region_info_t *rit;             /* &ri[j]           */
1587
0
    region_type_t *reg;             /* ri[j].reg          */
1588
0
    box_type_t *box;                /* Current box in rects       */
1589
0
    box_type_t *ri_box;             /* Last box in ri[j].reg        */
1590
0
    region_type_t *hreg;            /* ri[j_half].reg         */
1591
0
    pixman_bool_t ret = TRUE;
1592
1593
0
    if (!badreg->data)
1594
0
    {
1595
0
        GOOD (badreg);
1596
0
        return TRUE;
1597
0
    }
1598
    
1599
0
    numRects = badreg->data->numRects;
1600
0
    if (!numRects)
1601
0
    {
1602
0
        if (PIXREGION_NAR (badreg))
1603
0
      return FALSE;
1604
0
        GOOD (badreg);
1605
0
        return TRUE;
1606
0
    }
1607
    
1608
0
    if (badreg->extents.x1 < badreg->extents.x2)
1609
0
    {
1610
0
        if ((numRects) == 1)
1611
0
        {
1612
0
            FREE_DATA (badreg);
1613
0
            badreg->data = (region_data_type_t *) NULL;
1614
0
  }
1615
0
        else
1616
0
        {
1617
0
            DOWNSIZE (badreg, numRects);
1618
0
  }
1619
1620
0
        GOOD (badreg);
1621
1622
0
  return TRUE;
1623
0
    }
1624
1625
    /* Step 1: Sort the rects array into ascending (y1, x1) order */
1626
0
    quick_sort_rects (PIXREGION_BOXPTR (badreg), numRects);
1627
1628
    /* Step 2: Scatter the sorted array into the minimum number of regions */
1629
1630
    /* Set up the first region to be the first rectangle in badreg */
1631
    /* Note that step 2 code will never overflow the ri[0].reg rects array */
1632
0
    ri = stack_regions;
1633
0
    size_ri = sizeof (stack_regions) / sizeof (stack_regions[0]);
1634
0
    num_ri = 1;
1635
0
    ri[0].prev_band = 0;
1636
0
    ri[0].cur_band = 0;
1637
0
    ri[0].reg = *badreg;
1638
0
    box = PIXREGION_BOXPTR (&ri[0].reg);
1639
0
    ri[0].reg.extents = *box;
1640
0
    ri[0].reg.data->numRects = 1;
1641
0
    badreg->extents = *pixman_region_empty_box;
1642
0
    badreg->data = pixman_region_empty_data;
1643
1644
    /* Now scatter rectangles into the minimum set of valid regions.  If the
1645
     * next rectangle to be added to a region would force an existing rectangle
1646
     * in the region to be split up in order to maintain y-x banding, just
1647
     * forget it.  Try the next region.  If it doesn't fit cleanly into any
1648
     * region, make a new one.
1649
     */
1650
1651
0
    for (i = numRects; --i > 0;)
1652
0
    {
1653
0
        box++;
1654
        /* Look for a region to append box to */
1655
0
        for (j = num_ri, rit = ri; --j >= 0; rit++)
1656
0
        {
1657
0
            reg = &rit->reg;
1658
0
            ri_box = PIXREGION_END (reg);
1659
1660
0
            if (box->y1 == ri_box->y1 && box->y2 == ri_box->y2)
1661
0
            {
1662
                /* box is in same band as ri_box.  Merge or append it */
1663
0
                if (box->x1 <= ri_box->x2)
1664
0
                {
1665
                    /* Merge it with ri_box */
1666
0
                    if (box->x2 > ri_box->x2)
1667
0
      ri_box->x2 = box->x2;
1668
0
    }
1669
0
                else
1670
0
                {
1671
0
                    RECTALLOC_BAIL (reg, 1, bail);
1672
0
                    *PIXREGION_TOP (reg) = *box;
1673
0
                    reg->data->numRects++;
1674
0
    }
1675
    
1676
0
                goto next_rect;   /* So sue me */
1677
0
      }
1678
0
            else if (box->y1 >= ri_box->y2)
1679
0
            {
1680
                /* Put box into new band */
1681
0
                if (reg->extents.x2 < ri_box->x2)
1682
0
        reg->extents.x2 = ri_box->x2;
1683
    
1684
0
                if (reg->extents.x1 > box->x1)
1685
0
        reg->extents.x1 = box->x1;
1686
    
1687
0
                COALESCE (reg, rit->prev_band, rit->cur_band);
1688
0
                rit->cur_band = reg->data->numRects;
1689
0
                RECTALLOC_BAIL (reg, 1, bail);
1690
0
                *PIXREGION_TOP (reg) = *box;
1691
0
                reg->data->numRects++;
1692
1693
0
                goto next_rect;
1694
0
      }
1695
            /* Well, this region was inappropriate.  Try the next one. */
1696
0
  } /* for j */
1697
1698
        /* Uh-oh.  No regions were appropriate.  Create a new one. */
1699
0
        if (size_ri == num_ri)
1700
0
        {
1701
0
            size_t data_size;
1702
1703
            /* Oops, allocate space for new region information */
1704
0
            size_ri <<= 1;
1705
1706
0
            data_size = size_ri * sizeof(region_info_t);
1707
0
            if (data_size / size_ri != sizeof(region_info_t))
1708
0
    goto bail;
1709
1710
0
            if (ri == stack_regions)
1711
0
            {
1712
0
                rit = malloc (data_size);
1713
0
                if (!rit)
1714
0
        goto bail;
1715
0
                memcpy (rit, ri, num_ri * sizeof (region_info_t));
1716
0
      }
1717
0
            else
1718
0
            {
1719
0
                rit = (region_info_t *) realloc (ri, data_size);
1720
0
                if (!rit)
1721
0
        goto bail;
1722
0
      }
1723
0
            ri = rit;
1724
0
            rit = &ri[num_ri];
1725
0
  }
1726
0
        num_ri++;
1727
0
        rit->prev_band = 0;
1728
0
        rit->cur_band = 0;
1729
0
        rit->reg.extents = *box;
1730
0
        rit->reg.data = (region_data_type_t *)NULL;
1731
1732
  /* MUST force allocation */
1733
0
        if (!pixman_rect_alloc (&rit->reg, (i + num_ri) / num_ri))
1734
0
      goto bail;
1735
  
1736
0
    next_rect: ;
1737
0
    } /* for i */
1738
1739
    /* Make a final pass over each region in order to COALESCE and set
1740
     * extents.x2 and extents.y2
1741
     */
1742
0
    for (j = num_ri, rit = ri; --j >= 0; rit++)
1743
0
    {
1744
0
        reg = &rit->reg;
1745
0
        ri_box = PIXREGION_END (reg);
1746
0
        reg->extents.y2 = ri_box->y2;
1747
1748
0
        if (reg->extents.x2 < ri_box->x2)
1749
0
      reg->extents.x2 = ri_box->x2;
1750
  
1751
0
        COALESCE (reg, rit->prev_band, rit->cur_band);
1752
1753
0
  if (reg->data->numRects == 1) /* keep unions happy below */
1754
0
        {
1755
0
            FREE_DATA (reg);
1756
0
            reg->data = (region_data_type_t *)NULL;
1757
0
  }
1758
0
    }
1759
1760
    /* Step 3: Union all regions into a single region */
1761
0
    while (num_ri > 1)
1762
0
    {
1763
0
        int half = num_ri / 2;
1764
0
        for (j = num_ri & 1; j < (half + (num_ri & 1)); j++)
1765
0
        {
1766
0
            reg = &ri[j].reg;
1767
0
            hreg = &ri[j + half].reg;
1768
1769
0
            if (!pixman_op (reg, reg, hreg, pixman_region_union_o, TRUE, TRUE))
1770
0
    ret = FALSE;
1771
1772
0
            if (hreg->extents.x1 < reg->extents.x1)
1773
0
    reg->extents.x1 = hreg->extents.x1;
1774
1775
0
            if (hreg->extents.y1 < reg->extents.y1)
1776
0
    reg->extents.y1 = hreg->extents.y1;
1777
1778
0
            if (hreg->extents.x2 > reg->extents.x2)
1779
0
    reg->extents.x2 = hreg->extents.x2;
1780
1781
0
            if (hreg->extents.y2 > reg->extents.y2)
1782
0
    reg->extents.y2 = hreg->extents.y2;
1783
1784
0
            FREE_DATA (hreg);
1785
0
  }
1786
1787
0
        num_ri -= half;
1788
1789
0
  if (!ret)
1790
0
      goto bail;
1791
0
    }
1792
1793
0
    *badreg = ri[0].reg;
1794
1795
0
    if (ri != stack_regions)
1796
0
  free (ri);
1797
1798
0
    GOOD (badreg);
1799
0
    return ret;
1800
1801
0
bail:
1802
0
    for (i = 0; i < num_ri; i++)
1803
0
  FREE_DATA (&ri[i].reg);
1804
1805
0
    if (ri != stack_regions)
1806
0
  free (ri);
1807
1808
0
    return pixman_break (badreg);
1809
0
}
Unexecuted instantiation: pixman-region32.c:validate
Unexecuted instantiation: pixman-region16.c:validate
1810
1811
/*======================================================================
1812
 *                Region Subtraction
1813
 *====================================================================*/
1814
1815
/*-
1816
 *-----------------------------------------------------------------------
1817
 * pixman_region_subtract_o --
1818
 *  Overlapping band subtraction. x1 is the left-most point not yet
1819
 *  checked.
1820
 *
1821
 * Results:
1822
 *  TRUE if successful.
1823
 *
1824
 * Side Effects:
1825
 *  region may have rectangles added to it.
1826
 *
1827
 *-----------------------------------------------------------------------
1828
 */
1829
/*ARGSUSED*/
1830
static pixman_bool_t
1831
pixman_region_subtract_o (region_type_t * region,
1832
        box_type_t *    r1,
1833
        box_type_t *    r1_end,
1834
        box_type_t *    r2,
1835
        box_type_t *    r2_end,
1836
        int             y1,
1837
        int             y2)
1838
0
{
1839
0
    box_type_t *        next_rect;
1840
0
    int x1;
1841
1842
0
    x1 = r1->x1;
1843
1844
0
    critical_if_fail (y1 < y2);
1845
0
    critical_if_fail (r1 != r1_end && r2 != r2_end);
1846
1847
0
    next_rect = PIXREGION_TOP (region);
1848
1849
0
    do
1850
0
    {
1851
0
        if (r2->x2 <= x1)
1852
0
        {
1853
            /*
1854
       * Subtrahend entirely to left of minuend: go to next subtrahend.
1855
       */
1856
0
            r2++;
1857
0
  }
1858
0
        else if (r2->x1 <= x1)
1859
0
        {
1860
            /*
1861
       * Subtrahend precedes minuend: nuke left edge of minuend.
1862
       */
1863
0
            x1 = r2->x2;
1864
0
            if (x1 >= r1->x2)
1865
0
            {
1866
                /*
1867
     * Minuend completely covered: advance to next minuend and
1868
     * reset left fence to edge of new minuend.
1869
     */
1870
0
                r1++;
1871
0
                if (r1 != r1_end)
1872
0
        x1 = r1->x1;
1873
0
      }
1874
0
            else
1875
0
            {
1876
                /*
1877
     * Subtrahend now used up since it doesn't extend beyond
1878
     * minuend
1879
     */
1880
0
                r2++;
1881
0
      }
1882
0
  }
1883
0
        else if (r2->x1 < r1->x2)
1884
0
        {
1885
            /*
1886
       * Left part of subtrahend covers part of minuend: add uncovered
1887
       * part of minuend to region and skip to next subtrahend.
1888
       */
1889
0
            critical_if_fail (x1 < r2->x1);
1890
0
            NEWRECT (region, next_rect, x1, y1, r2->x1, y2);
1891
1892
0
            x1 = r2->x2;
1893
0
            if (x1 >= r1->x2)
1894
0
            {
1895
                /*
1896
     * Minuend used up: advance to new...
1897
     */
1898
0
                r1++;
1899
0
                if (r1 != r1_end)
1900
0
        x1 = r1->x1;
1901
0
      }
1902
0
            else
1903
0
            {
1904
                /*
1905
     * Subtrahend used up
1906
     */
1907
0
                r2++;
1908
0
      }
1909
0
  }
1910
0
        else
1911
0
        {
1912
            /*
1913
       * Minuend used up: add any remaining piece before advancing.
1914
       */
1915
0
            if (r1->x2 > x1)
1916
0
    NEWRECT (region, next_rect, x1, y1, r1->x2, y2);
1917
1918
0
            r1++;
1919
1920
0
      if (r1 != r1_end)
1921
0
    x1 = r1->x1;
1922
0
  }
1923
0
    }
1924
0
    while ((r1 != r1_end) && (r2 != r2_end));
1925
1926
    /*
1927
     * Add remaining minuend rectangles to region.
1928
     */
1929
0
    while (r1 != r1_end)
1930
0
    {
1931
0
        critical_if_fail (x1 < r1->x2);
1932
1933
0
        NEWRECT (region, next_rect, x1, y1, r1->x2, y2);
1934
1935
0
        r1++;
1936
0
        if (r1 != r1_end)
1937
0
      x1 = r1->x1;
1938
0
    }
1939
0
    return TRUE;
1940
0
}
Unexecuted instantiation: pixman-region32.c:pixman_region_subtract_o
Unexecuted instantiation: pixman-region16.c:pixman_region_subtract_o
1941
1942
/*-
1943
 *-----------------------------------------------------------------------
1944
 * pixman_region_subtract --
1945
 *  Subtract reg_s from reg_m and leave the result in reg_d.
1946
 *  S stands for subtrahend, M for minuend and D for difference.
1947
 *
1948
 * Results:
1949
 *  TRUE if successful.
1950
 *
1951
 * Side Effects:
1952
 *  reg_d is overwritten.
1953
 *
1954
 *-----------------------------------------------------------------------
1955
 */
1956
PIXMAN_EXPORT pixman_bool_t
1957
PREFIX (_subtract) (region_type_t *      reg_d,
1958
                    const region_type_t *reg_m,
1959
                    const region_type_t *reg_s)
1960
0
{
1961
0
    GOOD (reg_m);
1962
0
    GOOD (reg_s);
1963
0
    GOOD (reg_d);
1964
    
1965
    /* check for trivial rejects */
1966
0
    if (PIXREGION_NIL (reg_m) || PIXREGION_NIL (reg_s) ||
1967
0
        !EXTENTCHECK (&reg_m->extents, &reg_s->extents))
1968
0
    {
1969
0
        if (PIXREGION_NAR (reg_s))
1970
0
      return pixman_break (reg_d);
1971
  
1972
0
        return PREFIX (_copy) (reg_d, reg_m);
1973
0
    }
1974
0
    else if (reg_m == reg_s)
1975
0
    {
1976
0
        FREE_DATA (reg_d);
1977
0
        reg_d->extents.x2 = reg_d->extents.x1;
1978
0
        reg_d->extents.y2 = reg_d->extents.y1;
1979
0
        reg_d->data = pixman_region_empty_data;
1980
1981
0
        return TRUE;
1982
0
    }
1983
1984
    /* Add those rectangles in region 1 that aren't in region 2,
1985
       do yucky subtraction for overlaps, and
1986
       just throw away rectangles in region 2 that aren't in region 1 */
1987
0
    if (!pixman_op (reg_d, reg_m, reg_s, pixman_region_subtract_o, TRUE, FALSE))
1988
0
  return FALSE;
1989
1990
    /*
1991
     * Can't alter reg_d's extents before we call pixman_op because
1992
     * it might be one of the source regions and pixman_op depends
1993
     * on the extents of those regions being unaltered. Besides, this
1994
     * way there's no checking against rectangles that will be nuked
1995
     * due to coalescing, so we have to examine fewer rectangles.
1996
     */
1997
0
    pixman_set_extents (reg_d);
1998
0
    GOOD (reg_d);
1999
0
    return TRUE;
2000
0
}
Unexecuted instantiation: pixman_region32_subtract
Unexecuted instantiation: pixman_region_subtract
2001
2002
/*======================================================================
2003
 *      Region Inversion
2004
 *====================================================================*/
2005
2006
/*-
2007
 *-----------------------------------------------------------------------
2008
 * pixman_region_inverse --
2009
 *  Take a region and a box and return a region that is everything
2010
 *  in the box but not in the region. The careful reader will note
2011
 *  that this is the same as subtracting the region from the box...
2012
 *
2013
 * Results:
2014
 *  TRUE.
2015
 *
2016
 * Side Effects:
2017
 *  new_reg is overwritten.
2018
 *
2019
 *-----------------------------------------------------------------------
2020
 */
2021
PIXMAN_EXPORT pixman_bool_t
2022
PREFIX (_inverse) (region_type_t *      new_reg,  /* Destination region */
2023
       const region_type_t *reg1,     /* Region to invert */
2024
       const box_type_t *   inv_rect) /* Bounding box for inversion */
2025
0
{
2026
0
    region_type_t inv_reg; /* Quick and dirty region made from the
2027
          * bounding box */
2028
0
    GOOD (reg1);
2029
0
    GOOD (new_reg);
2030
    
2031
    /* check for trivial rejects */
2032
0
    if (PIXREGION_NIL (reg1) || !EXTENTCHECK (inv_rect, &reg1->extents))
2033
0
    {
2034
0
        if (PIXREGION_NAR (reg1))
2035
0
      return pixman_break (new_reg);
2036
  
2037
0
        new_reg->extents = *inv_rect;
2038
0
        FREE_DATA (new_reg);
2039
0
        new_reg->data = (region_data_type_t *)NULL;
2040
  
2041
0
        return TRUE;
2042
0
    }
2043
2044
    /* Add those rectangles in region 1 that aren't in region 2,
2045
     * do yucky subtraction for overlaps, and
2046
     * just throw away rectangles in region 2 that aren't in region 1
2047
     */
2048
0
    inv_reg.extents = *inv_rect;
2049
0
    inv_reg.data = (region_data_type_t *)NULL;
2050
0
    if (!pixman_op (new_reg, &inv_reg, reg1, pixman_region_subtract_o, TRUE, FALSE))
2051
0
  return FALSE;
2052
2053
    /*
2054
     * Can't alter new_reg's extents before we call pixman_op because
2055
     * it might be one of the source regions and pixman_op depends
2056
     * on the extents of those regions being unaltered. Besides, this
2057
     * way there's no checking against rectangles that will be nuked
2058
     * due to coalescing, so we have to examine fewer rectangles.
2059
     */
2060
0
    pixman_set_extents (new_reg);
2061
0
    GOOD (new_reg);
2062
0
    return TRUE;
2063
0
}
Unexecuted instantiation: pixman_region32_inverse
Unexecuted instantiation: pixman_region_inverse
2064
2065
/* In time O(log n), locate the first box whose y2 is greater than y.
2066
 * Return @end if no such box exists.
2067
 */
2068
static box_type_t *
2069
find_box_for_y (box_type_t *begin, box_type_t *end, int y)
2070
0
{
2071
0
    box_type_t *mid;
2072
2073
0
    if (end == begin)
2074
0
  return end;
2075
2076
0
    if (end - begin == 1)
2077
0
    {
2078
0
  if (begin->y2 > y)
2079
0
      return begin;
2080
0
  else
2081
0
      return end;
2082
0
    }
2083
2084
0
    mid = begin + (end - begin) / 2;
2085
0
    if (mid->y2 > y)
2086
0
    {
2087
  /* If no box is found in [begin, mid], the function
2088
   * will return @mid, which is then known to be the
2089
   * correct answer.
2090
   */
2091
0
  return find_box_for_y (begin, mid, y);
2092
0
    }
2093
0
    else
2094
0
    {
2095
0
  return find_box_for_y (mid, end, y);
2096
0
    }
2097
0
}
Unexecuted instantiation: pixman-region32.c:find_box_for_y
Unexecuted instantiation: pixman-region16.c:find_box_for_y
2098
2099
/*
2100
 *   rect_in(region, rect)
2101
 *   This routine takes a pointer to a region and a pointer to a box
2102
 *   and determines if the box is outside/inside/partly inside the region.
2103
 *
2104
 *   The idea is to travel through the list of rectangles trying to cover the
2105
 *   passed box with them. Anytime a piece of the rectangle isn't covered
2106
 *   by a band of rectangles, part_out is set TRUE. Any time a rectangle in
2107
 *   the region covers part of the box, part_in is set TRUE. The process ends
2108
 *   when either the box has been completely covered (we reached a band that
2109
 *   doesn't overlap the box, part_in is TRUE and part_out is false), the
2110
 *   box has been partially covered (part_in == part_out == TRUE -- because of
2111
 *   the banding, the first time this is true we know the box is only
2112
 *   partially in the region) or is outside the region (we reached a band
2113
 *   that doesn't overlap the box at all and part_in is false)
2114
 */
2115
PIXMAN_EXPORT pixman_region_overlap_t
2116
PREFIX (_contains_rectangle) (const region_type_t *  region,
2117
            const box_type_t *     prect)
2118
499k
{
2119
499k
    box_type_t *     pbox;
2120
499k
    box_type_t *     pbox_end;
2121
499k
    int part_in, part_out;
2122
499k
    int numRects;
2123
499k
    int x, y;
2124
2125
499k
    GOOD (region);
2126
2127
499k
    numRects = PIXREGION_NUMRECTS (region);
2128
2129
    /* useful optimization */
2130
499k
    if (!numRects || !EXTENTCHECK (&region->extents, prect))
2131
499k
  return(PIXMAN_REGION_OUT);
2132
2133
0
    if (numRects == 1)
2134
0
    {
2135
        /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */
2136
0
        if (SUBSUMES (&region->extents, prect))
2137
0
      return(PIXMAN_REGION_IN);
2138
0
        else
2139
0
      return(PIXMAN_REGION_PART);
2140
0
    }
2141
2142
0
    part_out = FALSE;
2143
0
    part_in = FALSE;
2144
2145
    /* (x,y) starts at upper left of rect, moving to the right and down */
2146
0
    x = prect->x1;
2147
0
    y = prect->y1;
2148
2149
    /* can stop when both part_out and part_in are TRUE, or we reach prect->y2 */
2150
0
    for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects;
2151
0
   pbox != pbox_end;
2152
0
   pbox++)
2153
0
    {
2154
  /* getting up to speed or skipping remainder of band */
2155
0
  if (pbox->y2 <= y)
2156
0
  {
2157
0
      if ((pbox = find_box_for_y (pbox, pbox_end, y)) == pbox_end)
2158
0
    break;
2159
0
  }
2160
2161
0
        if (pbox->y1 > y)
2162
0
        {
2163
0
            part_out = TRUE;     /* missed part of rectangle above */
2164
0
            if (part_in || (pbox->y1 >= prect->y2))
2165
0
    break;
2166
0
            y = pbox->y1;       /* x guaranteed to be == prect->x1 */
2167
0
  }
2168
2169
0
        if (pbox->x2 <= x)
2170
0
      continue;           /* not far enough over yet */
2171
2172
0
        if (pbox->x1 > x)
2173
0
        {
2174
0
            part_out = TRUE;     /* missed part of rectangle to left */
2175
0
            if (part_in)
2176
0
    break;
2177
0
  }
2178
2179
0
        if (pbox->x1 < prect->x2)
2180
0
        {
2181
0
            part_in = TRUE;      /* definitely overlap */
2182
0
            if (part_out)
2183
0
    break;
2184
0
  }
2185
2186
0
        if (pbox->x2 >= prect->x2)
2187
0
        {
2188
0
            y = pbox->y2;       /* finished with this band */
2189
0
            if (y >= prect->y2)
2190
0
    break;
2191
0
            x = prect->x1;      /* reset x out to left again */
2192
0
  }
2193
0
        else
2194
0
        {
2195
            /*
2196
       * Because boxes in a band are maximal width, if the first box
2197
       * to overlap the rectangle doesn't completely cover it in that
2198
       * band, the rectangle must be partially out, since some of it
2199
       * will be uncovered in that band. part_in will have been set true
2200
       * by now...
2201
       */
2202
0
            part_out = TRUE;
2203
0
            break;
2204
0
  }
2205
0
    }
2206
2207
0
    if (part_in)
2208
0
    {
2209
0
        if (y < prect->y2)
2210
0
      return PIXMAN_REGION_PART;
2211
0
        else
2212
0
      return PIXMAN_REGION_IN;
2213
0
    }
2214
0
    else
2215
0
    {
2216
0
        return PIXMAN_REGION_OUT;
2217
0
    }
2218
0
}
pixman_region32_contains_rectangle
Line
Count
Source
2118
499k
{
2119
499k
    box_type_t *     pbox;
2120
499k
    box_type_t *     pbox_end;
2121
499k
    int part_in, part_out;
2122
499k
    int numRects;
2123
499k
    int x, y;
2124
2125
499k
    GOOD (region);
2126
2127
499k
    numRects = PIXREGION_NUMRECTS (region);
2128
2129
    /* useful optimization */
2130
499k
    if (!numRects || !EXTENTCHECK (&region->extents, prect))
2131
499k
  return(PIXMAN_REGION_OUT);
2132
2133
0
    if (numRects == 1)
2134
0
    {
2135
        /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */
2136
0
        if (SUBSUMES (&region->extents, prect))
2137
0
      return(PIXMAN_REGION_IN);
2138
0
        else
2139
0
      return(PIXMAN_REGION_PART);
2140
0
    }
2141
2142
0
    part_out = FALSE;
2143
0
    part_in = FALSE;
2144
2145
    /* (x,y) starts at upper left of rect, moving to the right and down */
2146
0
    x = prect->x1;
2147
0
    y = prect->y1;
2148
2149
    /* can stop when both part_out and part_in are TRUE, or we reach prect->y2 */
2150
0
    for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects;
2151
0
   pbox != pbox_end;
2152
0
   pbox++)
2153
0
    {
2154
  /* getting up to speed or skipping remainder of band */
2155
0
  if (pbox->y2 <= y)
2156
0
  {
2157
0
      if ((pbox = find_box_for_y (pbox, pbox_end, y)) == pbox_end)
2158
0
    break;
2159
0
  }
2160
2161
0
        if (pbox->y1 > y)
2162
0
        {
2163
0
            part_out = TRUE;     /* missed part of rectangle above */
2164
0
            if (part_in || (pbox->y1 >= prect->y2))
2165
0
    break;
2166
0
            y = pbox->y1;       /* x guaranteed to be == prect->x1 */
2167
0
  }
2168
2169
0
        if (pbox->x2 <= x)
2170
0
      continue;           /* not far enough over yet */
2171
2172
0
        if (pbox->x1 > x)
2173
0
        {
2174
0
            part_out = TRUE;     /* missed part of rectangle to left */
2175
0
            if (part_in)
2176
0
    break;
2177
0
  }
2178
2179
0
        if (pbox->x1 < prect->x2)
2180
0
        {
2181
0
            part_in = TRUE;      /* definitely overlap */
2182
0
            if (part_out)
2183
0
    break;
2184
0
  }
2185
2186
0
        if (pbox->x2 >= prect->x2)
2187
0
        {
2188
0
            y = pbox->y2;       /* finished with this band */
2189
0
            if (y >= prect->y2)
2190
0
    break;
2191
0
            x = prect->x1;      /* reset x out to left again */
2192
0
  }
2193
0
        else
2194
0
        {
2195
            /*
2196
       * Because boxes in a band are maximal width, if the first box
2197
       * to overlap the rectangle doesn't completely cover it in that
2198
       * band, the rectangle must be partially out, since some of it
2199
       * will be uncovered in that band. part_in will have been set true
2200
       * by now...
2201
       */
2202
0
            part_out = TRUE;
2203
0
            break;
2204
0
  }
2205
0
    }
2206
2207
0
    if (part_in)
2208
0
    {
2209
0
        if (y < prect->y2)
2210
0
      return PIXMAN_REGION_PART;
2211
0
        else
2212
0
      return PIXMAN_REGION_IN;
2213
0
    }
2214
0
    else
2215
0
    {
2216
0
        return PIXMAN_REGION_OUT;
2217
0
    }
2218
0
}
Unexecuted instantiation: pixman_region_contains_rectangle
2219
2220
/* PREFIX(_translate) (region, x, y)
2221
 * translates in place
2222
 */
2223
2224
PIXMAN_EXPORT void
2225
PREFIX (_translate) (region_type_t *region, int x, int y)
2226
0
{
2227
0
    overflow_int_t x1, x2, y1, y2;
2228
0
    int nbox;
2229
0
    box_type_t * pbox;
2230
2231
0
    GOOD (region);
2232
2233
0
    if (x == 0 && y == 0)
2234
0
        return;
2235
2236
0
    region->extents.x1 = x1 = region->extents.x1 + x;
2237
0
    region->extents.y1 = y1 = region->extents.y1 + y;
2238
0
    region->extents.x2 = x2 = region->extents.x2 + x;
2239
0
    region->extents.y2 = y2 = region->extents.y2 + y;
2240
    
2241
0
    if (((x1 - PIXMAN_REGION_MIN) | (y1 - PIXMAN_REGION_MIN) | (PIXMAN_REGION_MAX - x2) | (PIXMAN_REGION_MAX - y2)) >= 0)
2242
0
    {
2243
0
        if (region->data && (nbox = region->data->numRects))
2244
0
        {
2245
0
            for (pbox = PIXREGION_BOXPTR (region); nbox--; pbox++)
2246
0
            {
2247
0
                pbox->x1 += x;
2248
0
                pbox->y1 += y;
2249
0
                pbox->x2 += x;
2250
0
                pbox->y2 += y;
2251
0
      }
2252
0
  }
2253
0
        return;
2254
0
    }
2255
2256
0
    if (((x2 - PIXMAN_REGION_MIN) | (y2 - PIXMAN_REGION_MIN) | (PIXMAN_REGION_MAX - x1) | (PIXMAN_REGION_MAX - y1)) <= 0)
2257
0
    {
2258
0
        region->extents.x2 = region->extents.x1;
2259
0
        region->extents.y2 = region->extents.y1;
2260
0
        FREE_DATA (region);
2261
0
        region->data = pixman_region_empty_data;
2262
0
        return;
2263
0
    }
2264
2265
0
    if (x1 < PIXMAN_REGION_MIN)
2266
0
  region->extents.x1 = PIXMAN_REGION_MIN;
2267
0
    else if (x2 > PIXMAN_REGION_MAX)
2268
0
  region->extents.x2 = PIXMAN_REGION_MAX;
2269
2270
0
    if (y1 < PIXMAN_REGION_MIN)
2271
0
  region->extents.y1 = PIXMAN_REGION_MIN;
2272
0
    else if (y2 > PIXMAN_REGION_MAX)
2273
0
  region->extents.y2 = PIXMAN_REGION_MAX;
2274
2275
0
    if (region->data && (nbox = region->data->numRects))
2276
0
    {
2277
0
        box_type_t * pbox_out;
2278
2279
0
        for (pbox_out = pbox = PIXREGION_BOXPTR (region); nbox--; pbox++)
2280
0
        {
2281
0
            pbox_out->x1 = x1 = pbox->x1 + x;
2282
0
            pbox_out->y1 = y1 = pbox->y1 + y;
2283
0
            pbox_out->x2 = x2 = pbox->x2 + x;
2284
0
            pbox_out->y2 = y2 = pbox->y2 + y;
2285
2286
0
            if (((x2 - PIXMAN_REGION_MIN) | (y2 - PIXMAN_REGION_MIN) |
2287
0
                 (PIXMAN_REGION_MAX - x1) | (PIXMAN_REGION_MAX - y1)) <= 0)
2288
0
            {
2289
0
                region->data->numRects--;
2290
0
                continue;
2291
0
      }
2292
2293
0
            if (x1 < PIXMAN_REGION_MIN)
2294
0
    pbox_out->x1 = PIXMAN_REGION_MIN;
2295
0
            else if (x2 > PIXMAN_REGION_MAX)
2296
0
    pbox_out->x2 = PIXMAN_REGION_MAX;
2297
2298
0
            if (y1 < PIXMAN_REGION_MIN)
2299
0
    pbox_out->y1 = PIXMAN_REGION_MIN;
2300
0
            else if (y2 > PIXMAN_REGION_MAX)
2301
0
    pbox_out->y2 = PIXMAN_REGION_MAX;
2302
2303
0
            pbox_out++;
2304
0
  }
2305
2306
0
        if (pbox_out != pbox)
2307
0
        {
2308
0
            if (region->data->numRects == 1)
2309
0
            {
2310
0
                region->extents = *PIXREGION_BOXPTR (region);
2311
0
                FREE_DATA (region);
2312
0
                region->data = (region_data_type_t *)NULL;
2313
0
      }
2314
0
            else
2315
0
      {
2316
0
    pixman_set_extents (region);
2317
0
      }
2318
0
  }
2319
0
    }
2320
2321
0
    GOOD (region);
2322
0
}
Unexecuted instantiation: pixman_region32_translate
Unexecuted instantiation: pixman_region_translate
2323
2324
PIXMAN_EXPORT void
2325
PREFIX (_reset) (region_type_t *region, const box_type_t *box)
2326
0
{
2327
0
    GOOD (region);
2328
2329
0
    critical_if_fail (GOOD_RECT (box));
2330
2331
0
    region->extents = *box;
2332
2333
0
    FREE_DATA (region);
2334
2335
0
    region->data = NULL;
2336
0
}
Unexecuted instantiation: pixman_region32_reset
Unexecuted instantiation: pixman_region_reset
2337
2338
PIXMAN_EXPORT void
2339
PREFIX (_clear) (region_type_t *region)
2340
0
{
2341
0
    GOOD (region);
2342
0
    FREE_DATA (region);
2343
2344
0
    region->extents = *pixman_region_empty_box;
2345
0
    region->data = pixman_region_empty_data;
2346
0
}
Unexecuted instantiation: pixman_region32_clear
Unexecuted instantiation: pixman_region_clear
2347
2348
/* box is "return" value */
2349
PIXMAN_EXPORT int
2350
PREFIX (_contains_point) (const region_type_t * region,
2351
                          int x, int y,
2352
                          box_type_t * box)
2353
0
{
2354
0
    box_type_t *pbox, *pbox_end;
2355
0
    int numRects;
2356
2357
0
    GOOD (region);
2358
0
    numRects = PIXREGION_NUMRECTS (region);
2359
2360
0
    if (!numRects || !INBOX (&region->extents, x, y))
2361
0
  return(FALSE);
2362
2363
0
    if (numRects == 1)
2364
0
    {
2365
0
        if (box)
2366
0
      *box = region->extents;
2367
2368
0
        return(TRUE);
2369
0
    }
2370
2371
0
    pbox = PIXREGION_BOXPTR (region);
2372
0
    pbox_end = pbox + numRects;
2373
2374
0
    pbox = find_box_for_y (pbox, pbox_end, y);
2375
2376
0
    for (;pbox != pbox_end; pbox++)
2377
0
    {
2378
0
        if ((y < pbox->y1) || (x < pbox->x1))
2379
0
      break;              /* missed it */
2380
2381
0
        if (x >= pbox->x2)
2382
0
      continue;           /* not there yet */
2383
2384
0
        if (box)
2385
0
      *box = *pbox;
2386
2387
0
        return(TRUE);
2388
0
    }
2389
2390
0
    return(FALSE);
2391
0
}
Unexecuted instantiation: pixman_region32_contains_point
Unexecuted instantiation: pixman_region_contains_point
2392
2393
PIXMAN_EXPORT int
2394
PREFIX (_empty) (const region_type_t * region)
2395
0
{
2396
0
    GOOD (region);
2397
2398
0
    return(PIXREGION_NIL (region));
2399
0
}
Unexecuted instantiation: pixman_region32_empty
Unexecuted instantiation: pixman_region_empty
2400
2401
PIXMAN_EXPORT int
2402
PREFIX (_not_empty) (const region_type_t * region)
2403
0
{
2404
0
    GOOD (region);
2405
2406
0
    return(!PIXREGION_NIL (region));
2407
0
}
Unexecuted instantiation: pixman_region32_not_empty
Unexecuted instantiation: pixman_region_not_empty
2408
2409
PIXMAN_EXPORT box_type_t *
2410
PREFIX (_extents) (const region_type_t * region)
2411
188
{
2412
188
    GOOD (region);
2413
2414
188
    return(box_type_t *)(&region->extents);
2415
188
}
pixman_region32_extents
Line
Count
Source
2411
188
{
2412
188
    GOOD (region);
2413
2414
188
    return(box_type_t *)(&region->extents);
2415
188
}
Unexecuted instantiation: pixman_region_extents
2416
2417
/*
2418
 * Clip a list of scanlines to a region.  The caller has allocated the
2419
 * space.  FSorted is non-zero if the scanline origins are in ascending order.
2420
 *
2421
 * returns the number of new, clipped scanlines.
2422
 */
2423
2424
PIXMAN_EXPORT pixman_bool_t
2425
PREFIX (_selfcheck) (region_type_t *reg)
2426
0
{
2427
0
    int i, numRects;
2428
2429
0
    if ((reg->extents.x1 > reg->extents.x2) ||
2430
0
        (reg->extents.y1 > reg->extents.y2))
2431
0
    {
2432
0
  return FALSE;
2433
0
    }
2434
2435
0
    numRects = PIXREGION_NUMRECTS (reg);
2436
0
    if (!numRects)
2437
0
    {
2438
0
  return ((reg->extents.x1 == reg->extents.x2) &&
2439
0
          (reg->extents.y1 == reg->extents.y2) &&
2440
0
          (reg->data->size || (reg->data == pixman_region_empty_data)));
2441
0
    }
2442
0
    else if (numRects == 1)
2443
0
    {
2444
0
  return (!reg->data);
2445
0
    }
2446
0
    else
2447
0
    {
2448
0
        box_type_t * pbox_p, * pbox_n;
2449
0
        box_type_t box;
2450
2451
0
        pbox_p = PIXREGION_RECTS (reg);
2452
0
        box = *pbox_p;
2453
0
        box.y2 = pbox_p[numRects - 1].y2;
2454
0
        pbox_n = pbox_p + 1;
2455
2456
0
        for (i = numRects; --i > 0; pbox_p++, pbox_n++)
2457
0
        {
2458
0
            if ((pbox_n->x1 >= pbox_n->x2) ||
2459
0
                (pbox_n->y1 >= pbox_n->y2))
2460
0
      {
2461
0
    return FALSE;
2462
0
      }
2463
2464
0
            if (pbox_n->x1 < box.x1)
2465
0
    box.x1 = pbox_n->x1;
2466
      
2467
0
            if (pbox_n->x2 > box.x2)
2468
0
    box.x2 = pbox_n->x2;
2469
      
2470
0
            if ((pbox_n->y1 < pbox_p->y1) ||
2471
0
                ((pbox_n->y1 == pbox_p->y1) &&
2472
0
                 ((pbox_n->x1 < pbox_p->x2) || (pbox_n->y2 != pbox_p->y2))))
2473
0
      {
2474
0
    return FALSE;
2475
0
      }
2476
0
  }
2477
2478
0
        return ((box.x1 == reg->extents.x1) &&
2479
0
                (box.x2 == reg->extents.x2) &&
2480
0
                (box.y1 == reg->extents.y1) &&
2481
0
                (box.y2 == reg->extents.y2));
2482
0
    }
2483
0
}
Unexecuted instantiation: pixman_region32_selfcheck
Unexecuted instantiation: pixman_region_selfcheck
2484
2485
PIXMAN_EXPORT pixman_bool_t
2486
PREFIX (_init_rects) (region_type_t *region,
2487
                      const box_type_t *boxes, int count)
2488
0
{
2489
0
    box_type_t *rects;
2490
0
    int displacement;
2491
0
    int i;
2492
2493
    /* if it's 1, then we just want to set the extents, so call
2494
     * the existing method. */
2495
0
    if (count == 1)
2496
0
    {
2497
0
        PREFIX (_init_rect) (region,
2498
0
                             boxes[0].x1,
2499
0
                             boxes[0].y1,
2500
0
                             boxes[0].x2 - boxes[0].x1,
2501
0
                             boxes[0].y2 - boxes[0].y1);
2502
0
        return TRUE;
2503
0
    }
2504
2505
0
    PREFIX (_init) (region);
2506
2507
    /* if it's 0, don't call pixman_rect_alloc -- 0 rectangles is
2508
     * a special case, and causing pixman_rect_alloc would cause
2509
     * us to leak memory (because the 0-rect case should be the
2510
     * static pixman_region_empty_data data).
2511
     */
2512
0
    if (count == 0)
2513
0
  return TRUE;
2514
2515
0
    if (!pixman_rect_alloc (region, count))
2516
0
  return FALSE;
2517
2518
0
    rects = PIXREGION_RECTS (region);
2519
2520
    /* Copy in the rects */
2521
0
    memcpy (rects, boxes, sizeof(box_type_t) * count);
2522
0
    region->data->numRects = count;
2523
2524
    /* Eliminate empty and malformed rectangles */
2525
0
    displacement = 0;
2526
2527
0
    for (i = 0; i < count; ++i)
2528
0
    {
2529
0
        box_type_t *box = &rects[i];
2530
2531
0
        if (box->x1 >= box->x2 || box->y1 >= box->y2)
2532
0
      displacement++;
2533
0
        else if (displacement)
2534
0
      rects[i - displacement] = rects[i];
2535
0
    }
2536
2537
0
    region->data->numRects -= displacement;
2538
2539
    /* If eliminating empty rectangles caused there
2540
     * to be only 0 or 1 rectangles, deal with that.
2541
     */
2542
0
    if (region->data->numRects == 0)
2543
0
    {
2544
0
        FREE_DATA (region);
2545
0
        PREFIX (_init) (region);
2546
2547
0
        return TRUE;
2548
0
    }
2549
2550
0
    if (region->data->numRects == 1)
2551
0
    {
2552
0
        region->extents = rects[0];
2553
2554
0
        FREE_DATA (region);
2555
0
        region->data = NULL;
2556
2557
0
        GOOD (region);
2558
2559
0
        return TRUE;
2560
0
    }
2561
2562
    /* Validate */
2563
0
    region->extents.x1 = region->extents.x2 = 0;
2564
2565
0
    return validate (region);
2566
0
}
Unexecuted instantiation: pixman_region32_init_rects
Unexecuted instantiation: pixman_region_init_rects
2567
2568
0
#define READ(_ptr) (*(_ptr))
2569
2570
static inline box_type_t *
2571
bitmap_addrect (region_type_t *reg,
2572
                box_type_t *r,
2573
                box_type_t **first_rect,
2574
                int rx1, int ry1,
2575
                int rx2, int ry2)
2576
0
{
2577
0
    if ((rx1 < rx2) && (ry1 < ry2) &&
2578
0
  (!(reg->data->numRects &&
2579
0
     ((r-1)->y1 == ry1) && ((r-1)->y2 == ry2) &&
2580
0
     ((r-1)->x1 <= rx1) && ((r-1)->x2 >= rx2))))
2581
0
    {
2582
0
  if (reg->data->numRects == reg->data->size)
2583
0
  {
2584
0
      if (!pixman_rect_alloc (reg, 1))
2585
0
    return NULL;
2586
0
      *first_rect = PIXREGION_BOXPTR(reg);
2587
0
      r = *first_rect + reg->data->numRects;
2588
0
  }
2589
0
  r->x1 = rx1;
2590
0
  r->y1 = ry1;
2591
0
  r->x2 = rx2;
2592
0
  r->y2 = ry2;
2593
0
  reg->data->numRects++;
2594
0
  if (r->x1 < reg->extents.x1)
2595
0
      reg->extents.x1 = r->x1;
2596
0
  if (r->x2 > reg->extents.x2)
2597
0
      reg->extents.x2 = r->x2;
2598
0
  r++;
2599
0
    }
2600
0
    return r;
2601
0
}
Unexecuted instantiation: pixman-region32.c:bitmap_addrect
Unexecuted instantiation: pixman-region16.c:bitmap_addrect
2602
2603
/* Convert bitmap clip mask into clipping region.
2604
 * First, goes through each line and makes boxes by noting the transitions
2605
 * from 0 to 1 and 1 to 0.
2606
 * Then it coalesces the current line with the previous if they have boxes
2607
 * at the same X coordinates.
2608
 * Stride is in number of uint32_t per line.
2609
 */
2610
PIXMAN_EXPORT void
2611
PREFIX (_init_from_image) (region_type_t *region,
2612
                           pixman_image_t *image)
2613
0
{
2614
0
    uint32_t mask0 = 0xffffffff & ~SCREEN_SHIFT_RIGHT(0xffffffff, 1);
2615
0
    box_type_t *first_rect, *rects, *prect_line_start;
2616
0
    box_type_t *old_rect, *new_rect;
2617
0
    uint32_t *pw, w, *pw_line, *pw_line_end;
2618
0
    int irect_prev_start, irect_line_start;
2619
0
    int h, base, rx1 = 0, crects;
2620
0
    int ib;
2621
0
    pixman_bool_t in_box, same;
2622
0
    int width, height, stride;
2623
2624
0
    PREFIX(_init) (region);
2625
2626
0
    critical_if_fail (region->data);
2627
2628
0
    return_if_fail (image->type == BITS);
2629
0
    return_if_fail (image->bits.format == PIXMAN_a1);
2630
2631
0
    pw_line = pixman_image_get_data (image);
2632
0
    width = pixman_image_get_width (image);
2633
0
    height = pixman_image_get_height (image);
2634
0
    stride = pixman_image_get_stride (image) / 4;
2635
2636
0
    first_rect = PIXREGION_BOXPTR(region);
2637
0
    rects = first_rect;
2638
2639
0
    region->extents.x1 = width - 1;
2640
0
    region->extents.x2 = 0;
2641
0
    irect_prev_start = -1;
2642
0
    for (h = 0; h < height; h++)
2643
0
    {
2644
0
        pw = pw_line;
2645
0
        pw_line += stride;
2646
0
        irect_line_start = rects - first_rect;
2647
2648
        /* If the Screen left most bit of the word is set, we're starting in
2649
         * a box */
2650
0
        if (READ(pw) & mask0)
2651
0
        {
2652
0
            in_box = TRUE;
2653
0
            rx1 = 0;
2654
0
        }
2655
0
        else
2656
0
        {
2657
0
            in_box = FALSE;
2658
0
        }
2659
2660
        /* Process all words which are fully in the pixmap */
2661
0
        pw_line_end = pw + (width >> 5);
2662
0
        for (base = 0; pw < pw_line_end; base += 32)
2663
0
        {
2664
0
            w = READ(pw++);
2665
0
            if (in_box)
2666
0
            {
2667
0
                if (!~w)
2668
0
                    continue;
2669
0
            }
2670
0
            else
2671
0
            {
2672
0
                if (!w)
2673
0
                    continue;
2674
0
            }
2675
0
            for (ib = 0; ib < 32; ib++)
2676
0
            {
2677
                /* If the Screen left most bit of the word is set, we're
2678
                 * starting a box */
2679
0
                if (w & mask0)
2680
0
                {
2681
0
                    if (!in_box)
2682
0
                    {
2683
0
                        rx1 = base + ib;
2684
                        /* start new box */
2685
0
                        in_box = TRUE;
2686
0
                    }
2687
0
                }
2688
0
                else
2689
0
                {
2690
0
                    if (in_box)
2691
0
                    {
2692
                        /* end box */
2693
0
                        rects = bitmap_addrect (region, rects, &first_rect,
2694
0
                                                rx1, h, base + ib, h + 1);
2695
0
                        if (rects == NULL)
2696
0
                            goto error;
2697
0
                        in_box = FALSE;
2698
0
                    }
2699
0
                }
2700
                /* Shift the word VISUALLY left one. */
2701
0
                w = SCREEN_SHIFT_LEFT(w, 1);
2702
0
            }
2703
0
        }
2704
2705
0
        if (width & 31)
2706
0
        {
2707
            /* Process final partial word on line */
2708
0
             w = READ(pw++);
2709
0
            for (ib = 0; ib < (width & 31); ib++)
2710
0
            {
2711
                /* If the Screen left most bit of the word is set, we're
2712
                 * starting a box */
2713
0
                if (w & mask0)
2714
0
                {
2715
0
                    if (!in_box)
2716
0
                    {
2717
0
                        rx1 = base + ib;
2718
                        /* start new box */
2719
0
                        in_box = TRUE;
2720
0
                    }
2721
0
                }
2722
0
                else
2723
0
                {
2724
0
                    if (in_box)
2725
0
                    {
2726
                        /* end box */
2727
0
                        rects = bitmap_addrect(region, rects, &first_rect,
2728
0
                 rx1, h, base + ib, h + 1);
2729
0
      if (rects == NULL)
2730
0
          goto error;
2731
0
                        in_box = FALSE;
2732
0
                    }
2733
0
                }
2734
                /* Shift the word VISUALLY left one. */
2735
0
                w = SCREEN_SHIFT_LEFT(w, 1);
2736
0
            }
2737
0
        }
2738
        /* If scanline ended with last bit set, end the box */
2739
0
        if (in_box)
2740
0
        {
2741
0
            rects = bitmap_addrect(region, rects, &first_rect,
2742
0
           rx1, h, base + (width & 31), h + 1);
2743
0
      if (rects == NULL)
2744
0
    goto error;
2745
0
        }
2746
        /* if all rectangles on this line have the same x-coords as
2747
         * those on the previous line, then add 1 to all the previous  y2s and
2748
         * throw away all the rectangles from this line
2749
         */
2750
0
        same = FALSE;
2751
0
        if (irect_prev_start != -1)
2752
0
        {
2753
0
            crects = irect_line_start - irect_prev_start;
2754
0
            if (crects != 0 &&
2755
0
                crects == ((rects - first_rect) - irect_line_start))
2756
0
            {
2757
0
                old_rect = first_rect + irect_prev_start;
2758
0
                new_rect = prect_line_start = first_rect + irect_line_start;
2759
0
                same = TRUE;
2760
0
                while (old_rect < prect_line_start)
2761
0
                {
2762
0
                    if ((old_rect->x1 != new_rect->x1) ||
2763
0
                        (old_rect->x2 != new_rect->x2))
2764
0
                    {
2765
0
                          same = FALSE;
2766
0
                          break;
2767
0
                    }
2768
0
                    old_rect++;
2769
0
                    new_rect++;
2770
0
                }
2771
0
                if (same)
2772
0
                {
2773
0
                    old_rect = first_rect + irect_prev_start;
2774
0
                    while (old_rect < prect_line_start)
2775
0
                    {
2776
0
                        old_rect->y2 += 1;
2777
0
                        old_rect++;
2778
0
                    }
2779
0
                    rects -= crects;
2780
0
                    region->data->numRects -= crects;
2781
0
                }
2782
0
            }
2783
0
        }
2784
0
        if(!same)
2785
0
            irect_prev_start = irect_line_start;
2786
0
    }
2787
0
    if (!region->data->numRects)
2788
0
    {
2789
0
        region->extents.x1 = region->extents.x2 = 0;
2790
0
    }
2791
0
    else
2792
0
    {
2793
0
        region->extents.y1 = PIXREGION_BOXPTR(region)->y1;
2794
0
        region->extents.y2 = PIXREGION_END(region)->y2;
2795
0
        if (region->data->numRects == 1)
2796
0
        {
2797
0
            free (region->data);
2798
0
            region->data = NULL;
2799
0
        }
2800
0
    }
2801
2802
0
 error:
2803
0
    return;
2804
0
}
Unexecuted instantiation: pixman_region32_init_from_image
Unexecuted instantiation: pixman_region_init_from_image