Line data Source code
1 : /*
2 : * primrect.c
3 : * Patater GUI Kit
4 : *
5 : * Created by Jaeden Amero on 2021-01-15.
6 : * Copyright 2021. SPDX-License-Identifier: AGPL-3.0-or-later
7 : */
8 :
9 : #include "guikit/primrect.h"
10 : #include "ptest/test.h"
11 :
12 1 : static int rectangleIsClippedNW(void)
13 : {
14 1 : struct Rect rect;
15 1 : struct Rect clip;
16 : int ret;
17 :
18 1 : clip.left = 20;
19 1 : clip.top = 20;
20 1 : clip.right = 30;
21 1 : clip.bottom = 30;
22 :
23 1 : rect.left = 15;
24 1 : rect.top = 15;
25 1 : rect.right = 25;
26 1 : rect.bottom = 25;
27 :
28 1 : ret = ClipRect(&rect, &clip);
29 :
30 1 : TEST_EQ(ret, CLIP_CLIPPED);
31 1 : TEST_EQ(rect.left, 20);
32 1 : TEST_EQ(rect.top, 20);
33 1 : TEST_EQ(rect.right, 25);
34 1 : TEST_EQ(rect.bottom, 25);
35 :
36 1 : return 0;
37 : }
38 :
39 1 : static int rectangleIsClippedN(void)
40 : {
41 1 : struct Rect rect;
42 1 : struct Rect clip;
43 : int ret;
44 :
45 1 : clip.left = 20;
46 1 : clip.top = 20;
47 1 : clip.right = 30;
48 1 : clip.bottom = 30;
49 :
50 1 : rect.left = 20;
51 1 : rect.top = 15;
52 1 : rect.right = 30;
53 1 : rect.bottom = 25;
54 :
55 1 : ret = ClipRect(&rect, &clip);
56 :
57 1 : TEST_EQ(ret, CLIP_CLIPPED);
58 1 : TEST_EQ(rect.left, 20);
59 1 : TEST_EQ(rect.top, 20);
60 1 : TEST_EQ(rect.right, 30);
61 1 : TEST_EQ(rect.bottom, 25);
62 :
63 1 : return 0;
64 : }
65 :
66 1 : static int rectangleIsClippedNE(void)
67 : {
68 1 : struct Rect rect;
69 1 : struct Rect clip;
70 : int ret;
71 :
72 1 : clip.left = 20;
73 1 : clip.top = 20;
74 1 : clip.right = 30;
75 1 : clip.bottom = 30;
76 :
77 1 : rect.left = 25;
78 1 : rect.top = 15;
79 1 : rect.right = 35;
80 1 : rect.bottom = 25;
81 :
82 1 : ret = ClipRect(&rect, &clip);
83 :
84 1 : TEST_EQ(ret, CLIP_CLIPPED);
85 1 : TEST_EQ(rect.left, 25);
86 1 : TEST_EQ(rect.top, 20);
87 1 : TEST_EQ(rect.right, 30);
88 1 : TEST_EQ(rect.bottom, 25);
89 :
90 1 : return 0;
91 : }
92 :
93 1 : static int rectangleIsClippedE(void)
94 : {
95 1 : struct Rect rect;
96 1 : struct Rect clip;
97 : int ret;
98 :
99 1 : clip.left = 20;
100 1 : clip.top = 20;
101 1 : clip.right = 30;
102 1 : clip.bottom = 30;
103 :
104 1 : rect.left = 25;
105 1 : rect.top = 20;
106 1 : rect.right = 35;
107 1 : rect.bottom = 30;
108 :
109 1 : ret = ClipRect(&rect, &clip);
110 :
111 1 : TEST_EQ(ret, CLIP_CLIPPED);
112 1 : TEST_EQ(rect.left, 25);
113 1 : TEST_EQ(rect.top, 20);
114 1 : TEST_EQ(rect.right, 30);
115 1 : TEST_EQ(rect.bottom, 30);
116 :
117 1 : return 0;
118 : }
119 :
120 1 : static int rectangleIsClippedSE(void)
121 : {
122 1 : struct Rect rect;
123 1 : struct Rect clip;
124 : int ret;
125 :
126 1 : clip.left = 20;
127 1 : clip.top = 20;
128 1 : clip.right = 30;
129 1 : clip.bottom = 30;
130 :
131 1 : rect.left = 25;
132 1 : rect.top = 25;
133 1 : rect.right = 35;
134 1 : rect.bottom = 35;
135 :
136 1 : ret = ClipRect(&rect, &clip);
137 :
138 1 : TEST_EQ(ret, CLIP_CLIPPED);
139 1 : TEST_EQ(rect.left, 25);
140 1 : TEST_EQ(rect.top, 25);
141 1 : TEST_EQ(rect.right, 30);
142 1 : TEST_EQ(rect.bottom, 30);
143 :
144 1 : return 0;
145 : }
146 :
147 1 : static int rectangleIsClippedS(void)
148 : {
149 1 : struct Rect rect;
150 1 : struct Rect clip;
151 : int ret;
152 :
153 1 : clip.left = 20;
154 1 : clip.top = 20;
155 1 : clip.right = 30;
156 1 : clip.bottom = 30;
157 :
158 1 : rect.left = 20;
159 1 : rect.top = 25;
160 1 : rect.right = 30;
161 1 : rect.bottom = 80;
162 :
163 1 : ret = ClipRect(&rect, &clip);
164 :
165 1 : TEST_EQ(ret, CLIP_CLIPPED);
166 1 : TEST_EQ(rect.left, 20);
167 1 : TEST_EQ(rect.top, 25);
168 1 : TEST_EQ(rect.right, 30);
169 1 : TEST_EQ(rect.bottom, 30);
170 :
171 1 : return 0;
172 : }
173 :
174 1 : static int rectangleIsClippedSW(void)
175 : {
176 1 : struct Rect rect;
177 1 : struct Rect clip;
178 : int ret;
179 :
180 1 : clip.left = 20;
181 1 : clip.top = 20;
182 1 : clip.right = 30;
183 1 : clip.bottom = 30;
184 :
185 1 : rect.left = 15;
186 1 : rect.top = 25;
187 1 : rect.right = 25;
188 1 : rect.bottom = 35;
189 :
190 1 : ret = ClipRect(&rect, &clip);
191 :
192 1 : TEST_EQ(ret, CLIP_CLIPPED);
193 1 : TEST_EQ(rect.left, 20);
194 1 : TEST_EQ(rect.top, 25);
195 1 : TEST_EQ(rect.right, 25);
196 1 : TEST_EQ(rect.bottom, 30);
197 :
198 1 : return 0;
199 : }
200 :
201 1 : static int rectangleIsClippedW(void)
202 : {
203 1 : struct Rect rect;
204 1 : struct Rect clip;
205 : int ret;
206 :
207 1 : clip.left = 20;
208 1 : clip.top = 20;
209 1 : clip.right = 30;
210 1 : clip.bottom = 30;
211 :
212 1 : rect.left = 15;
213 1 : rect.top = 20;
214 1 : rect.right = 25;
215 1 : rect.bottom = 30;
216 :
217 1 : ret = ClipRect(&rect, &clip);
218 :
219 1 : TEST_EQ(ret, CLIP_CLIPPED);
220 1 : TEST_EQ(rect.left, 20);
221 1 : TEST_EQ(rect.top, 20);
222 1 : TEST_EQ(rect.right, 25);
223 1 : TEST_EQ(rect.bottom, 30);
224 :
225 1 : return 0;
226 : }
227 :
228 1 : static int rectangleIsRejectedNW(void)
229 : {
230 1 : struct Rect rect;
231 1 : struct Rect clip;
232 : int ret;
233 :
234 1 : clip.left = 20;
235 1 : clip.top = 20;
236 1 : clip.right = 30;
237 1 : clip.bottom = 30;
238 :
239 1 : rect.left = 15;
240 1 : rect.top = 15;
241 1 : rect.right = 19;
242 1 : rect.bottom = 19;
243 :
244 1 : ret = ClipRect(&rect, &clip);
245 :
246 1 : TEST_EQ(ret, CLIP_REJECTED);
247 :
248 1 : return 0;
249 : }
250 :
251 1 : static int rectangleIsRejectedN(void)
252 : {
253 1 : struct Rect rect;
254 1 : struct Rect clip;
255 : int ret;
256 :
257 1 : clip.left = 20;
258 1 : clip.top = 20;
259 1 : clip.right = 30;
260 1 : clip.bottom = 30;
261 :
262 1 : rect.left = 20;
263 1 : rect.top = 15;
264 1 : rect.right = 30;
265 1 : rect.bottom = 19;
266 :
267 1 : ret = ClipRect(&rect, &clip);
268 :
269 1 : TEST_EQ(ret, CLIP_REJECTED);
270 :
271 1 : return 0;
272 : }
273 :
274 1 : static int rectangleIsRejectedNE(void)
275 : {
276 1 : struct Rect rect;
277 1 : struct Rect clip;
278 : int ret;
279 :
280 1 : clip.left = 20;
281 1 : clip.top = 20;
282 1 : clip.right = 30;
283 1 : clip.bottom = 30;
284 :
285 1 : rect.left = 30;
286 1 : rect.top = 15;
287 1 : rect.right = 35;
288 1 : rect.bottom = 19;
289 :
290 1 : ret = ClipRect(&rect, &clip);
291 :
292 1 : TEST_EQ(ret, CLIP_REJECTED);
293 :
294 1 : return 0;
295 : }
296 :
297 1 : static int rectangleIsRejectedE(void)
298 : {
299 1 : struct Rect rect;
300 1 : struct Rect clip;
301 : int ret;
302 :
303 1 : clip.left = 20;
304 1 : clip.top = 20;
305 1 : clip.right = 30;
306 1 : clip.bottom = 30;
307 :
308 1 : rect.left = 31;
309 1 : rect.top = 20;
310 1 : rect.right = 35;
311 1 : rect.bottom = 30;
312 :
313 1 : ret = ClipRect(&rect, &clip);
314 :
315 1 : TEST_EQ(ret, CLIP_REJECTED);
316 :
317 1 : return 0;
318 : }
319 :
320 1 : static int rectangleIsRejectedSE(void)
321 : {
322 1 : struct Rect rect;
323 1 : struct Rect clip;
324 : int ret;
325 :
326 1 : clip.left = 20;
327 1 : clip.top = 20;
328 1 : clip.right = 30;
329 1 : clip.bottom = 30;
330 :
331 1 : rect.left = 31;
332 1 : rect.top = 30;
333 1 : rect.right = 35;
334 1 : rect.bottom = 35;
335 :
336 1 : ret = ClipRect(&rect, &clip);
337 :
338 1 : TEST_EQ(ret, CLIP_REJECTED);
339 :
340 1 : return 0;
341 : }
342 :
343 1 : static int rectangleIsRejectedS(void)
344 : {
345 1 : struct Rect rect;
346 1 : struct Rect clip;
347 : int ret;
348 :
349 1 : clip.left = 20;
350 1 : clip.top = 20;
351 1 : clip.right = 30;
352 1 : clip.bottom = 30;
353 :
354 1 : rect.left = 20;
355 1 : rect.top = 31;
356 1 : rect.right = 30;
357 1 : rect.bottom = 35;
358 :
359 1 : ret = ClipRect(&rect, &clip);
360 :
361 1 : TEST_EQ(ret, CLIP_REJECTED);
362 :
363 1 : return 0;
364 : }
365 :
366 1 : static int rectangleIsRejectedSW(void)
367 : {
368 1 : struct Rect rect;
369 1 : struct Rect clip;
370 : int ret;
371 :
372 1 : clip.left = 20;
373 1 : clip.top = 20;
374 1 : clip.right = 30;
375 1 : clip.bottom = 30;
376 :
377 1 : rect.left = 15;
378 1 : rect.top = 30;
379 1 : rect.right = 19;
380 1 : rect.bottom = 35;
381 :
382 1 : ret = ClipRect(&rect, &clip);
383 :
384 1 : TEST_EQ(ret, CLIP_REJECTED);
385 :
386 1 : return 0;
387 : }
388 :
389 1 : static int rectangleIsRejectedW(void)
390 : {
391 1 : struct Rect rect;
392 1 : struct Rect clip;
393 : int ret;
394 :
395 1 : clip.left = 20;
396 1 : clip.top = 20;
397 1 : clip.right = 30;
398 1 : clip.bottom = 30;
399 :
400 1 : rect.left = 15;
401 1 : rect.top = 20;
402 1 : rect.right = 19;
403 1 : rect.bottom = 29;
404 :
405 1 : ret = ClipRect(&rect, &clip);
406 :
407 1 : TEST_EQ(ret, CLIP_REJECTED);
408 :
409 1 : return 0;
410 : }
411 :
412 1 : static int rectangleIsNoChange(void)
413 : {
414 1 : struct Rect rect;
415 1 : struct Rect clip;
416 : int ret;
417 :
418 1 : clip.left = 20;
419 1 : clip.top = 20;
420 1 : clip.right = 30;
421 1 : clip.bottom = 30;
422 :
423 1 : rect.left = 20;
424 1 : rect.top = 20;
425 1 : rect.right = 29;
426 1 : rect.bottom = 29;
427 :
428 1 : ret = ClipRect(&rect, &clip);
429 :
430 1 : TEST_EQ(ret, CLIP_NO_CHANGE);
431 :
432 1 : return 0;
433 : }
434 :
435 1 : static int rectangleAdjustClipS(void)
436 : {
437 1 : struct Rect dst;
438 1 : struct Rect src;
439 1 : struct Rect clip;
440 : int ret;
441 :
442 1 : clip.left = 20;
443 1 : clip.top = 20;
444 1 : clip.right = 30;
445 1 : clip.bottom = 30;
446 :
447 1 : dst.left = 25;
448 1 : dst.top = 25;
449 1 : dst.right = 35;
450 1 : dst.bottom = 35;
451 :
452 1 : src.left = 0;
453 1 : src.top = 0;
454 1 : src.right = 10;
455 1 : src.bottom = 10;
456 :
457 1 : ret = ClipRectAdjust(&dst, &src, &clip);
458 :
459 1 : TEST_EQ(ret, CLIP_CLIPPED);
460 :
461 1 : TEST_EQ(dst.left, 25);
462 1 : TEST_EQ(dst.top, 25);
463 1 : TEST_EQ(dst.right, 30);
464 1 : TEST_EQ(dst.bottom, 30);
465 :
466 1 : TEST_EQ(src.left, 0);
467 1 : TEST_EQ(src.top, 0);
468 1 : TEST_EQ(src.right, 5);
469 1 : TEST_EQ(src.bottom, 5);
470 :
471 1 : return 0;
472 : }
473 :
474 1 : int rectUnionOverlap(void)
475 : {
476 1 : struct Rect a;
477 1 : struct Rect b;
478 1 : struct Rect u;
479 : int ret;
480 :
481 1 : a.left = 0;
482 1 : a.top = 0;
483 1 : a.right = 10;
484 1 : a.bottom = 10;
485 :
486 1 : b.left = 5;
487 1 : b.top = 5;
488 1 : b.right = 15;
489 1 : b.bottom = 15;
490 :
491 1 : u.left = -1;
492 1 : u.top = -1;
493 1 : u.right = -1;
494 1 : u.bottom = -1;
495 :
496 1 : ret = RectUnion(&a, &b, &u);
497 :
498 1 : TEST_EQ(ret, 0);
499 1 : TEST_EQ(u.left, 0);
500 1 : TEST_EQ(u.top, 0);
501 1 : TEST_EQ(u.right, 15);
502 1 : TEST_EQ(u.bottom, 15);
503 :
504 1 : return 0;
505 : }
506 :
507 1 : int rectUnionEmptyIsSelf(void)
508 : {
509 1 : struct Rect self;
510 1 : struct Rect empty;
511 1 : struct Rect u;
512 : int ret;
513 :
514 1 : self.left = 10;
515 1 : self.top = 20;
516 1 : self.right = 30;
517 1 : self.bottom = 40;
518 :
519 1 : empty.left = 0;
520 1 : empty.top = 0;
521 1 : empty.right = 0;
522 1 : empty.bottom = 0;
523 :
524 1 : u.left = -1;
525 1 : u.top = -1;
526 1 : u.right = -1;
527 1 : u.bottom = -1;
528 :
529 1 : ret = RectUnion(&empty, &self, &u);
530 :
531 1 : TEST_EQ(ret, 0);
532 1 : TEST_EQ(u.left, self.left);
533 1 : TEST_EQ(u.top, self.top);
534 1 : TEST_EQ(u.right, self.right);
535 1 : TEST_EQ(u.bottom, self.bottom);
536 :
537 1 : return 0;
538 : }
539 :
540 1 : int rectUnionWithEmptyFirstIsSelf(void)
541 : {
542 1 : struct Rect self;
543 1 : struct Rect empty;
544 : int ret;
545 :
546 1 : self.left = 10;
547 1 : self.top = 20;
548 1 : self.right = 30;
549 1 : self.bottom = 40;
550 :
551 1 : empty.left = 0;
552 1 : empty.top = 0;
553 1 : empty.right = 0;
554 1 : empty.bottom = 0;
555 :
556 1 : ret = RectUnion(&empty, &self, &self);
557 :
558 1 : TEST_EQ(ret, 0);
559 1 : TEST_EQ(self.left, 10);
560 1 : TEST_EQ(self.top, 20);
561 1 : TEST_EQ(self.right, 30);
562 1 : TEST_EQ(self.bottom, 40);
563 :
564 1 : return 0;
565 : }
566 :
567 1 : int rectUnionWithEmptySecondIsSelf(void)
568 : {
569 1 : struct Rect self;
570 1 : struct Rect empty;
571 : int ret;
572 :
573 1 : self.left = 10;
574 1 : self.top = 20;
575 1 : self.right = 30;
576 1 : self.bottom = 40;
577 :
578 1 : empty.left = 0;
579 1 : empty.top = 0;
580 1 : empty.right = 0;
581 1 : empty.bottom = 0;
582 :
583 1 : ret = RectUnion(&self, &empty, &self);
584 :
585 1 : TEST_EQ(ret, 0);
586 1 : TEST_EQ(self.left, 10);
587 1 : TEST_EQ(self.top, 20);
588 1 : TEST_EQ(self.right, 30);
589 1 : TEST_EQ(self.bottom, 40);
590 :
591 1 : return 0;
592 : }
593 :
594 1 : int rectIntersectOverlap(void)
595 : {
596 1 : struct Rect a;
597 1 : struct Rect b;
598 1 : struct Rect i;
599 : int ret;
600 :
601 1 : a.left = 0;
602 1 : a.top = 0;
603 1 : a.right = 10;
604 1 : a.bottom = 10;
605 :
606 1 : b.left = 5;
607 1 : b.top = 5;
608 1 : b.right = 15;
609 1 : b.bottom = 15;
610 :
611 1 : i.left = -1;
612 1 : i.top = -1;
613 1 : i.right = -1;
614 1 : i.bottom = -1;
615 :
616 1 : ret = RectIntersect(&a, &b, &i);
617 :
618 1 : TEST_EQ(ret, RECT_INTERSECT);
619 1 : TEST_EQ(i.left, 5);
620 1 : TEST_EQ(i.top, 5);
621 1 : TEST_EQ(i.right, 10);
622 1 : TEST_EQ(i.bottom, 10);
623 :
624 1 : return 0;
625 : }
626 :
627 1 : int rectIntersectNoOverlap(void)
628 : {
629 1 : struct Rect a;
630 1 : struct Rect b;
631 1 : struct Rect i;
632 : int ret;
633 :
634 1 : a.left = 0;
635 1 : a.top = 0;
636 1 : a.right = 10;
637 1 : a.bottom = 10;
638 :
639 1 : b.left = 15;
640 1 : b.top = 15;
641 1 : b.right = 25;
642 1 : b.bottom = 25;
643 :
644 1 : i.left = -1;
645 1 : i.top = -1;
646 1 : i.right = -1;
647 1 : i.bottom = -1;
648 :
649 1 : ret = RectIntersect(&a, &b, &i);
650 :
651 1 : TEST_EQ(ret, RECT_NO_INTERSECT);
652 :
653 1 : return 0;
654 : }
655 :
656 1 : int rectNormalizedReverseX(void)
657 : {
658 1 : struct Rect r;
659 1 : r.left = 441;
660 1 : r.top = 242;
661 1 : r.right = 378;
662 1 : r.bottom = 266;
663 :
664 1 : NormalizedRect(&r, &r);
665 :
666 1 : TEST_EQ(r.left, 378);
667 1 : TEST_EQ(r.top, 242);
668 1 : TEST_EQ(r.right, 441);
669 1 : TEST_EQ(r.bottom, 266);
670 :
671 1 : return 0;
672 : }
673 :
674 1 : int rectNormalizedForwardX(void)
675 : {
676 1 : struct Rect r;
677 1 : r.left = 378;
678 1 : r.top = 242;
679 1 : r.right = 441;
680 1 : r.bottom = 266;
681 :
682 1 : NormalizedRect(&r, &r);
683 :
684 1 : TEST_EQ(r.left, 378);
685 1 : TEST_EQ(r.top, 242);
686 1 : TEST_EQ(r.right, 441);
687 1 : TEST_EQ(r.bottom, 266);
688 :
689 1 : return 0;
690 : }
691 :
692 1 : int rectNormalizedReverseY(void)
693 : {
694 1 : struct Rect r;
695 1 : r.left = 378;
696 1 : r.top = 266;
697 1 : r.right = 441;
698 1 : r.bottom = 242;
699 :
700 1 : NormalizedRect(&r, &r);
701 :
702 1 : TEST_EQ(r.left, 378);
703 1 : TEST_EQ(r.top, 242);
704 1 : TEST_EQ(r.right, 441);
705 1 : TEST_EQ(r.bottom, 266);
706 :
707 1 : return 0;
708 : }
709 :
710 1 : int rectNormalizedForwardY(void)
711 : {
712 1 : struct Rect r;
713 1 : r.left = 378;
714 1 : r.top = 242;
715 1 : r.right = 441;
716 1 : r.bottom = 266;
717 :
718 1 : NormalizedRect(&r, &r);
719 :
720 1 : TEST_EQ(r.left, 378);
721 1 : TEST_EQ(r.top, 242);
722 1 : TEST_EQ(r.right, 441);
723 1 : TEST_EQ(r.bottom, 266);
724 :
725 1 : return 0;
726 : }
727 :
728 : const test_fn tests[] =
729 : {
730 : rectangleIsClippedNW,
731 :
732 : rectangleIsClippedN,
733 : rectangleIsClippedNE,
734 : rectangleIsClippedE,
735 : rectangleIsClippedSE,
736 : rectangleIsClippedS,
737 : rectangleIsClippedSW,
738 : rectangleIsClippedW,
739 :
740 : rectangleIsRejectedNW,
741 : rectangleIsRejectedN,
742 : rectangleIsRejectedNE,
743 : rectangleIsRejectedE,
744 : rectangleIsRejectedSE,
745 : rectangleIsRejectedS,
746 : rectangleIsRejectedSW,
747 : rectangleIsRejectedW,
748 :
749 : rectangleIsNoChange,
750 :
751 : rectangleAdjustClipS,
752 :
753 : rectUnionOverlap,
754 : rectUnionWithEmptySecondIsSelf,
755 : rectUnionEmptyIsSelf,
756 : rectUnionWithEmptyFirstIsSelf,
757 : rectIntersectOverlap,
758 : rectIntersectNoOverlap,
759 :
760 : rectNormalizedReverseX,
761 : rectNormalizedForwardX,
762 : rectNormalizedReverseY,
763 : rectNormalizedForwardY,
764 :
765 : 0
766 : };
|