diff --git a/data.go b/data.go index 59196f3..3c3fc5f 100644 --- a/data.go +++ b/data.go @@ -129,6 +129,7 @@ type PictureData struct { Pix []NRGBA Stride int Rect Rect + Orig *PictureData } // MakePictureData creates a zero-initialized PictureData covering the given rectangle. @@ -140,6 +141,7 @@ func MakePictureData(rect Rect) *PictureData { Rect: rect, } pd.Pix = make([]NRGBA, w*h) + pd.Orig = pd return pd } @@ -265,9 +267,16 @@ func (pd *PictureData) Slice(r Rect) Picture { Pix: pd.Pix[pd.offset(r.Pos):], Stride: pd.Stride, Rect: r, + Orig: pd.Orig, } } +// Original returns the most original PictureData that this PictureData was obtained from using +// Slice-ing. +func (pd *PictureData) Original() Picture { + return pd.Orig +} + // Color returns the color located at the given position. func (pd *PictureData) Color(at Vec) NRGBA { if !pd.Rect.Contains(at) { diff --git a/drawer.go b/drawer.go index d5ec2fe..a1bf9d2 100644 --- a/drawer.go +++ b/drawer.go @@ -77,11 +77,12 @@ func (d *Drawer) Draw(t Target) { return } - pic := d.pics[targetPicturePair{t, d.Picture}] + pic := d.pics[targetPicturePair{t, d.Picture.Original()}] if pic == nil { - pic = t.MakePicture(d.Picture) - d.pics[targetPicturePair{t, d.Picture}] = pic + pic = t.MakePicture(d.Picture.Original()) + d.pics[targetPicturePair{t, d.Picture.Original()}] = pic } + pic = pic.Slice(d.Picture.Bounds()).(TargetPicture) pic.Draw(tri) } diff --git a/interface.go b/interface.go index 0cb906b..d58cee7 100644 --- a/interface.go +++ b/interface.go @@ -109,6 +109,14 @@ type Picture interface { // Slice returns a sub-Picture with specified Bounds. Slice(Rect) Picture + + // Original returns the most original Picture (may be itself) that this Picture was created + // from using Slice-ing. + // + // Since the Original and this Picture should share the underlying data and this Picture can + // be obtained just by slicing the Original, this method can be used for more efficient + // caching of Pictures. + Original() Picture } // TargetPicture is a Picture generated by a Target using MakePicture method. This Picture can be drawn onto diff --git a/pixelgl/canvas.go b/pixelgl/canvas.go index ef3e553..16ae1b2 100644 --- a/pixelgl/canvas.go +++ b/pixelgl/canvas.go @@ -69,6 +69,17 @@ func (c *Canvas) MakeTriangles(t pixel.Triangles) pixel.TargetTriangles { // // PictureColor is supported. func (c *Canvas) MakePicture(p pixel.Picture) pixel.TargetPicture { + if cp, ok := p.(*canvasPicture); ok { + return &canvasPicture{ + tex: cp.tex, + orig: cp.orig, + size: cp.size, + bounds: cp.bounds, + original: cp.original, + c: c, + } + } + bounds := p.Bounds() bx, by, bw, bh := discreteBounds(bounds) @@ -94,13 +105,15 @@ func (c *Canvas) MakePicture(p pixel.Picture) pixel.TargetPicture { tex = glhf.NewTexture(bw, bh, c.smooth, pixels) }) - return &canvasPicture{ + cp := &canvasPicture{ tex: tex, orig: pixel.V(float64(bx), float64(by)), size: pixel.V(float64(bw), float64(bh)), bounds: bounds, c: c, } + cp.original = cp + return cp } // SetTransform sets a set of Transforms that every position in triangles will be put through. @@ -258,7 +271,8 @@ type canvasPicture struct { orig, size pixel.Vec bounds pixel.Rect - c *Canvas + original *canvasPicture + c *Canvas } func (cp *canvasPicture) Bounds() pixel.Rect { @@ -267,13 +281,19 @@ func (cp *canvasPicture) Bounds() pixel.Rect { func (cp *canvasPicture) Slice(r pixel.Rect) pixel.Picture { return &canvasPicture{ - orig: cp.orig, - size: cp.size, - bounds: r, - c: cp.c, + tex: cp.tex, + orig: cp.orig, + size: cp.size, + bounds: r, + original: cp.original, + c: cp.c, } } +func (cp *canvasPicture) Original() pixel.Picture { + return cp.original +} + func (cp *canvasPicture) Draw(t pixel.TargetTriangles) { ct := t.(*canvasTriangles) if cp.c != ct.c {