PageRenderTime 59ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/source/libs/pixman/pixman-0.32.4/pixman/pixman-region.c

https://bitbucket.org/minux/luatex
C | 1742 lines | 1066 code | 245 blank | 431 comment | 276 complexity | de113823ab8613a6aa2891e0e1845a2d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, LGPL-3.0, MIT, LGPL-2.0, Zlib
  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. #include <stdlib.h>
  66. #include <limits.h>
  67. #include <string.h>
  68. #include <stdio.h>
  69. #include "pixman-private.h"
  70. #define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects)
  71. /* not a region */
  72. #define PIXREGION_NAR(reg) ((reg)->data == pixman_broken_data)
  73. #define PIXREGION_NUMRECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)
  74. #define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0)
  75. #define PIXREGION_RECTS(reg) \
  76. ((reg)->data ? (box_type_t *)((reg)->data + 1) \
  77. : &(reg)->extents)
  78. #define PIXREGION_BOXPTR(reg) ((box_type_t *)((reg)->data + 1))
  79. #define PIXREGION_BOX(reg, i) (&PIXREGION_BOXPTR (reg)[i])
  80. #define PIXREGION_TOP(reg) PIXREGION_BOX (reg, (reg)->data->numRects)
  81. #define PIXREGION_END(reg) PIXREGION_BOX (reg, (reg)->data->numRects - 1)
  82. #define GOOD_RECT(rect) ((rect)->x1 < (rect)->x2 && (rect)->y1 < (rect)->y2)
  83. #define BAD_RECT(rect) ((rect)->x1 > (rect)->x2 || (rect)->y1 > (rect)->y2)
  84. #ifdef DEBUG
  85. #define GOOD(reg) \
  86. do \
  87. { \
  88. if (!PREFIX (_selfcheck (reg))) \
  89. _pixman_log_error (FUNC, "Malformed region " # reg); \
  90. } while (0)
  91. #else
  92. #define GOOD(reg)
  93. #endif
  94. static const box_type_t PREFIX (_empty_box_) = { 0, 0, 0, 0 };
  95. static const region_data_type_t PREFIX (_empty_data_) = { 0, 0 };
  96. #if defined (__llvm__) && !defined (__clang__)
  97. static const volatile region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
  98. #else
  99. static const region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
  100. #endif
  101. static box_type_t *pixman_region_empty_box =
  102. (box_type_t *)&PREFIX (_empty_box_);
  103. static region_data_type_t *pixman_region_empty_data =
  104. (region_data_type_t *)&PREFIX (_empty_data_);
  105. static region_data_type_t *pixman_broken_data =
  106. (region_data_type_t *)&PREFIX (_broken_data_);
  107. static pixman_bool_t
  108. pixman_break (region_type_t *region);
  109. /*
  110. * The functions in this file implement the Region abstraction used extensively
  111. * throughout the X11 sample server. A Region is simply a set of disjoint
  112. * (non-overlapping) rectangles, plus an "extent" rectangle which is the
  113. * smallest single rectangle that contains all the non-overlapping rectangles.
  114. *
  115. * A Region is implemented as a "y-x-banded" array of rectangles. This array
  116. * imposes two degrees of order. First, all rectangles are sorted by top side
  117. * y coordinate first (y1), and then by left side x coordinate (x1).
  118. *
  119. * Furthermore, the rectangles are grouped into "bands". Each rectangle in a
  120. * band has the same top y coordinate (y1), and each has the same bottom y
  121. * coordinate (y2). Thus all rectangles in a band differ only in their left
  122. * and right side (x1 and x2). Bands are implicit in the array of rectangles:
  123. * there is no separate list of band start pointers.
  124. *
  125. * The y-x band representation does not minimize rectangles. In particular,
  126. * if a rectangle vertically crosses a band (the rectangle has scanlines in
  127. * the y1 to y2 area spanned by the band), then the rectangle may be broken
  128. * down into two or more smaller rectangles stacked one atop the other.
  129. *
  130. * ----------- -----------
  131. * | | | | band 0
  132. * | | -------- ----------- --------
  133. * | | | | in y-x banded | | | | band 1
  134. * | | | | form is | | | |
  135. * ----------- | | ----------- --------
  136. * | | | | band 2
  137. * -------- --------
  138. *
  139. * An added constraint on the rectangles is that they must cover as much
  140. * horizontal area as possible: no two rectangles within a band are allowed
  141. * to touch.
  142. *
  143. * Whenever possible, bands will be merged together to cover a greater vertical
  144. * distance (and thus reduce the number of rectangles). Two bands can be merged
  145. * only if the bottom of one touches the top of the other and they have
  146. * rectangles in the same places (of the same width, of course).
  147. *
  148. * Adam de Boor wrote most of the original region code. Joel McCormack
  149. * substantially modified or rewrote most of the core arithmetic routines, and
  150. * added pixman_region_validate in order to support several speed improvements
  151. * to pixman_region_validate_tree. Bob Scheifler changed the representation
  152. * to be more compact when empty or a single rectangle, and did a bunch of
  153. * gratuitous reformatting. Carl Worth did further gratuitous reformatting
  154. * while re-merging the server and client region code into libpixregion.
  155. * Soren Sandmann did even more gratuitous reformatting.
  156. */
  157. /* true iff two Boxes overlap */
  158. #define EXTENTCHECK(r1, r2) \
  159. (!( ((r1)->x2 <= (r2)->x1) || \
  160. ((r1)->x1 >= (r2)->x2) || \
  161. ((r1)->y2 <= (r2)->y1) || \
  162. ((r1)->y1 >= (r2)->y2) ) )
  163. /* true iff (x,y) is in Box */
  164. #define INBOX(r, x, y) \
  165. ( ((r)->x2 > x) && \
  166. ((r)->x1 <= x) && \
  167. ((r)->y2 > y) && \
  168. ((r)->y1 <= y) )
  169. /* true iff Box r1 contains Box r2 */
  170. #define SUBSUMES(r1, r2) \
  171. ( ((r1)->x1 <= (r2)->x1) && \
  172. ((r1)->x2 >= (r2)->x2) && \
  173. ((r1)->y1 <= (r2)->y1) && \
  174. ((r1)->y2 >= (r2)->y2) )
  175. static size_t
  176. PIXREGION_SZOF (size_t n)
  177. {
  178. size_t size = n * sizeof(box_type_t);
  179. if (n > UINT32_MAX / sizeof(box_type_t))
  180. return 0;
  181. if (sizeof(region_data_type_t) > UINT32_MAX - size)
  182. return 0;
  183. return size + sizeof(region_data_type_t);
  184. }
  185. static region_data_type_t *
  186. alloc_data (size_t n)
  187. {
  188. size_t sz = PIXREGION_SZOF (n);
  189. if (!sz)
  190. return NULL;
  191. return malloc (sz);
  192. }
  193. #define FREE_DATA(reg) if ((reg)->data && (reg)->data->size) free ((reg)->data)
  194. #define RECTALLOC_BAIL(region, n, bail) \
  195. do \
  196. { \
  197. if (!(region)->data || \
  198. (((region)->data->numRects + (n)) > (region)->data->size)) \
  199. { \
  200. if (!pixman_rect_alloc (region, n)) \
  201. goto bail; \
  202. } \
  203. } while (0)
  204. #define RECTALLOC(region, n) \
  205. do \
  206. { \
  207. if (!(region)->data || \
  208. (((region)->data->numRects + (n)) > (region)->data->size)) \
  209. { \
  210. if (!pixman_rect_alloc (region, n)) { \
  211. return FALSE; \
  212. } \
  213. } \
  214. } while (0)
  215. #define ADDRECT(next_rect, nx1, ny1, nx2, ny2) \
  216. do \
  217. { \
  218. next_rect->x1 = nx1; \
  219. next_rect->y1 = ny1; \
  220. next_rect->x2 = nx2; \
  221. next_rect->y2 = ny2; \
  222. next_rect++; \
  223. } \
  224. while (0)
  225. #define NEWRECT(region, next_rect, nx1, ny1, nx2, ny2) \
  226. do \
  227. { \
  228. if (!(region)->data || \
  229. ((region)->data->numRects == (region)->data->size)) \
  230. { \
  231. if (!pixman_rect_alloc (region, 1)) \
  232. return FALSE; \
  233. next_rect = PIXREGION_TOP (region); \
  234. } \
  235. ADDRECT (next_rect, nx1, ny1, nx2, ny2); \
  236. region->data->numRects++; \
  237. critical_if_fail (region->data->numRects <= region->data->size); \
  238. } while (0)
  239. #define DOWNSIZE(reg, numRects) \
  240. do \
  241. { \
  242. if (((numRects) < ((reg)->data->size >> 1)) && \
  243. ((reg)->data->size > 50)) \
  244. { \
  245. region_data_type_t * new_data; \
  246. size_t data_size = PIXREGION_SZOF (numRects); \
  247. \
  248. if (!data_size) \
  249. { \
  250. new_data = NULL; \
  251. } \
  252. else \
  253. { \
  254. new_data = (region_data_type_t *) \
  255. realloc ((reg)->data, data_size); \
  256. } \
  257. \
  258. if (new_data) \
  259. { \
  260. new_data->size = (numRects); \
  261. (reg)->data = new_data; \
  262. } \
  263. } \
  264. } while (0)
  265. PIXMAN_EXPORT pixman_bool_t
  266. PREFIX (_equal) (region_type_t *reg1, region_type_t *reg2)
  267. {
  268. int i;
  269. box_type_t *rects1;
  270. box_type_t *rects2;
  271. if (reg1->extents.x1 != reg2->extents.x1)
  272. return FALSE;
  273. if (reg1->extents.x2 != reg2->extents.x2)
  274. return FALSE;
  275. if (reg1->extents.y1 != reg2->extents.y1)
  276. return FALSE;
  277. if (reg1->extents.y2 != reg2->extents.y2)
  278. return FALSE;
  279. if (PIXREGION_NUMRECTS (reg1) != PIXREGION_NUMRECTS (reg2))
  280. return FALSE;
  281. rects1 = PIXREGION_RECTS (reg1);
  282. rects2 = PIXREGION_RECTS (reg2);
  283. for (i = 0; i != PIXREGION_NUMRECTS (reg1); i++)
  284. {
  285. if (rects1[i].x1 != rects2[i].x1)
  286. return FALSE;
  287. if (rects1[i].x2 != rects2[i].x2)
  288. return FALSE;
  289. if (rects1[i].y1 != rects2[i].y1)
  290. return FALSE;
  291. if (rects1[i].y2 != rects2[i].y2)
  292. return FALSE;
  293. }
  294. return TRUE;
  295. }
  296. int
  297. PREFIX (_print) (region_type_t *rgn)
  298. {
  299. int num, size;
  300. int i;
  301. box_type_t * rects;
  302. num = PIXREGION_NUMRECTS (rgn);
  303. size = PIXREGION_SIZE (rgn);
  304. rects = PIXREGION_RECTS (rgn);
  305. fprintf (stderr, "num: %d size: %d\n", num, size);
  306. fprintf (stderr, "extents: %d %d %d %d\n",
  307. rgn->extents.x1,
  308. rgn->extents.y1,
  309. rgn->extents.x2,
  310. rgn->extents.y2);
  311. for (i = 0; i < num; i++)
  312. {
  313. fprintf (stderr, "%d %d %d %d \n",
  314. rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
  315. }
  316. fprintf (stderr, "\n");
  317. return(num);
  318. }
  319. PIXMAN_EXPORT void
  320. PREFIX (_init) (region_type_t *region)
  321. {
  322. region->extents = *pixman_region_empty_box;
  323. region->data = pixman_region_empty_data;
  324. }
  325. PIXMAN_EXPORT void
  326. PREFIX (_init_rect) (region_type_t * region,
  327. int x,
  328. int y,
  329. unsigned int width,
  330. unsigned int height)
  331. {
  332. region->extents.x1 = x;
  333. region->extents.y1 = y;
  334. region->extents.x2 = x + width;
  335. region->extents.y2 = y + height;
  336. if (!GOOD_RECT (&region->extents))
  337. {
  338. if (BAD_RECT (&region->extents))
  339. _pixman_log_error (FUNC, "Invalid rectangle passed");
  340. PREFIX (_init) (region);
  341. return;
  342. }
  343. region->data = NULL;
  344. }
  345. PIXMAN_EXPORT void
  346. PREFIX (_init_with_extents) (region_type_t *region, box_type_t *extents)
  347. {
  348. if (!GOOD_RECT (extents))
  349. {
  350. if (BAD_RECT (extents))
  351. _pixman_log_error (FUNC, "Invalid rectangle passed");
  352. PREFIX (_init) (region);
  353. return;
  354. }
  355. region->extents = *extents;
  356. region->data = NULL;
  357. }
  358. PIXMAN_EXPORT void
  359. PREFIX (_fini) (region_type_t *region)
  360. {
  361. GOOD (region);
  362. FREE_DATA (region);
  363. }
  364. PIXMAN_EXPORT int
  365. PREFIX (_n_rects) (region_type_t *region)
  366. {
  367. return PIXREGION_NUMRECTS (region);
  368. }
  369. PIXMAN_EXPORT box_type_t *
  370. PREFIX (_rectangles) (region_type_t *region,
  371. int *n_rects)
  372. {
  373. if (n_rects)
  374. *n_rects = PIXREGION_NUMRECTS (region);
  375. return PIXREGION_RECTS (region);
  376. }
  377. static pixman_bool_t
  378. pixman_break (region_type_t *region)
  379. {
  380. FREE_DATA (region);
  381. region->extents = *pixman_region_empty_box;
  382. region->data = pixman_broken_data;
  383. return FALSE;
  384. }
  385. static pixman_bool_t
  386. pixman_rect_alloc (region_type_t * region,
  387. int n)
  388. {
  389. region_data_type_t *data;
  390. if (!region->data)
  391. {
  392. n++;
  393. region->data = alloc_data (n);
  394. if (!region->data)
  395. return pixman_break (region);
  396. region->data->numRects = 1;
  397. *PIXREGION_BOXPTR (region) = region->extents;
  398. }
  399. else if (!region->data->size)
  400. {
  401. region->data = alloc_data (n);
  402. if (!region->data)
  403. return pixman_break (region);
  404. region->data->numRects = 0;
  405. }
  406. else
  407. {
  408. size_t data_size;
  409. if (n == 1)
  410. {
  411. n = region->data->numRects;
  412. if (n > 500) /* XXX pick numbers out of a hat */
  413. n = 250;
  414. }
  415. n += region->data->numRects;
  416. data_size = PIXREGION_SZOF (n);
  417. if (!data_size)
  418. {
  419. data = NULL;
  420. }
  421. else
  422. {
  423. data = (region_data_type_t *)
  424. realloc (region->data, PIXREGION_SZOF (n));
  425. }
  426. if (!data)
  427. return pixman_break (region);
  428. region->data = data;
  429. }
  430. region->data->size = n;
  431. return TRUE;
  432. }
  433. PIXMAN_EXPORT pixman_bool_t
  434. PREFIX (_copy) (region_type_t *dst, region_type_t *src)
  435. {
  436. GOOD (dst);
  437. GOOD (src);
  438. if (dst == src)
  439. return TRUE;
  440. dst->extents = src->extents;
  441. if (!src->data || !src->data->size)
  442. {
  443. FREE_DATA (dst);
  444. dst->data = src->data;
  445. return TRUE;
  446. }
  447. if (!dst->data || (dst->data->size < src->data->numRects))
  448. {
  449. FREE_DATA (dst);
  450. dst->data = alloc_data (src->data->numRects);
  451. if (!dst->data)
  452. return pixman_break (dst);
  453. dst->data->size = src->data->numRects;
  454. }
  455. dst->data->numRects = src->data->numRects;
  456. memmove ((char *)PIXREGION_BOXPTR (dst), (char *)PIXREGION_BOXPTR (src),
  457. dst->data->numRects * sizeof(box_type_t));
  458. return TRUE;
  459. }
  460. /*======================================================================
  461. * Generic Region Operator
  462. *====================================================================*/
  463. /*-
  464. *-----------------------------------------------------------------------
  465. * pixman_coalesce --
  466. * Attempt to merge the boxes in the current band with those in the
  467. * previous one. We are guaranteed that the current band extends to
  468. * the end of the rects array. Used only by pixman_op.
  469. *
  470. * Results:
  471. * The new index for the previous band.
  472. *
  473. * Side Effects:
  474. * If coalescing takes place:
  475. * - rectangles in the previous band will have their y2 fields
  476. * altered.
  477. * - region->data->numRects will be decreased.
  478. *
  479. *-----------------------------------------------------------------------
  480. */
  481. static inline int
  482. pixman_coalesce (region_type_t * region, /* Region to coalesce */
  483. int prev_start, /* Index of start of previous band */
  484. int cur_start) /* Index of start of current band */
  485. {
  486. box_type_t *prev_box; /* Current box in previous band */
  487. box_type_t *cur_box; /* Current box in current band */
  488. int numRects; /* Number rectangles in both bands */
  489. int y2; /* Bottom of current band */
  490. /*
  491. * Figure out how many rectangles are in the band.
  492. */
  493. numRects = cur_start - prev_start;
  494. critical_if_fail (numRects == region->data->numRects - cur_start);
  495. if (!numRects) return cur_start;
  496. /*
  497. * The bands may only be coalesced if the bottom of the previous
  498. * matches the top scanline of the current.
  499. */
  500. prev_box = PIXREGION_BOX (region, prev_start);
  501. cur_box = PIXREGION_BOX (region, cur_start);
  502. if (prev_box->y2 != cur_box->y1) return cur_start;
  503. /*
  504. * Make sure the bands have boxes in the same places. This
  505. * assumes that boxes have been added in such a way that they
  506. * cover the most area possible. I.e. two boxes in a band must
  507. * have some horizontal space between them.
  508. */
  509. y2 = cur_box->y2;
  510. do
  511. {
  512. if ((prev_box->x1 != cur_box->x1) || (prev_box->x2 != cur_box->x2))
  513. return (cur_start);
  514. prev_box++;
  515. cur_box++;
  516. numRects--;
  517. }
  518. while (numRects);
  519. /*
  520. * The bands may be merged, so set the bottom y of each box
  521. * in the previous band to the bottom y of the current band.
  522. */
  523. numRects = cur_start - prev_start;
  524. region->data->numRects -= numRects;
  525. do
  526. {
  527. prev_box--;
  528. prev_box->y2 = y2;
  529. numRects--;
  530. }
  531. while (numRects);
  532. return prev_start;
  533. }
  534. /* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */
  535. #define COALESCE(new_reg, prev_band, cur_band) \
  536. do \
  537. { \
  538. if (cur_band - prev_band == new_reg->data->numRects - cur_band) \
  539. prev_band = pixman_coalesce (new_reg, prev_band, cur_band); \
  540. else \
  541. prev_band = cur_band; \
  542. } while (0)
  543. /*-
  544. *-----------------------------------------------------------------------
  545. * pixman_region_append_non_o --
  546. * Handle a non-overlapping band for the union and subtract operations.
  547. * Just adds the (top/bottom-clipped) rectangles into the region.
  548. * Doesn't have to check for subsumption or anything.
  549. *
  550. * Results:
  551. * None.
  552. *
  553. * Side Effects:
  554. * region->data->numRects is incremented and the rectangles overwritten
  555. * with the rectangles we're passed.
  556. *
  557. *-----------------------------------------------------------------------
  558. */
  559. static inline pixman_bool_t
  560. pixman_region_append_non_o (region_type_t * region,
  561. box_type_t * r,
  562. box_type_t * r_end,
  563. int y1,
  564. int y2)
  565. {
  566. box_type_t *next_rect;
  567. int new_rects;
  568. new_rects = r_end - r;
  569. critical_if_fail (y1 < y2);
  570. critical_if_fail (new_rects != 0);
  571. /* Make sure we have enough space for all rectangles to be added */
  572. RECTALLOC (region, new_rects);
  573. next_rect = PIXREGION_TOP (region);
  574. region->data->numRects += new_rects;
  575. do
  576. {
  577. critical_if_fail (r->x1 < r->x2);
  578. ADDRECT (next_rect, r->x1, y1, r->x2, y2);
  579. r++;
  580. }
  581. while (r != r_end);
  582. return TRUE;
  583. }
  584. #define FIND_BAND(r, r_band_end, r_end, ry1) \
  585. do \
  586. { \
  587. ry1 = r->y1; \
  588. r_band_end = r + 1; \
  589. while ((r_band_end != r_end) && (r_band_end->y1 == ry1)) { \
  590. r_band_end++; \
  591. } \
  592. } while (0)
  593. #define APPEND_REGIONS(new_reg, r, r_end) \
  594. do \
  595. { \
  596. int new_rects; \
  597. if ((new_rects = r_end - r)) { \
  598. RECTALLOC_BAIL (new_reg, new_rects, bail); \
  599. memmove ((char *)PIXREGION_TOP (new_reg), (char *)r, \
  600. new_rects * sizeof(box_type_t)); \
  601. new_reg->data->numRects += new_rects; \
  602. } \
  603. } while (0)
  604. /*-
  605. *-----------------------------------------------------------------------
  606. * pixman_op --
  607. * Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse,
  608. * pixman_region_subtract, pixman_region_intersect.... Both regions MUST have at least one
  609. * rectangle, and cannot be the same object.
  610. *
  611. * Results:
  612. * TRUE if successful.
  613. *
  614. * Side Effects:
  615. * The new region is overwritten.
  616. * overlap set to TRUE if overlap_func ever returns TRUE.
  617. *
  618. * Notes:
  619. * The idea behind this function is to view the two regions as sets.
  620. * Together they cover a rectangle of area that this function divides
  621. * into horizontal bands where points are covered only by one region
  622. * or by both. For the first case, the non_overlap_func is called with
  623. * each the band and the band's upper and lower extents. For the
  624. * second, the overlap_func is called to process the entire band. It
  625. * is responsible for clipping the rectangles in the band, though
  626. * this function provides the boundaries.
  627. * At the end of each band, the new region is coalesced, if possible,
  628. * to reduce the number of rectangles in the region.
  629. *
  630. *-----------------------------------------------------------------------
  631. */
  632. typedef pixman_bool_t (*overlap_proc_ptr) (region_type_t *region,
  633. box_type_t * r1,
  634. box_type_t * r1_end,
  635. box_type_t * r2,
  636. box_type_t * r2_end,
  637. int y1,
  638. int y2);
  639. static pixman_bool_t
  640. pixman_op (region_type_t * new_reg, /* Place to store result */
  641. region_type_t * reg1, /* First region in operation */
  642. region_type_t * reg2, /* 2d region in operation */
  643. overlap_proc_ptr overlap_func, /* Function to call for over-
  644. * lapping bands */
  645. int append_non1, /* Append non-overlapping bands
  646. * in region 1 ?
  647. */
  648. int append_non2 /* Append non-overlapping bands
  649. * in region 2 ?
  650. */
  651. )
  652. {
  653. box_type_t *r1; /* Pointer into first region */
  654. box_type_t *r2; /* Pointer into 2d region */
  655. box_type_t *r1_end; /* End of 1st region */
  656. box_type_t *r2_end; /* End of 2d region */
  657. int ybot; /* Bottom of intersection */
  658. int ytop; /* Top of intersection */
  659. region_data_type_t *old_data; /* Old data for new_reg */
  660. int prev_band; /* Index of start of
  661. * previous band in new_reg */
  662. int cur_band; /* Index of start of current
  663. * band in new_reg */
  664. box_type_t * r1_band_end; /* End of current band in r1 */
  665. box_type_t * r2_band_end; /* End of current band in r2 */
  666. int top; /* Top of non-overlapping band */
  667. int bot; /* Bottom of non-overlapping band*/
  668. int r1y1; /* Temps for r1->y1 and r2->y1 */
  669. int r2y1;
  670. int new_size;
  671. int numRects;
  672. /*
  673. * Break any region computed from a broken region
  674. */
  675. if (PIXREGION_NAR (reg1) || PIXREGION_NAR (reg2))
  676. return pixman_break (new_reg);
  677. /*
  678. * Initialization:
  679. * set r1, r2, r1_end and r2_end appropriately, save the rectangles
  680. * of the destination region until the end in case it's one of
  681. * the two source regions, then mark the "new" region empty, allocating
  682. * another array of rectangles for it to use.
  683. */
  684. r1 = PIXREGION_RECTS (reg1);
  685. new_size = PIXREGION_NUMRECTS (reg1);
  686. r1_end = r1 + new_size;
  687. numRects = PIXREGION_NUMRECTS (reg2);
  688. r2 = PIXREGION_RECTS (reg2);
  689. r2_end = r2 + numRects;
  690. critical_if_fail (r1 != r1_end);
  691. critical_if_fail (r2 != r2_end);
  692. old_data = (region_data_type_t *)NULL;
  693. if (((new_reg == reg1) && (new_size > 1)) ||
  694. ((new_reg == reg2) && (numRects > 1)))
  695. {
  696. old_data = new_reg->data;
  697. new_reg->data = pixman_region_empty_data;
  698. }
  699. /* guess at new size */
  700. if (numRects > new_size)
  701. new_size = numRects;
  702. new_size <<= 1;
  703. if (!new_reg->data)
  704. new_reg->data = pixman_region_empty_data;
  705. else if (new_reg->data->size)
  706. new_reg->data->numRects = 0;
  707. if (new_size > new_reg->data->size)
  708. {
  709. if (!pixman_rect_alloc (new_reg, new_size))
  710. {
  711. free (old_data);
  712. return FALSE;
  713. }
  714. }
  715. /*
  716. * Initialize ybot.
  717. * In the upcoming loop, ybot and ytop serve different functions depending
  718. * on whether the band being handled is an overlapping or non-overlapping
  719. * band.
  720. * In the case of a non-overlapping band (only one of the regions
  721. * has points in the band), ybot is the bottom of the most recent
  722. * intersection and thus clips the top of the rectangles in that band.
  723. * ytop is the top of the next intersection between the two regions and
  724. * serves to clip the bottom of the rectangles in the current band.
  725. * For an overlapping band (where the two regions intersect), ytop clips
  726. * the top of the rectangles of both regions and ybot clips the bottoms.
  727. */
  728. ybot = MIN (r1->y1, r2->y1);
  729. /*
  730. * prev_band serves to mark the start of the previous band so rectangles
  731. * can be coalesced into larger rectangles. qv. pixman_coalesce, above.
  732. * In the beginning, there is no previous band, so prev_band == cur_band
  733. * (cur_band is set later on, of course, but the first band will always
  734. * start at index 0). prev_band and cur_band must be indices because of
  735. * the possible expansion, and resultant moving, of the new region's
  736. * array of rectangles.
  737. */
  738. prev_band = 0;
  739. do
  740. {
  741. /*
  742. * This algorithm proceeds one source-band (as opposed to a
  743. * destination band, which is determined by where the two regions
  744. * intersect) at a time. r1_band_end and r2_band_end serve to mark the
  745. * rectangle after the last one in the current band for their
  746. * respective regions.
  747. */
  748. critical_if_fail (r1 != r1_end);
  749. critical_if_fail (r2 != r2_end);
  750. FIND_BAND (r1, r1_band_end, r1_end, r1y1);
  751. FIND_BAND (r2, r2_band_end, r2_end, r2y1);
  752. /*
  753. * First handle the band that doesn't intersect, if any.
  754. *
  755. * Note that attention is restricted to one band in the
  756. * non-intersecting region at once, so if a region has n
  757. * bands between the current position and the next place it overlaps
  758. * the other, this entire loop will be passed through n times.
  759. */
  760. if (r1y1 < r2y1)
  761. {
  762. if (append_non1)
  763. {
  764. top = MAX (r1y1, ybot);
  765. bot = MIN (r1->y2, r2y1);
  766. if (top != bot)
  767. {
  768. cur_band = new_reg->data->numRects;
  769. if (!pixman_region_append_non_o (new_reg, r1, r1_band_end, top, bot))
  770. goto bail;
  771. COALESCE (new_reg, prev_band, cur_band);
  772. }
  773. }
  774. ytop = r2y1;
  775. }
  776. else if (r2y1 < r1y1)
  777. {
  778. if (append_non2)
  779. {
  780. top = MAX (r2y1, ybot);
  781. bot = MIN (r2->y2, r1y1);
  782. if (top != bot)
  783. {
  784. cur_band = new_reg->data->numRects;
  785. if (!pixman_region_append_non_o (new_reg, r2, r2_band_end, top, bot))
  786. goto bail;
  787. COALESCE (new_reg, prev_band, cur_band);
  788. }
  789. }
  790. ytop = r1y1;
  791. }
  792. else
  793. {
  794. ytop = r1y1;
  795. }
  796. /*
  797. * Now see if we've hit an intersecting band. The two bands only
  798. * intersect if ybot > ytop
  799. */
  800. ybot = MIN (r1->y2, r2->y2);
  801. if (ybot > ytop)
  802. {
  803. cur_band = new_reg->data->numRects;
  804. if (!(*overlap_func)(new_reg,
  805. r1, r1_band_end,
  806. r2, r2_band_end,
  807. ytop, ybot))
  808. {
  809. goto bail;
  810. }
  811. COALESCE (new_reg, prev_band, cur_band);
  812. }
  813. /*
  814. * If we've finished with a band (y2 == ybot) we skip forward
  815. * in the region to the next band.
  816. */
  817. if (r1->y2 == ybot)
  818. r1 = r1_band_end;
  819. if (r2->y2 == ybot)
  820. r2 = r2_band_end;
  821. }
  822. while (r1 != r1_end && r2 != r2_end);
  823. /*
  824. * Deal with whichever region (if any) still has rectangles left.
  825. *
  826. * We only need to worry about banding and coalescing for the very first
  827. * band left. After that, we can just group all remaining boxes,
  828. * regardless of how many bands, into one final append to the list.
  829. */
  830. if ((r1 != r1_end) && append_non1)
  831. {
  832. /* Do first non_overlap1Func call, which may be able to coalesce */
  833. FIND_BAND (r1, r1_band_end, r1_end, r1y1);
  834. cur_band = new_reg->data->numRects;
  835. if (!pixman_region_append_non_o (new_reg,
  836. r1, r1_band_end,
  837. MAX (r1y1, ybot), r1->y2))
  838. {
  839. goto bail;
  840. }
  841. COALESCE (new_reg, prev_band, cur_band);
  842. /* Just append the rest of the boxes */
  843. APPEND_REGIONS (new_reg, r1_band_end, r1_end);
  844. }
  845. else if ((r2 != r2_end) && append_non2)
  846. {
  847. /* Do first non_overlap2Func call, which may be able to coalesce */
  848. FIND_BAND (r2, r2_band_end, r2_end, r2y1);
  849. cur_band = new_reg->data->numRects;
  850. if (!pixman_region_append_non_o (new_reg,
  851. r2, r2_band_end,
  852. MAX (r2y1, ybot), r2->y2))
  853. {
  854. goto bail;
  855. }
  856. COALESCE (new_reg, prev_band, cur_band);
  857. /* Append rest of boxes */
  858. APPEND_REGIONS (new_reg, r2_band_end, r2_end);
  859. }
  860. free (old_data);
  861. if (!(numRects = new_reg->data->numRects))
  862. {
  863. FREE_DATA (new_reg);
  864. new_reg->data = pixman_region_empty_data;
  865. }
  866. else if (numRects == 1)
  867. {
  868. new_reg->extents = *PIXREGION_BOXPTR (new_reg);
  869. FREE_DATA (new_reg);
  870. new_reg->data = (region_data_type_t *)NULL;
  871. }
  872. else
  873. {
  874. DOWNSIZE (new_reg, numRects);
  875. }
  876. return TRUE;
  877. bail:
  878. free (old_data);
  879. return pixman_break (new_reg);
  880. }
  881. /*-
  882. *-----------------------------------------------------------------------
  883. * pixman_set_extents --
  884. * Reset the extents of a region to what they should be. Called by
  885. * pixman_region_subtract and pixman_region_intersect as they can't
  886. * figure it out along the way or do so easily, as pixman_region_union can.
  887. *
  888. * Results:
  889. * None.
  890. *
  891. * Side Effects:
  892. * The region's 'extents' structure is overwritten.
  893. *
  894. *-----------------------------------------------------------------------
  895. */
  896. static void
  897. pixman_set_extents (region_type_t *region)
  898. {
  899. box_type_t *box, *box_end;
  900. if (!region->data)
  901. return;
  902. if (!region->data->size)
  903. {
  904. region->extents.x2 = region->extents.x1;
  905. region->extents.y2 = region->extents.y1;
  906. return;
  907. }
  908. box = PIXREGION_BOXPTR (region);
  909. box_end = PIXREGION_END (region);
  910. /*
  911. * Since box is the first rectangle in the region, it must have the
  912. * smallest y1 and since box_end is the last rectangle in the region,
  913. * it must have the largest y2, because of banding. Initialize x1 and
  914. * x2 from box and box_end, resp., as good things to initialize them
  915. * to...
  916. */
  917. region->extents.x1 = box->x1;
  918. region->extents.y1 = box->y1;
  919. region->extents.x2 = box_end->x2;
  920. region->extents.y2 = box_end->y2;
  921. critical_if_fail (region->extents.y1 < region->extents.y2);
  922. while (box <= box_end)
  923. {
  924. if (box->x1 < region->extents.x1)
  925. region->extents.x1 = box->x1;
  926. if (box->x2 > region->extents.x2)
  927. region->extents.x2 = box->x2;
  928. box++;
  929. }
  930. critical_if_fail (region->extents.x1 < region->extents.x2);
  931. }
  932. /*======================================================================
  933. * Region Intersection
  934. *====================================================================*/
  935. /*-
  936. *-----------------------------------------------------------------------
  937. * pixman_region_intersect_o --
  938. * Handle an overlapping band for pixman_region_intersect.
  939. *
  940. * Results:
  941. * TRUE if successful.
  942. *
  943. * Side Effects:
  944. * Rectangles may be added to the region.
  945. *
  946. *-----------------------------------------------------------------------
  947. */
  948. /*ARGSUSED*/
  949. static pixman_bool_t
  950. pixman_region_intersect_o (region_type_t *region,
  951. box_type_t * r1,
  952. box_type_t * r1_end,
  953. box_type_t * r2,
  954. box_type_t * r2_end,
  955. int y1,
  956. int y2)
  957. {
  958. int x1;
  959. int x2;
  960. box_type_t * next_rect;
  961. next_rect = PIXREGION_TOP (region);
  962. critical_if_fail (y1 < y2);
  963. critical_if_fail (r1 != r1_end && r2 != r2_end);
  964. do
  965. {
  966. x1 = MAX (r1->x1, r2->x1);
  967. x2 = MIN (r1->x2, r2->x2);
  968. /*
  969. * If there's any overlap between the two rectangles, add that
  970. * overlap to the new region.
  971. */
  972. if (x1 < x2)
  973. NEWRECT (region, next_rect, x1, y1, x2, y2);
  974. /*
  975. * Advance the pointer(s) with the leftmost right side, since the next
  976. * rectangle on that list may still overlap the other region's
  977. * current rectangle.
  978. */
  979. if (r1->x2 == x2)
  980. {
  981. r1++;
  982. }
  983. if (r2->x2 == x2)
  984. {
  985. r2++;
  986. }
  987. }
  988. while ((r1 != r1_end) && (r2 != r2_end));
  989. return TRUE;
  990. }
  991. PIXMAN_EXPORT pixman_bool_t
  992. PREFIX (_intersect) (region_type_t * new_reg,
  993. region_type_t * reg1,
  994. region_type_t * reg2)
  995. {
  996. GOOD (reg1);
  997. GOOD (reg2);
  998. GOOD (new_reg);
  999. /* check for trivial reject */
  1000. if (PIXREGION_NIL (reg1) || PIXREGION_NIL (reg2) ||
  1001. !EXTENTCHECK (&reg1->extents, &reg2->extents))
  1002. {
  1003. /* Covers about 20% of all cases */
  1004. FREE_DATA (new_reg);
  1005. new_reg->extents.x2 = new_reg->extents.x1;
  1006. new_reg->extents.y2 = new_reg->extents.y1;
  1007. if (PIXREGION_NAR (reg1) || PIXREGION_NAR (reg2))
  1008. {
  1009. new_reg->data = pixman_broken_data;
  1010. return FALSE;
  1011. }
  1012. else
  1013. {
  1014. new_reg->data = pixman_region_empty_data;
  1015. }
  1016. }
  1017. else if (!reg1->data && !reg2->data)
  1018. {
  1019. /* Covers about 80% of cases that aren't trivially rejected */
  1020. new_reg->extents.x1 = MAX (reg1->extents.x1, reg2->extents.x1);
  1021. new_reg->extents.y1 = MAX (reg1->extents.y1, reg2->extents.y1);
  1022. new_reg->extents.x2 = MIN (reg1->extents.x2, reg2->extents.x2);
  1023. new_reg->extents.y2 = MIN (reg1->extents.y2, reg2->extents.y2);
  1024. FREE_DATA (new_reg);
  1025. new_reg->data = (region_data_type_t *)NULL;
  1026. }
  1027. else if (!reg2->data && SUBSUMES (&reg2->extents, &reg1->extents))
  1028. {
  1029. return PREFIX (_copy) (new_reg, reg1);
  1030. }
  1031. else if (!reg1->data && SUBSUMES (&reg1->extents, &reg2->extents))
  1032. {
  1033. return PREFIX (_copy) (new_reg, reg2);
  1034. }
  1035. else if (reg1 == reg2)
  1036. {
  1037. return PREFIX (_copy) (new_reg, reg1);
  1038. }
  1039. else
  1040. {
  1041. /* General purpose intersection */
  1042. if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE))
  1043. return FALSE;
  1044. pixman_set_extents (new_reg);
  1045. }
  1046. GOOD (new_reg);
  1047. return(TRUE);
  1048. }
  1049. #define MERGERECT(r) \
  1050. do \
  1051. { \
  1052. if (r->x1 <= x2) \
  1053. { \
  1054. /* Merge with current rectangle */ \
  1055. if (x2 < r->x2) \
  1056. x2 = r->x2; \
  1057. } \
  1058. else \
  1059. { \
  1060. /* Add current rectangle, start new one */ \
  1061. NEWRECT (region, next_rect, x1, y1, x2, y2); \
  1062. x1 = r->x1; \
  1063. x2 = r->x2; \
  1064. } \
  1065. r++; \
  1066. } while (0)
  1067. /*======================================================================
  1068. * Region Union
  1069. *====================================================================*/
  1070. /*-
  1071. *-----------------------------------------------------------------------
  1072. * pixman_region_union_o --
  1073. * Handle an overlapping band for the union operation. Picks the
  1074. * left-most rectangle each time and merges it into the region.
  1075. *
  1076. * Results:
  1077. * TRUE if successful.
  1078. *
  1079. * Side Effects:
  1080. * region is overwritten.
  1081. * overlap is set to TRUE if any boxes overlap.
  1082. *
  1083. *-----------------------------------------------------------------------
  1084. */
  1085. static pixman_bool_t
  1086. pixman_region_union_o (region_type_t *region,
  1087. box_type_t * r1,
  1088. box_type_t * r1_end,
  1089. box_type_t * r2,
  1090. box_type_t * r2_end,
  1091. int y1,
  1092. int y2)
  1093. {
  1094. box_type_t *next_rect;
  1095. int x1; /* left and right side of current union */
  1096. int x2;
  1097. critical_if_fail (y1 < y2);
  1098. critical_if_fail (r1 != r1_end && r2 != r2_end);
  1099. next_rect = PIXREGION_TOP (region);
  1100. /* Start off current rectangle */
  1101. if (r1->x1 < r2->x1)
  1102. {
  1103. x1 = r1->x1;
  1104. x2 = r1->x2;
  1105. r1++;
  1106. }
  1107. else
  1108. {
  1109. x1 = r2->x1;
  1110. x2 = r2->x2;
  1111. r2++;
  1112. }
  1113. while (r1 != r1_end && r2 != r2_end)
  1114. {
  1115. if (r1->x1 < r2->x1)
  1116. MERGERECT (r1);
  1117. else
  1118. MERGERECT (r2);
  1119. }
  1120. /* Finish off whoever (if any) is left */
  1121. if (r1 != r1_end)
  1122. {
  1123. do
  1124. {
  1125. MERGERECT (r1);
  1126. }
  1127. while (r1 != r1_end);
  1128. }
  1129. else if (r2 != r2_end)
  1130. {
  1131. do
  1132. {
  1133. MERGERECT (r2);
  1134. }
  1135. while (r2 != r2_end);
  1136. }
  1137. /* Add current rectangle */
  1138. NEWRECT (region, next_rect, x1, y1, x2, y2);
  1139. return TRUE;
  1140. }
  1141. PIXMAN_EXPORT pixman_bool_t
  1142. PREFIX(_intersect_rect) (region_type_t *dest,
  1143. region_type_t *source,
  1144. int x, int y,
  1145. unsigned int width,
  1146. unsigned int height)
  1147. {
  1148. region_type_t region;
  1149. region.data = NULL;
  1150. region.extents.x1 = x;
  1151. region.extents.y1 = y;
  1152. region.extents.x2 = x + width;
  1153. region.extents.y2 = y + height;
  1154. return PREFIX(_intersect) (dest, source, &region);
  1155. }
  1156. /* Convenience function for performing union of region with a
  1157. * single rectangle
  1158. */
  1159. PIXMAN_EXPORT pixman_bool_t
  1160. PREFIX (_union_rect) (region_type_t *dest,
  1161. region_type_t *source,
  1162. int x,
  1163. int y,
  1164. unsigned int width,
  1165. unsigned int height)
  1166. {
  1167. region_type_t region;
  1168. region.extents.x1 = x;
  1169. region.extents.y1 = y;
  1170. region.extents.x2 = x + width;
  1171. region.extents.y2 = y + height;
  1172. if (!GOOD_RECT (&region.extents))
  1173. {
  1174. if (BAD_RECT (&region.extents))
  1175. _pixman_log_error (FUNC, "Invalid rectangle passed");
  1176. return PREFIX (_copy) (dest, source);
  1177. }
  1178. region.data = NULL;
  1179. return PREFIX (_union) (dest, source, &region);
  1180. }
  1181. PIXMAN_EXPORT pixman_bool_t
  1182. PREFIX (_union) (region_type_t *new_reg,
  1183. region_type_t *reg1,
  1184. region_type_t *reg2)
  1185. {
  1186. /* Return TRUE if some overlap
  1187. * between reg1, reg2
  1188. */
  1189. GOOD (reg1);
  1190. GOOD (reg2);
  1191. GOOD (new_reg);
  1192. /* checks all the simple cases */
  1193. /*
  1194. * Region 1 and 2 are the same
  1195. */
  1196. if (reg1 == reg2)
  1197. return PREFIX (_copy) (new_reg, reg1);
  1198. /*
  1199. * Region 1 is empty
  1200. */
  1201. if (PIXREGION_NIL (reg1))
  1202. {
  1203. if (PIXREGION_NAR (reg1))
  1204. return pixman_break (new_reg);
  1205. if (new_reg != reg2)
  1206. return PREFIX (_copy) (new_reg, reg2);
  1207. return TRUE;
  1208. }
  1209. /*
  1210. * Region 2 is empty
  1211. */
  1212. if (PIXREGION_NIL (reg2))
  1213. {
  1214. if (PIXREGION_NAR (reg2))
  1215. return pixman_break (new_reg);
  1216. if (new_reg != reg1)
  1217. return PREFIX (_copy) (new_reg, reg1);
  1218. return TRUE;
  1219. }
  1220. /*
  1221. * Region 1 completely subsumes region 2
  1222. */
  1223. if (!reg1->data && SUBSUMES (&reg1->extents, &reg2->extents))
  1224. {
  1225. if (new_reg != reg1)
  1226. return PREFIX (_copy) (new_reg, reg1);
  1227. return TRUE;
  1228. }
  1229. /*
  1230. * Region 2 completely subsumes region 1
  1231. */
  1232. if (!reg2->data && SUBSUMES (&reg2->extents, &reg1->extents))
  1233. {
  1234. if (new_reg != reg2)
  1235. return PREFIX (_copy) (new_reg, reg2);
  1236. return TRUE;
  1237. }
  1238. if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE))
  1239. return FALSE;
  1240. new_reg->extents.x1 = MIN (reg1->extents.x1, reg2->extents.x1);
  1241. new_reg->extents.y1 = MIN (reg1->extents.y1, reg2->extents.y1);
  1242. new_reg->extents.x2 = MAX (reg1->extents.x2, reg2->extents.x2);
  1243. new_reg->extents.y2 = MAX (reg1->extents.y2, reg2->extents.y2);
  1244. GOOD (new_reg);
  1245. return TRUE;
  1246. }
  1247. /*======================================================================
  1248. * Batch Rectangle Union
  1249. *====================================================================*/
  1250. #define EXCHANGE_RECTS(a, b) \
  1251. { \
  1252. box_type_t t; \
  1253. t = rects[a]; \
  1254. rects[a] = rects[b]; \
  1255. rects[b] = t; \
  1256. }
  1257. static void
  1258. quick_sort_rects (
  1259. box_type_t rects[],
  1260. int numRects)
  1261. {
  1262. int y1;
  1263. int x1;
  1264. int i, j;
  1265. box_type_t *r;
  1266. /* Always called with numRects > 1 */
  1267. do
  1268. {
  1269. if (numRects == 2)
  1270. {
  1271. if (rects[0].y1 > rects[1].y1 ||
  1272. (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
  1273. {
  1274. EXCHANGE_RECTS (0, 1);
  1275. }
  1276. return;
  1277. }
  1278. /* Choose partition element, stick in location 0 */
  1279. EXCHANGE_RECTS (0, numRects >> 1);
  1280. y1 = rects[0].y1;
  1281. x1 = rects[0].x1;
  1282. /* Partition array */
  1283. i = 0;
  1284. j = numRects;
  1285. do
  1286. {
  1287. r = &(rects[i]);
  1288. do
  1289. {
  1290. r++;
  1291. i++;
  1292. }
  1293. while (i != numRects && (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
  1294. r = &(rects[j]);
  1295. do
  1296. {
  1297. r--;
  1298. j--;
  1299. }
  1300. while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
  1301. if (i < j)
  1302. EXCHANGE_RECTS (i, j);
  1303. }
  1304. while (i < j);
  1305. /* Move partition element back to middle */
  1306. EXCHANGE_RECTS (0, j);
  1307. /* Recurse */
  1308. if (numRects - j - 1 > 1)
  1309. quick_sort_rects (&rects[j + 1], numRects - j - 1);
  1310. numRects = j;
  1311. }
  1312. while (numRects > 1);
  1313. }
  1314. /*-
  1315. *-----------------------------------------------------------------------
  1316. * pixman_region_validate --
  1317. *
  1318. * Take a ``region'' which is a non-y-x-banded random collection of
  1319. * rectangles, and compute a nice region which is the union of all the
  1320. * rectangles.
  1321. *
  1322. * Results:
  1323. * TRUE if successful.
  1324. *
  1325. * Side Effects:
  1326. * The passed-in ``region'' may be modified.
  1327. * overlap set to TRUE if any retangles overlapped,
  1328. * else FALSE;
  1329. *
  1330. * Strategy:
  1331. * Step 1. Sort the rectangles into ascending order with primary key y1
  1332. * and secondary key x1.
  1333. *
  1334. * Step 2. Split the rectangles into the minimum number of proper y-x
  1335. * banded regions. This may require horizontally merging
  1336. * rectangles, and vertically coalescing bands. With any luck,
  1337. * this step in an identity transformation (ala the Box widget),
  1338. * or a coalescing into 1 box (ala Menus).
  1339. *
  1340. * Step 3. Merge the separate regions down to a single region by calling
  1341. * pixman_region_union. Maximize the work each pixman_region_union call does by using
  1342. * a binary merge.
  1343. *
  1344. *-----------------------------------------------------------------------
  1345. */
  1346. static pixman_bool_t
  1347. validate (region_type_t * badreg)
  1348. {
  1349. /* Descriptor for regions under construction in Step 2. */
  1350. typedef struct
  1351. {
  1352. region_type_t reg;
  1353. int prev_band;
  1354. int cur_band;
  1355. } region_info_t;
  1356. region_info_t stack_regions[64];
  1357. int numRects; /* Original numRects for badreg */
  1358. region_info_t *ri; /* Array of current regions */
  1359. int num_ri; /* Number of entries used in ri */
  1360. int size_ri; /* Number of entries available in ri */
  1361. int i; /* Index into rects */
  1362. int j; /* Index into ri */
  1363. region_info_t *rit; /* &ri[j] */
  1364. region_type_t *reg; /* ri[j].reg */
  1365. box_type_t *box; /* Current box in rects */
  1366. box_type_t *ri_box; /* Last box in ri[j].reg */
  1367. region_type_t *hreg; /* ri[j_half].reg */
  1368. pixman_bool_t ret = TRUE;
  1369. if (!badreg->data)
  1370. {
  1371. GOOD (badreg);
  1372. return TRUE;
  1373. }
  1374. numRects = badreg->data->numRects;
  1375. if (!numRects)
  1376. {
  1377. if (PIXREGION_NAR (badreg))
  1378. return FALSE;
  1379. GOOD (badreg);
  1380. return TRUE;
  1381. }
  1382. if (badreg->extents.x1 < badreg->extents.x2)
  1383. {
  1384. if ((numRects) == 1)
  1385. {
  1386. FREE_DATA (badreg);
  1387. badreg->data = (region_data_type_t *) NULL;
  1388. }
  1389. else
  1390. {
  1391. DOWNSIZE (badreg, numRects);
  1392. }
  1393. GOOD (badreg);
  1394. return TRUE;
  1395. }
  1396. /* Step 1: Sort the rects array into ascending (y1, x1) order */
  1397. quick_sort_rects (PIXREGION_BOXPTR (badreg), numRects);
  1398. /* Step 2: Scatter the sorted array into the minimum number of regions */
  1399. /* Set up the first region to be the first rectangle in badreg */
  1400. /* Note that step 2 code will never overflow the ri[0].reg rects array */
  1401. ri = stack_regions;
  1402. size_ri = sizeof (stack_regions) / sizeof (stack_regions[0]);
  1403. num_ri = 1;
  1404. ri[0].prev_band = 0;
  1405. ri[0].cur_band = 0;
  1406. ri[0].reg = *badreg;
  1407. box = PIXREGION_BOXPTR (&ri[0].reg);
  1408. ri[0].reg.extents = *box;
  1409. ri[0].reg.data->numRects = 1;
  1410. badreg->extents = *pixman_region_empty_box;
  1411. badreg->data = pixman_region_empty_data;
  1412. /* Now scatter rectangles into the minimum set of valid regions. If the
  1413. * next rectangle to be added to a region would force an existing rectangle
  1414. * in the region to be split up in order to maintain y-x banding, just
  1415. * forget it. Try the next region. If it doesn't fit cleanly into any
  1416. * region, make a new one.
  1417. */
  1418. for (i = numRects; --i > 0;)
  1419. {
  1420. box++;
  1421. /* Look for a region to append box to */
  1422. for (j = num_ri, rit = ri; --j >= 0; rit++)
  1423. {
  1424. reg = &rit->reg;
  1425. ri_box = PIXREGION_END (reg);
  1426. if (box->y1 == ri_box->y1 && box->y2 == ri_box->y2)
  1427. {
  1428. /* box is in same band as ri_box. Merge or append it */
  1429. if (box->x1 <= ri_box->x2)
  1430. {
  1431. /* Merge it with ri_box */
  1432. if (box->x2 > ri_box->x2)
  1433. ri_box->x2 = box->x2;
  1434. }
  1435. else
  1436. {
  1437. RECTALLOC_BAIL (reg, 1, bail);
  1438. *PIXREGION_TOP (reg) = *box;
  1439. reg->data->numRects++;
  1440. }
  1441. goto next_rect; /* So sue me */
  1442. }
  1443. else if (box->y1 >= ri_box->y2)
  1444. {
  1445. /* Put box into new band */
  1446. if (reg->extents.x2 < ri_box->x2)
  1447. reg->extents.x2 = ri_box->x2;
  1448. if (reg->extents.x1 > box->x1)
  1449. reg->extents.x1 = box->x1;
  1450. COALESCE (reg, rit->prev_band, rit->cur_band);
  1451. rit->cur_band = reg->data->numRects;
  1452. RECTALLOC_BAIL (reg, 1, bail);
  1453. *PIXREGION_TOP (reg) = *box;
  1454. reg->data->numRects++;
  1455. goto next_rect;
  1456. }
  1457. /* Well, this region was inappropriate. Try the next one. */
  1458. } /* for j */
  1459. /* Uh-oh. No regions were appropriate. Create a new one. */
  1460. if (size_ri == num_ri)
  1461. {
  1462. size_t data_size;
  1463. /* Oops, allocate space for new region information */
  1464. size_ri <<= 1;
  1465. data_size = size_ri * sizeof(region_info_t);
  1466. if (data_size / size_ri != sizeof(region_info_t))
  1467. goto bail;
  1468. if (ri == stack_regions)
  1469. {
  1470. rit = malloc (data_size);
  1471. if (!rit)
  1472. goto bail;
  1473. memcpy (rit, ri, num_ri * sizeof (region_info_t));
  1474. }
  1475. else
  1476. {
  1477. rit = (region_info_t *) realloc (ri, data_size);
  1478. if (!rit)
  1479. goto bail;
  1480. }
  1481. ri = rit;
  1482. rit = &ri[num_ri];
  1483. }
  1484. num_ri++;
  1485. rit->prev_band = 0;
  1486. rit->cur_band = 0;
  1487. rit->reg.extents = *box;
  1488. rit->reg.data = (region_data_type_t *)NULL;
  1489. /* MUST force allocation */
  1490. if (!pixman_rect_alloc (&rit->reg, (i + num_ri) / num_ri))
  1491. goto bail;
  1492. next_rect: ;
  1493. } /* for i */
  1494. /* Make a final pass over each region in order to COALESCE and set
  1495. * extents.x2 and extents.y2
  1496. */
  1497. for (j = num_ri, rit = ri; --j