# DReader Application

## Project Status

| Badge | Description |
|-------|-------------|
| ![Test Coverage](https://gitea.tourolle.paris/dtourolle/dreader-application/raw/branch/badges/cov_info/coverage.svg) | **Test Coverage** - Percentage of code covered by unit tests |
| ![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 |

## 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 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.

## Key Features

### 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
- 📋 **Unified Overlays** - Navigation (TOC + Bookmarks) and Settings overlays
- 📊 **Progress Tracking** - Real-time reading progress percentage

### Text Interaction
- 🎨 **Text Highlighting** - Highlight words and text selections with custom colors
- 💡 **Highlight Notes** - Attach notes and annotations to highlights
- 🔍 **Text Selection** - Select words or ranges via pixel coordinates
- 👆 **Gesture Support** - Handle tap, swipe, pinch, long-press events
- 🎯 **Pixel Queries** - Query text content at any screen position

### Customization & Display
- 🔤 **Font Control** - Dynamically adjust font size with live preview
- 📏 **Spacing Control** - Customize line and paragraph spacing
- 💾 **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

```bash
# Clone the repository
git clone https://gitea.tourolle.paris/dtourolle/dreader-application.git
cd dreader-application

# Install in development mode
pip install -e .

# Or install with dev dependencies
pip install -e ".[dev]"
```

The pyWebLayout dependency will be automatically installed from the git repository.

## DReader in Action

Here are animated demonstrations of the key features:

<table>
  <tr>
    <td align="center">
      <b>Page Navigation</b><br>
      <img src="docs/images/ereader_page_navigation.gif" width="300" alt="Page Navigation"><br>
      <em>Forward and backward navigation through pages</em>
    </td>
    <td align="center">
      <b>Font Size Adjustment</b><br>
      <img src="docs/images/ereader_font_size.gif" width="300" alt="Font Size"><br>
      <em>Dynamic font size scaling with position preservation</em>
    </td>
  </tr>
  <tr>
    <td align="center">
      <b>Chapter Navigation</b><br>
      <img src="docs/images/ereader_chapter_navigation.gif" width="300" alt="Chapter Navigation"><br>
      <em>Jump directly to chapters by title or index</em>
    </td>
    <td align="center">
      <b>Bookmarks & Positions</b><br>
      <img src="docs/images/ereader_bookmarks.gif" width="300" alt="Bookmarks"><br>
      <em>Save and restore reading positions anywhere in the book</em>
    </td>
  </tr>
  <tr>
    <td align="center">
      <b>Text Highlighting</b><br>
      <img src="docs/images/ereader_highlighting.gif" width="300" alt="Highlighting"><br>
      <em>Highlight words and selections with custom colors and notes</em>
    </td>
    <td align="center">
      <b>TOC Overlay</b><br>
      <img src="docs/images/toc_overlay_demo.gif" width="300" alt="TOC Overlay"><br>
      <em>Interactive table of contents with gesture-based navigation</em>
    </td>
  </tr>
</table>

## Quick Start

```python
from dreader.application import EbookReader

# Create an ebook reader
with EbookReader(page_size=(800, 1000)) as reader:
    # Load an EPUB file
    reader.load_epub("mybook.epub")

    # Get current page as PIL Image
    page = reader.get_current_page()
    page.save("page_001.png")

    # Navigate through pages
    reader.next_page()
    reader.previous_page()

    # Save reading position
    reader.save_position("chapter_3")

    # Jump to a chapter
    reader.jump_to_chapter("Chapter 5")

    # Adjust font size
    reader.increase_font_size()

    # Highlight text at coordinates
    highlight_id = reader.highlight_word(x=200, y=300, note="Important!")

    # Get progress
    progress = reader.get_reading_progress()
    print(f"Progress: {progress*100:.1f}%")
```

## API Overview

### Loading Content

```python
reader.load_epub("book.epub")
reader.is_loaded()  # Check if book loaded
reader.get_book_info()  # Get metadata (title, author, etc.)
```

### Navigation

```python
reader.next_page()
reader.previous_page()
reader.jump_to_chapter("Chapter 1")  # By title
reader.jump_to_chapter(0)  # By index
reader.get_chapters()  # List all chapters
reader.get_current_chapter_info()
reader.get_reading_progress()  # Returns 0.0 to 1.0

# Navigation Overlay (unified TOC + Bookmarks)
overlay_image = reader.open_navigation_overlay()  # Opens with tabs
reader.close_overlay()
reader.is_overlay_open()
```

### Styling & Display

```python
reader.increase_font_size()
reader.decrease_font_size()
reader.set_font_size(1.5)  # 150% scale
reader.get_font_size()

reader.set_line_spacing(8)
reader.set_inter_block_spacing(20)
```

### Bookmarks & Position Management

```python
reader.save_position("my_bookmark")
reader.load_position("my_bookmark")
reader.list_saved_positions()
reader.delete_position("my_bookmark")
```

### Text Highlighting

```python
from pyWebLayout.core.highlight import HighlightColor

# Highlight a word at pixel coordinates
highlight_id = reader.highlight_word(
    x=100,
    y=200,
    color=HighlightColor.YELLOW,
    note="Important concept!"
)

# Highlight a text selection
highlight_id = reader.highlight_selection(
    start=(100, 200),
    end=(300, 250),
    color=(255, 255, 0, 128)  # RGBA
)

# Query word at position
result = reader.query_pixel(x=200, y=300)
if result:
    print(f"Word: {result.word.text}")

# Manage highlights
highlights = reader.list_highlights()
reader.remove_highlight(highlight_id)
reader.clear_highlights()
reader.get_highlights_for_current_page()
```

### Gesture Handling

```python
from dreader.gesture import TouchEvent, GestureType, ActionType

# Handle touch input
event = TouchEvent(GestureType.TAP, x=400, y=300)
response = reader.handle_touch(event)

# Response contains action type and data
if response.action == ActionType.PAGE_TURN:
    print(f"Page turned: {response.data['direction']}")
elif response.action == ActionType.WORD_SELECTED:
    print(f"Word selected: {response.data['word']}")
elif response.action == ActionType.CHAPTER_SELECTED:
    print(f"Chapter selected: {response.data['chapter_title']}")

# Supported gestures:
# - TAP: Select words, activate links, navigate TOC
# - LONG_PRESS: Show definitions or context menu
# - SWIPE_LEFT/RIGHT: Page navigation
# - 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
```

### Settings Persistence

```python
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()

# 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/](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
- **[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

DReader Application is a **high-level application layer** that combines pyWebLayout's low-level components:

```
dreader.application.EbookReader (High-Level API)
    ↓
├── pyWebLayout.layout.EreaderLayoutManager  # Layout engine & pagination
├── pyWebLayout.layout.EreaderLayout         # Bidirectional layout
├── pyWebLayout.core.HighlightManager        # Highlighting system
├── pyWebLayout.io.gesture                   # Touch/gesture handling
└── 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:
- Text rendering and layout algorithms
- Document structure and pagination
- Query systems for interactive content
- Core rendering infrastructure

**DReader Application** is an application framework that:
- Combines pyWebLayout components into a complete reader
- Provides user-friendly APIs for common ereader tasks
- Manages application state (bookmarks, highlights, positions)
- Handles business logic for gestures and interactions

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
- 🌐 **Web-based Readers** - Serve rendered pages via Flask/FastAPI
- 📟 **E-ink Device Firmware** - Optimized rendering for e-ink displays
- 📊 **Reading Analytics** - Track reading patterns, highlights, and engagement
- 🎓 **Educational Tools** - Create annotated reading experiences with highlights and notes
- 🔬 **Research Applications** - Build specialized reading tools for academic work

## Development

```bash
# Install in development mode with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run tests with coverage
pytest --cov=dreader --cov-report=html

# Format code
black dreader/ tests/

# Type checking
mypy dreader/

# Linting
flake8 dreader/ tests/
```

### Running Examples

```bash
# Ensure you have an EPUB file for testing
cd examples

# Run simple example
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
```

## Testing

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
# Run all tests
pytest

# Run specific test file
pytest tests/test_ereader_application.py

# Run with verbose output
pytest -v

# Run with coverage report
pytest --cov=dreader --cov-report=term-missing
```

## Hardware Integration

DReader includes complete hardware support for e-ink displays via the **dreader-hal** library.

### Supported Hardware

- **Display**: IT8951 e-ink controller (1872×1404)
- **Touch**: FT5316 capacitive touch panel
- **Buttons**: GPIO buttons (configurable)
- **Sensors**: BMA400 accelerometer, PCF8523 RTC, INA219 power monitor

### Quick Setup on Raspberry Pi

```bash
# 1. Clone and install
git clone https://gitea.tourolle.paris/dtourolle/dreader-application.git
cd dreader-application
python3 -m venv venv
source venv/bin/activate
pip install -e .
./install_hardware_drivers.sh

# 2. Interactive hardware setup
sudo python3 setup_rpi.py

# 3. Run on hardware
python examples/run_on_hardware_config.py
```

### Hardware Configuration

The repository includes a pre-configured **[hardware_config.json](hardware_config.json)** for the reference hardware:

- **Buttons**: GPIO 22 (prev), GPIO 27 (next), GPIO 21 (power)
- **Display**: 1872×1404 IT8951 e-ink
- **I2C Bus**: GPIO 2/3 (touch, sensors, RTC, power)

See [docs/HARDWARE.md](docs/HARDWARE.md) for complete wiring diagrams and setup instructions.

### HAL Architecture

```python
from dreader.hal_hardware import HardwareDisplayHAL
from dreader.main import DReaderApplication, AppConfig

# Hardware HAL with GPIO buttons
hal = HardwareDisplayHAL(width=1872, height=1404, vcom=-2.0)
config = AppConfig(display_hal=hal, library_path="~/Books")
app = DReaderApplication(config)
```

**Available HAL Implementations:**
- **HardwareDisplayHAL** - Real e-ink hardware (IT8951 + dreader-hal)
- **PygameDisplayHAL** - Desktop testing with pygame window

See [docs/HARDWARE.md](docs/HARDWARE.md) for pin assignments and button configuration.

## Documentation

- [README.md](README.md) - This file, main project documentation
- [docs/HARDWARE.md](docs/HARDWARE.md) - Wiring, configuration, and running on real hardware
- [docs/REQUIREMENTS.md](docs/REQUIREMENTS.md) - Application requirements specification
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) - System architecture and design details
- [docs/HAL_IMPLEMENTATION_SPEC.md](docs/HAL_IMPLEMENTATION_SPEC.md) - Writing a HAL for other hardware

## 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!

### How to Contribute

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes with tests
4. Run tests and ensure coverage stays high
5. Format code with black
6. Submit a pull request

## License

MIT License - see [LICENSE](LICENSE) file for details

## Author

Duncan Tourolle - duncan@tourolle.paris

## Related Projects

- [pyWebLayout](https://gitea.tourolle.paris/dtourolle/pyWebLayout) - The underlying layout engine library

## Acknowledgments

Built with [pyWebLayout](https://gitea.tourolle.paris/dtourolle/pyWebLayout) - A powerful Python library for HTML-like layout and rendering.
