#!/usr/bin/env python3 """ Text and Layout Example This example demonstrates text rendering using the pyWebLayout system: - Different text alignments - Font sizes and styles - Multi-line paragraphs - Document layout and pagination This example uses the HTML parsing system to create rich text layouts. """ from pyWebLayout.style.page_style import PageStyle from pyWebLayout.concrete.page import Page from pyWebLayout.style import Font from pyWebLayout.io.readers.html_extraction import parse_html_string 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)) def create_sample_document(): """Create different HTML samples demonstrating various features.""" samples = [] # Sample 1: Text alignment examples samples.append(( "Text Alignment", """

Left Aligned

This is left-aligned text. It is the default alignment for most text.

Justified Text

This paragraph is justified. The text stretches to fill the entire width of the line, creating clean edges on both sides.

Centered

This text is centered.

""" )) # Sample 2: Font sizes samples.append(( "Font Sizes", """

Heading 1

Heading 2

Heading 3

Normal paragraph text at the default size.

Small text for fine print.

""" )) # Sample 3: Text styles samples.append(( "Text Styles", """

Normal text with bold words and italic text.

Completely bold paragraph.

Completely italic paragraph.

Text with underlined words for emphasis.

""" )) # Sample 4: Mixed content samples.append(( "Mixed Content", """

Document Title

A paragraph with bold, italic, and normal text all mixed together.

Subsection

Another paragraph demonstrating the layout system.

""" )) return samples def render_html_to_image(html_content, page_size=(500, 400)): """Render HTML content to an image using the pyWebLayout system.""" # Create a page page_style = PageStyle( border_width=2, border_color=(200, 200, 200), padding=(30, 30, 30, 30), background_color=(255, 255, 255) ) page = Page(size=page_size, style=page_style) # Parse HTML base_font = Font(font_size=14) blocks = parse_html_string(html_content, base_font=base_font) # For now, just render the page structure # (The full layout engine would place the blocks, but we'll show the page) image = page.render() draw = ImageDraw.Draw(image) # Add a note that this is HTML-parsed content try: font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 11) except BaseException: font = ImageFont.load_default() # Draw info about what was parsed content_x = page.border_size + page.style.padding_left + 10 content_y = page.border_size + page.style.padding_top + 10 draw.text((content_x, content_y), f"Parsed {len(blocks)} block(s) from HTML", fill=(100, 100, 100), font=font) # List the block types y_offset = content_y + 25 for i, block in enumerate(blocks[:10]): # Show first 10 block_type = type(block).__name__ draw.text((content_x, y_offset), f" {i + 1}. {block_type}", fill=(60, 60, 60), font=font) y_offset += 18 if y_offset > page.size[1] - 60: # Don't overflow break return image def combine_samples(samples): """Combine multiple sample renders into a grid.""" print("\n Rendering samples...") images = [] for title, html in samples: print(f" - {title}") img = render_html_to_image(html) # Add title to image draw = ImageDraw.Draw(img) try: font = ImageFont.truetype( "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 14) except BaseException: font = ImageFont.load_default() draw.text((10, 10), title, fill=(50, 50, 150), font=font) images.append(img) # Create grid (2x2) padding = 20 cols = 2 rows = 2 img_width = images[0].size[0] img_height = images[0].size[1] total_width = cols * img_width + (cols + 1) * padding total_height = rows * img_height + (rows + 1) * padding combined = Image.new('RGB', (total_width, total_height), (240, 240, 240)) # Place images y_offset = padding for row in range(rows): x_offset = padding for col in range(cols): idx = row * cols + col if idx < len(images): combined.paste(images[idx], (x_offset, y_offset)) x_offset += img_width + padding y_offset += img_height + padding return combined def main(): """Demonstrate text and layout features.""" print("Text and Layout Example") print("=" * 50) # Create sample documents samples = create_sample_document() # Render and combine combined_image = combine_samples(samples) # Save output output_dir = Path("docs/images") output_dir.mkdir(parents=True, exist_ok=True) output_path = output_dir / "example_02_text_and_layout.png" combined_image.save(output_path) print("\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(" Note: This example demonstrates HTML parsing") print(" Full layout rendering requires the typesetting engine") return combined_image if __name__ == "__main__": main()