fixed issue with cover and image rendering
Python CI / test (3.10) (push) Successful in 2m10s
Python CI / test (3.12) (push) Successful in 2m3s
Python CI / test (3.13) (push) Successful in 1m57s

This commit is contained in:
2025-11-10 13:06:21 +01:00
parent 9fb6792e10
commit a8e459bce5
6 changed files with 681 additions and 15 deletions
+5
View File
@@ -306,6 +306,11 @@ def image_layouter(image: AbstractImage, page: Page, max_width: Optional[int] =
# Calculate available height on page
available_height = page.size[1] - page._current_y_offset - page.border_size
# If no space available, image doesn't fit
if available_height <= 0:
return False
if max_height is None:
max_height = available_height
else:
+64 -2
View File
@@ -15,13 +15,13 @@ from __future__ import annotations
from dataclasses import dataclass, asdict
from typing import List, Dict, Tuple, Optional, Any
from pyWebLayout.abstract.block import Block, Paragraph, Heading, HeadingLevel, Table, HList
from pyWebLayout.abstract.block import Block, Paragraph, Heading, HeadingLevel, Table, HList, Image
from pyWebLayout.abstract.inline import Word
from pyWebLayout.concrete.page import Page
from pyWebLayout.concrete.text import Text
from pyWebLayout.style.page_style import PageStyle
from pyWebLayout.style import Font
from pyWebLayout.layout.document_layouter import paragraph_layouter
from pyWebLayout.layout.document_layouter import paragraph_layouter, image_layouter
@dataclass
@@ -94,6 +94,26 @@ class ChapterNavigator:
"""Scan blocks for headings and build chapter navigation map"""
current_chapter_index = 0
# Check if first block is a cover image and add it to TOC
if self.blocks and isinstance(self.blocks[0], Image):
cover_position = RenderingPosition(
chapter_index=0,
block_index=0,
word_index=0,
table_row=0,
table_col=0,
list_item_index=0
)
cover_info = ChapterInfo(
title="Cover",
level=HeadingLevel.H1, # Treat as top-level entry
position=cover_position,
block_index=0
)
self.chapters.append(cover_info)
for block_index, block in enumerate(self.blocks):
if isinstance(block, Heading):
# Create position for this heading
@@ -384,6 +404,8 @@ class BidirectionalLayouter:
return self._layout_table_on_page(block, page, position, font_scale)
elif isinstance(block, HList):
return self._layout_list_on_page(block, page, position, font_scale)
elif isinstance(block, Image):
return self._layout_image_on_page(block, page, position, font_scale)
else:
# Skip unknown block types
new_pos = position.copy()
@@ -496,6 +518,46 @@ class BidirectionalLayouter:
new_pos.list_item_index = 0
return True, new_pos
def _layout_image_on_page(self,
image: Image,
page: Page,
position: RenderingPosition,
font_scale: float) -> Tuple[bool,
RenderingPosition]:
"""
Layout an image on the page using the image_layouter.
Args:
image: The Image block to layout
page: The page to layout on
position: Current rendering position (should be at the start of this image block)
font_scale: Font scaling factor (not used for images, but kept for consistency)
Returns:
Tuple of (success, new_position)
- success: True if image was laid out, False if page ran out of space
- new_position: Updated position (next block if success, same block if failed)
"""
# Try to layout the image on the current page
success = image_layouter(
image=image,
page=page,
max_width=None, # Use page available width
max_height=None # Use page available height
)
new_pos = position.copy()
if success:
# Image was successfully laid out, move to next block
new_pos.block_index += 1
new_pos.word_index = 0
return True, new_pos
else:
# Image didn't fit on current page, signal to continue on next page
# Keep same position so it will be attempted on the next page
return False, position
def _estimate_page_start(
self,
end_position: RenderingPosition,