canvas/draw.go

141 lines
2.8 KiB
Go

package canvas
import (
"image"
"image/color"
"image/draw"
"math"
)
// Fill 填充当前路径
func (c *Context) Fill() {
if len(c.path.points) < 3 {
return
}
// 应用阴影
if c.state.shadowBlur > 0 || c.state.shadowOffsetX != 0 || c.state.shadowOffsetY != 0 {
c.drawShadow(true)
}
// 创建多边形
poly := make([]image.Point, len(c.path.points))
for i, p := range c.path.points {
poly[i] = p
}
// 绘制填充
switch style := c.state.fillStyle.(type) {
case color.Color:
fillColor := c.applyAlpha(style)
draw.DrawMask(c.img, c.img.Bounds(),
image.NewUniform(fillColor),
image.Point{},
&filledPolygon{poly},
image.Point{},
draw.Over)
case Gradient:
draw.DrawMask(c.img, c.img.Bounds(),
&gradientImage{grad: style, alpha: c.state.globalAlpha},
image.Point{},
&filledPolygon{poly},
image.Point{},
draw.Over)
}
}
// Stroke 描边当前路径
func (c *Context) Stroke() {
if len(c.path.points) < 2 {
return
}
// 应用阴影
if c.state.shadowBlur > 0 || c.state.shadowOffsetX != 0 || c.state.shadowOffsetY != 0 {
c.drawShadow(false)
}
// 绘制线段
for i := 0; i < len(c.path.points)-1; i++ {
c.drawLine(c.path.points[i], c.path.points[i+1])
}
}
// FillRect 填充矩形
func (c *Context) FillRect(x, y, width, height float64) {
c.BeginPath()
c.Rect(x, y, width, height)
c.Fill()
}
// StrokeRect 描边矩形
func (c *Context) StrokeRect(x, y, width, height float64) {
c.BeginPath()
c.Rect(x, y, width, height)
c.Stroke()
}
// ClearRect 清除矩形区域
func (c *Context) ClearRect(x, y, width, height float64) {
rect := image.Rect(
int(x), int(y),
int(x+width), int(y+height),
)
draw.Draw(c.img, rect, image.Transparent, image.Point{}, draw.Src)
}
// 绘制线段
func (c *Context) drawLine(p1, p2 image.Point) {
dx := p2.X - p1.X
dy := p2.Y - p1.Y
steps := int(math.Max(math.Abs(float64(dx)), math.Abs(float64(dy))))
if steps == 0 {
return
}
xStep := float64(dx) / float64(steps)
yStep := float64(dy) / float64(steps)
x := float64(p1.X)
y := float64(p1.Y)
for i := 0; i <= steps; i++ {
switch style := c.state.strokeStyle.(type) {
case color.Color:
strokeColor := c.applyAlpha(style)
c.img.Set(int(x), int(y), strokeColor)
case Gradient:
gradCol := style.At(int(x), int(y))
c.img.Set(int(x), int(y), c.applyAlpha(gradCol))
}
x += xStep
y += yStep
}
}
// 绘制阴影
func (c *Context) drawShadow(fill bool) {
// 保存当前状态
c.Save()
// 设置阴影样式
shadowStyle := c.state.shadowColor
c.SetFillColor(shadowStyle)
c.SetStrokeColor(shadowStyle)
c.SetGlobalAlpha(0.5 * c.state.globalAlpha) // 阴影透明度
// 应用阴影偏移
c.Translate(c.state.shadowOffsetX, c.state.shadowOffsetY)
// 绘制阴影
if fill {
c.Fill()
} else {
c.Stroke()
}
// 恢复状态
c.Restore()
}