From 23d3278b50b241eb5f5a2051e2a78864aae39cbe Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Tue, 11 Nov 2025 18:19:49 +0100 Subject: [PATCH] update docs and gitignore --- .gitignore | 5 +- FONT_SWITCHING_FEATURE.md | 139 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 FONT_SWITCHING_FEATURE.md diff --git a/.gitignore b/.gitignore index 56cca20..be58037 100644 --- a/.gitignore +++ b/.gitignore @@ -45,9 +45,12 @@ test_output/ examples/output/ # Generated data - +bookmarks/ positions/ +# Profiling scripts +profile_*.py + # Debug scripts output debug_*.png .fish* \ No newline at end of file diff --git a/FONT_SWITCHING_FEATURE.md b/FONT_SWITCHING_FEATURE.md new file mode 100644 index 0000000..0d22cd3 --- /dev/null +++ b/FONT_SWITCHING_FEATURE.md @@ -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).