FreeRDP
TestFreeRDPRegion.c
1 
20 #include <winpr/crt.h>
21 #include <winpr/print.h>
22 
23 #include <freerdp/codec/region.h>
24 
25 static BOOL compareRectangles(const RECTANGLE_16* src1, const RECTANGLE_16* src2, int nb)
26 {
27  for (int i = 0; i < nb; i++, src1++, src2++)
28  {
29  if (memcmp(src1, src2, sizeof(RECTANGLE_16)) != 0)
30  {
31  (void)fprintf(stderr,
32  "expecting rect %d (%" PRIu16 ",%" PRIu16 "-%" PRIu16 ",%" PRIu16
33  ") and have (%" PRIu16 ",%" PRIu16 "-%" PRIu16 ",%" PRIu16 ")\n",
34  i, src2->left, src2->top, src2->right, src2->bottom, src1->left,
35  src1->top, src1->right, src1->bottom);
36  return FALSE;
37  }
38  }
39 
40  return TRUE;
41 }
42 
43 static int test_basic(void)
44 {
45  REGION16 region;
46  int retCode = -1;
47  const RECTANGLE_16* rects = NULL;
48  UINT32 nbRects = 0;
49  /* R1 + R2 ==> disjointed rects */
50  RECTANGLE_16 r1 = { 0, 101, 200, 201 };
51  RECTANGLE_16 r2 = { 150, 301, 250, 401 };
52  RECTANGLE_16 r1_r2[] = { { 0, 101, 200, 201 }, { 150, 301, 250, 401 } };
53  /* r1 */
54  region16_init(&region);
55 
56  if (!region16_union_rect(&region, &region, &r1))
57  goto out;
58 
59  rects = region16_rects(&region, &nbRects);
60 
61  if (!rects || nbRects != 1 || memcmp(rects, &r1, sizeof(RECTANGLE_16)) != 0)
62  goto out;
63 
64  /* r1 + r2 */
65  if (!region16_union_rect(&region, &region, &r2))
66  goto out;
67 
68  rects = region16_rects(&region, &nbRects);
69 
70  if (!rects || nbRects != 2 || !compareRectangles(rects, r1_r2, nbRects))
71  goto out;
72 
73  /* clear region */
74  region16_clear(&region);
75  region16_rects(&region, &nbRects);
76 
77  if (nbRects)
78  goto out;
79 
80  retCode = 0;
81 out:
82  region16_uninit(&region);
83  return retCode;
84 }
85 
86 static int test_r1_r3(void)
87 {
88  REGION16 region;
89  int retCode = -1;
90  const RECTANGLE_16* rects = NULL;
91  UINT32 nbRects = 0;
92  RECTANGLE_16 r1 = { 0, 101, 200, 201 };
93  RECTANGLE_16 r3 = { 150, 151, 250, 251 };
94  RECTANGLE_16 r1_r3[] = { { 0, 101, 200, 151 }, { 0, 151, 250, 201 }, { 150, 201, 250, 251 } };
95  region16_init(&region);
96  /*
97  * +===============================================================
98  * |
99  * |+-----+ +-----+
100  * || r1 | | |
101  * || +-+------+ +-----+--------+
102  * || | r3 | | |
103  * |+---+ | ====> +-----+--------+
104  * | | | | |
105  * | +--------+ +--------+
106  */
107 
108  /* R1 + R3 */
109  if (!region16_union_rect(&region, &region, &r1))
110  goto out;
111 
112  if (!region16_union_rect(&region, &region, &r3))
113  goto out;
114 
115  rects = region16_rects(&region, &nbRects);
116 
117  if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r3, nbRects))
118  goto out;
119 
120  /* R3 + R1 */
121  region16_clear(&region);
122 
123  if (!region16_union_rect(&region, &region, &r3))
124  goto out;
125 
126  if (!region16_union_rect(&region, &region, &r1))
127  goto out;
128 
129  rects = region16_rects(&region, &nbRects);
130 
131  if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r3, nbRects))
132  goto out;
133 
134  retCode = 0;
135 out:
136  region16_uninit(&region);
137  return retCode;
138 }
139 
140 static int test_r9_r10(void)
141 {
142  REGION16 region;
143  int retCode = -1;
144  const RECTANGLE_16* rects = NULL;
145  UINT32 nbRects = 0;
146  /*
147  * +===============================================================
148  * |
149  * | +---+ +---+
150  * |+--|r10|-+ +--+---+-+
151  * ||r9| | | | |
152  * || | | | | |
153  * || | | | =====> | |
154  * || | | | | |
155  * || | | | | |
156  * |+--| |-+ +--+---+-+
157  * | +---+ +---+
158  */
159  RECTANGLE_16 r9 = { 0, 100, 400, 200 };
160  RECTANGLE_16 r10 = { 200, 0, 300, 300 };
161  RECTANGLE_16 r9_r10[] = {
162  { 200, 0, 300, 100 },
163  { 0, 100, 400, 200 },
164  { 200, 200, 300, 300 },
165  };
166  region16_init(&region);
167 
168  if (!region16_union_rect(&region, &region, &r9))
169  goto out;
170 
171  if (!region16_union_rect(&region, &region, &r10))
172  goto out;
173 
174  rects = region16_rects(&region, &nbRects);
175 
176  if (!rects || nbRects != 3 || !compareRectangles(rects, r9_r10, nbRects))
177  goto out;
178 
179  retCode = 0;
180 out:
181  region16_uninit(&region);
182  return retCode;
183 }
184 
185 static int test_r1_r5(void)
186 {
187  REGION16 region;
188  int retCode = -1;
189  const RECTANGLE_16* rects = NULL;
190  UINT32 nbRects = 0;
191  RECTANGLE_16 r1 = { 0, 101, 200, 201 };
192  RECTANGLE_16 r5 = { 150, 121, 300, 131 };
193  RECTANGLE_16 r1_r5[] = { { 0, 101, 200, 121 }, { 0, 121, 300, 131 }, { 0, 131, 200, 201 } };
194  region16_init(&region);
195 
196  /*
197  * +===============================================================
198  * |
199  * |+--------+ +--------+
200  * || r1 | | |
201  * || +--+----+ +--------+----+
202  * || | r5 | =====> | |
203  * || +-------+ +--------+----+
204  * || | | |
205  * |+--------+ +--------+
206  * |
207  *
208  */
209  if (!region16_union_rect(&region, &region, &r1))
210  goto out;
211 
212  if (!region16_union_rect(&region, &region, &r5))
213  goto out;
214 
215  rects = region16_rects(&region, &nbRects);
216 
217  if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r5, nbRects))
218  goto out;
219 
220  retCode = 0;
221 out:
222  region16_uninit(&region);
223  return retCode;
224 }
225 
226 static int test_r1_r6(void)
227 {
228  REGION16 region;
229  int retCode = -1;
230  const RECTANGLE_16* rects = NULL;
231  UINT32 nbRects = 0;
232  RECTANGLE_16 r1 = { 0, 101, 200, 201 };
233  RECTANGLE_16 r6 = { 150, 121, 170, 131 };
234  region16_init(&region);
235  /*
236  * +===============================================================
237  * |
238  * |+--------+ +--------+
239  * || r1 | | |
240  * || +--+ | | |
241  * || |r6| | =====> | |
242  * || +--+ | | |
243  * || | | |
244  * |+--------+ +--------+
245  * |
246  */
247  region16_clear(&region);
248 
249  if (!region16_union_rect(&region, &region, &r1))
250  goto out;
251 
252  if (!region16_union_rect(&region, &region, &r6))
253  goto out;
254 
255  rects = region16_rects(&region, &nbRects);
256 
257  if (!rects || nbRects != 1 || !compareRectangles(rects, &r1, nbRects))
258  goto out;
259 
260  retCode = 0;
261 out:
262  region16_uninit(&region);
263  return retCode;
264 }
265 
266 static int test_r1_r2_r4(void)
267 {
268  REGION16 region;
269  int retCode = -1;
270  const RECTANGLE_16* rects = NULL;
271  UINT32 nbRects = 0;
272  RECTANGLE_16 r1 = { 0, 101, 200, 201 };
273  RECTANGLE_16 r2 = { 150, 301, 250, 401 };
274  RECTANGLE_16 r4 = { 150, 251, 250, 301 };
275  RECTANGLE_16 r1_r2_r4[] = { { 0, 101, 200, 201 }, { 150, 251, 250, 401 } };
276  /*
277  * +===============================================================
278  * |
279  * |+-----+ +-----+
280  * || r1 | | |
281  * || | | |
282  * || | | |
283  * |+-----+ ====> +-----+
284  * |
285  * | +--------+ +--------+
286  * | | r4 | | |
287  * | +--------+ | |
288  * | | r2 | | |
289  * | | | | |
290  * | +--------+ +--------+
291  *
292  */
293  region16_init(&region);
294 
295  if (!region16_union_rect(&region, &region, &r1))
296  goto out;
297 
298  if (!region16_union_rect(&region, &region, &r2))
299  goto out;
300 
301  if (!region16_union_rect(&region, &region, &r4))
302  goto out;
303 
304  rects = region16_rects(&region, &nbRects);
305 
306  if (!rects || nbRects != 2 || !compareRectangles(rects, r1_r2_r4, nbRects))
307  goto out;
308 
309  retCode = 0;
310 out:
311  region16_uninit(&region);
312  return retCode;
313 }
314 
315 static int test_r1_r7_r8(void)
316 {
317  REGION16 region;
318  int retCode = -1;
319  const RECTANGLE_16* rects = NULL;
320  UINT32 nbRects = 0;
321  RECTANGLE_16 r1 = { 0, 101, 200, 201 };
322  RECTANGLE_16 r7 = { 300, 101, 500, 201 };
323  RECTANGLE_16 r8 = { 150, 121, 400, 131 };
324  RECTANGLE_16 r1_r7_r8[] = {
325  { 0, 101, 200, 121 }, { 300, 101, 500, 121 }, { 0, 121, 500, 131 },
326  { 0, 131, 200, 201 }, { 300, 131, 500, 201 },
327  };
328  /*
329  * +===============================================================
330  * |
331  * |+--------+ +--------+ +--------+ +--------+
332  * || r1 | | r7 | | | | |
333  * || +------------+ | +--------+---+--------+
334  * || | r8 | | =====> | |
335  * || +------------+ | +--------+---+--------+
336  * || | | | | | | |
337  * |+--------+ +--------+ +--------+ +--------+
338  * |
339  */
340  region16_init(&region);
341 
342  if (!region16_union_rect(&region, &region, &r1))
343  goto out;
344 
345  if (!region16_union_rect(&region, &region, &r7))
346  goto out;
347 
348  if (!region16_union_rect(&region, &region, &r8))
349  goto out;
350 
351  rects = region16_rects(&region, &nbRects);
352 
353  if (!rects || nbRects != 5 || !compareRectangles(rects, r1_r7_r8, nbRects))
354  goto out;
355 
356  region16_clear(&region);
357 
358  if (!region16_union_rect(&region, &region, &r1))
359  goto out;
360 
361  if (!region16_union_rect(&region, &region, &r8))
362  goto out;
363 
364  if (!region16_union_rect(&region, &region, &r7))
365  goto out;
366 
367  rects = region16_rects(&region, &nbRects);
368 
369  if (!rects || nbRects != 5 || !compareRectangles(rects, r1_r7_r8, nbRects))
370  goto out;
371 
372  region16_clear(&region);
373 
374  if (!region16_union_rect(&region, &region, &r8))
375  goto out;
376 
377  if (!region16_union_rect(&region, &region, &r7))
378  goto out;
379 
380  if (!region16_union_rect(&region, &region, &r1))
381  goto out;
382 
383  rects = region16_rects(&region, &nbRects);
384 
385  if (!rects || nbRects != 5 || !compareRectangles(rects, r1_r7_r8, nbRects))
386  goto out;
387 
388  retCode = 0;
389 out:
390  region16_uninit(&region);
391  return retCode;
392 }
393 
394 static int test_r1_r2_r3_r4(void)
395 {
396  REGION16 region;
397  int retCode = -1;
398  const RECTANGLE_16* rects = NULL;
399  UINT32 nbRects = 0;
400  RECTANGLE_16 r1 = { 0, 101, 200, 201 };
401  RECTANGLE_16 r2 = { 150, 301, 250, 401 };
402  RECTANGLE_16 r3 = { 150, 151, 250, 251 };
403  RECTANGLE_16 r4 = { 150, 251, 250, 301 };
404  RECTANGLE_16 r1_r2_r3[] = {
405  { 0, 101, 200, 151 }, { 0, 151, 250, 201 }, { 150, 201, 250, 251 }, { 150, 301, 250, 401 }
406  };
407  RECTANGLE_16 r1_r2_r3_r4[] = { { 0, 101, 200, 151 },
408  { 0, 151, 250, 201 },
409  { 150, 201, 250, 401 } };
410  region16_init(&region);
411 
412  /*
413  * +===============================================================
414  * |
415  * |+-----+ +-----+
416  * || r1 | | |
417  * || +-+------+ +-----+--------+
418  * || | r3 | | |
419  * |+---+ | ====> +-----+--------+
420  * | | | | |
421  * | +--------+ +--------+
422  * | +--------+ +--------+
423  * | | r2 | | |
424  * | | | | |
425  * | +--------+ +--------+
426  */
427  if (!region16_union_rect(&region, &region, &r1))
428  goto out;
429 
430  if (!region16_union_rect(&region, &region, &r2))
431  goto out;
432 
433  if (!region16_union_rect(&region, &region, &r3))
434  goto out;
435 
436  rects = region16_rects(&region, &nbRects);
437 
438  if (!rects || nbRects != 4 || !compareRectangles(rects, r1_r2_r3, 4))
439  goto out;
440 
441  /*
442  * +===============================================================
443  * |
444  * |+-----+ +-----+
445  * || | | |
446  * |+-----+--------+ +-----+--------+
447  * || | ==> | |
448  * |+-----+--------+ +-----+--------+
449  * | | | | |
450  * | +--------+ | |
451  * | | + r4 | | |
452  * | +--------+ | |
453  * | | | | |
454  * | | | | |
455  * | +--------+ +--------+
456  */
457  if (!region16_union_rect(&region, &region, &r4))
458  goto out;
459 
460  rects = region16_rects(&region, &nbRects);
461 
462  if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r2_r3_r4, 3))
463  goto out;
464 
465  retCode = 0;
466 out:
467  region16_uninit(&region);
468  return retCode;
469 }
470 
471 static int test_from_weston(void)
472 {
473  /*
474  * 0: 0,0 -> 640,32 (w=640 h=32)
475  * 1: 236,169 -> 268,201 (w=32 h=32)
476  * 2: 246,258 -> 278,290 (w=32 h=32)
477  */
478  REGION16 region;
479  int retCode = -1;
480  const RECTANGLE_16* rects = NULL;
481  UINT32 nbRects = 0;
482  RECTANGLE_16 r1 = { 0, 0, 640, 32 };
483  RECTANGLE_16 r2 = { 236, 169, 268, 201 };
484  RECTANGLE_16 r3 = { 246, 258, 278, 290 };
485  RECTANGLE_16 r1_r2_r3[] = { { 0, 0, 640, 32 }, { 236, 169, 268, 201 }, { 246, 258, 278, 290 } };
486  region16_init(&region);
487 
488  /*
489  * +===============================================================
490  * |+-------------------------------------------------------------+
491  * || r1 |
492  * |+-------------------------------------------------------------+
493  * |
494  * | +---------------+
495  * | | r2 |
496  * | +---------------+
497  * |
498  * | +---------------+
499  * | | r3 |
500  * | +---------------+
501  * |
502  */
503  if (!region16_union_rect(&region, &region, &r1))
504  goto out;
505 
506  if (!region16_union_rect(&region, &region, &r2))
507  goto out;
508 
509  if (!region16_union_rect(&region, &region, &r3))
510  goto out;
511 
512  rects = region16_rects(&region, &nbRects);
513 
514  if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r2_r3, 3))
515  goto out;
516 
517  retCode = 0;
518 out:
519  region16_uninit(&region);
520  return retCode;
521 }
522 
523 static int test_r1_inter_r3(void)
524 {
525  REGION16 region;
526  REGION16 intersection;
527  int retCode = -1;
528  const RECTANGLE_16* rects = NULL;
529  UINT32 nbRects = 0;
530  RECTANGLE_16 r1 = { 0, 101, 200, 201 };
531  RECTANGLE_16 r3 = { 150, 151, 250, 251 };
532  RECTANGLE_16 r1_inter_r3[] = {
533  { 150, 151, 200, 201 },
534  };
535  region16_init(&region);
536  region16_init(&intersection);
537 
538  /*
539  * +===============================================================
540  * |
541  * |+-----+
542  * || r1 |
543  * || +-+------+ +-+
544  * || | r3 | r1&r3 | |
545  * |+---+ | ====> +-+
546  * | | |
547  * | +--------+
548  */
549  if (!region16_union_rect(&region, &region, &r1))
550  goto out;
551 
552  if (!region16_intersects_rect(&region, &r3))
553  goto out;
554 
555  if (!region16_intersect_rect(&intersection, &region, &r3))
556  goto out;
557 
558  rects = region16_rects(&intersection, &nbRects);
559 
560  if (!rects || nbRects != 1 || !compareRectangles(rects, r1_inter_r3, nbRects))
561  goto out;
562 
563  retCode = 0;
564 out:
565  region16_uninit(&region);
566  region16_uninit(&intersection);
567  return retCode;
568 }
569 
570 static int test_r1_r3_inter_r11(void)
571 {
572  REGION16 region;
573  REGION16 intersection;
574  int retCode = -1;
575  const RECTANGLE_16* rects = NULL;
576  UINT32 nbRects = 0;
577  RECTANGLE_16 r1 = { 0, 101, 200, 201 };
578  RECTANGLE_16 r3 = { 150, 151, 250, 251 };
579  RECTANGLE_16 r11 = { 170, 151, 600, 301 };
580  RECTANGLE_16 r1_r3_inter_r11[] = {
581  { 170, 151, 250, 251 },
582  };
583  region16_init(&region);
584  region16_init(&intersection);
585 
586  /*
587  * +===============================================================
588  * |
589  * |+-----+
590  * || |
591  * || +------+
592  * || r1+r3 | (r1+r3) & r11
593  * || +----------------+ +--------+
594  * |+---+ | | | ====> | |
595  * | | | | | | |
596  * | | | | | | |
597  * | +-|------+ | +--------+
598  * | | r11 |
599  * | +----------------+
600  *
601  *
602  * R1+R3 is made of 3 bands, R11 overlap the second and the third band. The
603  * intersection is made of two band that must be reassembled to give only
604  * one
605  */
606  if (!region16_union_rect(&region, &region, &r1))
607  goto out;
608 
609  if (!region16_union_rect(&region, &region, &r3))
610  goto out;
611 
612  if (!region16_intersects_rect(&region, &r11))
613  goto out;
614 
615  if (!region16_intersect_rect(&intersection, &region, &r11))
616  goto out;
617 
618  rects = region16_rects(&intersection, &nbRects);
619 
620  if (!rects || nbRects != 1 || !compareRectangles(rects, r1_r3_inter_r11, nbRects))
621  goto out;
622 
623  retCode = 0;
624 out:
625  region16_uninit(&intersection);
626  region16_uninit(&region);
627  return retCode;
628 }
629 
630 static int test_norbert_case(void)
631 {
632  REGION16 region;
633  REGION16 intersection;
634  int retCode = -1;
635  const RECTANGLE_16* rects = NULL;
636  UINT32 nbRects = 0;
637  RECTANGLE_16 inRectangles[5] = { { 1680, 0, 1920, 242 },
638  { 294, 242, 971, 776 },
639  { 1680, 242, 1920, 776 },
640  { 1680, 776, 1920, 1036 },
641  { 2, 1040, 53, 1078 } };
642  RECTANGLE_16 screenRect = { 0, 0, 1920, 1080 };
643  RECTANGLE_16 expected_inter_extents = { 2, 0, 1920, 1078 };
644  region16_init(&region);
645  region16_init(&intersection);
646 
647  /*
648  * Consider following as a screen with resolution 1920*1080
649  * | | | | | | |
650  * | |2 |53 |294 |971 |1680 |
651  * | | | | | | |
652  * 0 +=+======================================+======+
653  * | | | |
654  * | | R[0]|
655  * 242 | +-----------+ +------+
656  * | | | | | |
657  * | | | | |
658  * | | R[1]| | R[2]|
659  * 776 | | +-----------+ +------+
660  * | | |
661  * | | R[3]|
662  * 1036 | | +------+
663  * 1040 | +----+
664  * | |R[4]| Union of R[0-4]|
665  * 1078 | +----+ - - - - - - - -+
666  * 1080 |
667  *
668  *
669  * The result is union of R[0] - R[4].
670  * After intersected with the full screen rect, the
671  * result should keep the same.
672  */
673  for (int i = 0; i < 5; i++)
674  {
675  if (!region16_union_rect(&region, &region, &inRectangles[i]))
676  goto out;
677  }
678 
679  if (!compareRectangles(region16_extents(&region), &expected_inter_extents, 1))
680  goto out;
681 
682  if (!region16_intersect_rect(&intersection, &region, &screenRect))
683  goto out;
684 
685  rects = region16_rects(&intersection, &nbRects);
686 
687  if (!rects || nbRects != 5 || !compareRectangles(rects, inRectangles, nbRects))
688  goto out;
689 
690  if (!compareRectangles(region16_extents(&intersection), &expected_inter_extents, 1))
691  goto out;
692 
693  retCode = 0;
694 out:
695  region16_uninit(&intersection);
696  region16_uninit(&region);
697  return retCode;
698 }
699 
700 static int test_norbert2_case(void)
701 {
702  REGION16 region;
703  int retCode = -1;
704  const RECTANGLE_16* rects = NULL;
705  UINT32 nbRects = 0;
706  RECTANGLE_16 rect1 = { 464, 696, 476, 709 };
707  RECTANGLE_16 rect2 = { 0, 0, 1024, 32 };
708  region16_init(&region);
709 
710  if (!region16_union_rect(&region, &region, &rect1))
711  {
712  (void)fprintf(stderr, "%s: Error 1 - region16_union_rect failed\n", __func__);
713  goto out;
714  }
715 
716  if (!(rects = region16_rects(&region, &nbRects)))
717  {
718  (void)fprintf(stderr, "%s: Error 2 - region16_rects failed\n", __func__);
719  goto out;
720  }
721 
722  if (nbRects != 1)
723  {
724  (void)fprintf(stderr, "%s: Error 3 - expected nbRects == 1 but got %" PRIu32 "\n", __func__,
725  nbRects);
726  goto out;
727  }
728 
729  if (!compareRectangles(&rects[0], &rect1, 1))
730  {
731  (void)fprintf(stderr, "%s: Error 4 - compare failed\n", __func__);
732  goto out;
733  }
734 
735  if (!region16_union_rect(&region, &region, &rect2))
736  {
737  (void)fprintf(stderr, "%s: Error 5 - region16_union_rect failed\n", __func__);
738  goto out;
739  }
740 
741  if (!(rects = region16_rects(&region, &nbRects)))
742  {
743  (void)fprintf(stderr, "%s: Error 6 - region16_rects failed\n", __func__);
744  goto out;
745  }
746 
747  if (nbRects != 2)
748  {
749  (void)fprintf(stderr, "%s: Error 7 - expected nbRects == 2 but got %" PRIu32 "\n", __func__,
750  nbRects);
751  goto out;
752  }
753 
754  if (!compareRectangles(&rects[0], &rect2, 1))
755  {
756  (void)fprintf(stderr, "%s: Error 8 - compare failed\n", __func__);
757  goto out;
758  }
759 
760  if (!compareRectangles(&rects[1], &rect1, 1))
761  {
762  (void)fprintf(stderr, "%s: Error 9 - compare failed\n", __func__);
763  goto out;
764  }
765 
766  retCode = 0;
767 out:
768  region16_uninit(&region);
769  return retCode;
770 }
771 
772 static int test_empty_rectangle(void)
773 {
774  REGION16 region;
775  REGION16 intersection;
776  int retCode = -1;
777  RECTANGLE_16 emptyRectangles[3] = { { 0, 0, 0, 0 }, { 10, 10, 10, 11 }, { 10, 10, 11, 10 } };
778  RECTANGLE_16 firstRect = { 0, 0, 100, 100 };
779  RECTANGLE_16 anotherRect = { 100, 100, 200, 200 };
780  RECTANGLE_16 expected_inter_extents = { 0, 0, 0, 0 };
781  region16_init(&region);
782  region16_init(&intersection);
783 
784  /* Check for empty rectangles */
785  for (int i = 0; i < 3; i++)
786  {
787  if (!rectangle_is_empty(&emptyRectangles[i]))
788  goto out;
789  }
790 
791  /* Check for non-empty rectangles */
792  if (rectangle_is_empty(&firstRect))
793  goto out;
794 
795  /* Intersect 2 non-intersect rectangle, result should be empty */
796  if (!region16_union_rect(&region, &region, &firstRect))
797  goto out;
798 
799  if (!region16_intersect_rect(&region, &region, &anotherRect))
800  goto out;
801 
802  if (!compareRectangles(region16_extents(&region), &expected_inter_extents, 1))
803  goto out;
804 
805  if (!region16_is_empty(&region))
806  goto out;
807 
808  if (!rectangle_is_empty(region16_extents(&intersection)))
809  goto out;
810 
811  retCode = 0;
812 out:
813  region16_uninit(&intersection);
814  region16_uninit(&region);
815  return retCode;
816 }
817 
818 typedef int (*TestFunction)(void);
819 struct UnitaryTest
820 {
821  const char* name;
822  TestFunction func;
823 };
824 
825 static struct UnitaryTest tests[] = { { "Basic trivial tests", test_basic },
826  { "R1+R3 and R3+R1", test_r1_r3 },
827  { "R1+R5", test_r1_r5 },
828  { "R1+R6", test_r1_r6 },
829  { "R9+R10", test_r9_r10 },
830  { "R1+R2+R4", test_r1_r2_r4 },
831  { "R1+R7+R8 in many orders", test_r1_r7_r8 },
832  { "R1+R2+R3+R4", test_r1_r2_r3_r4 },
833  { "data from weston", test_from_weston },
834  { "R1 & R3", test_r1_inter_r3 },
835  { "(R1+R3)&R11 (band merge)", test_r1_r3_inter_r11 },
836  { "norbert's case", test_norbert_case },
837  { "norbert's case 2", test_norbert2_case },
838  { "empty rectangle case", test_empty_rectangle },
839 
840  { NULL, NULL } };
841 
842 int TestFreeRDPRegion(int argc, char* argv[])
843 {
844  int testNb = 0;
845  int retCode = -1;
846  WINPR_UNUSED(argc);
847  WINPR_UNUSED(argv);
848 
849  for (int i = 0; tests[i].func; i++)
850  {
851  testNb++;
852  (void)fprintf(stderr, "%d: %s\n", testNb, tests[i].name);
853  retCode = tests[i].func();
854 
855  if (retCode < 0)
856  break;
857  }
858 
859  if (retCode < 0)
860  (void)fprintf(stderr, "failed for test %d\n", testNb);
861 
862  return retCode;
863 }