Skip to content

6.1.3 - Teletext row padding

Choose a tag to compare

@superuser404notfound superuser404notfound released this 30 Jul 09:03

A rendering fix on the DVB teletext path, plus a build-level pin change that affects how released tags resolve. Anyone showing live teletext captions wants this one.

Fixed

  • Teletext rows no longer arrive with their column padding still on them. A two-row caption reached the host as row one<pad> / <pad>row two, so a renderer that centres each line put the second row visibly off centre and drew the cue's background box wider than its text. Reported by tresby, who had solved it row-wise in a proxy implementation and supplied the failing sequence (#233).

    The padding is the grid. On a page libzvbi does not classify as a subtitle page, gen_sub_ass writes every row at full column width (decode_string(page, row, &buf, 0, page->columns, ...), one \h per grid cell) and appends " \N" after it. Two whitespace passes existed and neither reached the inside of a line break: edgeTrimmed trims the leading and trailing edge of the whole run sequence, so the first row's leading pad and the last row's trailing pad only, and collapseInteriorBlankLines folds what sits between two newlines, dropping nothing against a single retained one and never looking at the characters before one at all.

    trimGridRows now takes the padding off both ends of every row. Like the fold it works on the flattened character sequence and re-splits along the original run boundaries, because a row's pad carries the spacing attribute that changes colour and therefore lands in a whitespace-only run of its own, which a per-run walk steps right over.

    The pass is gated, and the blank-line fold moved behind the same gate. Both only correct a raw grid dump, which is exactly the page that arrives without an \an: gen_sub_ass emits {\anN} on the first row of a flagged page that holds any character, and a flagged page holding none produces no cue at all, so an arriving alignment and a curated body are equivalent. On a curated page both of the things these passes remove are decisions rather than noise. The empty_lines / 2 fillers are its vertical fine-positioning inside the block, and the residual padding is the relative indentation that carries the horizontal alignment it picked (leading = min_leading for left, trailing = min_trailing for right, both for its non-centrable centre case). A curated body is now passed through whole, including through that fold, which had been discarding those fillers since #107.

    Not taken, though the trim does make it measurable: deriving the horizontal anchor the way can_align_left / _right / _center do. Where that analysis leaves more than one of the three viable it resolves the tie from last_ass_alignment, the answer given to the previous cue. A stateless parser has to fall back to centre there, so an unambiguous left-aligned cue followed by an ambiguous one would jump, which is the same blink the vertical derivation already refuses.

Changed

  • FFmpegBuild and LibDovi are pinned to the minor rather than floating from a lower bound, so a released tag's dependency set is a property of the tag instead of the registry at resolve time. Both classes of drift were live this week: LibDovi 1.1.0 raised its declared tvOS floor in a minor, which SwiftPM floats onto and then fails on instead of backing off to a version that fits, so every 5.x tag stopped resolving; and FFmpegBuild 2.4.0 replaced 2.3.0 under a fixed 5.28.0 checkout, harmless in that instance but not by design. Forward-looking only, already published tags keep whatever they declared.

Upgrading

.package(url: "https://github.com/superuser404notfound/AetherEngine", from: "6.1.3")

No API change and no source change for consumers. Resolution is unchanged too: the pin change lands on FFmpegBuild 2.4.0 and LibDovi 2.0.0, the same versions a from: bound resolved to.