ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
sh_shelf.c
Go to the documentation of this file.
1
20#include <string.h>
21
22#include "ra8_box.h"
23#include "ra8_gfx.h"
24#include "ra8_gfx_font.h"
25#include "sh_app.h"
26
28typedef enum : uint32_t {
33 k_sh_two = 2U,
34 k_sh_card_h = 272U,
36
37void sh_decode_cover(uint16_t idx, const book_src_t* src)
38{
39 g_sh.thumb_w[idx] = 0U;
40 g_sh.thumb_h[idx] = 0U;
41 if (src == nullptr) {
42 return;
43 }
44 const uint32_t cover = src->hdr.cover_image_index;
45 if (cover == k_book_nil) {
46 return;
47 }
48 int32_t w = 0;
49 int32_t h = 0;
51 cover,
52 g_sh.thumb[idx],
53 (int32_t)k_sh_thumb_w,
54 (int32_t)k_sh_thumb_h,
55 &w,
56 &h) == k_ra8_ok) {
57 g_sh.thumb_w[idx] = (uint16_t)w;
58 g_sh.thumb_h[idx] = (uint16_t)h;
59 }
60}
61
63{
64 /* Baked covers are pre-decoded in library.h, so boot just copies the gray8
65 * thumbnail -- no per-book decode (which dominated boot time). SD covers
66 * still load lazily on first open. */
67 for (uint16_t i = 0U; i < g_sh.book_count; ++i) {
68 g_sh.thumb_w[i] = 0U;
69 g_sh.thumb_h[i] = 0U;
70 const sh_entry_t* const e = &g_sh.entry[i];
71 if (e->from_sd || (e->thumb == nullptr)) {
72 continue; /* SD entries get their cover from sh_book_open on first tap */
73 }
74 (void)memcpy(g_sh.thumb[i], e->thumb, (size_t)e->thumb_w * (size_t)e->thumb_h);
75 g_sh.thumb_w[i] = e->thumb_w;
76 g_sh.thumb_h[i] = e->thumb_h;
77 }
78}
79
81static void sh_draw_card(ra8_ui_rect_t r, uint16_t idx)
82{
83 const bool sel = (idx == g_sh.selected);
84 const uint32_t bg = sel ? (uint32_t)k_sh_col_card_hi : (uint32_t)k_sh_col_card;
85 (void)ra8_gfx_rect(r.x, r.y, r.w, r.h, bg, true);
86 sh_border(r,
87 sel ? (uint32_t)k_sh_col_sel : (uint32_t)k_sh_col_edge,
88 sel ? (int32_t)k_sh_sel_border : (int32_t)k_sh_card_bord);
89
90 const int32_t tw = (int32_t)g_sh.thumb_w[idx];
91 const int32_t th = (int32_t)g_sh.thumb_h[idx];
92 const int32_t cx = r.x + ((r.w - tw) / (int32_t)k_sh_two);
93 const int32_t cy = r.y + (int32_t)k_sh_card_pad;
94 if (tw > 0) {
95 sh_image_blit_gray8(g_sh.thumb[idx], tw, th, cx, cy);
96 sh_border((ra8_ui_rect_t){cx, cy, tw, th}, (uint32_t)k_sh_col_edge, 1);
97 } else {
98 (void)ra8_gfx_rect(cx,
99 cy,
100 (int32_t)k_sh_thumb_w,
101 (int32_t)k_sh_thumb_h,
102 (uint32_t)k_sh_col_edge,
103 false);
104 }
105
106 char buf[k_sh_linebuf];
107 const int32_t inner = r.w - (2 * (int32_t)k_sh_card_pad);
108 const int32_t ty = cy + (int32_t)k_sh_thumb_h + (int32_t)k_sh_title_gap;
109 sh_fit(buf, sizeof buf, g_sh.entry[idx].title, sh_cells(inner));
110 (void)ra8_gfx_text_out(r.x + (int32_t)k_sh_card_pad,
111 ty,
112 buf,
114 (uint32_t)k_sh_col_ink,
115 bg);
116 sh_fit(buf, sizeof buf, g_sh.entry[idx].author, sh_cells(inner));
117 (void)ra8_gfx_text_out(r.x + (int32_t)k_sh_card_pad,
118 ty + (int32_t)k_sh_glyph_h,
119 buf,
121 (uint32_t)k_sh_col_sub,
122 bg);
123}
124
126static uint16_t sh_layout_cards(void)
127{
128 ra8_box_t store[k_sh_box_cap];
129 ra8_box_tree_t tree;
130 if (ra8_box_tree_init(&tree, store, (uint16_t)k_sh_box_cap) != k_ra8_ok) {
131 return 0U;
132 }
133 const ra8_box_t grid = {.kind = k_ra8_box_grid,
134 .grid_cols = (uint8_t)k_sh_grid_cols,
135 .flex = 1U,
136 .pad = (int16_t)k_sh_pad,
137 .gap = (int16_t)k_sh_gap};
138 const int16_t gi = ra8_box_add(&tree, (int16_t)k_ra8_box_none, &grid);
139 for (uint16_t i = 0U; i < g_sh.book_count; ++i) {
140 const ra8_box_t cell = {.kind = k_ra8_box_leaf, .flex = 1U, .tag = (int16_t)i};
141 (void)ra8_box_add(&tree, gi, &cell);
142 }
143 const int32_t rows =
144 (int32_t)((g_sh.book_count + (uint16_t)k_sh_grid_cols - 1U) / (uint16_t)k_sh_grid_cols);
145 const int32_t avail = (int32_t)k_sh_fb_h - (int32_t)k_sh_bar_h;
146 int32_t ah = (rows * (int32_t)k_sh_card_h) + (int32_t)k_sh_pad;
147 if (ah > avail) {
148 ah = avail;
149 }
150 const ra8_ui_rect_t area = {.x = 0, .y = (int32_t)k_sh_bar_h, .w = (int32_t)k_sh_fb_w, .h = ah};
151 if (ra8_box_layout(&tree, gi, &area) != k_ra8_ok) {
152 return 0U;
153 }
154 for (uint16_t i = 0U; i < g_sh.book_count; ++i) {
155 g_sh.card_rect[i] = store[(size_t)gi + 1U + (size_t)i].rect;
156 }
157 return g_sh.book_count;
158}
159
161{
162 (void)ra8_gfx_clear((uint32_t)k_sh_col_bg);
163 sh_titlebar("Library", g_sh.sd_ready ? "SD + baked" : "baked");
164 const uint16_t n = sh_layout_cards();
165 for (uint16_t i = 0U; i < n; ++i) {
166 sh_draw_card(g_sh.card_rect[i], i);
167 }
168}
169
170int32_t sh_shelf_hit(int32_t x, int32_t y)
171{
172 for (uint16_t i = 0U; i < g_sh.book_count; ++i) {
173 const ra8_ui_rect_t r = g_sh.card_rect[i];
174 if ((x >= r.x) && (x < (r.x + r.w)) && (y >= r.y) && (y < (r.y + r.h))) {
175 return (int32_t)i;
176 }
177 }
178 return -1;
179}
@ k_book_nil
Absent index / "applies to all chapters".
Definition book.h:129
Bounded, allocation-free box-model layout for e-reader chrome.
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
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
@ k_ra8_box_none
No child / no sibling link.
Definition ra8_box.h:57
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
@ 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_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
Software 2D graphics primitives layered on top of a caller-ownedframebuffer (DRW / D/AVE 2D / GLCDC r...
ra8_err_t ra8_gfx_clear(uint32_t color)
Fill the bound framebuffer's clip region with a single colour.
ra8_err_t ra8_gfx_text_out(int32_t x, int32_t y, const char *str, const ra8_gfx_font_t *font, uint32_t fg_color, uint32_t bg_color)
Render a NUL-terminated ASCII string.
ra8_err_t ra8_gfx_rect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color, bool filled)
Draw an axis-aligned rectangle.
Bitmap font descriptor + bundled font handles for ra8_gfx.
const ra8_gfx_font_t ra8_gfx_font_8x16
Bundled 8x16 IBM PC VGA bitmap font, ASCII 0x20..0x7E.
Shared contract for the ereader_shelf multi-screen e-reader.
int32_t sh_cells(int32_t pixels)
Cells of the 8px bitmap font that fit in pixels.
Definition sh_util.c:28
ra8_err_t sh_image_decode_gray8(const book_src_t *src, uint32_t img_idx, uint8_t *out, int32_t box_w, int32_t box_h, int32_t *out_w, int32_t *out_h)
Decode a 4bpp grayscale image, aspect-fit-scale it into box, and write the result into a gray8 buffer...
Definition sh_image.c:174
void sh_border(ra8_ui_rect_t r, uint32_t colour, int32_t width)
Draw a width-thick rectangle outline in colour.
Definition sh_util.c:69
void sh_titlebar(const char *title, const char *right)
Fill the header bar and draw title left + optional right text.
Definition sh_util.c:76
@ k_sh_gap
Gap between shelf cards.
Definition sh_app.h:53
@ k_sh_thumb_h
Shelf cover-thumbnail box height.
Definition sh_app.h:56
@ k_sh_glyph_h
Bitmap font cell height.
Definition sh_app.h:49
@ k_sh_fb_h
Panel height in pixels.
Definition sh_app.h:47
@ k_sh_pad
Outer margin / content inset.
Definition sh_app.h:52
@ k_sh_thumb_w
Shelf cover-thumbnail box width.
Definition sh_app.h:55
@ k_sh_bar_h
Header / title-bar height.
Definition sh_app.h:51
@ k_sh_linebuf
Per-line draw buffer bytes.
Definition sh_app.h:59
@ k_sh_fb_w
Panel width in pixels.
Definition sh_app.h:46
@ k_sh_grid_cols
Shelf grid columns.
Definition sh_app.h:57
@ k_sh_card_pad
Inner card inset.
Definition sh_app.h:54
void sh_image_blit_gray8(const uint8_t *src, int32_t w, int32_t h, int32_t dst_x, int32_t dst_y)
Blit a gray8 bitmap to the bound framebuffer at dst_x, dst_y.
Definition sh_image.c:208
sh_state_t g_sh
The single whole-app state instance (defined in main.c).
Definition main.c:64
void sh_fit(char *dst, size_t cap, const char *src, int32_t max_chars)
Copy src into dst (cap bytes), truncating past max_chars with "..".
Definition sh_util.c:33
@ k_sh_col_edge
Card / image border.
Definition sh_app.h:104
@ k_sh_col_card_hi
Selected card fill.
Definition sh_app.h:101
@ k_sh_col_bg
App background (dark wood).
Definition sh_app.h:98
@ k_sh_col_ink
Body ink.
Definition sh_app.h:102
@ k_sh_col_card
Card / page fill (paper).
Definition sh_app.h:100
@ k_sh_col_sub
Secondary ink (author / hints).
Definition sh_app.h:103
@ k_sh_col_sel
Selection accent (amber).
Definition sh_app.h:105
@ k_sh_two
Centring divisor / half-extent divisor.
Definition sh_image.c:32
void sh_decode_cover(uint16_t idx, const book_src_t *src)
Decode the open rabook source's 4bpp cover into thumbnail slot idx.
Definition sh_shelf.c:37
void sh_shelf_build_thumbs(void)
Copy the baked books' pre-decoded covers into sh_state_t::thumb at boot.
Definition sh_shelf.c:62
static uint16_t sh_layout_cards(void)
Lay out the shelf grid into sh_state_t::card_rect; returns count placed.
Definition sh_shelf.c:126
int32_t sh_shelf_hit(int32_t x, int32_t y)
Hit-test a shelf tap; returns the book index or -1.
Definition sh_shelf.c:170
static void sh_draw_card(ra8_ui_rect_t r, uint16_t idx)
Draw one book card: cover thumbnail (or placeholder) + title + author.
Definition sh_shelf.c:81
sh_shelf_const_t
Shelf-layout constants.
Definition sh_shelf.c:28
@ k_sh_sel_border
Selected card border width.
Definition sh_shelf.c:30
@ k_sh_title_gap
Cover-to-title vertical gap.
Definition sh_shelf.c:32
@ k_sh_box_cap
ra8_box scratch node capacity.
Definition sh_shelf.c:29
@ k_sh_card_h
Card height (cover box + 2 text lines + insets).
Definition sh_shelf.c:34
@ k_sh_card_bord
Idle card border width.
Definition sh_shelf.c:31
void sh_shelf_render(void)
Render the shelf grid (cover cards) into the framebuffer.
Definition sh_shelf.c:160
uint32_t cover_image_index
Image-table index of the cover, or nil.
Definition book.h:255
A book data source: resident (zero-copy) or paged (demand-fetched).
Definition book_paged.h:69
book_header_t hdr
Resident copy of the blob header.
Definition book_paged.h:75
One node in a box tree (caller-owned).
Definition ra8_box.h:90
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
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
One shelf book, sourced from MRAM (baked) or the SD card, in either the .rabook or ....
Definition sh_app.h:141
bool from_sd
true: read sd_name from SD; false: use blob.
Definition sh_app.h:142
uint16_t thumb_w
Pre-baked thumbnail width.
Definition sh_app.h:147
uint16_t thumb_h
Pre-baked thumbnail height.
Definition sh_app.h:148
const uint8_t * thumb
Pre-baked gray8 cover thumbnail, or NULL.
Definition sh_app.h:146