36 {0x2014U,
"--"}, {0x2013U,
"-"}, {0x2012U,
"-"}, {0x2010U,
"-"}, {0x2011U,
"-"},
37 {0x2018U,
"'"}, {0x2019U,
"'"}, {0x201AU,
"'"}, {0x2032U,
"'"}, {0x201CU,
"\""},
38 {0x201DU,
"\""}, {0x201EU,
"\""}, {0x2033U,
"\""}, {0x2026U,
"..."}, {0x00A0U,
" "},
39 {0x2007U,
" "}, {0x2009U,
" "}, {0x202FU,
" "}, {0x200AU,
" "}, {0x2002U,
" "},
44typedef enum : uint32_t {
59typedef enum : uint8_t {
67 const uint8_t b = s[0];
101 while (r <
g_sh.text_len) {
106 g_sh.text[w++] = (char)cp;
119 while ((i <
g_sh.text_len) && (
g_sh.text[i] !=
' ') && (
g_sh.text[i] !=
'\n')) {
126static size_t sh_wrap_line(
size_t i, int32_t chars,
size_t* ls,
size_t* le)
128 while ((i <
g_sh.text_len) && (
g_sh.text[i] ==
' ')) {
134 while (i <
g_sh.text_len) {
135 if (
g_sh.text[i] ==
'\n') {
141 const int32_t need = (col > 0 ? col + 1 : 0) + (int32_t)(we - ws);
142 if ((col > 0) && (need > chars)) {
146 i = ((we <
g_sh.text_len) && (
g_sh.text[we] ==
' ')) ? (we + 1U) : we;
156 g_sh.line_count = 0U;
162 if (ls >=
g_sh.text_len) {
165 g_sh.lines[
g_sh.line_count].off = (uint32_t)ls;
166 g_sh.lines[
g_sh.line_count].len = (uint16_t)(le - ls);
179 g_sh.chapter = chapter;
189 uint32_t pages = (lpp == 0U) ? 1U : ((
g_sh.line_count + lpp - 1U) / lpp);
190 g_sh.chap_pages = (pages == 0U) ? 1U : pages;
194typedef enum : uint32_t {
200 for (uint32_t c = 0U; c <
g_sh.chapter_count; ++c) {
230 const uint32_t first =
g_sh.page * lpp;
232 for (uint32_t r = 0U; r < lpp; ++r) {
233 const uint32_t li = first + r;
234 if (li >=
g_sh.line_count) {
237 uint16_t len =
g_sh.lines[li].len;
238 if (len >= (uint16_t)
sizeof line) {
239 len = (uint16_t)
sizeof line - 1U;
257 if ((
g_sh.page + 1U) <
g_sh.chap_pages) {
261 if ((
g_sh.chapter + 1U) <
g_sh.chapter_count) {
268 if (
g_sh.page > 0U) {
272 if (
g_sh.chapter > 0U) {
274 g_sh.page = (
g_sh.chap_pages > 0U) ? (
g_sh.chap_pages - 1U) : 0U;
287 if (
g_sh.book_src.vm ==
nullptr) {
290 const uint32_t ch =
g_sh.chapter;
291 if ((ch + 1U) <
g_sh.chapter_count) {
ra8_err_t book_src_prefetch_chapter(const book_src_t *src, uint32_t chapter_idx)
Warm the cache frame holding a chapter's first content bytes, without pinning it (single-threaded rea...
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
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.
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.
void sh_titlebar(const char *title, const char *right)
Fill the header bar and draw title left + optional right text.
ra8_err_t sh_book_chapter_text(uint32_t chapter, char *out, size_t cap, size_t *out_len)
Extract one chapter's plain text from the open book (either backend).
@ k_sh_line_h
Reader text line height.
@ k_sh_fb_h
Panel height in pixels.
@ k_sh_pad
Outer margin / content inset.
@ k_sh_bar_h
Header / title-bar height.
@ k_sh_linebuf
Per-line draw buffer bytes.
@ k_sh_max_lines
Max wrapped reader lines per chapter.
@ k_sh_fb_w
Panel width in pixels.
@ k_sh_card_pad
Inner card inset.
size_t sh_fmt_uint(char *dst, size_t pos, uint32_t v)
Append unsigned v as decimal into dst at pos; returns new pos.
sh_state_t g_sh
The single whole-app state instance (defined in main.c).
@ k_sh_col_card
Card / page fill (paper).
@ k_sh_fmt_rabook
book RBKC container (demand-paged chunks).
static size_t sh_skip_word(size_t i)
Skip the next word in the text at i; returns the index past it.
bool sh_reader_turn(int32_t dir)
Turn the reader page by dir (-1/+1) across chapters; returns changed.
uint32_t sh_reader_first_content(void)
First chapter with substantial prose (skips title/imprint front matter).
void sh_reader_load_chapter(uint32_t chapter)
Load + wrap a chapter into the reader working set.
sh_u8_t
UTF-8 lead/continuation masks.
@ k_sh_u8_data3
3-byte payload bits.
@ k_sh_u8_lead2
2-byte lead prefix.
@ k_sh_u8_mask3
3-byte lead mask.
@ k_sh_u8_ascii
Below this: bare ASCII.
@ k_sh_u8_lead4
4-byte lead prefix.
@ k_sh_u8_lead3
3-byte lead prefix.
@ k_sh_u8_repl
U+FFFD replacement.
@ k_sh_u8_data2
2-byte payload bits.
@ k_sh_u8_mask4
4-byte lead mask.
@ k_sh_u8_mask2
2-byte lead mask.
@ k_sh_u8_cont
Continuation payload bits.
static void sh_ascii_fold(void)
Fold sh_state_t::text in place from UTF-8 to ASCII.
static uint32_t sh_lines_per_page(void)
Reader lines that fit on one page.
static void sh_reader_wrap(int32_t chars)
Greedy word-wrap sh_state_t::text into sh_state_t::lines.
void sh_reader_render(void)
Render the current reader page.
void sh_reader_prefetch_adjacent(void)
Read-ahead warm the adjacent chapters into the page cache (#207).
static const char * sh_fold_lookup(uint32_t cp)
ASCII replacement for code point cp; "" to drop it.
static const sh_fold_t k_sh_fold[]
Punctuation the ASCII bitmap font cannot draw, folded to ASCII.
static size_t sh_wrap_line(size_t i, int32_t chars, size_t *ls, size_t *le)
Wrap one line from i; store [*ls,*le); return the next index.
sh_content_const_t
Front-matter skip threshold.
@ k_sh_content_min
Min chars to treat a chapter as readable prose.
sh_u8_shift_t
Continuation-byte shifts.
@ k_sh_u8_sh12
Two continuation bytes.
@ k_sh_u8_sh6
One continuation byte.
static size_t sh_utf8_decode(const uint8_t *s, size_t n, uint32_t *cp)
Decode one UTF-8 sequence at s; sets cp, returns bytes consumed.
One typographic-Unicode -> ASCII substitution.
const char * rep
ASCII replacement ("" drops the char).
uint32_t cp
Source Unicode code point.