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 X0, Y0 float64
} X1, Y1 float64
RadFrom float64
type LinearGradientData struct { RadTo float64
X0, Y0 float64 }
X1, Y1 float64 Image Image
Stops Gradient
}
type RadialGradientData struct {
X0, Y0 float64
X1, Y1 float64
RadFrom float64
RadTo float64
Stops Gradient
} }
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

@ -11,13 +11,14 @@ import (
// be drawn such that each point on the gradient // be drawn such that each point on the gradient
// will correspond to a straight line // will correspond to a straight line
type LinearGradient struct { type LinearGradient struct {
cv *Canvas cv *Canvas
created bool from, to vec
loaded bool created bool
deleted bool loaded bool
opaque bool deleted bool
grad backendbase.LinearGradient opaque bool
data backendbase.LinearGradientData grad backendbase.LinearGradient
data backendbase.Gradient
} }
// RadialGradient is a gradient with any number of // RadialGradient is a gradient with any number of
@ -25,13 +26,16 @@ type LinearGradient struct {
// be drawn such that each point on the gradient // be drawn such that each point on the gradient
// will correspond to a circle // will correspond to a circle
type RadialGradient struct { type RadialGradient struct {
cv *Canvas cv *Canvas
created bool from, to vec
loaded bool radFrom float64
deleted bool radTo float64
opaque bool created bool
grad backendbase.RadialGradient loaded bool
data backendbase.RadialGradientData deleted bool
opaque bool
grad backendbase.RadialGradient
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),
},
} }
} }
@ -57,19 +57,14 @@ func (cv *Canvas) NewLinearGradient(x0, y0, x1, y1 float64) *LinearGradient {
// circle // circle
func (cv *Canvas) NewRadialGradient(x0, y0, r0, x1, y1, r1 float64) *RadialGradient { func (cv *Canvas) NewRadialGradient(x0, y0, r0, x1, y1, r1 float64) *RadialGradient {
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
} }