Api for changing sizes dynamically
All checks were successful
Python CI / test (push) Successful in 6m54s

This commit is contained in:
Duncan Tourolle 2025-11-08 18:22:58 +01:00
parent f8baf155e9
commit 13d20c28c5
4 changed files with 119 additions and 10 deletions

View File

@ -75,6 +75,15 @@ def paragraph_layouter(paragraph: Paragraph, page: Page, start_word: int = 0, pr
) )
text_align = concrete_style.text_align text_align = concrete_style.text_align
# Apply page-level word spacing override if specified
if hasattr(page.style, 'word_spacing') and isinstance(page.style.word_spacing, int) and page.style.word_spacing > 0:
# Add the page-level word spacing to both min and max constraints
min_ws, max_ws = word_spacing_constraints
word_spacing_constraints = (
min_ws + page.style.word_spacing,
max_ws + page.style.word_spacing
)
# Apply alignment override if provided # Apply alignment override if provided
if alignment_override is not None: if alignment_override is not None:
text_align = alignment_override text_align = alignment_override
@ -91,9 +100,14 @@ def paragraph_layouter(paragraph: Paragraph, page: Page, start_word: int = 0, pr
background=font.background background=font.background
) )
# Calculate baseline-to-baseline spacing using line spacing multiplier # Calculate baseline-to-baseline spacing: font size + additional line spacing
# This is the vertical distance between baselines of consecutive lines # This is the vertical distance between baselines of consecutive lines
baseline_spacing = int(font.font_size * page.style.line_spacing_multiplier) # Formula: baseline_spacing = font_size + line_spacing (absolute pixels)
line_spacing_value = getattr(page.style, 'line_spacing', 5)
# Ensure line_spacing is an int (could be Mock in tests)
if not isinstance(line_spacing_value, int):
line_spacing_value = 5
baseline_spacing = font.font_size + line_spacing_value
# Get font metrics for boundary checking # Get font metrics for boundary checking
ascent, descent = font.font.getmetrics() ascent, descent = font.font.getmetrics()

View File

@ -252,6 +252,11 @@ class BidirectionalLayouter:
# Block doesn't fit, we're done with this page # Block doesn't fit, we're done with this page
break break
# Add inter-block spacing after successfully laying out a block
# Only add if we're not at the end of the document and there's space
if new_pos.block_index < len(self.blocks):
page._current_y_offset += self.page_style.inter_block_spacing
# Ensure new position doesn't go beyond bounds # Ensure new position doesn't go beyond bounds
if new_pos.block_index >= len(self.blocks): if new_pos.block_index >= len(self.blocks):
# We've reached the end of the document # We've reached the end of the document

View File

@ -342,6 +342,96 @@ class EreaderLayoutManager:
"""Get the current font scale""" """Get the current font scale"""
return self.font_scale return self.font_scale
def increase_line_spacing(self, amount: int = 2) -> Page:
"""
Increase line spacing and re-render current page.
Args:
amount: Pixels to add to line spacing (default: 2)
Returns:
Re-rendered page with increased line spacing
"""
self.page_style.line_spacing += amount
self.renderer.page_style = self.page_style # Update renderer's reference
self.renderer.buffer.invalidate_all() # Clear cache to force re-render
return self.get_current_page()
def decrease_line_spacing(self, amount: int = 2) -> Page:
"""
Decrease line spacing and re-render current page.
Args:
amount: Pixels to remove from line spacing (default: 2)
Returns:
Re-rendered page with decreased line spacing
"""
self.page_style.line_spacing = max(0, self.page_style.line_spacing - amount)
self.renderer.page_style = self.page_style # Update renderer's reference
self.renderer.buffer.invalidate_all() # Clear cache to force re-render
return self.get_current_page()
def increase_inter_block_spacing(self, amount: int = 5) -> Page:
"""
Increase spacing between blocks and re-render current page.
Args:
amount: Pixels to add to inter-block spacing (default: 5)
Returns:
Re-rendered page with increased block spacing
"""
self.page_style.inter_block_spacing += amount
self.renderer.page_style = self.page_style # Update renderer's reference
self.renderer.buffer.invalidate_all() # Clear cache to force re-render
return self.get_current_page()
def decrease_inter_block_spacing(self, amount: int = 5) -> Page:
"""
Decrease spacing between blocks and re-render current page.
Args:
amount: Pixels to remove from inter-block spacing (default: 5)
Returns:
Re-rendered page with decreased block spacing
"""
self.page_style.inter_block_spacing = max(0, self.page_style.inter_block_spacing - amount)
self.renderer.page_style = self.page_style # Update renderer's reference
self.renderer.buffer.invalidate_all() # Clear cache to force re-render
return self.get_current_page()
def increase_word_spacing(self, amount: int = 2) -> Page:
"""
Increase spacing between words and re-render current page.
Args:
amount: Pixels to add to word spacing (default: 2)
Returns:
Re-rendered page with increased word spacing
"""
self.page_style.word_spacing += amount
self.renderer.page_style = self.page_style # Update renderer's reference
self.renderer.buffer.invalidate_all() # Clear cache to force re-render
return self.get_current_page()
def decrease_word_spacing(self, amount: int = 2) -> Page:
"""
Decrease spacing between words and re-render current page.
Args:
amount: Pixels to remove from word spacing (default: 2)
Returns:
Re-rendered page with decreased word spacing
"""
self.page_style.word_spacing = max(0, self.page_style.word_spacing - amount)
self.renderer.page_style = self.page_style # Update renderer's reference
self.renderer.buffer.invalidate_all() # Clear cache to force re-render
return self.get_current_page()
def get_table_of_contents(self) -> List[Tuple[str, HeadingLevel, RenderingPosition]]: def get_table_of_contents(self) -> List[Tuple[str, HeadingLevel, RenderingPosition]]:
""" """
Get the table of contents. Get the table of contents.

View File

@ -14,8 +14,9 @@ class PageStyle:
border_color: Tuple[int, int, int] = (0, 0, 0) border_color: Tuple[int, int, int] = (0, 0, 0)
# Spacing properties # Spacing properties
line_spacing: int = 5 line_spacing: int = 5 # Additional pixels between lines (added to font size)
inter_block_spacing: int = 15 inter_block_spacing: int = 15 # Pixels between blocks (paragraphs, headings, etc.)
word_spacing: int = 0 # Additional pixels between words (0 = use font defaults)
# Padding (top, right, bottom, left) # Padding (top, right, bottom, left)
padding: Tuple[int, int, int, int] = (20, 20, 20, 20) padding: Tuple[int, int, int, int] = (20, 20, 20, 20)
@ -25,7 +26,6 @@ class PageStyle:
# Typography properties # Typography properties
max_font_size: int = 72 # Maximum font size allowed on a page max_font_size: int = 72 # Maximum font size allowed on a page
line_spacing_multiplier: float = 1.2 # Baseline-to-baseline spacing multiplier
@property @property
def padding_top(self) -> int: def padding_top(self) -> int: