update docs
All checks were successful
Python CI / test (3.12) (push) Successful in 8m40s
Python CI / test (3.13) (push) Successful in 22m41s

This commit is contained in:
Duncan Tourolle 2025-11-09 22:06:06 +01:00
parent 0f9e38eb7c
commit 8f6205dcfe
6 changed files with 1606 additions and 1503 deletions

1303
HAL_IMPLEMENTATION_SPEC.md Normal file

File diff suppressed because it is too large Load Diff

185
README.md
View File

@ -8,11 +8,9 @@
| ![Documentation Coverage](https://gitea.tourolle.paris/dtourolle/dreader-application/raw/branch/badges/cov_info/coverage-docs.svg) | **Documentation Coverage** - Percentage of code with docstrings |
| ![License](https://img.shields.io/badge/license-MIT-blue.svg) | **License** - Project licensing information |
> 📋 **Note**: Badges show results from the commit referenced in the URLs. Red "error" badges indicate build failures for that specific step.
## Description
DReader Application is a complete, production-ready ebook reader built on [pyWebLayout](https://gitea.tourolle.paris/dtourolle/pyWebLayout). It demonstrates how to build a full-featured ebook reader with text highlighting, bookmarks, gesture support, and position persistence.
DReader Application is a complete, production-ready ebook reader built on [pyWebLayout](https://gitea.tourolle.paris/dtourolle/pyWebLayout). It demonstrates how to build a full-featured ebook reader with library browsing, text highlighting, bookmarks, gesture support, overlays, and position persistence.
This project serves as both a reference implementation and a ready-to-use ereader library for building desktop, web-based, or embedded reading applications.
@ -20,11 +18,12 @@ This project serves as both a reference implementation and a ready-to-use ereade
### Core Reading Features
- 📖 **EPUB Support** - Load and render EPUB files with full text extraction
- 📚 **Library Management** - Browse and select books from your collection
- 📄 **Page Rendering** - Render pages as PIL Images optimized for any display
- ⬅️➡️ **Navigation** - Smooth forward and backward page navigation
- 🔖 **Bookmarks** - Save and restore reading positions with persistence
- 📑 **Chapter Navigation** - Jump to chapters by title or index via TOC
- 📋 **TOC Overlay** - Interactive table of contents overlay with gesture support
- 📋 **Unified Overlays** - Navigation (TOC + Bookmarks) and Settings overlays
- 📊 **Progress Tracking** - Real-time reading progress percentage
### Text Interaction
@ -40,6 +39,7 @@ This project serves as both a reference implementation and a ready-to-use ereade
- 💾 **Position Persistence** - Stable positions across style changes
- ⚡ **Smart Reflow** - Automatic text reflow on font/spacing changes
- 🎨 **Custom Styling** - Full control over colors, fonts, and layout
- 💾 **Settings Persistence** - Save and restore preferences across sessions
## Installation
@ -156,8 +156,8 @@ reader.get_chapters() # List all chapters
reader.get_current_chapter_info()
reader.get_reading_progress() # Returns 0.0 to 1.0
# TOC Overlay
overlay_image = reader.open_toc_overlay() # Returns composited image with TOC
# Navigation Overlay (unified TOC + Bookmarks)
overlay_image = reader.open_navigation_overlay() # Opens with tabs
reader.close_overlay()
reader.is_overlay_open()
```
@ -236,34 +236,84 @@ elif response.action == ActionType.CHAPTER_SELECTED:
# - TAP: Select words, activate links, navigate TOC
# - LONG_PRESS: Show definitions or context menu
# - SWIPE_LEFT/RIGHT: Page navigation
# - SWIPE_UP: Open TOC overlay (from bottom 20% of screen)
# - SWIPE_DOWN: Close overlay
# - SWIPE_UP: Open navigation overlay (from bottom 20% of screen)
# - SWIPE_DOWN: Close overlay or open settings (from top 20%)
# - PINCH_IN/OUT: Font size adjustment
# - DRAG: Text selection
```
### File Operations
### Settings Persistence
```python
# Save current page to file
reader.render_to_file("current_page.png")
from dreader.state import StateManager
from pathlib import Path
# Context manager (auto-saves position on close)
with EbookReader(page_size=(800, 1000)) as reader:
reader.load_epub("book.epub")
# ... use reader ...
# Position automatically saved on exit
# Initialize state manager
state_file = Path.home() / ".config" / "dreader" / "state.json"
state_manager = StateManager(state_file=state_file)
# Load saved state
state = state_manager.load_state()
# Create reader and apply saved settings
reader = EbookReader(page_size=(800, 1000))
reader.load_epub("mybook.epub")
reader.apply_settings(state.settings.to_dict())
# Settings are automatically saved
reader.increase_font_size()
state_manager.update_settings(reader.get_current_settings())
state_manager.save_state()
```
### Library Management
```python
from dreader.library import LibraryManager
# Initialize library
library = LibraryManager(
library_path="/path/to/books",
page_size=(800, 1200)
)
# Scan for EPUB files
library.scan_library()
# Render library view
library_image = library.render_library()
# Handle book selection
book_path = library.handle_library_tap(x=400, y=300)
if book_path:
reader.load_epub(book_path)
```
## Examples
Check out the `examples/` directory for complete working examples:
Check out the [examples/](examples/) directory for complete working examples:
### Basic Examples
- **[simple_ereader_example.py](examples/simple_ereader_example.py)** - Basic ereader usage with EPUB loading and navigation
- **[ereader_demo.py](examples/ereader_demo.py)** - Comprehensive demo showcasing all features
- **[word_selection_highlighting.py](examples/word_selection_highlighting.py)** - Text selection and highlighting
- **[simple_word_highlight.py](examples/simple_word_highlight.py)** - Minimal highlighting example
### Text Highlighting
- **[word_selection_highlighting.py](examples/word_selection_highlighting.py)** - Text selection and highlighting
### Overlays
- **[demo_toc_overlay.py](examples/demo_toc_overlay.py)** - Interactive table of contents overlay
- **[navigation_overlay_example.py](examples/navigation_overlay_example.py)** - Unified navigation overlay (TOC + Bookmarks)
- **[demo_settings_overlay.py](examples/demo_settings_overlay.py)** - Settings panel with font/spacing controls
### Library & State
- **[library_reading_integration.py](examples/library_reading_integration.py)** - Complete library → reading → resume workflow
- **[persistent_settings_example.py](examples/persistent_settings_example.py)** - Save/restore settings across sessions
### Advanced
- **[demo_pagination.py](examples/demo_pagination.py)** - Pagination system demonstration
- **[generate_ereader_gifs.py](examples/generate_ereader_gifs.py)** - Generate animated GIF demonstrations
- **[generate_library_demo_gif.py](examples/generate_library_demo_gif.py)** - Generate library demo animations
## Architecture
@ -279,6 +329,27 @@ dreader.application.EbookReader (High-Level API)
└── pyWebLayout.io.readers.epub_reader # EPUB parsing
```
### Component Structure
```
dreader/
├── application.py # Main EbookReader class (coordinator)
├── managers/ # Specialized management modules
│ ├── document.py # Document loading (EPUB/HTML)
│ ├── settings.py # Font and spacing controls
│ └── highlight_coordinator.py # Text highlighting
├── handlers/
│ └── gestures.py # Touch event routing
├── overlays/ # UI overlay system
│ ├── base.py # Base overlay functionality
│ ├── navigation.py # TOC and bookmarks overlay
│ └── settings.py # Settings overlay
├── library.py # Library browsing and book selection
├── state.py # Application state persistence
├── html_generator.py # HTML generation for overlays
└── gesture.py # Gesture definitions and responses
```
### Relationship to pyWebLayout
**pyWebLayout** is a layout engine library providing low-level primitives:
@ -297,6 +368,30 @@ Think of it like this:
- **pyWebLayout** = React (library)
- **DReader Application** = Next.js (framework)
## State Management
### File Structure
```
~/.config/dreader/
├── state.json # Application state
├── covers/ # Cached book covers
├── bookmarks/ # Per-book bookmarks
├── highlights/ # Per-book highlights
└── xray/ # X-Ray data (future)
```
### State Persistence
- **Auto-save**: Every 60 seconds
- **Immediate save**: On mode change, settings change, shutdown
- **Boot behavior**: Resume last book at last position or show library
- **Error handling**: Fall back to library if book missing or state corrupt
### Position Stability
- Positions stored by abstract document structure (chapter/block/word indices)
- Stable across font size changes, spacing changes, page size changes
- Per-book storage using document IDs
- Special `__auto_resume__` bookmark for last reading position
## Use Cases
- 📱 **Desktop Ereader Applications** - Build native ereader apps with Python
@ -340,6 +435,9 @@ python simple_ereader_example.py /path/to/book.epub
# Run comprehensive demo
python ereader_demo.py /path/to/book.epub
# Run library integration demo
python library_reading_integration.py /path/to/library/
# Generate animated GIFs
python generate_ereader_gifs.py /path/to/book.epub
```
@ -351,6 +449,10 @@ The project includes comprehensive tests covering:
- **Application API** - All EbookReader methods and workflows
- **System Integration** - Layout manager, bookmarks, and state management
- **Highlighting** - Word and selection highlighting with persistence
- **Overlays** - Navigation and settings overlay interactions
- **Gestures** - Touch event handling and routing
- **Boot Recovery** - State persistence and position restoration
- **Library** - Book scanning, selection, and metadata
- **Edge Cases** - Error handling, boundary conditions, and recovery
```bash
@ -367,6 +469,53 @@ pytest -v
pytest --cov=dreader --cov-report=term-missing
```
## Hardware Integration
DReader requires a Hardware Abstraction Layer (HAL) for display and input:
```python
from abc import ABC, abstractmethod
from PIL import Image
class DisplayHAL(ABC):
"""Abstract display interface for platform integration"""
@abstractmethod
def show_image(self, image: Image.Image):
"""Display a PIL Image on the screen"""
@abstractmethod
def get_touch_events(self) -> Iterator[TouchEvent]:
"""Get iterator of touch events from hardware"""
@abstractmethod
def set_brightness(self, level: int):
"""Set display brightness (0-10)"""
```
**Example HAL Implementations:**
- **E-ink Displays**: IT8951, Remarkable device SDK
- **Desktop**: pygame, tkinter, Qt
- **Web**: Flask + HTML canvas
- **Embedded**: Device-specific framebuffer
See [HAL_IMPLEMENTATION_SPEC.md](HAL_IMPLEMENTATION_SPEC.md) for detailed integration guidelines.
## Documentation
- [README.md](README.md) - This file, main project documentation
- [REQUIREMENTS.md](REQUIREMENTS.md) - Application requirements specification
- [ARCHITECTURE.md](ARCHITECTURE.md) - System architecture and design details
- [HAL_IMPLEMENTATION_SPEC.md](HAL_IMPLEMENTATION_SPEC.md) - Hardware integration guide
## Performance
- **Boot Time**: ~2-3 seconds to resume reading
- **Page Turn**: ~50-100ms (depends on page complexity)
- **Overlay Open**: ~200-250ms (includes HTML generation and rendering)
- **Memory Usage**: ~20-30MB base + 10-50MB per book
- **Cache**: Automatic cover image and metadata caching for fast library loading
## Contributing
Contributions welcome! This project demonstrates what's possible with pyWebLayout. If you build something cool or find ways to improve the reader, please share!

File diff suppressed because it is too large Load Diff

View File

@ -200,6 +200,8 @@ class PygameDisplayHAL(EventLoopHAL):
# Detect gesture type
gesture = None
# For swipe gestures, use the starting position (mouse_down_pos)
# For tap/long-press, use the ending position (mouse_up_pos)
x, y = mouse_up_pos
if distance < self.drag_threshold:
@ -211,7 +213,8 @@ class PygameDisplayHAL(EventLoopHAL):
gesture = GestureType.TAP
logger.info(f"[GESTURE] ✓ Detected: TAP")
else:
# Swipe
# Swipe - use starting position for location-based checks
x, y = self.mouse_down_pos
if abs(dx) > abs(dy):
# Horizontal swipe
if dx > 0:
@ -233,6 +236,8 @@ class PygameDisplayHAL(EventLoopHAL):
self.mouse_down_pos = None
if gesture:
# For swipe gestures, (x,y) is the start position
# For tap/long-press, (x,y) is the tap position
logger.info(f"[EVENT] Returning TouchEvent: {gesture.value} at ({x}, {y})")
return TouchEvent(gesture, x, y)
else:

View File

@ -1,164 +0,0 @@
# Library Reading Demo
This directory contains scripts to demonstrate the complete LIBRARY ↔ READING workflow for the dreader e-reader application.
## Demo GIF
**File**: [`doc/images/library_reading_demo.gif`](../doc/images/library_reading_demo.gif) (591 KB, 800x1200 pixels)
### What the Demo Shows
The animated GIF demonstrates the complete user workflow:
1. **Library View** (2s)
- Shows a grid of available books
- Title: "📚 My Library - Select a book"
2. **Book Selection** (1.5s)
- Visual tap indicator on the first book
- Shows where user taps to select
3. **Reading Pages** (5 frames, ~5s total)
- Opens "Alice's Adventures in Wonderland"
- Shows 5 consecutive pages
- Page turns are animated
- Progress shown in header
4. **Settings Overlay** (2s)
- Shows settings panel with font controls
- Highlights "Back to Library" button
- Visual tap indicator showing where to click
5. **Return to Library** (2s)
- Book closes, position saved automatically
- Library view shown again
- Annotation: "Back to Library (position saved)"
6. **Reopen Book** (1.5s)
- User taps same book again
- Visual indicator shows reselection
7. **Auto-Resume** (3s)
- Book opens at saved position (24.6% progress)
- Shows the exact page where user left off
- Annotation: "✅ Auto-resumed at 24.6%"
**Total Duration**: ~17 seconds (looping)
## Scripts
### `generate_library_demo_gif.py`
Generate the demo GIF showing the complete workflow.
**Usage**:
```bash
python generate_library_demo_gif.py path/to/library [output.gif]
```
**Examples**:
```bash
# Generate to default location (doc/images/library_reading_demo.gif)
python generate_library_demo_gif.py tests/data/library-epub/
# Generate to custom location
python generate_library_demo_gif.py tests/data/library-epub/ doc/images/custom_demo.gif
```
**Features**:
- Automatic book scanning and cover extraction
- Visual tap indicators showing user interactions
- Annotations explaining each step
- Configurable frame durations
- Auto-resume demonstration
### `library_reading_integration.py`
Comprehensive integration test for the library ↔ reading workflow.
**Usage**:
```bash
python library_reading_integration.py path/to/library
```
**What it Tests**:
1. Library scanning and rendering
2. Book selection via tap
3. Book loading and reading
4. Page navigation (swipe gestures)
5. Settings overlay
6. Settings adjustments (font size)
7. Back to library button
8. Auto-resume functionality
9. Multiple book selection
**Output**: Generates PNG images for each step (8 images total)
## Implementation Status
### ✅ Complete Features
- **Library Management** ([library.py](../dreader/library.py))
- Book scanning and metadata extraction
- Cover image caching
- Interactive book selection
- Clickable book rows
- **Reading Mode** ([application.py](../dreader/application.py))
- EPUB rendering
- Page navigation (swipe, tap)
- Progress tracking
- Position saving/loading
- **State Persistence** ([state.py](../dreader/state.py))
- Auto-save on page turn
- Resume at last position
- Settings persistence
- Per-book bookmarks
- **Overlays**
- TOC (Table of Contents) - ✅ Working
- Settings - ✅ Working
- Bookmarks - ✅ Working
### 🚧 Known Issues
- **HTML Link Interactivity**: The "Back to Library" button in settings overlay doesn't respond to taps
- Root cause documented in [HTML_LINKS_INVESTIGATION.md](../HTML_LINKS_INVESTIGATION.md)
- Workaround: Will be implemented using programmatic UI generation
- Does not affect the demo GIF (which shows the intended workflow)
## Requirements
- Python 3.8+
- PIL/Pillow (for image generation)
- dreader application
- pyWebLayout library
- Test EPUB files in the library directory
## File Sizes
- Demo GIF: ~622 KB (optimized for quality)
- Integration test PNGs: ~50-170 KB each
- Total demo assets: <2 MB
## Demo Generation Time
- Library scanning: <1 second
- EPUB loading: <1 second
- Page rendering: ~0.5 seconds per page
- Total: ~10-15 seconds to generate complete GIF
## Use Cases
1. **Documentation**: Visual demonstration of application features
2. **Testing**: Verify complete workflow end-to-end
3. **Presentations**: Show stakeholders the user experience
4. **Debugging**: Identify issues in the workflow
5. **Training**: Help users understand the application flow
## See Also
- [REQUIREMENTS.md](../REQUIREMENTS.md) - Full application requirements
- [HTML_GENERATION.md](../HTML_GENERATION.md) - HTML rendering documentation
- [HTML_LINKS_INVESTIGATION.md](../HTML_LINKS_INVESTIGATION.md) - Link interactivity debugging

View File

@ -1,421 +0,0 @@
# EbookReader - Simple EPUB Reader Application
The `EbookReader` class provides a complete, user-friendly interface for building ebook reader applications with pyWebLayout. It wraps all the complex ereader infrastructure into a simple API.
## Features
- 📖 **EPUB Loading** - Load EPUB files with automatic content extraction
- ⬅️➡️ **Page Navigation** - Forward and backward page navigation
- 🔖 **Position Management** - Save/load reading positions (stable across font changes)
- 📑 **Chapter Navigation** - Jump to chapters by title or index
- 🔤 **Font Size Control** - Increase/decrease font size with live re-rendering
- 📏 **Spacing Control** - Adjust line, block, and word spacing
- 💾 **Persistent Settings** - Save and restore rendering preferences across sessions
- 📊 **Progress Tracking** - Get reading progress and position information
- 🎨 **Text Highlighting** - Highlight words and passages with colors
- 📋 **Overlays** - TOC, Settings, and Bookmarks overlays
- 🖱️ **Gesture Support** - Handle tap, swipe, pinch gestures
- 💾 **Context Manager Support** - Automatic cleanup with `with` statement
## Quick Start
```python
from pyWebLayout.layout.ereader_application import EbookReader
# Create reader
reader = EbookReader(page_size=(800, 1000))
# Load an EPUB
reader.load_epub("mybook.epub")
# Get current page as PIL Image
page_image = reader.get_current_page()
page_image.save("current_page.png")
# Navigate
reader.next_page()
reader.previous_page()
# Close reader
reader.close()
```
## API Reference
### Initialization
```python
reader = EbookReader(
page_size=(800, 1000), # Page dimensions (width, height) in pixels
margin=40, # Page margin in pixels
background_color=(255, 255, 255), # RGB background color
line_spacing=5, # Line spacing in pixels
inter_block_spacing=15, # Space between blocks in pixels
bookmarks_dir="ereader_bookmarks", # Directory for bookmarks
buffer_size=5 # Number of pages to cache
)
```
### Loading EPUB
```python
# Load EPUB file
success = reader.load_epub("path/to/book.epub")
# Check if book is loaded
if reader.is_loaded():
print("Book loaded successfully")
# Get book information
book_info = reader.get_book_info()
# Returns: {
# 'title': 'Book Title',
# 'author': 'Author Name',
# 'document_id': 'book',
# 'total_blocks': 5000,
# 'total_chapters': 20,
# 'page_size': (800, 1000),
# 'font_scale': 1.0
# }
```
### Page Navigation
```python
# Get current page as PIL Image
page = reader.get_current_page()
# Navigate to next page
page = reader.next_page() # Returns None at end of book
# Navigate to previous page
page = reader.previous_page() # Returns None at beginning
# Save current page to file
reader.render_to_file("page.png")
```
### Position Management
Positions are saved based on abstract document structure (chapter/block/word indices), making them stable across font size and styling changes.
```python
# Save current position
reader.save_position("my_bookmark")
# Load saved position
page = reader.load_position("my_bookmark")
# List all saved positions
positions = reader.list_saved_positions()
# Returns: ['my_bookmark', 'chapter_2', ...]
# Delete a position
reader.delete_position("my_bookmark")
# Get detailed position info
info = reader.get_position_info()
# Returns: {
# 'position': {'chapter_index': 0, 'block_index': 42, 'word_index': 15, ...},
# 'chapter': {'title': 'Chapter 1', 'level': 'H1', ...},
# 'progress': 0.15, # 15% through the book
# 'font_scale': 1.0,
# 'book_title': 'Book Title',
# 'book_author': 'Author Name'
# }
# Get reading progress (0.0 to 1.0)
progress = reader.get_reading_progress()
print(f"You're {progress*100:.1f}% through the book")
```
### Chapter Navigation
```python
# Get all chapters
chapters = reader.get_chapters()
# Returns: [('Chapter 1', 0), ('Chapter 2', 1), ...]
# Get chapters with positions
chapter_positions = reader.get_chapter_positions()
# Returns: [('Chapter 1', RenderingPosition(...)), ...]
# Jump to chapter by index
page = reader.jump_to_chapter(1) # Jump to second chapter
# Jump to chapter by title
page = reader.jump_to_chapter("Chapter 1")
# Get current chapter info
chapter_info = reader.get_current_chapter_info()
# Returns: {'title': 'Chapter 1', 'level': HeadingLevel.H1, 'block_index': 0}
```
### Font Size Control
```python
# Get current font size scale
scale = reader.get_font_size() # Default: 1.0
# Set specific font size scale
page = reader.set_font_size(1.5) # 150% of normal size
# Increase font size by 10%
page = reader.increase_font_size()
# Decrease font size by 10%
page = reader.decrease_font_size()
```
### Spacing Control
```python
# Set line spacing (spacing between lines within a paragraph)
page = reader.set_line_spacing(10) # 10 pixels
# Set inter-block spacing (spacing between paragraphs, headings, etc.)
page = reader.set_inter_block_spacing(20) # 20 pixels
```
### Context Manager
The reader supports Python's context manager protocol for automatic cleanup:
```python
with EbookReader(page_size=(800, 1000)) as reader:
reader.load_epub("book.epub")
page = reader.get_current_page()
# ... do stuff
# Automatically saves position and cleans up resources
```
## Complete Example
```python
from pyWebLayout.layout.ereader_application import EbookReader
# Create reader with custom settings
with EbookReader(
page_size=(800, 1000),
margin=50,
line_spacing=8,
inter_block_spacing=20
) as reader:
# Load EPUB
if not reader.load_epub("my_novel.epub"):
print("Failed to load EPUB")
exit(1)
# Get book info
info = reader.get_book_info()
print(f"Reading: {info['title']} by {info['author']}")
print(f"Total chapters: {info['total_chapters']}")
# Navigate through first few pages
for i in range(5):
page = reader.get_current_page()
page.save(f"page_{i+1:03d}.png")
reader.next_page()
# Save current position
reader.save_position("page_5")
# Jump to a chapter
chapters = reader.get_chapters()
if len(chapters) > 2:
print(f"Jumping to: {chapters[2][0]}")
reader.jump_to_chapter(2)
reader.render_to_file("chapter_3_start.png")
# Return to saved position
reader.load_position("page_5")
# Adjust font size
reader.increase_font_size()
reader.render_to_file("page_5_larger_font.png")
# Get progress
progress = reader.get_reading_progress()
print(f"Reading progress: {progress*100:.1f}%")
```
## Persistent Settings
Settings like font size and spacing are automatically saved and restored across sessions:
```python
from dreader import EbookReader
from dreader.state import StateManager
from pathlib import Path
# Initialize state manager
state_file = Path.home() / ".config" / "dreader" / "state.json"
state_manager = StateManager(state_file=state_file)
# Load saved state
state = state_manager.load_state()
print(f"Saved font scale: {state.settings.font_scale}")
# Create reader with saved settings
reader = EbookReader(
line_spacing=state.settings.line_spacing,
inter_block_spacing=state.settings.inter_block_spacing
)
# Load book and apply all saved settings
reader.load_epub("mybook.epub")
reader.apply_settings(state.settings.to_dict())
# User changes settings...
reader.increase_font_size()
reader.set_line_spacing(10)
# Save new settings for next session
current_settings = reader.get_current_settings()
state_manager.update_settings(current_settings)
state_manager.save_state()
# Next time the app starts, these settings will be restored!
```
See [persistent_settings_example.py](persistent_settings_example.py) for a complete demonstration.
## Demo Scripts
Run these demos to see features in action:
```bash
# Comprehensive feature demo
python examples/ereader_demo.py path/to/book.epub
# Persistent settings demo
python examples/persistent_settings_example.py
# TOC overlay demo (generates animated GIF)
python examples/demo_toc_overlay.py
# Settings overlay demo (generates animated GIF)
python examples/demo_settings_overlay.py
# Word highlighting examples
python examples/word_selection_highlighting.py
```
This will demonstrate:
- Basic page navigation
- Position save/load
- Chapter navigation
- Font size adjustments
- Spacing adjustments
- Book information retrieval
The demo generates multiple PNG files showing different pages and settings.
## Position Storage Format
Positions are stored as JSON files in the `bookmarks_dir` (default: `ereader_bookmarks/`):
```json
{
"chapter_index": 0,
"block_index": 42,
"word_index": 15,
"table_row": 0,
"table_col": 0,
"list_item_index": 0,
"remaining_pretext": null,
"page_y_offset": 0
}
```
This format is tied to the abstract document structure, making positions stable across:
- Font size changes
- Line spacing changes
- Inter-block spacing changes
- Page size changes
## Integration Example: Simple GUI
Here's a minimal example of integrating with Tkinter:
```python
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk
from pyWebLayout.layout.ereader_application import EbookReader
class SimpleEreaderGUI:
def __init__(self, root):
self.root = root
self.reader = EbookReader(page_size=(600, 800))
# Create UI
self.image_label = tk.Label(root)
self.image_label.pack()
btn_frame = tk.Frame(root)
btn_frame.pack()
tk.Button(btn_frame, text="Open EPUB", command=self.open_epub).pack(side=tk.LEFT)
tk.Button(btn_frame, text="Previous", command=self.prev_page).pack(side=tk.LEFT)
tk.Button(btn_frame, text="Next", command=self.next_page).pack(side=tk.LEFT)
tk.Button(btn_frame, text="Font+", command=self.increase_font).pack(side=tk.LEFT)
tk.Button(btn_frame, text="Font-", command=self.decrease_font).pack(side=tk.LEFT)
def open_epub(self):
filepath = filedialog.askopenfilename(filetypes=[("EPUB files", "*.epub")])
if filepath:
self.reader.load_epub(filepath)
self.display_page()
def display_page(self):
page = self.reader.get_current_page()
if page:
photo = ImageTk.PhotoImage(page)
self.image_label.config(image=photo)
self.image_label.image = photo
def next_page(self):
if self.reader.next_page():
self.display_page()
def prev_page(self):
if self.reader.previous_page():
self.display_page()
def increase_font(self):
self.reader.increase_font_size()
self.display_page()
def decrease_font(self):
self.reader.decrease_font_size()
self.display_page()
root = tk.Tk()
root.title("Simple Ereader")
app = SimpleEreaderGUI(root)
root.mainloop()
```
## Performance Notes
- The reader uses intelligent page caching for fast navigation
- First page load may take ~1 second, subsequent pages are typically < 0.1 seconds
- Background rendering attempts to pre-cache upcoming pages (you may see pickle warnings, which can be ignored)
- Font size changes invalidate the cache and require re-rendering from the current position
- Position save/load is nearly instantaneous
## Limitations
- Currently supports EPUB files only (no PDF, MOBI, etc.)
- Images in EPUBs may not render in some cases
- Tables are skipped in rendering
- Complex HTML layouts may not render perfectly
- No text selection or search functionality (these would need to be added separately)
## See Also
- `examples/ereader_demo.py` - Comprehensive feature demonstration
- `pyWebLayout/layout/ereader_manager.py` - Underlying manager class
- `pyWebLayout/layout/ereader_layout.py` - Core layout engine
- `examples/README_EPUB_RENDERERS.md` - Lower-level EPUB rendering