render

package
v0.0.0-...-2f6e621 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 35 Imported by: 0

Documentation

Overview

The CSS box primitives: per-corner rounded fills, rounded border rings with per-side widths and colors, angled multi-stop linear gradients, and box shadows with offset, spread, blur, and inset — everything a CSS box paints behind its content. Every primitive is a per-pixel signed-distance coverage pass at the device scale and blends through the single blend site, so PushAlpha and PushBrightness apply by construction.

Package render holds pure drawing and damage primitives. Nothing in here touches Wayland; everything is unit-testable.

The shadow raster cache. Canvas.Shadow paints a blurred rounded-rect silhouette; the expensive half of that is the coverage field - the Gaussian kernel and the per-pixel signed-distance sweep - and it depends only on (rect size, corner radius, blur, device scale), never on the color or what is underneath. This file builds each field once and hands the cached raster back, so a hover twitch that repaints the same floating surface every frame re-blends the ring but never re-Gaussians it. The counters double as the paint-count proof: a second identical Shadow must be a hit, not a rebuild.

Index

Constants

View Source
const Ellipsis = "…"

Ellipsis is the mark a truncated text carries where it was cut.

Variables

View Source
var Identity = Affine{A: 1, D: 1}

Identity is the affine map that moves nothing.

Functions

func AlignedPen

func AlignedPen(sh *ShapedText, box Rect, h Alignment, d text.Direction) (x, baseline int)

AlignedPen is where an aligned draw puts sh's pen inside box: the alignment mirrored for a right-to-left line, the line centered vertically on its baseline. Decorations and carets drawn after a DrawAligned use it to land on the painted text.

func DecodeImage

func DecodeImage(data []byte) (image.Image, error)

DecodeImage decodes image bytes: an animated GIF or APNG to an *Animation, anything else (PNG, JPEG, GIF, still WebP) to a still image. Animated WebP is not decoded: golang.org/x/image/webp, the pure-Go decoder, reads still images only.

func EllipsizeText

func EllipsizeText(f Font, text string, mode EllipsizeMode, maxWidth, px float64) string

EllipsizeText shortens text so its advance fits maxWidth, cutting at mode and inserting an ellipsis; see Typeface.Ellipsize. Package-level so any Font - a lone typeface or a fallback chain - truncates through the same code path the methods use.

func FixtureFontData

func FixtureFontData() []byte

FixtureFontData returns the bytes of the bundled Cantarell Regular fixture font (SIL Open Font License 1.1; the license text ships in testdata/LICENSE-Cantarell.txt). It is the single face every golden snapshot is shaped with.

func FixtureHebrewFontData

func FixtureHebrewFontData() []byte

FixtureHebrewFontData returns the bytes of the bundled Hebrew fixture face; see render/testdata/README.md for why a second face exists.

func NRGBA

func NRGBA(data []byte, stride, width, height int) *image.NRGBA

NRGBA converts a Canvas-format pixel buffer — ARGB8888 premultiplied in wl_shm byte order — into a straight-alpha image.NRGBA: exactly the pixel representation the PNG goldens store, so encode, decode, and compare all see the same bytes and the comparison is exact. stride is in bytes; the returned image's rows are tight.

func Resample

func Resample(src image.Image, srcRect image.Rectangle, dstW, dstH int) *image.RGBA

Resample scales srcRect of src into a fresh dstW x dstH RGBA with the CatmullRom kernel. Cubic resampling is what keeps fractional and non-integer down- and upscales from the blockiness of a nearest-neighbor pass (stubbedev/gelm#14); the canvas's own image drawing is nearest-neighbor and must never see unresampled pixels.

func ScaleRect

func ScaleRect(srcW, srcH, boxW, boxH int, s ImageScale) (src image.Rectangle, dstW, dstH int)

ScaleRect resolves a scaling policy for a srcW x srcH image into a boxW x boxH box. Both sizes are in the same units - widget.Image feeds device pixels so the result stays crisp at fractional scales. It returns the source rectangle to sample and the size to resample it into; drawing that resample centered in the box is the whole policy. An empty result means a zero-sized input.

func Stride

func Stride(widthPx int) int

Stride returns the row stride in bytes for a width in pixels (ARGB8888).

func WrapText

func WrapText(f Font, text string, maxWidth, px float64) []string

WrapText breaks text into lines of at most maxWidth pixels; see Wrap. Package-level so any Font wraps through the same code path.

Types

type Affine

type Affine struct{ A, B, C, D, E, F float64 }

Affine is a 2-D affine map in device pixels: (x, y) goes to (A·x + C·y + E, B·x + D·y + F). The zero value maps everything to the origin; Identity leaves points where they are.

func Rotate

func Rotate(deg float64) Affine

Rotate is the map rotating about the origin by deg degrees, clockwise on screen (y grows downward), as a GSK snapshot rotation does.

func Scale

func Scale(sx, sy float64) Affine

Scale is the map scaling about the origin.

func Translate

func Translate(dx, dy float64) Affine

Translate is the map moving by (dx, dy).

func (Affine) About

func (m Affine) About(px, py float64) Affine

About is m applied about the pivot (px, py) instead of the origin.

func (Affine) Apply

func (m Affine) Apply(x, y float64) (float64, float64)

Apply maps the point (x, y).

func (Affine) Invert

func (m Affine) Invert() (Affine, bool)

Invert returns the inverse map; false when m collapses an axis.

func (Affine) MapBounds

func (m Affine) MapBounds(r Rect) Rect

MapBounds is the smallest pixel rect covering r's image under m.

func (Affine) Mul

func (m Affine) Mul(n Affine) Affine

Mul is m∘n: the map applying n first, then m. A chain of snapshot operations t1, t2, t3 on a point is t1.Mul(t2).Mul(t3).

type Alignment

type Alignment uint8

Alignment selects how a drawn run is positioned inside its box.

const (
	AlignStart Alignment = iota
	AlignCenter
	AlignEnd
)

Text alignments: start (left for LTR lines), center, end.

type Animation

type Animation struct {
	Frames []*image.RGBA
	Delays []time.Duration
	Loops  int
}

Animation is a decoded animated image (GIF, APNG): every frame fully composited over the canvas, how long each shows, and how many times the sequence plays (0: forever). It is an image.Image as its first frame, so every still-image path - sizing, a static paint, a cache - takes it unchanged; an animating painter steps through Frames.

func (*Animation) At

func (a *Animation) At(x, y int) color.Color

At implements image.Image: the first frame.

func (*Animation) Bounds

func (a *Animation) Bounds() image.Rectangle

Bounds implements image.Image: the canvas.

func (*Animation) ColorModel

func (a *Animation) ColorModel() color.Model

ColorModel implements image.Image (the first frame's).

func (*Animation) PixelBytes

func (a *Animation) PixelBytes() int

PixelBytes is the frames' combined pixel cost, what a byte-budget cache charges for the animation.

type BoxShadow

type BoxShadow struct {
	X, Y, Blur, Spread int
	Color              Color
	Inset              bool
}

BoxShadow is one CSS box-shadow layer: an offset, a blur radius (the Gaussian spans two sigmas of it, CSS's convention), a spread, and whether it paints inside the box instead of outside.

func (BoxShadow) Extent

func (s BoxShadow) Extent() Insets

Extent returns how far an outer shadow paints beyond its box, per side; an inset shadow never paints outside. Callers owe these pixels damage.

type Canvas

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

Canvas paints into a raw ARGB8888 premultiplied pixel buffer: the exact format of a wl_shm buffer at any scale. All drawing clips to the intersection of the requested rect, the canvas bounds, and any clip set with PushClip, and blends through the opacity set with PushAlpha.

The canvas carries a device scale: a rational number of device (buffer) pixels per logical pixel - 240/120 is 2x, 150/120 is the fractional 1.25x. Primitive arguments (FillRect, RoundedRect, text, ...) are in logical pixels and land on device pixels rounded outward, so a logical rect fully covers the device area it spans; text is shaped at its logical size and rasterized at the device scale, which keeps it crisp at any factor. PushClip takes a logical rect like every primitive; the bounds returned by Rect and the explicit device bridge (MapRect, ClearDevice, FillRectDevice, PushClipDevice) are in device pixels.

func New

func New(data []byte, stride, width, height int) *Canvas

New returns a canvas over data: height rows of stride bytes holding width ARGB8888 pixels each, at device scale 1 (one device pixel per logical pixel).

func NewScaled

func NewScaled(data []byte, stride, width, height, num, denom int) *Canvas

NewScaled returns a canvas over data at the given device scale: num device pixels per denom logical pixels (240/120 doubles). width and height are the buffer's device size. It panics on a non-positive scale, which is a programming error, not a runtime condition.

func (*Canvas) Arc

func (c *Canvas) Arc(cx, cy, radius, width, start, sweep float64, col Color)

Arc strokes a circular arc of the logical circle centered at (cx, cy) with the given radius (to the stroke's middle) and stroke width, clockwise from start through sweep radians (0 is three o'clock, -π/2 is twelve). Caps are round, like cairo's LINE_CAP_ROUND; a sweep of 2π or more is the whole circle. Anti-aliased by per-pixel signed distance at the device scale.

func (*Canvas) BeginOverlays

func (c *Canvas) BeginOverlays()

BeginOverlays arms the frame's top layer: until FlushOverlays, Overlay defers its paints instead of running them in place. A window arms it around painting its tree, so a widget that hangs content outside its own bounds (an open dropdown list) paints above every later sibling, as a popover would.

func (*Canvas) BorderRect

func (c *Canvas) BorderRect(r Rect, width int, col Color)

BorderRect blends col over a hollow rect of the given logical thickness. The stroke grows inward from the rect edges.

func (*Canvas) BoxShadow

func (c *Canvas) BoxShadow(r Rect, radii Corners, s BoxShadow)

BoxShadow paints one CSS box-shadow layer for the box r with the given corner radii. An outer shadow is the box offset and grown by the spread, blurred, and clipped to outside the box itself (so a translucent box never shows its own shadow through); an inset shadow fills the box's inside except the offset, spread-shrunk hole, blurred at the hole's edge. The blur is Gaussian with sigma half the blur radius, evaluated per pixel from the silhouette's signed distance.

func (*Canvas) Clear

func (c *Canvas) Clear(r Rect, col Color)

Clear overwrites the logical rect with col, ignoring what is underneath. ClearDevice is the device-space counterpart for callers that already hold mapped rects.

func (*Canvas) ClearDevice

func (c *Canvas) ClearDevice(r Rect, col Color)

ClearDevice overwrites the device-pixel rect r with col, ignoring what is underneath. Unlike Clear it applies no logical mapping: it is the bridge for frame pipelines that track damage in device pixels.

func (*Canvas) Composite

func (c *Canvas) Composite(l *Layer, src Rect, m Affine, alpha float64)

Composite draws the src device rect of l onto c through m (layer device pixels to canvas device pixels), bilinearly filtered, blended through c's opacity times alpha and clipped to c's clip. Pixels of l outside src count as transparent, so the drawn edge antialiases. A whole-pixel translation copies without filtering.

func (*Canvas) DeviceScale

func (c *Canvas) DeviceScale() (num, denom int)

DeviceScale returns the canvas's device scale as a rational: num device pixels per denom logical pixels.

func (*Canvas) DrawImage

func (c *Canvas) DrawImage(img image.Image, x, y int)

DrawImage blends img onto the canvas, scaled from its natural (logical) size to the device rect its logical placement spans.

func (*Canvas) DrawImageCover

func (c *Canvas) DrawImageCover(img image.Image, r Rect, radii Corners)

DrawImageCover blends img onto the canvas scaled to COVER r: the image scales uniformly until it fills the rect, centered, the overflow cropped (CSS background-size: cover), the whole masked by the rounded rect.

func (*Canvas) DrawImageCoverImage

func (c *Canvas) DrawImageCoverImage(ic *Icon, r Rect, radii Corners)

DrawImageCoverImage is DrawImageCover for an Icon's pixels.

func (*Canvas) DrawImageDevice

func (c *Canvas) DrawImageDevice(img image.Image, x, y int)

DrawImageDevice blends img onto the canvas one-to-one in device pixels, its top-left corner at (x, y). It is the device-space counterpart of DrawImage: rasters that were already resampled for the device rect they cover - widget.Image's cache - must land without a second scale, which DrawImage's nearest-neighbor logical mapping would apply at any device scale other than 1.

Opacity (PushAlpha) modulates here, at blit time, and nowhere earlier: the cached rasters are premultiplied and shared by every consumer, so baking a factor into them would double-multiply the next frame and bleed into widgets fading independently. Multiplying the premultiplied channels together (blend then modulate) keeps a modulated raster premultiplied, exactly like the AA coverage ramps.

func (*Canvas) FillPath

func (c *Canvas) FillPath(p *Path, col Color)

FillPath fills the path's subpaths with col, anti-aliased, under the clip and the pushed opacity. Overlapping subpaths fill once.

func (*Canvas) FillRect

func (c *Canvas) FillRect(r Rect, col Color)

FillRect blends col over the logical rect with source-over compositing.

func (*Canvas) FillRectDevice

func (c *Canvas) FillRectDevice(r Rect, col Color)

FillRectDevice blends col over the device-pixel rect with source-over compositing; the device counterpart of FillRect.

func (*Canvas) FinishFocus

func (c *Canvas) FinishFocus()

FinishFocus draws the focus ring if no container reached its widget (a container defined outside the kit, a subtree composited from a layer) and disarms it.

func (*Canvas) FlushOverlays

func (c *Canvas) FlushOverlays()

FlushOverlays runs the deferred top-layer paints in queue order (one queued while flushing runs too) and disarms the frame.

func (*Canvas) Layer

func (c *Canvas) Layer(old *Layer, region Rect) *Layer

Layer returns a layer the size and scale of c whose region (device pixels) is transparent and is the layer's clip; drawing lands only there. old's buffer is reused when it is the right size, so a layer kept across frames allocates once.

func (*Canvas) Line

func (c *Canvas) Line(x0, y0, x1, y1, width int, col Color)

Line blends col along the segment from logical (x0, y0) to (x1, y1) with the given thickness in logical pixels, anti-aliased with per-pixel signed-distance coverage at the device scale. Caps are round.

func (*Canvas) MapRect

func (c *Canvas) MapRect(r Rect) Rect

MapRect maps the logical rect r into device pixels on this canvas.

func (*Canvas) MarkFocus

func (c *Canvas) MarkFocus(key any, paint func(*Canvas))

MarkFocus arms the frame's focus ring: Painted draws it the moment key's widget finishes painting, so everything painted after it in tree order (a card over a list, a later sibling) covers it, as a widget's own outline would be covered. A nil key clears it.

func (*Canvas) Overlay

func (c *Canvas) Overlay(paint func(*Canvas))

Overlay paints on the frame's top layer: deferred to FlushOverlays while a frame is armed, in place otherwise (a subtree painted on its own has no later siblings to escape). The deferred paint runs under the frame's clip, not the caller's, so a scrolled container does not cut it, with the opacity in force now.

func (*Canvas) PaintGradient

func (c *Canvas) PaintGradient(r Rect, radii Corners, g Gradient)

PaintGradient fills r with g, clipped to its rounded outline (radii in logical pixels). Colors interpolate premultiplied between the stops. A linear gradient's line spans the box's corners along its angle, CSS's rule; radial and conic geometry sizes against the box.

func (*Canvas) Painted

func (c *Canvas) Painted(w any)

Painted reports that w finished painting: the containers call it after each child, drawing the armed focus ring after its widget.

func (*Canvas) PopAlpha

func (c *Canvas) PopAlpha(prev float64)

PopAlpha restores an opacity returned by PushAlpha.

func (*Canvas) PopBrightness

func (c *Canvas) PopBrightness(prev float64)

PopBrightness restores a factor returned by PushBrightness.

func (*Canvas) PopClip

func (c *Canvas) PopClip(prev Rect)

PopClip restores a clip returned by PushClip.

func (*Canvas) PushAlpha

func (c *Canvas) PushAlpha(a float64) float64

PushAlpha scales the opacity of everything painted until the matching PopAlpha: every blended primitive (FillRect, RoundedRect, gradients, Line, text, images) has its premultiplied color channels - color with the alpha, never the alpha alone - multiplied by a. It is the subtree-opacity primitive fades hang off: nested pushes multiply, and a zero push makes every blend a no-op without touching a pixel. a clamps to [0, 1], so a spring tween's overshoot saturates instead of over-brightening.

It returns the previous opacity; restore it with PopAlpha, the same save-and-restore shape as PushClip. Clear and ClearDevice are the one exception: they overwrite pixels rather than blend, so a faded subtree cannot punch transparent holes in its background.

func (*Canvas) PushBrightness

func (c *Canvas) PushBrightness(f float64) float64

PushBrightness multiplies the color channels of everything painted until the matching PopBrightness by f: CSS's filter: brightness(). Nested pushes multiply. Channels clamp at the pixel's alpha, so the result stays a valid premultiplied color. It returns the previous factor; restore it with PopBrightness.

func (*Canvas) PushClip

func (c *Canvas) PushClip(r Rect) Rect

PushClip narrows subsequent drawing to the intersection of the logical rect r, mapped to device pixels the way FillRect maps, and the current clip. It returns the previous clip; restore it with PopClip.

func (*Canvas) PushClipDevice

func (c *Canvas) PushClipDevice(r Rect) Rect

PushClipDevice is PushClip for a rect already in device pixels (a damage region, a layer's rect).

func (*Canvas) Rect

func (c *Canvas) Rect() Rect

Rect returns the full canvas bounds in device pixels.

func (*Canvas) ResetTouched

func (c *Canvas) ResetTouched() int

ResetTouched zeroes the drawn-pixel counter and returns the previous value.

func (*Canvas) RoundedBorder

func (c *Canvas) RoundedBorder(r Rect, radii Corners, widths Insets, col Color)

RoundedBorder strokes the ring between r's rounded outline and its inner edge, inset per side by widths: a CSS border. The inner corner radii shrink by the adjacent widths.

func (*Canvas) RoundedBorderSides

func (c *Canvas) RoundedBorderSides(r Rect, radii Corners, widths Insets, cols [4]Color)

RoundedBorderSides is RoundedBorder with a color per side (top, right, bottom, left). A ring pixel takes the color of the side it is relatively closest to, which splits the corners along their diagonals the way CSS borders join.

func (*Canvas) RoundedRect

func (c *Canvas) RoundedRect(r Rect, radius int, col Color)

RoundedRect blends col over a filled logical rect with corners rounded by radius logical pixels, anti-aliased with per-pixel signed-distance coverage. The rasterization runs at the device scale.

func (*Canvas) RoundedRectCorners

func (c *Canvas) RoundedRectCorners(r Rect, radii Corners, col Color)

RoundedRectCorners blends col over r with each corner rounded by its own radius, anti-aliased. Radii that overlap scale down together, per CSS.

func (*Canvas) Shadow

func (c *Canvas) Shadow(r Rect, cornerRadius, blur int, col Color)

Shadow blends a box shadow for the logical rect: the blurred silhouette of a rounded rect, centered on r (no spread), falling off with a precomputed Gaussian kernel. blur is the falloff radius in logical pixels. The shadow paints OUTSIDE r - full strength at the edges, tail gone past blur - so callers keep layout and hit-testing on r itself and owe the ring only damage. The coverage raster is cached per (rect size, radius, blur, device scale) in shadowRasterFor, so a hover twitch that repaints the same shadow re-blends the pixels but never re-Gaussians. Per-pixel coverage scales all four premultiplied channels exactly as RoundedRect's AA, and the draw blends through the PushAlpha stack like every primitive, so a fading surface fades its shadow with it.

func (*Canvas) Touched

func (c *Canvas) Touched() int

Touched returns the number of pixels written since the last ResetTouched (or since the canvas was created). Blends count even when their source color equals the destination.

type Chain

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

Chain shapes mixed-script text across faces: every rune goes to the first face that covers it, so a line mixing latin, CJK, and emoji renders instead of drawing .notdef boxes. The picks cache per rune, so repeated shapes pay one lookup per distinct rune. Like Typeface, a chain is not safe for concurrent use.

func FixtureChain

func FixtureChain() (*Chain, error)

FixtureChain returns a fresh fallback chain over the two bundled fixture faces — Latin and digits from Cantarell, Hebrew from Noto Sans Hebrew — the shape mixed-direction goldens pin.

func NewChain

func NewChain(primary *Typeface, fallback ...*Typeface) *Chain

NewChain returns a chain shaping with primary and, for runes it lacks, the first covering face of fallback. A nil primary panics here, naming the argument — the same nil-face contract the widget constructors enforce — instead of failing on the first Shape.

func (*Chain) Draw

func (c *Chain) Draw(cv *Canvas, s *ShapedText, x, baselineY int, col Color)

Draw paints a shaped line; see ShapedText.Draw.

func (*Chain) DrawAligned

func (c *Chain) DrawAligned(cv *Canvas, s string, box Rect, px float64, col Color, h Alignment) *ShapedText

DrawAligned draws text inside box with the given alignment; see Typeface.DrawAligned.

func (*Chain) DrawAlignedDir

func (c *Chain) DrawAlignedDir(cv *Canvas, s string, box Rect, px float64, col Color, h Alignment, d text.Direction) *ShapedText

DrawAlignedDir draws text inside box under base direction d; start and end mirror for a right-to-left base. See text.Direction.

func (*Chain) Ellipsize

func (c *Chain) Ellipsize(text string, maxWidth, px float64) string

Ellipsize shortens text to fit maxWidth; see Typeface.Ellipsize.

func (*Chain) Face

func (c *Chain) Face(r rune) *Typeface

Face returns the face rune r shapes with: the diagnostic view of the fallback decision, and a way for tests to pin which family a rune lands on.

func (*Chain) Primary

func (c *Chain) Primary() *Typeface

Primary is the chain's first face: the one variants resolve from.

func (*Chain) Shape

func (c *Chain) Shape(s string, px float64) *ShapedText

Shape splits text into runs of consecutive runes sharing a face and shapes each with it, on one shared baseline, serving repeats from the process-wide shaping cache like Typeface.Shape. Within that, the line resolves into directional runs (internal/text.BidiRuns) laid out in visual order, so mixed Hebrew/Arabic + Latin lines render reading-correct. The chain is the key: a chain held by the app reuses its entries across frames, and two chains over the same faces never collide. Empty text still shapes one primary run, so its metrics reserve the font's line height.

func (*Chain) ShapeDir

func (c *Chain) ShapeDir(s string, px float64, d text.Direction) *ShapedText

ShapeDir shapes under base direction d; see Chain.Shape and text.Direction.

func (*Chain) ShapeRune

func (c *Chain) ShapeRune(r rune, px float64) *ShapedText

ShapeRune shapes one rune; see Font.ShapeRune and Chain.Shape.

func (*Chain) Spaced

func (c *Chain) Spaced(px float64) *Chain

Spaced returns the chain shaping with px of letter spacing after every cluster, whichever face a rune lands on (see Typeface.Spaced).

func (*Chain) Tabular

func (c *Chain) Tabular() *Chain

Tabular returns the chain shaping with each face's tnum twin: digits on a uniform advance grid, what a clock or a numeric column wants. The variant keeps its own rune picks, so it never rewrites the base chain's.

func (*Chain) Weighted

func (c *Chain) Weighted(w int) *Chain

Weighted is the chain at CSS weight w (see Typeface.Weighted).

func (*Chain) WithResolver

func (c *Chain) WithResolver(resolve func(rune) *Typeface) *Chain

WithResolver installs a store-backed face picker consulted for runes neither the primary nor the fallback list covers, and returns the chain. internal/sysfont.Fallback wires one to the system font store.

func (*Chain) WithVariations

func (c *Chain) WithVariations(vs ...Variation) *Chain

WithVariations returns the chain shaping with every face instantiated at vs (each face ignores axes it lacks); faces the store resolves for uncovered runes shape at their defaults.

func (*Chain) Wrap

func (c *Chain) Wrap(text string, maxWidth, px float64) []string

Wrap breaks text into lines of at most maxWidth pixels; see Typeface.Wrap.

type Color

type Color uint32

Color is a premultiplied ARGB8888 pixel value, laid out as 0xAARRGGBB. Premultiplied is the native format of both the wl_shm buffers and Go's image.RGBA, so colors pass through blending without conversion.

func ColorFromBytes

func ColorFromBytes(b []byte) Color

ColorFromBytes decodes a premultiplied color from the wl_shm byte order: little-endian ARGB8888, that is bytes B, G, R, A.

func RGB

func RGB(r, g, b uint8) Color

RGB builds an opaque color from non-premultiplied components.

func RGBA

func RGBA(r, g, b, a uint8) Color

RGBA builds a color from non-premultiplied components and premultiplies them.

func (Color) A

func (c Color) A() uint8

A returns the alpha channel.

func (Color) B

func (c Color) B() uint8

B returns the premultiplied blue channel.

func (Color) G

func (c Color) G() uint8

G returns the premultiplied green channel.

func (Color) R

func (c Color) R() uint8

R returns the premultiplied red channel.

func (Color) Straight

func (c Color) Straight() [4]byte

Straight returns the color as non-premultiplied bytes in R, G, B, A order, as PNG and most image code expect.

type Corners

type Corners struct {
	TopLeft, TopRight, BottomRight, BottomLeft int
}

Corners is a per-corner radius set in logical pixels, clockwise from the top-left.

func UniformCorners

func UniformCorners(r int) Corners

UniformCorners returns r on every corner.

type Decoration

type Decoration struct {
	Lines DecorationLine
	Style DecorationStyle
	Color Color
}

Decoration is a text decoration: its lines, their style, and their color (zero: the text's).

type DecorationLine

type DecorationLine uint8

DecorationLine is a set of text decoration lines (CSS text-decoration-line).

const (
	Underline DecorationLine = 1 << iota
	Overline
	LineThrough
)

Decoration lines.

type DecorationStyle

type DecorationStyle uint8

DecorationStyle is how decoration lines are drawn (CSS text-decoration-style).

const (
	DecorationSolid DecorationStyle = iota
	DecorationDouble
	DecorationDotted
	DecorationDashed
	DecorationWavy
)

Decoration styles.

type EllipsizeMode

type EllipsizeMode uint8

EllipsizeMode selects which end of an overflowing line the ellipsis replaces.

const (
	// EllipsizeNone never truncates: long text overflows and clips.
	EllipsizeNone EllipsizeMode = iota
	// EllipsizeStart cuts from the front: "…cated text".
	EllipsizeStart
	// EllipsizeMiddle keeps the head and the tail: "trunc…text" - the
	// mode for paths and filenames, whose both halves identify them.
	EllipsizeMiddle
	// EllipsizeEnd cuts from the back: "truncated te…".
	EllipsizeEnd
)

type Extend

type Extend uint8

Extend says what lies beyond a gradient's first and last stops.

const (
	// ExtendPad continues the end colors (CSS's plain gradients).
	ExtendPad Extend = iota
	// ExtendRepeat repeats the stop range (CSS's repeating-*).
	ExtendRepeat
	// ExtendReflect mirrors the stop range back and forth (COLR).
	ExtendReflect
)

type Font

type Font interface {
	// Shape lays text out at the given pixel size, resolving the base
	// paragraph direction from the text's first strong character.
	Shape(s string, px float64) *ShapedText
	// ShapeDir is Shape under an explicit base direction; see
	// text.Direction.
	ShapeDir(s string, px float64, d text.Direction) *ShapedText
	// ShapeRune shapes one rune at the pixel size - the per-rune probe
	// wrap measurement and advance math use. Rune-keyed in the caches,
	// so a probe never builds a one-rune string per call.
	ShapeRune(r rune, px float64) *ShapedText
	// Draw paints a shaped line with its baseline at logical
	// (x, baselineY).
	Draw(cv *Canvas, s *ShapedText, x, baselineY int, col Color)
	// DrawAligned draws text inside box with the given alignment; start
	// and end mirror for a right-to-left paragraph.
	DrawAligned(cv *Canvas, s string, box Rect, px float64, col Color, h Alignment) *ShapedText
	// DrawAlignedDir is DrawAligned under an explicit base direction.
	DrawAlignedDir(cv *Canvas, s string, box Rect, px float64, col Color, h Alignment, d text.Direction) *ShapedText
}

Font shapes and paints text: a single Typeface, or a Chain that falls back across faces for runes the primary face lacks. Widgets take a Font, so either works at every text call site.

type Gradient

type Gradient struct {
	Kind   GradientKind
	Stops  []GradientStop
	Extend Extend
	// Angle is the linear direction, or the conic start, in degrees on
	// CSS's compass: 0 up, 90 right, clockwise.
	Angle float64
	// CenterX and CenterY place a radial or conic center as fractions
	// of the box (0.5 is its middle).
	CenterX, CenterY float64
	// Circle makes a radial gradient's ending shape a circle instead
	// of an ellipse.
	Circle bool
	// Size picks the radial ending shape's size; RadiusX and RadiusY
	// are its explicit radii in logical pixels under RadiusExplicit (a
	// circle takes RadiusX).
	Size             RadialSize
	RadiusX, RadiusY float64
}

Gradient is one gradient fill: its geometry, its stops (sorted by position; positions may repeat for a hard stop), and its extend mode. The zero value is a padded linear gradient pointing up; build one with Linear, Radial or Conic.

func Conic

func Conic(from float64, stops ...GradientStop) Gradient

Conic is a centered conic gradient starting at from (CSS degrees).

func Linear

func Linear(angle float64, stops ...GradientStop) Gradient

Linear is a linear gradient at angle (CSS degrees).

func Radial

func Radial(stops ...GradientStop) Gradient

Radial is a centered farthest-corner ellipse.

func (Gradient) Repeating

func (g Gradient) Repeating() Gradient

Repeating returns g repeating its stop range (CSS repeating-*).

type GradientKind

type GradientKind uint8

GradientKind is a gradient's geometry.

const (
	// GradientLinear runs along a line at an angle (CSS linear-gradient).
	GradientLinear GradientKind = iota
	// GradientRadial grows from a center out to an ellipse or circle
	// (CSS radial-gradient).
	GradientRadial
	// GradientConic sweeps around a center (CSS conic-gradient).
	GradientConic
)

type GradientStop

type GradientStop struct {
	Pos   float64
	Color Color
}

GradientStop is one color stop of a gradient: Pos is the fraction of the gradient line (or ray, or turn), 0 at its start and 1 at its end.

type Icon

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

Icon is a rasterized icon ready to blend onto a canvas.

func IconFromARGB32

func IconFromARGB32(width, height int, data []byte, w, h int) (*Icon, error)

IconFromARGB32 decodes a width x height raster of 32-bit ARGB pixels in network byte order (A, R, G, B per pixel, straight alpha, rows top to bottom with no padding) and scales it to w x h pixels. This is the StatusNotifierItem IconPixmap wire format (also the _NET_WM_ICON payload once byte-swapped to big-endian). data shorter than width*height*4 is an error, not a partial icon; trailing bytes past the raster are ignored.

func IconFromImage

func IconFromImage(src image.Image, w, h int) (*Icon, error)

IconFromImage scales any decoded image to w x h pixels, the same resampling LoadPNG applies. It is the entry point for pixels that did not come from a file: a decoded image the caller already holds, or a raster protocol payload converted to an image.

func LoadJPEG

func LoadJPEG(data []byte, w, h int) (*Icon, error)

LoadJPEG decodes JPEG icon data and scales it to w x h pixels.

func LoadPNG

func LoadPNG(data []byte, w, h int) (*Icon, error)

LoadPNG decodes PNG icon data and scales it to w x h pixels.

func LoadSVG

func LoadSVG(data []byte, w, h int) (*Icon, error)

LoadSVG rasterizes SVG icon data at w x h pixels. The icon's viewBox is scaled to fit inside that box with its aspect ratio kept and centered; the rest stays transparent. Unsupported SVG elements are an error, not silently dropped.

func (*Icon) At

func (i *Icon) At(x, y int) color.Color

At returns the pixel at (x, y) in icon coordinates.

func (*Icon) Draw

func (i *Icon) Draw(cv *Canvas, x, y int)

Draw blends the icon with its top-left corner at (x, y).

func (*Icon) DrawRotated

func (i *Icon) DrawRotated(cv *Canvas, x, y int, deg float64)

DrawRotated blends the icon turned deg degrees clockwise about its center, the center staying where the unrotated draw's center is. Destination pixels inverse-map into the icon with nearest sampling; the corners past the rotated bounds stay transparent.

func (*Icon) DrawXformed

func (i *Icon) DrawXformed(cv *Canvas, x, y int, m Affine)

DrawXformed blends the icon through the affine m, applied about the icon's center: destination pixels inverse-map into the icon with nearest sampling; corners past the transformed bounds stay transparent. The identity draws straight.

func (*Icon) Size

func (i *Icon) Size() (int, int)

Size returns the rasterized icon size in pixels.

func (*Icon) Tint

func (i *Icon) Tint(tint Color) *Icon

Tint returns a copy of the icon recolored to tint: every pixel keeps its alpha (anti-aliasing, opacity) and takes tint's color, so the source works as a mask. This is how symbolic icons follow the theme accent. The limits are the mask approach's limits: ink comes out one flat color, gradient hue variation collapses to its alpha ramp, and multi-color art goes monochrome - which is the symbolic-icon contract. A translucent tint yields a translucent result.

type ImageScale

type ImageScale uint8

ImageScale picks how an image fills the box its widget was arranged into.

const (
	// ImageFit scales the image to the largest size that fits the box
	// with the aspect ratio kept (contain); the rest of the box stays
	// transparent. The default.
	ImageFit ImageScale = iota
	// ImageCover scales the image until it fills the box completely,
	// aspect ratio kept, cropping the overflow: the largest centered
	// crop of the source with the box's aspect ratio, resampled to the
	// full box.
	ImageCover
	// ImageNone draws the image at its natural size, one source pixel
	// per device pixel, centered in the box and clipped to it. Nothing
	// is resampled, so the pixels stay exactly as decoded - at a 2x
	// device scale an image covers half the logical size it would at
	// 1x.
	ImageNone
	// ImageStretch resamples the whole image to exactly the box,
	// ignoring the aspect ratio.
	ImageStretch
	// ImageScaleDown is ImageNone for an image that fits the box and
	// ImageFit for one that does not: never enlarged, only shrunk (aspect
	// kept) until it fits - GTK's ContentFit.SCALE_DOWN, with the natural
	// size measured in device pixels like ImageNone.
	ImageScaleDown
)

type Insets

type Insets struct {
	Top, Right, Bottom, Left int
}

Insets is a per-side length set in logical pixels, in CSS order.

func UniformInsets

func UniformInsets(v int) Insets

UniformInsets returns v on every side.

func (Insets) Grow

func (i Insets) Grow(r Rect) Rect

Grow pushes r out by the insets.

func (Insets) Shrink

func (i Insets) Shrink(r Rect) Rect

Shrink pulls r in by the insets, clamping at an empty rect.

func (Insets) Zero

func (i Insets) Zero() bool

Zero reports whether every side is zero.

type Layer

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

Layer is an offscreen buffer shaped like a canvas: the same device size and scale, so a widget subtree paints into it exactly as it would onto the canvas, to be drawn back transformed by Composite.

func (*Layer) Canvas

func (l *Layer) Canvas() *Canvas

Canvas is the layer's canvas to paint into.

func (*Layer) CrossFade

func (l *Layer) CrossFade(other *Layer, region Rect, t float64)

CrossFade blends other into l over region: each pixel becomes l·(1−t) + other·t, premultiplied channels alike - GSK's cross-fade, exact where drawing one over the other at partial opacity is not.

type Path

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

Path is an outline in logical pixels for FillPath: straight and cubic Bézier segments in subpaths, each closed when filled (cairo's move_to / line_to / curve_to / close_path).

func (*Path) Close

func (p *Path) Close()

Close closes the current subpath back to its start.

func (*Path) CubeTo

func (p *Path) CubeTo(x1, y1, x2, y2, x, y float64)

CubeTo adds a cubic Bézier to (x, y) through the control points (x1, y1) and (x2, y2).

func (*Path) Empty

func (p *Path) Empty() bool

Empty reports a path with no segments.

func (*Path) LineTo

func (p *Path) LineTo(x, y float64)

LineTo adds a straight segment to (x, y).

func (*Path) MoveTo

func (p *Path) MoveTo(x, y float64)

MoveTo starts a subpath at (x, y).

type RadialSize

type RadialSize uint8

RadialSize is a radial gradient's ending-shape size, the CSS keywords plus explicit radii.

const (
	// FarthestCorner reaches the farthest corner (the CSS default).
	FarthestCorner RadialSize = iota
	// ClosestSide touches the nearest side.
	ClosestSide
	// ClosestCorner reaches the nearest corner.
	ClosestCorner
	// FarthestSide touches the farthest side.
	FarthestSide
	// RadiusExplicit uses Gradient.RadiusX and RadiusY.
	RadiusExplicit
)

type Rect

type Rect struct {
	X, Y, W, H int
}

Rect is an axis-aligned rectangle in buffer pixel coordinates. A Rect with a non-positive width or height is empty and covers no pixels.

func MapRect

func MapRect(r Rect, num, denom int) Rect

MapRect maps the logical rect r into device pixels at scale num/denom, rounding the origin down and the far edge up so the device rect fully covers everything r spans. Package-level so the frame pipeline can map damage without a canvas instance.

func UnionAll

func UnionAll(rects []Rect) Rect

UnionAll returns the bounding box of all rects. Nil and empty inputs yield an empty Rect.

func (Rect) Contains

func (r Rect) Contains(x, y int) bool

Contains reports whether the pixel (x, y) lies inside r. Empty rects contain nothing.

func (Rect) Empty

func (r Rect) Empty() bool

Empty reports whether r covers no pixels.

func (Rect) Intersect

func (r Rect) Intersect(o Rect) Rect

Intersect returns the overlap of r and o. Disjoint or empty inputs yield an empty Rect.

func (Rect) Subtract

func (r Rect) Subtract(o Rect) []Rect

Subtract returns r with o cut out, as up to four non-overlapping rects that tile the remainder exactly. Order is unspecified. A non-intersecting or empty o yields [r]; an o that covers r yields nil.

func (Rect) Union

func (r Rect) Union(o Rect) Rect

Union returns the bounding box of r and o. Empty rectangles drop out, so the Union of two empty rects is empty.

type ShapedText

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

ShapedText is one line of text shaped at a fixed pixel size: a sequence of runs, each shaped with its own face and embedding direction, sharing one baseline, laid out in visual left-to-right order (the directional runs internal/text resolves). Glyph positions are relative to the line origin. A single face and direction produce a single run; fallback chains produce one run per face change.

ShapedText is immutable once built - the process-wide shaping cache shares one instance between every caller that shapes the same (font, size, string) - so readers may hold and consult it freely but never write it.

func (*ShapedText) Advance

func (s *ShapedText) Advance() float64

Advance returns the line width in pixels: the sum over the runs.

func (*ShapedText) AppendCaretBands

func (s *ShapedText) AppendCaretBands(buf [][2]float64, start, end int) [][2]float64

AppendCaretBands appends the x spans covering the selected rune range [start, end) to buf and returns it: one span per visual run the range touches, left to right, so a selection across mixed-direction text highlights disjoint spans instead of spanning the middle. Spans are line-relative; callers offset them. The buffer is the caller's, kept across frames, so the render path stays allocation-free in the steady state.

func (*ShapedText) Ascent

func (s *ShapedText) Ascent() float64

Ascent returns the line's ascent above the baseline in pixels: the maximum over the runs, so a taller fallback face grows the line.

func (*ShapedText) CaretAt

func (s *ShapedText) CaretAt(x float64) int

CaretAt returns the rune boundary nearest x: the inverse of CaretX for hit-testing clicks in a text field, direction-agnostic because the table already follows the line visually.

func (*ShapedText) CaretPositions

func (s *ShapedText) CaretPositions() []float64

CaretPositions returns the caret x for every rune boundary 0..n at once - the table CaretX indexes, shared with every other reader of this line: read it, never modify it. Callers composing several runs into one line (rich labels) offset each run's table by its line x.

func (*ShapedText) CaretX

func (s *ShapedText) CaretX(caret int) float64

CaretX returns the x offset of the caret placed before rune index caret, clamped to [0, rune count]. The x follows the line visually: before an RTL run's first rune it sits at that run's right edge.

func (*ShapedText) Descent

func (s *ShapedText) Descent() float64

Descent returns the line's descent below the baseline in pixels (positive): the maximum over the runs.

func (*ShapedText) Draw

func (s *ShapedText) Draw(cv *Canvas, x, baselineY int, col Color)

Draw paints the line with its baseline at logical (x, baselineY), clipped to the canvas like every other primitive. Each run draws with its own face; every run was shaped at the logical pixel size and rasterizes at the canvas's device scale, so text stays crisp at any factor no matter which face supplied the glyph.

func (*ShapedText) DrawDecoration

func (s *ShapedText) DrawDecoration(cv *Canvas, x, baseline int, d Decoration, col Color)

DrawDecoration draws d along the line s, drawn with its pen at x and baseline: each line spans the shaped advance - the line's visual extent, whatever its runs' directions - at the font's own underline, strikethrough, and ascent metrics (post and OS/2, variable-font deltas included), in d.Color or else col. Every text widget and a rich label's runs paint decorations through it.

func (*ShapedText) LineHeight

func (s *ShapedText) LineHeight() int

LineHeight returns the rounded line height: the smallest integer box height that fits the line's ascent and descent. Measure and drawing guards must both use this so a label's natural height is never smaller than the height its own painter requires.

func (*ShapedText) NotDefCount

func (s *ShapedText) NotDefCount() int

NotDefCount returns how many shaped glyphs are the .notdef box (glyph 0), i.e. runes no face in the chain could render. Fallback chains aim for zero on scripts the system covers.

func (*ShapedText) Runs

func (s *ShapedText) Runs() int

Runs returns how many faces the line was shaped across. A single typeface always returns 1.

func (*ShapedText) Text

func (s *ShapedText) Text() string

Text returns the string the run was shaped from.

type Typeface

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

Typeface is a loaded font plus the machinery to shape and rasterize it. One instance per font family; it is not safe for concurrent use.

func LoadFont

func LoadFont(data []byte) (*Typeface, error)

LoadFont parses font data (TTF or OTF).

func NewFixtureHebrewTypeface

func NewFixtureHebrewTypeface() (*Typeface, error)

NewFixtureHebrewTypeface parses the bundled Hebrew fixture into a fresh Typeface, one per caller like NewFixtureTypeface.

func NewFixtureTypeface

func NewFixtureTypeface() (*Typeface, error)

NewFixtureTypeface parses the bundled fixture font into a fresh Typeface. One per caller: a Typeface is stateful and not safe for concurrent use, so tests never share one.

func NewTypeface

func NewTypeface(face *font.Face) (*Typeface, error)

NewTypeface wraps an already-resolved face, as returned by a font matcher.

func (*Typeface) Covers

func (t *Typeface) Covers(r rune) bool

Covers reports whether the face has a glyph for r. Fallback chains consult it per rune to decide where a glyph comes from.

func (*Typeface) Describe

func (t *Typeface) Describe() font.Description

Describe returns the face's font description: family, style, weight, and stretch. Callers compare it to pin which variant a request resolved to.

func (*Typeface) Draw

func (t *Typeface) Draw(cv *Canvas, s *ShapedText, x, baselineY int, col Color)

Draw paints a shaped line; see ShapedText.Draw.

func (*Typeface) DrawAligned

func (t *Typeface) DrawAligned(cv *Canvas, s string, box Rect, px float64, col Color, h Alignment) *ShapedText

DrawAligned draws text inside box with the given alignment, skipping it entirely when the box cannot hold one line of the font. The guard uses the same rounded LineHeight the measurement reports.

func (*Typeface) DrawAlignedDir

func (t *Typeface) DrawAlignedDir(cv *Canvas, s string, box Rect, px float64, col Color, h Alignment, d text.Direction) *ShapedText

DrawAlignedDir draws text inside box under base direction d; start and end mirror for a right-to-left base. See text.Direction.

func (*Typeface) Ellipsize

func (t *Typeface) Ellipsize(text string, maxWidth, px float64) string

Ellipsize shortens text to fit maxWidth, replacing the cut remainder with an ellipsis. Text that already fits is returned unchanged. For the other cut points use EllipsizeText.

func (*Typeface) Family

func (t *Typeface) Family() string

Family returns the resolved face's family name.

func (*Typeface) HasAxis

func (t *Typeface) HasAxis(tag string) bool

HasAxis reports whether the face is variable along tag: setting the axis to its two extremes yields different coordinates.

func (*Typeface) IsMonospace

func (t *Typeface) IsMonospace() bool

IsMonospace reports whether the face's glyphs are fixed-width (its post table's flag), what a monospace filter asks.

func (*Typeface) Shape

func (t *Typeface) Shape(s string, px float64) *ShapedText

Shape lays text out at the given pixel size, resolving the base direction from the text's first strong character. Results are served from the process-wide shaping cache: the second Shape of the same (face, size, string) is a map hit returning the identical ShapedText, so per-frame re-shapes - Entry's selection band, text, and caret, or a per-event click mapping - cost a lookup.

func (*Typeface) ShapeDir

func (t *Typeface) ShapeDir(s string, px float64, d text.Direction) *ShapedText

ShapeDir lays text out under base direction d; see Shape and text.Direction.

func (*Typeface) ShapeRune

func (t *Typeface) ShapeRune(r rune, px float64) *ShapedText

ShapeRune shapes one rune; see Font.ShapeRune. Identical result to Shape(string(r)) - the fill goes through the same uncached path - but the cache keys on the rune, so per-rune probes (wrap measurement walks one rune at a time) stay allocation-free in the steady state.

func (*Typeface) Spaced

func (t *Typeface) Spaced(px float64) *Typeface

Spaced returns the face shaping with px of letter spacing after every cluster (CSS letter-spacing): the advances themselves carry it, so measuring, caret placement, and painting agree. Memoized; zero returns the face itself.

func (*Typeface) Tabular

func (t *Typeface) Tabular() *Typeface

Tabular returns the face shaping with the tnum OpenType feature on: digits on a uniform advance grid, what a clock or a numeric column wants. Memoized; the twin shares nothing the lazy caches fill, so the two entries never contend.

func (*Typeface) Variations

func (t *Typeface) Variations() []Variation

Variations reports the settings this face was instantiated at; nil for a face at its default instance.

func (*Typeface) Weighted

func (t *Typeface) Weighted(w int) *Typeface

Weighted is the face at CSS weight w along its wght axis - a variable family's real weight rather than its default instance; a face without the axis returns itself.

func (*Typeface) WithVariations

func (t *Typeface) WithVariations(vs ...Variation) *Typeface

WithVariations returns the face instantiated at vs (CSS font-variation-settings, a named instance's coordinates): axes the font lacks are ignored, values clamp to each axis's range, and unnamed axes keep their defaults - settings apply over the default instance, not over t's own. A face with none of the axes, or empty vs, returns the default face. Instances are memoized per setting.

func (*Typeface) Wrap

func (t *Typeface) Wrap(text string, maxWidth, px float64) []string

Wrap breaks text into lines of at most maxWidth pixels, filling greedily along Unicode UAX #14 break opportunities: each line takes as much as fits before the first opportunity that overflows. Breaks land where real typesetting puts them - at spaces, after hyphens, inside CJK runs - not only at ASCII spaces. A run with no break opportunity before the width, an unbreakable token, stays whole on its own line and overflows. Hard newlines split unconditionally; trailing spaces at a break and leading spaces of a continuation are dropped.

type Variation

type Variation struct {
	Tag   string
	Value float32
}

Variation is one setting of a variable font's design axis: an OpenType axis tag ("wght", "wdth", "slnt", "ital", "opsz", or a font's own) and a value in that axis's design units (wght 100-900).

func ParseVariations

func ParseVariations(s string) ([]Variation, error)

ParseVariations parses a CSS font-variation-settings value - "normal", or comma-separated quoted four-letter tags and numbers ("wght" 650, "wdth" 80).

Jump to

Keyboard shortcuts

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