Files
crosspoint-reader-mod/chat-summaries/2026-03-09_00-44-summary.md
cottongin 1105919359 fix: BookInfo performance — Y-culling, newline normalization, cover clamping
Addressed critical render performance issues identified via device debug log:
- Add Y-culling in render() to skip off-screen draw calls (was causing
  337K LOG_ERR calls per frame, 7-13s render times)
- Normalize description whitespace (strip embedded \n/\r/\t) to prevent
  "No glyph for codepoint 10" errors
- Clamp cover bitmap maxHeight to prevent drawing beyond screen edge
- Pre-compute layout in onEnter() with InfoField struct (wrappedText
  called once, not per frame)
- Add cover image display via generateThumbBmp + drawBitmap1Bit

Made-with: Cursor
2026-03-09 01:52:07 -04:00

2.5 KiB

BookInfoActivity: Performance Fix and Cover Image

Task

Fix BookInfoActivity sluggishness (slow open, unresponsive scrolling) and add book cover display.

Root Cause (from device debug log)

  1. No Y-culling in render(): All text lines drawn even when off-screen. Content extending ~1162px on 800px screen caused hundreds of thousands of LOG_ERR("Outside range") calls per frame, each doing serial I/O. Render times: 7-13 seconds per frame.
  2. Description text contained literal newlines: stripHtml() and trim() in ContentOpfParser don't replace interior \n characters. These got passed to drawText(), triggering "No glyph for codepoint 10" errors.
  3. wrappedText() recomputed every frame: Original render called it for every field on every scroll -- now pre-computed once.
  4. No cover image: Activity never loaded or displayed any cover.

Changes Made

Committed first: PR #1342 port (commit 4cf395a)

  • Staged and committed all prior working state before making further changes

BookInfoActivity refactor (2 files)

src/activities/home/BookInfoActivity.h:

  • Replaced individual metadata string members with InfoField struct + std::vector<InfoField> fields
  • Added coverBmpPath, coverDisplayHeight, coverDisplayWidth members
  • Added buildLayout() method for pre-computation

src/activities/home/BookInfoActivity.cpp:

  • Y-culling: render() skips draw calls for items entirely above or below the visible screen area (y + height > 0 && y < pageH); breaks out of field loop when y >= pageH
  • Newline normalization: Added normalizeWhitespace() helper that collapses \n, \r, \t sequences into single spaces; applied to description text before word-wrapping
  • Cover height clamping: drawBitmap1Bit maxHeight capped to std::min(coverDisplayHeight, pageH - y) to prevent drawing beyond screen
  • Pre-computed layout: All wrappedText() calls moved to onEnter() via buildLayout(); render() only iterates pre-computed lines
  • Cover thumbnail generated via epub.generateThumbBmp() / xtc.generateThumbBmp(); fallback to PlaceholderCoverGenerator
  • Cover rendered centered at top using renderer.drawBitmap1Bit()

Build Verification

  • pio run SUCCESS (19s incremental, RAM 30.3%, Flash 95.7%)

Follow-up Items

  • Hardware test: verify render times dropped from 7-13s to <100ms with Y-culling
  • Hardware test: verify cover image renders correctly
  • Hardware test: verify scroll responsiveness on device