Skip to content

PictexSubtitleRenderer: get_word_size crops padding, so words render with no gaps #22

Description

@stkzlv

Summary

PictexSubtitleRenderer renders multi-word captions with no gaps between words. The same template rendered with CssSubtitleRenderer is correct. It fails silently: the render completes without error, so the only signal is looking at a frame.

Observed with the bundled word-focus template at 1080x1920. Script line "like my phone went from" renders as Likemyphonewentfrom. Also reproduces on explosive.

Cause

The two renderers disagree on what get_word_size should include, and the preset templates space words with CSS padding on the word element rather than a word-spacing property:

  • word-focus/styles.css: padding: 4px 4px
  • explosive/styles.css: padding: 5px 8px

CssSubtitleRenderer.get_word_size measures each letter plus a NON_CONTENT_WIDTH sentinel, and the comment there states why:

# All letters are measured without padding/borders/etc, the "NON_CONTENT_WIDTH" is used to measure the paddings/borders/etc
# So, each word must have the "NON_CONTENT_WIDTH" to include its padding/border/etc
letters = list(word.text) + ["NON_CONTENT_WIDTH"]

PictexSubtitleRenderer.get_word_size instead renders the word and returns the cropped image's size:

image = canvas.render(root_element, crop_mode=CropMode.CONTENT_BOX, scale_factor=self._scale_factor)
return (image.width, image.height)

CropMode.CONTENT_BOX crops to the content box, which by definition excludes padding. So pictex reports a glyph-only width where the layout expects width-plus-padding, and each word is placed hard against the previous one.

At 1080x1920 the scale factor is BASE_SCALE_FACTOR 2.0 * (1920 / 1280) = 3.0, so word-focus loses about 12px per side, roughly 24px between adjacent words. It reads as a total collapse rather than tight kerning.

Note render_word (line 71) uses the same crop mode. That one is arguably correct, since the drawn glyph image should not carry padding; the measurement at line 102 is where the mismatch bites.

Reproduction

renderer: pictex
template: word-focus
video: 1080x1920

Any caption with two or more words in a line. Rendered here via a downstream project, but the code path is PictexSubtitleRenderer.get_word_size directly.

Suggested direction

Make the pictex measurement include non-content width so the two renderers return comparable values. CropMode exposes SMART and NONE alongside CONTENT_BOX, so one option is measuring with a mode that retains padding while continuing to draw with CONTENT_BOX. Deriving the padding from the styled tree and adding it to the returned width would also work.

Happy to test a patch against the reproduction above.

Environment

  • pycaps 0.2.1 (also present at 68a6843b, current default-branch HEAD)
  • pictex 2.3.0, html2pic 0.2.2
  • Python 3.12, Linux

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions