#!/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()