microui  14.1.0
microui
ui_rect_util.c
1 /*
2  * C
3  *
4  * Copyright 2024 MicroEJ Corp. All rights reserved.
5  * Use of this source code is governed by a BSD-style license that can be found with this software.
6  */
7 
8 /*
9  * @file
10  * @brief Utility functions to handle rectangles
11  *
12  * @see ui_rect_t
13  *
14  * @author MicroEJ Developer Team
15  * @version 14.1.0
16  */
17 
18 // --------------------------------------------------------------------------------
19 // Includes
20 // --------------------------------------------------------------------------------
21 
22 #include <assert.h>
23 
24 #include "ui_util.h"
25 #include "ui_rect_util.h"
26 
27 // --------------------------------------------------------------------------------
28 // Functions
29 // --------------------------------------------------------------------------------
30 
31 // See the header file for the function documentation
32 ui_rect_t UI_RECT_get_minimum_bounding_rect(const ui_rect_t rects[], const size_t count) {
33  assert(count > 0u);
34  ui_rect_t result = rects[0];
35  for (size_t i = 1; i < count; i++) {
36  result = UI_RECT_get_minimum_bounding_rect_two_rects(&result, &rects[i]);
37  }
38  return result;
39 }
40 
41 // See the header file for the function documentation
42 uint32_t UI_RECT_union(ui_rect_t output[3], const ui_rect_t *first, const ui_rect_t *second) {
43  uint32_t ret;
44  if (UI_RECT_contains_rect(first, second)) {
45  output[0] = *first;
46  UI_RECT_mark_empty(&output[1]);
47  UI_RECT_mark_empty(&output[2]);
48  ret = 1u;
49  } else if (UI_RECT_contains_rect(second, first)) {
50  output[0] = *second;
51  UI_RECT_mark_empty(&output[1]);
52  UI_RECT_mark_empty(&output[2]);
53  ret = 1u;
54  } else if (!UI_RECT_intersects_rect(first, second)) {
55  output[0] = *first;
56  output[1] = *second;
57  UI_RECT_mark_empty(&output[2]);
58  ret = 2u;
59  } else {
60  const ui_rect_t *top_above = (first->y1 < second->y1) ? first : second;
61  const ui_rect_t *top_below = (first->y1 < second->y1) ? second : first;
62  const ui_rect_t *bottom_below = (first->y2 > second->y2) ? first : second;
63  const ui_rect_t *bottom_above = (first->y2 > second->y2) ? second : first;
64 
65  uint32_t count = 0u;
66 
67  output[count] = UI_RECT_new_xyxy(top_above->x1, top_above->y1, top_above->x2, top_below->y1 - 1);
68  if (!UI_RECT_is_empty(output)) {
69  count++;
70  }
71 
72  output[count] = UI_RECT_new_xyxy(MIN(first->x1, second->x1), top_below->y1, MAX(first->x2, second->x2),
73  bottom_above->y2);
74  if (!UI_RECT_is_empty(output)) {
75  count++;
76  }
77 
78  output[count] = UI_RECT_new_xyxy(bottom_below->x1, bottom_above->y2 + 1, bottom_below->x2, bottom_below->y2);
79  if (!UI_RECT_is_empty(output)) {
80  count++;
81  }
82 
83  ret = count;
84  }
85  return ret;
86 }
87 
88 // See the header file for the function documentation
89 uint32_t UI_RECT_subtract(ui_rect_t output[4], const ui_rect_t *first, const ui_rect_t *second) {
90  uint32_t ret;
91  if (UI_RECT_contains_rect(first, second)) {
92  output[0] = UI_RECT_new_xyxy(first->x1, first->y1, first->x2, second->y1 - 1); // Top
93  output[1] = UI_RECT_new_xyxy(first->x1, second->y1, second->x1 - 1, second->y2); // Left
94  output[2] = UI_RECT_new_xyxy(second->x2 + 1, second->y1, first->x2, second->y2); // Right
95  output[3] = UI_RECT_new_xyxy(first->x1, second->y2 + 1, first->x2, first->y2); // Bottom
96  ret = 4u;
97  } else if (UI_RECT_contains_rect(second, first)) {
98  UI_RECT_mark_empty(&output[0]);
99  UI_RECT_mark_empty(&output[1]);
100  UI_RECT_mark_empty(&output[2]);
101  UI_RECT_mark_empty(&output[3]);
102  ret = 0u;
103  } else if (!UI_RECT_intersects_rect(first, second)) {
104  output[0] = *first;
105  UI_RECT_mark_empty(&output[1]);
106  UI_RECT_mark_empty(&output[2]);
107  UI_RECT_mark_empty(&output[3]);
108  ret = 1u;
109  } else {
110  output[0] = UI_RECT_new_xyxy(first->x1, first->y1, first->x2, second->y1 - 1); // Top
111  output[1] = UI_RECT_new_xyxy(first->x1, MAX(first->y1, second->y1), second->x1 - 1, MIN(first->y2, second->y2)); // Left
112  output[2] = UI_RECT_new_xyxy(second->x2 + 1, MAX(first->y1, second->y1), first->x2, MIN(first->y2, second->y2)); // Right
113  output[3] = UI_RECT_new_xyxy(first->x1, second->y2 + 1, first->x2, first->y2); // Bottom
114  ret = 4u;
115  }
116  return ret;
117 }