initial commit

This commit is contained in:
2026-09-21 13:41:40 +09:00
commit 855c7328df
411 changed files with 85352 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
# 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.