69 lines
5.2 KiB
Markdown
69 lines
5.2 KiB
Markdown
# Tagged-PDF boundary corpus
|
|
|
|
The 26 tagged PDFs and 4 context-only PDFs are self-authored. They contain
|
|
Standard-14 Helvetica text and vector paths, with no third-party document content.
|
|
Regenerate the deterministic files and hashes with:
|
|
|
|
```sh
|
|
python3 tests/fixtures/pdf/generate_headings.py
|
|
```
|
|
|
|
`manifest.json` records SHA-256, byte size, authored expectations and PDF-point
|
|
regions `[left, bottom, right, top]`. Regions follow the source placements,
|
|
font sizes and transforms; they are not copied from renderer output. None of the
|
|
tagged files has bookmarks, so an outline cannot conceal missing tag extraction.
|
|
|
|
`test_pdf::taggedBoundaryCorpus` checks every tagged file's hash, page count,
|
|
title, level, structure order, destination precision, fallback reason and bbox.
|
|
Exact targets must map inside the page and round-trip within 0.5 pt at scale 2
|
|
for user rotations 0, 90, 180 and 270 degrees. The PDFium drawing engine still
|
|
provides character boxes; a shared worker-only qpdf context now supplies the
|
|
source-qualified logical structure.
|
|
|
|
| Files | Authored condition and expected behavior |
|
|
| --- | --- |
|
|
| `transformed-form.pdf` | Page wrapper MCID plus Form-owned MCR. Exact heading in `[70,102,240,130]`. |
|
|
| `rotated-tags.pdf` | Rotate 90 and offset CropBox. H3 is drawn first but H1 precedes it in structure order; exact targets follow structure order. |
|
|
| `cross-page-structure.pdf` | One H1 has interleaved nested Span and direct MCR children on two pages. Page-local fragments preserve K order without mixing reused MCID 0. |
|
|
| `vector-heading.pdf` | H4 vector with ActualText but no glyph bbox. Title retained with page precision and a coordinate reason. |
|
|
| `form-only-structure.pdf` | Only the Form has StructParents. One exact H2, `Form only heading`, in `[50,125,190,147]`. This is now a positive extraction case. |
|
|
| `form-vector-mcid-collision.pdf` | Page vector heading and unrelated Form text both use MCID 0. Keep the heading title at page precision; never borrow Form paragraph bounds. |
|
|
| `named-property-rolemap.pdf` | Form BDC references a named property and a custom RoleMap name. Extract actual text without a supplied title. |
|
|
| `nested-form-matrix.pdf` | Nested Forms with a nonidentity Form Matrix and independent caller CTMs. Exact target uses PDFium page-space character boxes once. |
|
|
| `different-form-same-mcid.pdf` | Two uniquely positioned Forms reuse MCID 0, with reverse structure order. Keep separate exact headings in that order. |
|
|
| `ambiguous-form-matrix.pdf` | Different Forms share matrix and MCID signature. Use titles and explicit page precision instead of relying on enumeration order. |
|
|
| `repeated-form.pdf` | One source Form is invoked twice. Preserve the heading at page precision with a repeated-Form reason. |
|
|
| `unused-form-resource.pdf` | Uninvoked Form remains in Resources. It must not create an extra heading. |
|
|
| `inline-image-before-form.pdf` | Inline image precedes a used Form. Skip image pixels and retain the exact heading. |
|
|
| `cyclic-form.pdf`, `cyclic-rolemap.pdf`, `cyclic-parent.pdf`, `cyclic-children.pdf`, `cyclic-number-tree.pdf` | Explicit structure limitation, no fabricated destination. |
|
|
| `broken-mcr-page.pdf`, `broken-mcr-stream.pdf`, `annotation-owned-mcr.pdf`, `broken-graphics-stack.pdf`, `conflicting-parent-tree-owner.pdf` | Invalid or unsupported ownership/graphics relation. Explicit limitation, no borrowed exact text or position. |
|
|
| `stream-quota-at-limit.pdf`, `stream-quota-over-limit.pdf` | Compressed operator data expands to exactly 16 MiB or one byte more. The first succeeds; the second is limited, truncated and incomplete. |
|
|
| `bounded-heading-response.pdf` | 70 vector headings have long Japanese ActualText. Return a nonempty validated prefix within 512 KiB CBOR and mark the response incomplete. |
|
|
|
|
Context-only cases exercise the shared parser separately from PDFium:
|
|
|
|
- `context-deep-tree.pdf`: a depth failure must remain sticky on retries; the
|
|
valid later sibling must never become page zero.
|
|
- `context-warnings-32.pdf` and `context-warnings-33.pdf`: one diagnostic occurs
|
|
during initial parse and the remainder during lazy object reads. The 32-line
|
|
boundary succeeds; crossing it remains limited after a new operation begins.
|
|
- `context-warning-bytes.pdf`: one initial diagnostic exceeds 64 KiB. Opening
|
|
stops without emitting its contents.
|
|
|
|
The existing `../missing-first-page.pdf` separately checks that qpdf does not
|
|
repair `[null, page]` into a shortened page list before validation. This caught
|
|
the qpdf 12.4.1 `setMaxWarnings` startup side effect; diagnostics now use a bounded
|
|
private sink instead.
|
|
|
|
The production worker suite uses the real sandbox, IPC and font broker for
|
|
Form-only/nested exact destinations, ambiguous/repeated page fallbacks, quota,
|
|
partial response and cancellation. A temporary encrypted version checks wrong
|
|
password rejection, the same borrowed QFile and unchanged source bytes. Worker
|
|
cases compare original SHA-256 before and after. See the [recorded Linux
|
|
results](../../../results/pdf-structure/README.md).
|
|
|
|
Annotation-owned OBJR/StmOwn structures remain an explicit limitation. Repeated
|
|
or ambiguous Form instances deliberately retain page precision. These synthetic
|
|
cases do not establish native Windows behavior or general conformance for every
|
|
producer's tagged PDFs.
|