added function to create an image pattern

This commit is contained in:
Thomas Friedel 2019-03-28 11:25:59 +01:00
parent 5acbe5452b
commit 0e16a8261b
7 changed files with 91 additions and 13 deletions

View file

@ -13,6 +13,7 @@ type Backend interface {
Size() (int, int)
LoadImage(img image.Image) (Image, error)
LoadImagePattern(data ImagePatternData) ImagePattern
LoadLinearGradient(data Gradient) LinearGradient
LoadRadialGradient(data Gradient) RadialGradient
@ -43,7 +44,7 @@ type FillStyle struct {
RadFrom float64
RadTo float64
}
Image Image
ImagePattern ImagePattern
}
type Gradient []GradientStop
@ -104,3 +105,12 @@ type Image interface {
Delete()
Replace(src image.Image) error
}
type ImagePatternData struct {
Image Image
}
type ImagePattern interface {
Delete()
Replace(data ImagePatternData)
}

View file

@ -441,8 +441,8 @@ func (b *GoGLBackend) useShader(style *backendbase.FillStyle) (vertexLoc uint32)
gl.Uniform1f(b.rgr.GlobalAlpha, float32(style.Color.A)/255)
return b.rgr.Vertex
}
if img := style.Image; img != nil {
img := img.(*Image)
if ip := style.ImagePattern; ip != nil {
img := ip.(*ImagePattern).data.Image.(*Image)
gl.UseProgram(b.ipr.ID)
gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, img.tex)
@ -498,8 +498,8 @@ func (b *GoGLBackend) useAlphaShader(style *backendbase.FillStyle, alphaTexSlot
gl.Uniform1f(b.rgar.GlobalAlpha, float32(style.Color.A)/255)
return b.rgar.Vertex, b.rgar.AlphaTexCoord
}
if img := style.Image; img != nil {
img := img.(*Image)
if ip := style.ImagePattern; ip != nil {
img := ip.(*ImagePattern).data.Image.(*Image)
gl.UseProgram(b.ipar.ID)
gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, img.tex)

View file

@ -239,3 +239,18 @@ func (b *GoGLBackend) DrawImage(dimg backendbase.Image, sx, sy, sw, sh float64,
gl.StencilFunc(gl.ALWAYS, 0, 0xFF)
}
type ImagePattern struct {
b *GoGLBackend
data backendbase.ImagePatternData
}
func (b *GoGLBackend) LoadImagePattern(data backendbase.ImagePatternData) backendbase.ImagePattern {
return &ImagePattern{
b: b,
data: data,
}
}
func (ip *ImagePattern) Delete() {}
func (ip *ImagePattern) Replace(data backendbase.ImagePatternData) { ip.data = data }

View file

@ -241,3 +241,18 @@ func (b *XMobileBackend) DrawImage(dimg backendbase.Image, sx, sy, sw, sh float6
b.glctx.StencilFunc(gl.ALWAYS, 0, 0xFF)
}
type ImagePattern struct {
b *XMobileBackend
data backendbase.ImagePatternData
}
func (b *XMobileBackend) LoadImagePattern(data backendbase.ImagePatternData) backendbase.ImagePattern {
return &ImagePattern{
b: b,
data: data,
}
}
func (ip *ImagePattern) Delete() {}
func (ip *ImagePattern) Replace(data backendbase.ImagePatternData) { ip.data = data }

View file

@ -434,8 +434,8 @@ func (b *XMobileBackend) useShader(style *backendbase.FillStyle) (vertexLoc gl.A
b.glctx.Uniform1f(b.rgr.GlobalAlpha, float32(style.Color.A)/255)
return b.rgr.Vertex
}
if img := style.Image; img != nil {
img := img.(*Image)
if ip := style.ImagePattern; ip != nil {
img := ip.(*ImagePattern).data.Image.(*Image)
b.glctx.UseProgram(b.ipr.ID)
b.glctx.ActiveTexture(gl.TEXTURE0)
b.glctx.BindTexture(gl.TEXTURE_2D, img.tex)
@ -491,8 +491,8 @@ func (b *XMobileBackend) useAlphaShader(style *backendbase.FillStyle, alphaTexSl
b.glctx.Uniform1f(b.rgar.GlobalAlpha, float32(style.Color.A)/255)
return b.rgar.Vertex, b.rgar.AlphaTexCoord
}
if img := style.Image; img != nil {
img := img.(*Image)
if ip := style.ImagePattern; ip != nil {
img := ip.(*ImagePattern).data.Image.(*Image)
b.glctx.UseProgram(b.ipar.ID)
b.glctx.ActiveTexture(gl.TEXTURE0)
b.glctx.BindTexture(gl.TEXTURE_2D, img.tex)

View file

@ -74,7 +74,7 @@ type drawStyle struct {
color color.RGBA
radialGradient *RadialGradient
linearGradient *LinearGradient
image *Image
imagePattern *ImagePattern
}
type lineJoin uint8
@ -202,6 +202,8 @@ func (cv *Canvas) SetStrokeStyle(value ...interface{}) {
cv.state.stroke = cv.parseStyle(value...)
}
var imagePatterns = make(map[interface{}]*ImagePattern)
func (cv *Canvas) parseStyle(value ...interface{}) drawStyle {
var style drawStyle
if len(value) == 1 {
@ -220,7 +222,12 @@ func (cv *Canvas) parseStyle(value ...interface{}) drawStyle {
} else if len(value) == 1 {
switch v := value[0].(type) {
case *Image, string:
style.image = cv.getImage(v)
if _, ok := imagePatterns[v]; !ok {
imagePatterns[v] = cv.CreatePattern(v, "")
}
style.imagePattern = imagePatterns[v]
case *ImagePattern:
style.imagePattern = v
}
}
return style
@ -249,8 +256,12 @@ func (cv *Canvas) backendFillStyle(s *drawStyle, alpha float64) backendbase.Fill
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
} else if ip := s.imagePattern; ip != nil {
if ip.ip == nil {
stl.Color = color.RGBA{}
} else {
stl.ImagePattern = ip.ip
}
} else {
alpha *= float64(s.color.A) / 255
}

View file

@ -183,3 +183,30 @@ func (cv *Canvas) GetImageData(x, y, w, h int) *image.RGBA {
func (cv *Canvas) PutImageData(img *image.RGBA, x, y int) {
cv.b.PutImageData(img, x, y)
}
// ImagePattern is an image pattern that can be used for any
// fill call
type ImagePattern struct {
cv *Canvas
img *Image
ip backendbase.ImagePattern
}
func (ip *ImagePattern) data() backendbase.ImagePatternData {
return backendbase.ImagePatternData{
Image: ip.img.img,
}
}
// CreatePattern creates a new image pattern with the specified
// image and repetition
func (cv *Canvas) CreatePattern(src interface{}, repetition string) *ImagePattern {
ip := &ImagePattern{
cv: cv,
img: cv.getImage(src),
}
if ip.img != nil {
ip.ip = cv.b.LoadImagePattern(ip.data())
}
return ip
}