PDF objects#
General#
You can create a new PDF object with
or
which create a new Object:
type Object struct {
ObjectNumber Objectnumber
Data *bytes.Buffer
Dictionary Dict
Array []any
Raw bool // Data holds everything between object number and endobj
ForceStream bool
}
The object is not written to the PDF until saving it
Example:
myObj := PDFWriter.NewObject()
myObj.Dictionary = pdf.Dict{"Type": "/whatever", "Foo": pdf.Array([]any{1, 2, 3})}
myObj.Save()
creates this object in the PDF file:
The Object struct has two fields: Dictionary
and Array
. If the Dictionary
is present and has entries (there will be always a /Length
entry if the object contains data), this will be written before the contents of the data. Otherwise the Array
is used. If you set Raw to true, the header will be skipped and the data will be written to the PDF between the x 0 obj
and endobj
marker.
Object numbers#
When you create an object, it will get the next object number starting from 1. In PDF it is often necessary to have back and forth references. For example a page needs to know the object number of the pages object and the pages object needs to know the page objects. This can be solved with indirect objects where the /Kids
entry in a pages object is an indirect object to be filled when every Page and the Pages objects are written. But it is often easier to reserve an object number for a specific purpose or to create an object and save it later.
For example in this situation:
% The pages object
8 0 obj
<<
/Type /Pages
/MediaBox [0 0 595.28 841.89]
/Kids [ 2 0 R ]
/Count 2
>>
endobj
% The first page
2 0 obj
<<
/Type /Page
/Contents 3 0 R
/Parent 8 0 R
% ...
>>
endobj
The code could be something like this:
page1 := PDFWriter.NewObject()
pages := PDFWriter.NewObject()
pages.Dictionary = pdf.Dict{
"Type": "Pages",
"Kids": pdf.Array([]any{page1.ObjectNumber}),
}
page1.Dictionary = pdf.Dict {
"Type": "Page",
"Parent": pages.ObjectNumber,
}
// todo: error handling
pages.Save()
page1.Save()
Reserve an object number:#
If you just want a unique and free object number, you can call
and use this object number for a new object:
Names#
Names are PDF objects that start with a slash and are used for keys in dictionaries (among other places). When you assign a string value to a Name object, it should not contain a leading slash. Names are used in keys for the Dict object.
Strings#
PDF strings are enclosed in balancing parenthesis ( ... ) or encoded as hexadecimal values in angle brackets. The PDF backend uses either encoding, depending on the input (but no guarantee is made which encoding is used).
Arrays#
Arrays are implemented as []any
. When using the String()
method, the array is correctly encoded. Arrays may contain the following types: string
, Array
, int
, float64
, Dict
, String
. Every other value calls the String()
method.
Dict#
Dictionaries are implemented as map[Name]any
.
Object numbers as values#
The object numbers (type Objectnumber
) has the base type int
. The String()
method returns a reference to the object such as 12 0 R
.
Direct PDF writing#
If you want to write text to the PDF without using Objects/Save(), you can use the three Print methods:
Using these methods ensure that the XRef table knows the PDF offsets.