diff --git a/backend/backendbase/base.go b/backend/backendbase/base.go index e5d326f..d077592 100644 --- a/backend/backendbase/base.go +++ b/backend/backendbase/base.go @@ -13,8 +13,8 @@ type Backend interface { Size() (int, int) LoadImage(img image.Image) (Image, error) - LoadLinearGradient(data *LinearGradientData) LinearGradient - LoadRadialGradient(data *RadialGradientData) RadialGradient + LoadLinearGradient(data Gradient) LinearGradient + LoadRadialGradient(data Gradient) RadialGradient Clear(pts [4][2]float64) Fill(style *FillStyle, pts [][2]float64) @@ -34,22 +34,13 @@ type FillStyle struct { Blur float64 LinearGradient LinearGradient RadialGradient RadialGradient - Image Image - FillMatrix [9]float64 -} - -type LinearGradientData struct { - X0, Y0 float64 - X1, Y1 float64 - Stops Gradient -} - -type RadialGradientData struct { - X0, Y0 float64 - X1, Y1 float64 - RadFrom float64 - RadTo float64 - Stops Gradient + Gradient struct { + X0, Y0 float64 + X1, Y1 float64 + RadFrom float64 + RadTo float64 + } + Image Image } type Gradient []GradientStop @@ -97,14 +88,14 @@ type LinearGradient interface { Delete() IsDeleted() bool IsOpaque() bool - Replace(data *LinearGradientData) + Replace(data Gradient) } type RadialGradient interface { Delete() IsDeleted() bool IsOpaque() bool - Replace(data *RadialGradientData) + Replace(data Gradient) } type Image interface { diff --git a/backend/gogl/gogl.go b/backend/gogl/gogl.go index 0d39d8c..91a2e37 100644 --- a/backend/gogl/gogl.go +++ b/backend/gogl/gogl.go @@ -306,8 +306,8 @@ func (b *GoGLBackend) useShader(style *backendbase.FillStyle) (vertexLoc uint32) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, lg.tex) gl.UseProgram(b.lgr.ID) - from := mat(style.FillMatrix).mul(lg.from) - to := mat(style.FillMatrix).mul(lg.to) + from := vec{style.Gradient.X0, style.Gradient.Y0} + to := vec{style.Gradient.X1, style.Gradient.Y1} dir := to.sub(from) length := dir.len() dir = dir.scale(1 / length) @@ -324,13 +324,13 @@ func (b *GoGLBackend) useShader(style *backendbase.FillStyle) (vertexLoc uint32) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, rg.tex) gl.UseProgram(b.rgr.ID) - from := mat(style.FillMatrix).mul(rg.from) - to := mat(style.FillMatrix).mul(rg.to) + from := vec{style.Gradient.X0, style.Gradient.Y0} + to := vec{style.Gradient.X1, style.Gradient.Y1} gl.Uniform2f(b.rgr.CanvasSize, float32(b.fw), float32(b.fh)) gl.Uniform2f(b.rgr.From, float32(from[0]), float32(from[1])) gl.Uniform2f(b.rgr.To, float32(to[0]), float32(to[1])) - gl.Uniform1f(b.rgr.RadFrom, float32(rg.radFrom)) - gl.Uniform1f(b.rgr.RadTo, float32(rg.radTo)) + gl.Uniform1f(b.rgr.RadFrom, float32(style.Gradient.RadFrom)) + gl.Uniform1f(b.rgr.RadTo, float32(style.Gradient.RadTo)) gl.Uniform1i(b.rgr.Gradient, 0) gl.Uniform1f(b.rgr.GlobalAlpha, float32(style.Color.A)/255) return b.rgr.Vertex @@ -361,8 +361,8 @@ func (b *GoGLBackend) useAlphaShader(style *backendbase.FillStyle, alphaTexSlot gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, lg.tex) gl.UseProgram(b.lgar.ID) - from := mat(style.FillMatrix).mul(lg.from) - to := mat(style.FillMatrix).mul(lg.to) + from := vec{style.Gradient.X0, style.Gradient.Y0} + to := vec{style.Gradient.X1, style.Gradient.Y1} dir := to.sub(from) length := dir.len() dir = dir.scale(1 / length) @@ -380,13 +380,13 @@ func (b *GoGLBackend) useAlphaShader(style *backendbase.FillStyle, alphaTexSlot gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, rg.tex) gl.UseProgram(b.rgar.ID) - from := mat(style.FillMatrix).mul(rg.from) - to := mat(style.FillMatrix).mul(rg.to) + from := vec{style.Gradient.X0, style.Gradient.Y0} + to := vec{style.Gradient.X1, style.Gradient.Y1} gl.Uniform2f(b.rgar.CanvasSize, float32(b.fw), float32(b.fh)) gl.Uniform2f(b.rgar.From, float32(from[0]), float32(from[1])) gl.Uniform2f(b.rgar.To, float32(to[0]), float32(to[1])) - gl.Uniform1f(b.rgar.RadFrom, float32(rg.radFrom)) - gl.Uniform1f(b.rgar.RadTo, float32(rg.radTo)) + gl.Uniform1f(b.rgar.RadFrom, float32(style.Gradient.RadFrom)) + gl.Uniform1f(b.rgar.RadTo, float32(style.Gradient.RadTo)) gl.Uniform1i(b.rgar.Gradient, 0) gl.Uniform1i(b.rgar.AlphaTex, alphaTexSlot) gl.Uniform1f(b.rgar.GlobalAlpha, float32(style.Color.A)/255) diff --git a/backend/gogl/gradients.go b/backend/gogl/gradients.go index ced1826..27e07b2 100644 --- a/backend/gogl/gradients.go +++ b/backend/gogl/gradients.go @@ -21,23 +21,21 @@ type LinearGradient struct { // will correspond to a circle type RadialGradient struct { gradient - radFrom, radTo float64 } type gradient struct { - b *GoGLBackend - from, to vec - tex uint32 - loaded bool - deleted bool - opaque bool + b *GoGLBackend + tex uint32 + loaded bool + deleted bool + opaque bool } -func (b *GoGLBackend) LoadLinearGradient(data *backendbase.LinearGradientData) backendbase.LinearGradient { +func (b *GoGLBackend) LoadLinearGradient(data backendbase.Gradient) backendbase.LinearGradient { b.activate() lg := &LinearGradient{ - gradient: gradient{b: b, from: vec{data.X0, data.Y0}, to: vec{data.X1, data.Y1}, opaque: true}, + gradient: gradient{b: b, opaque: true}, } gl.GenTextures(1, &lg.tex) gl.ActiveTexture(gl.TEXTURE0) @@ -46,7 +44,7 @@ func (b *GoGLBackend) LoadLinearGradient(data *backendbase.LinearGradientData) b gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - lg.load(data.Stops) + lg.load(data) runtime.SetFinalizer(lg, func(lg *LinearGradient) { b.glChan <- func() { gl.DeleteTextures(1, &lg.tex) @@ -55,13 +53,11 @@ func (b *GoGLBackend) LoadLinearGradient(data *backendbase.LinearGradientData) b return lg } -func (b *GoGLBackend) LoadRadialGradient(data *backendbase.RadialGradientData) backendbase.RadialGradient { +func (b *GoGLBackend) LoadRadialGradient(data backendbase.Gradient) backendbase.RadialGradient { b.activate() rg := &RadialGradient{ - gradient: gradient{b: b, from: vec{data.X0, data.Y0}, to: vec{data.X1, data.Y1}, opaque: true}, - radFrom: data.RadFrom, - radTo: data.RadTo, + gradient: gradient{b: b, opaque: true}, } gl.GenTextures(1, &rg.tex) gl.ActiveTexture(gl.TEXTURE0) @@ -70,7 +66,7 @@ func (b *GoGLBackend) LoadRadialGradient(data *backendbase.RadialGradientData) b gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - rg.load(data.Stops) + rg.load(data) runtime.SetFinalizer(rg, func(rg *RadialGradient) { b.glChan <- func() { gl.DeleteTextures(1, &rg.tex) @@ -90,8 +86,8 @@ func (g *gradient) Delete() { func (g *gradient) IsDeleted() bool { return g.deleted } func (g *gradient) IsOpaque() bool { return g.opaque } -func (lg *LinearGradient) Replace(data *backendbase.LinearGradientData) { lg.load(data.Stops) } -func (rg *RadialGradient) Replace(data *backendbase.RadialGradientData) { rg.load(data.Stops) } +func (lg *LinearGradient) Replace(data backendbase.Gradient) { lg.load(data) } +func (rg *RadialGradient) Replace(data backendbase.Gradient) { rg.load(data) } func (g *gradient) load(stops backendbase.Gradient) { if g.loaded { diff --git a/canvas.go b/canvas.go index a187450..ba55f8c 100644 --- a/canvas.go +++ b/canvas.go @@ -244,13 +244,27 @@ func (s *drawStyle) isOpaque() bool { } func (cv *Canvas) backendFillStyle(s *drawStyle, alpha float64) backendbase.FillStyle { - stl := backendbase.FillStyle{Color: s.color, FillMatrix: cv.state.transform} + stl := backendbase.FillStyle{Color: s.color} alpha *= cv.state.globalAlpha if lg := s.linearGradient; lg != nil { lg.load() stl.LinearGradient = lg.grad + from := cv.tf(lg.from) + to := cv.tf(lg.to) + stl.Gradient.X0 = from[0] + stl.Gradient.Y0 = from[1] + stl.Gradient.X1 = to[0] + stl.Gradient.Y1 = to[1] } else if rg := s.radialGradient; rg != nil { rg.load() + from := cv.tf(rg.from) + to := cv.tf(rg.to) + stl.Gradient.X0 = from[0] + stl.Gradient.Y0 = from[1] + stl.Gradient.X1 = to[0] + stl.Gradient.Y1 = to[1] + stl.Gradient.RadFrom = rg.radFrom + stl.Gradient.RadTo = rg.radTo stl.RadialGradient = rg.grad } else if img := s.image; img != nil { stl.Image = img.img diff --git a/gradients.go b/gradients.go index 48b4911..e6f0e46 100644 --- a/gradients.go +++ b/gradients.go @@ -11,13 +11,14 @@ import ( // be drawn such that each point on the gradient // will correspond to a straight line type LinearGradient struct { - cv *Canvas - created bool - loaded bool - deleted bool - opaque bool - grad backendbase.LinearGradient - data backendbase.LinearGradientData + cv *Canvas + from, to vec + created bool + loaded bool + deleted bool + opaque bool + grad backendbase.LinearGradient + data backendbase.Gradient } // RadialGradient is a gradient with any number of @@ -25,13 +26,16 @@ type LinearGradient struct { // be drawn such that each point on the gradient // will correspond to a circle type RadialGradient struct { - cv *Canvas - created bool - loaded bool - deleted bool - opaque bool - grad backendbase.RadialGradient - data backendbase.RadialGradientData + cv *Canvas + from, to vec + radFrom float64 + radTo float64 + created bool + loaded bool + deleted bool + opaque bool + grad backendbase.RadialGradient + data backendbase.Gradient } // NewLinearGradient creates a new linear gradient with @@ -41,13 +45,9 @@ func (cv *Canvas) NewLinearGradient(x0, y0, x1, y1 float64) *LinearGradient { return &LinearGradient{ cv: cv, opaque: true, - data: backendbase.LinearGradientData{ - X0: x0, - Y0: y0, - X1: x1, - Y1: y1, - Stops: make(backendbase.Gradient, 0, 20), - }, + from: vec{x0, y0}, + to: vec{x1, y1}, + data: make(backendbase.Gradient, 0, 20), } } @@ -57,19 +57,14 @@ func (cv *Canvas) NewLinearGradient(x0, y0, x1, y1 float64) *LinearGradient { // circle func (cv *Canvas) NewRadialGradient(x0, y0, r0, x1, y1, r1 float64) *RadialGradient { return &RadialGradient{ - cv: cv, - opaque: true, - data: backendbase.RadialGradientData{ - X0: x0, - Y0: y0, - X1: x1, - Y1: y1, - RadFrom: r0, - RadTo: r1, - Stops: make(backendbase.Gradient, 0, 20), - }, + cv: cv, + opaque: true, + from: vec{x0, y0}, + to: vec{x1, y1}, + radFrom: r0, + radTo: r1, + data: make(backendbase.Gradient, 0, 20), } - } // Delete explicitly deletes the gradient @@ -79,28 +74,28 @@ func (lg *LinearGradient) Delete() { lg.grad.Delete() } func (rg *RadialGradient) Delete() { rg.grad.Delete() } func (lg *LinearGradient) load() { - if lg.loaded || len(lg.data.Stops) < 1 { + if lg.loaded || len(lg.data) < 1 { return } if !lg.created { - lg.grad = lg.cv.b.LoadLinearGradient(&lg.data) + lg.grad = lg.cv.b.LoadLinearGradient(lg.data) } else { - lg.grad.Replace(&lg.data) + lg.grad.Replace(lg.data) } lg.created = true lg.loaded = true } func (rg *RadialGradient) load() { - if rg.loaded || len(rg.data.Stops) < 1 { + if rg.loaded || len(rg.data) < 1 { return } if !rg.created { - rg.grad = rg.cv.b.LoadRadialGradient(&rg.data) + rg.grad = rg.cv.b.LoadRadialGradient(rg.data) } else { - rg.grad.Replace(&rg.data) + rg.grad.Replace(rg.data) } rg.created = true rg.loaded = true @@ -111,7 +106,7 @@ func (rg *RadialGradient) load() { // right place func (lg *LinearGradient) AddColorStop(pos float64, stopColor ...interface{}) { var c color.RGBA - lg.data.Stops, c = addColorStop(lg.data.Stops, pos, stopColor...) + lg.data, c = addColorStop(lg.data, pos, stopColor...) if c.A < 255 { lg.opaque = false } @@ -123,7 +118,7 @@ func (lg *LinearGradient) AddColorStop(pos float64, stopColor ...interface{}) { // right place func (rg *RadialGradient) AddColorStop(pos float64, stopColor ...interface{}) { var c color.RGBA - rg.data.Stops, c = addColorStop(rg.data.Stops, pos, stopColor...) + rg.data, c = addColorStop(rg.data, pos, stopColor...) if c.A < 255 { rg.opaque = false }