Documentation
¶
Overview ¶
Package linearize implements ISO 32000-1:2008 Annex F linearization: the object partition, the two cross-reference sections, the linearization parameter dictionary and the primary hint stream.
It knows nothing about parsing PDF. Everything it needs arrives as a neutral representation -- object numbers, outgoing references, and already-serialized object bodies -- built by internal/pdfdoc, which is the only package allowed to import pdfcpu (arch_test.go). The split is not cosmetic: the hint tables are bit-packed, column-major, MSB-first structures where a wrong bit width produces a file every viewer accepts and qpdf rejects with "overflow reading bit stream". In front of the pdfcpu wall they can be tested against hand-decoded byte vectors from real linearized files; behind it they could only be tested by writing a PDF and reading it back.
This package must import nothing outside the standard library. TestLinearizePackageDependsOnlyOnTheStandardLibrary (linearize_arch_test.go in the root package) enforces that, so an implementer cannot resolve a compile error by reaching for pdfcpu.
Tracked as byb-1y7.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Write ¶
Write assembles the linearized file.
bodies is keyed by NEW object number and holds each object's serialized bytes WITHOUT the "N 0 obj" / "endobj" wrapper, with every reference already rewritten to new numbers. A stream's body is its dictionary, then "\nstream\n", then the raw payload, then "\nendstream" -- the shape pdfcpu's own writer produces, so an object that round-trips through this package is byte-identical to one that did not.
Types ¶
type Graph ¶
type Graph struct {
Refs map[int][]int
Pages []int // page object numbers, in page order
PageTree []int // every /Pages node, root first
Catalog int
Info int // 0 when the document has none
// OpenDoc holds the direct targets of the catalog keys a reader consults
// before it can display anything: /ViewerPreferences, /PageMode, /Threads,
// /OpenAction and /AcroForm. They belong to part 4.
OpenDoc []int
// Outlines is the catalog's /Outlines target, and UseOutlines records
// whether /PageMode is /UseOutlines. An outline tree that will be shown
// immediately belongs to the first-page section; one that will not belongs
// to part 9 (F.3.8).
Outlines int
UseOutlines bool
// Other holds the direct targets of every remaining catalog key, plus the
// info dictionary. An object reachable from one of these is document-level
// material that no single page owns, so it may not be filed under a page
// even when exactly one page also refers to it.
Other []int
}
Graph is a document's object graph, with no PDF parser attached. Every object number in it is the ORIGINAL number from the input document.
Refs holds the outgoing references of every object that must survive, so its key set is also the set of objects to be written. A page dictionary's /Parent and /Thumb are deliberately absent from its entry: /Parent points back at the page tree, which Annex F.3.10 puts in part 9, and a thumbnail is not needed to display the page. Both would otherwise drag part-9 material into the first-page section. They stay in the key set because they are still reachable and still get written -- they just do not steer the partition.
type Hint ¶
Hint is an encoded primary hint stream.
S and O are the /S and /O entries of the hint stream dictionary: the offsets, within Payload, of the shared object table and of the outline table. O is 0 when there is no outline table, and /O must then be omitted.
func EncodeHints ¶
EncodeHints builds the primary hint stream payload.
type Hints ¶
type Hints struct {
Pages []PageHint
FirstPageOffset int
Outline *OutlineHint
}
Hints is everything the primary hint stream is computed from.
FirstPageOffset, like every offset stored in a hint table, is measured as if the primary hint stream were not present (Annex F.4) -- so it is the offset the first page's first object had before the hint stream was spliced in, not its offset in the finished file.
type Meta ¶
type Meta struct {
Version string // e.g. "1.5"; the %PDF- header. "1.4" when empty.
ID [2][]byte // the trailer /ID; omitted when the first half is nil
}
Meta is what the assembled file needs that is not structural.
type OutlineHint ¶
OutlineHint is the generic hint table Annex F.4.6 defines for the outline tree. It is emitted only when the document has one; the hint stream dictionary's /O names its offset.
type PageHint ¶
PageHint is one page's row of the page offset hint table.
Length is the number of bytes the page's objects occupy, i.e. the sum over the page's NObjects consecutive object numbers of each object's serialized extent. SharedIDs are indices into Hints.Shared, and must be empty for page 0: Table F.4 item 3 defines the first page's shared objects implicitly, and qpdf warns "page 0 has shared identifier entries" for a file that lists them.
type Plan ¶
type Plan struct {
// Renumber maps original object number to new, over exactly Graph.Refs's
// key set.
Renumber map[int]int
Part4 []int // catalog first
Part6 []int // Part6[0] is the first page's dictionary, i.e. /O
Part7 [][]int // one group per page 2..N; each group's page dictionary first
Part8 []int
Part9 []int
// table (Part6 followed by Part8) of the shared objects that page uses.
// PageShared[0] is always empty: Table F.4 defines the first page's shared
// objects implicitly.
PageShared [][]int
// Outlines holds the outline tree's objects in placement order, the
// /Outlines root first. They sit at the end of part 6 or the end of part 9
// -- and they are also members of whichever of those slices they went into,
// so this is an index, not a fourth part. It is empty when the document has
// no outline tree, and non-empty means the primary hint stream must carry
// an outline hint table: the reference implementation computes one whether
// the outlines went to part 6 or part 9, and warns "incorrect object count
// in outline hint table" when the file does not have one.
Outlines []int
LinDict int // the linearization parameter dictionary's object number
Hint int // the primary hint stream's object number
Catalog int
Info int // 0 when the document has none
Size int // trailer /Size for the whole file: every object plus object 0
NPages int
}
Plan is the layout decision. Every object number in it is the NEW number.
func PlanLayout ¶
PlanLayout partitions g and assigns new object numbers.
type SharedHint ¶
type SharedHint struct {
}
SharedHint is one group of the shared object hint table. Every group here is a single object, so the table's "number of objects in the group" column is zero-width.