removed FillMatrix and moved transformations to frontend

This commit is contained in:
Thomas Friedel 2019-02-22 16:53:53 +01:00
parent 3e874d544b
commit 816582dbb3
5 changed files with 87 additions and 91 deletions

View file

@ -13,8 +13,8 @@ type Backend interface {
Size() (int, int) Size() (int, int)
LoadImage(img image.Image) (Image, error) LoadImage(img image.Image) (Image, error)
LoadLinearGradient(data *LinearGradientData) LinearGradient LoadLinearGradient(data Gradient) LinearGradient
LoadRadialGradient(data *RadialGradientData) RadialGradient LoadRadialGradient(data Gradient) RadialGradient
Clear(pts [4][2]float64) Clear(pts [4][2]float64)
Fill(style *FillStyle, pts [][2]float64) Fill(style *FillStyle, pts [][2]float64)
@ -34,22 +34,13 @@ type FillStyle struct {
Blur float64 Blur float64
LinearGradient LinearGradient LinearGradient LinearGradient
RadialGradient RadialGradient RadialGradient RadialGradient
Image Image Gradient struct {
FillMatrix [9]float64
}
type LinearGradientData struct {
X0, Y0 float64
X1, Y1 float64
Stops Gradient
}
type RadialGradientData struct {
X0, Y0 float64 X0, Y0 float64
X1, Y1 float64 X1, Y1 float64
RadFrom float64 RadFrom float64
RadTo float64 RadTo float64
Stops Gradient }
Image Image
} }
type Gradient []GradientStop type Gradient []GradientStop
@ -97,14 +88,14 @@ type LinearGradient interface {
Delete() Delete()
IsDeleted() bool IsDeleted() bool
IsOpaque() bool IsOpaque() bool
Replace(data *LinearGradientData) Replace(data Gradient)
} }
type RadialGradient interface { type RadialGradient interface {
Delete() Delete()
IsDeleted() bool IsDeleted() bool
IsOpaque() bool IsOpaque() bool
Replace(data *RadialGradientData) Replace(data Gradient)
} }
type Image interface { type Image interface {

View file

@ -306,8 +306,8 @@ func (b *GoGLBackend) useShader(style *backendbase.FillStyle) (vertexLoc uint32)
gl.ActiveTexture(gl.TEXTURE0) gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, lg.tex) gl.BindTexture(gl.TEXTURE_2D, lg.tex)
gl.UseProgram(b.lgr.ID) gl.UseProgram(b.lgr.ID)
from := mat(style.FillMatrix).mul(lg.from) from := vec{style.Gradient.X0, style.Gradient.Y0}
to := mat(style.FillMatrix).mul(lg.to) to := vec{style.Gradient.X1, style.Gradient.Y1}
dir := to.sub(from) dir := to.sub(from)
length := dir.len() length := dir.len()
dir = dir.scale(1 / length) dir = dir.scale(1 / length)
@ -324,13 +324,13 @@ func (b *GoGLBackend) useShader(style *backendbase.FillStyle) (vertexLoc uint32)
gl.ActiveTexture(gl.TEXTURE0) gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, rg.tex) gl.BindTexture(gl.TEXTURE_2D, rg.tex)
gl.UseProgram(b.rgr.ID) gl.UseProgram(b.rgr.ID)
from := mat(style.FillMatrix).mul(rg.from) from := vec{style.Gradient.X0, style.Gradient.Y0}
to := mat(style.FillMatrix).mul(rg.to) to := vec{style.Gradient.X1, style.Gradient.Y1}
gl.Uniform2f(b.rgr.CanvasSize, float32(b.fw), float32(b.fh)) 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.From, float32(from[0]), float32(from[1]))
gl.Uniform2f(b.rgr.To, float32(to[0]), float32(to[1])) gl.Uniform2f(b.rgr.To, float32(to[0]), float32(to[1]))
gl.Uniform1f(b.rgr.RadFrom, float32(rg.radFrom)) gl.Uniform1f(b.rgr.RadFrom, float32(style.Gradient.RadFrom))
gl.Uniform1f(b.rgr.RadTo, float32(rg.radTo)) gl.Uniform1f(b.rgr.RadTo, float32(style.Gradient.RadTo))
gl.Uniform1i(b.rgr.Gradient, 0) gl.Uniform1i(b.rgr.Gradient, 0)
gl.Uniform1f(b.rgr.GlobalAlpha, float32(style.Color.A)/255) gl.Uniform1f(b.rgr.GlobalAlpha, float32(style.Color.A)/255)
return b.rgr.Vertex return b.rgr.Vertex
@ -361,8 +361,8 @@ func (b *GoGLBackend) useAlphaShader(style *backendbase.FillStyle, alphaTexSlot
gl.ActiveTexture(gl.TEXTURE0) gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, lg.tex) gl.BindTexture(gl.TEXTURE_2D, lg.tex)
gl.UseProgram(b.lgar.ID) gl.UseProgram(b.lgar.ID)
from := mat(style.FillMatrix).mul(lg.from) from := vec{style.Gradient.X0, style.Gradient.Y0}
to := mat(style.FillMatrix).mul(lg.to) to := vec{style.Gradient.X1, style.Gradient.Y1}
dir := to.sub(from) dir := to.sub(from)
length := dir.len() length := dir.len()
dir = dir.scale(1 / length) dir = dir.scale(1 / length)
@ -380,13 +380,13 @@ func (b *GoGLBackend) useAlphaShader(style *backendbase.FillStyle, alphaTexSlot
gl.ActiveTexture(gl.TEXTURE0) gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, rg.tex) gl.BindTexture(gl.TEXTURE_2D, rg.tex)
gl.UseProgram(b.rgar.ID) gl.UseProgram(b.rgar.ID)
from := mat(style.FillMatrix).mul(rg.from) from := vec{style.Gradient.X0, style.Gradient.Y0}
to := mat(style.FillMatrix).mul(rg.to) to := vec{style.Gradient.X1, style.Gradient.Y1}
gl.Uniform2f(b.rgar.CanvasSize, float32(b.fw), float32(b.fh)) 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.From, float32(from[0]), float32(from[1]))
gl.Uniform2f(b.rgar.To, float32(to[0]), float32(to[1])) gl.Uniform2f(b.rgar.To, float32(to[0]), float32(to[1]))
gl.Uniform1f(b.rgar.RadFrom, float32(rg.radFrom)) gl.Uniform1f(b.rgar.RadFrom, float32(style.Gradient.RadFrom))
gl.Uniform1f(b.rgar.RadTo, float32(rg.radTo)) gl.Uniform1f(b.rgar.RadTo, float32(style.Gradient.RadTo))
gl.Uniform1i(b.rgar.Gradient, 0) gl.Uniform1i(b.rgar.Gradient, 0)
gl.Uniform1i(b.rgar.AlphaTex, alphaTexSlot) gl.Uniform1i(b.rgar.AlphaTex, alphaTexSlot)
gl.Uniform1f(b.rgar.GlobalAlpha, float32(style.Color.A)/255) gl.Uniform1f(b.rgar.GlobalAlpha, float32(style.Color.A)/255)

View file

@ -21,23 +21,21 @@ type LinearGradient struct {
// will correspond to a circle // will correspond to a circle
type RadialGradient struct { type RadialGradient struct {
gradient gradient
radFrom, radTo float64
} }
type gradient struct { type gradient struct {
b *GoGLBackend b *GoGLBackend
from, to vec
tex uint32 tex uint32
loaded bool loaded bool
deleted bool deleted bool
opaque bool opaque bool
} }
func (b *GoGLBackend) LoadLinearGradient(data *backendbase.LinearGradientData) backendbase.LinearGradient { func (b *GoGLBackend) LoadLinearGradient(data backendbase.Gradient) backendbase.LinearGradient {
b.activate() b.activate()
lg := &LinearGradient{ 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.GenTextures(1, &lg.tex)
gl.ActiveTexture(gl.TEXTURE0) 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_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_S, gl.CLAMP_TO_EDGE)
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, 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) { runtime.SetFinalizer(lg, func(lg *LinearGradient) {
b.glChan <- func() { b.glChan <- func() {
gl.DeleteTextures(1, &lg.tex) gl.DeleteTextures(1, &lg.tex)
@ -55,13 +53,11 @@ func (b *GoGLBackend) LoadLinearGradient(data *backendbase.LinearGradientData) b
return lg return lg
} }
func (b *GoGLBackend) LoadRadialGradient(data *backendbase.RadialGradientData) backendbase.RadialGradient { func (b *GoGLBackend) LoadRadialGradient(data backendbase.Gradient) backendbase.RadialGradient {
b.activate() b.activate()
rg := &RadialGradient{ rg := &RadialGradient{
gradient: gradient{b: b, from: vec{data.X0, data.Y0}, to: vec{data.X1, data.Y1}, opaque: true}, gradient: gradient{b: b, opaque: true},
radFrom: data.RadFrom,
radTo: data.RadTo,
} }
gl.GenTextures(1, &rg.tex) gl.GenTextures(1, &rg.tex)
gl.ActiveTexture(gl.TEXTURE0) 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_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_S, gl.CLAMP_TO_EDGE)
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, 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) { runtime.SetFinalizer(rg, func(rg *RadialGradient) {
b.glChan <- func() { b.glChan <- func() {
gl.DeleteTextures(1, &rg.tex) gl.DeleteTextures(1, &rg.tex)
@ -90,8 +86,8 @@ func (g *gradient) Delete() {
func (g *gradient) IsDeleted() bool { return g.deleted } func (g *gradient) IsDeleted() bool { return g.deleted }
func (g *gradient) IsOpaque() bool { return g.opaque } func (g *gradient) IsOpaque() bool { return g.opaque }
func (lg *LinearGradient) Replace(data *backendbase.LinearGradientData) { lg.load(data.Stops) } func (lg *LinearGradient) Replace(data backendbase.Gradient) { lg.load(data) }
func (rg *RadialGradient) Replace(data *backendbase.RadialGradientData) { rg.load(data.Stops) } func (rg *RadialGradient) Replace(data backendbase.Gradient) { rg.load(data) }
func (g *gradient) load(stops backendbase.Gradient) { func (g *gradient) load(stops backendbase.Gradient) {
if g.loaded { if g.loaded {

View file

@ -244,13 +244,27 @@ func (s *drawStyle) isOpaque() bool {
} }
func (cv *Canvas) backendFillStyle(s *drawStyle, alpha float64) backendbase.FillStyle { 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 alpha *= cv.state.globalAlpha
if lg := s.linearGradient; lg != nil { if lg := s.linearGradient; lg != nil {
lg.load() lg.load()
stl.LinearGradient = lg.grad 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 { } else if rg := s.radialGradient; rg != nil {
rg.load() 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 stl.RadialGradient = rg.grad
} else if img := s.image; img != nil { } else if img := s.image; img != nil {
stl.Image = img.img stl.Image = img.img

View file

@ -12,12 +12,13 @@ import (
// will correspond to a straight line // will correspond to a straight line
type LinearGradient struct { type LinearGradient struct {
cv *Canvas cv *Canvas
from, to vec
created bool created bool
loaded bool loaded bool
deleted bool deleted bool
opaque bool opaque bool
grad backendbase.LinearGradient grad backendbase.LinearGradient
data backendbase.LinearGradientData data backendbase.Gradient
} }
// RadialGradient is a gradient with any number of // RadialGradient is a gradient with any number of
@ -26,12 +27,15 @@ type LinearGradient struct {
// will correspond to a circle // will correspond to a circle
type RadialGradient struct { type RadialGradient struct {
cv *Canvas cv *Canvas
from, to vec
radFrom float64
radTo float64
created bool created bool
loaded bool loaded bool
deleted bool deleted bool
opaque bool opaque bool
grad backendbase.RadialGradient grad backendbase.RadialGradient
data backendbase.RadialGradientData data backendbase.Gradient
} }
// NewLinearGradient creates a new linear gradient with // NewLinearGradient creates a new linear gradient with
@ -41,13 +45,9 @@ func (cv *Canvas) NewLinearGradient(x0, y0, x1, y1 float64) *LinearGradient {
return &LinearGradient{ return &LinearGradient{
cv: cv, cv: cv,
opaque: true, opaque: true,
data: backendbase.LinearGradientData{ from: vec{x0, y0},
X0: x0, to: vec{x1, y1},
Y0: y0, data: make(backendbase.Gradient, 0, 20),
X1: x1,
Y1: y1,
Stops: make(backendbase.Gradient, 0, 20),
},
} }
} }
@ -59,17 +59,12 @@ func (cv *Canvas) NewRadialGradient(x0, y0, r0, x1, y1, r1 float64) *RadialGradi
return &RadialGradient{ return &RadialGradient{
cv: cv, cv: cv,
opaque: true, opaque: true,
data: backendbase.RadialGradientData{ from: vec{x0, y0},
X0: x0, to: vec{x1, y1},
Y0: y0, radFrom: r0,
X1: x1, radTo: r1,
Y1: y1, data: make(backendbase.Gradient, 0, 20),
RadFrom: r0,
RadTo: r1,
Stops: make(backendbase.Gradient, 0, 20),
},
} }
} }
// Delete explicitly deletes the gradient // Delete explicitly deletes the gradient
@ -79,28 +74,28 @@ func (lg *LinearGradient) Delete() { lg.grad.Delete() }
func (rg *RadialGradient) Delete() { rg.grad.Delete() } func (rg *RadialGradient) Delete() { rg.grad.Delete() }
func (lg *LinearGradient) load() { func (lg *LinearGradient) load() {
if lg.loaded || len(lg.data.Stops) < 1 { if lg.loaded || len(lg.data) < 1 {
return return
} }
if !lg.created { if !lg.created {
lg.grad = lg.cv.b.LoadLinearGradient(&lg.data) lg.grad = lg.cv.b.LoadLinearGradient(lg.data)
} else { } else {
lg.grad.Replace(&lg.data) lg.grad.Replace(lg.data)
} }
lg.created = true lg.created = true
lg.loaded = true lg.loaded = true
} }
func (rg *RadialGradient) load() { func (rg *RadialGradient) load() {
if rg.loaded || len(rg.data.Stops) < 1 { if rg.loaded || len(rg.data) < 1 {
return return
} }
if !rg.created { if !rg.created {
rg.grad = rg.cv.b.LoadRadialGradient(&rg.data) rg.grad = rg.cv.b.LoadRadialGradient(rg.data)
} else { } else {
rg.grad.Replace(&rg.data) rg.grad.Replace(rg.data)
} }
rg.created = true rg.created = true
rg.loaded = true rg.loaded = true
@ -111,7 +106,7 @@ func (rg *RadialGradient) load() {
// right place // right place
func (lg *LinearGradient) AddColorStop(pos float64, stopColor ...interface{}) { func (lg *LinearGradient) AddColorStop(pos float64, stopColor ...interface{}) {
var c color.RGBA 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 { if c.A < 255 {
lg.opaque = false lg.opaque = false
} }
@ -123,7 +118,7 @@ func (lg *LinearGradient) AddColorStop(pos float64, stopColor ...interface{}) {
// right place // right place
func (rg *RadialGradient) AddColorStop(pos float64, stopColor ...interface{}) { func (rg *RadialGradient) AddColorStop(pos float64, stopColor ...interface{}) {
var c color.RGBA 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 { if c.A < 255 {
rg.opaque = false rg.opaque = false
} }