""" Demonstration of dynamic font family switching in the ereader. This example shows how to: 1. Initialize an ereader with content 2. Dynamically switch between different font families (Sans, Serif, Monospace) 3. Maintain reading position across font changes 4. Use the font family API The ereader manager provides a high-level API for changing fonts on-the-fly without losing your place in the document. """ from pyWebLayout.abstract import Paragraph, Heading, Word from pyWebLayout.abstract.block import HeadingLevel from pyWebLayout.style import Font from pyWebLayout.style.fonts import BundledFont, FontWeight from pyWebLayout.style.page_style import PageStyle from pyWebLayout.layout.ereader_manager import create_ereader_manager from PIL import Image def create_sample_content(): """Create sample document content with various text styles""" blocks = [] # Create a default font for the content default_font = Font.from_family(BundledFont.SANS, font_size=16) heading_font = Font.from_family(BundledFont.SANS, font_size=24, weight=FontWeight.BOLD) # Title title = Heading(level=HeadingLevel.H1, style=heading_font) for word in "Font Family Switching Demo".split(): title.add_word(Word(word, heading_font)) blocks.append(title) # Introduction paragraph intro_font = Font.from_family(BundledFont.SANS, font_size=16) intro = Paragraph(intro_font) intro_text = ( "This demonstration shows how the ereader can dynamically switch between " "different font families while maintaining your reading position. " "The three bundled font families (Sans, Serif, and Monospace) can be " "changed on-the-fly without recreating the document." ) for word in intro_text.split(): intro.add_word(Word(word, intro_font)) blocks.append(intro) # Section 1 section1_heading = Heading(level=HeadingLevel.H2, style=heading_font) for word in "Sans-Serif Font".split(): section1_heading.add_word(Word(word, heading_font)) blocks.append(section1_heading) para1 = Paragraph(default_font) text1 = ( "Sans-serif fonts like DejaVu Sans are clean and modern, making them " "ideal for screen reading. They lack the decorative strokes (serifs) " "found in traditional typefaces, which can improve legibility on digital displays. " "Many ereader applications default to sans-serif fonts for this reason." ) for word in text1.split(): para1.add_word(Word(word, default_font)) blocks.append(para1) # Section 2 section2_heading = Heading(level=HeadingLevel.H2, style=heading_font) for word in "Serif Font".split(): section2_heading.add_word(Word(word, heading_font)) blocks.append(section2_heading) para2 = Paragraph(default_font) text2 = ( "Serif fonts like DejaVu Serif have small decorative strokes at the ends " "of letter strokes. These fonts are traditionally used in print media and " "can give a more formal, classic appearance. Many readers prefer serif fonts " "for long-form reading as they find them easier on the eyes." ) for word in text2.split(): para2.add_word(Word(word, default_font)) blocks.append(para2) # Section 3 section3_heading = Heading(level=HeadingLevel.H2, style=heading_font) for word in "Monospace Font".split(): section3_heading.add_word(Word(word, heading_font)) blocks.append(section3_heading) para3 = Paragraph(default_font) text3 = ( "Monospace fonts like DejaVu Sans Mono have equal spacing between all characters. " "They are commonly used for displaying code, technical documentation, and typewriter-style " "text. While less common for general reading, some users prefer the uniform character " "spacing for certain types of content." ) for word in text3.split(): para3.add_word(Word(word, default_font)) blocks.append(para3) # Final paragraph conclusion = Paragraph(default_font) conclusion_text = ( "The ability to switch fonts dynamically is a key feature of modern ereaders. " "It allows readers to customize their reading experience based on personal preference, " "lighting conditions, and content type. Try switching between the three font families " "to see which one you prefer for different types of reading." ) for word in conclusion_text.split(): conclusion.add_word(Word(word, default_font)) blocks.append(conclusion) return blocks def render_pages_with_different_fonts(manager, output_prefix="demo_11"): """Render the same page with different font families""" print("\nRendering pages with different font families...") print("=" * 70) font_families = [ (None, "Original (Sans)"), (BundledFont.SERIF, "Serif"), (BundledFont.MONOSPACE, "Monospace"), (BundledFont.SANS, "Sans (explicit)") ] images = [] for font_family, name in font_families: print(f"\nRendering with {name} font...") # Switch font family manager.set_font_family(font_family) # Get current page page = manager.get_current_page() # Render to image image = page.render() filename = f"{output_prefix}_{name.lower().replace(' ', '_').replace('(', '').replace(')', '')}.png" image.save(filename) print(f" Saved: {filename}") images.append((name, image)) return images def demonstrate_font_switching(): """Main demonstration function""" print("\n") print("=" * 70) print("Font Family Switching Demonstration") print("=" * 70) print() # Create sample content print("Creating sample document...") blocks = create_sample_content() print(f" Created {len(blocks)} blocks") # Initialize ereader manager print("\nInitializing ereader manager...") page_size = (600, 800) manager = create_ereader_manager( blocks, page_size, document_id="font_switching_demo" ) print(f" Page size: {page_size[0]}x{page_size[1]}") print(f" Initial font family: {manager.get_font_family()}") # Render pages with different fonts images = render_pages_with_different_fonts(manager) # Show position info print("\nPosition information after font switches:") print(" " + "-" * 66) pos_info = manager.get_position_info() print(f" Current position: Block {pos_info['position']['block_index']}, " f"Word {pos_info['position']['word_index']}") print(f" Font family: {pos_info['font_family'] or 'Original'}") print(f" Font scale: {pos_info['font_scale']}") print(f" Reading progress: {pos_info['progress']:.1%}") # Test navigation with font switching print("\nTesting navigation with font switching...") print(" " + "-" * 66) # Reset to beginning manager.jump_to_position(manager.current_position.__class__()) # Advance a few pages with serif font manager.set_font_family(BundledFont.SERIF) print(f" Switched to SERIF font") for i in range(3): next_page = manager.next_page() if next_page: print(f" Page {i+2}: Advanced successfully") # Switch to monospace manager.set_font_family(BundledFont.MONOSPACE) print(f" Switched to MONOSPACE font") current_page = manager.get_current_page() print(f" Re-rendered current page with new font") # Go back a page prev_page = manager.previous_page() if prev_page: print(f" Navigated back successfully") # Cache statistics print("\nCache statistics:") print(" " + "-" * 66) stats = manager.get_cache_stats() for key, value in stats.items(): print(f" {key}: {value}") print() print("=" * 70) print("Demo complete!") print() print("Key features demonstrated:") print(" ✓ Dynamic font family switching (Sans, Serif, Monospace)") print(" ✓ Position preservation across font changes") print(" ✓ Automatic cache invalidation on font change") print(" ✓ Navigation with different fonts") print(" ✓ Font family info in position tracking") print() print("The rendered pages show the same content in different font families.") print("Notice how the layout adapts while maintaining readability.") print("=" * 70) print() if __name__ == "__main__": demonstrate_font_switching()