Repository navigation
Measure the text runs of page.content() on the fallback faces (#658) - #664
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 tasks
…-faces # Conflicts: # crates/pyropdf-engine/src/extract/model.rs
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.
Closes #658
The text runs of
page.content()now describe a CJK font that a document does not embed as the fallback face that draws it, as frozen pylopdf does after a first rendering. Before this,page.pixmap()drew glyphs thatpage.content()gave no box for.How the fields split
Two interpretations of the page supply a run's fields. The second runs through the faces, and only when
Fallback::watchingreports during the first that a face would draw a font of the page.weight(400) here andNonewithout faces. This is not in the issue's table, but the acceptance needs it. The name stays the PDF's in both.scale_non_uniform(font.glyph_stretch(..))). Under/W [0 65535 500], its 0.5 would halve the advances andmatrix.a.A run with no ink at all falls back to the box of its origins and advances, also from the read without faces.
Three things follow from running a second interpretation:
clipkeeps items by their box, so it applies after the faces have moved the boxes. A clip that meets the ink above the baseline now keeps the run.content_element_count, andmax_elementsstill bounds one interpretation. Its per-glyph list is charged tomemory_sizeand released when the read ends.Acceptance
tests/assets/text/nonembedded-cjk.pdf, the text runs ofpage.content()match frozen pylopdf with its CJK extras, read after a first rendering.target/parity/pylopdf-env, rounded to 6 decimals, and this holds for pyropdf read fresh and after a rendering.FROZEN_RUNSintests/test_fallback_fonts.pypins the IDs, boxes, and weight, so CI holds this without the oracle.doc.fallback_fontschanges the runs that the next call returns, and a call with the same faces reuses the memoized result (test_editing_the_fallback_fonts_changes_the_text_runs_of_the_next_call).text_runs=Falsekeeps its memo key (test_content_without_text_runs_keeps_its_memo_key_when_the_fallback_fonts_change).doc.fallback_fonts = {}, every field also matches frozen pylopdf without faces (FROZEN_RUNS_WITHOUT_FACESpins the IDs, boxes, and weight).only_text_runs_of_a_font_that_is_not_embedded_read_a_faceproves no face is read for an embedded font, Helvetica, andtext_runs=False, by removing the face's file afterwards.The page in
/W [0 65535 500], where a face's stretch applies, also matches frozen pylopdf in every field.Checks
python tools/check.py --locked: all passed on this head (sync, pytest, ruff, ruff-format, ty, fmt, clippy, cargo-test).cargo check --manifest-path fuzz/Cargo.toml --bins --locked: passes.page_contentandpage_content_intotake the faces, so the fuzz target changed; it passes no faces, so the second interpretation is not fuzzed.For review
python/pyropdf/_document.py,docs/en/rendering.md, anddocs/ja/rendering.mdsaid only exact boxes use the faces, which this change makes untrue.docs/en/api/documents.mdandpages.mdare generated from the docstrings.record_text_item. This pull request leaves that computation as it is, so Keep the PDF's advances when hayro stretches a substitute glyph #656 still applies to the read without faces. A non-embedded Latin font's advances stay as they are onmainuntil then.evidence/phase1-paritystill does not comparepage.content(). The issue's paths leave that out, so here only this fixture is compared with the oracle.For 0.2.2's changelog
page.content()describes a CJK font that a document does not embed as the face ofdoc.fallback_fontsthat draws it: glyph IDs, glyph and run boxes, and the font's weight. Its glyphs used to have no box, and a run's box lay on its baseline. The result now depends ondoc.fallback_fonts, unlesstext_runs=False.Merge
#658 is not linked as a blocker of #636, so I have not treated it as covered by the merge authorization there. This waits for the owner.
🤖 Generated with Claude Code