canvas/util.go

127 lines
2.3 KiB
Go

package canvas
import (
"image"
"image/color"
)
// 应用全局透明度
func (c *Context) applyAlpha(col color.Color) color.Color {
if c.state.globalAlpha >= 1.0 {
return col
}
r, g, b, a := col.RGBA()
a = uint32(float64(a) * c.state.globalAlpha)
return color.NRGBA64{
R: uint16(r),
G: uint16(g),
B: uint16(b),
A: uint16(a),
}
}
// 颜色插值
func interpolateColor(c1, c2 color.Color, t float64) color.Color {
r1, g1, b1, a1 := c1.RGBA()
r2, g2, b2, a2 := c2.RGBA()
return color.RGBA64{
R: uint16(float64(r1)*(1-t) + float64(r2)*t),
G: uint16(float64(g1)*(1-t) + float64(g2)*t),
B: uint16(float64(b1)*(1-t) + float64(b2)*t),
A: uint16(float64(a1)*(1-t) + float64(a2)*t),
}
}
// 渐变图像
type gradientImage struct {
grad Gradient
alpha float64
}
func (g *gradientImage) ColorModel() color.Model {
return color.RGBAModel
}
func (g *gradientImage) Bounds() image.Rectangle {
return image.Rect(-1e9, -1e9, 1e9, 1e9)
}
func (g *gradientImage) At(x, y int) color.Color {
c := g.grad.At(x, y)
if g.alpha < 1.0 {
r, gr, b, a := c.RGBA()
a = uint32(float64(a) * g.alpha)
return color.NRGBA64{
R: uint16(r),
G: uint16(gr),
B: uint16(b),
A: uint16(a),
}
}
return c
}
// 填充多边形
type filledPolygon struct {
points []image.Point
}
func (p *filledPolygon) ColorModel() color.Model {
return color.AlphaModel
}
func (p *filledPolygon) Bounds() image.Rectangle {
if len(p.points) == 0 {
return image.Rectangle{}
}
minX, minY := p.points[0].X, p.points[0].Y
maxX, maxY := minX, minY
for _, pt := range p.points {
if pt.X < minX {
minX = pt.X
}
if pt.X > maxX {
maxX = pt.X
}
if pt.Y < minY {
minY = pt.Y
}
if pt.Y > maxY {
maxY = pt.Y
}
}
return image.Rect(minX, minY, maxX+1, maxY+1)
}
func (p *filledPolygon) At(x, y int) color.Color {
if pointInPolygon(image.Pt(x, y), p.points) {
return color.Alpha{A: 255}
}
return color.Alpha{A: 0}
}
// 判断点是否在多边形内
func pointInPolygon(pt image.Point, poly []image.Point) bool {
if len(poly) < 3 {
return false
}
inside := false
j := len(poly) - 1
for i := 0; i < len(poly); i++ {
if (poly[i].Y > pt.Y) != (poly[j].Y > pt.Y) &&
(pt.X < poly[i].X+(poly[j].X-poly[i].X)*(pt.Y-poly[i].Y)/(poly[j].Y-poly[i].Y)) {
inside = !inside
}
j = i
}
return inside
}