Documentation
¶
Overview ¶
Package scene provides blend mode integration with internal/blend package.
Package scene provides a retained-mode scene graph encoding system for efficient GPU rendering.
The encoding system uses a dual-stream architecture inspired by vello:
- A compact tags stream (1 byte per command)
- Separate data streams for paths, draws, and transforms
This design is cache-friendly and GPU-ready, minimizing memory bandwidth and enabling efficient batched rendering.
Index ¶
- Constants
- Variables
- func PutEncoding(enc *Encoding)
- func TextAdvance(glyphs []*RenderedGlyph) float32
- type Affine
- type ArcShape
- type BlendMode
- type Brush
- type BrushKind
- type CacheEntry
- type CacheStats
- type CircleShape
- type ClipStack
- func (s *ClipStack) CombinedBounds() Rect
- func (s *ClipStack) Contains(x, y float32) bool
- func (s *ClipStack) Depth() int
- func (s *ClipStack) Intersects(r Rect) bool
- func (s *ClipStack) IsEmpty() bool
- func (s *ClipStack) Pop() *ClipState
- func (s *ClipStack) Push(clip *ClipState)
- func (s *ClipStack) Reset()
- func (s *ClipStack) Top() *ClipState
- type ClipState
- type CompositeShape
- type Decoder
- func (d *Decoder) Brush() (r, g, b, a float32)
- func (d *Decoder) CollectPath() *Path
- func (d *Decoder) CubicTo() (c1x, c1y, c2x, c2y, x, y float32)
- func (d *Decoder) Encoding() *Encoding
- func (d *Decoder) Fill() (brush Brush, style FillStyle)
- func (d *Decoder) HasMore() bool
- func (d *Decoder) Image() (imageIndex uint32, transform Affine)
- func (d *Decoder) LineTo() (x, y float32)
- func (d *Decoder) MoveTo() (x, y float32)
- func (d *Decoder) Next() bool
- func (d *Decoder) Peek() Tag
- func (d *Decoder) Position() int
- func (d *Decoder) PushLayer() (blend BlendMode, alpha float32)
- func (d *Decoder) QuadTo() (cx, cy, x, y float32)
- func (d *Decoder) Reset(enc *Encoding)
- func (d *Decoder) SkipPath()
- func (d *Decoder) Stroke() (brush Brush, style *StrokeStyle)
- func (d *Decoder) Tag() Tag
- func (d *Decoder) Transform() Affine
- type EllipseShape
- type Encoding
- func (e *Encoding) Append(other *Encoding)
- func (e *Encoding) Bounds() Rect
- func (e *Encoding) Brushes() []Brush
- func (e *Encoding) Capacity() int
- func (e *Encoding) Clone() *Encoding
- func (e *Encoding) DrawData() []uint32
- func (e *Encoding) EncodeBeginClip()
- func (e *Encoding) EncodeBrush(brush Brush) int
- func (e *Encoding) EncodeEndClip()
- func (e *Encoding) EncodeFill(brush Brush, style FillStyle)
- func (e *Encoding) EncodeImage(imageIndex uint32, transform Affine)
- func (e *Encoding) EncodePath(p *gg.Path)
- func (e *Encoding) EncodePopLayer()
- func (e *Encoding) EncodePushLayer(blend BlendMode, alpha float32)
- func (e *Encoding) EncodeStroke(brush Brush, style *StrokeStyle)
- func (e *Encoding) EncodeTransform(t Affine)
- func (e *Encoding) EncodeTransformFromMatrix(m gg.Matrix)
- func (e *Encoding) Hash() uint64
- func (e *Encoding) IsEmpty() bool
- func (e *Encoding) NewIterator() *Iterator
- func (e *Encoding) PathCount() int
- func (e *Encoding) PathData() []float32
- func (e *Encoding) Reset()
- func (e *Encoding) ShapeCount() int
- func (e *Encoding) Size() int
- func (e *Encoding) Tags() []Tag
- func (e *Encoding) Transforms() []Affine
- func (e *Encoding) UpdateBounds(bounds Rect)
- type EncodingPool
- type FillStyle
- type Filter
- type FilterChain
- type FilterType
- type Image
- type Iterator
- type LayerCache
- func (c *LayerCache) Contains(hash uint64) bool
- func (c *LayerCache) EntryCount() int
- func (c *LayerCache) Get(hash uint64) (*gg.Pixmap, bool)
- func (c *LayerCache) GetVersion(hash uint64) (uint64, bool)
- func (c *LayerCache) Invalidate(hash uint64)
- func (c *LayerCache) InvalidateAll()
- func (c *LayerCache) MaxSize() int64
- func (c *LayerCache) Put(hash uint64, pixmap *gg.Pixmap, version uint64)
- func (c *LayerCache) ResetStats()
- func (c *LayerCache) SetMaxSize(mb int)
- func (c *LayerCache) Size() int64
- func (c *LayerCache) Stats() CacheStats
- func (c *LayerCache) Trim(targetSize int64)
- type LayerKind
- type LayerStack
- func (s *LayerStack) AcquireLayer() *LayerState
- func (s *LayerStack) All() []*LayerState
- func (s *LayerStack) Depth() int
- func (s *LayerStack) IsRoot() bool
- func (s *LayerStack) Pop() *LayerState
- func (s *LayerStack) Push(layer *LayerState)
- func (s *LayerStack) ReleaseLayer(layer *LayerState)
- func (s *LayerStack) Reset()
- func (s *LayerStack) Root() *LayerState
- func (s *LayerStack) Top() *LayerState
- type LayerState
- type LineCap
- type LineJoin
- type LineShape
- type Path
- func (p *Path) Arc(cx, cy, rx, ry, startAngle, endAngle float32, sweepClockwise bool) *Path
- func (p *Path) Bounds() Rect
- func (p *Path) Circle(cx, cy, r float32) *Path
- func (p *Path) Clone() *Path
- func (p *Path) Close() *Path
- func (p *Path) Contains(px, py float32) bool
- func (p *Path) CubicTo(c1x, c1y, c2x, c2y, x, y float32) *Path
- func (p *Path) Elements() iter.Seq[PathElement]
- func (p *Path) ElementsWithCursor() iter.Seq2[Point, PathElement]
- func (p *Path) Ellipse(cx, cy, rx, ry float32) *Path
- func (p *Path) IsEmpty() bool
- func (p *Path) LineTo(x, y float32) *Path
- func (p *Path) MoveTo(x, y float32) *Path
- func (p *Path) PointCount() int
- func (p *Path) Points() []float32
- func (p *Path) QuadTo(cx, cy, x, y float32) *Path
- func (p *Path) Rectangle(x, y, w, h float32) *Path
- func (p *Path) Reset()
- func (p *Path) Reverse() *Path
- func (p *Path) RoundedRectangle(x, y, w, h, r float32) *Path
- func (p *Path) Transform(t Affine) *Path
- func (p *Path) VerbCount() int
- func (p *Path) Verbs() []PathVerb
- type PathElement
- type PathPool
- type PathShape
- type PathVerb
- type PieShape
- type Point
- type PolygonShape
- type Rect
- type RectShape
- type RegularPolygonShape
- type RenderStats
- type RenderedGlyph
- type Renderer
- func (r *Renderer) Cache() *LayerCache
- func (r *Renderer) CacheStats() CacheStats
- func (r *Renderer) Close()
- func (r *Renderer) DirtyTileCount() int
- func (r *Renderer) Height() int
- func (r *Renderer) MarkAllDirty()
- func (r *Renderer) MarkDirty(x, y, w, h int)
- func (r *Renderer) Render(target *gg.Pixmap, scene *Scene) error
- func (r *Renderer) RenderDirty(target *gg.Pixmap, scene *Scene, dirty *parallel.DirtyRegion) error
- func (r *Renderer) RenderDirtyWithContext(ctx context.Context, target *gg.Pixmap, scene *Scene, ...) error
- func (r *Renderer) RenderWithContext(ctx context.Context, target *gg.Pixmap, scene *Scene) error
- func (r *Renderer) Resize(width, height int)
- func (r *Renderer) Stats() RenderStats
- func (r *Renderer) TileCount() int
- func (r *Renderer) Width() int
- func (r *Renderer) Workers() int
- type RendererOption
- type RoundedRectShape
- type Scene
- func (s *Scene) Bounds() Rect
- func (s *Scene) ClipBounds() Rect
- func (s *Scene) ClipDepth() int
- func (s *Scene) DrawGlyphs(glyphs []text.ShapedGlyph, face text.Face, brush Brush) error
- func (s *Scene) DrawImage(img *Image, transform Affine)
- func (s *Scene) DrawText(str string, face text.Face, x, y float32, brush Brush) error
- func (s *Scene) Encoding() *Encoding
- func (s *Scene) Fill(style FillStyle, transform Affine, brush Brush, shape Shape)
- func (s *Scene) Flatten() *Encoding
- func (s *Scene) Images() []*Image
- func (s *Scene) IsEmpty() bool
- func (s *Scene) LayerDepth() int
- func (s *Scene) PopClip() bool
- func (s *Scene) PopLayer() bool
- func (s *Scene) PopTransform() bool
- func (s *Scene) PushClip(shape Shape)
- func (s *Scene) PushLayer(blend BlendMode, alpha float32, clip Shape)
- func (s *Scene) PushTransform(t Affine)
- func (s *Scene) Reset()
- func (s *Scene) Rotate(angle float32)
- func (s *Scene) Scale(x, y float32)
- func (s *Scene) SetTransform(t Affine)
- func (s *Scene) Stroke(style *StrokeStyle, transform Affine, brush Brush, shape Shape)
- func (s *Scene) Transform() Affine
- func (s *Scene) TransformDepth() int
- func (s *Scene) Translate(x, y float32)
- func (s *Scene) Version() uint64
- type SceneBuilder
- func (b *SceneBuilder) Build() *Scene
- func (b *SceneBuilder) Clip(shape Shape, fn func(*SceneBuilder)) *SceneBuilder
- func (b *SceneBuilder) CurrentTransform() Affine
- func (b *SceneBuilder) DrawLine(x1, y1, x2, y2 float32, brush Brush, lineWidth float32) *SceneBuilder
- func (b *SceneBuilder) Fill(shape Shape, brush Brush) *SceneBuilder
- func (b *SceneBuilder) FillCircle(cx, cy, r float32, brush Brush) *SceneBuilder
- func (b *SceneBuilder) FillPath(path *Path, brush Brush) *SceneBuilder
- func (b *SceneBuilder) FillRect(x, y, width, height float32, brush Brush) *SceneBuilder
- func (b *SceneBuilder) FillWith(shape Shape, brush Brush, style FillStyle) *SceneBuilder
- func (b *SceneBuilder) Group(fn func(*SceneBuilder)) *SceneBuilder
- func (b *SceneBuilder) Image(img *Image, rect Rect) *SceneBuilder
- func (b *SceneBuilder) Layer(blend BlendMode, alpha float32, clip Shape, fn func(*SceneBuilder)) *SceneBuilder
- func (b *SceneBuilder) Reset() *SceneBuilder
- func (b *SceneBuilder) ResetTransform() *SceneBuilder
- func (b *SceneBuilder) Rotate(angle float32) *SceneBuilder
- func (b *SceneBuilder) Scale(x, y float32) *SceneBuilder
- func (b *SceneBuilder) Scene() *Scene
- func (b *SceneBuilder) Stroke(shape Shape, brush Brush, width float32) *SceneBuilder
- func (b *SceneBuilder) StrokeCircle(cx, cy, r float32, brush Brush, lineWidth float32) *SceneBuilder
- func (b *SceneBuilder) StrokePath(path *Path, brush Brush, lineWidth float32) *SceneBuilder
- func (b *SceneBuilder) StrokeRect(x, y, width, height float32, brush Brush, lineWidth float32) *SceneBuilder
- func (b *SceneBuilder) StrokeWith(shape Shape, brush Brush, style *StrokeStyle) *SceneBuilder
- func (b *SceneBuilder) Transform(t Affine) *SceneBuilder
- func (b *SceneBuilder) Translate(x, y float32) *SceneBuilder
- func (b *SceneBuilder) WithTransform(t Affine, fn func(*SceneBuilder)) *SceneBuilder
- type ScenePool
- type Shape
- type StarShape
- type StrokeStyle
- type Tag
- type TextRenderer
- func (r *TextRenderer) Config() TextRendererConfig
- func (r *TextRenderer) RenderGlyph(glyph text.ShapedGlyph, face text.Face) (*RenderedGlyph, error)
- func (r *TextRenderer) RenderGlyphs(glyphs []text.ShapedGlyph, face text.Face) ([]*RenderedGlyph, error)
- func (r *TextRenderer) RenderRun(run *text.ShapedRun) ([]*RenderedGlyph, error)
- func (r *TextRenderer) RenderText(str string, face text.Face) ([]*RenderedGlyph, error)
- func (r *TextRenderer) RenderTextToScene(s *Scene, str string, face text.Face, x, y float32, brush Brush) error
- func (r *TextRenderer) RenderToScene(s *Scene, glyphs []text.ShapedGlyph, face text.Face, brush Brush) error
- func (r *TextRenderer) SetConfig(config TextRendererConfig)
- func (r *TextRenderer) ToCompositePath(glyphs []*RenderedGlyph) *Path
- type TextRendererConfig
- type TextRendererPool
- type TextShape
- type TransformShape
Constants ¶
const (
// DefaultMaxSizeMB is the default maximum cache size in megabytes.
DefaultMaxSizeMB = 64
)
Default cache configuration constants.
Variables ¶
var DefaultPool = NewEncodingPool()
DefaultPool is a global encoding pool for convenience. For performance-critical code, consider creating dedicated pools.
Functions ¶
func PutEncoding ¶
func PutEncoding(enc *Encoding)
PutEncoding returns an encoding to the default pool.
func TextAdvance ¶ added in v0.11.0
func TextAdvance(glyphs []*RenderedGlyph) float32
TextAdvance returns the total advance width of rendered glyphs.
Types ¶
type Affine ¶
Affine represents a 2D affine transformation matrix. The matrix is stored in row-major order as:
| A B C | | D E F |
Where a point (x, y) is transformed to:
x' = A*x + B*y + C y' = D*x + E*y + F
func AffineFromMatrix ¶
AffineFromMatrix converts a gg.Matrix to an Affine.
func IdentityAffine ¶
func IdentityAffine() Affine
IdentityAffine returns the identity transformation.
func RotateAffine ¶
RotateAffine creates a rotation transformation (angle in radians).
func ScaleAffine ¶
ScaleAffine creates a scaling transformation.
func TranslateAffine ¶
TranslateAffine creates a translation transformation.
func (Affine) IsIdentity ¶
IsIdentity returns true if this is the identity transformation.
type ArcShape ¶
type ArcShape struct {
CX, CY float32 // Center
RX, RY float32 // Radii
StartAngle float32 // Start angle in radians
EndAngle float32 // End angle in radians
SweepClockwise bool // Direction
}
ArcShape represents an arc (portion of an ellipse outline).
func NewArcShape ¶
NewArcShape creates a new arc shape.
type BlendMode ¶
type BlendMode uint32
BlendMode represents a compositing blend mode.
const ( BlendNormal BlendMode = iota BlendMultiply BlendScreen BlendOverlay BlendDarken BlendLighten BlendColorDodge BlendColorBurn BlendHardLight BlendSoftLight BlendDifference BlendExclusion BlendHue BlendSaturation BlendColor BlendLuminosity // Porter-Duff modes BlendClear BlendCopy BlendDestination BlendSourceOver BlendDestinationOver BlendSourceIn BlendDestinationIn BlendSourceOut BlendDestinationOut BlendSourceAtop BlendDestinationAtop BlendXor BlendPlus )
Blend mode constants following Porter-Duff and advanced blend modes.
func AdvancedModes ¶
func AdvancedModes() []BlendMode
AdvancedModes returns a slice of advanced separable blend modes.
func AllBlendModes ¶
func AllBlendModes() []BlendMode
AllBlendModes returns a slice of all supported blend modes. This is useful for testing and iteration.
func BlendModeFromInternal ¶
BlendModeFromInternal converts an internal blend.BlendMode to scene.BlendMode. This is the reverse mapping for cases where you need to convert from internal representation back to the scene graph representation.
func HSLModes ¶
func HSLModes() []BlendMode
HSLModes returns a slice of HSL-based non-separable blend modes.
func PorterDuffModes ¶
func PorterDuffModes() []BlendMode
PorterDuffModes returns a slice of Porter-Duff compositing modes.
func (BlendMode) GetBlendFunc ¶
GetBlendFunc returns the internal blend function for this mode. This is a convenience method that combines ToInternalBlendMode with blend.GetBlendFunc.
Usage:
blendFn := scene.BlendMultiply.GetBlendFunc() r, g, b, a := blendFn(sr, sg, sb, sa, dr, dg, db, da)
func (BlendMode) IsAdvanced ¶
IsAdvanced returns true if this is an advanced separable blend mode.
func (BlendMode) IsPorterDuff ¶
IsPorterDuff returns true if this is a Porter-Duff compositing mode.
func (BlendMode) ToInternalBlendMode ¶
ToInternalBlendMode converts scene.BlendMode to internal blend.BlendMode. This provides the mapping between the scene graph blend modes and the low-level pixel blending implementation.
The internal blend.BlendMode uses a different enumeration order, so this function provides the translation.
type CacheEntry ¶
type CacheEntry struct {
// contains filtered or unexported fields
}
CacheEntry represents a single cached pixmap with metadata.
type CacheStats ¶
type CacheStats struct {
// Size is the current memory usage in bytes.
Size int64
// MaxSize is the memory budget in bytes.
MaxSize int64
// Entries is the number of cached entries.
Entries int
// Hits is the number of cache hits.
Hits uint64
// Misses is the number of cache misses.
Misses uint64
// HitRate is the cache hit rate (0.0 to 1.0).
HitRate float64
// Evictions is the number of entries evicted.
Evictions uint64
}
CacheStats contains cache statistics for monitoring.
type CircleShape ¶
CircleShape represents a circle.
func NewCircleShape ¶
func NewCircleShape(cx, cy, r float32) *CircleShape
NewCircleShape creates a new circle shape.
func (*CircleShape) Bounds ¶
func (c *CircleShape) Bounds() Rect
Bounds returns the bounding rectangle.
func (*CircleShape) Contains ¶
func (c *CircleShape) Contains(px, py float32) bool
Contains returns true if the point (px, py) is inside the circle.
func (*CircleShape) ToPath ¶
func (c *CircleShape) ToPath() *Path
ToPath converts the circle to a Path.
type ClipStack ¶
type ClipStack struct {
// contains filtered or unexported fields
}
ClipStack manages a stack of clip regions.
func (*ClipStack) CombinedBounds ¶
CombinedBounds returns the intersection of all clip bounds. Returns an empty rect if any clip is empty.
func (*ClipStack) Intersects ¶
Intersects returns true if the rectangle intersects all clip regions.
type ClipState ¶
type ClipState struct {
// Shape is the clip shape
Shape Shape
// Bounds is the clip bounds (for quick rejection)
Bounds Rect
// Transform is the transform that was active when clip was pushed
Transform Affine
}
ClipState represents a clip region on the clip stack.
func NewClipState ¶
NewClipState creates a new clip state.
func (*ClipState) Contains ¶
Contains returns true if the point is inside the clip region. This is a conservative test using the bounding box.
func (*ClipState) Intersects ¶
Intersects returns true if the rectangle intersects the clip region. This is a conservative test using bounding boxes.
type CompositeShape ¶
type CompositeShape struct {
// contains filtered or unexported fields
}
CompositeShape combines multiple shapes into one.
func NewCompositeShape ¶
func NewCompositeShape(shapes ...Shape) *CompositeShape
NewCompositeShape creates a new composite shape.
func (*CompositeShape) AddShape ¶
func (cs *CompositeShape) AddShape(shape Shape)
AddShape adds a shape to the composite.
func (*CompositeShape) Bounds ¶
func (cs *CompositeShape) Bounds() Rect
Bounds returns the union of all shape bounds.
func (*CompositeShape) ShapeCount ¶
func (cs *CompositeShape) ShapeCount() int
ShapeCount returns the number of shapes in the composite.
func (*CompositeShape) ToPath ¶
func (cs *CompositeShape) ToPath() *Path
ToPath converts all shapes to a single Path.
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder provides sequential decoding of an Encoding's command stream. It tracks position indices across all data streams (tags, paths, draws, transforms) and provides methods to read each command type's associated data.
The decoder is designed for efficient rendering playback, supporting both full traversal and selective decoding for tile-based rendering.
Example usage:
dec := NewDecoder(encoding)
for dec.Next() {
switch dec.Tag() {
case TagMoveTo:
x, y := dec.MoveTo()
// handle move
case TagLineTo:
x, y := dec.LineTo()
// handle line
case TagFill:
brush, style := dec.Fill()
// handle fill
}
}
func NewDecoder ¶
NewDecoder creates a new decoder for the given encoding. Returns nil if encoding is nil.
func (*Decoder) Brush ¶
Brush reads the current Brush command data. Returns the RGBA color values. Only valid when Tag() == TagBrush.
func (*Decoder) CollectPath ¶
CollectPath collects all path commands until EndPath into a new Path. Returns the collected path. The decoder is advanced past the path data. Returns nil if not currently at the start of a path.
func (*Decoder) CubicTo ¶
CubicTo reads the current CubicTo command data. Returns control point 1 (c1x, c1y), control point 2 (c2x, c2y), and destination (x, y). Only valid when Tag() == TagCubicTo.
func (*Decoder) Fill ¶
Fill reads the current Fill command data. Returns the brush and fill style. Only valid when Tag() == TagFill.
func (*Decoder) Image ¶
Image reads the current Image command data. Returns the image index and transform. Only valid when Tag() == TagImage.
func (*Decoder) LineTo ¶
LineTo reads the current LineTo command data. Returns the destination point (x, y). Only valid when Tag() == TagLineTo.
func (*Decoder) MoveTo ¶
MoveTo reads the current MoveTo command data. Returns the destination point (x, y). Only valid when Tag() == TagMoveTo.
func (*Decoder) Next ¶
Next advances to the next command in the stream. Returns true if there is another command, false when iteration is complete. After calling Next, use Tag() to get the current command type, then call the appropriate method (MoveTo, LineTo, Fill, etc.) to get the data.
func (*Decoder) Peek ¶
Peek returns the next tag without advancing the decoder. Returns 0 if at end of stream.
func (*Decoder) PushLayer ¶
PushLayer reads the current PushLayer command data. Returns the blend mode and alpha value. Only valid when Tag() == TagPushLayer.
func (*Decoder) QuadTo ¶
QuadTo reads the current QuadTo command data. Returns the control point (cx, cy) and destination point (x, y). Only valid when Tag() == TagQuadTo.
func (*Decoder) Reset ¶
Reset resets the decoder to the beginning of the encoding. This allows reusing the decoder for multiple passes.
func (*Decoder) SkipPath ¶
func (d *Decoder) SkipPath()
SkipPath advances past all path commands until EndPath is found. This is useful for quickly skipping paths that are outside the clip region.
func (*Decoder) Stroke ¶
func (d *Decoder) Stroke() (brush Brush, style *StrokeStyle)
Stroke reads the current Stroke command data. Returns the brush and stroke style. Only valid when Tag() == TagStroke.
type EllipseShape ¶
EllipseShape represents an axis-aligned ellipse.
func NewEllipseShape ¶
func NewEllipseShape(cx, cy, rx, ry float32) *EllipseShape
NewEllipseShape creates a new ellipse shape.
func (*EllipseShape) Bounds ¶
func (e *EllipseShape) Bounds() Rect
Bounds returns the bounding rectangle.
func (*EllipseShape) Contains ¶
func (e *EllipseShape) Contains(px, py float32) bool
Contains returns true if the point (px, py) is inside the ellipse.
func (*EllipseShape) ToPath ¶
func (e *EllipseShape) ToPath() *Path
ToPath converts the ellipse to a Path.
type Encoding ¶
type Encoding struct {
// contains filtered or unexported fields
}
Encoding holds the dual-stream encoded representation of drawing commands. It uses separate streams for tags (1 byte each), path data, draw data, and transforms to maximize cache efficiency and GPU compatibility.
func GetEncoding ¶
func GetEncoding() *Encoding
GetEncoding retrieves an encoding from the default pool.
func (*Encoding) Append ¶
Append merges another encoding into this one. The other encoding's content is appended after the current content.
func (*Encoding) EncodeBeginClip ¶
func (e *Encoding) EncodeBeginClip()
EncodeBeginClip begins a clipping region.
func (*Encoding) EncodeBrush ¶
EncodeBrush encodes a brush definition.
func (*Encoding) EncodeEndClip ¶
func (e *Encoding) EncodeEndClip()
EncodeEndClip ends the current clipping region.
func (*Encoding) EncodeFill ¶
EncodeFill adds a fill command with the given brush and fill style.
func (*Encoding) EncodeImage ¶
EncodeImage encodes an image reference.
func (*Encoding) EncodePath ¶
EncodePath encodes a complete path from a gg.Path.
func (*Encoding) EncodePopLayer ¶
func (e *Encoding) EncodePopLayer()
EncodePopLayer pops the current compositing layer.
func (*Encoding) EncodePushLayer ¶
EncodePushLayer pushes a new compositing layer.
func (*Encoding) EncodeStroke ¶
func (e *Encoding) EncodeStroke(brush Brush, style *StrokeStyle)
EncodeStroke adds a stroke command with the given brush and stroke style.
func (*Encoding) EncodeTransform ¶
EncodeTransform adds a transform command.
func (*Encoding) EncodeTransformFromMatrix ¶
EncodeTransformFromMatrix adds a transform from a gg.Matrix.
func (*Encoding) Hash ¶
Hash computes a 64-bit FNV-1a hash of the encoding for cache keys. The hash includes all stream data to ensure uniqueness.
func (*Encoding) NewIterator ¶
NewIterator creates an iterator for the encoding.
func (*Encoding) Reset ¶
func (e *Encoding) Reset()
Reset clears the encoding for reuse without deallocating memory. This is the key method for zero-allocation pooling.
func (*Encoding) ShapeCount ¶
ShapeCount returns the number of shapes (fills + strokes) encoded.
func (*Encoding) Transforms ¶
Transforms returns the transform stream.
func (*Encoding) UpdateBounds ¶ added in v0.29.0
UpdateBounds expands the encoding's bounding box to include the given rect. This is used to propagate transformed bounds from Scene to Encoding, ensuring that the tile-based renderer's early-out intersection test uses correct post-transform coordinates.
type EncodingPool ¶
type EncodingPool struct {
// contains filtered or unexported fields
}
EncodingPool manages a pool of reusable Encoding objects. After warmup, allocations are minimized by reusing encodings.
Usage:
pool := NewEncodingPool() enc := pool.Get() defer pool.Put(enc) // use enc...
func NewEncodingPool ¶
func NewEncodingPool() *EncodingPool
NewEncodingPool creates a new encoding pool.
func (*EncodingPool) Get ¶
func (p *EncodingPool) Get() *Encoding
Get retrieves an encoding from the pool. The encoding is reset and ready for use.
func (*EncodingPool) Put ¶
func (p *EncodingPool) Put(enc *Encoding)
Put returns an encoding to the pool for reuse. The encoding will be reset on the next Get.
func (*EncodingPool) Warmup ¶
func (p *EncodingPool) Warmup(count int)
Warmup pre-allocates encodings to avoid allocation during critical paths. Call this during initialization if allocation-free operation is required.
type Filter ¶
type Filter interface {
// Apply processes src pixmap and writes result to dst.
// bounds specifies the affected region in pixel coordinates.
// The filter may read pixels outside bounds but only writes within bounds.
Apply(src, dst *gg.Pixmap, bounds Rect)
// ExpandBounds returns the expanded bounds after filter application.
// This is used for buffer allocation:
// - Blur expands by radius in all directions
// - Shadow expands by offset + blur radius
// - Color matrix does not expand
ExpandBounds(input Rect) Rect
}
Filter applies visual effects to rendered layers. Filters are applied during layer pop when LayerFiltered is used.
The filter interface supports both in-place and copy operations: - If src == dst, the filter operates in-place when possible - Some filters (like blur) may require temporary buffers internally
Bounds handling: - Input bounds specify the region to process - ExpandBounds returns how much the output grows (e.g., blur radius)
type FilterChain ¶
type FilterChain struct {
// contains filtered or unexported fields
}
FilterChain represents multiple filters applied in sequence. Filters are applied in order from first to last.
func NewFilterChain ¶
func NewFilterChain(filters ...Filter) *FilterChain
NewFilterChain creates a new filter chain from the given filters.
func (*FilterChain) Apply ¶
func (fc *FilterChain) Apply(src, dst *gg.Pixmap, bounds Rect)
Apply processes src through all filters in sequence. For chains with more than one filter, temporary buffers are used.
func (*FilterChain) ExpandBounds ¶
func (fc *FilterChain) ExpandBounds(input Rect) Rect
ExpandBounds returns the combined expansion of all filters.
func (*FilterChain) IsEmpty ¶
func (fc *FilterChain) IsEmpty() bool
IsEmpty returns true if the chain has no filters.
func (*FilterChain) Len ¶
func (fc *FilterChain) Len() int
Len returns the number of filters in the chain.
type FilterType ¶
type FilterType uint8
FilterType identifies the type of filter for serialization and debugging.
const ( // FilterNone represents no filter (identity). FilterNone FilterType = iota // FilterBlur represents Gaussian blur filter. FilterBlur // FilterDropShadow represents drop shadow filter. FilterDropShadow // FilterColorMatrix represents color matrix transformation. FilterColorMatrix )
Filter type constants.
func (FilterType) ExpandsOutput ¶
func (ft FilterType) ExpandsOutput() bool
ExpandsOutput returns true if this filter type typically expands output bounds.
func (FilterType) String ¶
func (ft FilterType) String() string
String returns a human-readable name for the filter type.
type Image ¶
type Image struct {
// Width is the image width in pixels
Width int
// Height is the image height in pixels
Height int
// Data holds the pixel data (RGBA format)
// This will be populated during integration phase
Data []byte
}
Image represents an image resource for drawing. This is a placeholder that will be expanded during integration.
type Iterator ¶
type Iterator struct {
// contains filtered or unexported fields
}
Iterator provides sequential access to encoded commands.
func (*Iterator) Next ¶
Next advances to the next command and returns its tag. Returns false when iteration is complete.
func (*Iterator) ReadDrawData ¶
ReadDrawData reads n uint32 values from the draw data stream.
func (*Iterator) ReadPathData ¶
ReadPathData reads n float32 values from the path data stream.
func (*Iterator) ReadTransform ¶
ReadTransform reads the next transform from the stream.
type LayerCache ¶
type LayerCache struct {
// contains filtered or unexported fields
}
LayerCache provides an LRU cache for rendered layer pixmaps. It is thread-safe and uses atomic counters for statistics.
The cache evicts least recently used entries when the memory limit is exceeded. Cache entries are keyed by a 64-bit hash computed from the encoding content.
func DefaultLayerCache ¶
func DefaultLayerCache() *LayerCache
DefaultLayerCache creates a new layer cache with the default 64MB limit.
func NewLayerCache ¶
func NewLayerCache(maxSizeMB int) *LayerCache
NewLayerCache creates a new layer cache with the specified maximum size. The maxSizeMB parameter sets the memory budget in megabytes.
func (*LayerCache) Contains ¶
func (c *LayerCache) Contains(hash uint64) bool
Contains checks if an entry with the given hash exists in the cache. This does not update the LRU order.
func (*LayerCache) EntryCount ¶
func (c *LayerCache) EntryCount() int
EntryCount returns the number of entries in the cache.
func (*LayerCache) Get ¶
func (c *LayerCache) Get(hash uint64) (*gg.Pixmap, bool)
Get retrieves a cached pixmap by its hash. Returns the pixmap and true if found, nil and false otherwise. On cache hit, the entry is moved to the front of the LRU list.
func (*LayerCache) GetVersion ¶
func (c *LayerCache) GetVersion(hash uint64) (uint64, bool)
GetVersion returns the version of a cached entry if it exists. Returns 0 and false if the entry is not found.
func (*LayerCache) Invalidate ¶
func (c *LayerCache) Invalidate(hash uint64)
Invalidate removes a specific entry from the cache by hash.
func (*LayerCache) InvalidateAll ¶
func (c *LayerCache) InvalidateAll()
InvalidateAll clears the entire cache.
func (*LayerCache) MaxSize ¶
func (c *LayerCache) MaxSize() int64
MaxSize returns the memory budget in bytes.
func (*LayerCache) Put ¶
func (c *LayerCache) Put(hash uint64, pixmap *gg.Pixmap, version uint64)
Put stores a pixmap in the cache with the given hash and version. If the cache exceeds its memory budget, least recently used entries are evicted. If an entry with the same hash exists, it is replaced.
func (*LayerCache) ResetStats ¶
func (c *LayerCache) ResetStats()
ResetStats resets the hit, miss, and eviction counters to zero.
func (*LayerCache) SetMaxSize ¶
func (c *LayerCache) SetMaxSize(mb int)
SetMaxSize updates the memory budget. If the new budget is smaller than current usage, entries are evicted. The mb parameter is the new budget in megabytes.
func (*LayerCache) Size ¶
func (c *LayerCache) Size() int64
Size returns the current memory usage in bytes.
func (*LayerCache) Stats ¶
func (c *LayerCache) Stats() CacheStats
Stats returns current cache statistics. This operation is lock-free for the atomic counters.
func (*LayerCache) Trim ¶
func (c *LayerCache) Trim(targetSize int64)
Trim evicts entries until the cache size is at or below the target size. The targetSize parameter is in bytes.
type LayerKind ¶
type LayerKind uint8
LayerKind identifies the type of compositing layer.
const ( // LayerRegular is a normal blend layer with alpha and blend mode. LayerRegular LayerKind = iota // LayerFiltered is a layer that will have filter effects applied. // This layer's contents are rendered to an offscreen buffer for processing. LayerFiltered // LayerClip is a clip-only layer that masks subsequent content. // No rendering is done to this layer; it only defines a clip region. LayerClip )
Layer kind constants.
func (LayerKind) IsClipOnly ¶
IsClipOnly returns true if this layer is only for clipping (no rendering).
func (LayerKind) NeedsOffscreen ¶
NeedsOffscreen returns true if this layer kind requires an offscreen buffer.
type LayerStack ¶
type LayerStack struct {
// contains filtered or unexported fields
}
LayerStack manages a stack of active layers. The stack always has at least one layer (the root layer).
func NewLayerStack ¶
func NewLayerStack() *LayerStack
NewLayerStack creates a new layer stack with a root layer.
func (*LayerStack) AcquireLayer ¶
func (s *LayerStack) AcquireLayer() *LayerState
AcquireLayer gets a layer from the pool.
func (*LayerStack) All ¶
func (s *LayerStack) All() []*LayerState
All returns all layers in the stack (bottom to top).
func (*LayerStack) Depth ¶
func (s *LayerStack) Depth() int
Depth returns the current stack depth (1 = only root).
func (*LayerStack) IsRoot ¶
func (s *LayerStack) IsRoot() bool
IsRoot returns true if only the root layer is on the stack.
func (*LayerStack) Pop ¶
func (s *LayerStack) Pop() *LayerState
Pop removes and returns the top layer. Returns nil if only the root layer remains.
func (*LayerStack) Push ¶
func (s *LayerStack) Push(layer *LayerState)
Push adds a new layer to the stack.
func (*LayerStack) ReleaseLayer ¶
func (s *LayerStack) ReleaseLayer(layer *LayerState)
ReleaseLayer returns a layer to the pool.
func (*LayerStack) Reset ¶
func (s *LayerStack) Reset()
Reset clears the stack, returning to just the root layer.
func (*LayerStack) Root ¶
func (s *LayerStack) Root() *LayerState
Root returns the root (bottom) layer.
func (*LayerStack) Top ¶
func (s *LayerStack) Top() *LayerState
Top returns the current (topmost) layer without removing it.
type LayerState ¶
type LayerState struct {
// Kind identifies the type of layer
Kind LayerKind
// BlendMode specifies how this layer composites with layers below
BlendMode BlendMode
// Alpha is the layer opacity (0.0 to 1.0)
Alpha float32
// Clip is the optional clip shape for this layer.
// If nil, the layer has no clip (infinite bounds).
Clip Shape
// Encoding holds the layer's drawing commands.
// This is populated as drawing commands are added to the scene
// while this layer is active.
Encoding *Encoding
// Bounds tracks the cumulative bounding box of layer content.
// This is updated as content is added.
Bounds Rect
// Transform is the transform active when the layer was pushed.
// Used to restore transform state on pop.
Transform Affine
// ClipStackDepth records the clip stack depth when layer was pushed.
// Used to restore clip state on pop.
ClipStackDepth int
}
LayerState represents the state of an active compositing layer. Each layer has its own encoding for isolated rendering.
func NewClipLayer ¶
func NewClipLayer(clip Shape) *LayerState
NewClipLayer creates a new clip-only layer.
func NewFilteredLayer ¶
func NewFilteredLayer(blend BlendMode, alpha float32) *LayerState
NewFilteredLayer creates a new layer for filter effects.
func NewLayerState ¶
func NewLayerState(kind LayerKind, blend BlendMode, alpha float32) *LayerState
NewLayerState creates a new layer state with default values.
func (*LayerState) HasClip ¶
func (ls *LayerState) HasClip() bool
HasClip returns true if the layer has a clip shape.
func (*LayerState) IsEmpty ¶
func (ls *LayerState) IsEmpty() bool
IsEmpty returns true if the layer has no content.
func (*LayerState) UpdateBounds ¶
func (ls *LayerState) UpdateBounds(r Rect)
UpdateBounds expands the layer bounds to include the given rectangle.
type LineShape ¶
LineShape represents a line segment.
func NewLineShape ¶
NewLineShape creates a new line shape.
type Path ¶
type Path struct {
// contains filtered or unexported fields
}
Path represents a vector path for encoding. It stores path commands (verbs) and coordinate data separately for efficient processing and encoding.
func (*Path) Arc ¶
Arc adds an arc path (portion of an ellipse). The arc is drawn from startAngle to endAngle (in radians). If sweepClockwise is true, the arc is drawn clockwise.
func (*Path) Bounds ¶
Bounds returns the bounding rectangle of the path. Note: This is a conservative approximation that includes control points.
func (*Path) Contains ¶
Contains returns true if the point (px, py) is inside the path. This uses the non-zero winding rule to determine containment. The test is performed by casting a ray from the point to infinity and counting the number of times the path crosses the ray.
func (*Path) CubicTo ¶
CubicTo draws a cubic Bezier curve. The curve goes from the current point to (x, y) using (c1x, c1y) and (c2x, c2y) as control points.
func (*Path) Elements ¶ added in v0.13.0
func (p *Path) Elements() iter.Seq[PathElement]
Elements returns an iterator over all path elements. This uses Go 1.25+ iter.Seq for efficient, zero-allocation iteration when used with a for-range loop.
Example:
for elem := range path.Elements() {
switch elem.Verb {
case VerbMoveTo:
fmt.Printf("Move to %v\n", elem.Points[0])
case VerbLineTo:
fmt.Printf("Line to %v\n", elem.Points[0])
case VerbQuadTo:
fmt.Printf("Quad to %v via %v\n", elem.Points[1], elem.Points[0])
case VerbCubicTo:
fmt.Printf("Cubic to %v\n", elem.Points[2])
case VerbClose:
fmt.Println("Close")
}
}
func (*Path) ElementsWithCursor ¶ added in v0.13.0
func (p *Path) ElementsWithCursor() iter.Seq2[Point, PathElement]
ElementsWithCursor returns an iterator that includes the current cursor position. This is useful when you need to know the starting point of each segment.
func (*Path) PointCount ¶
PointCount returns the number of float32 values in the point stream.
func (*Path) QuadTo ¶
QuadTo draws a quadratic Bezier curve. The curve goes from the current point to (x, y) using (cx, cy) as control point.
func (*Path) Reset ¶
func (p *Path) Reset()
Reset clears the path for reuse without deallocating memory.
func (*Path) Reverse ¶
Reverse returns a new path with the direction reversed. This is useful for creating cut-out shapes.
func (*Path) RoundedRectangle ¶
RoundedRectangle adds a rounded rectangle path.
func (*Path) Transform ¶
Transform returns a new path with all points transformed by the affine matrix.
type PathElement ¶ added in v0.13.0
type PathElement struct {
// Verb is the path command type.
Verb PathVerb
// Points contains the coordinates for this element.
// The number of points depends on the verb:
// - MoveTo: 1 point (destination)
// - LineTo: 1 point (destination)
// - QuadTo: 2 points (control, destination)
// - CubicTo: 3 points (control1, control2, destination)
// - Close: 0 points
Points []Point
}
PathElement represents a single path command with its associated points. This type is used by the Elements() iterator for ergonomic path traversal.
type PathPool ¶
type PathPool struct {
// contains filtered or unexported fields
}
PathPool manages a pool of reusable Path objects.
type PathShape ¶
type PathShape struct {
// contains filtered or unexported fields
}
PathShape wraps a Path as a Shape.
type PathVerb ¶
type PathVerb uint8
PathVerb represents a path construction command.
const ( // VerbMoveTo moves the current point without drawing. VerbMoveTo PathVerb = iota // VerbLineTo draws a line to the specified point. VerbLineTo // VerbQuadTo draws a quadratic Bezier curve. VerbQuadTo // VerbCubicTo draws a cubic Bezier curve. VerbCubicTo // VerbClose closes the current subpath. VerbClose )
Path verb constants.
func (PathVerb) PointCount ¶
PointCount returns the number of points this verb consumes.
type PieShape ¶
type PieShape struct {
CX, CY float32 // Center
R float32 // Radius
StartAngle float32 // Start angle in radians
EndAngle float32 // End angle in radians
SweepClockwise bool // Direction
}
PieShape represents a pie slice (wedge).
func NewPieShape ¶
NewPieShape creates a new pie shape.
type Point ¶ added in v0.13.0
type Point struct {
X, Y float32
}
Point represents a 2D point with float32 coordinates. This is used by PathElement for iterator-based path traversal.
type PolygonShape ¶
type PolygonShape struct {
// contains filtered or unexported fields
}
PolygonShape represents a closed polygon.
func NewPolygonShape ¶
func NewPolygonShape(points ...float32) *PolygonShape
NewPolygonShape creates a new polygon shape from a list of points. Points should be provided as x, y pairs.
func (*PolygonShape) Bounds ¶
func (p *PolygonShape) Bounds() Rect
Bounds returns the bounding rectangle.
func (*PolygonShape) Point ¶
func (p *PolygonShape) Point(i int) (x, y float32, ok bool)
Point returns the i-th vertex of the polygon.
func (*PolygonShape) PointCount ¶
func (p *PolygonShape) PointCount() int
PointCount returns the number of vertices in the polygon.
func (*PolygonShape) ToPath ¶
func (p *PolygonShape) ToPath() *Path
ToPath converts the polygon to a Path.
type Rect ¶
Rect represents a bounding rectangle.
func EmptyRect ¶
func EmptyRect() Rect
EmptyRect returns an empty rectangle (inverted bounds for union operations).
func TextBounds ¶ added in v0.11.0
func TextBounds(glyphs []*RenderedGlyph) Rect
TextBounds computes the bounding box for rendered text.
func (Rect) UnionPoint ¶
UnionPoint expands the rectangle to include the point.
type RectShape ¶
RectShape represents an axis-aligned rectangle.
func NewRectShape ¶
NewRectShape creates a new rectangle shape.
type RegularPolygonShape ¶
type RegularPolygonShape struct {
CX, CY float32 // Center
R float32 // Radius (distance from center to vertices)
Sides int // Number of sides
Rotation float32 // Rotation angle in radians
}
RegularPolygonShape represents a regular polygon (all sides equal length).
func NewRegularPolygonShape ¶
func NewRegularPolygonShape(cx, cy, r float32, sides int, rotation float32) *RegularPolygonShape
NewRegularPolygonShape creates a new regular polygon shape.
func (*RegularPolygonShape) Bounds ¶
func (rp *RegularPolygonShape) Bounds() Rect
Bounds returns the bounding rectangle.
func (*RegularPolygonShape) ToPath ¶
func (rp *RegularPolygonShape) ToPath() *Path
ToPath converts the regular polygon to a Path.
type RenderStats ¶
type RenderStats struct {
// Tile statistics
TilesTotal int
TilesDirty int
TilesRendered int
// Layer statistics
LayersCached int
LayersRendered int
// Timing (durations for the last render)
TimeEncode time.Duration
TimeRaster time.Duration
TimeComposite time.Duration
TimeTotal time.Duration
// Frame timing
FrameTime time.Duration
FPS float64
}
RenderStats contains performance statistics for a render operation.
type RenderedGlyph ¶ added in v0.11.0
type RenderedGlyph struct {
// Path is the vector path representing the glyph outline.
// May be nil for non-outline glyphs (bitmap, empty).
Path *Path
// Bounds is the bounding box of the rendered glyph.
Bounds Rect
// Advance is the distance to the next glyph position.
Advance float32
// Position is the glyph position relative to the text origin.
X, Y float32
// GID is the glyph ID.
GID text.GlyphID
// Type indicates the glyph type.
Type text.GlyphType
// Cluster is the source character index.
Cluster int
}
RenderedGlyph represents a glyph that has been converted to a path.
type Renderer ¶
type Renderer struct {
// contains filtered or unexported fields
}
Renderer renders Scene content to a target Pixmap using parallel tile-based processing. It integrates with TileGrid for spatial subdivision and WorkerPool for concurrent execution.
The renderer supports:
- Full scene rendering (all tiles)
- Incremental rendering (dirty tiles only)
- Layer caching for static content
- Performance statistics collection
Thread safety: Renderer methods are safe for concurrent use after initialization.
func NewRenderer ¶
func NewRenderer(width, height int, opts ...RendererOption) *Renderer
NewRenderer creates a new scene renderer for the given dimensions. Options can be used to configure caching, parallelism, and other settings.
func (*Renderer) CacheStats ¶
func (r *Renderer) CacheStats() CacheStats
CacheStats returns the layer cache statistics.
func (*Renderer) Close ¶
func (r *Renderer) Close()
Close releases all resources used by the renderer. The renderer should not be used after Close is called.
func (*Renderer) DirtyTileCount ¶
DirtyTileCount returns the number of dirty tiles.
func (*Renderer) MarkAllDirty ¶
func (r *Renderer) MarkAllDirty()
MarkAllDirty marks all tiles as needing redraw.
func (*Renderer) MarkDirty ¶
MarkDirty marks the specified rectangle as needing redraw. Coordinates are in pixel space.
func (*Renderer) Render ¶
Render renders the entire scene to the target pixmap. This processes all tiles regardless of dirty state.
For cancellable rendering, use RenderWithContext.
func (*Renderer) RenderDirty ¶
RenderDirty renders only the dirty regions of the scene. This is more efficient when only parts of the scene have changed. The dirty parameter specifies which tiles need re-rendering.
For cancellable rendering, use RenderDirtyWithContext.
func (*Renderer) RenderDirtyWithContext ¶ added in v0.13.0
func (r *Renderer) RenderDirtyWithContext(ctx context.Context, target *gg.Pixmap, scene *Scene, dirty *parallel.DirtyRegion) error
RenderDirtyWithContext renders only the dirty regions of the scene with cancellation support. This is more efficient when only parts of the scene have changed. The dirty parameter specifies which tiles need re-rendering.
The context can be used to cancel long-running renders. When canceled, the function returns ctx.Err() and the target may contain partial results.
func (*Renderer) RenderWithContext ¶ added in v0.13.0
RenderWithContext renders the entire scene to the target pixmap with cancellation support. This processes all tiles regardless of dirty state.
The context can be used to cancel long-running renders. When canceled, the function returns ctx.Err() and the target may contain partial results.
func (*Renderer) Resize ¶
Resize updates the renderer dimensions. All tiles will be marked dirty after resize.
func (*Renderer) Stats ¶
func (r *Renderer) Stats() RenderStats
Stats returns the current render statistics.
type RendererOption ¶
type RendererOption func(*Renderer)
RendererOption configures a Renderer.
func WithCache ¶
func WithCache(cache *LayerCache) RendererOption
WithCache sets a custom layer cache. If nil, a default cache is created.
func WithCacheSize ¶
func WithCacheSize(mb int) RendererOption
WithCacheSize sets the layer cache size in megabytes. Default is 64MB.
func WithTileSize ¶
func WithTileSize(size int) RendererOption
WithTileSize sets the tile size for rendering. This is informational only; actual tile size is fixed at 64x64.
func WithWorkers ¶
func WithWorkers(n int) RendererOption
WithWorkers sets the number of worker goroutines for parallel rendering. If n <= 0, GOMAXPROCS is used.
type RoundedRectShape ¶
type RoundedRectShape struct {
X, Y float32 // Top-left corner
Width, Height float32 // Dimensions
Radius float32 // Corner radius (same for all corners)
}
RoundedRectShape represents a rectangle with rounded corners.
func NewRoundedRectShape ¶
func NewRoundedRectShape(x, y, width, height, radius float32) *RoundedRectShape
NewRoundedRectShape creates a new rounded rectangle shape.
func (*RoundedRectShape) Bounds ¶
func (r *RoundedRectShape) Bounds() Rect
Bounds returns the bounding rectangle.
func (*RoundedRectShape) ToPath ¶
func (r *RoundedRectShape) ToPath() *Path
ToPath converts the rounded rectangle to a Path.
type Scene ¶
type Scene struct {
// contains filtered or unexported fields
}
Scene is the main retained mode container for accumulating drawing operations. It builds an Encoding that can be efficiently rendered or cached.
Scene provides a familiar drawing API with Fill, Stroke, layers, clips, and transforms. All operations are recorded into an internal Encoding for later playback or GPU submission.
Example:
scene := NewScene() scene.Fill(FillNonZero, IdentityAffine(), SolidBrush(gg.Red), circle) scene.PushLayer(BlendMultiply, 0.5, nil) scene.Stroke(DefaultStrokeStyle(), IdentityAffine(), SolidBrush(gg.Blue), rect) scene.PopLayer() enc := scene.Encoding()
func (*Scene) ClipBounds ¶
ClipBounds returns the intersection of all active clip regions.
func (*Scene) DrawGlyphs ¶ added in v0.11.0
DrawGlyphs draws pre-shaped glyphs directly to the scene.
func (*Scene) DrawText ¶ added in v0.11.0
DrawText is a convenience method on Scene to draw text directly. It creates a temporary TextRenderer, renders the text, and adds it to the scene.
func (*Scene) Encoding ¶
Encoding returns the root encoding containing all scene commands. This encoding can be used for rendering or caching.
func (*Scene) Flatten ¶
Flatten composites all layers into a single encoding. This is useful for rendering the complete scene as a single flattened representation.
Unlike Encoding(), this method returns a new cloned encoding that is independent of the scene's internal state. This allows the scene to be modified after calling Flatten() without affecting the returned encoding.
The flattening process:
- All open layers are popped and composited
- Layer blend modes and alpha values are applied
- The result is a single encoding with all content merged
Example:
scene := NewScene() scene.Fill(FillNonZero, IdentityAffine(), SolidBrush(gg.Red), rect) scene.PushLayer(BlendMultiply, 0.5, nil) scene.Fill(FillNonZero, IdentityAffine(), SolidBrush(gg.Blue), circle) flat := scene.Flatten() // flat contains both shapes with layer compositing applied
func (*Scene) LayerDepth ¶
LayerDepth returns the current layer stack depth.
func (*Scene) PopClip ¶
PopClip pops the current clip region. Returns false if there's no clip to pop.
func (*Scene) PopLayer ¶
PopLayer pops the current layer and composites it with the content below. Returns false if there's no layer to pop (only root layer remains).
func (*Scene) PopTransform ¶
PopTransform pops the current transform from the stack. Returns false if there's no transform to pop.
func (*Scene) PushClip ¶
PushClip pushes a clip region. All subsequent drawing operations will be clipped to this shape until PopClip is called.
func (*Scene) PushLayer ¶
PushLayer pushes a new compositing layer. All subsequent drawing operations will be rendered to this layer. Call PopLayer to composite the layer with the content below.
func (*Scene) PushTransform ¶
PushTransform pushes a transform onto the transform stack. The transform is concatenated with the current transform.
func (*Scene) Reset ¶
func (s *Scene) Reset()
Reset clears the scene for reuse without deallocating memory.
func (*Scene) SetTransform ¶
SetTransform sets the current transform, replacing the existing one. This does not affect the transform stack.
func (*Scene) Stroke ¶
func (s *Scene) Stroke(style *StrokeStyle, transform Affine, brush Brush, shape Shape)
Stroke strokes a shape with the given style, transform, and brush.
func (*Scene) TransformDepth ¶
TransformDepth returns the current transform stack depth.
type SceneBuilder ¶
type SceneBuilder struct {
// contains filtered or unexported fields
}
SceneBuilder provides a fluent API for constructing scenes ergonomically. It wraps a Scene and provides chainable methods for drawing operations, transform management, and layer composition.
The builder maintains its own transform state that accumulates with each transform operation. Use ResetTransform to clear the accumulated transform.
Example:
scene := NewSceneBuilder().
Fill(NewRectShape(0, 0, 800, 600), SolidBrush(White)).
Translate(100, 100).
Layer(BlendMultiply, 0.8, nil, func(b *SceneBuilder) {
b.Fill(NewCircleShape(0, 0, 50), SolidBrush(Red)).
Stroke(NewCircleShape(0, 0, 50), SolidBrush(Black), 2)
}).
Build()
func NewSceneBuilder ¶
func NewSceneBuilder() *SceneBuilder
NewSceneBuilder creates a new scene builder with an empty scene.
func NewSceneBuilderFrom ¶
func NewSceneBuilderFrom(scene *Scene) *SceneBuilder
NewSceneBuilderFrom creates a scene builder wrapping an existing scene. This is useful for adding to a scene that already has content.
func (*SceneBuilder) Build ¶
func (b *SceneBuilder) Build() *Scene
Build returns the constructed scene and resets the builder for reuse. The builder is left in a clean state with a new empty scene.
func (*SceneBuilder) Clip ¶
func (b *SceneBuilder) Clip(shape Shape, fn func(*SceneBuilder)) *SceneBuilder
Clip creates a clipping region from the given shape. The callback receives the same builder to add clipped content.
Example:
builder.Clip(circle, func(b *SceneBuilder) {
b.Fill(largeRect, SolidBrush(Blue)) // clipped to circle
})
func (*SceneBuilder) CurrentTransform ¶
func (b *SceneBuilder) CurrentTransform() Affine
CurrentTransform returns the builder's current transform.
func (*SceneBuilder) DrawLine ¶
func (b *SceneBuilder) DrawLine(x1, y1, x2, y2 float32, brush Brush, lineWidth float32) *SceneBuilder
DrawLine is a convenience method to draw a line.
func (*SceneBuilder) Fill ¶
func (b *SceneBuilder) Fill(shape Shape, brush Brush) *SceneBuilder
Fill fills a shape with the given brush using the non-zero winding rule.
func (*SceneBuilder) FillCircle ¶
func (b *SceneBuilder) FillCircle(cx, cy, r float32, brush Brush) *SceneBuilder
FillCircle is a convenience method to fill a circle.
func (*SceneBuilder) FillPath ¶
func (b *SceneBuilder) FillPath(path *Path, brush Brush) *SceneBuilder
FillPath is a convenience method to fill a path wrapped as a shape.
func (*SceneBuilder) FillRect ¶
func (b *SceneBuilder) FillRect(x, y, width, height float32, brush Brush) *SceneBuilder
FillRect is a convenience method to fill a rectangle.
func (*SceneBuilder) FillWith ¶
func (b *SceneBuilder) FillWith(shape Shape, brush Brush, style FillStyle) *SceneBuilder
FillWith fills a shape with the given brush and fill style.
func (*SceneBuilder) Group ¶
func (b *SceneBuilder) Group(fn func(*SceneBuilder)) *SceneBuilder
Group creates a logical grouping of drawing operations. This is primarily for organizational purposes; no blending or clipping is applied. The callback receives the same builder.
Example:
builder.Group(func(b *SceneBuilder) {
b.Fill(rect1, SolidBrush(Red))
b.Fill(rect2, SolidBrush(Blue))
})
func (*SceneBuilder) Image ¶
func (b *SceneBuilder) Image(img *Image, rect Rect) *SceneBuilder
Image draws an image at the given rectangle. The image is scaled to fit the rectangle bounds.
func (*SceneBuilder) Layer ¶
func (b *SceneBuilder) Layer(blend BlendMode, alpha float32, clip Shape, fn func(*SceneBuilder)) *SceneBuilder
Layer creates a compositing layer with the given blend mode and alpha. The callback receives the same builder to add content to the layer. If clip is not nil, the layer content is clipped to that shape.
Example:
builder.Layer(BlendMultiply, 0.8, nil, func(b *SceneBuilder) {
b.Fill(circle, SolidBrush(Red))
})
func (*SceneBuilder) Reset ¶
func (b *SceneBuilder) Reset() *SceneBuilder
Reset clears the builder's scene and transform for reuse. Unlike Build(), this does not return the scene.
func (*SceneBuilder) ResetTransform ¶
func (b *SceneBuilder) ResetTransform() *SceneBuilder
ResetTransform resets the current transform to identity.
func (*SceneBuilder) Rotate ¶
func (b *SceneBuilder) Rotate(angle float32) *SceneBuilder
Rotate applies a rotation to the current transform (angle in radians). Rotations accumulate - use ResetTransform to clear.
func (*SceneBuilder) Scale ¶
func (b *SceneBuilder) Scale(x, y float32) *SceneBuilder
Scale applies a scale to the current transform. Scales accumulate - use ResetTransform to clear.
func (*SceneBuilder) Scene ¶
func (b *SceneBuilder) Scene() *Scene
Scene returns the current scene without resetting the builder. Use this to inspect the scene during construction.
func (*SceneBuilder) Stroke ¶
func (b *SceneBuilder) Stroke(shape Shape, brush Brush, width float32) *SceneBuilder
Stroke strokes a shape with the given brush and line width.
func (*SceneBuilder) StrokeCircle ¶
func (b *SceneBuilder) StrokeCircle(cx, cy, r float32, brush Brush, lineWidth float32) *SceneBuilder
StrokeCircle is a convenience method to stroke a circle.
func (*SceneBuilder) StrokePath ¶
func (b *SceneBuilder) StrokePath(path *Path, brush Brush, lineWidth float32) *SceneBuilder
StrokePath is a convenience method to stroke a path wrapped as a shape.
func (*SceneBuilder) StrokeRect ¶
func (b *SceneBuilder) StrokeRect(x, y, width, height float32, brush Brush, lineWidth float32) *SceneBuilder
StrokeRect is a convenience method to stroke a rectangle.
func (*SceneBuilder) StrokeWith ¶
func (b *SceneBuilder) StrokeWith(shape Shape, brush Brush, style *StrokeStyle) *SceneBuilder
StrokeWith strokes a shape with the given brush and stroke style.
func (*SceneBuilder) Transform ¶
func (b *SceneBuilder) Transform(t Affine) *SceneBuilder
Transform sets the current transform, replacing any existing transform.
func (*SceneBuilder) Translate ¶
func (b *SceneBuilder) Translate(x, y float32) *SceneBuilder
Translate applies a translation to the current transform. Translations accumulate - use ResetTransform to clear.
func (*SceneBuilder) WithTransform ¶
func (b *SceneBuilder) WithTransform(t Affine, fn func(*SceneBuilder)) *SceneBuilder
WithTransform executes the callback with a temporary transform applied. The transform is reset after the callback completes.
Example:
builder.WithTransform(TranslateAffine(100, 100), func(b *SceneBuilder) {
b.Fill(shape, brush) // drawn at (100, 100)
})
type ScenePool ¶
type ScenePool struct {
// contains filtered or unexported fields
}
ScenePool manages a pool of reusable Scene objects.
type Shape ¶
type Shape interface {
// ToPath converts the shape to a Path for encoding.
ToPath() *Path
// Bounds returns the bounding rectangle of the shape.
Bounds() Rect
}
Shape is the interface for geometric shapes that can be converted to paths. All shapes must be able to provide a path representation and their bounds.
type StarShape ¶
type StarShape struct {
CX, CY float32 // Center
OuterRadius float32 // Outer radius (points)
InnerRadius float32 // Inner radius (valleys)
Points int // Number of points
Rotation float32 // Rotation angle in radians
}
StarShape represents a star shape.
type StrokeStyle ¶
StrokeStyle contains stroke parameters.
func DefaultStrokeStyle ¶
func DefaultStrokeStyle() *StrokeStyle
DefaultStrokeStyle returns default stroke parameters.
type Tag ¶
type Tag byte
Tag represents a single-byte command identifier in the encoding stream. Tags are organized into groups by their high nibble:
0x0X: Transform operations 0x1X: Path commands 0x2X: Fill/Stroke operations 0x3X: Layer operations 0x4X: Clip operations 0x5X: Brush/Image operations
const ( // TagTransform encodes an affine transformation. // Data: 6 float32 values [a, b, c, d, e, f] representing the matrix: // | a b c | // | d e f | TagTransform Tag = 0x01 // TagBeginPath marks the start of a new path. // Data: none (marker only) TagBeginPath Tag = 0x10 // TagMoveTo moves the current point without drawing. // Data: 2 float32 values [x, y] TagMoveTo Tag = 0x11 // TagLineTo draws a line to the specified point. // Data: 2 float32 values [x, y] TagLineTo Tag = 0x12 // TagQuadTo draws a quadratic Bezier curve. // Data: 4 float32 values [cx, cy, x, y] (control point, end point) TagQuadTo Tag = 0x13 // TagCubicTo draws a cubic Bezier curve. // Data: 6 float32 values [c1x, c1y, c2x, c2y, x, y] (control1, control2, end) TagCubicTo Tag = 0x14 // TagClosePath closes the current subpath. // Data: none (uses implicit return to subpath start) TagClosePath Tag = 0x16 // TagEndPath marks the end of a path definition. // Data: none (marker only) TagEndPath Tag = 0x17 // TagFill fills the current path. // Data: 1 uint32 for brush index, 1 uint32 for fill style (NonZero=0, EvenOdd=1) TagFill Tag = 0x20 // TagStroke strokes the current path. // Data: 1 uint32 for brush index, then stroke style: // 4 float32: [lineWidth, miterLimit, lineCap, lineJoin] TagStroke Tag = 0x21 // TagPushLayer pushes a new compositing layer. // Data: 1 uint32 for blend mode, 1 float32 for alpha TagPushLayer Tag = 0x30 // TagPopLayer pops the current compositing layer. // Data: none TagPopLayer Tag = 0x31 // TagBeginClip begins a clipping region using the current path. // Data: none (uses current path as clip) TagBeginClip Tag = 0x40 // TagEndClip ends the current clipping region. // Data: none TagEndClip Tag = 0x41 // TagBrush defines a brush (solid color, gradient, etc.). // Data: variable depending on brush type // Solid: 4 float32 [r, g, b, a] TagBrush Tag = 0x50 // TagImage references an image resource. // Data: 1 uint32 for image index, 6 float32 for transform TagImage Tag = 0x51 )
Tag constants define all encoding commands. Each tag has a fixed data layout documented in its comment.
func (Tag) DataSize ¶
DataSize returns the number of float32 values this tag consumes from pathData. Returns -1 for tags that don't use pathData.
func (Tag) IsClipCommand ¶
IsClipCommand returns true if the tag is a clip command.
func (Tag) IsDrawCommand ¶
IsDrawCommand returns true if the tag is a draw command (fill/stroke).
func (Tag) IsLayerCommand ¶
IsLayerCommand returns true if the tag is a layer command.
func (Tag) IsPathCommand ¶
IsPathCommand returns true if the tag is a path construction command.
type TextRenderer ¶ added in v0.11.0
type TextRenderer struct {
// contains filtered or unexported fields
}
TextRenderer converts shaped text to scene paths for GPU rendering. It supports glyph outlines and handles positioning, transforms, and caching.
TextRenderer is safe for concurrent use.
func NewTextRenderer ¶ added in v0.11.0
func NewTextRenderer() *TextRenderer
NewTextRenderer creates a new text renderer with default configuration.
func NewTextRendererWithConfig ¶ added in v0.11.0
func NewTextRendererWithConfig(config TextRendererConfig) *TextRenderer
NewTextRendererWithConfig creates a new text renderer with the given configuration.
func (*TextRenderer) Config ¶ added in v0.11.0
func (r *TextRenderer) Config() TextRendererConfig
Config returns the current configuration.
func (*TextRenderer) RenderGlyph ¶ added in v0.11.0
func (r *TextRenderer) RenderGlyph(glyph text.ShapedGlyph, face text.Face) (*RenderedGlyph, error)
RenderGlyph converts a single shaped glyph to a renderable path. The path is positioned at the glyph's location and scaled appropriately.
func (*TextRenderer) RenderGlyphs ¶ added in v0.11.0
func (r *TextRenderer) RenderGlyphs(glyphs []text.ShapedGlyph, face text.Face) ([]*RenderedGlyph, error)
RenderGlyphs converts multiple shaped glyphs to renderable paths. Returns a slice of rendered glyphs in the same order as input.
func (*TextRenderer) RenderRun ¶ added in v0.11.0
func (r *TextRenderer) RenderRun(run *text.ShapedRun) ([]*RenderedGlyph, error)
RenderRun converts a shaped run to renderable glyphs.
func (*TextRenderer) RenderText ¶ added in v0.11.0
func (r *TextRenderer) RenderText(str string, face text.Face) ([]*RenderedGlyph, error)
RenderText shapes and renders text in one operation. Uses the global shaper for text shaping.
func (*TextRenderer) RenderTextToScene ¶ added in v0.11.0
func (r *TextRenderer) RenderTextToScene(s *Scene, str string, face text.Face, x, y float32, brush Brush) error
RenderTextToScene shapes and renders text directly into a scene.
func (*TextRenderer) RenderToScene ¶ added in v0.11.0
func (r *TextRenderer) RenderToScene(s *Scene, glyphs []text.ShapedGlyph, face text.Face, brush Brush) error
RenderToScene renders shaped glyphs directly into a scene. This is the primary method for GPU text rendering.
func (*TextRenderer) SetConfig ¶ added in v0.11.0
func (r *TextRenderer) SetConfig(config TextRendererConfig)
SetConfig updates the configuration.
func (*TextRenderer) ToCompositePath ¶ added in v0.11.0
func (r *TextRenderer) ToCompositePath(glyphs []*RenderedGlyph) *Path
ToCompositePath combines multiple rendered glyphs into a single path. This is useful for text that will be rendered as a single unit.
type TextRendererConfig ¶ added in v0.11.0
type TextRendererConfig struct {
// FlipY inverts the Y-axis for glyph outlines (default: false).
// Our OutlineExtractor preserves sfnt's Y-down convention
// (Y=0 at baseline, Y<0 above, Y>0 below), which matches
// screen coordinates directly. Set to true only if your
// coordinate system has Y increasing upward.
FlipY bool
// SubpixelPositioning enables fractional glyph positioning.
// When false, glyphs are snapped to integer pixel positions.
SubpixelPositioning bool
// HintingEnabled enables font hinting for sharper rendering at small sizes.
HintingEnabled bool
}
TextRendererConfig holds configuration for TextRenderer.
func DefaultTextRendererConfig ¶ added in v0.11.0
func DefaultTextRendererConfig() TextRendererConfig
DefaultTextRendererConfig returns the default configuration.
type TextRendererPool ¶ added in v0.11.0
type TextRendererPool struct {
// contains filtered or unexported fields
}
TextRendererPool manages a pool of TextRenderers for concurrent use.
func NewTextRendererPool ¶ added in v0.11.0
func NewTextRendererPool() *TextRendererPool
NewTextRendererPool creates a new pool of text renderers.
func (*TextRendererPool) Get ¶ added in v0.11.0
func (p *TextRendererPool) Get() *TextRenderer
Get retrieves a renderer from the pool.
func (*TextRendererPool) Put ¶ added in v0.11.0
func (p *TextRendererPool) Put(r *TextRenderer)
Put returns a renderer to the pool.
type TextShape ¶ added in v0.11.0
type TextShape struct {
// contains filtered or unexported fields
}
TextShape represents a shaped text string as a scene Shape. This allows text to be used with fill/stroke operations.
func NewTextShape ¶ added in v0.11.0
NewTextShape creates a TextShape from text. The text is shaped and converted to a path at the specified position.
type TransformShape ¶
type TransformShape struct {
// contains filtered or unexported fields
}
TransformShape wraps a shape with a transformation.
func NewTransformShape ¶
func NewTransformShape(shape Shape, transform Affine) *TransformShape
NewTransformShape creates a transformed shape.
func (*TransformShape) Bounds ¶
func (ts *TransformShape) Bounds() Rect
Bounds returns the transformed bounding rectangle. Note: This is a conservative approximation.
func (*TransformShape) ToPath ¶
func (ts *TransformShape) ToPath() *Path
ToPath converts the shape to a transformed Path.