# EbookReader - Simple EPUB Reader Application The `EbookReader` class provides a complete, user-friendly interface for building ebook reader applications with pyWebLayout. It wraps all the complex ereader infrastructure into a simple API. ## Features - 📖 **EPUB Loading** - Load EPUB files with automatic content extraction - ⬅️➡️ **Page Navigation** - Forward and backward page navigation - 🔖 **Position Management** - Save/load reading positions (stable across font changes) - 📑 **Chapter Navigation** - Jump to chapters by title or index - 🔤 **Font Size Control** - Increase/decrease font size with live re-rendering - 📏 **Spacing Control** - Adjust line and block spacing - 📊 **Progress Tracking** - Get reading progress and position information - 💾 **Context Manager Support** - Automatic cleanup with `with` statement ## Quick Start ```python from pyWebLayout.layout.ereader_application import EbookReader # Create reader reader = EbookReader(page_size=(800, 1000)) # Load an EPUB reader.load_epub("mybook.epub") # Get current page as PIL Image page_image = reader.get_current_page() page_image.save("current_page.png") # Navigate reader.next_page() reader.previous_page() # Close reader reader.close() ``` ## API Reference ### Initialization ```python reader = EbookReader( page_size=(800, 1000), # Page dimensions (width, height) in pixels margin=40, # Page margin in pixels background_color=(255, 255, 255), # RGB background color line_spacing=5, # Line spacing in pixels inter_block_spacing=15, # Space between blocks in pixels bookmarks_dir="ereader_bookmarks", # Directory for bookmarks buffer_size=5 # Number of pages to cache ) ``` ### Loading EPUB ```python # Load EPUB file success = reader.load_epub("path/to/book.epub") # Check if book is loaded if reader.is_loaded(): print("Book loaded successfully") # Get book information book_info = reader.get_book_info() # Returns: { # 'title': 'Book Title', # 'author': 'Author Name', # 'document_id': 'book', # 'total_blocks': 5000, # 'total_chapters': 20, # 'page_size': (800, 1000), # 'font_scale': 1.0 # } ``` ### Page Navigation ```python # Get current page as PIL Image page = reader.get_current_page() # Navigate to next page page = reader.next_page() # Returns None at end of book # Navigate to previous page page = reader.previous_page() # Returns None at beginning # Save current page to file reader.render_to_file("page.png") ``` ### Position Management Positions are saved based on abstract document structure (chapter/block/word indices), making them stable across font size and styling changes. ```python # Save current position reader.save_position("my_bookmark") # Load saved position page = reader.load_position("my_bookmark") # List all saved positions positions = reader.list_saved_positions() # Returns: ['my_bookmark', 'chapter_2', ...] # Delete a position reader.delete_position("my_bookmark") # Get detailed position info info = reader.get_position_info() # Returns: { # 'position': {'chapter_index': 0, 'block_index': 42, 'word_index': 15, ...}, # 'chapter': {'title': 'Chapter 1', 'level': 'H1', ...}, # 'progress': 0.15, # 15% through the book # 'font_scale': 1.0, # 'book_title': 'Book Title', # 'book_author': 'Author Name' # } # Get reading progress (0.0 to 1.0) progress = reader.get_reading_progress() print(f"You're {progress*100:.1f}% through the book") ``` ### Chapter Navigation ```python # Get all chapters chapters = reader.get_chapters() # Returns: [('Chapter 1', 0), ('Chapter 2', 1), ...] # Get chapters with positions chapter_positions = reader.get_chapter_positions() # Returns: [('Chapter 1', RenderingPosition(...)), ...] # Jump to chapter by index page = reader.jump_to_chapter(1) # Jump to second chapter # Jump to chapter by title page = reader.jump_to_chapter("Chapter 1") # Get current chapter info chapter_info = reader.get_current_chapter_info() # Returns: {'title': 'Chapter 1', 'level': HeadingLevel.H1, 'block_index': 0} ``` ### Font Size Control ```python # Get current font size scale scale = reader.get_font_size() # Default: 1.0 # Set specific font size scale page = reader.set_font_size(1.5) # 150% of normal size # Increase font size by 10% page = reader.increase_font_size() # Decrease font size by 10% page = reader.decrease_font_size() ``` ### Spacing Control ```python # Set line spacing (spacing between lines within a paragraph) page = reader.set_line_spacing(10) # 10 pixels # Set inter-block spacing (spacing between paragraphs, headings, etc.) page = reader.set_inter_block_spacing(20) # 20 pixels ``` ### Context Manager The reader supports Python's context manager protocol for automatic cleanup: ```python with EbookReader(page_size=(800, 1000)) as reader: reader.load_epub("book.epub") page = reader.get_current_page() # ... do stuff # Automatically saves position and cleans up resources ``` ## Complete Example ```python from pyWebLayout.layout.ereader_application import EbookReader # Create reader with custom settings with EbookReader( page_size=(800, 1000), margin=50, line_spacing=8, inter_block_spacing=20 ) as reader: # Load EPUB if not reader.load_epub("my_novel.epub"): print("Failed to load EPUB") exit(1) # Get book info info = reader.get_book_info() print(f"Reading: {info['title']} by {info['author']}") print(f"Total chapters: {info['total_chapters']}") # Navigate through first few pages for i in range(5): page = reader.get_current_page() page.save(f"page_{i+1:03d}.png") reader.next_page() # Save current position reader.save_position("page_5") # Jump to a chapter chapters = reader.get_chapters() if len(chapters) > 2: print(f"Jumping to: {chapters[2][0]}") reader.jump_to_chapter(2) reader.render_to_file("chapter_3_start.png") # Return to saved position reader.load_position("page_5") # Adjust font size reader.increase_font_size() reader.render_to_file("page_5_larger_font.png") # Get progress progress = reader.get_reading_progress() print(f"Reading progress: {progress*100:.1f}%") ``` ## Demo Script Run the comprehensive demo to see all features in action: ```bash python examples/ereader_demo.py path/to/book.epub ``` This will demonstrate: - Basic page navigation - Position save/load - Chapter navigation - Font size adjustments - Spacing adjustments - Book information retrieval The demo generates multiple PNG files showing different pages and settings. ## Position Storage Format Positions are stored as JSON files in the `bookmarks_dir` (default: `ereader_bookmarks/`): ```json { "chapter_index": 0, "block_index": 42, "word_index": 15, "table_row": 0, "table_col": 0, "list_item_index": 0, "remaining_pretext": null, "page_y_offset": 0 } ``` This format is tied to the abstract document structure, making positions stable across: - Font size changes - Line spacing changes - Inter-block spacing changes - Page size changes ## Integration Example: Simple GUI Here's a minimal example of integrating with Tkinter: ```python import tkinter as tk from tkinter import filedialog from PIL import ImageTk from pyWebLayout.layout.ereader_application import EbookReader class SimpleEreaderGUI: def __init__(self, root): self.root = root self.reader = EbookReader(page_size=(600, 800)) # Create UI self.image_label = tk.Label(root) self.image_label.pack() btn_frame = tk.Frame(root) btn_frame.pack() tk.Button(btn_frame, text="Open EPUB", command=self.open_epub).pack(side=tk.LEFT) tk.Button(btn_frame, text="Previous", command=self.prev_page).pack(side=tk.LEFT) tk.Button(btn_frame, text="Next", command=self.next_page).pack(side=tk.LEFT) tk.Button(btn_frame, text="Font+", command=self.increase_font).pack(side=tk.LEFT) tk.Button(btn_frame, text="Font-", command=self.decrease_font).pack(side=tk.LEFT) def open_epub(self): filepath = filedialog.askopenfilename(filetypes=[("EPUB files", "*.epub")]) if filepath: self.reader.load_epub(filepath) self.display_page() def display_page(self): page = self.reader.get_current_page() if page: photo = ImageTk.PhotoImage(page) self.image_label.config(image=photo) self.image_label.image = photo def next_page(self): if self.reader.next_page(): self.display_page() def prev_page(self): if self.reader.previous_page(): self.display_page() def increase_font(self): self.reader.increase_font_size() self.display_page() def decrease_font(self): self.reader.decrease_font_size() self.display_page() root = tk.Tk() root.title("Simple Ereader") app = SimpleEreaderGUI(root) root.mainloop() ``` ## Performance Notes - The reader uses intelligent page caching for fast navigation - First page load may take ~1 second, subsequent pages are typically < 0.1 seconds - Background rendering attempts to pre-cache upcoming pages (you may see pickle warnings, which can be ignored) - Font size changes invalidate the cache and require re-rendering from the current position - Position save/load is nearly instantaneous ## Limitations - Currently supports EPUB files only (no PDF, MOBI, etc.) - Images in EPUBs may not render in some cases - Tables are skipped in rendering - Complex HTML layouts may not render perfectly - No text selection or search functionality (these would need to be added separately) ## See Also - `examples/ereader_demo.py` - Comprehensive feature demonstration - `pyWebLayout/layout/ereader_manager.py` - Underlying manager class - `pyWebLayout/layout/ereader_layout.py` - Core layout engine - `examples/README_EPUB_RENDERERS.md` - Lower-level EPUB rendering