Skip to content

Nodes#

A node is the smallest piece of information. There are different kinds of node, for example a glyph node contains a single visual representation of a letter such as the letter “A”.

Each glyph can be stored in a linked list together with other nodes. These linked lists are also called “node list”. These node lists can be packed in a horizontal box (hbox) or a vertical box (vbox). These packed lists are nodes themselves and can be part of a linked list. So during typesetting, a page that is ready to be placed in the PDF contains a vertical list which contains a list of nodes, usually paragraphs with lines of text and images, each placed in a vertical or a horizontal list.

Common traits of nodes#

Nodes that take up some space usually have a width and a height but also a depth.

The height is the size of the box of the baseline and the depth below the base line. When placing nodes next to each other, the baseline of each node is taken for alignment.

Each node has methods to chain the nodes in a linked list

Method Description
Next() Node Get the next node.
Prev() Node Get the previous node.
SetNext(Node) Set the next pointer of the current node so that it points to the given node. The prev pointer of the argument is not changed.
SetPrev(Node) Set the prev pointer of the current node so that it points to the given node. The next pointer of the argument is not changed.
GetID() int Return the internal id. Each node in the document has its own unique id.
Type() Type Return the node type.
Name() string Return a string representation of the node type.
Copy() Node Create a deep copy of of the node.

List of nodes#

Node Description
Disc A hyphenation point. This node should be surrounded by glyph nodes.
Glue The glue node is a space between other nodes which has a natural width, a stretchability and a shrinkability.
Glyph A glyph node contains information about a font and a code point (the font specific glyph id).
HList Horizontal lists contain a pointer to a node list which items are placed horizontally next to each other.
Image An image is a rectangular area that represents a PNG, JPEG or a PDF file.
Kern A kern is inserted between two glyphs or other nodes to bring them closer together or further apart.
Lang The lang node contains information about the language which is used to hyphenate words behind the lang node.
Penalty The penalty node (in the range -10000 to +10000 inserts a possible line break. The values +/- 10000 are considered to be infinity. The higher the value is, the more likely a line break will be inserted.
Rule A rule contains a black box.
StartStop A paired set of nodes that temporarily inserts a color change or a hyperlink.
VList Vertical lists contain a node list which items are stacked on top of each other. The first item is placed at the top the next item below the first and so on.

There are a few helper functions that deal with node lists:

Node Description
func CopyList(nl Node) Node Make a deep copy of the node at nl. That means if the node contains a list of other nodes, these nodes will be deep-copied as well.
func InsertAfter(head, cur, insert Node) Node Inserts insert after cur at the list starting with head.
func InsertBefore(head, cur, insert Node) Node Inserts insert before cur at the list starting with head. The (perhaps new) head is returned.
func Tail(nl Node) Node Return the last element of the list at nl.

Each node has the following additional fields:

Field Type Description
ID int An internal unique identifier which gets created when creating a node with the new function (NewGlyph() for example).
Attributes H A hash (any/any) for user defined values.

Disc#

type Disc struct {
    Pre     Node
    Post    Node
    Replace Node
    Penalty int // Added to the hyphen penalty
}

Disc nodes are inserted during the hyphenation phase.

Glue#

A glue node is a vertical or horizontal space, depending on the surrounding box. In a vbox, the glue is a vertical space and otherwise it is a horizontal space. It consists of a fixed width portion and a (perhaps zero) shrinkability and stretchability. Each value of shrink or stretch can have different orders of infinity. The highest infinity wins.

type Glue struct {
    Subtype      GlueSubtype
    Width        bag.ScaledPoint // The natural width of the glue.
    Stretch      bag.ScaledPoint // The stretchability of the glue, where width plus stretch = maximum width.
    Shrink       bag.ScaledPoint // The shrinkability of the glue, where width minus shrink = minimum width.
    StretchOrder GlueOrder       // The order of infinity of stretching.
    ShrinkOrder  GlueOrder       // The order of infinity of shrinking.
}

Glyph#

type Glyph struct {
    Font *font.Font
    // The font specific glyph id
    Codepoint int
    // A codepoint can contain more than one rune, for example a fi ligature
    // contains f + i. Filling the components string is optional.
    Components string
    // The advance width of the box.
    Width bag.ScaledPoint
    // The height is the length above the base line.
    Height bag.ScaledPoint
    // The Depth is the length below the base line. For example the letter g has
    // a depth > 0.
    Depth bag.ScaledPoint
    // Vertical displacement. Positive values move the glyph towards the top of
    // the page.
    YOffset bag.ScaledPoint
    // This allows the glyph to be part of word hyphenation.
    Hyphenate bool
}

The component of the glyph node is a textual representation of the glyph and does not have to be exact.

HList#

type HList struct {
    Width     bag.ScaledPoint
    Height    bag.ScaledPoint
    Depth     bag.ScaledPoint
    Badness   int
    GlueSet   float64         // The ratio of the glue. Positive means stretching, negative shrinking.
    GlueSign  uint8           // 0 = normal, 1 = stretching, 2 = shrinking
    GlueOrder GlueOrder       // The level of infinity
    Shift     bag.ScaledPoint // The displacement perpendicular to the progressing direction. Not used.
    List      Node            // The list itself.
    VAlign    VerticalAlignment
}

Image#

type Image struct {
    Width  bag.ScaledPoint
    Height bag.ScaledPoint
    Img    *image.Image
}

Kern#

type Kern struct {
    // The displacement in progression direction.
    Kern bag.ScaledPoint
}

Lang#

type Lang struct {
    Lang *lang.Lang // The language setting  for the following nodes.
}

Penalty#

type Penalty struct {
    Penalty int             // Value
    Width   bag.ScaledPoint // Width of the penalty
}

Rule#

type Rule struct {
    // PDF code that gets output before the rule.
    Pre string
    // PDF Code after drawing the rule.
    Post string
    // Hide makes the rule invisible, no colored area is drawn. Used to make Pre
    // and Post appear in the output with the given dimensions.
    Hide   bool
    Width  bag.ScaledPoint
    Height bag.ScaledPoint
    Depth  bag.ScaledPoint
}

Example code#

Let's assume that you have a node list where the field head points to the first node of the list. You can now insert a new rule node:

r := node.NewRule()
r.Pre = "0.6 g"
r.Post = "0 g"
// wd, ht = 0.5pt, 2pt
r.Width = bag.ScaledPointFromFloat(0.5)
r.Height = bag.ScaledPointFromFloat(2)
head = node.InsertAfter(head, cur, r)

StartStop#

type StartStop struct {
    Action          ActionType
    StartNode       *StartStop
    Position        PDFDataOutput
    ShipoutCallback StartStopFunc
    // Value contains action specific contents
    Value any
}

VList#

type VList struct {
    Width    bag.ScaledPoint
    Height   bag.ScaledPoint
    Depth    bag.ScaledPoint
    GlueSet  float64
    GlueSign uint8
    ShiftX   bag.ScaledPoint
    List     Node
}