Ask pdfium the four questions that were open, and act on the two it answered against us - #17
Merged
Conversation
…lds on 3 more sheets
pdfium reads an absent `layout` on the outermost subform differently from
pdf.js, and the difference shows as a sheet count rather than as a coordinate.
pdf.js reads an absent or unrecognised `layout` as "position" wherever it
appears (getStringOption, utils.js:70-76), and this package followed it.
pdfium's GetLayout (cxfa_contentlayoutprocessor.cpp:365-379) returns the
attribute where it parses to one of the seven values, and where it does NOT
and the node's parent is the <form> root it returns Tb. A positioned container
is never flowed, so a <break> inside one is never reached — pdfium recurses
into one with bUseBreakControl false (line 1163) and the break stage begins by
testing it (line 1751) — which is why the whole of the difference is which
sheet things land on.
FOUR of the corpus's 560 root subforms write no `layout`. Three of them are
forms this package put on ONE sheet where pdfium and pdf.js BOTH use two:
us-opm__sf39 1 -> 2 sheets, and its 6 unplaced fields are now placed
us-opm__sf39a 1 -> 2 sheets
us-opm__sf813 1 -> 2 sheets
The fourth, us-opm__sf181, has one child and no break, and does not move.
Nothing else in the corpus moves: the whole-corpus box dump differs on those
three forms and on no other.
Against pdfium, per form, boxes on the same sheet:
us-opm__sf39 96/104 -> 110/110 (and 6 unplaced -> 0)
us-opm__sf39a 24/50 -> 50/50
us-opm__sf813 sheet split 151/16, which is pdfium's 151/16 exactly
The half of bRootForceTb this does NOT do is named in [placer.forcedTb]:
pdfium also gives such a root's children their WRITTEN x and y instead of the
packing cursor. Every child of all four roots writes no x and no y, so nothing
in 560 templates separates that from stacking them.
The tests that used an absent `layout` as shorthand for a positioned root now
write `layout="position"`, which is what they meant and what pdfium reads.
Gate: 100% of statements, go vet, gofmt -l empty against Go 1.27.1 via
GOTOOLCHAIN, -race, nine cross-compile targets, CGO_ENABLED=0, GOWORK=off.
The corpus suite is green, and TestPaginationAgainstPdfjs goes from six
disagreements to two.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…h pdfium on 3 731 more leaves
The second thing the pdfium oracle settled, and the one that had been open
since v0.12.0: on fr-cerfa__cerfa_12818 pdfium put four buttons 3.6 pt right of
where this package put them, and the line responsible had not been found.
It is not a constant in pdfium and not an accumulation. It is the container's
own written inset. CXFA_ContentLayoutItem::GetAbsoluteRect
(xfa/fxfa/layout/cxfa_contentlayoutitem.cpp:82-90) adds every ancestor's
margin/@leftInset and @topInset on the way down, with NO test of the layout,
and cxfa_ffwidget.cpp:228 makes that the rectangle pdfium draws and hit-tests
with. The template says the rest: the anonymous <subform> between the cell
`Bouton` and its four buttons writes
<margin leftInset="1.27mm" topInset="1.27mm"
rightInset="1.27mm" bottomInset="1.27mm"/>
and 1.27mm IS 3.6pt. 0.05 inch is the same number by coincidence.
[placer.stack] has always begun a stacked child at f.x+in.left, f.y+in.top.
The positioned arm of [placer.children] did not, and that is the whole change.
An inset nobody can read refuses the children rather than being taken as
nought, which is the refusal stack has always made.
pdf.js casts no vote: it cannot lay this form out at all, it hands <margin> to
CSS as `margin` (html_utils.js:171-174) and never resolves it into a
coordinate, and the accumulating judge sums `left` and cannot see a CSS margin.
## Before and after, against pdfium, over all 559 dumps
before after
leaves under a table row 19454/19522 19522/19522 100.00%
leaves under neither, the 160022/167632 163753/167632 97.69%
control 95.46%
forms agreeing on x for
EVERY control leaf 461/559 473/559
Every one of the 68 row disagreements is gone, the 64 on ca-cra__rc1-fill-11-25e
that the last release could not read included: x on that form was not
comparable at all, and this is why. y improves with it — 93.45% to 94.13% for
the control, 76.53% to 76.72% under a row — though y stays informative rather
than a verdict, because pdfium measures text and this package does not.
9 794 boxes move, on 26 of 560 forms. No sheet count and no unplaced count
changes anywhere in the corpus.
## And nothing regresses against pdf.js
TestPlacementAgainstPdfjs 176/176 exact, 0 disagreements (unchanged)
TestFlowHeightsAgainstPdfjs 7794/7794, 0 disagreements (unchanged)
TestPaginationAgainstPdfjs 151199/151199 on the same sheet (unchanged)
TestIntraLinePlacementProperties the same 2 known violations (unchanged)
Gate: 100% of statements, go vet, gofmt -l empty against Go 1.27.1 via
GOTOOLCHAIN, -race, nine cross-compile targets, CGO_ENABLED=0, GOWORK=off.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Two changes, each with its own before/after, both settled by driving pdfium
over the corpus. They are independent and could be split; they are together
because one diagnosis produced both.
1 — Flow the one root subform that writes no layout (adab7ef)
pdf.js reads an absent or unrecognised
layoutaspositionwherever itappears (getStringOption,
utils.js:70-76), and this package followed it.pdfium's
GetLayout(cxfa_contentlayoutprocessor.cpp:365-379) returns theattribute where it parses to one of the seven values, and where it does not
and the node's parent is the
<form>root it returnsTb. A positionedcontainer is never flowed, so a
<break>inside one is never reached — pdfiumrecurses into one with
bUseBreakControlfalse (line 1163) and the break stagebegins by testing it (line 1751). That is why the difference is a sheet count
and never a coordinate.
Four of the corpus's 560 root subforms write no
layout; three of them areforms this package put on one sheet where pdfium and pdf.js both use two.
us-opm__sf39us-opm__sf39aus-opm__sf813us-opm__sf181, the fourth, has one child and no break and does not move.The whole-corpus box dump differs on those three forms and on no other.
TestPaginationAgainstPdfjsgoes from six disagreements to two.The half of
bRootForceTbthis does not do is named inplacer.forcedTb:pdfium also gives such a root's children their written x and y instead of the
packing cursor. Every child of all four roots writes no x and no y, so nothing
in 560 templates separates that from stacking them.
Tests that used an absent
layoutas shorthand for a positioned root now writelayout="position", which is what they meant.2 — Begin a positioned child inside its container's insets (6488963)
The 3.6 pt on
fr-cerfa__cerfa_12818that v0.12.0 left open. It is not aconstant in pdfium and not an accumulation: it is the container's own written
inset.
CXFA_ContentLayoutItem::GetAbsoluteRect(
xfa/fxfa/layout/cxfa_contentlayoutitem.cpp:82-90) adds every ancestor'smargin/@leftInsetand@topInseton the way down, with no test of thelayout, and
cxfa_ffwidget.cpp:228makes that the rectangle pdfium draws with.The anonymous
<subform>between the cellBoutonand its four buttons writesleftInset="1.27mm" topInset="1.27mm", and 1.27 mm is 3.6 pt. 0.05 inch isthe same number by coincidence.
placer.stackhas always begun a stacked child atf.x+in.left, f.y+in.top.The positioned arm of
placer.childrendid not.All 68 row disagreements are gone, the 64 on
ca-cra__rc1-fill-11-25ethat thelast release wrote off as "x on that form is not comparable at all" included.
9 794 boxes move on 26 of 560 forms; no sheet count and no unplaced count
changes anywhere.
Nothing regresses against pdf.js: placement 176/176 exact, heights 7794/7794,
pagination 151199/151199 on the same sheet, the same two known line violations.
What is NOT here
ca-cra__t183-fill-25e, all blocked byone
<subform anchorType="bottomLeft">that writes nowand noh.pdfium places them and its size rule is arithmetic on written numbers
(
DoLayoutPositionedContainer, 1194-1205), verified against the dump. It isa new capability — auto-sizing a positioned container — not a fix, and it is
one node in 560 forms.
hAligninside a line. Decided for pdfium and nothing moves: pdfiumdiscards
hAlignwhen the wrapping container writes no width(
if (bContainerWidthAutoSize) uHAlign = 0;, 2499-2503), both of thecorpus's two instances are such containers, and pdfium's own numbers show the
centred child packed left in document order.
The full reading, including the four items it settles and the one it does not,
is on #7.
Gate on both commits: 100% of statements,
go vet,gofmt -lempty against Go1.27.1 via
GOTOOLCHAIN,-race, nine cross-compile targets,CGO_ENABLED=0,GOWORK=off.🤖 Generated with Claude Code