#!/usr/bin/env python3 """ Simple demonstration of mono-space font testing concepts. """ from pyWebLayout.concrete.text import Text, Line from pyWebLayout.style.fonts import Font from pyWebLayout.style.layout import Alignment def main(): print("=== Mono-space Font Testing Demo ===\n") # Create a regular font font = Font(font_size=12) print("1. Character Width Variance Analysis:") print("-" * 40) # Test different characters to show width variance test_chars = "iIlLmMwW" widths = {} for char in test_chars: text = Text(char, font) widths[char] = text.width print(f" '{char}': {text.width:3d}px") min_w = min(widths.values()) max_w = max(widths.values()) variance = max_w - min_w print(f"\n Range: {min_w}-{max_w}px (variance: {variance}px)") print(f" Ratio: {max_w/min_w:.1f}x difference") print("\n2. Why This Matters for Testing:") print("-" * 40) # Show how same-length strings have different widths word1 = "ill" # narrow word2 = "WWW" # wide text1 = Text(word1, font) text2 = Text(word2, font) print(f" '{word1}' (3 chars): {text1.width}px") print(f" '{word2}' (3 chars): {text2.width}px") print(f" Same length, {abs(text1.width - text2.width)}px difference!") print("\n3. Line Capacity Prediction:") print("-" * 40) line_width = 100 print(f" Line width: {line_width}px") # Test how many characters fit test_cases = [ ("narrow chars", "i" * 20), ("wide chars", "W" * 10), ("mixed text", "Hello World") ] for name, text_str in test_cases: text_obj = Text(text_str, font) fits = "YES" if text_obj.width <= line_width else "NO" print(f" {name:12}: '{text_str[:10]}...' ({len(text_str)} chars, {text_obj.width}px) → {fits}") print("\n4. With Mono-space Fonts:") print("-" * 40) # Try to use an actual mono-space font mono_font = None mono_paths = [ "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", "/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf", "/System/Library/Fonts/Monaco.ttf", "C:/Windows/Fonts/consola.ttf" ] import os for path in mono_paths: if os.path.exists(path): try: mono_font = Font(font_path=path, font_size=12) print(f" Using actual mono-space font: {os.path.basename(path)}") break except: continue if mono_font: # Test actual mono-space character consistency mono_test_chars = "iIlLmMwW" mono_widths = {} for char in mono_test_chars: text = Text(char, mono_font) mono_widths[char] = text.width mono_min = min(mono_widths.values()) mono_max = max(mono_widths.values()) mono_variance = mono_max - mono_min print(f" Mono-space character widths:") for char, width in mono_widths.items(): print(f" '{char}': {width}px") print(f" Range: {mono_min}-{mono_max}px (variance: {mono_variance}px)") # Compare to regular font variance regular_variance = max_w - min_w improvement = regular_variance / max(1, mono_variance) print(f" Improvement: {improvement:.1f}x more consistent!") # Test line capacity with actual mono-space mono_char_width = mono_widths['M'] # Use actual width capacity = line_width // mono_char_width print(f"\n Actual mono-space line capacity:") print(f" Each character: {mono_char_width}px") print(f" Line capacity: {capacity} characters") # Prove consistency with different character combinations test_strings = [ "i" * capacity, "W" * capacity, "M" * capacity, "l" * capacity ] print(f" Testing {capacity}-character strings:") all_same_width = True first_width = None for test_str in test_strings: text_obj = Text(test_str, mono_font) if first_width is None: first_width = text_obj.width elif abs(text_obj.width - first_width) > 2: # Allow 2px tolerance all_same_width = False print(f" '{test_str[0]}' × {len(test_str)}: {text_obj.width}px") if all_same_width: print(f" ✓ ALL {capacity}-character strings have the same width!") else: print(f" ⚠ Some variance detected (font may not be perfectly mono-space)") else: print(" No mono-space font found - showing theoretical values:") mono_char_width = 8 # Typical mono-space width capacity = line_width // mono_char_width print(f" Each character: {mono_char_width}px (theoretical)") print(f" Line capacity: {capacity} characters") print(f" ANY {capacity}-character string would fit!") print(f" Layout calculations become simple math") print("\n5. Line Fitting Test:") print("-" * 40) # Test actual line fitting line = Line( spacing=(2, 4), origin=(0, 0), size=(line_width, 20), font=font, halign=Alignment.LEFT ) test_word = "development" # 11 characters word_obj = Text(test_word, font) print(f" Test word: '{test_word}' ({len(test_word)} chars, {word_obj.width}px)") print(f" Line width: {line_width}px") result = line.add_word(test_word, font) if result is None: print(" Result: Word fits completely") else: if line.text_objects: added = line.text_objects[0].text print(f" Result: Added '{added}', remaining '{result}'") else: print(" Result: Word rejected completely") # Use actual mono font width if available, otherwise theoretical if mono_font: actual_mono_width = mono_widths['M'] print(f"\n With actual mono-space ({actual_mono_width}px/char):") print(f" Word would be: {len(test_word)} × {actual_mono_width} = {len(test_word) * actual_mono_width}px") if len(test_word) * actual_mono_width <= line_width: print(" → Would fit completely") else: chars_that_fit = line_width // actual_mono_width print(f" → Would need breaking after {chars_that_fit} characters") else: theoretical_mono_width = 8 print(f"\n With theoretical mono-space ({theoretical_mono_width}px/char):") print(f" Word would be: {len(test_word)} × {theoretical_mono_width} = {len(test_word) * theoretical_mono_width}px") if len(test_word) * theoretical_mono_width <= line_width: print(" → Would fit completely") else: chars_that_fit = line_width // theoretical_mono_width print(f" → Would need breaking after {chars_that_fit} characters") print("\n=== Conclusion ===") print("Mono-space fonts make testing predictable because:") print("- Character width is constant") print("- Line capacity is calculable") print("- Word fitting is based on character count") print("- Layout behavior is deterministic") # Check if test_output directory exists, if so save a simple visual import os if os.path.exists("test_output"): print(f"\nCreating visual test output...") # Create a simple line rendering test from pyWebLayout.concrete.page import Page, Container page = Page(size=(400, 200)) container = Container( origin=(0, 0), size=(380, 180), direction='vertical', spacing=5, padding=(10, 10, 10, 10) ) # Add title title = Text("Character Width Variance Demo", font) container.add_child(title) # Add test lines showing different characters for char_type, char in [("Narrow", "i"), ("Wide", "W"), ("Average", "n")]: line_text = f"{char_type}: {char * 10}" text_obj = Text(line_text, font) container.add_child(text_obj) page.add_child(container) image = page.render() output_path = os.path.join("test_output", "monospace_demo.png") image.save(output_path) print(f"Visual demo saved to: {output_path}") if __name__ == "__main__": main()