From 7fa1f9096f2dc857e28e39f8073e2efcb3591dde Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Tue, 16 Apr 2019 16:33:55 +0200 Subject: [PATCH] implemented FillImageMask in software backend --- backend/backendbase/base.go | 2 +- backend/gogl/fill.go | 2 +- backend/software/fill.go | 30 ++++++++++++++++++++++++++++++ backend/xmobile/fill.go | 2 +- shadows.go | 4 +++- text.go | 2 +- 6 files changed, 37 insertions(+), 5 deletions(-) diff --git a/backend/backendbase/base.go b/backend/backendbase/base.go index 5b26030..3cb678c 100644 --- a/backend/backendbase/base.go +++ b/backend/backendbase/base.go @@ -20,7 +20,7 @@ type Backend interface { Clear(pts [4][2]float64) Fill(style *FillStyle, pts [][2]float64) DrawImage(dimg Image, sx, sy, sw, sh float64, pts [4][2]float64, alpha float64) - FillImageMask(style *FillStyle, mask *image.Alpha, pts [][2]float64) // pts must have four points + FillImageMask(style *FillStyle, mask *image.Alpha, pts [4][2]float64) // pts must have four points ClearClip() Clip(pts [][2]float64) diff --git a/backend/gogl/fill.go b/backend/gogl/fill.go index 125321d..68e5c58 100644 --- a/backend/gogl/fill.go +++ b/backend/gogl/fill.go @@ -146,7 +146,7 @@ func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) { } } -func (b *GoGLBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [][2]float64) { +func (b *GoGLBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [4][2]float64) { b.activate() w, h := mask.Rect.Dx(), mask.Rect.Dy() diff --git a/backend/software/fill.go b/backend/software/fill.go index 89a46a1..77c63a1 100644 --- a/backend/software/fill.go +++ b/backend/software/fill.go @@ -1,6 +1,7 @@ package softwarebackend import ( + "image" "image/color" "github.com/tfriedel6/canvas/backend/backendbase" @@ -28,6 +29,35 @@ func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) { }) } +func mix(col color.Color, alpha color.Alpha) color.RGBA { + ir, ig, ib, ia := col.RGBA() + a2 := float64(alpha.A) / 255.0 + r := float64(ir) * a2 / 65535.0 + g := float64(ig) * a2 / 65535.0 + b := float64(ib) * a2 / 65535.0 + a := float64(ia) * a2 / 65535.0 + return color.RGBA{ + R: uint8(r * 255.0), + G: uint8(g * 255.0), + B: uint8(b * 255.0), + A: uint8(a * 255.0), + } +} + +func (b *SoftwareBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [4][2]float64) { + mw := float64(mask.Bounds().Dx()) + mh := float64(mask.Bounds().Dy()) + b.fillQuad(pts, func(x, y int, sx2, sy2 float64) { + sxi := int(mw*sx2 + 0.5) + syi := int(mh*sy2 + 0.5) + a := mask.AlphaAt(sxi, syi) + if a.A == 0 { + return + } + b.Image.SetRGBA(x, y, mix(style.Color, a)) + }) +} + func (b *SoftwareBackend) ClearClip() { p := b.clip.Pix for i := range p { diff --git a/backend/xmobile/fill.go b/backend/xmobile/fill.go index fe7a217..8f27cba 100755 --- a/backend/xmobile/fill.go +++ b/backend/xmobile/fill.go @@ -146,7 +146,7 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) { } } -func (b *XMobileBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [][2]float64) { +func (b *XMobileBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [4][2]float64) { b.activate() w, h := mask.Rect.Dx(), mask.Rect.Dy() diff --git a/shadows.go b/shadows.go index 8b153d6..3944335 100644 --- a/shadows.go +++ b/shadows.go @@ -34,7 +34,9 @@ func (cv *Canvas) drawShadow(pts [][2]float64, mask *image.Alpha) { if len(cv.shadowBuf) != 4 { panic("invalid number of points to fill with mask, must be 4") } - cv.b.FillImageMask(&style, mask, cv.shadowBuf) + var quad [4][2]float64 + copy(quad[:], cv.shadowBuf) + cv.b.FillImageMask(&style, mask, quad) } else { cv.b.Fill(&style, cv.shadowBuf) } diff --git a/text.go b/text.go index c010423..adaa673 100644 --- a/text.go +++ b/text.go @@ -218,7 +218,7 @@ func (cv *Canvas) FillText(str string, x, y float64) { cv.drawShadow(pts[:], mask) stl := cv.backendFillStyle(&cv.state.fill, 1) - cv.b.FillImageMask(&stl, mask, pts[:]) + cv.b.FillImageMask(&stl, mask, pts) } // StrokeText draws the given string at the given coordinates