Skip to content

Add text boxing support#30

Merged
bitomule merged 9 commits into
mainfrom
feature/text-boxing
May 10, 2026
Merged

Add text boxing support#30
bitomule merged 9 commits into
mainfrom
feature/text-boxing

Conversation

@bitomule
Copy link
Copy Markdown
Owner

@bitomule bitomule commented May 9, 2026

Summary

  • Add optional text box configuration for YAML/content text items
  • Render paragraph boxes as one box around the wrapped text block
  • Render character boxes as boxes around wrapped line fragments, matching the issue example
  • Pass box configuration through project generation and document the YAML API

Closes #28

Testing

  • PYTHONPATH=src pytest tests/test_config.py tests/test_renderers.py tests/test_generator.py tests/test_rotation.py tests/test_auto_sizing.py -v
  • PYTHONPATH=src pytest tests/ --ignore=tests/test_html_preview.py --ignore=tests/test_watcher.py -v
  • black --check src/koubou/config.py src/koubou/generator.py src/koubou/renderers/text.py tests/test_config.py tests/test_generator.py tests/test_renderers.py
  • flake8 src/koubou/config.py src/koubou/renderers/text.py tests/test_renderers.py

E2E validation

  • Generated a CLI screenshot comparing the original issue image against Koubou output
  • Verified centered line-fragment boxing with alignment=center

Notes

  • Full test suite cannot complete in this sandbox: tests/test_html_preview.py cannot bind localhost (PermissionError), and tests/test_watcher.py hits a native watchdog/FSEvents bus error.

@bitomule
Copy link
Copy Markdown
Owner Author

bitomule commented May 9, 2026

E2E validation performed locally with the branch code:

PYTHONPATH=src /opt/homebrew/opt/python@3.13/bin/python3.13 -m koubou.cli generate /private/tmp/koubou-text-box-e2e/config.yaml --output json

Generated PNG:
/private/tmp/koubou-text-box-e2e/output/iPhone_16_Pro_-_Black_Titanium_-_Portrait/text_box_e2e.png

Verified visually and with PIL pixel inspection:

  • output size is 400x800
  • paragraph boxing rendered red rounded boxes per wrapped line
  • character boxing rendered blue boxes per visible character
  • whitespace between character boxes is present with padding: 0

Pixel inspection result:

  • text_region_red_pixels=16996, red_bbox=(32, 2, 207, 138)
  • text_region_blue_pixels=2107, blue_bbox=(40, 165, 105, 215)
  • white_gap_between_character_boxes_at_y190 count=8

@bitomule
Copy link
Copy Markdown
Owner Author

bitomule commented May 9, 2026

Follow-up after visual E2E review: tightened text box bounds to use actual font bounding boxes instead of full line height, so the text sits visually centered in paragraph and character boxes.

New E2E render generated with rounded character boxes:
/private/tmp/koubou-text-box-e2e/output/iPhone_16_Pro_-_Black_Titanium_-_Portrait/text_box_e2e.png

Validated again:

  • PYTHONPATH=src pytest tests/test_config.py tests/test_renderers.py tests/test_generator.py tests/test_rotation.py tests/test_auto_sizing.py -v -> 181 passed
  • PYTHONPATH=src pytest tests/ --ignore=tests/test_html_preview.py --ignore=tests/test_watcher.py -v -> 415 passed, 7 skipped
  • black --check src/koubou/renderers/text.py tests/test_renderers.py
  • flake8 src/koubou/renderers/text.py tests/test_renderers.py

@bitomule
Copy link
Copy Markdown
Owner Author

bitomule commented May 9, 2026

Adjusted after comparing against the original issue image. The earlier implementation treated paragraph as one box per wrapped line; the example image indicates paragraph should be one box around the whole text block. Updated behavior:

  • level: paragraph -> one box around the full wrapped text block
  • level: character -> boxes around visible characters, preserving unboxed spaces

E2E comparison artifact generated locally:
/private/tmp/koubou-text-box-e2e/issue-vs-generated-text-boxing.png

Latest validation:

  • PYTHONPATH=src pytest tests/test_config.py tests/test_renderers.py tests/test_generator.py tests/test_rotation.py tests/test_auto_sizing.py -v -> 182 passed
  • PYTHONPATH=src pytest tests/ --ignore=tests/test_html_preview.py --ignore=tests/test_watcher.py -v -> 416 passed, 7 skipped
  • black --check src/koubou/config.py src/koubou/generator.py src/koubou/renderers/text.py tests/test_config.py tests/test_generator.py tests/test_renderers.py
  • flake8 src/koubou/renderers/text.py tests/test_renderers.py

@bitomule
Copy link
Copy Markdown
Owner Author

bitomule commented May 9, 2026

Final semantic adjustment after comparing with the issue image: character should not mean one rectangle per individual letter. It now means boxes around wrapped line fragments, matching the AB / C examples. paragraph remains one box around the whole wrapped block.

Updated modes:

  • level: character, type: rounded -> rounded boxes per line fragment
  • level: character, type: straight -> straight boxes per line fragment
  • level: paragraph, type: rounded -> one rounded box around the block
  • level: paragraph, type: straight -> one straight box around the block

E2E comparison artifact:
/private/tmp/koubou-text-box-e2e/issue-vs-generated-text-boxing-v2.png

Validation:

  • PYTHONPATH=src pytest tests/ --ignore=tests/test_html_preview.py --ignore=tests/test_watcher.py -v -> 416 passed, 7 skipped
  • black --check ... -> passed
  • flake8 ... -> passed

@bitomule
Copy link
Copy Markdown
Owner Author

bitomule commented May 9, 2026

Added an explicit regression test for centered line-fragment boxing. The E2E comparison config now uses alignment: center, matching the original issue image where the shorter C line is centered under AB.

Centered E2E comparison artifact:
/private/tmp/koubou-text-box-e2e/issue-vs-generated-text-boxing-v3-centered.png

Additional validation:

  • PYTHONPATH=src pytest tests/test_renderers.py::TestTextRenderer -v -> 16 passed
  • black --check tests/test_renderers.py -> passed

@bitomule bitomule merged commit ca6ec6b into main May 10, 2026
7 checks passed
@bitomule bitomule deleted the feature/text-boxing branch May 10, 2026 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feature: text boxing

1 participant