pdf

package
v1.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 28, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package pdf manages PDF document creation, page layout, and styling.

Index

Constants

View Source
const (
	FontBody    = "NotoSans"
	FontCode    = "NotoSansMono"
	FontSymbols = "NotoSansSymbols2"
	FontEmoji   = "NotoEmoji"

	FontSizeBody          = 11.0
	FontSizeH1            = 24.0
	FontSizeH2            = 20.0
	FontSizeH3            = 16.0
	FontSizeH4            = 14.0
	FontSizeH5            = 12.0
	FontSizeH6            = 11.0
	FontSizeCoverTitle    = 36.0 // Large title on cover page
	FontSizeCoverSubtitle = 18.0 // Subtitle below title
	FontSizeCoverMeta     = 14.0 // Author, date, version

	CoverTitleY    = 80.0 // Y position for title (from top, mm)
	CoverSpacing   = 12.0 // Vertical spacing between cover elements
	CoverMetaSpace = 8.0  // Spacing between metadata fields

	LineHeight = 6.0

	PageMargin = 20.0

	BlockquoteIndent = 10.0
	BlockquoteBar    = 2.0

	FontSizeCode     = 9.0
	CodeBlockPadding = 6.0
	CodeBlockMarginV = 4.0

	ListIndent      = 7.0 // left margin increase per nesting level (LaTeX ~2.5em)
	ListLabelWidth  = 5.0 // width of the label box (right-aligned labels)
	ListLabelSep    = 2.0 // gap between label box and text (LaTeX \labelsep ≈ 5pt)
	ListBulletSize  = 2.0
	ListItemSpacing = 2.0

	TableCellPadding = 3.0
	TableBorderWidth = 0.3
	FontSizeTable    = 10.0

	ImageMarginV   = 4.0
	SVGRenderScale = 2.0

	CodeContinuationIndicator = " →" // → shows code wraps to next line (falls back to "->" if unsupported)
	// Heading spacing (LaTeX article.cls inspired, ~1.5:1 before:after ratio).
	// LaTeX \section uses 3.5ex/2.3ex (~1.52:1), CSS uses 1:1 symmetric.
	// We use ~1.4–1.5:1 as a balanced professional compromise.
	// Before: space above heading (proximity break from previous content).
	// After:  space below heading (closer to its own content).
	HeadingBeforeH1 = 14.0 // ~40pt
	HeadingBeforeH2 = 12.0 // ~34pt
	HeadingBeforeH3 = 10.0 // ~28pt
	HeadingBeforeH4 = 8.0  // ~23pt
	HeadingBeforeH5 = 6.0  // ~17pt
	HeadingBeforeH6 = 5.0  // ~14pt

	HeadingAfterH1 = 10.0 // ~28pt (ratio 1.40:1)
	HeadingAfterH2 = 8.0  // ~23pt (ratio 1.50:1)
	HeadingAfterH3 = 6.5  // ~18pt (ratio 1.54:1)
	HeadingAfterH4 = 5.5  // ~16pt (ratio 1.45:1)
	HeadingAfterH5 = 4.0  // ~11pt (ratio 1.50:1)
	HeadingAfterH6 = 3.5  // ~10pt (ratio 1.43:1)

	// Heading line height multiplier (tighter than body text for visual impact).
	HeadingLeading = 1.25
)

Variables

View Source
var (
	// ListBulletChars are the UTF-8 bullet characters by nesting depth.
	ListBulletChars = []rune{'•', '‣', '⁃'}

	ColorText            = fpdf.RGBType{R: 20, G: 20, B: 20}
	ColorLink            = fpdf.RGBType{R: 20, G: 90, B: 200}
	ColorBlockquote      = fpdf.RGBType{R: 230, G: 230, B: 230}
	ColorCodeFill        = fpdf.RGBType{R: 240, G: 240, B: 240}
	ColorCodeBlockBG     = fpdf.RGBType{R: 245, G: 245, B: 245}
	ColorCodeBlockBorder = fpdf.RGBType{R: 220, G: 220, B: 220}
	ColorTableHeader     = fpdf.RGBType{R: 240, G: 240, B: 240}
	ColorTableBorder     = fpdf.RGBType{R: 180, G: 180, B: 180}
)

Functions

func FontSupportsGlyph added in v0.0.3

func FontSupportsGlyph(fontData []byte, r rune) bool

FontSupportsGlyph checks whether the given TTF font data contains a glyph for the specified rune. It uses golang.org/x/image/font/sfnt to parse the font's cmap table. A GlyphIndex of 0 means the .notdef (missing) glyph.

func HeadingLineHeight added in v0.0.3

func HeadingLineHeight(fontSize float64) float64

HeadingLineHeight returns the line height (mm) for multi-line headings. It uses a tighter leading (1.25×) than body text for visual impact.

func HeadingSpaceAfter added in v0.0.3

func HeadingSpaceAfter(level int) float64

HeadingSpaceAfter returns the vertical space (mm) to insert below a heading.

func HeadingSpaceBefore added in v0.0.3

func HeadingSpaceBefore(level int) float64

HeadingSpaceBefore returns the vertical space (mm) to insert above a heading.

func LoadCustomEmojiFont added in v0.0.3

func LoadCustomEmojiFont(pdf *fpdf.Fpdf, archivePath string) ([]byte, error)

LoadCustomEmojiFont reads a zip or tar.gz archive and registers the first TTF found as the emoji fallback font family. Returns the font bytes.

func LoadCustomFonts added in v0.0.3

func LoadCustomFonts(pdf *fpdf.Fpdf, archivePath string) ([]byte, error)

LoadCustomFonts reads a zip or tar.gz archive from path, extracts all .ttf files, and registers them as the body font family on the PDF document. It maps filename patterns (Regular, Bold, Italic, BoldItalic) to fpdf styles. Returns the regular font bytes (for glyph detection) or an error.

func LoadCustomSymbolsFont added in v0.0.3

func LoadCustomSymbolsFont(pdf *fpdf.Fpdf, archivePath string) ([]byte, error)

LoadCustomSymbolsFont reads a zip or tar.gz archive and registers the first TTF found as the symbols fallback font family. Returns the font bytes.

func RegisterEmojiFont added in v0.0.3

func RegisterEmojiFont(pdf *fpdf.Fpdf) []byte

RegisterEmojiFont registers the embedded Noto Emoji font as the third-tier fallback font family for rendering emoji glyphs that neither the body nor symbols font supports. It returns the emoji font bytes for glyph detection.

func RegisterFonts

func RegisterFonts(pdf *fpdf.Fpdf) []byte

RegisterFonts registers the embedded Noto Sans font families with the PDF document. After registration, FontBody and FontCode constants can be used with SetFont as usual. It returns the regular body font bytes for glyph detection.

func RegisterSymbolsFont added in v0.0.3

func RegisterSymbolsFont(pdf *fpdf.Fpdf) []byte

RegisterSymbolsFont registers the embedded Noto Sans Symbols 2 font as a fallback font family for rendering glyphs the body font doesn't support. It returns the symbols font bytes for glyph detection.

func SubstituteUnsupportedGlyphs added in v0.0.3

func SubstituteUnsupportedGlyphs(bodyFont, symbolsFont, emojiFont []byte, text string) string

SubstituteUnsupportedGlyphs replaces runes that neither the body nor symbols font can render with ASCII text equivalents from the substitution table. Runes renderable by the symbols font are kept as-is (they will be rendered via font fallback). This function is used for text measurement where we need a flat string rather than segmented output.

Types

type Document

type Document struct {
	// contains filtered or unexported fields
}

func NewDocument

func NewDocument(opts ...DocumentOption) (*Document, error)

func (*Document) BaseDir

func (d *Document) BaseDir() string

func (*Document) BodyFontBytes added in v0.0.3

func (d *Document) BodyFontBytes() []byte

BodyFontBytes returns the raw TTF bytes of the regular body font, used for glyph detection (e.g. checking if bullet characters exist).

func (*Document) EmojiFontBytes added in v0.0.3

func (d *Document) EmojiFontBytes() []byte

EmojiFontBytes returns the raw TTF bytes of the emoji fallback font, used for glyph detection when neither the body nor symbols font has a glyph.

func (*Document) FooterCalls

func (d *Document) FooterCalls() int

func (*Document) PDF

func (d *Document) PDF() *fpdf.Fpdf

func (*Document) Save

func (d *Document) Save(path string) error

func (*Document) SetBaseDir

func (d *Document) SetBaseDir(dir string)

func (*Document) SymbolsFontBytes added in v0.0.3

func (d *Document) SymbolsFontBytes() []byte

SymbolsFontBytes returns the raw TTF bytes of the symbols fallback font, used for glyph detection when the body font lacks a glyph.

type DocumentOption added in v0.0.3

type DocumentOption func(*documentConfig)

DocumentOption configures Document creation.

func WithCustomEmojiFont added in v0.0.3

func WithCustomEmojiFont(archivePath string) DocumentOption

WithCustomEmojiFont returns an option that loads an emoji fallback font from a zip or tar.gz archive instead of the default embedded Noto Emoji.

func WithCustomFont added in v0.0.3

func WithCustomFont(archivePath string) DocumentOption

WithCustomFont returns an option that loads fonts from a zip or tar.gz archive instead of the default embedded Noto Sans.

func WithCustomSymbolsFont added in v0.0.3

func WithCustomSymbolsFont(archivePath string) DocumentOption

WithCustomSymbolsFont returns an option that loads a symbols fallback font from a zip or tar.gz archive instead of the default embedded Noto Sans Symbols 2.

type FontKind added in v0.0.3

type FontKind int

FontKind indicates which font family a text segment should be rendered with.

const (
	// FontKindBody means the segment should be rendered with the body font.
	FontKindBody FontKind = iota
	// FontKindSymbols means the segment should be rendered with the symbols fallback font.
	FontKindSymbols
	// FontKindEmoji means the segment should be rendered with the emoji fallback font.
	FontKindEmoji
)

type TextSegment added in v0.0.3

type TextSegment struct {
	Text string
	Kind FontKind
}

TextSegment is a contiguous run of text that should be rendered with a single font family. The renderer switches fonts between segments.

func SegmentText added in v0.0.3

func SegmentText(bodyFont, symbolsFont, emojiFont []byte, text string) []TextSegment

SegmentText splits text into segments tagged with the font that can render them. It checks each rune against the body font first, then the symbols font, and falls back to text substitution if neither font has the glyph.

Adjacent runes using the same font are coalesced into a single segment.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL