From f89b3eccdc344913bfb7ae2c69130e51da3f67b0 Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Thu, 25 Apr 2019 17:58:21 +0200 Subject: [PATCH] implemented imapge pattern repeat types --- backend/backendbase/base.go | 11 +++++++++++ backend/gogl/gogl.go | 20 ++++++++++++++++++++ backend/gogl/shaders.go | 26 ++++++++++++++++++++++---- canvas.go | 2 +- images.go | 16 +++++++++++++++- 5 files changed, 69 insertions(+), 6 deletions(-) diff --git a/backend/backendbase/base.go b/backend/backendbase/base.go index eb6ef7b..5b26030 100644 --- a/backend/backendbase/base.go +++ b/backend/backendbase/base.go @@ -109,8 +109,19 @@ type Image interface { type ImagePatternData struct { Image Image Transform [9]float64 + Repeat ImagePatternRepeat } +type ImagePatternRepeat uint8 + +// Image pattern repeat constants +const ( + Repeat ImagePatternRepeat = iota + RepeatX + RepeatY + NoRepeat +) + type ImagePattern interface { Delete() Replace(data ImagePatternData) diff --git a/backend/gogl/gogl.go b/backend/gogl/gogl.go index 1c577e7..14bf820 100644 --- a/backend/gogl/gogl.go +++ b/backend/gogl/gogl.go @@ -445,6 +445,16 @@ func (b *GoGLBackend) useShader(style *backendbase.FillStyle) (vertexLoc uint32) f32mat[i] = float32(v) } gl.UniformMatrix3fv(b.ipr.ImageTransform, 1, false, &f32mat[0]) + switch ipd.Repeat { + case backendbase.Repeat: + gl.Uniform2f(b.ipr.Repeat, 1, 1) + case backendbase.RepeatX: + gl.Uniform2f(b.ipr.Repeat, 1, 0) + case backendbase.RepeatY: + gl.Uniform2f(b.ipr.Repeat, 0, 1) + case backendbase.NoRepeat: + gl.Uniform2f(b.ipr.Repeat, 0, 0) + } gl.Uniform1f(b.ipr.GlobalAlpha, float32(style.Color.A)/255) return b.ipr.Vertex } @@ -508,6 +518,16 @@ func (b *GoGLBackend) useAlphaShader(style *backendbase.FillStyle, alphaTexSlot f32mat[i] = float32(v) } gl.UniformMatrix3fv(b.ipr.ImageTransform, 1, false, &f32mat[0]) + switch ipd.Repeat { + case backendbase.Repeat: + gl.Uniform2f(b.ipr.Repeat, 1, 1) + case backendbase.RepeatX: + gl.Uniform2f(b.ipr.Repeat, 1, 0) + case backendbase.RepeatY: + gl.Uniform2f(b.ipr.Repeat, 0, 1) + case backendbase.NoRepeat: + gl.Uniform2f(b.ipr.Repeat, 0, 0) + } gl.Uniform1i(b.ipar.AlphaTex, alphaTexSlot) gl.Uniform1f(b.ipar.GlobalAlpha, float32(style.Color.A)/255) return b.ipar.Vertex, b.ipar.AlphaTexCoord diff --git a/backend/gogl/shaders.go b/backend/gogl/shaders.go index 32eac02..0e9d6e2 100755 --- a/backend/gogl/shaders.go +++ b/backend/gogl/shaders.go @@ -133,10 +133,18 @@ varying vec2 v_cp; uniform vec2 imageSize; uniform sampler2D image; uniform mat3 imageTransform; +uniform vec2 repeat; uniform float globalAlpha; void main() { - vec3 tfp = vec3(v_cp, 1.0) * imageTransform; - vec4 col = texture2D(image, mod(tfp.xy / imageSize, 1.0)); + vec3 tfpt = vec3(v_cp, 1.0) * imageTransform; + vec2 imgpt = tfpt.xy / imageSize; + vec4 col = texture2D(image, mod(imgpt, 1.0)); + if (imgpt.x < 0.0 || imgpt.x > 1.0) { + col *= repeat.x; + } + if (imgpt.y < 0.0 || imgpt.y > 1.0) { + col *= repeat.y; + } col.a *= globalAlpha; gl_FragColor = col; }` @@ -262,11 +270,19 @@ varying vec2 v_atc; uniform vec2 imageSize; uniform sampler2D image; uniform mat3 imageTransform; +uniform vec2 repeat; uniform sampler2D alphaTex; uniform float globalAlpha; void main() { - vec3 tfp = vec3(v_cp, 1.0) * imageTransform; - vec4 col = texture2D(image, mod(tfp.xy / imageSize, 1.0)); + vec3 tfpt = vec3(v_cp, 1.0) * imageTransform; + vec2 imgpt = tfpt.xy / imageSize; + vec4 col = texture2D(image, mod(imgpt, 1.0)); + if (imgpt.x < 0.0 || imgpt.x > 1.0) { + col *= repeat.x; + } + if (imgpt.y < 0.0 || imgpt.y > 1.0) { + col *= repeat.y; + } col.a *= texture2D(alphaTex, v_atc).a * globalAlpha; gl_FragColor = col; }` @@ -409,6 +425,7 @@ type imagePatternShader struct { ImageSize int32 Image int32 ImageTransform int32 + Repeat int32 GlobalAlpha int32 } @@ -457,6 +474,7 @@ type imagePatternAlphaShader struct { ImageSize int32 Image int32 ImageTransform int32 + Repeat int32 AlphaTex int32 GlobalAlpha int32 } diff --git a/canvas.go b/canvas.go index 4bd68b2..86a6e2c 100644 --- a/canvas.go +++ b/canvas.go @@ -223,7 +223,7 @@ func (cv *Canvas) parseStyle(value ...interface{}) drawStyle { switch v := value[0].(type) { case *Image, string: if _, ok := imagePatterns[v]; !ok { - imagePatterns[v] = cv.CreatePattern(v, "") + imagePatterns[v] = cv.CreatePattern(v, Repeat) } style.imagePattern = imagePatterns[v] case *ImagePattern: diff --git a/images.go b/images.go index 5a14020..0bc0eb3 100644 --- a/images.go +++ b/images.go @@ -190,13 +190,25 @@ type ImagePattern struct { cv *Canvas img *Image tf [9]float64 + rep imagePatternRepeat ip backendbase.ImagePattern } +type imagePatternRepeat uint8 + +// Image pattern repeat constants +const ( + Repeat imagePatternRepeat = imagePatternRepeat(backendbase.Repeat) + RepeatX = imagePatternRepeat(backendbase.RepeatX) + RepeatY = imagePatternRepeat(backendbase.RepeatY) + NoRepeat = imagePatternRepeat(backendbase.NoRepeat) +) + func (ip *ImagePattern) data() backendbase.ImagePatternData { return backendbase.ImagePatternData{ Image: ip.img.img, Transform: ip.tf, + Repeat: backendbase.ImagePatternRepeat(ip.rep), } } @@ -214,10 +226,12 @@ func (ip *ImagePattern) SetTransform(tf [6]float64) { // CreatePattern creates a new image pattern with the specified // image and repetition -func (cv *Canvas) CreatePattern(src interface{}, repetition string) *ImagePattern { +func (cv *Canvas) CreatePattern(src interface{}, repeat imagePatternRepeat) *ImagePattern { ip := &ImagePattern{ cv: cv, img: cv.getImage(src), + rep: repeat, + tf: [9]float64{1, 0, 0, 0, 1, 0, 0, 0, 1}, } if ip.img != nil { ip.ip = cv.b.LoadImagePattern(ip.data())