Documentation
¶
Overview ¶
Package layout is a block-and-inline flow engine. Block boxes stack vertically honouring margins, padding and width; inline content (text runs and inline elements) is broken into lines within the containing block at a given viewport width using measured word advances supplied through a Measurer. The geometry is deterministic and, given a fake Measurer, exactly testable without any font machinery.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BuildIndex ¶
BuildIndex walks a laid-out box tree and returns, for every element node, its used border-box rectangle in document coordinates. Block-level elements take their box rect directly (authoritative); inline-level elements — which produce InlineItems inside line boxes rather than their own Box — take the union of their fragments' rects (and of any inline descendants). This is the geometry the JS DOM binding reads back through getBoundingClientRect / offset* / getComputedStyle, so scripts that decide layout from measured metrics (responsive nav, MediaWiki's mw.loader sidebar collapse) see real numbers.
Types ¶
type Box ¶
type Box struct {
Node *dom.Node
Style *css.Style
X, Y, W, H float64
ContentX, ContentY, ContentW, ContentH float64
Children []*Box
Lines []*LineBox
Anonymous bool
// Float marks a box taken out of normal flow (float:left/right). Floated
// boxes are painted like blocks but positioned by the float algorithm.
Float css.Float
// Position records the box's CSS position. Relative/sticky boxes remain in
// flow but are shifted at the end of layout; absolute/fixed boxes are laid
// out out of flow and appended to the root box (painted after in-flow
// content) with their coordinates already resolved to document space.
Position css.Position
// Marker is the list-item marker box (bullet or ordinal), non-nil only on a
// display:list-item box whose list-style-type is not `none`. Its coordinates
// are in document space, positioned relative to this box's content box.
Marker *Marker
}
Box is a laid-out block box. X,Y,W,H describe the border box (which, with no borders in Phase 0, equals the padding box that a background fills). Content* describe the content box. A box either has block Children or holds inline Lines (an anonymous box may hold Lines and carry no Node).
func LayoutDocument ¶
func LayoutDocument(root *dom.Node, sm css.StyleMap, viewportW float64, m Measurer, imgSize map[*dom.Node][2]float64) (*Box, float64)
LayoutDocument lays out the element subtree at root within a viewport of width viewportW (CSS pixels), returning the root Box and the total content height. imgSize provides intrinsic image dimensions keyed by <img> node; it may be nil (images then fall back to width/height attributes).
type InlineItem ¶
type InlineItem struct {
Text string
Style *css.Style
// Node is the element that directly produced this item — the immediate
// parent element of a text run, or the <img> element of an image item. It
// lets a consumer walk up the DOM (e.g. to the nearest <a href> ancestor)
// without re-deriving document structure from geometry. It is nil only for
// synthetic items with no originating element (a forced <br> carries its
// own element; anonymous runs never occur here).
Node *dom.Node
Width float64 // advance of the word / width of the image
SpaceBefore float64 // width of a space in this item's font
Ascent float64
LineHeight float64
Image *dom.Node // non-nil when this item is an <img>
ImgW, ImgH float64
LineBreak bool // a <br>: forces the current line to end
X, Y float64
}
InlineItem is one atom of inline content: a word, an image, or a forced line break. Positions (X,Y = top-left) are filled during line layout.
type LineBox ¶
type LineBox struct {
X, Y, W, H float64
Items []*InlineItem
}
LineBox is one line of inline content with its positioned items.
func WrapItems ¶
func WrapItems(items []*InlineItem, maxW float64) []*LineBox
WrapItems greedily breaks a sequence of inline items into lines so that each line's used width does not exceed maxW, inserting a per-item SpaceBefore between adjacent items on the same line. A single item wider than maxW is placed alone on its own line (overflow). A LineBreak item ends the current line (and is not itself placed). This is the pure, exactly-testable core of inline layout; positioning and heights are applied by the caller.
type Marker ¶
type Marker struct {
Type css.ListStyleType
Style *css.Style
X, Y, W, H float64
Ascent float64
Text string
}
Marker is a laid-out list-item marker. For a bullet type (disc/circle/square) X,Y,W,H is the glyph's square bounding box. For the decimal type, Text is the ordinal string ("1.", "2.", …), X is its pen origin, Y the top of its line box and Ascent the baseline offset; W is the text advance (H unused). Style supplies the marker's colour and, for decimal, its font face.
type Measurer ¶
type Measurer interface {
// Measure returns the advance width in pixels of text in the given family,
// size, weight and style (italic).
Measure(text string, fam css.FontFamily, sizePx float64, weight int, italic bool) float64
// Metrics returns the ascent (baseline offset from the top) and the line
// height in pixels for a family/size/weight/style.
Metrics(fam css.FontFamily, sizePx float64, weight int, italic bool) (ascent, lineHeight float64)
}
Measurer supplies text metrics to the layout engine. The real implementation lives in the paint package (backed by go-opentype); tests inject a fake.