chore: tidy repository layout and consolidate hardware docs
Root had grown to 30 entries, most of it generated output and one-off scripts. It now holds 12. Docs: - Merge HARDWARE_SETUP, HARDWARE_PINOUT, GPIO_BUTTONS and ACCELEROMETER_PAGE_FLIP into a single docs/HARDWARE.md - Move ARCHITECTURE, REQUIREMENTS and HAL_IMPLEMENTATION_SPEC to docs/, leaving only README.md in the root - Update cross-references in README, setup_rpi.py and install_hardware_drivers.sh, and re-base ARCHITECTURE's source links Merging surfaced three errors, reconciled against hardware_config.json: - The power button was documented as GPIO 21 to GND with a pull-up. It is active high (pull_up: false); wiring it as documented reads as permanently pressed. - GPIO_BUTTONS used GPIO 23 for next-page; it is GPIO 27. - The FT5316 INT pin was routed to GPIO 27, which collides with the next-page button. Now documented as a conflict. Scripts: - Move debug_overlay_links.py and debug_previous_page.py to scripts/debug/ - Rename test_pagination_visual.py to scripts/debug/visualize_pagination.py; it renders output and asserts nothing, so the test_ prefix was misleading - Fix the __file__-relative paths these three relied on - Track update_pyweblayout.sh under scripts/ Tests: - Reword the backward-navigation tests, which described a pyWebLayout bug that is now fixed, as regression tests Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Debug script to visualize interactive elements in overlays.
|
||||
Shows where clickable links are located.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
sys.path.insert(0, str(Path(__file__).parents[2]))
|
||||
|
||||
from dreader.application import EbookReader
|
||||
from dreader.overlays.settings import SettingsOverlay
|
||||
from dreader.overlays.navigation import NavigationOverlay
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
def find_all_links(overlay_reader, panel_width, panel_height):
|
||||
"""Scan overlay to find all interactive link positions."""
|
||||
link_positions = {}
|
||||
|
||||
if not overlay_reader or not overlay_reader.manager:
|
||||
print("No overlay reader available")
|
||||
return link_positions
|
||||
|
||||
page = overlay_reader.manager.get_current_page()
|
||||
if not page:
|
||||
print("No page available")
|
||||
return link_positions
|
||||
|
||||
print(f"Scanning {panel_width}x{panel_height} overlay for interactive elements...")
|
||||
|
||||
# Scan with moderate granularity (every 5 pixels)
|
||||
for y in range(0, panel_height, 5):
|
||||
for x in range(0, panel_width, 5):
|
||||
result = page.query_point((x, y))
|
||||
if result and result.link_target:
|
||||
if result.link_target not in link_positions:
|
||||
link_positions[result.link_target] = {
|
||||
'first_pos': (x, y),
|
||||
'bounds': result.bounds,
|
||||
'text': result.text
|
||||
}
|
||||
|
||||
return link_positions
|
||||
|
||||
|
||||
def visualize_settings_overlay():
|
||||
"""Visualize interactive elements in settings overlay."""
|
||||
print("\n" + "="*70)
|
||||
print("SETTINGS OVERLAY - Interactive Element Map")
|
||||
print("="*70)
|
||||
|
||||
# Create reader
|
||||
reader = EbookReader(page_size=(800, 1200))
|
||||
|
||||
# Load a test book
|
||||
test_book = Path(__file__).parents[2] / "tests" / "data" / "library-epub" / "pg11-images-3.epub"
|
||||
if not test_book.exists():
|
||||
print(f"Test book not found: {test_book}")
|
||||
return
|
||||
|
||||
reader.load_epub(str(test_book))
|
||||
|
||||
# Create settings overlay
|
||||
settings_overlay = SettingsOverlay(reader)
|
||||
base_page = reader.get_current_page()
|
||||
|
||||
# Open overlay
|
||||
overlay_image = settings_overlay.open(
|
||||
base_page,
|
||||
font_scale=1.0,
|
||||
line_spacing=5,
|
||||
inter_block_spacing=15,
|
||||
word_spacing=0
|
||||
)
|
||||
|
||||
# Find all interactive elements
|
||||
panel_width = 480 # 60% of 800
|
||||
panel_height = 840 # 70% of 1200
|
||||
|
||||
link_positions = find_all_links(
|
||||
settings_overlay._overlay_reader,
|
||||
panel_width,
|
||||
panel_height
|
||||
)
|
||||
|
||||
print(f"\nFound {len(link_positions)} interactive elements:")
|
||||
for link_target, info in sorted(link_positions.items()):
|
||||
x, y = info['first_pos']
|
||||
bounds = info['bounds']
|
||||
text = info['text']
|
||||
print(f" {link_target:30s} at ({x:3d}, {y:3d}) - \"{text}\"")
|
||||
print(f" Bounds: {bounds}")
|
||||
|
||||
# Create visualization
|
||||
print("\nCreating visualization...")
|
||||
|
||||
# Get just the overlay panel (not the composited image)
|
||||
overlay_panel = settings_overlay._cached_overlay_image.copy()
|
||||
draw = ImageDraw.Draw(overlay_panel)
|
||||
|
||||
# Draw markers on each interactive element
|
||||
for link_target, info in link_positions.items():
|
||||
x, y = info['first_pos']
|
||||
|
||||
# Draw red circle at first detected position
|
||||
radius = 8
|
||||
draw.ellipse(
|
||||
[x - radius, y - radius, x + radius, y + radius],
|
||||
outline=(255, 0, 0),
|
||||
width=2
|
||||
)
|
||||
|
||||
# Draw crosshair
|
||||
draw.line([(x - 15, y), (x + 15, y)], fill=(255, 0, 0), width=1)
|
||||
draw.line([(x, y - 15), (x, y + 15)], fill=(255, 0, 0), width=1)
|
||||
|
||||
# Save visualization
|
||||
output_path = Path(__file__).parent / "overlay_links_debug.png"
|
||||
overlay_panel.save(output_path)
|
||||
print(f"\nVisualization saved to: {output_path}")
|
||||
print("Red circles show clickable link positions")
|
||||
|
||||
reader.close()
|
||||
|
||||
|
||||
def visualize_navigation_overlay():
|
||||
"""Visualize interactive elements in navigation overlay."""
|
||||
print("\n" + "="*70)
|
||||
print("NAVIGATION OVERLAY - Interactive Element Map")
|
||||
print("="*70)
|
||||
|
||||
# Create reader
|
||||
reader = EbookReader(page_size=(800, 1200))
|
||||
|
||||
# Load a test book
|
||||
test_book = Path(__file__).parents[2] / "tests" / "data" / "library-epub" / "pg11-images-3.epub"
|
||||
if not test_book.exists():
|
||||
print(f"Test book not found: {test_book}")
|
||||
return
|
||||
|
||||
reader.load_epub(str(test_book))
|
||||
|
||||
# Create navigation overlay
|
||||
nav_overlay = NavigationOverlay(reader)
|
||||
base_page = reader.get_current_page()
|
||||
|
||||
# Get chapters
|
||||
chapters = reader.get_chapters()
|
||||
|
||||
# Open overlay
|
||||
overlay_image = nav_overlay.open(
|
||||
base_page,
|
||||
chapters=chapters,
|
||||
bookmarks=[],
|
||||
active_tab="contents"
|
||||
)
|
||||
|
||||
# Find all interactive elements
|
||||
panel_width = 480 # 60% of 800
|
||||
panel_height = 840 # 70% of 1200
|
||||
|
||||
link_positions = find_all_links(
|
||||
nav_overlay._overlay_reader,
|
||||
panel_width,
|
||||
panel_height
|
||||
)
|
||||
|
||||
print(f"\nFound {len(link_positions)} interactive elements:")
|
||||
for link_target, info in sorted(link_positions.items()):
|
||||
x, y = info['first_pos']
|
||||
text = info['text']
|
||||
print(f" {link_target:30s} at ({x:3d}, {y:3d}) - \"{text}\"")
|
||||
|
||||
# Create visualization
|
||||
print("\nCreating visualization...")
|
||||
|
||||
# Get just the overlay panel
|
||||
overlay_panel = nav_overlay._cached_overlay_image.copy()
|
||||
draw = ImageDraw.Draw(overlay_panel)
|
||||
|
||||
# Draw markers on each interactive element
|
||||
for link_target, info in link_positions.items():
|
||||
x, y = info['first_pos']
|
||||
|
||||
# Draw green circle
|
||||
radius = 8
|
||||
draw.ellipse(
|
||||
[x - radius, y - radius, x + radius, y + radius],
|
||||
outline=(0, 255, 0),
|
||||
width=2
|
||||
)
|
||||
|
||||
# Save visualization
|
||||
output_path = Path(__file__).parent / "nav_overlay_links_debug.png"
|
||||
overlay_panel.save(output_path)
|
||||
print(f"\nVisualization saved to: {output_path}")
|
||||
print("Green circles show clickable link positions")
|
||||
|
||||
reader.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
visualize_settings_overlay()
|
||||
visualize_navigation_overlay()
|
||||
print("\n" + "="*70)
|
||||
print("Debug complete! Check the generated PNG files.")
|
||||
print("="*70)
|
||||
Reference in New Issue
Block a user