Documentation
¶
Overview ¶
Package stilus is a sparse CPU rasterizer for 2D vector graphics.
Its cost per path is the length of the path's edges in pixels plus the covered spans, never the area of the bounding box or the width of the canvas. It knows nothing about PDF, fonts or color spaces and has no dependencies, so it can serve as the CPU backend of a PDF renderer, a UI toolkit or another 2D library (for example as the CPU filler behind gogpu/gg).
Layers ¶
Each layer can be used on its own:
- Rasterizer turns device-space paths (Fill, or AddLine/AddPath and Rasterize) into coverage spans delivered to a Blitter: BlitRun for the constant interior runs of wide shapes, BlitCoverage for antialiased edge pixels and for narrow shapes as a whole. Implement Blitter to composite into any pixel format.
- Stroker turns a stroke (width, caps, joins, miter limit, dashes; all in user space, exact under anisotropic transforms) into fill geometry for a LineSink, such as a Rasterizer or a PathSink.
- Canvas combines both with a clip stack and compositing onto a caller-owned *image.RGBA. Its methods map one to one onto a display-list device: Fill, Stroke, ClipPath, ClipRect, ClipStroke, PopClip.
- Shaders paint what a solid colour cannot, per span: ImageShader (Texture with mip levels), LinearGradient and RadialGradient (a Ramp of colours), LayerShader (a layer with opacity, mask and BlendMode), MaskShader and GlyphCache (glyph coverage masks). FillMesh draws Gouraud-shaded triangles into a layer.
Performance model ¶
Edges are accumulated as signed area and cover into a band of cells (32 rows × clip width) in 24.8 fixed point. Per row, the touched cell range is integrated directly when it is narrow; wide rows are swept with a dirty bitset that skips untouched cells, and the constant stretches between edges are emitted as runs that blitters fill without a per-pixel loop. Nothing is cleared as a whole: the sweep zeroes what it reads.
Strokes are filled analytically between their corners: rows bounded only by a segment's two parallel sides get each pixel's exact area in closed form; only the rows around joins and caps go through the accumulator. Strokes thinner than one device pixel are drawn one pixel wide. Rectangle clips cost nothing per pixel; other clips are rasterized once into a mask over their bounds.
All buffers grow on demand and are retained: after warm-up, drawing performs no allocations. Rasterizer, Stroker and Canvas are not safe for concurrent use; use one per worker and give each worker its own band or tile of the destination (Canvas.Reset takes a region).
Robustness ¶
NaN and infinite coordinates are rejected, huge ones are clipped analytically, curve and arc subdivision and dash counts are bounded, and the edge count per path is budgeted (Rasterizer.MaxEdges). Canvas never panics; it reports problems through Err and keeps drawing.
Example ¶
package main
import (
"fmt"
"image"
"image/color"
"github.com/timzifer/stilus"
)
func main() {
img := image.NewRGBA(image.Rect(0, 0, 200, 100))
c := stilus.NewCanvas(img)
// Page space in points, drawn at 144 dpi.
m := stilus.Scale(2, 2)
c.ClipRect(stilus.Rect{X0: 5, Y0: 5, X1: 95, Y1: 45}, m)
var p stilus.Path
p.MoveTo(10, 40)
p.CubicTo(30, 0, 70, 80, 90, 10)
c.Stroke(&p, m, &stilus.StrokeStyle{Width: 1.5, Cap: stilus.RoundCap}, &stilus.Paint{Color: color.RGBA{0, 0, 0, 255}})
var r stilus.Path
r.Ellipse(50, 25, 20, 12)
c.Fill(&r, m, stilus.NonZero, &stilus.Paint{Color: color.RGBA{0, 0, 128, 128}}) // premultiplied
c.PopClip()
fmt.Println(c.Err())
}
Output: <nil>
Index ¶
- Constants
- Variables
- func Blend(bm BlendMode, cb, cs [3]float64) [3]float64
- func FillMesh(dst *image.RGBA, region image.Rectangle, tris []MeshTriangle, m Matrix, ...)
- func IsHairline(m Matrix, st *StrokeStyle) bool
- func PackRGBA(c color.RGBA) uint32
- func SIMD() bool
- func UnpackRGBA(v uint32) color.RGBA
- type BlendMode
- type Blitter
- type Canvas
- func (c *Canvas) Clip() image.Rectangle
- func (c *Canvas) ClipDepth() int
- func (c *Canvas) ClipPath(p *Path, m Matrix, rule FillRule)
- func (c *Canvas) ClipRect(r Rect, m Matrix)
- func (c *Canvas) ClipStroke(p *Path, m Matrix, st *StrokeStyle)
- func (c *Canvas) Err() error
- func (c *Canvas) Fill(p *Path, m Matrix, rule FillRule, paint *Paint)
- func (c *Canvas) PopClip()
- func (c *Canvas) Reset(dst *image.RGBA, region image.Rectangle)
- func (c *Canvas) Stroke(p *Path, m Matrix, st *StrokeStyle, paint *Paint)
- type Cap
- type FillRule
- type GlyphCache
- type Gradient
- type ImageShader
- type Join
- type LayerShader
- type LineSink
- type LinearGradient
- type MaskBlitter
- type MaskShader
- type Matrix
- type MeshTriangle
- type MeshVertex
- type Paint
- type Palette
- type Path
- func (p *Path) Bounds() Rect
- func (p *Path) Close()
- func (p *Path) CubicTo(c1x, c1y, c2x, c2y, x, y float32)
- func (p *Path) Ellipse(cx, cy, rx, ry float32)
- func (p *Path) Empty() bool
- func (p *Path) LineTo(x, y float32)
- func (p *Path) MoveTo(x, y float32)
- func (p *Path) QuadTo(cx, cy, x, y float32)
- func (p *Path) Rect(x, y, w, h float32)
- func (p *Path) Reset()
- type PathSink
- type Plane
- type PlaneKind
- type Point
- type RadialGradient
- type Ramp
- type Rasterizer
- func (r *Rasterizer) AddLine(x0, y0, x1, y1 float64)
- func (r *Rasterizer) AddPath(p *Path, m Matrix)
- func (r *Rasterizer) Clip() image.Rectangle
- func (r *Rasterizer) Fill(p *Path, m Matrix, rule FillRule, b Blitter)
- func (r *Rasterizer) Rasterize(rule FillRule, b Blitter)
- func (r *Rasterizer) Reset()
- func (r *Rasterizer) SetAntialias(aa bool)
- func (r *Rasterizer) SetClip(clip image.Rectangle)
- func (r *Rasterizer) Truncated() bool
- type Rect
- type Sampler
- type Shader
- type ShaderBlitter
- type SolidBlitter
- type StrokeStyle
- type Stroker
- type Texture
- type Verb
Examples ¶
Constants ¶
const ( // MaxCachedEm is the em size in device pixels above which glyphs are // filled as paths: large glyphs are few, and their masks big. MaxCachedEm = 160 // DefaultGlyphCacheBytes bounds the masks of a cache whose MaxBytes // is zero; a full cache evicts masks to make room. DefaultGlyphCacheBytes = 4 << 20 )
const DefaultMaxClipDepth = 256
DefaultMaxClipDepth bounds the clip stack of a Canvas.
const DefaultMaxDashes = 1 << 20
DefaultMaxDashes bounds dash transitions per subpath. Subpaths estimated to exceed the budget are skipped; the subdivision loop also stops at the budget. Stroker.Truncated reports either condition.
const (
// DefaultMaxEdges is the default edge budget per path.
DefaultMaxEdges = 1 << 22
)
Variables ¶
var ( ErrEdgeBudget = errors.New("stilus: edge budget exceeded, path truncated") ErrDashBudget = errors.New("stilus: dash budget exceeded, stroke truncated") ErrClipDepth = errors.New("stilus: clip stack too deep") ErrInternal = errors.New("stilus: internal error") )
Errors reported by Canvas.Err.
var GrayPalette, AlphaPalette = func() (*Palette, *Palette) {
var g, a Palette
for i := range 256 {
v := uint8(i)
g[i] = pack(v, v, v, 255)
a[i] = pack(v, v, v, v)
}
return &g, &a
}()
Shared palettes: opaque greys and levels of alpha (white premultiplied, so all four channels are the level). They must not be modified.
var Identity = Matrix{1, 0, 0, 1, 0, 0}
Identity is the identity transform.
Functions ¶
func Blend ¶ added in v0.5.0
Blend returns B(Cb, Cs), the blend function of bm, for a backdrop and a source colour of straight components in [0, 1].
func FillMesh ¶ added in v0.5.0
FillMesh draws tris, transformed by m into device space, into dst within region, interpolating the colours of their vertices linearly (or, with a non-empty ramp, their parameters, looked up in the ramp). Pixels are replaced, not composited: the mesh is meant to be drawn into a transparent layer that is then composited through a Canvas, for example with a LayerShader, so that the mesh is clipped and blended like any fill. A triangle covers the pixels whose centres lie inside it, by the top-left rule, without antialiasing, so that triangles sharing an edge leave no seam and draw no pixel twice; later triangles overwrite earlier ones where they overlap.
func IsHairline ¶
func IsHairline(m Matrix, st *StrokeStyle) bool
IsHairline reports whether st under m is thinner than one device pixel in every direction. Such strokes are drawn one pixel wide in device space, like PDFium.
func PackRGBA ¶
PackRGBA packs a premultiplied color into the native pixel layout used by Shader.ShadeSpan.
Types ¶
type BlendMode ¶ added in v0.5.0
type BlendMode uint8
BlendMode is a separable or non-separable blend mode of the W3C Compositing and Blending specification, which are also those of PDF (ISO 32000-2, 11.3.5) and of SVG and CSS.
type Blitter ¶
type Blitter interface {
// BlitRun paints the constant coverage alpha over [x0, x1) on row y:
// the constant stretches between the edges of wide shapes.
BlitRun(y, x0, x1 int, alpha uint8)
// BlitCoverage paints per-pixel coverage for [x, x+len(cov)) on row y.
// Narrow shapes (strokes, glyphs) arrive here as a whole, fully
// covered pixels included.
BlitCoverage(y, x int, cov []uint8)
}
Blitter receives the output of the rasterizer, one span at a time, in increasing y order and, within a row, in increasing x order. Spans never overlap and always lie inside the rasterizer's clip.
Implementations must not retain cov after the call returns.
type Canvas ¶
type Canvas struct {
// MaxClipDepth overrides DefaultMaxClipDepth when non-zero.
MaxClipDepth int
// contains filtered or unexported fields
}
Canvas draws paths onto a caller-owned *image.RGBA (premultiplied, as image.RGBA always is). It combines the rasterizer, the stroker and a clip stack, and maps one to one onto a display-list device: Fill/Stroke/ClipPath/ClipRect/PopClip.
Device space is the pixel space of the destination image, so a tile or band is rendered by passing an image whose Rect is that tile, or by restricting Reset's region. A Canvas is not safe for concurrent use; use one per worker. After warm-up a Canvas does not allocate.
func (*Canvas) ClipPath ¶
ClipPath intersects the clip with p under m. Rectangles ("re W n") take the rectangle fast path; other shapes are rasterized once into a mask over their bounds.
func (*Canvas) ClipRect ¶
ClipRect intersects the clip with rectangle r in user space. An axis-aligned result costs nothing per pixel; a rotated one becomes a mask.
func (*Canvas) ClipStroke ¶ added in v0.5.0
func (c *Canvas) ClipStroke(p *Path, m Matrix, st *StrokeStyle)
ClipStroke intersects the clip with the area a stroke of p with style st (in user space) under m paints, with the stroke's coverage: text in a stroking clip mode, or a stroke painted with a shader that only reaches the stroke as a clip. The area is rasterized once into a mask.
func (*Canvas) Err ¶
Err returns the first error since Reset, if any. Drawing continues after an error; the error only reports that output may be incomplete.
type GlyphCache ¶ added in v0.5.0
type GlyphCache struct {
// MaxBytes bounds the masks kept; 0 means DefaultGlyphCacheBytes.
MaxBytes int
// contains filtered or unexported fields
}
GlyphCache is a cache of glyph coverage masks. The zero value is ready to use.
func (*GlyphCache) FillGlyph ¶ added in v0.5.0
func (gc *GlyphCache) FillGlyph(c *Canvas, font uint64, glyph int32, outline *Path, m Matrix, paint *Paint)
FillGlyph fills outline (nonzero), transformed by m into device space, with paint through c. The outline is identified by font and glyph: the cache assumes that equal ids have equal outlines. Small glyphs painted with a solid colour are drawn from the cache; large ones, and any glyph painted with a shader, are filled as paths.
type Gradient ¶ added in v0.5.0
type Gradient struct {
// Ramp maps the gradient's parameter to colours.
Ramp Ramp
// Extend continues the colour at t = 0 before the start (Extend[0])
// and the colour at t = 1 past the end (Extend[1]); where the gradient
// does not extend it paints Outside.
Extend [2]bool
// Outside is the premultiplied colour (PackRGBA layout) painted
// where the gradient is not defined; 0 is transparent.
Outside uint32
// Alpha multiplies the gradient's colours; 255 is opaque, 0 paints
// nothing.
Alpha uint8
}
Gradient is what linear and radial gradients share.
type ImageShader ¶ added in v0.5.0
type ImageShader struct {
// contains filtered or unexported fields
}
ImageShader paints a texture (or a solid colour) times a constant alpha, times an optional mask texture whose colours are levels of alpha (all four channels equal, such as AlphaPalette). The zero value paints transparent black; set it up with SetColor or SetImage, and SetMask.
func (*ImageShader) Reset ¶ added in v0.5.0
func (s *ImageShader) Reset()
Reset clears the shader, keeping its buffer, and drops its textures.
func (*ImageShader) SetColor ¶ added in v0.5.0
func (s *ImageShader) SetColor(c uint32)
SetColor paints the premultiplied colour c (PackRGBA layout) instead of a texture: a stencil.
func (*ImageShader) SetImage ¶ added in v0.5.0
SetImage paints t, whose base pixel space toDevice maps to device space, with constant alpha. It reports false if t cannot be drawn so.
func (*ImageShader) SetMask ¶ added in v0.5.0
func (s *ImageShader) SetMask(t *Texture, toDevice Matrix, smooth bool) bool
SetMask multiplies the paint by mask texture t, whose base pixel space toDevice maps to device space. It reports false if t cannot be drawn so.
func (*ImageShader) ShadeSpan ¶ added in v0.5.0
func (s *ImageShader) ShadeSpan(y, x int, dst []uint32)
ShadeSpan implements Shader.
type LayerShader ¶ added in v0.5.0
type LayerShader struct {
// Src is the layer, premultiplied like any image.RGBA; spans must lie
// within its rectangle.
Src *image.RGBA
// Dst is the backdrop the canvas draws onto, read for blend modes
// other than Normal.
Dst *image.RGBA
// Mask, when non-nil, multiplies the layer; it is 0 outside its
// rectangle.
Mask *image.Alpha
// Alpha is the constant opacity of the layer.
Alpha uint8
Blend BlendMode
}
LayerShader composites a layer, an isolated group drawn into an image of its own, onto the backdrop it is drawn over: the layer's pixels times Alpha and the optional Mask, blended with the backdrop by Blend. Fill the layer's rectangle with it through a Canvas, so that the layer is composited through the clip stack and antialiased at the clip's edges like any fill.
Blend modes are exact under partial coverage: the canvas composites the shader's colour s over the backdrop d with coverage a as a·s + d·(1−a·αs), and the shader returns s = cs·(1−αb) + αs·αb·B(Cb, Cs) with alpha αs, which makes that the compositing formula of the specification interpolated by coverage.
func (*LayerShader) ShadeSpan ¶ added in v0.5.0
func (c *LayerShader) ShadeSpan(y, x int, out []uint32)
ShadeSpan implements Shader.
type LineSink ¶
type LineSink interface {
AddLine(x0, y0, x1, y1 float64)
}
LineSink receives device-space line segments. Segments emitted by the Stroker form closed polygons that must be filled with the NonZero rule. *Rasterizer implements LineSink.
type LinearGradient ¶ added in v0.5.0
type LinearGradient struct {
Gradient
// contains filtered or unexported fields
}
LinearGradient is an axial gradient: t runs from 0 at P0 to 1 at P1 and is constant on lines perpendicular to P0P1 (in the gradient's own space, which may be mapped to device space by any affine transform).
func (*LinearGradient) Set ¶ added in v0.5.0
func (g *LinearGradient) Set(x0, y0, x1, y1 float64, m Matrix) bool
Set places the gradient from (x0, y0) to (x1, y1) in a space that m maps to device space, and reports whether it can be drawn: false for coincident points and singular or non-finite transforms. It keeps Ramp, Extend, Outside and Alpha.
func (*LinearGradient) ShadeSpan ¶ added in v0.5.0
func (g *LinearGradient) ShadeSpan(y, x int, dst []uint32)
ShadeSpan implements Shader.
type MaskBlitter ¶
MaskBlitter accumulates coverage into an 8-bit alpha image (for clip masks, soft masks and tests). Coverage is combined with "max", which is exact for the non-overlapping spans of a single rasterization.
func (*MaskBlitter) BlitCoverage ¶
func (b *MaskBlitter) BlitCoverage(y, x int, cov []uint8)
func (*MaskBlitter) BlitRun ¶
func (b *MaskBlitter) BlitRun(y, x0, x1 int, alpha uint8)
type MaskShader ¶ added in v0.5.0
MaskShader paints a solid premultiplied colour (PackRGBA layout) through a coverage mask whose origin is at (X, Y) in device space. Spans must lie within the mask's rectangle moved by (X, Y).
func (*MaskShader) ShadeSpan ¶ added in v0.5.0
func (s *MaskShader) ShadeSpan(y, x int, dst []uint32)
ShadeSpan implements Shader.
type Matrix ¶
type Matrix [6]float64
Matrix is an affine transform in PDF order [a b c d e f]:
x' = a·x + c·y + e y' = b·x + d·y + f
type MeshTriangle ¶ added in v0.5.0
type MeshTriangle [3]MeshVertex
MeshTriangle is a Gouraud-shaded triangle.
type MeshVertex ¶ added in v0.5.0
type MeshVertex struct {
X, Y float32
C uint32 // premultiplied, PackRGBA layout
T float32 // parameter into the ramp, 0 to 1
}
MeshVertex is a vertex of a Gouraud-shaded triangle: a point and either a premultiplied colour or a parameter into a Ramp.
type Paint ¶
Paint describes what a fill or stroke paints: a solid premultiplied color, or a Shader when Shader is non-nil.
type Palette ¶ added in v0.5.0
type Palette [256]uint32
Palette maps samples to premultiplied colours in PackRGBA layout.
type Path ¶
Path is a sequence of subpaths. The zero value is an empty path ready to use. Reset keeps the backing storage, so a Path can be rebuilt many times without allocating.
type Plane ¶ added in v0.5.0
type Plane struct {
Kind PlaneKind
W, H int
Stride int // pixels per row for PlaneRGBA and PlaneIndex, bytes for PlaneBits
Pix8 []uint8
Pix32 []uint32
Pal *Palette
}
Plane is a picture of W × H pixels.
type Point ¶
type Point struct{ X, Y float32 }
Point is a 2D point. Path coordinates are stored as float32 to keep paths (and display lists built on top of them) compact.
type RadialGradient ¶ added in v0.5.0
type RadialGradient struct {
Gradient
// contains filtered or unexported fields
}
RadialGradient is a gradient between two circles: the circle at t has its centre at C0 + t·(C1 − C0) and its radius r0 + t·(r1 − r0), and a point takes the colour of the largest t whose circle passes through it with a radius ≥ 0 (in the extended range, if the gradient extends). This is the two-point conical gradient of PDF (type 3 shadings), of the HTML canvas and of SVG with a focal point.
func (*RadialGradient) Set ¶ added in v0.5.0
func (g *RadialGradient) Set(x0, y0, r0, x1, y1, r1 float64, m Matrix) bool
Set places the gradient between the circles (x0, y0, r0) and (x1, y1, r1) in a space that m maps to device space, and reports whether it can be drawn: false for negative radii and singular or non-finite transforms. It keeps Ramp, Extend, Outside and Alpha.
func (*RadialGradient) ShadeSpan ¶ added in v0.5.0
func (g *RadialGradient) ShadeSpan(y, x int, dst []uint32)
ShadeSpan implements Shader.
type Ramp ¶ added in v0.5.0
type Ramp []uint32
Ramp is a colour ramp: premultiplied colours (PackRGBA layout) at evenly spaced parameters from 0 to 1. A gradient with an empty ramp paints nothing.
type Rasterizer ¶
type Rasterizer struct {
// MaxEdges bounds the number of edges per path. Edges beyond it are
// dropped and Truncated reports true. Zero means DefaultMaxEdges.
MaxEdges int
// contains filtered or unexported fields
}
Rasterizer converts paths into coverage spans. Its cost per path is the length of the path's edges in pixels plus the number of covered spans; it never touches the area of the bounding box.
A Rasterizer is not safe for concurrent use; use one per worker. All buffers grow on demand and are retained, so steady-state use performs no allocations.
Example ¶
package main
import (
"fmt"
"image"
"github.com/timzifer/stilus"
)
// areaBlitter shows the span interface used to plug the rasterizer into
// another compositor: it just integrates the coverage.
type areaBlitter struct{ area int }
func (b *areaBlitter) BlitRun(y, x0, x1 int, alpha uint8) { b.area += (x1 - x0) * int(alpha) }
func (b *areaBlitter) BlitCoverage(y, x int, cov []uint8) {
for _, a := range cov {
b.area += int(a)
}
}
func main() {
r := stilus.NewRasterizer(image.Rect(0, 0, 100, 100))
var p stilus.Path
p.Rect(10.5, 10.5, 50, 30)
p.Rect(20, 60, 400, 10) // wide: interior rows arrive as runs
var b areaBlitter
r.Fill(&p, stilus.Identity, stilus.NonZero, &b)
fmt.Printf("%.0f px²\n", float64(b.area)/255)
}
Output: 2300 px²
func NewRasterizer ¶
func NewRasterizer(clip image.Rectangle) *Rasterizer
NewRasterizer returns a rasterizer clipped to clip.
func (*Rasterizer) AddLine ¶
func (r *Rasterizer) AddLine(x0, y0, x1, y1 float64)
AddLine adds a device-space line segment. Segments are clipped analytically: parts above or below the clip are dropped, parts right of it are dropped, and parts left of it become vertical edges on the clip's left border, which preserves the winding of everything inside.
func (*Rasterizer) AddPath ¶
func (r *Rasterizer) AddPath(p *Path, m Matrix)
AddPath adds the edges of p transformed by m. Open subpaths are closed implicitly. Curves are flattened in device space with a tolerance of a quarter pixel. Paths containing NaN or infinite values are ignored.
func (*Rasterizer) Clip ¶
func (r *Rasterizer) Clip() image.Rectangle
Clip returns the current clip rectangle.
func (*Rasterizer) Fill ¶
func (r *Rasterizer) Fill(p *Path, m Matrix, rule FillRule, b Blitter)
Fill rasterizes p transformed by m with the given fill rule. It is equivalent to Reset, AddPath and Rasterize.
func (*Rasterizer) Rasterize ¶
func (r *Rasterizer) Rasterize(rule FillRule, b Blitter)
Rasterize converts all added edges into spans and resets the rasterizer.
func (*Rasterizer) Reset ¶
func (r *Rasterizer) Reset()
Reset discards all accumulated edges and the Truncated state.
func (*Rasterizer) SetAntialias ¶
func (r *Rasterizer) SetAntialias(aa bool)
SetAntialias enables (default) or disables antialiasing. Without antialiasing a pixel is covered when at least half of it is inside.
func (*Rasterizer) SetClip ¶
func (r *Rasterizer) SetClip(clip image.Rectangle)
SetClip sets the device-space clip rectangle. Every span produced lies inside it. Buffers are resized only when the clip grows.
func (*Rasterizer) Truncated ¶
func (r *Rasterizer) Truncated() bool
Truncated reports whether the last path exceeded the edge budget.
type Rect ¶
type Rect struct{ X0, Y0, X1, Y1 float64 }
Rect is an axis-aligned rectangle [X0,X1)×[Y0,Y1).
type Sampler ¶ added in v0.5.0
type Sampler struct {
// contains filtered or unexported fields
}
Sampler reads a texture at device pixels.
func (*Sampler) Release ¶ added in v0.5.0
func (s *Sampler) Release()
Release drops the sampler's reference to its texture.
func (*Sampler) Sample ¶ added in v0.5.0
Sample writes the colours of pixels [x, x+len(dst)) of row y. Every pixel's coordinates are computed from its own position rather than accumulated along the span, so that a pixel samples the same texel whichever band, tile or span it is drawn in. Outside the texture the edge pixels repeat.
func (*Sampler) Setup ¶ added in v0.5.0
Setup chooses the mip level of t for drawing it with toDevice, which maps its base pixel space to device space, and reports whether t can be drawn so (toDevice is invertible). Magnified textures are sampled at the nearest pixel unless smooth is set; reduced ones bilinearly from the level at most twice as fine as the device.
type Shader ¶
Shader produces premultiplied colors (in PackRGBA layout) for the pixels [x, x+len(dst)) on row y. It is called once per span, never per pixel.
type ShaderBlitter ¶
type ShaderBlitter struct {
// contains filtered or unexported fields
}
ShaderBlitter composites the output of a Shader onto an image.RGBA.
func NewShaderBlitter ¶
func NewShaderBlitter(dst *image.RGBA, s Shader) *ShaderBlitter
NewShaderBlitter returns a blitter painting s onto dst.
func (*ShaderBlitter) BlitCoverage ¶
func (b *ShaderBlitter) BlitCoverage(y, x int, cov []uint8)
func (*ShaderBlitter) BlitRun ¶
func (b *ShaderBlitter) BlitRun(y, x0, x1 int, alpha uint8)
type SolidBlitter ¶
type SolidBlitter struct {
// contains filtered or unexported fields
}
SolidBlitter composites a single premultiplied color onto an image.RGBA.
func NewSolidBlitter ¶
func NewSolidBlitter(dst *image.RGBA, c color.RGBA) *SolidBlitter
NewSolidBlitter returns a blitter painting c (premultiplied) onto dst.
func (*SolidBlitter) BlitCoverage ¶
func (b *SolidBlitter) BlitCoverage(y, x int, cov []uint8)
func (*SolidBlitter) BlitRun ¶
func (b *SolidBlitter) BlitRun(y, x0, x1 int, alpha uint8)
func (*SolidBlitter) Reset ¶
func (b *SolidBlitter) Reset(dst *image.RGBA, c color.RGBA)
Reset retargets the blitter without allocating.
func (*SolidBlitter) SetColor ¶
func (b *SolidBlitter) SetColor(c color.RGBA)
SetColor changes the paint color (premultiplied).
type StrokeStyle ¶
type StrokeStyle struct {
Width float64 // 0 means the thinnest line the device can render
Cap Cap
Join Join
MiterLimit float64 // PDF default 10; values < 1 are treated as 1
Dash []float64 // on/off lengths; empty means solid
DashPhase float64
}
StrokeStyle describes a stroke in user space (the space the path is defined in), like the PDF graphics state.
type Stroker ¶
type Stroker struct {
// MaxDashes overrides DefaultMaxDashes when non-zero.
MaxDashes int
// contains filtered or unexported fields
}
Stroker converts strokes into fill geometry (closed outlines to be filled with NonZero). Offsets are computed in user space and transformed afterwards, which is exact for anisotropic transforms.
A Stroker is not safe for concurrent use. Buffers are retained.
func (*Stroker) Coverage ¶ added in v0.1.1
Coverage reports the factor to apply to the coverage of the last stroke's outline: the mean on-fraction of a dash pattern emitted as a solid stroke, else 1.
func (*Stroker) Stroke ¶
func (s *Stroker) Stroke(sink LineSink, p *Path, m Matrix, st *StrokeStyle)
Stroke emits the outline of p stroked with st under m into sink.
A dash pattern too dense to resolve in device space is emitted as a solid stroke; Coverage then reports the fraction the caller must scale the resulting coverage by.
type Texture ¶ added in v0.5.0
type Texture struct {
// contains filtered or unexported fields
}
Texture is a Plane and its mip levels, made on demand. It is safe for concurrent use: levels may be requested by several workers at once. The base plane must not change once the texture is made.
func NewTexture ¶ added in v0.5.0
NewTexture returns a texture of p.
func (*Texture) Level ¶ added in v0.5.0
Level returns mip level k (0 is the base), making it if needed.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
stilus-scenes
command
Command stilus-scenes renders the benchmark scenes, prints timings and allocations and optionally writes PNGs for visual inspection.
|
Command stilus-scenes renders the benchmark scenes, prints timings and allocations and optionally writes PNGs for visual inspection. |
|
internal
|
|
|
scenes
Package scenes provides deterministic benchmark scenes modelled on technical drawings: an A3 landscape page in PDF points, drawn under a scale to the requested resolution with a rectangular page clip.
|
Package scenes provides deterministic benchmark scenes modelled on technical drawings: an A3 landscape page in PDF points, drawn under a scale to the requested resolution with a rectangular page clip. |