141 lines
2.8 KiB
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()
|
|
}
|