140 lines
4.5 KiB
Markdown
140 lines
4.5 KiB
Markdown
# 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
|
|
|
|

|
|
|
|
*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).
|