update docs and gitignore
All checks were successful
Python CI / test (3.10) (push) Successful in 2m23s
Python CI / test (3.12) (push) Successful in 2m13s
Python CI / test (3.13) (push) Successful in 2m10s

This commit is contained in:
Duncan Tourolle 2025-11-11 18:19:49 +01:00
parent 3bcd1bffb5
commit 23d3278b50
2 changed files with 143 additions and 1 deletions

5
.gitignore vendored
View File

@ -45,9 +45,12 @@ test_output/
examples/output/
# Generated data
bookmarks/
positions/
# Profiling scripts
profile_*.py
# Debug scripts output
debug_*.png
.fish*

139
FONT_SWITCHING_FEATURE.md Normal file
View File

@ -0,0 +1,139 @@
# 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).