pyWebLayout/examples/03_page_layouts.py
Duncan Tourolle b1553f1628
All checks were successful
Python CI / test (push) Successful in 6m35s
refactor continues
2025-11-07 19:26:32 +01:00

244 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Page Layouts Example
This example demonstrates different page layout configurations:
- Various page sizes (small, medium, large)
- Different aspect ratios (portrait, landscape, square)
- Border and padding variations
- Color schemes
Shows how the pyWebLayout system handles different page dimensions.
"""
import sys
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
# Add pyWebLayout to path
sys.path.insert(0, str(Path(__file__).parent.parent))
from pyWebLayout.concrete.page import Page
from pyWebLayout.style.page_style import PageStyle
def add_page_info(page: Page, title: str):
"""Add informational text to a page showing its properties."""
if page.draw is None:
page.render()
draw = page.draw
try:
font_large = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 14)
font_small = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 11)
except:
font_large = ImageFont.load_default()
font_small = ImageFont.load_default()
# Title
content_x = page.border_size + page.style.padding_left + 5
content_y = page.border_size + page.style.padding_top + 5
draw.text((content_x, content_y), title, fill=(40, 40, 40), font=font_large)
# Page info
y = content_y + 25
info = [
f"Page: {page.size[0]}×{page.size[1]}px",
f"Content: {page.content_size[0]}×{page.content_size[1]}px",
f"Border: {page.border_size}px",
f"Padding: {page.style.padding}",
]
for line in info:
draw.text((content_x, y), line, fill=(80, 80, 80), font=font_small)
y += 16
# Draw content area boundary
cx = page.border_size + page.style.padding_left
cy = page.border_size + page.style.padding_top
cw = page.content_size[0]
ch = page.content_size[1]
draw.rectangle(
[cx, cy, cx + cw, cy + ch],
outline=(150, 150, 255),
width=1
)
def create_layouts():
"""Create various page layout examples."""
layouts = []
# 1. Small portrait page
print("\n Creating layout examples...")
print(" - Small portrait")
style1 = PageStyle(
border_width=2,
border_color=(100, 100, 100),
padding=(15, 15, 15, 15),
background_color=(255, 255, 255)
)
page1 = Page(size=(300, 400), style=style1)
add_page_info(page1, "Small Portrait")
layouts.append(("small_portrait", page1))
# 2. Large portrait page
print(" - Large portrait")
style2 = PageStyle(
border_width=3,
border_color=(150, 100, 100),
padding=(30, 30, 30, 30),
background_color=(255, 250, 250)
)
page2 = Page(size=(400, 600), style=style2)
add_page_info(page2, "Large Portrait")
layouts.append(("large_portrait", page2))
# 3. Landscape page
print(" - Landscape")
style3 = PageStyle(
border_width=2,
border_color=(100, 150, 100),
padding=(20, 40, 20, 40),
background_color=(250, 255, 250)
)
page3 = Page(size=(600, 350), style=style3)
add_page_info(page3, "Landscape")
layouts.append(("landscape", page3))
# 4. Square page
print(" - Square")
style4 = PageStyle(
border_width=3,
border_color=(100, 100, 150),
padding=(25, 25, 25, 25),
background_color=(250, 250, 255)
)
page4 = Page(size=(400, 400), style=style4)
add_page_info(page4, "Square")
layouts.append(("square", page4))
# 5. Minimal padding
print(" - Minimal padding")
style5 = PageStyle(
border_width=1,
border_color=(180, 180, 180),
padding=(5, 5, 5, 5),
background_color=(245, 245, 245)
)
page5 = Page(size=(350, 300), style=style5)
add_page_info(page5, "Minimal Padding")
layouts.append(("minimal", page5))
# 6. Generous padding
print(" - Generous padding")
style6 = PageStyle(
border_width=2,
border_color=(150, 120, 100),
padding=(50, 50, 50, 50),
background_color=(255, 250, 245)
)
page6 = Page(size=(400, 400), style=style6)
add_page_info(page6, "Generous Padding")
layouts.append(("generous", page6))
return layouts
def create_layout_showcase(layouts):
"""Create a showcase image displaying all layouts."""
print("\n Creating layout showcase...")
# Render all pages
images = [(name, page.render()) for name, page in layouts]
# Calculate grid layout (3×2)
padding = 15
title_height = 50
cols = 3
rows = 2
# Find max dimensions for each row/column
max_widths = []
for col in range(cols):
col_images = [images[row * cols + col][1] for row in range(rows) if row * cols + col < len(images)]
if col_images:
max_widths.append(max(img.size[0] for img in col_images))
max_heights = []
for row in range(rows):
row_images = [images[row * cols + col][1] for col in range(cols) if row * cols + col < len(images)]
if row_images:
max_heights.append(max(img.size[1] for img in row_images))
# Calculate total size
total_width = sum(max_widths) + padding * (cols + 1)
total_height = sum(max_heights) + padding * (rows + 1) + title_height
# Create combined image
combined = Image.new('RGB', (total_width, total_height), (235, 235, 235))
draw = ImageDraw.Draw(combined)
# Add title
try:
title_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 24)
except:
title_font = ImageFont.load_default()
title_text = "Page Layout Examples"
bbox = draw.textbbox((0, 0), title_text, font=title_font)
text_width = bbox[2] - bbox[0]
title_x = (total_width - text_width) // 2
draw.text((title_x, 15), title_text, fill=(50, 50, 50), font=title_font)
# Place images in grid
y_offset = title_height + padding
for row in range(rows):
x_offset = padding
for col in range(cols):
idx = row * cols + col
if idx < len(images):
name, img = images[idx]
# Center image in its cell
cell_width = max_widths[col]
cell_height = max_heights[row]
img_x = x_offset + (cell_width - img.size[0]) // 2
img_y = y_offset + (cell_height - img.size[1]) // 2
combined.paste(img, (img_x, img_y))
x_offset += max_widths[col] + padding if col < len(max_widths) else 0
y_offset += max_heights[row] + padding if row < len(max_heights) else 0
return combined
def main():
"""Demonstrate page layout variations."""
print("Page Layouts Example")
print("=" * 50)
# Create different layouts
layouts = create_layouts()
# Create showcase
combined_image = create_layout_showcase(layouts)
# Save output
output_dir = Path("docs/images")
output_dir.mkdir(parents=True, exist_ok=True)
output_path = output_dir / "example_03_page_layouts.png"
combined_image.save(output_path)
print(f"\n✓ Example completed!")
print(f" Output saved to: {output_path}")
print(f" Image size: {combined_image.size[0]}x{combined_image.size[1]} pixels")
print(f" Created {len(layouts)} layout examples")
return combined_image
if __name__ == "__main__":
main()