Documentation
¶
Overview ¶
Package pdfkit is a pure-Go, CGO-free PDF 1.7 writer with a Go-idiomatic API.
It builds documents from pages, draws vector graphics and text, embeds TrueType and OpenType/CFF fonts as subsetted composite (Type0) fonts, and places JPEG and raster images. Fonts are parsed and shaped with github.com/go-opentype/opentype; nothing outside the Go standard library and our own pure-Go libraries is required.
Quick start ¶
doc := pdfkit.New(pdfkit.Options{})
face, _ := pdfkit.LoadFont(ttfBytes)
p := doc.AddPage(pdfkit.A4)
p.SetFont(face, 24)
p.Text(72, 720, "Hello, PDF")
_ = doc.Write(w) // any io.Writer
Coordinate system ¶
User space is measured in points (1/72 inch) with the origin at the lower-left corner and y increasing upward, matching PDF. The Pt, Mm and In helpers convert physical units; the standard page sizes (A4, Letter, ...) and NewPageSize give a page's dimensions.
Text and fonts ¶
LoadFont parses a font blob once; a Font is immutable and may be shared. SetFont selects it for a page, then Text draws a left-to-right run. TextShaped runs the go-opentype shaper (GSUB/GPOS) for complex scripts. Every embedded font is written as a subset with Identity-H encoding, an Identity CIDToGIDMap, a per-glyph /W width array and a /ToUnicode CMap so copy and paste recover the original text. TrueType outlines embed as a subsetted FontFile2 / CIDFontType2; CFF/OpenType outlines embed as a FontFile3 / CIDFontType0.
Determinism ¶
With the zero Options the output contains no timestamps and a content-derived /ID, so identical inputs produce byte-identical documents. Set Options.Now to stamp creation and modification dates.
Missing upstream primitives ¶
go-opentype/opentype decodes a font fully but does not expose the raw table bytes, the units-per-em, the glyf/loca arrays or a subsetting export that a PDF embedder needs, so pdfkit reparses the sfnt container it is handed (see sfnt.go) and implements TrueType glyf subsetting itself (see subset.go). CFF charstring subsetting is not yet implemented: a CFF font embeds its whole 'CFF ' table.
Example ¶
Example builds a one-page document with embedded-font text and vector graphics, then writes it to a buffer. The output is deterministic: with the zero Options there are no timestamps and the /ID is content-derived.
package main
import (
"bytes"
"fmt"
"os"
"strings"
"github.com/go-pdfkit/pdfkit"
)
func main() {
font, err := pdfkit.LoadFont(mustRead("testdata/SourceSerif4-Regular.otf"))
if err != nil {
panic(err)
}
doc := pdfkit.New(pdfkit.Options{Title: "Hello"})
p := doc.AddPage(pdfkit.A4)
p.SetFont(font, 24)
_ = p.Text(pdfkit.Mm(20), p.Height()-pdfkit.Mm(20), "Hello, pdfkit")
p.SetStrokeColor(pdfkit.RGB8(0x0d, 0x94, 0x88))
p.SetLineWidth(2)
p.MoveTo(pdfkit.Mm(20), pdfkit.Mm(20))
p.LineTo(pdfkit.Mm(190), pdfkit.Mm(20))
p.Stroke()
var buf bytes.Buffer
if err := doc.Write(&buf); err != nil {
panic(err)
}
fmt.Println(strings.SplitN(buf.String(), "\n", 2)[0])
}
func mustRead(path string) []byte {
b, err := os.ReadFile(path)
if err != nil {
panic(err)
}
return b
}
Output: %PDF-1.7
Index ¶
- Constants
- Variables
- func In(v float64) float64
- func Mm(v float64) float64
- func Pt(v float64) float64
- type CMYK
- type Color
- type Document
- type Font
- type Gray
- type Options
- type Page
- func (p *Page) Clip()
- func (p *Page) ClipEvenOdd()
- func (p *Page) ClosePath()
- func (p *Page) CurveTo(x1, y1, x2, y2, x3, y3 float64)
- func (p *Page) DrawImage(img image.Image, r Rect)
- func (p *Page) DrawJPEG(data []byte, r Rect) error
- func (p *Page) DrawPNG(data []byte, r Rect) error
- func (p *Page) EndPath()
- func (p *Page) Fill()
- func (p *Page) FillEvenOdd()
- func (p *Page) FillStroke()
- func (p *Page) FillStrokeEvenOdd()
- func (p *Page) Height() float64
- func (p *Page) LineTo(x, y float64)
- func (p *Page) MoveTo(x, y float64)
- func (p *Page) Rectangle(r Rect)
- func (p *Page) Restore()
- func (p *Page) Rotate(deg float64)
- func (p *Page) Save()
- func (p *Page) Scale(sx, sy float64)
- func (p *Page) SetAlpha(fill, stroke float64)
- func (p *Page) SetCharSpacing(v float64)
- func (p *Page) SetDash(pattern []float64, phase float64)
- func (p *Page) SetFillColor(c Color)
- func (p *Page) SetFont(f *Font, size float64)
- func (p *Page) SetLeading(v float64)
- func (p *Page) SetLineCap(style int)
- func (p *Page) SetLineJoin(style int)
- func (p *Page) SetLineWidth(w float64)
- func (p *Page) SetMiterLimit(limit float64)
- func (p *Page) SetRenderMode(mode int)
- func (p *Page) SetStrokeColor(c Color)
- func (p *Page) SetWordSpacing(v float64)
- func (p *Page) Skew(axDeg, ayDeg float64)
- func (p *Page) Stroke()
- func (p *Page) Text(x, y float64, s string) error
- func (p *Page) TextLines(x, y float64, lines []string) error
- func (p *Page) TextShaped(x, y float64, s string, features ...string) error
- func (p *Page) TextWidth(s string) float64
- func (p *Page) Transform(a, b, c, d, e, f float64)
- func (p *Page) Translate(tx, ty float64)
- func (p *Page) Width() float64
- func (p *Page) WrapText(s string, maxWidth float64) []string
- type PageSize
- type RGB
- type Rect
Examples ¶
Constants ¶
const ( CapButt = 0 CapRound = 1 CapSquare = 2 )
Line-cap styles for SetLineCap.
const ( JoinMiter = 0 JoinRound = 1 JoinBevel = 2 )
Line-join styles for SetLineJoin.
const ( RenderFill = 0 // fill glyphs RenderStroke = 1 // stroke glyph outlines RenderFillStroke = 2 // fill then stroke RenderInvisible = 3 // neither (useful for OCR text layers) RenderFillClip = 4 // fill and add to clip RenderStrokeClip = 5 // stroke and add to clip RenderFSClip = 6 // fill, stroke and add to clip RenderClip = 7 // add to clip only )
Text render modes for SetRenderMode (a subset of PDF's Tr values).
const DefaultProducer = "go-pdfkit/pdfkit"
DefaultProducer is the /Producer value used when Options.Producer is empty.
Variables ¶
var ( A3 = PageSize{Width: Mm(297), Height: Mm(420)} A4 = PageSize{Width: Mm(210), Height: Mm(297)} A5 = PageSize{Width: Mm(148), Height: Mm(210)} Letter = PageSize{Width: In(8.5), Height: In(11)} Legal = PageSize{Width: In(8.5), Height: In(14)} Tabloid = PageSize{Width: In(11), Height: In(17)} )
Standard ISO 216 A-series and US page sizes, in points.
Functions ¶
Types ¶
type CMYK ¶
type CMYK struct{ C, M, Y, K float64 }
CMYK is a DeviceCMYK colour with cyan, magenta, yellow and black components in [0,1].
type Color ¶
type Color interface {
// contains filtered or unexported methods
}
Color is a paint in one of PDF's device colour spaces. Its ops method emits the content-stream operator that selects it for filling (stroke=false) or stroking (stroke=true). Component values are in the range [0,1].
type Document ¶
type Document struct {
// contains filtered or unexported fields
}
Document is a PDF document under construction. Build it with New, append pages with AddPage, then serialise with Write. It is not safe for concurrent use.
Example (MultiPage) ¶
ExampleDocument_multiPage lays out several pages of different sizes.
package main
import (
"bytes"
"fmt"
"github.com/go-pdfkit/pdfkit"
)
func main() {
doc := pdfkit.New(pdfkit.Options{})
doc.AddPage(pdfkit.A4)
doc.AddPage(pdfkit.Letter.Landscape())
doc.AddPage(pdfkit.NewPageSize(pdfkit.In(4), pdfkit.In(6)))
var buf bytes.Buffer
_ = doc.Write(&buf)
fmt.Println(bytes.Contains(buf.Bytes(), []byte("/Count 3")))
}
Output: true
type Font ¶
type Font struct {
// contains filtered or unexported fields
}
Font is a loaded TrueType or OpenType font ready to be used and embedded. It is immutable and may be shared across documents and goroutines; per-document glyph usage is tracked separately by the Document. Build one with LoadFont.
func LoadFont ¶
LoadFont parses a TrueType ('glyf') or OpenType/CFF ('OTTO'/CFF) font from its raw bytes. The bytes are retained and must not be mutated afterwards.
func (*Font) IsCFF ¶
IsCFF reports whether the font carries CFF/OpenType outlines (embedded as a CIDFontType0), as opposed to TrueType 'glyf' outlines (CIDFontType2).
func (*Font) UnitsPerEm ¶
UnitsPerEm returns the font's design grid size.
type Gray ¶
type Gray struct{ V float64 }
Gray is a DeviceGray colour: a single intensity from 0 (black) to 1 (white).
type Options ¶
type Options struct {
// Title and Author populate the document information dictionary. Empty
// values are omitted.
Title string
Author string
// Producer is the /Producer string in the information dictionary. When
// empty it defaults to DefaultProducer.
Producer string
// Now, when non-nil, is called once at Write time to stamp /CreationDate
// and /ModDate. When nil no dates are written, keeping output reproducible;
// tests should leave it nil.
Now func() time.Time
// Compress enables FlateDecode compression of content and embedded-font
// streams. Image streams choose their own filter regardless.
Compress bool
// ID, when both entries are non-nil, is used verbatim as the trailer /ID
// pair. When nil the ID is derived deterministically from the document
// body, so identical documents get identical IDs without a clock.
ID [2][]byte
}
Options configures a Document. The zero value is valid and yields a deterministic, uncompressed document with no timestamps.
type Page ¶
type Page struct {
// contains filtered or unexported fields
}
Page is a single page's content. It accumulates a content stream as drawing methods are called; the operators mirror PDF's imaging model. The default user space has its origin at the lower-left corner with y increasing upward.
func (*Page) Clip ¶
func (p *Page) Clip()
Clip intersects the clipping path with the current path using the nonzero rule (W). It must be followed by a path-painting or EndPath operator.
func (*Page) ClipEvenOdd ¶
func (p *Page) ClipEvenOdd()
ClipEvenOdd intersects the clipping path using the even-odd rule (W*).
func (*Page) ClosePath ¶
func (p *Page) ClosePath()
ClosePath closes the current subpath with a straight segment to its start (h).
func (*Page) CurveTo ¶
CurveTo adds a cubic Bézier segment to (x3, y3) with control points (x1, y1) and (x2, y2) (c).
func (*Page) DrawImage ¶
DrawImage embeds img and paints it into the rectangle r (in points). Any alpha channel becomes a soft mask, so partially transparent images composite correctly. Sample data is FlateDecode-compressed.
func (*Page) DrawJPEG ¶
DrawJPEG embeds JPEG bytes directly (DCTDecode, no re-encoding) into r, preserving the original compression. Grayscale (1), RGB/YCbCr (3) and CMYK (4) component counts are supported.
func (*Page) DrawPNG ¶
DrawPNG decodes PNG bytes and embeds the image into r. It returns an error if the data is not a valid PNG.
func (*Page) EndPath ¶
func (p *Page) EndPath()
EndPath ends the path with no fill or stroke (n), used after a clip.
func (*Page) Fill ¶
func (p *Page) Fill()
Fill fills the current path with the nonzero winding rule (f).
func (*Page) FillEvenOdd ¶
func (p *Page) FillEvenOdd()
FillEvenOdd fills the current path with the even-odd rule (f*).
func (*Page) FillStroke ¶
func (p *Page) FillStroke()
FillStroke fills (nonzero) then strokes the current path (B).
func (*Page) FillStrokeEvenOdd ¶
func (p *Page) FillStrokeEvenOdd()
FillStrokeEvenOdd fills (even-odd) then strokes the current path (B*).
func (*Page) Rotate ¶
Rotate rotates the coordinate system counter-clockwise by deg degrees about the origin.
func (*Page) SetAlpha ¶
SetAlpha sets the constant fill and stroke alpha (opacity) in [0,1] via an ExtGState resource (ca/CA).
func (*Page) SetCharSpacing ¶
SetCharSpacing sets additional spacing between glyphs, in points (Tc).
func (*Page) SetDash ¶
SetDash sets the line dash pattern and phase (d). An empty pattern restores a solid line.
func (*Page) SetFillColor ¶
SetFillColor selects the fill colour.
func (*Page) SetFont ¶
SetFont selects font f at the given size in points for subsequent text. The font is registered with the document for embedding on the first use.
func (*Page) SetLeading ¶
SetLeading sets the line leading (baseline-to-baseline distance) used by TextLines, in points (TL).
func (*Page) SetLineCap ¶
SetLineCap sets the line-cap style (J).
func (*Page) SetLineJoin ¶
SetLineJoin sets the line-join style (j).
func (*Page) SetLineWidth ¶
SetLineWidth sets the stroke line width in user-space units (w).
func (*Page) SetMiterLimit ¶
SetMiterLimit sets the miter limit (M).
func (*Page) SetRenderMode ¶
SetRenderMode sets the text rendering mode (Tr); see the Render constants.
func (*Page) SetStrokeColor ¶
SetStrokeColor selects the stroke colour.
func (*Page) SetWordSpacing ¶
SetWordSpacing sets additional spacing at space characters, in points (Tw). It has no visible effect on composite (Type0) fonts and is provided for completeness.
func (*Page) Text ¶
Text draws s with its baseline origin at (x, y) using the current font. It returns errNoFont if no font is set.
func (*Page) TextLines ¶
TextLines draws consecutive lines starting with the first baseline at (x, y), advancing by the current leading between lines.
func (*Page) TextShaped ¶
TextShaped draws s with complex-script shaping (GSUB substitution and GPOS positioning) via the go-opentype shaper, placing the run's origin at (x, y). The default Text path stays a simple left-to-right cmap mapping; use this for Arabic, Indic, CJK and any text needing ligatures, marks or kerning. features names OpenType feature tags to enable (e.g. "liga").
func (*Page) TextWidth ¶
TextWidth returns the width of s in points at the current font and size. It returns 0 when no font is set.
func (*Page) Transform ¶
Transform concatenates the affine matrix [a b c d e f] onto the current transformation matrix (cm). Points map as x' = a*x + c*y + e and y' = b*x + d*y + f.
type PageSize ¶
PageSize is a page's dimensions in points.
func NewPageSize ¶
NewPageSize builds a custom page size from a width and height in points.