printout

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package printout is the document an engine produces and a renderer consumes: pages of absolutely-positioned marks in paint order.

Nothing in a printout is evaluable. Every expression has been evaluated, every box resolved to absolute coordinates, every string wrapped to lines, every barcode encoded to stripe widths, every font resolved to a specific file. A renderer needs no data, no template, and no expression evaluator.

Index

Constants

View Source
const (
	WarnOverflow = "overflow"
	WarnGlyph    = "glyph"
	WarnFont     = "font"
)

Warning kinds.

View Source
const Version = 1

Version is the format version this package reads and writes.

Variables

This section is empty.

Functions

This section is empty.

Types

type Barcode

type Barcode struct {
	Kind     string  `json:"kind"`
	Box      Box     `json:"box"`
	Type     string  `json:"type"`
	Value    string  `json:"value"`
	Module   float64 `json:"module"`
	Vertical bool    `json:"vertical"`
	// Ink is the bar colour. Always present, and "#000000" unless the
	// template asked for another.
	Ink string `json:"ink"`
	// Paper is the fill painted behind the whole symbol, quiet zones
	// included. Absent leaves whatever is underneath showing, which
	// is what a template that says nothing about the background gets.
	Paper *string `json:"paper,omitempty"`
	// Stripes is a flat array for a 1-D type;
	// Rows is an array of rows for a 2-D one.
	// Exactly one is present. Both alternate light and dark
	// starting with light, so index 0 is a light run in every case.
	Stripes []int   `json:"stripes,omitempty"`
	Rows    [][]int `json:"rows,omitempty"`
}

Barcode is encoded stripe geometry, in modules.

func NewBarcode

func NewBarcode() *Barcode

NewBarcode builds a barcode mark with its kind set and black ink, which is what a template that names no colour means.

func (*Barcode) MarkKind

func (barcode *Barcode) MarkKind() string

MarkKind names the mark.

type Blob

type Blob struct {
	// Encoding is "base64" for binary, absent for literal text.
	Encoding string `json:"encoding,omitempty"`
	Content  string `json:"content"`
}

Blob is a shared piece of content, stored once however many marks read it.

type Box

type Box struct {
	Left   float64 `json:"x"`
	Top    float64 `json:"y"`
	Width  float64 `json:"width"`
	Height float64 `json:"height"`
}

Box is an absolute rectangle, with the top-left corner at x, y measured from the top-left of the page. Y grows downward.

type FontEntry

type FontEntry struct {
	Name      string `json:"name"`
	Size      int    `json:"size"`
	Bold      bool   `json:"bold"`
	Italic    bool   `json:"italic"`
	Underline bool   `json:"underline"`
	// Requested is the template's typeface. A font node that named
	// a file or data instead has no typeface to record, so this is
	// absent and ResolvedBy is "explicit".
	Requested string `json:"requested,omitempty"`
	// ResolvedFile is relative to the printout when the template named it,
	// and absolute -- as opened -- when the engine found it on the host.
	ResolvedFile string `json:"resolvedFile,omitempty"`
	// ResolvedData names a header data entry, for an embedded font.
	ResolvedData string `json:"resolvedData,omitempty"`
	// ResolvedIndex is the face's position inside a font collection,
	// absent for the ordinary single-face file. A .ttc holds several
	// faces and the file name alone does not say which one was measured.
	ResolvedIndex int    `json:"resolvedIndex,omitempty"`
	ResolvedFace  string `json:"resolvedFace"`
	ResolvedBy    string `json:"resolvedBy"`
	// contains filtered or unexported fields
}

FontEntry records a font that was actually measured, and how it was found.

func (FontEntry) ResolvedPath

func (entry FontEntry) ResolvedPath() string

ResolvedPath returns a font entry's file as an absolute path, resolved against wherever the printout was read from.

func (*FontEntry) SetResolvedPath

func (entry *FontEntry) SetResolvedPath(abs string, templateNamed bool)

SetResolvedPath records where a template-named font was found. Provenance decides what the writer emits: a path the template named travels with the printout, one the engine discovered is written as it was opened.

type Header struct {
	SR          int              `json:"sr"`
	Kind        string           `json:"kind"`
	Report      *ReportMeta      `json:"report,omitempty"`
	Built       string           `json:"built"`
	Engine      string           `json:"engine"`
	StrictFonts bool             `json:"strictFonts"`
	Pages       int              `json:"pages"`
	GroupRuns   map[string]int   `json:"groupRuns,omitempty"`
	GroupKeys   map[string]int   `json:"groupKeys,omitempty"`
	Page        PageGeometry     `json:"page"`
	Fonts       []FontEntry      `json:"fonts"`
	Data        map[string]*Blob `json:"data"`
	Warnings    []Warning        `json:"warnings,omitempty"`
}

Header is the printout's first line.

type Image

type Image struct {
	Kind string `json:"kind"`
	Box  Box    `json:"box"`
	Type string `json:"type"`
	Data string `json:"data,omitempty"`
	// File appears only for embed=#false.
	// The template named it, so it is written relative to the printout.
	File string `json:"file,omitempty"`
	Crop *Box   `json:"crop,omitempty"`
	// contains filtered or unexported fields
}

Image is a bitmap. Box is the final drawn rectangle and Crop names the source pixels that fill it, so a renderer needs no notion of fitting.

func NewImage

func NewImage() *Image

NewImage builds an image mark with its kind set.

func (*Image) MarkKind

func (image *Image) MarkKind() string

MarkKind names the mark.

func (*Image) ResolvedPath

func (image *Image) ResolvedPath() string

ResolvedPath returns an image mark's file as an absolute path.

func (*Image) SetFile

func (image *Image) SetFile(abs string)

SetFile records a referenced image's resolved location.

type Line

type Line struct {
	Kind      string  `json:"kind"`
	Box       Box     `json:"box"`
	Width     float64 `json:"width"`
	Dash      string  `json:"dash"`
	Color     string  `json:"color"`
	Backslant bool    `json:"backslant"`
}

Line runs from the box's top-left corner to its bottom-right, or bottom-left to top-right when Backslant is set.

func NewLine

func NewLine() *Line

NewLine builds a line mark with its kind set.

func (*Line) MarkKind

func (line *Line) MarkKind() string

MarkKind names the mark.

type Mark

type Mark interface {
	// MarkKind names the mark, matching its "kind" field.
	MarkKind() string
}

Mark is one drawn thing.

type Outline

type Outline struct {
	Kind   string  `json:"kind"`
	Title  string  `json:"title"`
	Level  int     `json:"level"`
	Name   string  `json:"name,omitempty"`
	Closed bool    `json:"closed"`
	Left   float64 `json:"x"`
	Top    float64 `json:"y"`
}

Outline is a document outline entry. It names a scroll position rather than a region, so it carries a point instead of a box.

func NewOutline

func NewOutline() *Outline

NewOutline builds an outline mark with its kind set.

func (*Outline) MarkKind

func (outline *Outline) MarkKind() string

MarkKind names the mark.

type Page

type Page struct {
	Kind   string  `json:"kind"`
	Number int     `json:"number"`
	Width  float64 `json:"width,omitempty"`
	Height float64 `json:"height,omitempty"`
	// The margins are pointers because zero is a real margin:
	// a page flush to the paper edge under a header that insets
	// is an override, and an omitted number could not say so.
	LeftMargin   *float64 `json:"leftMargin,omitempty"`
	RightMargin  *float64 `json:"rightMargin,omitempty"`
	TopMargin    *float64 `json:"topMargin,omitempty"`
	BottomMargin *float64 `json:"bottomMargin,omitempty"`
	Marks        []Mark   `json:"marks"`
}

Page is one page of marks.

The size and the margins are the header's, except where this page overrides them: a subreport that paginates itself may run at a page size and inset of its own, and its pages carry the difference.

func (*Page) Geometry

func (page *Page) Geometry(header PageGeometry) PageGeometry

Geometry is the page's size and margins: the header's, with whatever the page overrides applied.

func (*Page) SetGeometry

func (page *Page) SetGeometry(want, header PageGeometry)

SetGeometry records what this page runs at, writing only the parts that differ from the document default.

type PageGeometry

type PageGeometry struct {
	Width        float64 `json:"width"`
	Height       float64 `json:"height"`
	LeftMargin   float64 `json:"leftMargin"`
	RightMargin  float64 `json:"rightMargin"`
	TopMargin    float64 `json:"topMargin"`
	BottomMargin float64 `json:"bottomMargin"`
}

PageGeometry is a page's size and margins, in points.

type Printout

type Printout struct {
	Header Header
	Pages  []*Page
}

Printout is a whole document.

The in-memory structure is the primary artifact: the engine hands it to a renderer directly, and serializes only when asked.

func ReadCBOR

func ReadCBOR(reader io.Reader, dir string) (*Printout, error)

ReadCBOR reads a printout from a CBOR sequence.

func ReadFile

func ReadFile(path string) (*Printout, error)

ReadFile reads a printout, choosing the encoding from the extension.

func ReadNDJSON

func ReadNDJSON(reader io.Reader, dir string) (*Printout, error)

ReadNDJSON reads a printout back.

A relative path in the document resolves against dir, the directory the printout was read from; an absolute one is used as it stands. So a renderer needs no base directory and the header carries none.

func (*Printout) AddWarning

func (doc *Printout) AddWarning(kind, node string, record int, message string)

AddWarning records a document warning in the header.

func (*Printout) HasWarning

func (doc *Printout) HasWarning(kind string) bool

HasWarning reports whether the header carries a warning of a kind.

func (*Printout) Validate

func (doc *Printout) Validate() error

Validate checks the invariants of doc/printout.md#invariants. A valid printout satisfies all of them; the test suite asserts this on every printout it produces.

The numbers in the comments below are that list's numbering, so the checks read out of order: they are placed where the walk has what they need rather than in the order the document states them. Invariant 4 appears twice, once for an image's data and once for a font's.

func (*Printout) WriteCBOR

func (doc *Printout) WriteCBOR(writer io.Writer, dir string) error

WriteCBOR writes the same objects as a CBOR sequence, in the same order.

func (*Printout) WriteFile

func (doc *Printout) WriteFile(path string) error

WriteFile writes the printout, choosing the encoding from the extension: .srp.cbor is CBOR, anything else NDJSON.

func (*Printout) WriteNDJSON

func (doc *Printout) WriteNDJSON(writer io.Writer, dir string) error

WriteNDJSON writes the printout as one JSON object per line: the header, then one line per page.

dir is the directory the printout is being written to, which is what template-named paths are made relative to. An empty dir stands for the process's working directory, which is what a pipe or an in-memory hand-off gets.

type Rectangle

type Rectangle struct {
	Kind   string  `json:"kind"`
	Box    Box     `json:"box"`
	Width  float64 `json:"width"`
	Dash   string  `json:"dash"`
	Stroke *string `json:"stroke,omitempty"`
	Fill   *string `json:"fill,omitempty"`
	Radius float64 `json:"radius,omitempty"`
}

Rectangle is a box, stroked and filled independently. An absent Stroke means no outline is drawn regardless of Width; an absent Fill leaves the interior untouched.

func NewRectangle

func NewRectangle() *Rectangle

NewRectangle builds a rectangle mark with its kind set.

func (*Rectangle) MarkKind

func (rect *Rectangle) MarkKind() string

MarkKind names the mark.

type ReportMeta

type ReportMeta struct {
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	Version     string `json:"version,omitempty"`
	Author      string `json:"author,omitempty"`
}

ReportMeta is what the template's report node carried. Omitted fields are absent, not null.

type Text

type Text struct {
	Kind              string   `json:"kind"`
	Box               Box      `json:"box"`
	Font              string   `json:"font"`
	Color             string   `json:"color"`
	Align             string   `json:"align"`
	Leading           float64  `json:"leading"`
	Lines             []string `json:"lines"`
	LastLineJustified bool     `json:"lastLineJustified,omitempty"`
}

Text is wrapped text. A renderer must not re-wrap it.

func NewText

func NewText() *Text

NewText builds a text mark with its kind set.

func (*Text) MarkKind

func (text *Text) MarkKind() string

MarkKind names the mark.

type Warning

type Warning struct {
	// Kind is "overflow", "glyph", or "font".
	Kind    string `json:"kind"`
	Node    string `json:"node,omitempty"`
	Record  int    `json:"record,omitempty"`
	Message string `json:"message"`
}

Warning is a diagnostic about the document, recorded in the header so an affected printout is identifiable from the artifact.

type Xref

type Xref struct {
	Kind    string `json:"kind"`
	Box     Box    `json:"box"`
	Type    string `json:"type"`
	Target  string `json:"target"`
	Caption string `json:"caption,omitempty"`
	Marks   []Mark `json:"marks"`
}

Xref is a link region. Its nested marks use page coordinates, so a renderer can flatten them recursively and draw in one pass; the box is purely a hit region.

func NewXref

func NewXref() *Xref

NewXref builds an xref mark with its kind set.

func (*Xref) MarkKind

func (xref *Xref) MarkKind() string

MarkKind names the mark.

Jump to

Keyboard shortcuts

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