Add conic gradient

This commit is contained in:
Nor Khasyatillah 2021-01-29 19:00:22 +07:00
parent ad4d1eafac
commit c26555283c
3 changed files with 86 additions and 1 deletions

View File

@ -128,7 +128,7 @@ SetFillRule(fillRule FillRule)
## Gradients & Patterns
`gg` supports linear and radial gradients and surface patterns. You can also implement your own patterns.
`gg` supports linear, radial and conic gradients and surface patterns. You can also implement your own patterns.
```go
SetFillStyle(pattern Pattern)
@ -136,6 +136,7 @@ SetStrokeStyle(pattern Pattern)
NewSolidPattern(color color.Color)
NewLinearGradient(x0, y0, x1, y1 float64)
NewRadialGradient(x0, y0, r0, x1, y1, r1 float64)
NewConicGradient(cx, cy, deg float64)
NewSurfacePattern(im image.Image, op RepeatOp)
```

View File

@ -0,0 +1,38 @@
// +build ignore
package main
import (
"image/color"
"github.com/fogleman/gg"
)
func main() {
dc := gg.NewContext(400, 400)
grad1 := gg.NewConicGradient(200, 200, 0)
grad1.AddColorStop(0.0, color.Black)
grad1.AddColorStop(0.5, color.RGBA{255, 215, 0, 255})
grad1.AddColorStop(1.0, color.RGBA{255, 0, 0, 255})
grad2 := gg.NewConicGradient(200, 200, 90)
grad2.AddColorStop(0.00, color.RGBA{255, 0, 0, 255})
grad2.AddColorStop(0.16, color.RGBA{255, 255, 0, 255})
grad2.AddColorStop(0.33, color.RGBA{0, 255, 0, 255})
grad2.AddColorStop(0.50, color.RGBA{0, 255, 255, 255})
grad2.AddColorStop(0.66, color.RGBA{0, 0, 255, 255})
grad2.AddColorStop(0.83, color.RGBA{255, 0, 255, 255})
grad2.AddColorStop(1.00, color.RGBA{255, 0, 0, 255})
dc.SetStrokeStyle(grad1)
dc.SetLineWidth(20)
dc.DrawCircle(200, 200, 180)
dc.Stroke()
dc.SetFillStyle(grad2)
dc.DrawCircle(200, 200, 150)
dc.Fill()
dc.SavePNG("gradient-conic.png")
}

View File

@ -164,6 +164,52 @@ func NewRadialGradient(x0, y0, r0, x1, y1, r1 float64) Gradient {
return g
}
// Conic Gradient
type conicGradient struct {
cx, cy float64
rotation float64
stops stops
}
func (g *conicGradient) ColorAt(x, y int) color.Color {
if len(g.stops) == 0 {
return color.Transparent
}
a := math.Atan2(float64(y)-g.cy, float64(x)-g.cx)
t := norm(a, -math.Pi, math.Pi) - g.rotation
if t < 0 {
t += 1
}
return getColor(t, g.stops)
}
func (g *conicGradient) AddColorStop(offset float64, color color.Color) {
g.stops = append(g.stops, stop{pos: offset, color: color})
sort.Sort(g.stops)
}
func NewConicGradient(cx, cy, deg float64) Gradient {
g := &conicGradient{
cx: cx,
cy: cy,
rotation: normalizeAngle(deg) / 360,
}
return g
}
func normalizeAngle(t float64) float64 {
t = math.Mod(t, 360)
if t < 0 {
t += 360
}
return t
}
// Map value which is in range [a..b] to range [0..1]
func norm(value, a, b float64) float64 {
return (value - a) * (1.0 / (b - a))
}
func getColor(pos float64, stops stops) color.Color {
if pos <= 0.0 || len(stops) == 1 {
return stops[0].color