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