Resolve anchored drawing offsets against their relativeFrom frame - #18
Merged
Conversation
A wp:anchor offset is meaningless on its own. The same number lands somewhere different depending on whether it is measured from the page, the margin, the text column or the paragraph. We read relativeFrom into CT_Anchor and then ignored it, treating every offset as an absolute page coordinate, so anchored drawings ended up in the corner of the sheet. In the file attached to #3 the anchor asks for column plus 4.75pt horizontally and paragraph plus 0.05pt vertically. As page coordinates that is the very top left of the page, off the printable area. Resolved properly it is x 76.75, y 107.4, which is beside its paragraph. Resolving a paragraph-relative offset needs the laid-out position of the paragraph, which is only known during pagination. So the anchors now travel with the ParagraphBlock and the paginator places them once the page and the cursor are settled. That also removes the old pass, which had to guess and put everything on page one regardless of where the anchoring paragraph actually was. behindDoc drawings are collected separately and emitted before the rest of the page so they sit underneath the text rather than over it. A paragraph split across a page boundary places its anchors with the first part only, so they are not emitted twice. Closes #10.
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 #10.
The bug
A
wp:anchoroffset means nothing on its own. The same number lands somewhere different depending on whether it is measured from the page, the margin, the text column or the paragraph. We parsedrelativeFromintoCT_Anchorand then never used it, so every offset was treated as an absolute page coordinate.The file attached to #3 asks for:
That is 4.75pt from the column and 0.05pt from the paragraph. Read as page coordinates it is the very top left corner of the sheet, off the printable area, which is why the image looked like it had vanished. Resolved properly it is x 76.75, y 107.4, beside its paragraph.
Why this moved code around
Resolving a paragraph-relative offset needs the laid-out position of the paragraph, and that is only known during pagination. The old
resolve_anchor_imagesran afterwards with no paragraph-to-page mapping, which is why it also had to put every anchored drawing on page one regardless of where its paragraph ended up. Its own comment admitted this.So anchors now travel with the
ParagraphBlockand the paginator places them once the page and cursor are settled. The old pass is gone.Two details that fall out of doing it this way:
behindDocdrawings are collected separately and emitted before the rest of the page, so they sit under the text rather than over it.Coverage
All eight horizontal frames and all eight vertical frames are handled.
marginandcolumncoincide because multiple text columns are not laid out yet, andlinefalls back to the paragraph top because we do not track individual line boxes at that point. Both of those are noted in the code rather than left to be discovered.Two tests: one pinning every frame against a known geometry, and one asserting the property the old code could not express at all, that the same offset resolves differently once the paragraph moves down the page.
What this does not fix
The image in #3 still does not appear, for an unrelated reason. It is an 8-bit colormap PNG, and
decode_imagereturnsNonefor colour type 3, so neither the PDF nor the PNG backend can draw it. Filed separately as #17. With that fixed the drawing will appear in the right place.So the visible result for that specific document is unchanged. The fix is verified by the unit tests and by the resolved coordinates, not by the render.
Checks
cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warningsand the full suite all pass. 335 tests, up from 333.Note for PR #2
This rewrites
resolve_anchor_images, which PR #2 also touches. That PR adds alignment-based positioning (pos_h_align,pos_v_align), which is the natural next step on top of this and should slot intoresolve_anchor_handresolve_anchor_v. Its wrap, drop cap and footnote work is untouched by this change.