fix(pdf): make the object serialization writable - #843
Merged
Conversation
`to_stream` emitted PDF syntax already, but only ever fed error messages, so
four gaps went unnoticed: a literal string escaped nothing (the standing
`TODO`), a name escaped nothing, a dictionary key was written raw, and reals
went through `{:.4g}` — four significant digits, and an exponent form 7.3.3
has no syntax for. `612.345` came back out as `612.3` and `0.00001` as `1e-05`.
Reals now go through `util::number::to_string_significant`, which is already
the no-exponent, no-locale spelling the css and svg writers use. A round-trip
test through `ObjectParser` pins that what we write, we read back.
`Transform2D::inverse` comes along for the same reason: undoing the page
transform is how a viewport coordinate gets back to user space.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018e3PEzyU2oAFSzsEoWsSmz
andiwand
force-pushed
the
feat/pdf-object-serialization
branch
from
September 6, 2026 14:42
c951ac3 to
c57b7d4
Compare
This was referenced Sep 6, 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
Stacked on #842 (the design doc) — this is its Phase 0, the serialization correctness the writer needs before anything can be appended to a PDF.
pdf_object.cpp'sto_streamalready emitted PDF syntax rather than a debug dump, but nothing outside error messages ever consumed it, so four gaps went unnoticed:StandardString(a(b)c)— the standing// TODO escape(a\(b\)c)Name/Odd Key/Odd#20KeyNameReal{:.4g}→612.3,1e-05612.345,0.00001The real formatting is the one that would have silently corrupted geometry: four significant digits turns
612.345into612.3, andgreaches for an exponent form that 7.3.3 has no syntax for at all. It now goes throughutil::number::to_string_significant, already the no-exponent, no-locale spelling the CSS and SVG writers use.An unescaped name is not cosmetic either — a space in a dictionary key splits the dictionary in two on the way back in.
Also here
Transform2D::inverse—std::optional,nullopton a singular linear part. Undoing the page transform is how a viewport coordinate gets back to user space, which is the whole coordinate path for placing an annotation.[1 2],<</Type /Catalog >>) so writer output is diffable in assertions.Tests
ObjectParser— whatto_streamwrites,read_objectreads back unchanged. That is the assertion that makes the serialization usable for writing rather than only for dumping.inverseagainst a compound page-like transform, identity, and two singular matrices.292 PDF tests plus the
html/odr/Filesuites pass; clean under-Werrorand clang-tidy.No consumer-visible change —
to_streamonly ever reached exception text — so no changelog entry.