#!/usr/bin/env python3 """ Example: Word Selection and Highlighting This example demonstrates how to: 1. Query a pixel location to find a word 2. Select a range of words between two points 3. Highlight selected words by drawing overlays 4. Handle tap gestures to select words This is useful for: - Word definition lookup - Text highlighting/annotation - Copy/paste functionality - Interactive reading features """ from PIL import Image, ImageDraw import numpy as np from pyweblayout_ereader import EbookReader from pyWebLayout.io.gesture import TouchEvent, GestureType from pyWebLayout.core.query import QueryResult def draw_highlight(image: Image.Image, bounds: tuple, color: tuple = (255, 255, 0, 100)): """ Draw a highlight overlay on an image at the given bounds. Args: image: PIL Image to draw on bounds: (x, y, width, height) tuple color: RGBA color tuple (with alpha for transparency) """ # Create a semi-transparent overlay overlay = Image.new('RGBA', image.size, (255, 255, 255, 0)) draw = ImageDraw.Draw(overlay) x, y, w, h = bounds # Draw rectangle with rounded corners for nicer appearance draw.rectangle([x, y, x + w, y + h], fill=color) # Composite the overlay onto the original image image = Image.alpha_composite(image.convert('RGBA'), overlay) return image def example_1_single_word_selection(): """Example 1: Select and highlight a single word by tapping""" print("=" * 60) print("Example 1: Single Word Selection") print("=" * 60) # Create reader and load a book reader = EbookReader(page_size=(800, 1000)) success = reader.load_epub("tests/data/test.epub") if not success: print("Failed to load EPUB") return print(f"Loaded: {reader.book_title} by {reader.book_author}") # Get current page as image page_img = reader.get_current_page() if not page_img: print("No page rendered") return # Simulate a tap at coordinates (200, 300) tap_x, tap_y = 200, 300 print(f"\nSimulating tap at ({tap_x}, {tap_y})") # Query what's at that location result = reader.query_pixel(tap_x, tap_y) if result and result.text: print(f"Found word: '{result.text}'") print(f"Type: {result.object_type}") print(f"Bounds: {result.bounds}") print(f"Is interactive: {result.is_interactive}") # Highlight the word highlighted_img = draw_highlight(page_img, result.bounds, color=(255, 255, 0, 80)) highlighted_img.save("output_single_word_highlight.png") print(f"\nSaved highlighted image to: output_single_word_highlight.png") else: print("No word found at that location") reader.close() def example_2_range_selection(): """Example 2: Select and highlight a range of words (text selection)""" print("\n" + "=" * 60) print("Example 2: Range Selection (Multi-word)") print("=" * 60) # Create reader and load a book reader = EbookReader(page_size=(800, 1000)) success = reader.load_epub("tests/data/test.epub") if not success: print("Failed to load EPUB") return # Get current page page_img = reader.get_current_page() if not page_img: return # Simulate dragging from (100, 200) to (400, 250) start_x, start_y = 100, 200 end_x, end_y = 400, 250 print(f"Simulating selection from ({start_x}, {start_y}) to ({end_x}, {end_y})") # Create drag gesture events drag_start = TouchEvent(GestureType.DRAG_START, start_x, start_y) drag_move = TouchEvent(GestureType.DRAG_MOVE, end_x, end_y) drag_end = TouchEvent(GestureType.DRAG_END, end_x, end_y) # Handle the gesture (business logic) reader.handle_touch(drag_start) reader.handle_touch(drag_move) response = reader.handle_touch(drag_end) if response.action == "selection_complete": selected_text = response.data.get('text', '') bounds_list = response.data.get('bounds', []) word_count = response.data.get('word_count', 0) print(f"\nSelected {word_count} words:") print(f"Text: \"{selected_text}\"") # Highlight all selected words highlighted_img = page_img for bounds in bounds_list: highlighted_img = draw_highlight( highlighted_img, bounds, color=(100, 200, 255, 80) # Light blue highlight ) highlighted_img.save("output_range_highlight.png") print(f"\nSaved highlighted image to: output_range_highlight.png") else: print(f"Selection action: {response.action}") reader.close() def example_3_interactive_word_lookup(): """Example 3: Interactive word lookup with gesture handling""" print("\n" + "=" * 60) print("Example 3: Interactive Word Lookup (with Gestures)") print("=" * 60) # Create reader reader = EbookReader(page_size=(800, 1000)) success = reader.load_epub("tests/data/test.epub") if not success: print("Failed to load EPUB") return # Get page page_img = reader.get_current_page() if not page_img: return # Define some simulated touch events test_gestures = [ ("Tap at (250, 300)", TouchEvent(GestureType.TAP, 250, 300)), ("Long press at (250, 300)", TouchEvent(GestureType.LONG_PRESS, 250, 300)), ("Swipe left", TouchEvent(GestureType.SWIPE_LEFT, 600, 500)), ] for description, event in test_gestures: print(f"\n{description}:") response = reader.handle_touch(event) print(f" Action: {response.action}") if response.action == "word_selected": word = response.data.get('word', '') bounds = response.data.get('bounds', (0, 0, 0, 0)) print(f" Selected word: '{word}'") print(f" Bounds: {bounds}") # Highlight the word highlighted_img = draw_highlight(page_img, bounds, color=(255, 200, 0, 100)) filename = f"output_word_lookup_{word}.png" highlighted_img.save(filename) print(f" Saved: {filename}") elif response.action == "define": word = response.data.get('word', '') print(f" Show definition for: '{word}'") # In real app, you'd call a dictionary API here elif response.action == "page_turn": direction = response.data.get('direction', '') progress = response.data.get('progress', 0) print(f" Page turn {direction}, progress: {progress:.1%}") reader.close() def example_4_multi_word_annotation(): """Example 4: Annotate multiple words with different colors""" print("\n" + "=" * 60) print("Example 4: Multi-word Annotation") print("=" * 60) # Create reader reader = EbookReader(page_size=(800, 1000)) success = reader.load_epub("tests/data/test.epub") if not success: print("Failed to load EPUB") return # Get page page_img = reader.get_current_page() if not page_img: return # Simulate multiple taps at different locations tap_locations = [ (150, 200, "Important word", (255, 100, 100, 80)), # Red (300, 200, "Key concept", (100, 255, 100, 80)), # Green (450, 200, "Notable term", (100, 100, 255, 80)), # Blue ] annotated_img = page_img annotations = [] for x, y, label, color in tap_locations: result = reader.query_pixel(x, y) if result and result.text: print(f"\nFound word at ({x}, {y}): '{result.text}'") print(f" Annotation: {label}") # Highlight with specific color annotated_img = draw_highlight(annotated_img, result.bounds, color) annotations.append({ 'word': result.text, 'label': label, 'bounds': result.bounds }) # Save annotated image annotated_img.save("output_multi_annotation.png") print(f"\nSaved annotated image with {len(annotations)} highlights") print("File: output_multi_annotation.png") # Print annotation summary print("\nAnnotation Summary:") for i, ann in enumerate(annotations, 1): print(f" {i}. '{ann['word']}' - {ann['label']}") reader.close() def example_5_link_highlighting(): """Example 5: Find and highlight all links on a page""" print("\n" + "=" * 60) print("Example 5: Find and Highlight All Links") print("=" * 60) # Create reader reader = EbookReader(page_size=(800, 1000)) success = reader.load_epub("tests/data/test.epub") if not success: print("Failed to load EPUB") return # Get page page_img = reader.get_current_page() if not page_img: return # Get the page object to scan for links page = reader.manager.get_current_page() # Scan through all rendered content to find links links_found = [] from pyWebLayout.concrete.text import Line from pyWebLayout.concrete.functional import LinkText for child in page._children: if isinstance(child, Line): for text_obj in child._text_objects: if isinstance(text_obj, LinkText): origin = text_obj._origin size = text_obj.size bounds = ( int(origin[0]), int(origin[1]), int(size[0]), int(size[1]) ) links_found.append({ 'text': text_obj._text, 'target': text_obj._link.location, 'bounds': bounds }) print(f"Found {len(links_found)} links on page") # Highlight all links highlighted_img = page_img for link in links_found: print(f"\nLink: '{link['text']}' → {link['target']}") highlighted_img = draw_highlight( highlighted_img, link['bounds'], color=(0, 150, 255, 100) # Blue for links ) if links_found: highlighted_img.save("output_links_highlighted.png") print(f"\nSaved image with {len(links_found)} highlighted links") print("File: output_links_highlighted.png") else: print("\nNo links found on this page") reader.close() if __name__ == "__main__": print("Word Selection and Highlighting Examples") print("=" * 60) print() print("These examples demonstrate the query system for:") print("- Single word selection") print("- Range selection (multiple words)") print("- Interactive gesture handling") print("- Multi-word annotation") print("- Link detection and highlighting") print() try: # Run all examples example_1_single_word_selection() example_2_range_selection() example_3_interactive_word_lookup() example_4_multi_word_annotation() example_5_link_highlighting() print("\n" + "=" * 60) print("All examples completed successfully!") print("=" * 60) except Exception as e: print(f"\nError running examples: {e}") import traceback traceback.print_exc()