@awacloud/pdf 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +609 -0
- package/LICENSE +661 -0
- package/NOTICE +77 -0
- package/README.md +363 -2
- package/dist/build/index.js +21 -0
- package/dist/build/pdf-full-rw.js +10972 -0
- package/dist/build/pdf-full-rw.meta.json +105 -0
- package/dist/build/pdf-full-rw.min.js +53 -0
- package/dist/build/pdf-full.js +6078 -0
- package/dist/build/pdf-full.meta.json +90 -0
- package/dist/build/pdf-full.min.js +32 -0
- package/dist/build/pdf-large-rw.js +10367 -0
- package/dist/build/pdf-large-rw.meta.json +99 -0
- package/dist/build/pdf-large-rw.min.js +53 -0
- package/dist/build/pdf-large.js +5473 -0
- package/dist/build/pdf-large.meta.json +84 -0
- package/dist/build/pdf-large.min.js +32 -0
- package/dist/build/pdf-legacy-rw.js +12402 -0
- package/dist/build/pdf-legacy-rw.meta.json +110 -0
- package/dist/build/pdf-legacy-rw.min.js +53 -0
- package/dist/build/pdf-legacy.js +7508 -0
- package/dist/build/pdf-legacy.meta.json +95 -0
- package/dist/build/pdf-legacy.min.js +32 -0
- package/dist/build/pdf-rw.js +7578 -0
- package/dist/build/pdf-rw.meta.json +77 -0
- package/dist/build/pdf-rw.min.js +53 -0
- package/dist/build/pdf.js +2684 -0
- package/dist/build/pdf.meta.json +62 -0
- package/dist/build/pdf.min.js +32 -0
- package/dist/standalone/pdf-full-rw.js +16798 -0
- package/dist/standalone/pdf-full-rw.meta.json +78 -0
- package/dist/standalone/pdf-full-rw.min.js +56 -0
- package/dist/standalone/pdf-full.js +11904 -0
- package/dist/standalone/pdf-full.meta.json +63 -0
- package/dist/standalone/pdf-full.min.js +35 -0
- package/dist/standalone/pdf-large-rw.js +16193 -0
- package/dist/standalone/pdf-large-rw.meta.json +72 -0
- package/dist/standalone/pdf-large-rw.min.js +56 -0
- package/dist/standalone/pdf-large.js +11299 -0
- package/dist/standalone/pdf-large.meta.json +57 -0
- package/dist/standalone/pdf-large.min.js +35 -0
- package/dist/standalone/pdf-legacy-rw.js +18228 -0
- package/dist/standalone/pdf-legacy-rw.meta.json +83 -0
- package/dist/standalone/pdf-legacy-rw.min.js +56 -0
- package/dist/standalone/pdf-legacy.js +13334 -0
- package/dist/standalone/pdf-legacy.meta.json +68 -0
- package/dist/standalone/pdf-legacy.min.js +35 -0
- package/dist/standalone/pdf-rw.js +13404 -0
- package/dist/standalone/pdf-rw.meta.json +50 -0
- package/dist/standalone/pdf-rw.min.js +56 -0
- package/dist/standalone/pdf.js +8510 -0
- package/dist/standalone/pdf.meta.json +35 -0
- package/dist/standalone/pdf.min.js +35 -0
- package/docs/README.md +53 -0
- package/docs/api/README.md +38 -0
- package/docs/api/_shared/README.md +91 -0
- package/docs/api/action/README.md +29 -0
- package/docs/api/action/action.md +81 -0
- package/docs/api/action/goTo.md +66 -0
- package/docs/api/action/launch.md +58 -0
- package/docs/api/action/named.md +55 -0
- package/docs/api/action/uri.md +54 -0
- package/docs/api/annot/README.md +53 -0
- package/docs/api/annot/annot.md +114 -0
- package/docs/api/annot/fileAttach.md +53 -0
- package/docs/api/annot/freeText.md +68 -0
- package/docs/api/annot/ink.md +69 -0
- package/docs/api/annot/link.md +74 -0
- package/docs/api/annot/markup.md +83 -0
- package/docs/api/annot/popup.md +52 -0
- package/docs/api/annot/projection.md +56 -0
- package/docs/api/annot/redact.md +67 -0
- package/docs/api/annot/square.md +87 -0
- package/docs/api/annot/stamp.md +54 -0
- package/docs/api/annot/text.md +69 -0
- package/docs/api/annot/widget.md +69 -0
- package/docs/api/associatedFiles/README.md +9 -0
- package/docs/api/associatedFiles/associatedFiles.md +78 -0
- package/docs/api/bundles/README.md +68 -0
- package/docs/api/bundles/dist-matrix.md +165 -0
- package/docs/api/bundles/pdf-full.md +148 -0
- package/docs/api/bundles/pdf-large.md +144 -0
- package/docs/api/bundles/pdf-legacy.md +169 -0
- package/docs/api/content/README.md +29 -0
- package/docs/api/content/color.md +99 -0
- package/docs/api/content/graphics.md +114 -0
- package/docs/api/content/images.md +124 -0
- package/docs/api/content/ops.md +100 -0
- package/docs/api/content/stream.md +107 -0
- package/docs/api/content/text.md +98 -0
- package/docs/api/crypto/README.md +29 -0
- package/docs/api/crypto/aesGcm.md +72 -0
- package/docs/api/crypto/permissions.md +79 -0
- package/docs/api/crypto/security.md +98 -0
- package/docs/api/crypto/standardV4.md +104 -0
- package/docs/api/crypto/standardV5.md +84 -0
- package/docs/api/crypto/standardV6.md +93 -0
- package/docs/api/destination/README.md +9 -0
- package/docs/api/destination/destination.md +79 -0
- package/docs/api/document/README.md +29 -0
- package/docs/api/document/builder.md +281 -0
- package/docs/api/document/catalog.md +98 -0
- package/docs/api/document/document.md +187 -0
- package/docs/api/document/encryptedWriter.md +149 -0
- package/docs/api/document/incrementalWriter.md +148 -0
- package/docs/api/document/page.md +99 -0
- package/docs/api/document/pages.md +82 -0
- package/docs/api/document/resources.md +102 -0
- package/docs/api/document/writer.md +157 -0
- package/docs/api/document/xrefStreamWriter.md +122 -0
- package/docs/api/embedded/README.md +13 -0
- package/docs/api/embedded/collection.md +80 -0
- package/docs/api/embedded/embeddedFile.md +86 -0
- package/docs/api/embedded/fileSpec.md +87 -0
- package/docs/api/errors.md +110 -0
- package/docs/api/extra/3d-richmedia.md +76 -0
- package/docs/api/extra/README.md +99 -0
- package/docs/api/extra/annot-extended.md +71 -0
- package/docs/api/extra/associated-files.md +70 -0
- package/docs/api/extra/ccitt-fax-decoder.md +74 -0
- package/docs/api/extra/color-spaces-extended.md +72 -0
- package/docs/api/extra/content-ops-extended.md +82 -0
- package/docs/api/extra/document-parts.md +69 -0
- package/docs/api/extra/embedded-files-portfolio.md +87 -0
- package/docs/api/extra/font-cid-typed.md +77 -0
- package/docs/api/extra/font-color-tagging.md +76 -0
- package/docs/api/extra/form-actions-extended.md +75 -0
- package/docs/api/extra/info-dict-deprecated.md +72 -0
- package/docs/api/extra/jbig2-read.md +80 -0
- package/docs/api/extra/legacy-deprecated-annots.md +89 -0
- package/docs/api/extra/legacy-deprecated-filters.md +78 -0
- package/docs/api/extra/legacy-rc4-read.md +74 -0
- package/docs/api/extra/legacy-xfa-read.md +65 -0
- package/docs/api/extra/linearization-write.md +71 -0
- package/docs/api/extra/misc.md +93 -0
- package/docs/api/extra/optional-content-extended.md +83 -0
- package/docs/api/extra/pdf-a-output-intent.md +65 -0
- package/docs/api/extra/pdf-sandbox.md +76 -0
- package/docs/api/extra/pdf-ua-tagged.md +63 -0
- package/docs/api/extra/pdf-x-prepress.md +65 -0
- package/docs/api/extra/redaction-iso32005.md +65 -0
- package/docs/api/extra/shading-typed.md +73 -0
- package/docs/api/extra/sig-aes-gcm.md +69 -0
- package/docs/api/extra/sig-pades.md +103 -0
- package/docs/api/extra/tagged-pdf-typed.md +78 -0
- package/docs/api/extra/transparency-typed.md +74 -0
- package/docs/api/extra/well-tagged-pdf.md +61 -0
- package/docs/api/extra/xmp-extended.md +65 -0
- package/docs/api/font/README.md +25 -0
- package/docs/api/font/embed.md +157 -0
- package/docs/api/font/encoding.md +95 -0
- package/docs/api/font/font.md +97 -0
- package/docs/api/font/type3.md +89 -0
- package/docs/api/form/README.md +35 -0
- package/docs/api/form/acroform.md +88 -0
- package/docs/api/form/appearance.md +87 -0
- package/docs/api/form/button.md +97 -0
- package/docs/api/form/choice.md +96 -0
- package/docs/api/form/fieldTree.md +93 -0
- package/docs/api/form/signature.md +90 -0
- package/docs/api/form/text.md +88 -0
- package/docs/api/linearization/README.md +11 -0
- package/docs/api/linearization/linearization.md +81 -0
- package/docs/api/main.md +116 -0
- package/docs/api/metadata/README.md +10 -0
- package/docs/api/metadata/info.md +70 -0
- package/docs/api/metadata/xmp.md +62 -0
- package/docs/api/ocg/README.md +23 -0
- package/docs/api/ocg/config.md +95 -0
- package/docs/api/ocg/ocg.md +77 -0
- package/docs/api/outline/README.md +11 -0
- package/docs/api/outline/outline.md +107 -0
- package/docs/api/pdf.md +152 -0
- package/docs/api/prepress/README.md +10 -0
- package/docs/api/prepress/outputIntent.md +79 -0
- package/docs/api/prepress/pageBoundary.md +75 -0
- package/docs/api/sig/README.md +32 -0
- package/docs/api/sig/byteRange.md +120 -0
- package/docs/api/sig/certChain.md +84 -0
- package/docs/api/sig/dss.md +111 -0
- package/docs/api/sig/oids.md +76 -0
- package/docs/api/sig/sha1.md +72 -0
- package/docs/api/sig/sign.md +317 -0
- package/docs/api/sig/signature.md +178 -0
- package/docs/api/sig/timestamp.md +84 -0
- package/docs/api/syntax/README.md +29 -0
- package/docs/api/syntax/crossRefStream.md +115 -0
- package/docs/api/syntax/filters/README.md +50 -0
- package/docs/api/syntax/filters/ascii85.md +76 -0
- package/docs/api/syntax/filters/asciiHex.md +73 -0
- package/docs/api/syntax/filters/dispatch.md +125 -0
- package/docs/api/syntax/filters/flate.md +134 -0
- package/docs/api/syntax/filters/runLength.md +78 -0
- package/docs/api/syntax/objStream.md +88 -0
- package/docs/api/syntax/parser-obj.md +97 -0
- package/docs/api/syntax/parser.md +151 -0
- package/docs/api/syntax/serializer.md +109 -0
- package/docs/api/syntax/tokenizer.md +104 -0
- package/docs/api/syntax/trailer.md +85 -0
- package/docs/api/syntax/xref.md +139 -0
- package/docs/api/tagged/README.md +25 -0
- package/docs/api/tagged/classMap.md +67 -0
- package/docs/api/tagged/markedContent.md +62 -0
- package/docs/api/tagged/parentTree.md +67 -0
- package/docs/api/tagged/roleMap.md +67 -0
- package/docs/api/tagged/structElement.md +76 -0
- package/docs/api/tagged/structTree.md +75 -0
- package/docs/guide/coverage.md +113 -0
- package/docs/guide/crypto.md +121 -0
- package/docs/guide/extending.md +76 -0
- package/docs/guide/getting-started.md +75 -0
- package/docs/guide/legacy-1.7.md +42 -0
- package/docs/guide/pades-integration.md +579 -0
- package/docs/guide/read-pdf.md +89 -0
- package/package.json +97 -4
- package/src/_shared/index.js +179 -0
- package/src/action/action.js +119 -0
- package/src/action/goTo.js +89 -0
- package/src/action/launch.js +61 -0
- package/src/action/named.js +54 -0
- package/src/action/uri.js +51 -0
- package/src/annot/annot.js +212 -0
- package/src/annot/fileAttach.js +55 -0
- package/src/annot/freeText.js +82 -0
- package/src/annot/ink.js +77 -0
- package/src/annot/link.js +77 -0
- package/src/annot/markup.js +91 -0
- package/src/annot/popup.js +53 -0
- package/src/annot/projection.js +52 -0
- package/src/annot/redact.js +87 -0
- package/src/annot/square.js +132 -0
- package/src/annot/stamp.js +48 -0
- package/src/annot/text.js +54 -0
- package/src/annot/widget.js +61 -0
- package/src/associatedFiles/associatedFiles.js +86 -0
- package/src/bundles/pdf-full.js +91 -0
- package/src/bundles/pdf-large.js +81 -0
- package/src/bundles/pdf-legacy.js +107 -0
- package/src/content/color.js +114 -0
- package/src/content/graphics.js +192 -0
- package/src/content/images.js +160 -0
- package/src/content/ops.js +137 -0
- package/src/content/stream.js +154 -0
- package/src/content/text.js +125 -0
- package/src/crypto/aesGcm.js +123 -0
- package/src/crypto/permissions.js +112 -0
- package/src/crypto/security.js +327 -0
- package/src/crypto/standardV4.js +443 -0
- package/src/crypto/standardV5.js +306 -0
- package/src/crypto/standardV6.js +334 -0
- package/src/destination/destination.js +183 -0
- package/src/document/builder.js +618 -0
- package/src/document/catalog.js +100 -0
- package/src/document/document.js +472 -0
- package/src/document/encryptedWriter.js +554 -0
- package/src/document/incrementalWriter.js +514 -0
- package/src/document/page.js +131 -0
- package/src/document/pages.js +103 -0
- package/src/document/resources.js +146 -0
- package/src/document/writer.js +211 -0
- package/src/document/xrefStreamWriter.js +353 -0
- package/src/embedded/collection.js +102 -0
- package/src/embedded/embeddedFile.js +99 -0
- package/src/embedded/fileSpec.js +137 -0
- package/src/errors.js +78 -0
- package/src/extra/3d-richmedia.js +171 -0
- package/src/extra/annot-extended.js +200 -0
- package/src/extra/associated-files.js +131 -0
- package/src/extra/ccitt-fax-decoder.js +776 -0
- package/src/extra/color-spaces-extended.js +196 -0
- package/src/extra/content-ops-extended.js +153 -0
- package/src/extra/document-parts.js +149 -0
- package/src/extra/embedded-files-portfolio.js +234 -0
- package/src/extra/font-cid-typed.js +185 -0
- package/src/extra/font-color-tagging.js +144 -0
- package/src/extra/form-actions-extended.js +196 -0
- package/src/extra/info-dict-deprecated.js +137 -0
- package/src/extra/jbig2-read.js +169 -0
- package/src/extra/legacy-deprecated-annots.js +198 -0
- package/src/extra/legacy-deprecated-filters.js +167 -0
- package/src/extra/legacy-rc4-read.js +235 -0
- package/src/extra/legacy-xfa-read.js +104 -0
- package/src/extra/linearization-write.js +97 -0
- package/src/extra/misc.js +217 -0
- package/src/extra/optional-content-extended.js +142 -0
- package/src/extra/pdf-a-output-intent.js +112 -0
- package/src/extra/pdf-sandbox.js +88 -0
- package/src/extra/pdf-ua-tagged.js +116 -0
- package/src/extra/pdf-x-prepress.js +114 -0
- package/src/extra/redaction-iso32005.js +136 -0
- package/src/extra/shading-typed.js +222 -0
- package/src/extra/sig-aes-gcm.js +135 -0
- package/src/extra/sig-pades.js +242 -0
- package/src/extra/tagged-pdf-typed.js +203 -0
- package/src/extra/transparency-typed.js +135 -0
- package/src/extra/well-tagged-pdf.js +138 -0
- package/src/extra/xmp-extended.js +190 -0
- package/src/font/embed.js +480 -0
- package/src/font/encoding.js +92 -0
- package/src/font/font.js +101 -0
- package/src/font/type3.js +75 -0
- package/src/form/acroform.js +94 -0
- package/src/form/appearance.js +90 -0
- package/src/form/button.js +105 -0
- package/src/form/choice.js +152 -0
- package/src/form/fieldTree.js +120 -0
- package/src/form/signature.js +100 -0
- package/src/form/text.js +101 -0
- package/src/linearization/linearization.js +107 -0
- package/src/main.js +411 -0
- package/src/metadata/info.js +87 -0
- package/src/metadata/xmp.js +62 -0
- package/src/ocg/config.js +156 -0
- package/src/ocg/ocg.js +124 -0
- package/src/outline/outline.js +157 -0
- package/src/pdf.js +133 -0
- package/src/prepress/outputIntent.js +118 -0
- package/src/prepress/pageBoundary.js +108 -0
- package/src/sig/byteRange.js +306 -0
- package/src/sig/certChain.js +247 -0
- package/src/sig/dss.js +317 -0
- package/src/sig/oids.js +157 -0
- package/src/sig/sha1.js +142 -0
- package/src/sig/sign.js +1899 -0
- package/src/sig/signature.js +1441 -0
- package/src/sig/timestamp.js +236 -0
- package/src/syntax/crossRefStream.js +133 -0
- package/src/syntax/filters/ascii85.js +122 -0
- package/src/syntax/filters/asciiHex.js +83 -0
- package/src/syntax/filters/dispatch.js +176 -0
- package/src/syntax/filters/flate.js +316 -0
- package/src/syntax/filters/runLength.js +96 -0
- package/src/syntax/objStream.js +99 -0
- package/src/syntax/parser-obj.js +52 -0
- package/src/syntax/parser.js +321 -0
- package/src/syntax/serializer.js +221 -0
- package/src/syntax/tokenizer.js +290 -0
- package/src/syntax/trailer.js +76 -0
- package/src/syntax/xref.js +341 -0
- package/src/tagged/classMap.js +81 -0
- package/src/tagged/markedContent.js +123 -0
- package/src/tagged/parentTree.js +126 -0
- package/src/tagged/roleMap.js +107 -0
- package/src/tagged/structElement.js +138 -0
- package/src/tagged/structTree.js +94 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfFontEmbed
|
|
3
|
+
category: pdf/font
|
|
4
|
+
dependencies: [pdfErrors, embedSubsetForPdf, embedFontDescriptor, embedCidSystemInfo, embedToUnicodeBuilder]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfFontEmbed
|
|
11
|
+
|
|
12
|
+
> Adapter between `@awacloud/fonts/embed-pdf` and PDF dicts — ISO 32000-2 §9.6 / §9.7 / §9.10.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfFontEmbed` | **Source** `packages/front/office/pdf/src/font/embed.js` | **Deps** `pdfErrors`, `embedSubsetForPdf`, `embedFontDescriptor`, `embedCidSystemInfo`, `embedToUnicodeBuilder` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
The only file in `@awacloud/pdf` that knows about `@awacloud/fonts/embed-pdf`. It takes an already-parsed font (the output of `fonts.read(bytes)`) plus a set of code points, and produces the PDF dicts needed to embed a **subset** of that font — either simple (`/TrueType` + `/WinAnsiEncoding`) or composite (`/Type0` + `/Identity-H` + `/CIDFontType2`). The subsetting itself is delegated to `subsetForPdf`; this module exists so the writer's call sites don't re-derive the wiring.
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const emb = runtime.resolve('pdfFontEmbed');
|
|
22
|
+
// Returns: { embedSimple, embedCid }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|--------|-----------|---------|
|
|
29
|
+
| `embedSimple` | `(parsedFont, codePoints, opts?) => SimpleEmbed` | `/TrueType` + `/WinAnsiEncoding`. Every code point must be CP1252-representable. |
|
|
30
|
+
| `embedCid` | `(parsedFont, codePoints, opts?) => CidEmbed` | `/Type0` + `/Identity-H` with a `/CIDFontType2` descendant. Any Unicode code point. |
|
|
31
|
+
|
|
32
|
+
`parsedFont` must be a real parsed `Font` — `unicodeMap`, `glyphIndexForCodePoint`, `advanceWidth` and a numeric `unitsPerEm` are all read. `codePoints` is any iterable of integers; it is de-duplicated and sorted, and the sorted array is echoed back as `codePoints`. `opts` is forwarded to `subsetForPdf` (`embedCid` adds `{ cid: true }`).
|
|
33
|
+
|
|
34
|
+
The factory validates at construction that its four injected `@awacloud/fonts/embed-pdf` helpers (`subsetForPdf`, `buildFontDescriptor`, `buildCidSystemInfo`, `embedBuildToUnicode`) are functions, throwing `ContractError` otherwise.
|
|
35
|
+
|
|
36
|
+
## What the adapter consumes
|
|
37
|
+
|
|
38
|
+
`subsetForPdf(font, codePoints, opts?)` returns exactly eight keys — `subsetBytes`, `gidMap`, `glyphMap`, `encoding`, `widths`, `toUnicodeCmap`, `postScriptName`, `fontDescriptor`. The adapter reads all of them except `encoding` (always `null`: under `Identity-H` the encoding is the cmap). A unit-tier **contract-shape guard** (`src/font/embed.test.js`) resolves the REAL `embedSubsetForPdf` through a `ModuleRuntime` and asserts that key set, so the stub can never drift from the package again.
|
|
39
|
+
|
|
40
|
+
Two conversions happen here and nowhere else:
|
|
41
|
+
|
|
42
|
+
- **Widths.** `subset.widths` is indexed by NEW gid and expressed in **font units**. Everything this module emits (`/Widths`, `/W`, `widthOf`) is `round(w * 1000 / unitsPerEm)`.
|
|
43
|
+
- **`/ToUnicode` source.** A `/ToUnicode` CMap is keyed by *character code*. For `embedCid` the code IS the CID (= the subset's new gid), which is exactly how `subset.toUnicodeCmap` is keyed — it is used verbatim. For `embedSimple` the codes are WinAnsi **bytes**, so the gid-keyed CMap would be wrong; the adapter builds the byte-keyed map and passes it to `embedBuildToUnicode` with `{ codeBytes: 1 }`, so the CMap declares a one-byte codespace (`<00> <FF>`) and 2-hex-digit codes; `embedCid` keeps the 2-byte default. Never both for one route.
|
|
44
|
+
|
|
45
|
+
## The consumer's contract — the descriptor carries no font program
|
|
46
|
+
|
|
47
|
+
`buildFontDescriptor` puts the raw subset bytes in `FontFile2` (TrueType) or `FontFile3` (CFF). The adapter **lifts them out**: the returned `descriptor` dict has no font-program key, and the bytes come back as `fontFile` with the key name in `fontFileKey`. The consumer must:
|
|
48
|
+
|
|
49
|
+
1. allocate the font program as a **stream indirect** whose dict carries `/Length1 = fontFile.length` (the serializer adds `/Length`), and set `descriptor.entries[fontFileKey]` to that ref;
|
|
50
|
+
2. allocate `toUnicodeStream` as a stream indirect too and set the font dict's `ToUnicode` to that ref — `pdfSerializer` refuses an inline stream (`pdf/serializer/inline-stream`).
|
|
51
|
+
|
|
52
|
+
The font dict itself may be written inline or as an indirect; the descriptor nests fine inside it.
|
|
53
|
+
|
|
54
|
+
Do this wiring in **new** dicts — spread the result's `entries` into a fresh
|
|
55
|
+
`obj.dict({ … })` and add the references there — rather than by assigning into
|
|
56
|
+
the result's own dicts. The embed result is then left untouched and can be
|
|
57
|
+
reused for another document (or another page tree) as is.
|
|
58
|
+
[`pdfBuilder`](../document/builder.md)'s `addFont({ name, embedded })` does
|
|
59
|
+
exactly this wiring for you: it copies the entries into new dicts, never
|
|
60
|
+
mutates the result, and allocates its indirects per document.
|
|
61
|
+
|
|
62
|
+
### Shape `SimpleEmbed`
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
{
|
|
66
|
+
subtype: 'TrueType',
|
|
67
|
+
fontDict: typed dict (Type/Subtype/BaseFont/Encoding/FirstChar/LastChar/Widths/FontDescriptor/ToUnicode),
|
|
68
|
+
descriptor: typed dict — no FontFile2/FontFile3 key,
|
|
69
|
+
toUnicodeStream: typed stream (byte-keyed CMap),
|
|
70
|
+
fontFile: Uint8Array — the subset font program,
|
|
71
|
+
fontFileKey: 'FontFile2' | 'FontFile3',
|
|
72
|
+
encode(text): Uint8Array — one WinAnsi byte per code point,
|
|
73
|
+
widthOf(cp): number — 1000/em, 0 when the cp is not embedded,
|
|
74
|
+
codePoints: number[] — de-duplicated, ascending
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`BaseFont` is the subsetter's `postScriptName` (already `ABCDEF+Family`). `FirstChar`/`LastChar` are the min/max WinAnsi bytes of the embedded set, and `Widths` covers `[FirstChar..LastChar]` with `0` in the unused slots.
|
|
79
|
+
|
|
80
|
+
### Shape `CidEmbed`
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
{
|
|
84
|
+
type0Dict: typed dict (Type/Subtype:Type0/BaseFont/Encoding:Identity-H/DescendantFonts/ToUnicode),
|
|
85
|
+
cidFontDict: typed dict (Subtype:CIDFontType2/CIDSystemInfo/FontDescriptor/DW/W/CIDToGIDMap:Identity),
|
|
86
|
+
descriptor: typed dict — no FontFile2/FontFile3 key,
|
|
87
|
+
toUnicodeStream: typed stream (CID-keyed CMap),
|
|
88
|
+
fontFile: Uint8Array,
|
|
89
|
+
fontFileKey: 'FontFile2' | 'FontFile3',
|
|
90
|
+
encode(text): Uint8Array — 2 big-endian bytes (the CID) per code point;
|
|
91
|
+
an unknown cp becomes CID 0 (.notdef) and bumps `encode.missing`,
|
|
92
|
+
widthOf(cp): number — 1000/em, 0 when the cp is not embedded,
|
|
93
|
+
codePoints: number[]
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The subset is renumbered, so **CID === new gid** and `/CIDToGIDMap` is `/Identity`. `/DW` is `1000`; `/W` is the compact `[c [w …] …]` form over the subset's gids.
|
|
98
|
+
|
|
99
|
+
## Examples
|
|
100
|
+
|
|
101
|
+
### Simple embed (`/TrueType` + `/WinAnsiEncoding`)
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
const emb = runtime.resolve('pdfFontEmbed');
|
|
105
|
+
const { obj } = runtime.resolve('pdfParserObj');
|
|
106
|
+
|
|
107
|
+
const e = emb.embedSimple(parsedFont, [...'Hello'].map(c => c.codePointAt(0)));
|
|
108
|
+
|
|
109
|
+
// Clone, don't mutate: new dicts carry the two stream references,
|
|
110
|
+
// `e` itself stays reusable for another document.
|
|
111
|
+
const descriptor = obj.dict({ ...e.descriptor.entries, [e.fontFileKey]: obj.ref(6, 0) });
|
|
112
|
+
const fontDict = obj.dict({ ...e.fontDict.entries, FontDescriptor: descriptor, ToUnicode: obj.ref(7, 0) });
|
|
113
|
+
|
|
114
|
+
const indirects = [
|
|
115
|
+
/* … catalog, pages, page, contents … */
|
|
116
|
+
{ num: 5, gen: 0, value: fontDict },
|
|
117
|
+
{ num: 6, gen: 0, value: obj.stream(obj.dict({ Length1: obj.int(e.fontFile.length) }), e.fontFile) },
|
|
118
|
+
{ num: 7, gen: 0, value: obj.stream(obj.dict({}), e.toUnicodeStream.raw) }
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
// Content stream: the show-string is what `encode` produced.
|
|
122
|
+
e.encode('Hello'); // Uint8Array [0x48, 0x65, 0x6C, 0x6C, 0x6F]
|
|
123
|
+
e.widthOf(0x48); // advance width of 'H' in 1000/em, never font units
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### CID embed (composite `/Type0`)
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
const e = emb.embedCid(parsedFont, [...'Uni é fi'].map(c => c.codePointAt(0)));
|
|
130
|
+
|
|
131
|
+
const descriptor = obj.dict({ ...e.descriptor.entries, [e.fontFileKey]: obj.ref(6, 0) });
|
|
132
|
+
const cidFont = obj.dict({ ...e.cidFontDict.entries, FontDescriptor: descriptor });
|
|
133
|
+
const type0 = obj.dict({ ...e.type0Dict.entries,
|
|
134
|
+
DescendantFonts: obj.array([cidFont]),
|
|
135
|
+
ToUnicode: obj.ref(7, 0) });
|
|
136
|
+
// font program at 6 and e.toUnicodeStream at 7, as in the simple route
|
|
137
|
+
|
|
138
|
+
const codes = e.encode('Uni é fi'); // 2 bytes per code point, big-endian CIDs
|
|
139
|
+
e.encode.missing; // 0 — every cp was in the subset
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Errors
|
|
143
|
+
|
|
144
|
+
| Code | Class | When |
|
|
145
|
+
|------|--------|------|
|
|
146
|
+
| `pdf/embed/missing-fonts-embed` | `ContractError` | The injected `@awacloud/fonts/embed-pdf` helpers are absent or don't supply the 4 required functions (thrown at factory time). |
|
|
147
|
+
| `pdf/embed/bad-font` | `ContractError` | `parsedFont` is not a parsed `Font` (missing `unicodeMap` / `glyphIndexForCodePoint` / `advanceWidth` / numeric `unitsPerEm`). |
|
|
148
|
+
| `pdf/embed/bad-codepoints` | `ContractError` | `codePoints` is not iterable, is empty, or holds a non-integer / out-of-range value (`context.cp`). |
|
|
149
|
+
| `pdf/embed/not-winansi` | `ContractError` | `embedSimple` was given a code point outside CP1252 (`context.cp`) — use `embedCid`. Also thrown by `SimpleEmbed.encode` for a character outside the embedded set. |
|
|
150
|
+
|
|
151
|
+
## See also
|
|
152
|
+
|
|
153
|
+
- [`pdfFont`](./font.md) — read-side typing.
|
|
154
|
+
- [`pdfFontEncoding`](./encoding.md) — `/Encoding` resolution.
|
|
155
|
+
- [`pdfWriter`](../document/writer.md) — consumes the payload.
|
|
156
|
+
- [`parser-obj`](../syntax/parser-obj.md) — `obj.*` constructors.
|
|
157
|
+
- `tests/font-embed-real.integration.test.js` — both routes written and read back against a REAL parsed font.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfFontEncoding
|
|
3
|
+
category: pdf/font
|
|
4
|
+
dependencies: [pdfErrors]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfFontEncoding
|
|
11
|
+
|
|
12
|
+
> Resolution of a simple font's `/Encoding` entry — ISO 32000-2 §9.6.5.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfFontEncoding` | **Source** `packages/front/office/pdf/src/font/encoding.js` | **Deps** `pdfErrors` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Builds a 256-entry table of **glyph names** (or `null` for unmapped slots) from a PDF `/Encoding` entry. Three accepted shapes:
|
|
17
|
+
|
|
18
|
+
- **absent** → `StandardEncoding`.
|
|
19
|
+
- **name**: `/WinAnsiEncoding`, `/MacRomanEncoding`, `/MacExpertEncoding`, `/StandardEncoding`, `/SymbolEncoding`, `/ZapfDingbatsEncoding`.
|
|
20
|
+
- **dict**: `{ BaseEncoding?: name, Differences?: array }` — overlays slots on top of the base table.
|
|
21
|
+
|
|
22
|
+
The module is **pure**: it does not know the named tables themselves. The caller passes `lookupNamed` (typically `@awacloud/fonts/encodings#lookupEncoding`).
|
|
23
|
+
|
|
24
|
+
## Resolve
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
const enc = runtime.resolve('pdfFontEncoding');
|
|
28
|
+
// Returns: { resolveEncoding }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
|
|
33
|
+
| Method | Signature | Returns |
|
|
34
|
+
|--------|-----------|---------|
|
|
35
|
+
| `resolveEncoding` | `(entry, lookupNamed) => Array<string\|null>` | 256-entry table of glyph names. |
|
|
36
|
+
|
|
37
|
+
### `Differences` format (§9.6.5.4)
|
|
38
|
+
|
|
39
|
+
Array interleaving ints (starting slot) and names (consecutive glyphs):
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
[ 1 /a /b /c 65 /A /B ]
|
|
43
|
+
└─ slot 1=a, 2=b, 3=c
|
|
44
|
+
└─ slot 65=A, 66=B
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Examples
|
|
48
|
+
|
|
49
|
+
### Named encoding
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
const enc = runtime.resolve('pdfFontEncoding');
|
|
53
|
+
const table = enc.resolveEncoding(
|
|
54
|
+
{ type: 'name', value: 'WinAnsiEncoding' },
|
|
55
|
+
lookupNamed
|
|
56
|
+
);
|
|
57
|
+
table[0x41]; // 'A'
|
|
58
|
+
table[0x80]; // 'Euro' (WinAnsi)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Encoding with Differences
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
const entry = obj.dict({
|
|
65
|
+
BaseEncoding: obj.name('WinAnsiEncoding'),
|
|
66
|
+
Differences: obj.array([
|
|
67
|
+
obj.int(1), obj.name('exclamdown'), obj.name('cent')
|
|
68
|
+
])
|
|
69
|
+
});
|
|
70
|
+
const table = enc.resolveEncoding(entry, lookupNamed);
|
|
71
|
+
table[1]; // 'exclamdown'
|
|
72
|
+
table[2]; // 'cent'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Absent encoding → Standard
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
const table = enc.resolveEncoding(null, lookupNamed);
|
|
79
|
+
// → StandardEncoding
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Errors
|
|
83
|
+
|
|
84
|
+
| Code | Class | When |
|
|
85
|
+
|------|--------|------|
|
|
86
|
+
| `pdf/encoding/bad-base` | `ParseError` | `/BaseEncoding` is not a name. |
|
|
87
|
+
| `pdf/encoding/bad-shape` | `ParseError` | `/Encoding` is neither a name nor a dict. |
|
|
88
|
+
| `pdf/encoding/bad-differences` | `ParseError` | `/Differences` is not an array. |
|
|
89
|
+
| `pdf/encoding/bad-differences-entry` | `ParseError` | A `/Differences` entry is neither int nor name. |
|
|
90
|
+
|
|
91
|
+
## See also
|
|
92
|
+
|
|
93
|
+
- [`pdfFont`](./font.md) — carries the `encoding` field.
|
|
94
|
+
- [`pdfType3`](./type3.md) — accepts the same format.
|
|
95
|
+
- [`pdfText`](../content/text.md) — `extractText` consumes the mapping.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfFont
|
|
3
|
+
category: pdf/font
|
|
4
|
+
dependencies: [pdfErrors, pdfParser]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfFont
|
|
11
|
+
|
|
12
|
+
> Typing of a PDF Font dict — ISO 32000-2 §9.6 / §9.7.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfFont` | **Source** `packages/front/office/pdf/src/font/font.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
This module **does not parse font files** — all PFB/PFA, TrueType/OpenType, CFF, CIDFont byte reading is delegated to `@awacloud/fonts`. Here we only type the Font **dictionary** (Type, Subtype, BaseFont, Encoding, FirstChar, LastChar, Widths, FontDescriptor, ToUnicode, DescendantFonts) and classify the font among `Type0`, `Type1`, `MMType1`, `Type3`, `TrueType`, `CIDFontType0`, `CIDFontType2`. A Standard 14 fallback is available if the caller supplies `opts.standard14` (`isStandard14` / `lookupStandard14` lookup).
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const f = runtime.resolve('pdfFont');
|
|
22
|
+
// Returns: { typeFont, resolveDescendant }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|--------|-----------|---------|
|
|
29
|
+
| `typeFont` | `(dict, opts?: { standard14 }) => Font` | Typing. |
|
|
30
|
+
| `resolveDescendant` | `(type0Font, resolveRef) => Font \| null` | Reads the descendant CIDFont of a Type0. |
|
|
31
|
+
|
|
32
|
+
### Shape `Font`
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
{
|
|
36
|
+
subtype: 'Type0'|'Type1'|'MMType1'|'Type3'|'TrueType'|'CIDFontType0'|'CIDFontType2',
|
|
37
|
+
baseFont: string | null,
|
|
38
|
+
encoding: PdfObject | null, // name | dict
|
|
39
|
+
firstChar: int | null,
|
|
40
|
+
lastChar: int | null,
|
|
41
|
+
widths: number[] | null,
|
|
42
|
+
fontDescriptor: PdfObject | null,
|
|
43
|
+
toUnicode: PdfObject | null,
|
|
44
|
+
descendantFonts: PdfObject[] | null,
|
|
45
|
+
standard14: object | null, // set when the fallback triggers
|
|
46
|
+
raw: object
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The Standard 14 fallback triggers only when: `subtype ∈ {Type1, MMType1}`, **no** `/FontDescriptor`, and `baseFont` is recognized by `isStandard14`.
|
|
51
|
+
|
|
52
|
+
## Examples
|
|
53
|
+
|
|
54
|
+
### Simple typing
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
const f = runtime.resolve('pdfFont');
|
|
58
|
+
const font = f.typeFont(resources.Font.F1);
|
|
59
|
+
font.subtype; // 'Type1'
|
|
60
|
+
font.baseFont; // 'Helvetica'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Composite Type0 + descendant
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
const type0 = f.typeFont(resources.Font.F1);
|
|
67
|
+
if (type0.subtype === 'Type0') {
|
|
68
|
+
const cid = f.resolveDescendant(type0, doc._raw.resolve);
|
|
69
|
+
cid.subtype; // 'CIDFontType2'
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Standard 14 fallback
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
const font = f.typeFont(dict, {
|
|
77
|
+
standard14: runtime.resolve('fontsStandard14')
|
|
78
|
+
});
|
|
79
|
+
font.standard14; // { widths, bbox, italicAngle, ... } | null
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Errors
|
|
83
|
+
|
|
84
|
+
| Code | Class | When |
|
|
85
|
+
|------|--------|------|
|
|
86
|
+
| `pdf/font/not-dict` | `ParseError` | Argument is not a typed dict. |
|
|
87
|
+
| `pdf/font/bad-type` | `ParseError` | `/Type` present but ≠ `/Font`. |
|
|
88
|
+
| `pdf/font/missing-subtype` | `ParseError` | `/Subtype` absent or not a name. |
|
|
89
|
+
| `pdf/font/unknown-subtype` | `ParseError` | `/Subtype` outside the 7 known values. |
|
|
90
|
+
|
|
91
|
+
## See also
|
|
92
|
+
|
|
93
|
+
- [`pdfFontEncoding`](./encoding.md) — `/Encoding` resolution.
|
|
94
|
+
- [`pdfType3`](./type3.md) — Type 3 font (PDF-specific).
|
|
95
|
+
- [`pdfFontEmbed`](./embed.md) — write-side adapter.
|
|
96
|
+
- [`pdfText`](../content/text.md) — consumes `subtype` for `extractText`.
|
|
97
|
+
- [`pdfResources`](../document/resources.md) — supplies the dicts.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfType3
|
|
3
|
+
category: pdf/font
|
|
4
|
+
dependencies: [pdfErrors, pdfParser]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfType3
|
|
11
|
+
|
|
12
|
+
> Typing of a Type 3 font (glyphs defined by content streams) — ISO 32000-2 §9.6.4.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfType3` | **Source** `packages/front/office/pdf/src/font/type3.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Unlike Type1/TrueType/CIDFont (which delegate to `@awacloud/fonts`), Type 3 fonts are **PDF-specific**: each glyph is defined by a content stream in `/CharProcs`. That is why this module lives here rather than in `@awacloud/fonts`. The exposed record carries `bbox`, `matrix` (defaults to `[0.001, 0, 0, 0.001, 0, 0]`), `charProcs`, `encoding`, `firstChar`/`lastChar`/`widths`, `fontDescriptor` (optional in PDF 2.0), and `resources` (local to the glyphs).
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const t3 = runtime.resolve('pdfType3');
|
|
22
|
+
// Returns: { typeType3 }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|--------|-----------|---------|
|
|
29
|
+
| `typeType3` | `(dict) => Type3Font` | Typing. |
|
|
30
|
+
|
|
31
|
+
### Shape `Type3Font`
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
{
|
|
35
|
+
subtype: 'Type3',
|
|
36
|
+
bbox: [llx,lly,urx,ury] | null,
|
|
37
|
+
matrix: [0.001,0,0,0.001,0,0], // default
|
|
38
|
+
charProcs: { [glyphName]: PdfObject }, // stream | ref
|
|
39
|
+
encoding: PdfObject | null,
|
|
40
|
+
firstChar: int | null,
|
|
41
|
+
lastChar: int | null,
|
|
42
|
+
widths: number[] | null,
|
|
43
|
+
fontDescriptor: PdfObject | null,
|
|
44
|
+
resources: PdfObject | null,
|
|
45
|
+
raw: object
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
### Typing
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
const t3 = runtime.resolve('pdfType3');
|
|
55
|
+
const font = t3.typeType3(resources.Font.F1);
|
|
56
|
+
font.subtype; // 'Type3'
|
|
57
|
+
font.bbox; // [0, 0, 1000, 1000]
|
|
58
|
+
font.matrix; // [0.001, 0, 0, 0.001, 0, 0]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Rendering a glyph stream
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
const procRef = font.charProcs.a; // ref to a content stream
|
|
65
|
+
const proc = doc._raw.resolve(procRef);
|
|
66
|
+
const ops = runtime.resolve('pdfContentStream').parseContentStream(proc.raw);
|
|
67
|
+
// The first op is usually d0 or d1 (set glyph metrics)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Encoding via the dedicated module
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
const enc = runtime.resolve('pdfFontEncoding');
|
|
74
|
+
const table = enc.resolveEncoding(font.encoding, lookupNamed);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Errors
|
|
78
|
+
|
|
79
|
+
| Code | Class | When |
|
|
80
|
+
|------|--------|------|
|
|
81
|
+
| `pdf/type3/not-dict` | `ParseError` | Argument is not a typed dict. |
|
|
82
|
+
| `pdf/type3/wrong-subtype` | `ParseError` | `/Subtype` absent, not a name, or ≠ `/Type3`. |
|
|
83
|
+
|
|
84
|
+
## See also
|
|
85
|
+
|
|
86
|
+
- [`pdfFont`](./font.md) — generic typing (other subtypes).
|
|
87
|
+
- [`pdfFontEncoding`](./encoding.md) — `/Encoding` resolution.
|
|
88
|
+
- [`pdfContentStream`](../content/stream.md) — parses `CharProcs`.
|
|
89
|
+
- [`pdfContentOps`](../content/ops.md) — `d0` / `d1` Type3 ops.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Form — ISO 32000-2 §12.7 / §12.5.5
|
|
2
|
+
|
|
3
|
+
Interactive forms (AcroForm) layer: root dict typing, field-tree walk, typing by `/FT`, and `/AP` appearance streams.
|
|
4
|
+
|
|
5
|
+
| Module | Returns | Deps | Description |
|
|
6
|
+
|--------|----------|------|-------------|
|
|
7
|
+
| [`pdfAcroForm`](./acroform.md) | `{ typeAcroForm }` | `pdfErrors`, `pdfParser` | `/AcroForm` dict, §12.7.3. |
|
|
8
|
+
| [`pdfFieldTree`](./fieldTree.md) | `{ walkFieldTree, getInherited }` | `pdfErrors`, `pdfParser` | Walk + inheritance, §12.7.4. |
|
|
9
|
+
| [`pdfButtonField`](./button.md) | `{ typeButtonField }` | `pdfErrors`, `pdfParser` | `/FT /Btn`, §12.7.5.2. |
|
|
10
|
+
| [`pdfTextField`](./text.md) | `{ typeTextField }` | `pdfErrors`, `pdfParser` | `/FT /Tx`, §12.7.5.3. |
|
|
11
|
+
| [`pdfChoiceField`](./choice.md) | `{ typeChoiceField }` | `pdfErrors`, `pdfParser` | `/FT /Ch`, §12.7.5.4. |
|
|
12
|
+
| [`pdfSignatureField`](./signature.md) | `{ typeSignatureField }` | `pdfErrors`, `pdfParser` | `/FT /Sig`, §12.7.5.5. |
|
|
13
|
+
| [`pdfAppearance`](./appearance.md) | `{ typeAppearanceStreams, listPopulatedSlots }` | `pdfErrors`, `pdfParser` | `/AP`, §12.5.5. |
|
|
14
|
+
|
|
15
|
+
## Common pattern
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
const af = runtime.resolve('pdfAcroForm').typeAcroForm(doc._raw.resolve(catalog.acroForm));
|
|
19
|
+
const records = runtime.resolve('pdfFieldTree').walkFieldTree(af.fields, doc._raw.resolve);
|
|
20
|
+
for (const r of records.filter(r => r.terminal)) {
|
|
21
|
+
const ft = r.node.entries.FT && r.node.entries.FT.value;
|
|
22
|
+
switch (ft) {
|
|
23
|
+
case 'Btn': runtime.resolve('pdfButtonField').typeButtonField(r.node); break;
|
|
24
|
+
case 'Tx': runtime.resolve('pdfTextField').typeTextField(r.node); break;
|
|
25
|
+
case 'Ch': runtime.resolve('pdfChoiceField').typeChoiceField(r.node); break;
|
|
26
|
+
case 'Sig': runtime.resolve('pdfSignatureField').typeSignatureField(r.node); break;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## See also
|
|
32
|
+
|
|
33
|
+
- [Document layer](../document/README.md) — `pdfCatalog` carries `/AcroForm`.
|
|
34
|
+
- [Content layer](../content/README.md) — `pdfContentStream` parses appearances.
|
|
35
|
+
- [Syntax layer](../syntax/README.md) — the underlying `pdfParser`.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfAcroForm
|
|
3
|
+
category: pdf/form
|
|
4
|
+
dependencies: [pdfErrors, pdfParser]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfAcroForm
|
|
11
|
+
|
|
12
|
+
> Typing of the Catalog's `/AcroForm` dict — ISO 32000-2 §12.7.3.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfAcroForm` | **Source** `packages/front/office/pdf/src/form/acroform.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
The Catalog's `/AcroForm` describes the interactive-forms layer: root `/Fields`, `/NeedAppearances`, `/SigFlags` (bit 1 = SignaturesExist, bit 2 = AppendOnly), `/CO` (calculation order), `/DR` (default Resources), `/DA` (default appearance), `/Q` (default quadding, 0=left/1=center/2=right). `/XFA` (legacy 1.7) is preserved verbatim in `_extras` for 2.0 fidelity. Any unknown entry is also captured in `_extras`.
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const af = runtime.resolve('pdfAcroForm');
|
|
22
|
+
// Returns: { typeAcroForm }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|--------|-----------|---------|
|
|
29
|
+
| `typeAcroForm` | `(dict) => AcroForm` | Typing. |
|
|
30
|
+
|
|
31
|
+
### Shape `AcroForm`
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
{
|
|
35
|
+
fields: Array<{num:number, gen:number}>,
|
|
36
|
+
needAppearances: boolean, // default false
|
|
37
|
+
sigFlags: number, // default 0
|
|
38
|
+
co: Array<{num,gen}>, // calculation order
|
|
39
|
+
dr: object|null, // /DR dict
|
|
40
|
+
da: Uint8Array|null,// /DA bytes
|
|
41
|
+
q: number, // default 0
|
|
42
|
+
raw: object,
|
|
43
|
+
_extras: { [key]: PdfObject } // /XFA + others
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`/Fields` is required by §12.7.3 but a degenerate AcroForm dict without it is tolerated (result `[]`).
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
### Typing from the Catalog
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
const af = runtime.resolve('pdfAcroForm');
|
|
55
|
+
if (doc.catalog.acroForm) {
|
|
56
|
+
const form = af.typeAcroForm(doc._raw.resolve(doc.catalog.acroForm));
|
|
57
|
+
form.fields.length;
|
|
58
|
+
(form.sigFlags & 1) !== 0; // SignaturesExist
|
|
59
|
+
(form.sigFlags & 2) !== 0; // AppendOnly
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Walking the roots
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
const ft = runtime.resolve('pdfFieldTree');
|
|
67
|
+
const records = ft.walkFieldTree(form.fields, doc._raw.resolve);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### XFA preservation
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
form._extras.XFA; // typed array/stream — passed through as-is to the writer
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Errors
|
|
77
|
+
|
|
78
|
+
| Code | Class | When |
|
|
79
|
+
|------|--------|------|
|
|
80
|
+
| `pdf/form/acroform/not-dict` | `ParseError` | Argument is not a typed dict. |
|
|
81
|
+
| `pdf/form/acroform/bad-fields` | `ParseError` | `/Fields` is not an array of refs. |
|
|
82
|
+
| `pdf/form/acroform/bad-co` | `ParseError` | `/CO` is not an array of refs. |
|
|
83
|
+
|
|
84
|
+
## See also
|
|
85
|
+
|
|
86
|
+
- [`pdfFieldTree`](./fieldTree.md) — walks `fields`.
|
|
87
|
+
- [`pdfButtonField`](./button.md), [`pdfTextField`](./text.md), [`pdfChoiceField`](./choice.md), [`pdfSignatureField`](./signature.md) — typing by `/FT`.
|
|
88
|
+
- [`pdfCatalog`](../document/catalog.md) — carries `acroForm`.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfAppearance
|
|
3
|
+
category: pdf/form
|
|
4
|
+
dependencies: [pdfErrors, pdfParser]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfAppearance
|
|
11
|
+
|
|
12
|
+
> Typing of the `/AP` appearance-streams dict — ISO 32000-2 §12.5.5.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfAppearance` | **Source** `packages/front/office/pdf/src/form/appearance.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
A widget annotation carries an `/AP` with 3 slots: **N** (Normal, required), **R** (Rollover, optional), **D** (Down, optional). Each slot is either a direct stream (or ref), or a sub-dict mapping **state names** (e.g. `/Yes`, `/Off`) to streams — the form used by checkbox/radio, with the current state selected by `/AS`. The module normalizes both shapes to `{ default, states }`.
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const ap = runtime.resolve('pdfAppearance');
|
|
22
|
+
// Returns: { typeAppearanceStreams, listPopulatedSlots }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|--------|-----------|---------|
|
|
29
|
+
| `typeAppearanceStreams` | `(dict) => Appearance` | Typing. |
|
|
30
|
+
| `listPopulatedSlots` | `(ap) => Array<'N'\|'R'\|'D'>` | Non-null slots. |
|
|
31
|
+
|
|
32
|
+
### Shape `Appearance`
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
{
|
|
36
|
+
N: { default: stream|ref|null, states: { [stateName]: stream|ref } },
|
|
37
|
+
R: { ... } | null,
|
|
38
|
+
D: { ... } | null,
|
|
39
|
+
raw: object,
|
|
40
|
+
_extras: { [key]: PdfObject }
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- If the slot was a bare stream/ref → `default` is set, `states = {}`.
|
|
45
|
+
- If the slot was a sub-dict → `default = null`, `states` populated.
|
|
46
|
+
- `/N` is always present (otherwise `pdf/form/ap/missing-n`).
|
|
47
|
+
|
|
48
|
+
## Examples
|
|
49
|
+
|
|
50
|
+
### Stateless (text field)
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
const ap = runtime.resolve('pdfAppearance');
|
|
54
|
+
const a = ap.typeAppearanceStreams(widget.entries.AP);
|
|
55
|
+
a.N.default; // typed stream
|
|
56
|
+
a.N.states; // {}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Checkbox/radio (with states)
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const a = ap.typeAppearanceStreams(widget.entries.AP);
|
|
63
|
+
const currentState = widget.entries.AS && widget.entries.AS.value; // 'Yes' | 'Off'
|
|
64
|
+
const visualStream = a.N.states[currentState] || a.N.default;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Enumeration
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
ap.listPopulatedSlots(a); // ['N'] or ['N','R'] or ['N','R','D']
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Errors
|
|
74
|
+
|
|
75
|
+
| Code | Class | When |
|
|
76
|
+
|------|--------|------|
|
|
77
|
+
| `pdf/form/ap/not-dict` | `ParseError` | Argument is not a typed dict. |
|
|
78
|
+
| `pdf/form/ap/missing-n` | `ParseError` | `/N` absent (Normal slot required). |
|
|
79
|
+
| `pdf/form/ap/bad-state` | `ParseError` | A state entry is neither a stream nor a ref. |
|
|
80
|
+
| `pdf/form/ap/bad-slot` | `ParseError` | An `/N`/`/R`/`/D` slot is neither stream/ref nor a sub-dict. |
|
|
81
|
+
|
|
82
|
+
## See also
|
|
83
|
+
|
|
84
|
+
- [`pdfButtonField`](./button.md) — checkbox/radio uses the `states`.
|
|
85
|
+
- [`pdfTextField`](./text.md), [`pdfChoiceField`](./choice.md), [`pdfSignatureField`](./signature.md).
|
|
86
|
+
- [`pdfContentStream`](../content/stream.md) — parses the appearance streams.
|
|
87
|
+
- [`pdfImages`](../content/images.md) — typing of the underlying Form XObjects.
|