Coverage Report

Created: 2025-12-31 10:39

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