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 <christopher.waldon.dev@gmail.com>
This commit is contained in:
Chris Waldon
2023-03-27 11:02:55 -04:00
committed by Elias Naur
parent 3bdbcab874
commit 25171df66a
+23 -13
View File
@@ -262,6 +262,9 @@ type shaperImpl struct {
splitScratch1, splitScratch2 []shaping.Input splitScratch1, splitScratch2 []shaping.Input
outScratchBuf []shaping.Output outScratchBuf []shaping.Output
scratchRunes []rune scratchRunes []rune
// bitmapGlyphCache caches extracted bitmap glyph images.
bitmapGlyphCache bitmapCache
} }
// Load registers the provided FontFace with the shaper, if it is compatible. // 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: case api.GlyphBitmap:
var imgOp paint.ImageOp var imgOp paint.ImageOp
var imgSize image.Point var imgSize image.Point
var img image.Image bitmapData, ok := s.bitmapGlyphCache.Get(g.ID)
switch glyphData.Format { if !ok {
case api.PNG, api.JPG, api.TIFF: var img image.Image
img, _, _ = image.Decode(bytes.NewReader(glyphData.Data)) switch glyphData.Format {
case api.BlackAndWhite: case api.PNG, api.JPG, api.TIFF:
// This is a complex family of uncompressed bitmaps that don't seem to be img, _, _ = image.Decode(bytes.NewReader(glyphData.Data))
// very common in practice. We can try adding support later if needed. case api.BlackAndWhite:
fallthrough // This is a complex family of uncompressed bitmaps that don't seem to be
default: // very common in practice. We can try adding support later if needed.
// Unknown format. fallthrough
continue 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{ off := op.Offset(image.Point{
X: ((g.X - x) - g.Offset.X).Round(), X: ((g.X - x) - g.Offset.X).Round(),
Y: g.Offset.Y.Round() - g.Ascent.Round(), Y: g.Offset.Y.Round() - g.Ascent.Round(),