From 25171df66ae1ec92635392337aafdb4497ee68c3 Mon Sep 17 00:00:00 2001 From: Chris Waldon Date: Mon, 27 Mar 2023 11:02:55 -0400 Subject: [PATCH] text: cache bitmap glyph image operations This commit adds caching to the process of extracting bitmap images from glyphs, ensuring that we only do so once for a given glyph so long as it isn't evicted from our LRU. Signed-off-by: Chris Waldon --- text/gotext.go | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/text/gotext.go b/text/gotext.go index 62e2a8b7..7177b27d 100644 --- a/text/gotext.go +++ b/text/gotext.go @@ -262,6 +262,9 @@ type shaperImpl struct { splitScratch1, splitScratch2 []shaping.Input outScratchBuf []shaping.Output scratchRunes []rune + + // bitmapGlyphCache caches extracted bitmap glyph images. + bitmapGlyphCache bitmapCache } // Load registers the provided FontFace with the shaper, if it is compatible. @@ -592,20 +595,27 @@ func (s *shaperImpl) Bitmaps(ops *op.Ops, gs []Glyph) op.CallOp { case api.GlyphBitmap: var imgOp paint.ImageOp var imgSize image.Point - var img image.Image - switch glyphData.Format { - case api.PNG, api.JPG, api.TIFF: - img, _, _ = image.Decode(bytes.NewReader(glyphData.Data)) - case api.BlackAndWhite: - // This is a complex family of uncompressed bitmaps that don't seem to be - // very common in practice. We can try adding support later if needed. - fallthrough - default: - // Unknown format. - continue + bitmapData, ok := s.bitmapGlyphCache.Get(g.ID) + if !ok { + var img image.Image + switch glyphData.Format { + case api.PNG, api.JPG, api.TIFF: + img, _, _ = image.Decode(bytes.NewReader(glyphData.Data)) + case api.BlackAndWhite: + // This is a complex family of uncompressed bitmaps that don't seem to be + // very common in practice. We can try adding support later if needed. + fallthrough + default: + // Unknown format. + continue + } + imgOp = paint.NewImageOp(img) + imgSize = img.Bounds().Size() + s.bitmapGlyphCache.Put(g.ID, bitmap{img: imgOp, size: imgSize}) + } else { + imgOp = bitmapData.img + imgSize = bitmapData.size } - imgOp = paint.NewImageOp(img) - imgSize = img.Bounds().Size() off := op.Offset(image.Point{ X: ((g.X - x) - g.Offset.X).Round(), Y: g.Offset.Y.Round() - g.Ascent.Round(),