Documentation
¶
Overview ¶
Package gpdf is a pure Go, zero-dependency PDF generation library.
gpdf provides a layered architecture for PDF creation:
- pdf (Layer 1): Low-level PDF primitives — objects, streams, fonts, images
- document (Layer 2): Document model — nodes, box model, layout engine, renderer
- template (Layer 3): High-level declarative API — builders, grids, components
Most users should start with the template package for the simplest API:
doc := gpdf.NewDocument(
gpdf.WithPageSize(document.A4),
gpdf.WithMargins(document.UniformEdges(document.Mm(15))),
)
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Hello, World!", template.FontSize(24))
})
})
data, err := doc.Generate()
Example (Barcode) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Order barcode:")
c.Barcode("INV-2026-0001", template.BarcodeWidth(document.Mm(80)))
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (Colors) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/pdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(4, func(c *template.ColBuilder) {
c.Text("RGB", template.TextColor(pdf.RGB(0.2, 0.4, 0.8)))
})
r.Col(4, func(c *template.ColBuilder) {
c.Text("Hex", template.TextColor(pdf.RGBHex(0xFF6600)))
})
r.Col(4, func(c *template.ColBuilder) {
c.Text("Gray", template.TextColor(pdf.Gray(0.5)))
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (GridLayout) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
// Two-column layout (6+6 = 12)
page.AutoRow(func(r *template.RowBuilder) {
r.Col(6, func(c *template.ColBuilder) {
c.Text("Left column")
})
r.Col(6, func(c *template.ColBuilder) {
c.Text("Right column")
})
})
// Three-column layout (4+4+4 = 12)
page.AutoRow(func(r *template.RowBuilder) {
r.Col(4, func(c *template.ColBuilder) { c.Text("Col 1") })
r.Col(4, func(c *template.ColBuilder) { c.Text("Col 2") })
r.Col(4, func(c *template.ColBuilder) { c.Text("Col 3") })
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (Image) ¶
package main
import (
"bytes"
"fmt"
"image"
"image/color"
"image/png"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
// Create a small 2x2 test PNG image.
img := image.NewRGBA(image.Rect(0, 0, 2, 2))
for y := range 2 {
for x := range 2 {
img.Set(x, y, color.RGBA{R: 0, G: 100, B: 200, A: 255})
}
}
var buf bytes.Buffer
_ = png.Encode(&buf, img)
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Embedded image:")
c.Image(buf.Bytes(), template.FitWidth(document.Mm(30)))
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (List) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Bullet list:", template.Bold())
c.List([]string{"First item", "Second item", "Third item"})
c.Spacer(document.Mm(5))
c.Text("Numbered list:", template.Bold())
c.OrderedList([]string{"Step one", "Step two", "Step three"})
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (PageNumbers) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
doc.Footer(func(p *template.PageBuilder) {
p.AutoRow(func(r *template.RowBuilder) {
r.Col(6, func(c *template.ColBuilder) {
c.PageNumber(template.FontSize(8))
})
r.Col(6, func(c *template.ColBuilder) {
c.TotalPages(template.AlignRight(), template.FontSize(8))
})
})
})
for range 3 {
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Content page")
})
})
}
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (QrCode) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Scan to visit our site:")
c.QRCode("https://gpdf.dev", template.QRSize(document.Mm(30)))
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (RenderToWriter) ¶
package main
import (
"bytes"
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Written via Render(io.Writer)")
})
})
var buf bytes.Buffer
_ = doc.Render(&buf)
fmt.Println("PDF starts with:", string(buf.Bytes()[:5]))
}
Output: PDF starts with: %PDF-
Example (RichText) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/pdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.RichText(func(rt *template.RichTextBuilder) {
rt.Span("This is ")
rt.Span("bold", template.Bold())
rt.Span(" and this is ")
rt.Span("red italic", template.Italic(), template.TextColor(pdf.Red))
rt.Span(" in one line.")
})
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (Table) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Table(
[]string{"Name", "Age", "City"},
[][]string{
{"Alice", "30", "Tokyo"},
{"Bob", "25", "New York"},
{"Charlie", "35", "London"},
},
)
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (TableStyled) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/pdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Table(
[]string{"Product", "Qty", "Price"},
[][]string{
{"Widget", "10", "$9.99"},
{"Gadget", "5", "$24.99"},
},
template.ColumnWidths(50, 25, 25),
template.TableHeaderStyle(
template.TextColor(pdf.White),
template.BgColor(pdf.RGBHex(0x1A237E)),
),
template.TableStripe(pdf.RGBHex(0xF5F5F5)),
)
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (TextStyling) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/pdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument()
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Large bold title", template.FontSize(24), template.Bold())
c.Text("Italic subtitle", template.Italic())
c.Text("Red text", template.TextColor(pdf.Red))
c.Text("Centered", template.AlignCenter())
c.Text("Underlined", template.Underline())
c.Text("Yellow background", template.BgColor(pdf.Yellow))
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (Units) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument(
gpdf.WithMargins(document.Edges{
Top: document.Cm(2), // centimeters
Right: document.In(0.5), // inches
Bottom: document.Mm(15), // millimeters
Left: document.Pt(36), // points
}),
)
page := doc.AddPage()
page.Row(document.Mm(20), func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Fixed 20mm height row")
})
})
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Auto-height row")
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Index ¶
- Constants
- Variables
- func Merge(sources []Source, opts ...MergeOption) ([]byte, error)
- func NewDocument(opts ...template.Option) *template.Document
- func NewDocumentFromJSON(schema []byte, data any, opts ...template.Option) (*template.Document, error)
- func NewDocumentFromTemplate(tmpl *gotemplate.Template, data any, opts ...template.Option) (*template.Document, error)
- func Open(data []byte, opts ...template.Option) (*template.ExistingDocument, error)
- func SignDocument(pdfData []byte, signer signature.Signer, opts ...signature.Option) ([]byte, error)
- func WithEncryption(opts ...encrypt.Option) template.Option
- func WithPDFA(opts ...pdfa.Option) template.Option
- type MergeOption
- type PageRange
- type Source
Examples ¶
- Package (Barcode)
- Package (Colors)
- Package (GridLayout)
- Package (HeaderFooter)
- Package (Image)
- Package (List)
- Package (PageNumbers)
- Package (QrCode)
- Package (RenderToWriter)
- Package (RichText)
- Package (Table)
- Package (TableStyled)
- Package (TextStyling)
- Package (Units)
- NewDocument
- NewDocument (WithOptions)
- NewDocumentFromJSON
- NewDocumentFromJSON (WithData)
- NewDocumentFromTemplate
Constants ¶
const Version = buildinfo.Version
Version is the library version.
Variables ¶
var ( // WithPageSize sets the page dimensions. WithPageSize = template.WithPageSize // WithMargins sets the page margins. WithMargins = template.WithMargins // WithFont registers a TrueType font. WithFont = template.WithFont // WithDefaultFont sets the default font family and size. WithDefaultFont = template.WithDefaultFont // WithMetadata sets document metadata (title, author, etc.). WithMetadata = template.WithMetadata // WithWriterSetup registers a Writer configuration hook for extensions. WithWriterSetup = template.WithWriterSetup )
Re-export commonly used option functions for convenience.
var ( A4 = document.A4 A3 = document.A3 Letter = document.Letter Legal = document.Legal )
Re-export commonly used page sizes for convenience.
var ( // QRSize sets the display size of a QR code (width = height). QRSize = template.QRSize // QRErrorCorrection sets the QR error correction level. QRErrorCorrection = template.QRErrorCorrection // QRScale sets the pixels per QR module. QRScale = template.QRScale )
Re-export QR code option functions for convenience.
var ( // BarcodeWidth sets the display width of a barcode. BarcodeWidth = template.BarcodeWidth // BarcodeHeight sets the display height of a barcode. BarcodeHeight = template.BarcodeHeight // BarcodeFormat sets the barcode symbology. BarcodeFormat = template.BarcodeFormat )
Re-export barcode option functions for convenience.
var ( // AbsoluteWidth sets the width constraint for absolute-positioned content. AbsoluteWidth = template.AbsoluteWidth // AbsoluteHeight sets the height constraint for absolute-positioned content. AbsoluteHeight = template.AbsoluteHeight // AbsoluteOriginPage sets the coordinate origin to the page corner. AbsoluteOriginPage = template.AbsoluteOriginPage )
Re-export absolute positioning option functions for convenience.
var ( // FromJSON creates a Document from a JSON schema definition with // optional Go template data binding. FromJSON = template.FromJSON // FromTemplate creates a Document by executing a pre-parsed Go // template that produces JSON schema output. FromTemplate = template.FromTemplate // TemplateFuncMap returns helper functions (e.g., toJSON) for use // when parsing Go templates for FromTemplate. TemplateFuncMap = template.TemplateFuncMap )
Re-export JSON schema / Go template integration functions.
var ( // NewInvoice creates a ready-to-generate invoice PDF from structured data. NewInvoice = template.Invoice // NewReport creates a ready-to-generate report PDF from structured data. NewReport = template.Report // NewLetter creates a ready-to-generate business letter PDF from structured data. NewLetter = template.Letter )
Re-export reusable component constructors for convenience.
Functions ¶
func Merge ¶ added in v1.0.2
func Merge(sources []Source, opts ...MergeOption) ([]byte, error)
Merge combines pages from multiple PDF sources into a single PDF.
merged, err := gpdf.Merge(
[]gpdf.Source{
{Data: coverPage},
{Data: generated},
{Data: attachment, Pages: gpdf.PageRange{From: 1, To: 3}},
},
gpdf.WithMergeMetadata("Policy Bundle", "Example Ltd", ""),
)
func NewDocument ¶
NewDocument creates a new PDF document builder with the given options. This is the primary entry point for creating PDFs using the high-level API.
Example ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument(
gpdf.WithPageSize(document.A4),
gpdf.WithMargins(document.UniformEdges(document.Mm(20))),
)
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Hello, World!", template.FontSize(24))
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (WithOptions) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument(
gpdf.WithPageSize(document.Letter),
gpdf.WithMargins(document.Edges{
Top: document.Mm(25), Right: document.Mm(20),
Bottom: document.Mm(25), Left: document.Mm(20),
}),
gpdf.WithMetadata(document.DocumentMetadata{
Title: "Annual Report",
Author: "gpdf",
}),
)
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("Custom page size, margins, and metadata")
})
})
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
func NewDocumentFromJSON ¶ added in v0.8.0
func NewDocumentFromJSON(schema []byte, data any, opts ...template.Option) (*template.Document, error)
NewDocumentFromJSON is an alias for FromJSON that creates a Document from a JSON schema, optionally resolving Go template expressions with data.
Example ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
)
func main() {
schema := []byte(`{
"page": {"size": "A4", "margins": "15mm"},
"metadata": {"title": "JSON Example", "author": "gpdf"},
"body": [
{"row": {"cols": [
{"span": 12, "text": "Generated from JSON schema", "style": {"size": 20, "bold": true}}
]}},
{"row": {"cols": [
{"span": 6, "text": "Left column"},
{"span": 6, "text": "Right column", "style": {"align": "right"}}
]}}
]
}`)
doc, _ := gpdf.NewDocumentFromJSON(schema, nil)
data, _ := doc.Generate()
fmt.Println("PDF starts with:", string(data[:5]))
}
Output: PDF starts with: %PDF-
Example (WithData) ¶
package main
import (
"fmt"
gpdf "github.com/gpdf-dev/gpdf"
)
func main() {
schema := []byte(`{
"page": {"size": "A4"},
"body": [
{"row": {"cols": [
{"span": 12, "text": "Hello, {{.Name}}!", "style": {"size": 24}}
]}}
]
}`)
data := map[string]string{"Name": "World"}
doc, _ := gpdf.NewDocumentFromJSON(schema, data)
pdfData, _ := doc.Generate()
fmt.Println("PDF starts with:", string(pdfData[:5]))
}
Output: PDF starts with: %PDF-
func NewDocumentFromTemplate ¶ added in v0.8.0
func NewDocumentFromTemplate(tmpl *gotemplate.Template, data any, opts ...template.Option) (*template.Document, error)
NewDocumentFromTemplate creates a Document by executing a Go template that produces JSON schema output.
Example ¶
package main
import (
"fmt"
gotemplate "text/template"
gpdf "github.com/gpdf-dev/gpdf"
)
func main() {
tmplStr := `{
"page": {"size": "A4"},
"body": [
{"row": {"cols": [
{"span": 12, "text": "Items: {{len .Items}}", "style": {"size": 18}}
]}}
{{- range .Items}},
{"row": {"cols": [
{"span": 8, "text": "{{.Name}}"},
{"span": 4, "text": "{{.Price}}", "style": {"align": "right"}}
]}}
{{- end}}
]
}`
funcMap := gpdf.TemplateFuncMap()
tmpl := gotemplate.Must(gotemplate.New("").Funcs(funcMap).Parse(tmplStr))
data := map[string]any{
"Items": []map[string]string{
{"Name": "Widget", "Price": "$9.99"},
{"Name": "Gadget", "Price": "$24.99"},
},
}
doc, _ := gpdf.NewDocumentFromTemplate(tmpl, data)
pdfData, _ := doc.Generate()
fmt.Println("PDF starts with:", string(pdfData[:5]))
}
Output: PDF starts with: %PDF-
func Open ¶ added in v0.9.2
Open creates an ExistingDocument from raw PDF data for reading and modifying. Use the returned document's Overlay method to add content on top of existing pages.
doc, err := gpdf.Open(pdfBytes, gpdf.WithFont("NotoSans", fontData))
doc.Overlay(0, func(p *template.PageBuilder) {
p.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("APPROVED", template.FontSize(48))
})
})
})
result, err := doc.Save()
func SignDocument ¶ added in v1.0.0
func SignDocument(pdfData []byte, signer signature.Signer, opts ...signature.Option) ([]byte, error)
SignDocument adds a digital signature to a generated PDF. This is a post-processing step applied after document generation.
func WithEncryption ¶ added in v1.0.0
WithEncryption returns a template.Option that enables AES-256 encryption.
Types ¶
type MergeOption ¶ added in v1.0.2
type MergeOption func(*mergeConfig)
MergeOption configures the merge operation.
func WithMergeMetadata ¶ added in v1.0.2
func WithMergeMetadata(title, author, producer string) MergeOption
WithMergeMetadata sets the document info on the merged output.
Directories
¶
| Path | Synopsis |
|---|---|
|
_examples
|
|
|
testutil
Package testutil provides shared test helpers for gpdf example tests.
|
Package testutil provides shared test helpers for gpdf example tests. |
|
Package barcode implements barcode encoding and rendering for PDF generation.
|
Package barcode implements barcode encoding and rendering for PDF generation. |
|
Package document provides the intermediate document model that bridges the high-level template API and the low-level PDF writer.
|
Package document provides the intermediate document model that bridges the high-level template API and the low-level PDF writer. |
|
layout
Package layout provides layout engines that calculate the position and size of document nodes within the available space.
|
Package layout provides layout engines that calculate the position and size of document nodes within the available space. |
|
render
Package render provides interfaces and implementations for drawing laid-out document content to an output target such as a PDF file.
|
Package render provides interfaces and implementations for drawing laid-out document content to an output target such as a PDF file. |
|
Package encrypt provides AES-256 PDF encryption (ISO 32000-2, Rev 6).
|
Package encrypt provides AES-256 PDF encryption (ISO 32000-2, Rev 6). |
|
internal
|
|
|
buildinfo
Package buildinfo holds build-time constants shared across gpdf packages.
|
Package buildinfo holds build-time constants shared across gpdf packages. |
|
Package pdf provides low-level PDF object types, a streaming writer, and color utilities for producing valid PDF binary output.
|
Package pdf provides low-level PDF object types, a streaming writer, and color utilities for producing valid PDF binary output. |
|
font
Package font provides TrueType font parsing, glyph metrics, text measurement, line breaking, and font subsetting for PDF generation.
|
Package font provides TrueType font parsing, glyph metrics, text measurement, line breaking, and font subsetting for PDF generation. |
|
Package pdfa provides PDF/A conformance support for gpdf.
|
Package pdfa provides PDF/A conformance support for gpdf. |
|
Package qrcode implements QR code encoding per ISO 18004.
|
Package qrcode implements QR code encoding per ISO 18004. |
|
Package signature provides CMS/PKCS#7 digital signatures for PDF documents.
|
Package signature provides CMS/PKCS#7 digital signatures for PDF documents. |
|
Package template provides a declarative, builder-pattern API for constructing PDF documents.
|
Package template provides a declarative, builder-pattern API for constructing PDF documents. |