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 }