Skip to content

Open linearized files through the layer in layer mode - #111

Merged
bobsingor merged 1 commit into
embedpdf/mainfrom
embedpdf/fix/layer-mode-linearized
Nov 4, 2026
Merged

bobsingor merged 1 commit into
embedpdf/mainfrom
embedpdf/fix/layer-mode-linearized

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

What changed in the harness

EmbedderTest::OpenDocumentHelper() opened any file that FPDFAvail_IsLinearized() accepts with FPDFAvail_GetDocument(), and only the other branch went through embedpdf_test::LoadCustomDocumentForTest(). In layer mode (EPDF_EMBEDDER_LAYER_MODE=1) a test on a linearized fixture therefore ran on a plain document: no copy-up door, no reads-dont-write check, and EPDFLayer_GetPromotedObjectCount() read 0, so it never showed up as a writer.

Now, in layer mode, a linearized file opens through the layer like any other file. Only a test that asks for linearized loading (LinearizeOption::kMustLinearize, i.e. OpenDocumentLinearized()) keeps the FPDFAvail path. Plain mode is unchanged.

Why that rule: the tests that need progressive loading either ask for it (LoadMainCrossRefTable, LinearizedDocument, Hang1055, PasswordAfterGenerateSave) or build their own FPDF_AVAIL (CreateAvail() + SetDocumentFromAvail(): the data-avail tests and CPDFCreatorEmbedderTest.SaveLinearizedInfo). No test opens a linearized file with the default option and then relies on avail() or the hint tables; GetPageCount() and GetFirstPageNum() already run on non-linearized files.

FPDFAvail_IsLinearized() also checks that /L equals the file length, so 12 of the 14 fixtures that start with /Linearized take this path. annotation_stamp_with_ap.pdf and bug_781804.pdf were saved incrementally after linearizing and already opened through the layer.

Tests that moved onto a layer

20 tests on 10 fixtures (the other two linearized fixtures are only opened with kMustLinearize). All pass in layer mode.

New writers, added to testing/embedpdf_layer_mode_writers.txt:

Test Objects
EPDFAnnotEmbedderTest.RefitWrapsAStampAcrobatTurnedUpright 5
EPDFPageLabelsEmbedderTest.NoSectionsRemovesTheLabels 1
EPDFPageLabelsEmbedderTest.RefusesSectionsThatBreakTheRules 1
RichTextParityTest.BorderWidthsFixtureMatchesAcrobat 26
RichTextParityTest.CalloutWidthsFixtureMatchesAcrobat 12

RefusesSectionsThatBreakTheRules writes once, at its end; its refusals return before any mutable access. The RichText parity counts are 2 per annotation (annotation + appearance stream), as in the other parity tests.

Now checked as readers (0 objects): CPDFParserEmbedderTest.Bug757705; seven CPDFSecurityHandlerEmbedderTest tests on encrypted.pdf (BadPassword, NoPassword, UserPassword, OwnerPassword, SetRuntimeOwnerPermissions, CheckPasswordPermissionsDoesNotUnlockOwner, CheckPasswordPermissionsIgnoresCurrentOwnerUnlockState); EPDFAnnotEmbedderTest.AppearanceTransformOfAStampAcrobatTurned; EPDFAnnotEmbedderTest.UnrotatedRenderUndoesATurnDrawnInTheStream; EPDFMeasureEmbedderTest.ReadsAllAcrobatImperialMeasurements and ReadsAllAcrobatMetricMeasurements; EPDFPageLabelsEmbedderTest.ReadsTheSectionsOfAFile; FPDFDocEmbedderTest.GetPageLabels; FPDFSaveEmbedderTest.SaveLinearizedDoc.

CPDFSecurityHandlerEmbedderTest.PasswordAfterGenerateSave writes but asks for linearized loading, so it stays plain; it now says so in a comment.

Layer bugs

None found. One test changed: FPDFSaveEmbedderTest.SaveLinearizedDoc failed only in layer mode, and the plain run was the wrong one. The test saved before the simulated download had fetched the metadata stream, so the save left object 26 out (a free entry) while the catalog still said /Metadata 26 0 R. Its byte expectations (0000000026 65535 f, 7912 bytes) described that dangling save. The test now calls SetWholeFileAvailable() first, as SaveLinearizedInfo does, and checks that object 26 is written. Plain and layer mode now write the same 10982 bytes.

Tests (macOS arm64, against embedpdf/main 538900d)

  • run_layer_mode.py over the whole embedder suite (1780 tests): writers 500 on main, 505 here; the per-test object counts differ only in the five tests above. Pass/fail/crash counts are the same as main (1555/40/185, all matched by embedpdf_layer_mode_expectations.txt).
  • Embedder suite, plain: 1763 passed, 12 failed, 4 skipped, on both main and this branch: the same 12 Mac-baseline failures (progressive render, render goldens, CaptionAppearanceGolden). The independent save checker passed (49 PDFs).
  • Unit suite: 1320/1320 pass. pdfium_unittests has none of the changed files as inputs.
  • Pixel suite: 51 failures + 2 surprises, the known Mac baseline. pdfium_test has none of the changed files as inputs, so it is the same binary as main's.

Note for #110

With this change, text_rich_comment_acrobat.pdf (#110's fixture) opens through the layer. Measured on a scratch merge of both: EPDFAnnotEmbedderTest.AcrobatCommentWrittenBackReadsTheSame writes 1 object, AcrobatNoteCommentReadsAsRichText reads clean. Whichever of the two merges second needs EPDFAnnotEmbedderTest.AcrobatCommentWrittenBackReadsTheSame 1 in the writers list.

EmbedderTest::OpenDocumentHelper() took the FPDFAvail path for any
linearized file, and only the other path went through
LoadCustomDocumentForTest(), so in layer mode a test on a linearized
fixture ran on a plain document: no copy-up door, no reads-dont-write
check, and a write never showed up in its layer count. A linearized file
now opens through the layer too; only a test that asks for linearized
loading (LinearizeOption::kMustLinearize) keeps the FPDFAvail path.
Plain mode is unchanged.

Twenty tests on twelve fixtures move onto a layer. Five of them write
and join the writers list. FPDFSaveEmbedderTest.SaveLinearizedDoc saved
before the simulated download had fetched the metadata stream, so its
expected bytes were a save that left object 26 out while the catalog
still referred to it; it now makes the whole file available first, and
plain and layer mode write the same bytes.
@bobsingor
bobsingor merged commit 27c5057 into embedpdf/main Nov 4, 2026
1 check passed
@bobsingor
bobsingor deleted the embedpdf/fix/layer-mode-linearized branch November 4, 2026 09:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant