538 lines
14 KiB
Markdown
538 lines
14 KiB
Markdown
|
|
# EPUB Reader Architectural Decisions
|
||
|
|
|
||
|
|
**Date:** 2026-01-23 19:47:23
|
||
|
|
**Status:** Active
|
||
|
|
**Based on:** EPUB 3.3 Compliance Audit
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Purpose
|
||
|
|
|
||
|
|
This document captures architectural decisions about which EPUB 3.3 features to implement, intentionally omit, or defer. Each decision includes rationale based on:
|
||
|
|
|
||
|
|
- Hardware constraints (ESP32-C3, 800x480 4-level grayscale e-ink)
|
||
|
|
- Memory limitations (~400KB SRAM, no PSRAM)
|
||
|
|
- User experience goals
|
||
|
|
- Implementation complexity
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-001: Inline Image Support
|
||
|
|
|
||
|
|
**Status:** RECOMMENDED FOR IMPLEMENTATION
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
EPUBs frequently contain images for:
|
||
|
|
- Cover art
|
||
|
|
- Chapter illustrations
|
||
|
|
- Diagrams and figures
|
||
|
|
- Decorative elements
|
||
|
|
|
||
|
|
Current implementation displays `[Image: alt_text]` placeholder.
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Implement inline image rendering** using existing infrastructure.
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **Infrastructure Exists:**
|
||
|
|
- `Bitmap` class handles BMP parsing with grayscale conversion and dithering
|
||
|
|
- `JpegToBmpConverter` converts JPEG to BMP (most common EPUB image format)
|
||
|
|
- `GfxRenderer::drawBitmap()` already renders bitmaps to e-ink
|
||
|
|
- `ZipFile` can extract files from EPUB archive
|
||
|
|
- Home screen cover rendering demonstrates the pattern works
|
||
|
|
|
||
|
|
2. **Memory Management Pattern:**
|
||
|
|
- Convert and cache images to SD card (like thumbnail generation)
|
||
|
|
- Load one image at a time during page render
|
||
|
|
- Use streaming conversion to minimize RAM usage
|
||
|
|
|
||
|
|
3. **High User Impact:**
|
||
|
|
- Many EPUBs contain important visual content
|
||
|
|
- Technical books rely on diagrams
|
||
|
|
- Children's books heavily use illustrations
|
||
|
|
|
||
|
|
### Implementation Architecture
|
||
|
|
|
||
|
|
```
|
||
|
|
┌────────────────────────────────────────────────────────────────┐
|
||
|
|
│ Image Processing Pipeline │
|
||
|
|
├────────────────────────────────────────────────────────────────┤
|
||
|
|
│ │
|
||
|
|
│ EPUB ZIP ──► Extract Image ──► Convert to BMP ──► Cache to SD │
|
||
|
|
│ │ │ │
|
||
|
|
│ │ ├─ JPEG: JpegToBmpConverter│
|
||
|
|
│ │ └─ BMP: Direct copy │
|
||
|
|
│ │ │
|
||
|
|
│ └─► During page render: │
|
||
|
|
│ Load cached BMP ──► drawBitmap() │
|
||
|
|
│ │
|
||
|
|
└────────────────────────────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### Page Element Structure
|
||
|
|
|
||
|
|
```cpp
|
||
|
|
// New PageImage element (alongside PageLine)
|
||
|
|
class PageImage final : public PageElement {
|
||
|
|
std::string cachedBmpPath; // Path to converted BMP on SD
|
||
|
|
int16_t width;
|
||
|
|
int16_t height;
|
||
|
|
|
||
|
|
public:
|
||
|
|
void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override;
|
||
|
|
bool serialize(FsFile& file) override;
|
||
|
|
static std::unique_ptr<PageImage> deserialize(FsFile& file);
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
### Constraints
|
||
|
|
|
||
|
|
- **No PNG support** initially (would require adding `pngle` library)
|
||
|
|
- **Maximum image size:** Scale to viewport width, max 800x480
|
||
|
|
- **Memory budget:** ~10KB row buffer during conversion
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-002: JavaScript/Scripting Support
|
||
|
|
|
||
|
|
**Status:** INTENTIONALLY OMITTED
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
EPUB 3.3 allows JavaScript in content documents for interactive features.
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Do not implement JavaScript execution.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **Security Risk:**
|
||
|
|
- Untrusted code execution on embedded device
|
||
|
|
- No sandboxing infrastructure
|
||
|
|
- Potential for malicious EPUBs
|
||
|
|
|
||
|
|
2. **Hardware Limitations:**
|
||
|
|
- E-ink display unsuitable for interactive content
|
||
|
|
- Limited RAM for JavaScript engine
|
||
|
|
- No benefit for static reading experience
|
||
|
|
|
||
|
|
3. **Minimal EPUB Use:**
|
||
|
|
- Most EPUBs don't use JavaScript
|
||
|
|
- Interactive textbooks target tablets, not e-readers
|
||
|
|
|
||
|
|
4. **Implementation Complexity:**
|
||
|
|
- Would require embedding V8/Duktape/QuickJS
|
||
|
|
- DOM manipulation engine
|
||
|
|
- Event handling system
|
||
|
|
|
||
|
|
### Alternative
|
||
|
|
|
||
|
|
`<script>` elements are silently ignored. Content remains readable.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-003: Fixed Layout (FXL) Support
|
||
|
|
|
||
|
|
**Status:** INTENTIONALLY OMITTED
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
EPUB Fixed Layout provides pixel-precise page positioning for:
|
||
|
|
- Comic books
|
||
|
|
- Children's picture books
|
||
|
|
- Magazines
|
||
|
|
- Technical drawings with precise layout
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Do not implement Fixed Layout support.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **Display Mismatch:**
|
||
|
|
- FXL designed for high-resolution color tablets
|
||
|
|
- 800x480 grayscale e-ink would require heavy downscaling
|
||
|
|
- Visual quality would be poor
|
||
|
|
|
||
|
|
2. **User Experience:**
|
||
|
|
- FXL EPUBs expect pan/zoom interaction
|
||
|
|
- E-ink refresh rate makes this impractical
|
||
|
|
- Text would be too small to read without zoom
|
||
|
|
|
||
|
|
3. **Implementation Complexity:**
|
||
|
|
- Requires full CSS positioning engine
|
||
|
|
- Viewport meta tag handling
|
||
|
|
- Coordinate transformation system
|
||
|
|
|
||
|
|
### Alternative
|
||
|
|
|
||
|
|
FXL EPUBs will open but may display incorrectly. Users should use reflowable EPUBs on this device.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-004: Audio/Video and Media Overlays
|
||
|
|
|
||
|
|
**Status:** HARDWARE LIMITED - CANNOT IMPLEMENT
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
EPUB 3.3 supports:
|
||
|
|
- `<audio>` and `<video>` elements
|
||
|
|
- Media Overlays (SMIL synchronization)
|
||
|
|
- Text-to-speech hints
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Cannot implement due to hardware constraints.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **No Audio Hardware:**
|
||
|
|
- Device has no speaker or audio DAC
|
||
|
|
- No audio output jack
|
||
|
|
|
||
|
|
2. **No Video Capability:**
|
||
|
|
- E-ink refresh rate (~1 Hz) incompatible with video
|
||
|
|
- No video decoding hardware
|
||
|
|
|
||
|
|
### Alternative
|
||
|
|
|
||
|
|
- Audio/video elements are ignored
|
||
|
|
- Alt text or fallback content displayed if available
|
||
|
|
- Media Overlays not processed
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-005: Color CSS Properties
|
||
|
|
|
||
|
|
**Status:** HARDWARE LIMITED - SIMPLIFIED HANDLING
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
EPUBs use CSS colors for:
|
||
|
|
- Text color (`color`)
|
||
|
|
- Background color (`background-color`)
|
||
|
|
- Border colors
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Ignore color properties; display in grayscale.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **Hardware Constraint:**
|
||
|
|
- Display is 4-level grayscale only
|
||
|
|
- Cannot render colors
|
||
|
|
|
||
|
|
2. **Acceptable Degradation:**
|
||
|
|
- Text remains readable in black
|
||
|
|
- Background remains white
|
||
|
|
- Colored elements appear as gray variations
|
||
|
|
|
||
|
|
### Implementation
|
||
|
|
|
||
|
|
Color CSS properties are parsed but not applied. Default black text on white background used.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-006: Table Rendering
|
||
|
|
|
||
|
|
**Status:** DEFERRED - OPTIONAL IMPLEMENTATION
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
Tables appear in:
|
||
|
|
- Technical documentation
|
||
|
|
- Reference material
|
||
|
|
- Data presentations
|
||
|
|
|
||
|
|
Current implementation shows `[Table omitted]` placeholder.
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Implement simple text-based table rendering as an optional enhancement.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **Moderate Impact:**
|
||
|
|
- Some EPUBs use tables, but not majority
|
||
|
|
- Technical users would benefit most
|
||
|
|
|
||
|
|
2. **Complexity vs. Benefit:**
|
||
|
|
- Full table layout is complex (colspan, rowspan, sizing)
|
||
|
|
- Simple tables can be rendered as text columns
|
||
|
|
|
||
|
|
### Implementation Approach (if implemented)
|
||
|
|
|
||
|
|
```
|
||
|
|
┌──────────────────────────────────────┐
|
||
|
|
│ Text-Based Table Rendering │
|
||
|
|
├──────────────────────────────────────┤
|
||
|
|
│ │
|
||
|
|
│ Header1 │ Header2 │ Header3 │
|
||
|
|
│ ─────────────────────────────────────│
|
||
|
|
│ Data 1 │ Data 2 │ Data 3 │
|
||
|
|
│ Data 4 │ Data 5 │ Data 6 │
|
||
|
|
│ │
|
||
|
|
└──────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### Constraints
|
||
|
|
|
||
|
|
- Equal-width columns (no complex sizing)
|
||
|
|
- No colspan/rowspan support
|
||
|
|
- Truncate wide content
|
||
|
|
- Maximum 4-5 columns before overflow
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-007: SVG and MathML
|
||
|
|
|
||
|
|
**Status:** INTENTIONALLY OMITTED
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
- SVG: Scalable Vector Graphics for illustrations
|
||
|
|
- MathML: Mathematical notation markup
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Do not implement SVG or MathML rendering.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **Implementation Complexity:**
|
||
|
|
- SVG requires full vector graphics engine
|
||
|
|
- MathML requires specialized math typesetting
|
||
|
|
|
||
|
|
2. **Limited Use:**
|
||
|
|
- Most EPUBs use raster images, not SVG
|
||
|
|
- MathML primarily in academic texts
|
||
|
|
|
||
|
|
3. **Alternative Exists:**
|
||
|
|
- Many EPUBs include fallback PNG for SVG
|
||
|
|
- MathML often has image fallback
|
||
|
|
|
||
|
|
### Alternative
|
||
|
|
|
||
|
|
Display alt text or fallback image if available.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-008: CSS Selector Support
|
||
|
|
|
||
|
|
**Status:** CURRENT IMPLEMENTATION SUFFICIENT
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
CSS selectors enable targeting elements for styling. Current support:
|
||
|
|
- Element selectors (`p`, `div`)
|
||
|
|
- Class selectors (`.classname`)
|
||
|
|
- Element.class selectors (`p.intro`)
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Maintain current limited selector support; do not expand.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **Sufficient for Most EPUBs:**
|
||
|
|
- 90%+ of EPUB styling uses simple selectors
|
||
|
|
- Complex selectors rarely affect core readability
|
||
|
|
|
||
|
|
2. **Implementation Complexity:**
|
||
|
|
- Descendant selectors require DOM tree
|
||
|
|
- Pseudo-selectors need state tracking
|
||
|
|
- Specificity calculation is complex
|
||
|
|
|
||
|
|
3. **Memory Constraints:**
|
||
|
|
- DOM tree would consume significant RAM
|
||
|
|
- Current streaming parser is memory-efficient
|
||
|
|
|
||
|
|
### Not Implemented
|
||
|
|
|
||
|
|
- Descendant selectors (`div p`)
|
||
|
|
- Child selectors (`ul > li`)
|
||
|
|
- Sibling selectors (`h1 + p`)
|
||
|
|
- Pseudo-classes (`:first-child`, `:hover`)
|
||
|
|
- Pseudo-elements (`::before`, `::after`)
|
||
|
|
- Attribute selectors (`[type="text"]`)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-009: Internal Link Navigation
|
||
|
|
|
||
|
|
**Status:** RECOMMENDED FOR IMPLEMENTATION (PHASE 2)
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
EPUBs use internal links for:
|
||
|
|
- Footnotes
|
||
|
|
- Cross-references
|
||
|
|
- Table of contents
|
||
|
|
- Index entries
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Implement internal link navigation in Phase 2.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **User Value:**
|
||
|
|
- Footnotes are common in non-fiction
|
||
|
|
- Reference navigation improves usability
|
||
|
|
|
||
|
|
2. **Complexity:**
|
||
|
|
- Requires anchor parsing and storage
|
||
|
|
- Needs selection UI for link activation
|
||
|
|
- Cross-chapter navigation adds complexity
|
||
|
|
|
||
|
|
### Implementation Architecture
|
||
|
|
|
||
|
|
```
|
||
|
|
Link Navigation Flow:
|
||
|
|
1. Parse <a href="#id"> during HTML parsing
|
||
|
|
2. Store link targets in PageLine metadata
|
||
|
|
3. Add link highlighting (underline or marker)
|
||
|
|
4. User selects link via UI
|
||
|
|
5. Resolve target: same chapter (anchor) or cross-chapter (spine + anchor)
|
||
|
|
6. Navigate to target page/position
|
||
|
|
```
|
||
|
|
|
||
|
|
### Deferred
|
||
|
|
|
||
|
|
- External links (http://) - no network navigation on e-reader
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-010: DRM and Encryption
|
||
|
|
|
||
|
|
**Status:** INTENTIONALLY OMITTED
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
EPUB supports DRM through:
|
||
|
|
- `encryption.xml` in META-INF
|
||
|
|
- Adobe DRM
|
||
|
|
- Various proprietary schemes
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Do not implement DRM support.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **Licensing Complexity:**
|
||
|
|
- Adobe DRM requires licensing agreements
|
||
|
|
- Proprietary schemes have legal restrictions
|
||
|
|
|
||
|
|
2. **User Expectation:**
|
||
|
|
- Open-source e-reader users expect DRM-free content
|
||
|
|
- DRM conflicts with device modification philosophy
|
||
|
|
|
||
|
|
3. **Implementation Complexity:**
|
||
|
|
- Each DRM scheme is different
|
||
|
|
- Secure key storage required
|
||
|
|
- Regular updates needed for scheme changes
|
||
|
|
|
||
|
|
### Alternative
|
||
|
|
|
||
|
|
Users should remove DRM from purchased content using legal tools before loading to device.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ADR-011: List Rendering Enhancements
|
||
|
|
|
||
|
|
**Status:** RECOMMENDED FOR IMPLEMENTATION (PHASE 1)
|
||
|
|
|
||
|
|
### Context
|
||
|
|
|
||
|
|
Current implementation:
|
||
|
|
- `<li>` renders bullet character `•`
|
||
|
|
- No numbered list support
|
||
|
|
- No nesting indentation
|
||
|
|
|
||
|
|
### Decision
|
||
|
|
|
||
|
|
**Enhance list rendering with ordered numbers and nesting.**
|
||
|
|
|
||
|
|
### Rationale
|
||
|
|
|
||
|
|
1. **Low Complexity:**
|
||
|
|
- Track list type (`<ol>` vs `<ul>`) in parser state
|
||
|
|
- Maintain counter for ordered lists
|
||
|
|
- Apply indentation based on nesting depth
|
||
|
|
|
||
|
|
2. **Clear User Benefit:**
|
||
|
|
- Numbered lists convey sequence
|
||
|
|
- Indentation shows hierarchy
|
||
|
|
|
||
|
|
### Implementation
|
||
|
|
|
||
|
|
```cpp
|
||
|
|
// Parser state additions
|
||
|
|
int listDepth = 0;
|
||
|
|
int orderedListCounter = 0;
|
||
|
|
bool isOrderedList = false;
|
||
|
|
|
||
|
|
// On <ol> start
|
||
|
|
isOrderedList = true;
|
||
|
|
orderedListCounter = 1;
|
||
|
|
listDepth++;
|
||
|
|
|
||
|
|
// On <li> in ordered list
|
||
|
|
addWord(std::to_string(orderedListCounter++) + ".", REGULAR);
|
||
|
|
|
||
|
|
// Apply indent
|
||
|
|
textIndent = listDepth * 20; // pixels per level
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Summary Table
|
||
|
|
|
||
|
|
| Feature | Decision | Rationale |
|
||
|
|
|---------|----------|-----------|
|
||
|
|
| Inline Images | IMPLEMENT | High impact, infrastructure ready |
|
||
|
|
| JavaScript | OMIT | Security risk, no benefit for e-ink |
|
||
|
|
| Fixed Layout | OMIT | Display mismatch, poor UX |
|
||
|
|
| Audio/Video | CANNOT | No hardware support |
|
||
|
|
| Color CSS | IGNORE | Grayscale display |
|
||
|
|
| Tables | DEFER | Moderate impact, high complexity |
|
||
|
|
| SVG/MathML | OMIT | High complexity, limited use |
|
||
|
|
| Complex CSS Selectors | OMIT | Memory constraints, limited benefit |
|
||
|
|
| Internal Links | IMPLEMENT (Phase 2) | User value for references |
|
||
|
|
| DRM | OMIT | Licensing, philosophy conflict |
|
||
|
|
| List Enhancements | IMPLEMENT (Phase 1) | Low complexity, clear benefit |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Implementation Priority
|
||
|
|
|
||
|
|
### Phase 1 (Quick Wins)
|
||
|
|
- [x] Basic bullet rendering (already implemented)
|
||
|
|
- [ ] Ordered list numbering
|
||
|
|
- [ ] Nested list indentation
|
||
|
|
- [ ] Line-height CSS support
|
||
|
|
|
||
|
|
### Phase 2 (Image Support)
|
||
|
|
- [ ] Image extraction from EPUB
|
||
|
|
- [ ] JPEG to BMP conversion for inline images
|
||
|
|
- [ ] PageImage element integration
|
||
|
|
- [ ] Image scaling and layout
|
||
|
|
|
||
|
|
### Phase 3 (Navigation)
|
||
|
|
- [ ] Internal link parsing
|
||
|
|
- [ ] Link selection UI
|
||
|
|
- [ ] Anchor navigation
|
||
|
|
|
||
|
|
### Deferred/Not Planned
|
||
|
|
- PNG support (would need library addition)
|
||
|
|
- Table rendering
|
||
|
|
- Complex CSS selectors
|
||
|
|
- JavaScript, FXL, DRM
|