ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_box.c
Go to the documentation of this file.
1
17
18#include "ra8_box.h"
19
20#include <stddef.h>
21#include <stdint.h>
22
23#include "ra8_attributes.h"
24#include "ra8_check.h"
25#include "ra8_err.h"
26#include "ra8_ui.h"
27
29static const char* const s_tag = "ra8_box";
30
53{
55 r.x = outer.x + pad;
56 r.y = outer.y + pad;
57 r.w = outer.w - (2 * pad);
58 r.h = outer.h - (2 * pad);
59 if (r.w < 0) {
60 r.w = 0;
61 }
62 if (r.h < 0) {
63 r.h = 0;
64 }
65 return r;
66}
67
94RA8_INTERNAL static bool internal_iter_live(int32_t link, uint16_t guard, uint16_t count)
95{
96 /*
97 * The (guard < count) clause is a NASA Power-of-10 Rule 2 defensive iteration
98 * bound. Every sibling/child chain built through the public ra8_box API is
99 * acyclic and terminates when `link` becomes k_ra8_box_none, before `guard`
100 * can ever reach `count`. guard >= count is reachable only on a corrupted
101 * (cyclic) tree that no public-API sequence produces, so the second condition
102 * cannot be given independent MC/DC influence on any reachable path.
103 */
104 /* mcdc-deactivated: guard<count is an acyclic-tree cycle bound; guard>=count is unreachable via the public API. */
105 return (link != (int32_t)k_ra8_box_none) && (guard < count);
106}
107
132 int16_t parent,
133 uint16_t* out_count,
134 int32_t* out_fixed,
135 uint32_t* out_flex)
136{
137 uint16_t n = 0U;
138 int32_t fixed = 0;
139 uint32_t flex = 0U;
140 int32_t c = tree->nodes[parent].first_child;
141 for (uint16_t guard = 0U; internal_iter_live(c, guard, tree->count); ++guard) {
142 const ra8_box_t* child = &tree->nodes[c];
143 if (child->fixed > 0) {
144 fixed += (int32_t)child->fixed;
145 } else {
146 flex += (uint32_t)child->flex;
147 }
148 n++;
149 c = child->next;
150 }
151 *out_count = n;
152 *out_fixed = fixed;
153 *out_flex = flex;
154}
155
178RA8_INTERNAL static void
179internal_layout_stack(ra8_box_tree_t* tree, int16_t parent, bool horizontal)
180{
181 const ra8_box_t* p = &tree->nodes[parent];
182 const ra8_ui_rect_t cont = internal_inset(p->rect, (int32_t)p->pad);
183 const int32_t gap = (int32_t)p->gap;
184
185 uint16_t n = 0U;
186 int32_t fixed = 0;
187 uint32_t flex = 0U;
188 internal_tally(tree, parent, &n, &fixed, &flex);
189
190 const int32_t main_extent = horizontal ? cont.w : cont.h;
191 const int32_t gaps = (n > 0U) ? ((int32_t)(n - 1U) * gap) : 0;
192 int32_t flex_space = main_extent - fixed - gaps;
193 if (flex_space < 0) {
194 flex_space = 0;
195 }
196
197 int32_t cursor = horizontal ? cont.x : cont.y;
198 int32_t c = p->first_child;
199 for (uint16_t guard = 0U; internal_iter_live(c, guard, tree->count); ++guard) {
200 ra8_box_t* child = &tree->nodes[c];
201 int32_t main_sz;
202 if (child->fixed > 0) {
203 main_sz = (int32_t)child->fixed;
204 } else if (flex > 0U) {
205 main_sz = (flex_space * (int32_t)child->flex) / (int32_t)flex;
206 } else {
207 main_sz = 0;
208 }
209 if (horizontal) {
210 child->rect.x = cursor;
211 child->rect.y = cont.y;
212 child->rect.w = main_sz;
213 child->rect.h = cont.h;
214 } else {
215 child->rect.x = cont.x;
216 child->rect.y = cursor;
217 child->rect.w = cont.w;
218 child->rect.h = main_sz;
219 }
220 cursor += main_sz + gap;
221 c = child->next;
222 }
223}
224
246RA8_INTERNAL static void internal_layout_grid(ra8_box_tree_t* tree, int16_t parent)
247{
248 const ra8_box_t* p = &tree->nodes[parent];
249 const ra8_ui_rect_t cont = internal_inset(p->rect, (int32_t)p->pad);
250 const int32_t gap = (int32_t)p->gap;
251 const int32_t cols = (p->grid_cols >= 1U) ? (int32_t)p->grid_cols : 1;
252
253 uint16_t n = 0U;
254 int32_t fixed = 0;
255 uint32_t flex = 0U;
256 internal_tally(tree, parent, &n, &fixed, &flex);
257
258 const int32_t rows = ((int32_t)n + cols - 1) / cols;
259 const int32_t row_cnt = (rows > 0) ? rows : 1;
260 int32_t cell_w = (cont.w - ((cols - 1) * gap)) / cols;
261 if (cell_w < 0) {
262 cell_w = 0;
263 }
264 int32_t cell_h = (cont.h - ((row_cnt - 1) * gap)) / row_cnt;
265 if (cell_h < 0) {
266 cell_h = 0;
267 }
268
269 int32_t idx = 0;
270 int32_t c = p->first_child;
271 for (uint16_t guard = 0U; internal_iter_live(c, guard, tree->count); ++guard) {
272 ra8_box_t* child = &tree->nodes[c];
273 const int32_t col = idx % cols;
274 const int32_t row = idx / cols;
275 child->rect.x = cont.x + (col * (cell_w + gap));
276 child->rect.y = cont.y + (row * (cell_h + gap));
277 child->rect.w = cell_w;
278 child->rect.h = (child->fixed > 0) ? (int32_t)child->fixed : cell_h;
279 idx++;
280 c = child->next;
281 }
282}
283
285{
286 RA8_CHECK_NULL_PTR(tree, s_tag, "tree must not be nullptr");
287 RA8_CHECK_NULL_PTR(storage, s_tag, "storage must not be nullptr");
288 if (cap == 0U) {
290 }
291 tree->nodes = storage;
292 tree->cap = cap;
293 tree->count = 0U;
294 return k_ra8_ok;
295}
296
297int16_t ra8_box_add(ra8_box_tree_t* tree, int16_t parent, const ra8_box_t* node)
298{
299 if ((tree == nullptr) || (node == nullptr)) {
300 return (int16_t)k_ra8_box_none;
301 }
302 if (tree->count >= tree->cap) {
303 return (int16_t)k_ra8_box_none;
304 }
305 if ((parent != (int16_t)k_ra8_box_none) && ((parent < 0) || (parent >= (int16_t)tree->count))) {
306 return (int16_t)k_ra8_box_none;
307 }
308
309 const int16_t idx = (int16_t)tree->count;
310 tree->nodes[idx] = *node;
311 tree->nodes[idx].first_child = (int32_t)k_ra8_box_none;
312 tree->nodes[idx].next = (int32_t)k_ra8_box_none;
313 tree->count++;
314
315 if (parent != (int16_t)k_ra8_box_none) {
316 ra8_box_t* par = &tree->nodes[parent];
317 if (par->first_child == (int32_t)k_ra8_box_none) {
318 par->first_child = (int32_t)idx;
319 } else {
320 int32_t sib = par->first_child;
321 for (uint16_t guard = 0U; internal_iter_live(tree->nodes[sib].next, guard, tree->count);
322 ++guard) {
323 sib = tree->nodes[sib].next;
324 }
325 tree->nodes[sib].next = (int32_t)idx;
326 }
327 }
328 return idx;
329}
330
331ra8_err_t ra8_box_layout(ra8_box_tree_t* tree, int16_t root, const ra8_ui_rect_t* frame)
332{
333 RA8_CHECK_NULL_PTR(tree, s_tag, "tree must not be nullptr");
334 RA8_CHECK_NULL_PTR(frame, s_tag, "frame must not be nullptr");
335 if ((tree->count == 0U) || (root < 0) || (root >= (int16_t)tree->count)) {
337 }
338
339 tree->nodes[root].rect = *frame;
340 for (uint16_t i = 0U; i < tree->count; ++i) {
341 switch ((ra8_box_kind_t)tree->nodes[i].kind) {
343 internal_layout_stack(tree, (int16_t)i, false);
344 break;
346 internal_layout_stack(tree, (int16_t)i, true);
347 break;
348 case k_ra8_box_grid:
349 internal_layout_grid(tree, (int16_t)i);
350 break;
351 case k_ra8_box_leaf:
352 default:
353 break;
354 }
355 }
356 return k_ra8_ok;
357}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
ra8_err_t ra8_box_tree_init(ra8_box_tree_t *tree, ra8_box_t *storage, uint16_t cap)
Bind a tree builder to caller-owned node storage.
Definition ra8_box.c:284
static void internal_tally(const ra8_box_tree_t *tree, int16_t parent, uint16_t *out_count, int32_t *out_fixed, uint32_t *out_flex)
Sum child count, fixed extent, and flex weight of a container.
Definition ra8_box.c:131
static ra8_ui_rect_t internal_inset(ra8_ui_rect_t outer, int32_t pad)
Inset a rectangle by a uniform padding, clamping size to >= 0.
Definition ra8_box.c:52
ra8_err_t ra8_box_layout(ra8_box_tree_t *tree, int16_t root, const ra8_ui_rect_t *frame)
Lay out the tree, filling every node's rect.
Definition ra8_box.c:331
int16_t ra8_box_add(ra8_box_tree_t *tree, int16_t parent, const ra8_box_t *node)
Append a node and link it as a child of parent.
Definition ra8_box.c:297
static void internal_layout_grid(ra8_box_tree_t *tree, int16_t parent)
Lay out a grid container's children row-major.
Definition ra8_box.c:246
static void internal_layout_stack(ra8_box_tree_t *tree, int16_t parent, bool horizontal)
Lay out a stack container's children along one axis.
Definition ra8_box.c:179
static bool internal_iter_live(int32_t link, uint16_t guard, uint16_t count)
Child-walk loop guard: link is live and the bound is not hit.
Definition ra8_box.c:94
Bounded, allocation-free box-model layout for e-reader chrome.
@ k_ra8_box_none
No child / no sibling link.
Definition ra8_box.h:57
ra8_box_kind_t
Box layout kind.
Definition ra8_box.h:65
@ k_ra8_box_stack_v
Vertical stack: children stack top->bottom.
Definition ra8_box.h:66
@ k_ra8_box_grid
Fixed-column grid, row-major.
Definition ra8_box.h:68
@ k_ra8_box_leaf
Terminal box (no children laid out).
Definition ra8_box.h:69
@ k_ra8_box_stack_h
Horizontal stack: children left->right.
Definition ra8_box.h:67
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Bounded UI interaction core: hit-testing, screen stack, paging.
One node in a box tree (caller-owned).
Definition ra8_box.h:90
uint8_t grid_cols
Columns for k_ra8_box_grid (>= 1).
Definition ra8_box.h:92
uint8_t kind
ra8_box_kind_t.
Definition ra8_box.h:91
uint16_t flex
Flex weight when not fixed.
Definition ra8_box.h:94
int32_t first_child
First child index, or k_ra8_box_none.
Definition ra8_box.h:101
int16_t fixed
Fixed main-axis extent; 0 => use flex.
Definition ra8_box.h:93
int16_t gap
Gap between children.
Definition ra8_box.h:96
int32_t next
Next sibling index, or k_ra8_box_none.
Definition ra8_box.h:102
int16_t pad
Inner padding (all four sides).
Definition ra8_box.h:95
ra8_ui_rect_t rect
OUTPUT: computed rectangle.
Definition ra8_box.h:103
Append-only builder over caller-owned node storage.
Definition ra8_box.h:115
uint16_t cap
Capacity of nodes.
Definition ra8_box.h:117
ra8_box_t * nodes
Caller storage.
Definition ra8_box.h:116
uint16_t count
Nodes used.
Definition ra8_box.h:118
Axis-aligned rectangle in framebuffer pixel coordinates.
Definition ra8_ui.h:72
int32_t w
Width (pixels, >= 0).
Definition ra8_ui.h:75
int32_t h
Height (pixels, >= 0).
Definition ra8_ui.h:76
int32_t x
Left edge (pixels).
Definition ra8_ui.h:73
int32_t y
Top edge (pixels).
Definition ra8_ui.h:74