212 lines
5.4 KiB
Go
212 lines
5.4 KiB
Go
package drawing
|
|
|
|
import (
|
|
"image"
|
|
"image/color"
|
|
|
|
"github.com/golang/freetype/truetype"
|
|
)
|
|
|
|
// StackGraphicContext is a context that does thngs.
|
|
type StackGraphicContext struct {
|
|
current *ContextStack
|
|
}
|
|
|
|
// ContextStack is a graphic context implementation.
|
|
type ContextStack struct {
|
|
Tr Matrix
|
|
Path *Path
|
|
LineWidth float64
|
|
Dash []float64
|
|
DashOffset float64
|
|
StrokeColor color.Color
|
|
FillColor color.Color
|
|
FillRule FillRule
|
|
Cap LineCap
|
|
Join LineJoin
|
|
|
|
FontSizePoints float64
|
|
Font *truetype.Font
|
|
|
|
Scale float64
|
|
|
|
Previous *ContextStack
|
|
}
|
|
|
|
// NewStackGraphicContext Create a new Graphic context from an image
|
|
func NewStackGraphicContext() *StackGraphicContext {
|
|
gc := &StackGraphicContext{}
|
|
gc.current = new(ContextStack)
|
|
gc.current.Tr = NewIdentityMatrix()
|
|
gc.current.Path = new(Path)
|
|
gc.current.LineWidth = 1.0
|
|
gc.current.StrokeColor = image.Black
|
|
gc.current.FillColor = image.White
|
|
gc.current.Cap = RoundCap
|
|
gc.current.FillRule = FillRuleEvenOdd
|
|
gc.current.Join = RoundJoin
|
|
gc.current.FontSizePoints = 10
|
|
return gc
|
|
}
|
|
|
|
// GetMatrixTransform returns the matrix transform.
|
|
func (gc *StackGraphicContext) GetMatrixTransform() Matrix {
|
|
return gc.current.Tr
|
|
}
|
|
|
|
// SetMatrixTransform sets the matrix transform.
|
|
func (gc *StackGraphicContext) SetMatrixTransform(tr Matrix) {
|
|
gc.current.Tr = tr
|
|
}
|
|
|
|
// ComposeMatrixTransform composes a transform into the current transform.
|
|
func (gc *StackGraphicContext) ComposeMatrixTransform(tr Matrix) {
|
|
gc.current.Tr.Compose(tr)
|
|
}
|
|
|
|
// Rotate rotates the matrix transform by an angle in degrees.
|
|
func (gc *StackGraphicContext) Rotate(angle float64) {
|
|
gc.current.Tr.Rotate(angle)
|
|
}
|
|
|
|
// Translate translates a transform.
|
|
func (gc *StackGraphicContext) Translate(tx, ty float64) {
|
|
gc.current.Tr.Translate(tx, ty)
|
|
}
|
|
|
|
// Scale scales a transform.
|
|
func (gc *StackGraphicContext) Scale(sx, sy float64) {
|
|
gc.current.Tr.Scale(sx, sy)
|
|
}
|
|
|
|
// SetStrokeColor sets the stroke color.
|
|
func (gc *StackGraphicContext) SetStrokeColor(c color.Color) {
|
|
gc.current.StrokeColor = c
|
|
}
|
|
|
|
// SetFillColor sets the fill color.
|
|
func (gc *StackGraphicContext) SetFillColor(c color.Color) {
|
|
gc.current.FillColor = c
|
|
}
|
|
|
|
// SetFillRule sets the fill rule.
|
|
func (gc *StackGraphicContext) SetFillRule(f FillRule) {
|
|
gc.current.FillRule = f
|
|
}
|
|
|
|
// SetLineWidth sets the line width.
|
|
func (gc *StackGraphicContext) SetLineWidth(lineWidth float64) {
|
|
gc.current.LineWidth = lineWidth
|
|
}
|
|
|
|
// SetLineCap sets the line cap.
|
|
func (gc *StackGraphicContext) SetLineCap(cap LineCap) {
|
|
gc.current.Cap = cap
|
|
}
|
|
|
|
// SetLineJoin sets the line join.
|
|
func (gc *StackGraphicContext) SetLineJoin(join LineJoin) {
|
|
gc.current.Join = join
|
|
}
|
|
|
|
// SetLineDash sets the line dash.
|
|
func (gc *StackGraphicContext) SetLineDash(dash []float64, dashOffset float64) {
|
|
gc.current.Dash = dash
|
|
gc.current.DashOffset = dashOffset
|
|
}
|
|
|
|
// SetFontSize sets the font size.
|
|
func (gc *StackGraphicContext) SetFontSize(fontSizePoints float64) {
|
|
gc.current.FontSizePoints = fontSizePoints
|
|
}
|
|
|
|
// GetFontSize gets the font size.
|
|
func (gc *StackGraphicContext) GetFontSize() float64 {
|
|
return gc.current.FontSizePoints
|
|
}
|
|
|
|
// SetFont sets the current font.
|
|
func (gc *StackGraphicContext) SetFont(f *truetype.Font) {
|
|
gc.current.Font = f
|
|
}
|
|
|
|
// GetFont returns the font.
|
|
func (gc *StackGraphicContext) GetFont() *truetype.Font {
|
|
return gc.current.Font
|
|
}
|
|
|
|
// BeginPath starts a new path.
|
|
func (gc *StackGraphicContext) BeginPath() {
|
|
gc.current.Path.Clear()
|
|
}
|
|
|
|
// IsEmpty returns if the path is empty.
|
|
func (gc *StackGraphicContext) IsEmpty() bool {
|
|
return gc.current.Path.IsEmpty()
|
|
}
|
|
|
|
// LastPoint returns the last point on the path.
|
|
func (gc *StackGraphicContext) LastPoint() (x float64, y float64) {
|
|
return gc.current.Path.LastPoint()
|
|
}
|
|
|
|
// MoveTo moves the cursor for a path.
|
|
func (gc *StackGraphicContext) MoveTo(x, y float64) {
|
|
gc.current.Path.MoveTo(x, y)
|
|
}
|
|
|
|
// LineTo draws a line.
|
|
func (gc *StackGraphicContext) LineTo(x, y float64) {
|
|
gc.current.Path.LineTo(x, y)
|
|
}
|
|
|
|
// QuadCurveTo draws a quad curve.
|
|
func (gc *StackGraphicContext) QuadCurveTo(cx, cy, x, y float64) {
|
|
gc.current.Path.QuadCurveTo(cx, cy, x, y)
|
|
}
|
|
|
|
// CubicCurveTo draws a cubic curve.
|
|
func (gc *StackGraphicContext) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) {
|
|
gc.current.Path.CubicCurveTo(cx1, cy1, cx2, cy2, x, y)
|
|
}
|
|
|
|
// ArcTo draws an arc.
|
|
func (gc *StackGraphicContext) ArcTo(cx, cy, rx, ry, startAngle, angle float64) {
|
|
gc.current.Path.ArcTo(cx, cy, rx, ry, startAngle, angle)
|
|
}
|
|
|
|
// Close closes a path.
|
|
func (gc *StackGraphicContext) Close() {
|
|
gc.current.Path.Close()
|
|
}
|
|
|
|
// Save pushes a context onto the stack.
|
|
func (gc *StackGraphicContext) Save() {
|
|
context := new(ContextStack)
|
|
context.FontSizePoints = gc.current.FontSizePoints
|
|
context.Font = gc.current.Font
|
|
context.LineWidth = gc.current.LineWidth
|
|
context.StrokeColor = gc.current.StrokeColor
|
|
context.FillColor = gc.current.FillColor
|
|
context.FillRule = gc.current.FillRule
|
|
context.Dash = gc.current.Dash
|
|
context.DashOffset = gc.current.DashOffset
|
|
context.Cap = gc.current.Cap
|
|
context.Join = gc.current.Join
|
|
context.Path = gc.current.Path.Copy()
|
|
context.Font = gc.current.Font
|
|
context.Scale = gc.current.Scale
|
|
copy(context.Tr[:], gc.current.Tr[:])
|
|
context.Previous = gc.current
|
|
gc.current = context
|
|
}
|
|
|
|
// Restore restores the previous context.
|
|
func (gc *StackGraphicContext) Restore() {
|
|
if gc.current.Previous != nil {
|
|
oldContext := gc.current
|
|
gc.current = gc.current.Previous
|
|
oldContext.Previous = nil
|
|
}
|
|
}
|