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