4.5 KiB
4.5 KiB
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
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, orNonefor original fonts)
Returns:
- Re-rendered page with the new font family
Example:
# 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) orNoneif using original fonts
Example:
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 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 to create comparison images:
python examples/generate_readme_font_demo.py
Implementation Details
The font family switching is implemented using a hybrid approach that combines:
- FontFamilyOverride class: Manages font preferences at render time
- Font transformation pipeline: Intercepts and transforms Font objects during rendering
- Intelligent caching: Automatic cache invalidation when font family changes
- 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.
