From 3d3f1c6e1148e430131e7f2679c50a3f4cb6884d Mon Sep 17 00:00:00 2001
From: faiface <faiface@ksp.sk>
Date: Mon, 10 Apr 2017 00:30:50 +0200
Subject: [PATCH] add Canvas.SetComposeMethod

---
 pixelgl/canvas.go | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/pixelgl/canvas.go b/pixelgl/canvas.go
index 758a5b5..f2a9bc5 100644
--- a/pixelgl/canvas.go
+++ b/pixelgl/canvas.go
@@ -19,11 +19,14 @@ type Canvas struct {
 	gf     *GLFrame
 	shader *glhf.Shader
 
+	cmp    pixel.ComposeMethod
 	mat    mgl32.Mat3
 	col    mgl32.Vec4
 	smooth bool
 }
 
+var _ pixel.ComposeTarget = (*Canvas)(nil)
+
 // NewCanvas creates a new empty, fully transparent Canvas with given bounds. If the smooth flag is
 // set, then stretched Pictures will be smoothed and will not be drawn pixely onto this Canvas.
 func NewCanvas(bounds pixel.Rect, smooth bool) *Canvas {
@@ -107,6 +110,12 @@ func (c *Canvas) SetColorMask(col color.Color) {
 	}
 }
 
+// SetComposeMethod sets a Porter-Duff composition method to be used in the following draws onto
+// this Canvas.
+func (c *Canvas) SetComposeMethod(cmp pixel.ComposeMethod) {
+	c.cmp = cmp
+}
+
 // SetBounds resizes the Canvas to the new bounds. Old content will be preserved.
 func (c *Canvas) SetBounds(bounds pixel.Rect) {
 	c.gf.SetBounds(bounds)
@@ -135,6 +144,32 @@ func (c *Canvas) setGlhfBounds() {
 	glhf.Bounds(bx, by, bw, bh)
 }
 
+// must be manually called inside mainthread
+func (c *Canvas) setBlendFunc() {
+	switch c.cmp {
+	case pixel.ComposeOver:
+		glhf.BlendFunc(glhf.One, glhf.OneMinusSrcAlpha)
+	case pixel.ComposeIn:
+		glhf.BlendFunc(glhf.DstAlpha, glhf.Zero)
+	case pixel.ComposeOut:
+		glhf.BlendFunc(glhf.OneMinusDstAlpha, glhf.Zero)
+	case pixel.ComposeAtop:
+		glhf.BlendFunc(glhf.DstAlpha, glhf.OneMinusSrcAlpha)
+	case pixel.ComposeDstOver:
+		glhf.BlendFunc(glhf.OneMinusDstAlpha, glhf.One)
+	case pixel.ComposeDstIn:
+		glhf.BlendFunc(glhf.Zero, glhf.SrcAlpha)
+	case pixel.ComposeDstOut:
+		glhf.BlendFunc(glhf.Zero, glhf.OneMinusSrcAlpha)
+	case pixel.ComposeDstAtop:
+		glhf.BlendFunc(glhf.OneMinusDstAlpha, glhf.SrcAlpha)
+	case pixel.ComposeXor:
+		glhf.BlendFunc(glhf.OneMinusDstAlpha, glhf.OneMinusSrcAlpha)
+	default:
+		panic(errors.New("Canvas: invalid compose method"))
+	}
+}
+
 // Clear fills the whole Canvas with a single color.
 func (c *Canvas) Clear(color color.Color) {
 	c.gf.Dirty()
@@ -188,7 +223,7 @@ func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) {
 
 	mainthread.CallNonBlock(func() {
 		ct.dst.setGlhfBounds()
-		glhf.BlendFunc(glhf.One, glhf.OneMinusSrcAlpha)
+		ct.dst.setBlendFunc()
 
 		frame := ct.dst.gf.Frame()
 		shader := ct.dst.shader
-- 
GitLab