glimo

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2026 License: MIT Imports: 5 Imported by: 0

README

glimo-icon

glimo

A lightweight and powerful Go library for clear, easy 2D graphics, shapes, text, and auto layout.

Go Version License Coverage) Issues Stars


Installation

go get github.com/krispeckt/glimo

Features

  • Drawing primitives: line, circle, rectangle, text, image
  • Automatic layout (Flexbox-like: direction, wrap, justify, align, gap)
  • Layer & frame management
  • Visual effects: drop shadow, inner shadow, blur, noise, texture
  • Blend modes for colors (20+ CSS-compatible modes)
  • Gradients: linear, radial, conic with color stops
  • Unicode-aware text wrapping (word & symbol mode, ellipsis, max lines)
  • Thread-safe containers (AutoLayout, Group)

Project Structure

├── go.mod
├── go.sum
├── aliases.go
├── colors/
│   ├── aliases.go
│   ├── blue.go
│   ├── grayscale.go
│   ├── green.go
│   ├── purple.go
│   ├── red.go
│   └── yellow_orange.go
├── effects/
│   ├── drop_shadow.go
│   ├── effects.go
│   ├── inner_shadow.go
│   ├── layer_blur.go
│   ├── noise.go
│   └── texture.go
└── instructions/
    ├── auto_layout.go
    ├── circle.go
    ├── group.go
    ├── image.go
    ├── layer.go
    ├── line.go
    ├── rectangle.go
    ├── text.go
    ├── text_composite.go
    └── text_wrap.go

Font

render.Font wraps an OpenType/TrueType font file with pixel-accurate metrics that match Figma and CSS positioning semantics.

Loading
import "github.com/Krispeckt/glimo"

// From file
font, err := glimo.LoadFont("Inter-Regular.ttf", 16)

// From embedded bytes
//go:embed Inter-Regular.ttf
var fontData []byte
font, err := glimo.LoadFontFromBytes(fontData, 16)

// Panic variant for init code
font := glimo.MustLoadFont("Inter-Regular.ttf", 16)
Configuration (chainable)
Method Description
SetFontSizePt(pt float64) Font size in points. At 72 DPI, 1 pt = 1 px.
SetDPI(dpi float64) Dots per inch (default 72). At 96 DPI: 1 pt ≈ 1.33 px.
SetLetterSpacingPercent(pct float64) Tracking as % of font size. Positive = looser, negative = tighter.
SetAxis(tag string, value float32) Set a variable-font design axis (stored; see note below).
Clone() Deep-copy the font configuration with an independent mutex.
Metrics
Method Returns
HeightPt() Font size in points
HeightPx() Font size in pixels at current DPI
AscentPx() Distance from baseline to top of tallest glyph
DescentPx() Distance from baseline to bottom of lowest glyph
LineHeightPx() Full typographic line height (ascent + descent + leading)
LeadingPx() Internal leading (extra spacing inside the line box)
CapHeightPx() Height of capital letter 'H'
XHeightPx() Height of lowercase 'x'
TrackingPx() Per-character additional spacing in pixels
Coordinate model

glimo uses the visual-top model, matching Figma:

y ────────────────────  ← visual top  (y you pass to NewText)
         ascent
baseline ────────────
         descent
bottom ──────────────

The y coordinate is always baseline − ascent, never the CSS line-box top (which includes half-leading above the ascent and causes drift with many fonts).

Helper methods:

baseline := font.BaselineFromVisualTop(y)   // y + ascent
visualTop := font.VisualTopFromBaseline(b)  // b − ascent
Measuring and drawing
w, h := font.MeasureString("Hello")          // single line
w, h  = font.MeasureMultilineString(text, 0) // 0 = use font line height

// Draw into an RGBA buffer
endDot := font.DrawString(dst, colors.Black, "Hello", x, baselineY)
Variable fonts (API stub)

The VariationAxis / SetAxis API is available and stores axis values, but axis-based glyph shaping requires a backend with fvar/gvar support (planned):

font.SetAxis("wght", 700).SetAxis("wdth", 120) // stored, not yet rendered
axes := font.AvailableAxes()                    // nil until backend upgrade
Font face cache

Parsed font.Face objects are cached in a global LRU to avoid rebuilding per render call.

glimo.SetFontCacheCapacity(64) // default 32
glimo.ClearFontCache()

Layer

Layer is the root drawing surface. All instructions render onto a Layer.

Creating a layer
layer := instructions.NewLayer(800, 600)

// From an existing image
layer := instructions.NewLayerFromImage(img)
layer := instructions.NewLayerFromRGBA(rgbaImg)

// Load from file (PNG / JPEG)
layer, err := instructions.NewLayerFromImagePath("bg.png")
layer  = instructions.MustLoadLayerFromImagePath("bg.png")
Drawing instructions
layer.LoadInstruction(shape)
layer.LoadInstructions(shape1, shape2, shape3)
Compositing layers
// Draw `card` onto `background` at (x=250, y=200)
background.AddLayer(card, 250, 200)
Exporting
layer.Export("output.png")          // auto-detect by extension (.png/.jpg/.jpeg)
layer.ExportPNG("out.png", png.DefaultCompression)
layer.ExportJPEG("out.jpg", 90)     // quality 0–100

// In-memory (for HTTP responses, etc.)
data, err := layer.ExportBytes(png.BestSpeed)

Rectangle

rect := instructions.NewRectangle(x, y, width, height float64)
Fill and stroke
rect.SetFillColor(colors.Blue500)
rect.SetFillPattern(grad)           // linear / radial / conic gradient

rect.SetStrokeColor(colors.White)
rect.SetStrokePattern(grad)
rect.SetLineWidth(2)
rect.SetStrokePosition(instructions.StrokeInside)   // default
rect.SetStrokePosition(instructions.StrokeCenter)
rect.SetStrokePosition(instructions.StrokeOutside)
Corner radius
rect.SetRadius(12)                         // uniform
rect.SetCornerRadii(tl, tr, br, bl float64) // per-corner
rect.SetRoundedSteps(8)                    // arc resolution (default 8)
Effects
rect.AddEffect(effects.NewDropShadow(0, 8, 24, 0, colors.Black, 0.25))
rect.AddEffects(e1, e2)
Example
layer.LoadInstructions(
    instructions.NewRectangle(50, 50, 300, 180).
        SetFillColor(colors.White).
        SetRadius(16).
        AddEffect(effects.NewDropShadow(0, 8, 24, 0, colors.Black, 0.25)),
)

Circle

circle := instructions.NewCircle(x, y, radius float64) // x,y = top-left of bounding box
Fill, stroke, and effects

All the same setters as Rectangle:

circle.SetFillColor(colors.Blue500)
circle.SetFillPattern(grad)
circle.SetStrokeColor(colors.White)
circle.SetLineWidth(3)
circle.SetStrokePosition(instructions.StrokeOutside)
circle.SetSteps(64)    // polygon resolution; default 32
circle.AddEffect(effects.NewInnerShadow(0, 4, 12, 0, colors.Black, 0.4))
Example
layer.LoadInstructions(
    instructions.NewCircle(100, 100, 80).
        SetFillColor(colors.Indigo500).
        SetStrokeColor(colors.White).
        SetLineWidth(2).
        SetStrokePosition(instructions.StrokeOutside),
)

Line

Line is the low-level vector drawing API — used internally by Rectangle and Circle, but fully usable for custom paths.

line := instructions.NewLine()
Path commands
line.MoveTo(x, y)
line.LineTo(x, y)
line.QuadraticTo(cx, cy, x, y)   // quadratic Bézier
line.CubicTo(c1x, c1y, c2x, c2y, x, y) // cubic Bézier
line.ClosePath()
line.ClearPath()
line.NewSubPath()
Stroke and fill
line.SetLineWidth(2)
line.SetLineCap(instructions.LineCapRound)   // Round / Butt / Square
line.SetLineJoin(instructions.LineJoinRound) // Round / Bevel
line.SetFillRule(instructions.FillRuleWinding) // Winding / EvenOdd
line.SetStrokePattern(p)
line.SetFillPattern(p)

line.FillPreserve()    // fill without clearing path
line.Fill()
line.StrokePreserve()  // stroke without clearing path
line.Stroke()
Dashes
line.SetDashes([]float64{10, 5})  // 10 on, 5 off
line.SetDashOffset(2)
Transform
line.WithMatrix(geom.Scale(2, 2))
line.ResetMatrix()
Clipping
line.MoveTo(...)
line.LineTo(...)
line.ClipPreserve() // subsequent draws clipped to this path
line.ResetMask()
Example — star shape
line := instructions.NewLine().
    SetFillColor(colors.Yellow400).
    SetLineWidth(0)

for i := 0; i < 5; i++ {
    a := float64(i)*72 - 90
    r := math.Pi * a / 180
    if i == 0 {
        line.MoveTo(cx+outer*math.Cos(r), cy+outer*math.Sin(r))
    } else {
        line.LineTo(cx+outer*math.Cos(r), cy+outer*math.Sin(r))
    }
    a2 := a + 36
    r2 := math.Pi * a2 / 180
    line.LineTo(cx+inner*math.Cos(r2), cy+inner*math.Sin(r2))
}
line.ClosePath().FillPreserve()
layer.LoadInstruction(line)

Text

text := instructions.NewText(content string, x, y float64, font *render.Font)

x, y is the visual top-left of the first line — i.e. baseline − ascent. This matches Figma's text bounding box origin exactly.

Fill and color
text.SetSolidColor(colors.White)
text.SetColorPattern(grad)  // gradient fill mapped to canvas coordinates
Stroke
text.SetStrokeWithColor(colors.Black, 2)
text.SetStrokeWithPattern(grad, 2)
Layout
text.SetAlign(instructions.AlignTextLeft)    // default
text.SetAlign(instructions.AlignTextCenter)
text.SetAlign(instructions.AlignTextRight)

text.SetMaxWidth(360)   // enables line wrapping; 0 = no wrap
text.SetMaxLines(4)     // truncate; 0 = unlimited
text.SetLineSpacing(150) // 150% of line height (100 = normal)
text.SetScaleStep(2)    // increase font size by 2pt per line
Wrapping
text.SetWrapMode(instructions.WrapByWord)         // break at spaces
text.SetWrapMode(instructions.WrapBySymbol)       // break at any char
text.SetWrapSymbol("-")                           // hyphenation char
text.SetWrap(instructions.WrapBySymbol, "…")
Effects
text.AddEffect(effects.NewDropShadow(0, 4, 12, 0, colors.Black, 0.5))
Example — gradient text with wrapping
font, _ := glimo.LoadFont("Inter-Regular.ttf", 18)

grad := colors.NewLinearGradient(0, 0, 400, 0).
    AddColorStop(0, colors.RGBA(255, 87, 87, 255)).
    AddColorStop(1, colors.RGBA(87, 200, 255, 255))

layer := instructions.NewLayer(400, 300)
layer.LoadInstructions(
    instructions.NewRectangle(0, 0, 400, 300).SetFillColor(colors.Gray950),
    instructions.NewText("The quick brown fox jumps over the lazy dog.", 20, 20, font).
        SetColorPattern(grad).
        SetMaxWidth(360).
        SetMaxLines(4).
        SetAlign(instructions.AlignTextCenter).
        SetWrapMode(instructions.WrapByWord),
)
layer.Export("text.png")

Image

img := instructions.NewImage(src image.Image, x, y int)
Resize
img.SetSize(400, 300)
img.SetFit(instructions.FitStretch)  // exact resize, ignores aspect
img.SetFit(instructions.FitContain)  // fit inside, may letterbox (default)
img.SetFit(instructions.FitCover)    // fill and center-crop
Transform
img.Rotate(45)           // degrees, clockwise
img.SetExpand(true)      // grow canvas to avoid corner cropping
img.Mirror(true, false)  // flipH, flipV
Opacity and background
img.SetOpacity(0.8)             // global alpha [0..1]
img.SetBackground(colors.Black) // fill for rotation out-of-bounds pixels
Mask
img.SetMaskImage(mask)        // *image.RGBA in destination space
img.SetMaskFromShape(circle)  // render a shape as the mask
img.ClearMask()
Effects
img.AddEffect(effects.NewLayerBlur(3, false))
Example
src, _, _ := image.Decode(file)
layer.LoadInstructions(
    instructions.NewImage(src, 50, 50).
        SetSize(300, 200).
        SetFit(instructions.FitCover).
        SetOpacity(0.9).
        Rotate(5).
        SetExpand(true),
)

Group

Group composites a set of BoundedShape children into the parent layer. Children use local coordinates — the frame origin is added automatically.

group := instructions.NewGroup()
group.SetPositionChain(100, 100)
group.SetFrameSize(200, 150) // 0 = auto-fit to content
group.SetClip(true)          // clip children to frame rect

group.AddInstruction(rect)
group.AddInstructions(rect, circle, text)
group.Clear()

Thread-safe: concurrent AddInstruction / Draw / Clear calls are safe.

Example
card := instructions.NewGroup().
    SetPositionChain(50, 50).
    SetFrameSize(300, 200).
    SetClip(true)

card.AddInstructions(
    instructions.NewRectangle(0, 0, 300, 200).
        SetFillColor(colors.White).
        SetRadius(16),
    instructions.NewText("Card title", 16, 16, titleFont).
        SetSolidColor(colors.Gray900),
)

layer.LoadInstruction(card)

AutoLayout

AutoLayout is a Flexbox-like container. It arranges children automatically and is fully thread-safe.

layout := instructions.NewAutoLayout(x, y int, style instructions.ContainerStyle)
ContainerStyle
style := instructions.ContainerStyle{
    Direction:  instructions.Row,     // Row (default) or Column
    Wrap:       true,                 // wrap onto multiple lines
    Padding:    [4]int{8, 8, 8, 8},  // top, right, bottom, left
    Gap:        instructions.Vector2{X: 12, Y: 8},
    Justify:    instructions.JustifySpaceBetween,
    AlignItems: instructions.AlignItemsCenter,
    AlignContent: instructions.AlignItemsStart, // multi-line cross-axis
    Width:      460, // 0 = auto by content
    Height:     80,
}

JustifyContent values:

Value Behavior
JustifyStart Pack at start (default)
JustifyCenter Center along main axis
JustifyEnd Pack at end
JustifySpaceBetween Equal space between items
JustifySpaceAround Equal space around items
JustifySpaceEvenly Equal space including edges

AlignItems values:

Value Behavior
AlignItemsStart Align to cross-axis start
AlignItemsCenter Center on cross axis
AlignItemsEnd Align to cross-axis end
AlignItemsStretch Stretch to fill cross size
ItemStyle
style := instructions.ItemStyle{
    Width:      160,    // fixed; 0 = auto from shape
    Height:     64,
    FlexGrow:   1,      // take up remaining space
    FlexShrink: 1,      // shrink when container overflows; 0 = never shrink
    FlexBasis:  200,    // preferred size; 0 = auto
    Margin:     [4]int{0, 8, 0, 0},
    ZIndex:     1,      // paint order
    Position:   instructions.PosAbsolute, // remove from flow
    Top:        ptr(10), Right: ptr(10),  // absolute offsets
    IgnoreGapBefore: true, // skip container gap before this item
}
Adding children
layout.Add(shape, itemStyle)
layout.SetStyle(newStyle) // replace container style and invalidate layout
size := layout.Size()     // trigger layout and return outer dimensions
Example — navigation bar
font, _ := glimo.LoadFont("Inter-Regular.ttf", 14)

layout := instructions.NewAutoLayout(20, 20, instructions.ContainerStyle{
    Direction:  instructions.Row,
    Gap:        instructions.Vector2{X: 12},
    AlignItems: instructions.AlignItemsCenter,
    Justify:    instructions.JustifySpaceBetween,
    Width:      460,
    Height:     80,
})

for _, label := range []string{"Home", "About", "Blog", "Contact"} {
    label := label
    layout.Add(
        instructions.NewText(label, 0, 0, font).SetSolidColor(colors.White),
        instructions.ItemStyle{},
    )
}

layer.LoadInstructions(
    instructions.NewRectangle(0, 0, 500, 120).SetFillColor(colors.Gray900),
    layout,
)
Example — flex grow
layout := instructions.NewAutoLayout(0, 0, instructions.ContainerStyle{
    Direction: instructions.Row,
    Gap:       instructions.Vector2{X: 8},
    Width:     600,
    Height:    80,
    Padding:   [4]int{8, 8, 8, 8},
})

// Fixed sidebar
layout.Add(
    instructions.NewRectangle(0, 0, 0, 0).SetFillColor(colors.Blue500),
    instructions.ItemStyle{Width: 160, Height: 64},
)
// Content fills remaining space
layout.Add(
    instructions.NewRectangle(0, 0, 0, 0).SetFillColor(colors.Green500),
    instructions.ItemStyle{Height: 64, FlexGrow: 1},
)

Effects

Effects attach to any shape via AddEffect. They run as pre-effects (before drawing) or post-effects (after drawing).

import "github.com/Krispeckt/glimo/effects"
DropShadow

CSS-equivalent box-shadow. Uses the layer's alpha channel as a shape mask.

// NewDropShadow(offsetX, offsetY, blur, spread, color, opacity)
effects.NewDropShadow(0, 8, 24, 0, colors.Black, 0.25)
InnerShadow

Shadow drawn inside the shape.

// NewInnerShadow(offsetX, offsetY, blur, spread, color, opacity)
effects.NewInnerShadow(0, 4, 12, 0, colors.Black, 0.4)
LayerBlur

Gaussian-approximation blur on the layer.

// NewLayerBlur(radius, isBackground)
effects.NewLayerBlur(4, false) // false = blur the layer itself
effects.NewLayerBlur(4, true)  // true  = background blur (frosted glass)
Noise

Procedural grain overlay.

// NewNoise(intensity, scale, mode)
effects.NewNoise(0.35, 1, effects.NoiseMono)
effects.NewNoise(0.35, 1, effects.NoiseColor)
Texture

Repeating tiled texture with contrast and opacity.

// NewTexture(tileSize, contrast, opacity)
effects.NewTexture(40, 0.15, 0.6)

Complete examples

Basic shapes
layer := instructions.NewLayer(800, 600)
layer.LoadInstructions(
    instructions.NewCircle(100, 100, 100).SetFillColor(colors.Red),
    instructions.NewRectangle(100, 250, 200, 100).
        SetFillColor(colors.Amethyst).
        SetRadius(12),
)
layer.Export("output.png")
Gradient fill
grad := colors.NewLinearGradient(0, 0, 400, 0).
    AddColorStop(0, colors.RGBA(255, 87, 87, 255)).
    AddColorStop(0.5, colors.RGBA(255, 200, 50, 255)).
    AddColorStop(1, colors.RGBA(87, 200, 255, 255))

layer := instructions.NewLayer(400, 200)
layer.LoadInstructions(
    instructions.NewRectangle(0, 0, 400, 200).
        SetRadius(20).
        SetFillPattern(grad),
)
layer.Export("gradient.png")
Text with gradient fill and shadow
font, _ := glimo.LoadFont("Inter-Bold.ttf", 48)

grad := colors.NewLinearGradient(0, 0, 300, 0).
    AddColorStop(0, colors.RGBA(255, 100, 100, 255)).
    AddColorStop(1, colors.RGBA(100, 100, 255, 255))

layer := instructions.NewLayer(400, 150)
layer.LoadInstructions(
    instructions.NewRectangle(0, 0, 400, 150).SetFillColor(colors.Gray950),
    instructions.NewText("glimo", 50, 40, font).
        SetColorPattern(grad).
        AddEffect(effects.NewDropShadow(0, 4, 12, 0, colors.Black, 0.5)),
)
layer.Export("text_gradient.png")
Noise & texture overlay
layer := instructions.NewLayer(400, 400)
layer.LoadInstructions(
    instructions.NewRectangle(0, 0, 400, 400).SetFillColor(colors.Indigo600),
    instructions.NewRectangle(0, 0, 400, 400).
        SetFillColor(colors.Transparent).
        AddEffect(effects.NewNoise(0.35, 1, effects.NoiseMono)).
        AddEffect(effects.NewTexture(40, 0.15, 0.6)),
)
layer.Export("textured.png")
Compositing layers
background := instructions.NewLayer(800, 600)
background.LoadInstructions(
    instructions.NewRectangle(0, 0, 800, 600).SetFillColor(colors.Gray950),
)

card := instructions.NewLayer(300, 200)
card.LoadInstructions(
    instructions.NewRectangle(0, 0, 300, 200).
        SetFillColor(colors.White).
        SetRadius(16).
        AddEffect(effects.NewDropShadow(0, 8, 32, 0, colors.Black, 0.3)),
)

background.AddLayer(card, 250, 200)
background.Export("composite.png")
Concurrent rendering
// Each goroutine renders to its own independent Layer — no shared state.
var wg sync.WaitGroup
for i := 0; i < 4; i++ {
    wg.Add(1)
    go func(idx int) {
        defer wg.Done()
        layer := instructions.NewLayer(200, 200)
        c := colors.RGBA(uint8(idx*60), 120, 200, 255)
        layer.LoadInstructions(
            instructions.NewCircle(0, 0, 100).SetFillColor(c),
        )
        layer.Export(fmt.Sprintf("frame_%d.png", idx))
    }(i)
}
wg.Wait()

Thread safety: AutoLayout and Group protect their child lists with a mutex — concurrent Add / Draw calls on the same container are safe. Rendering to separate layers from multiple goroutines is always safe.


Visual Examples

Nested circles Nested rectangles Rounded corners Line drawing Gradient text Solid text

Run Tests

go test ./instructions/tests -v

Output Examples

See instructions/tests/output/ for reference images.


License

MIT License. See the LICENSE file for details.


Contributing

Pull requests are welcome. Before submitting, make sure all tests pass successfully.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClearFontCache

func ClearFontCache()

ClearFontCache removes all cached font data.

func LoadFont

func LoadFont(path string, sizePt float64) (*render.Font, error)

LoadFont loads a font from a file path.

func LoadFontFromBytes

func LoadFontFromBytes(data []byte, sizePt float64) (*render.Font, error)

LoadFontFromBytes loads a font from a byte slice in memory.

func LoadImage

func LoadImage(path string) (image.Image, error)

LoadImage loads an image from a file and returns it as image.Image.

func MustLoadFont

func MustLoadFont(path string, sizePt float64) *render.Font

MustLoadFont loads a font and panics if loading fails.

func MustLoadFontFromBytes

func MustLoadFontFromBytes(data []byte, sizePt float64) *render.Font

MustLoadFontFromBytes loads a font from memory and panics on failure.

func MustLoadFrameFromImagePath

func MustLoadFrameFromImagePath(path string) *instructions.Layer

MustLoadFrameFromImagePath loads a frame from a file and panics on failure.

func MustLoadLayerFromImagePath

func MustLoadLayerFromImagePath(path string) *instructions.Layer

MustLoadLayerFromImagePath loads a Layer from an image file and panics on failure.

func NewFrame

func NewFrame(width, height int) *instructions.Layer

NewFrame creates a blank frame surface with given dimensions.

func NewFrameFromImage

func NewFrameFromImage(img image.Image) *instructions.Layer

NewFrameFromImage wraps an existing image.Image as a frame.

func NewFrameFromImagePath

func NewFrameFromImagePath(path string) (*instructions.Layer, error)

NewFrameFromImagePath loads a PNG or JPEG image and returns it as a frame.

func NewFrameFromRGBA

func NewFrameFromRGBA(rgba *image.RGBA) *instructions.Layer

NewFrameFromRGBA creates a frame from an RGBA buffer.

func NewLayer

func NewLayer(width, height int) *instructions.Layer

NewLayer creates a blank RGBA layer with the specified width and height.

func NewLayerFromImage

func NewLayerFromImage(img image.Image) *instructions.Layer

NewLayerFromImage wraps an existing image.Image into a Layer.

func NewLayerFromImagePath

func NewLayerFromImagePath(path string) (*instructions.Layer, error)

NewLayerFromImagePath loads a PNG or JPEG image from a given file path and returns it as a Layer.

func NewLayerFromRGBA

func NewLayerFromRGBA(rgba *image.RGBA) *instructions.Layer

NewLayerFromRGBA constructs a Layer directly from an existing RGBA buffer.

func SetFontCacheCapacity

func SetFontCacheCapacity(limit int)

SetFontCacheCapacity sets the maximum number of cached faces for memory management.

Types

type Color

type Color = patterns.Color

Color defines the RGBA color model used throughout rendering and fill operations.

type Font

type Font = render.Font

Font represents a loaded font resource for text rendering.

type Frame

type Frame = instructions.Layer

Frame is an alias for Layer, used semantically for frame-based rendering.

type Layer

type Layer = instructions.Layer

Layer represents a 2D drawable surface.

Directories

Path Synopsis
Package effects defines post- and pre-render visual filters for 2D drawing operations.
Package effects defines post- and pre-render visual filters for 2D drawing operations.
Package instructions provides primitives for grouping and drawing bounded shapes together.
Package instructions provides primitives for grouping and drawing bounded shapes together.
internal

Jump to

Keyboard shortcuts

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