From bc0c0e9e67a20a5e33d93e4e51302f946f8d5583 Mon Sep 17 00:00:00 2001 From: Michael Fogleman Date: Wed, 14 Dec 2016 17:06:16 -0500 Subject: [PATCH] greatly improve clipping performance --- README.md | 2 -- context.go | 26 ++++---------------------- pattern.go | 22 ++++++++++++---------- 3 files changed, 16 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 7813a86..24441ad 100644 --- a/README.md +++ b/README.md @@ -173,8 +173,6 @@ ClipPreserve() ResetClip() ``` -Note: As currently implemented, clipping isn't very fast, but it works. - ## Helper Functions Sometimes you just don't want to write these yourself. diff --git a/context.go b/context.go index f6120f2..427b183 100644 --- a/context.go +++ b/context.go @@ -402,17 +402,8 @@ func (dc *Context) fill(painter raster.Painter) { // line cap, line join and dash settings. The path is preserved after this // operation. func (dc *Context) StrokePreserve() { - if dc.mask == nil { - painter := newPatternPainter(dc.im) - painter.setPattern(dc.strokePattern) - dc.stroke(painter) - } else { - im := image.NewRGBA(image.Rect(0, 0, dc.width, dc.height)) - painter := newPatternPainter(im) - painter.setPattern(dc.strokePattern) - dc.stroke(painter) - draw.DrawMask(dc.im, dc.im.Bounds(), im, image.ZP, dc.mask, image.ZP, draw.Over) - } + painter := newPatternPainter(dc.im, dc.mask, dc.strokePattern) + dc.stroke(painter) } // Stroke strokes the current path with the current color, line width, @@ -426,17 +417,8 @@ func (dc *Context) Stroke() { // FillPreserve fills the current path with the current color. Open subpaths // are implicity closed. The path is preserved after this operation. func (dc *Context) FillPreserve() { - if dc.mask == nil { - painter := newPatternPainter(dc.im) - painter.setPattern(dc.fillPattern) - dc.fill(painter) - } else { - im := image.NewRGBA(image.Rect(0, 0, dc.width, dc.height)) - painter := newPatternPainter(im) - painter.setPattern(dc.fillPattern) - dc.fill(painter) - draw.DrawMask(dc.im, dc.im.Bounds(), im, image.ZP, dc.mask, image.ZP, draw.Over) - } + painter := newPatternPainter(dc.im, dc.mask, dc.fillPattern) + dc.fill(painter) } // Fill fills the current path with the current color. Open subpaths diff --git a/pattern.go b/pattern.go index 8b20764..6b396ec 100644 --- a/pattern.go +++ b/pattern.go @@ -65,8 +65,9 @@ func NewSurfacePattern(im image.Image, op RepeatOp) Pattern { } type patternPainter struct { - im *image.RGBA - p Pattern + im *image.RGBA + mask *image.Alpha + p Pattern } // Paint satisfies the Painter interface. @@ -88,15 +89,20 @@ func (r *patternPainter) Paint(ss []raster.Span, done bool) { if s.X0 >= s.X1 { continue } - ma := s.Alpha const m = 1<<16 - 1 y := s.Y - r.im.Rect.Min.Y x0 := s.X0 - r.im.Rect.Min.X - // x1 := x0 + s.X1 - s.X0 // RGBAPainter.Paint() in $GOPATH/src/github.com/golang/freetype/raster/paint.go i0 := (s.Y-r.im.Rect.Min.Y)*r.im.Stride + (s.X0-r.im.Rect.Min.X)*4 i1 := i0 + (s.X1-s.X0)*4 for i, x := i0, x0; i < i1; i, x = i+4, x+1 { + ma := s.Alpha + if r.mask != nil { + ma = ma * uint32(r.mask.AlphaAt(x, y).A) / 255 + if ma == 0 { + continue + } + } c := r.p.ColorAt(x, y) cr, cg, cb, ca := c.RGBA() dr := uint32(r.im.Pix[i+0]) @@ -112,10 +118,6 @@ func (r *patternPainter) Paint(ss []raster.Span, done bool) { } } -func (r *patternPainter) setPattern(pattern Pattern) { - r.p = pattern -} - -func newPatternPainter(im *image.RGBA) *patternPainter { - return &patternPainter{im: im} +func newPatternPainter(im *image.RGBA, mask *image.Alpha, p Pattern) *patternPainter { + return &patternPainter{im, mask, p} }