fix for reverse redering on restart
All checks were successful
Python CI / test (3.10) (push) Successful in 2m10s
Python CI / test (3.12) (push) Successful in 2m2s
Python CI / test (3.13) (push) Successful in 1m56s

This commit is contained in:
Duncan Tourolle 2025-11-10 13:17:20 +01:00
parent a8e459bce5
commit 890a0e768b
2 changed files with 53 additions and 6 deletions

View File

@ -337,8 +337,17 @@ class BidirectionalLayouter:
comparison = self._position_compare(actual_end, end_position)
# Perfect match or close enough (within same block)
# BUT: ensure we actually moved backward (estimated_start < end_position)
if comparison == 0:
# Check if we actually found a valid previous page
if self._position_compare(estimated_start, end_position) < 0:
return page, estimated_start
# If estimated_start >= end_position, we haven't moved backward
# Continue iterating to find a better position
elif iteration == 0:
# On first iteration, if we can't find a previous position,
# we're likely at or near the beginning
break
# Track best result so far
distance = abs(actual_end.block_index - end_position.block_index)
@ -357,7 +366,39 @@ class BidirectionalLayouter:
estimated_start.word_index = 0
# If we exhausted iterations, return best result found
return best_page if best_page else page, best_start
# BUT: ensure we didn't return the same position (no backward progress)
final_page = best_page if best_page else page
final_start = best_start
# Safety check: if final_start >= end_position, we failed to move backward
# This can happen at the beginning of the document or when estimation failed
if self._position_compare(final_start, end_position) >= 0:
# Can't go further back - check if we're at the absolute beginning
if end_position.block_index == 0 and end_position.word_index == 0:
# Already at beginning, return as-is
return final_page, final_start
# Fallback strategy: try a more aggressive backward jump
# Start from several blocks before the current position
blocks_to_jump = max(1, min(5, end_position.block_index))
fallback_pos = RenderingPosition(
chapter_index=end_position.chapter_index,
block_index=max(0, end_position.block_index - blocks_to_jump),
word_index=0
)
# Render forward from the fallback position
fallback_page, fallback_end = self.render_page_forward(fallback_pos, font_scale)
# Verify the fallback actually moved us backward
if self._position_compare(fallback_pos, end_position) < 0:
return fallback_page, fallback_pos
# If even the fallback didn't work, we're likely at the beginning
# Return a page starting from the beginning
return self.render_page_forward(RenderingPosition(), font_scale)
return final_page, final_start
def _scale_block_fonts(self, block: Block, font_scale: float) -> Block:
"""Apply font scaling to all fonts in a block"""

View File

@ -420,13 +420,19 @@ class BufferedPageRenderer:
cached_page = self.buffer.get_page(end_position)
if cached_page:
# Get previous position from reverse position map
prev_pos = self.buffer.reverse_position_map.get(end_position, end_position)
prev_pos = self.buffer.reverse_position_map.get(end_position)
# Only use cache if we have the reverse position mapping
# Otherwise, we need to compute it
if prev_pos is not None:
# Start background rendering for previous pages
self.buffer.start_background_rendering(end_position, 'backward')
return cached_page, prev_pos
# Cache hit for the page, but we don't have the reverse position
# Fall through to compute it below
# Render the page directly
page, start_pos = self.layouter.render_page_backward(end_position, font_scale)