# Dynamic Font Family Switching

The pyWebLayout ereader now supports dynamic font family switching, allowing readers to change fonts on-the-fly without losing their reading position.

## Visual Demo

![Font Family Switching](docs/images/font_family_switching_vertical.png)

*The same content rendered in Sans-Serif, Serif, and Monospace fonts*

## Features

- **Three Bundled Font Families**: Sans-Serif (DejaVu Sans), Serif (DejaVu Serif), and Monospace (DejaVu Sans Mono)
- **Dynamic Switching**: Change fonts instantly during reading
- **Position Preservation**: Your reading position is maintained across font changes
- **Attribute Preservation**: Bold, italic, size, and color are preserved when switching families
- **Automatic Cache Management**: Intelligent cache invalidation ensures optimal performance

## Usage

```python
from pyWebLayout.style.fonts import BundledFont
from pyWebLayout.layout.ereader_manager import create_ereader_manager

# Create an ereader instance
manager = create_ereader_manager(blocks, page_size=(600, 800))

# Switch to serif font
manager.set_font_family(BundledFont.SERIF)
page = manager.get_current_page()

# Switch to monospace font
manager.set_font_family(BundledFont.MONOSPACE)
page = manager.get_current_page()

# Restore original fonts
manager.set_font_family(None)
page = manager.get_current_page()

# Query current font family
current_family = manager.get_font_family()  # Returns BundledFont or None
```

## API Reference

### EreaderLayoutManager Methods

#### `set_font_family(family: Optional[BundledFont]) -> Page`

Change the font family and re-render the current page.

**Parameters:**
- `family`: Font family to use (`BundledFont.SANS`, `BundledFont.SERIF`, `BundledFont.MONOSPACE`, or `None` for original fonts)

**Returns:**
- Re-rendered page with the new font family

**Example:**
```python
# Switch to serif
page = manager.set_font_family(BundledFont.SERIF)

# Restore original fonts
page = manager.set_font_family(None)
```

#### `get_font_family() -> Optional[BundledFont]`

Get the current font family override.

**Returns:**
- Current font family (`BundledFont.SANS`, `BundledFont.SERIF`, `BundledFont.MONOSPACE`) or `None` if using original fonts

**Example:**
```python
family = manager.get_font_family()
if family:
    print(f"Currently using: {family.value}")
else:
    print("Using original fonts")
```

## Font Families

### Sans-Serif (BundledFont.SANS)
- **Font**: DejaVu Sans
- **Best for**: Screen reading, modern interfaces
- **Characteristics**: Clean, legible, no decorative strokes

### Serif (BundledFont.SERIF)
- **Font**: DejaVu Serif
- **Best for**: Long-form reading, formal documents
- **Characteristics**: Traditional, classic appearance with decorative strokes

### Monospace (BundledFont.MONOSPACE)
- **Font**: DejaVu Sans Mono
- **Best for**: Code, technical documentation
- **Characteristics**: Fixed-width characters, uniform spacing

## Examples

### Complete Demo
See [examples/11_font_family_switching_demo.py](examples/11_font_family_switching_demo.py) for a full demonstration including:
- Creating ereader content
- Switching between font families
- Navigating with different fonts
- Position tracking across font changes

### Generate README Images
Run [examples/generate_readme_font_demo.py](examples/generate_readme_font_demo.py) to create comparison images:
```bash
python examples/generate_readme_font_demo.py
```

## Implementation Details

The font family switching is implemented using a **hybrid approach** that combines:

1. **FontFamilyOverride class**: Manages font preferences at render time
2. **Font transformation pipeline**: Intercepts and transforms Font objects during rendering
3. **Intelligent caching**: Automatic cache invalidation when font family changes
4. **Backward compatibility**: Works with existing Font-based content without migration

This approach provides:
- ✅ No breaking changes to existing code
- ✅ Instant font switching without document recreation
- ✅ Preservation of font attributes (weight, style, size, color)
- ✅ Optimal performance with intelligent buffering

## Technical Notes

- Font family changes invalidate the page buffer cache
- Reading position is preserved using the abstract document structure
- Background rendering adapts to the new font family automatically
- All three bundled fonts are included in the package (license: Bitstream Vera / Public Domain)

## License

The bundled DejaVu fonts are free and open source under the [Bitstream Vera License](pyWebLayout/assets/fonts/DEJAVU_README.md).
