feat(svm): draw the text run a metafile names, with the font it names - #785
Merged
Conversation
andiwand
added a commit
to opendocument-app/OpenDocument.test.output
that referenced
this pull request
Aug 30, 2026
andiwand
force-pushed
the
feat/svm-text
branch
from
August 30, 2026 08:17
82ea10f to
0380eea
Compare
This was referenced Aug 30, 2026
andiwand
force-pushed
the
fix/svm-graphics-state
branch
from
August 30, 2026 09:09
05c2061 to
7a68fa8
Compare
andiwand
force-pushed
the
fix/svm-graphics-state
branch
from
August 30, 2026 09:16
7a68fa8 to
488de91
Compare
Two thirds of every action in the corpus is text, and we drew almost none of what the file says about it. **A text action names a run of its string** - `(index, length)` - and the string it carries is the whole paragraph. We drew the string. A document whose text comes in runs, which is every bidirectional one and every formula, had the full sentence stamped at each run's position, overprinting itself into a smear. The run is taken in utf-16 units, before the conversion to utf-8, because that is what the offsets count. **The font attributes of #95**: italic (3068 of the 7962 fonts in the corpus, all of them formula variables we drew upright), bold, underline, strikeout, and the orientation, which rotates the run about its own start. **`TEXTALIGN`**, which says whether the draw point is the top, the baseline or the bottom of the run - vcl has no horizontal text alignment. Its default is `ALIGN_TOP` and svg's is the alphabetic baseline, so it has to be written out. `svgwriter.cxx` shifts the point by the font's ascent, having the metrics; `dominant-baseline` leaves that to the browser, which has them too. **The measurements the file took**: a `TEXTARRAY`'s dx array places every character where it was measured, and a `STRETCHTEXT`'s width becomes `textLength`, so a formula still fits its box when the viewer's font is not the author's. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CmCr22NW6wPQKiQidk96bq
The 21 private and 6 public files this branch changes, regenerated.
The eight test doc comments each restated their own test name, and the facts they carried were already stated where the code is - `MetaTextAlign`, the `text_align` member, `get_x_list_string`, the `textLength` and `rotate` sites. The one that was not, that half the text in the corpus is italic and all of it a formula variable, moves to `PLAN.md`, where it justifies the stage order. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XQpLmJpJ87qbKoG8B7kbLY
andiwand
force-pushed
the
feat/svm-text
branch
from
August 30, 2026 09:33
0380eea to
0f787dd
Compare
A version-1 text action's `offset` and `length` count utf-16 code units, but `read_string_with_encoding` has already decoded a `UCS2` string to utf-8 by the time they are read. Slicing that by byte drew the wrong run and could cut a character in half, and invalid utf-8 costs the whole image exactly as an unescaped `&` did. `select_run_with_encoding` slices where the offsets point. Also: an empty dx array no longer reaches `size() - 1` in `get_x_list_string`, and `read_utf16_string` is the new `read_u16string` converted, rather than a second copy of it. The changelog entries under `Unreleased` are cut to a claim and its consequence; several ran to four lines of it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XQpLmJpJ87qbKoG8B7kbLY
This was referenced Aug 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
Stage 3 of #772 and the whole of #95, stacked on #784 → #779. Review those
first; this branch's base is
fix/svm-graphics-state.Two thirds of every action in the corpus is text, and we drew almost none of
what the file says about it.
A text action names a run
MetaTextAction(point, string, index, length)— and the string it carries isthe whole paragraph. We drew the string, at every run's position.
odt/style+charset+svm-various-1.odtis the proof: its one metafile makes 29text actions out of one Hebrew paragraph, so the reference rendering is that
paragraph printed 29 times on top of itself — an unreadable smear. With the run
applied it reads as the sentence it is, and the page's visible text loses 505
characters, every one of them a duplicate.
The run is taken in utf-16 units, before the conversion to utf-8, because that
is what the offsets count.
The font (#95)
italic, bold, underline, strikeout, and the orientation, which rotates the run
about its own start (tenths of a degree counter-clockwise, where svg turns
clockwise). Of the 7962 fonts in the corpus, 3068 are italic — every one of
them a formula variable we were drawing upright.
TEXTALIGNIt says whether the draw point is the top, the baseline or the bottom of the
run. #772 reads it as centre/right alignment for chart labels; it is not —
vcl has no horizontal text alignment, a run always starts at its point. It
still has to be written out, because its default is
ALIGN_TOPand svg's isthe alphabetic baseline.
svgwriter.cxxshifts the point by the font's ascent,having the metrics;
dominant-baselineleaves that to the browser, which hasthem too.
The measurements the file already took
A
TEXTARRAYcarries a dx array — where each character ended, as the author'sfont measured it — which becomes an
xlist, one position per character. ASTRETCHTEXTcarries the advance its run has to fill, which becomestextLength+lengthAdjust. Both are what keep a formula together when theviewer's font is not the author's, and there are 20335 stretch texts in the
corpus.
An
xlist is only written when it has exactly one entry per character;anything else is logged and dropped rather than guessed at.
Verification
8 new tests (23 in the svm suite), each built from inline bytes.
Rendered: the four svm fixtures and every changed page in headless Chrome. The
formulas of
odt/Vektoranalysis Zusammenfassung.odt(1032 metafiles, 20kstretch texts) come out italic and correctly spaced;
odt/ruski.odt,odt/arbeitsplanKW21.odtand the charts are unchanged in content and tighterin spacing. Visible text is identical to the reference everywhere except the
Hebrew document above, where it loses the duplicates.
Needs the same reference-output regeneration as #784 — 23 files, all of
them documents carrying an svm.