diff --git a/ofdgo.go b/ofdgo.go index cebba4d..d3f7545 100644 --- a/ofdgo.go +++ b/ofdgo.go @@ -72,6 +72,7 @@ func NewRenderer(reader *Reader, opts ...RendererOption) *Renderer { CompositeGraphicUnits: reader.compositeGraphicUnitCache, FontMap: make(map[string]*canvas.FontFamily), fontFSCache: make(map[fontFSKey]*canvas.FontFamily), + textGlyphPathCache: make(map[textGlyphPathCacheKey]textGlyphPathCacheValue), } for _, opt := range opts { opt(r) diff --git a/ofdgo_renderer.go b/ofdgo_renderer.go index 7ae4efa..bae0c3a 100644 --- a/ofdgo_renderer.go +++ b/ofdgo_renderer.go @@ -34,6 +34,7 @@ type Renderer struct { FontGIDMap map[string]map[uint16]rune FontCIDMap map[string]map[uint16]rune fontFSCache map[fontFSKey]*canvas.FontFamily + textGlyphPathCache map[textGlyphPathCacheKey]textGlyphPathCacheValue fontDirs []string fontFS []fs.FS } diff --git a/ofdgo_renderer_text.go b/ofdgo_renderer_text.go index 49deb1b..700a083 100644 --- a/ofdgo_renderer_text.go +++ b/ofdgo_renderer_text.go @@ -148,7 +148,7 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64 var glyphPath *canvas.Path var glyphWidth float64 if drawAsGlyphPath { - glyphPath, glyphWidth = textGlyphPath(face, glyph) + glyphPath, glyphWidth = r.cachedTextGlyphPath(face, glyph) } else { glyphWidth = textGlyphWidth(face, glyph) } diff --git a/ofdgo_text.go b/ofdgo_text.go index 528a755..72ac273 100644 --- a/ofdgo_text.go +++ b/ofdgo_text.go @@ -20,6 +20,7 @@ import ( "strings" "github.com/tdewolff/canvas" + canvastext "github.com/tdewolff/canvas/text" "github.com/tdewolff/font" ) @@ -29,6 +30,26 @@ type textGlyph struct { GlyphID int } +// textGlyphPathCacheKey 字形路径缓存键 +type textGlyphPathCacheKey struct { + font *canvas.Font + size float64 + fauxBold float64 + fauxItalic float64 + xOffset int32 + yOffset int32 + language string + script canvastext.Script + direction canvastext.Direction + glyph textGlyph +} + +// textGlyphPathCacheValue 字形路径缓存值 +type textGlyphPathCacheValue struct { + path *canvas.Path + width float64 +} + // textGlyphTransform 字符到字形变换 type textGlyphTransform struct { CodeCount int @@ -161,6 +182,30 @@ func textGlyphPath(face *canvas.FontFace, glyph textGlyph) (*canvas.Path, float6 return p, face.MmPerEm * float64(face.Font.GlyphAdvance(glyphID)) } +// cachedTextGlyphPath 获取缓存的字形路径 +// 入参: face 字体, glyph 绘制字形 +// 返回: *canvas.Path 字形路径, float64 字形宽度 +func (r *Renderer) cachedTextGlyphPath(face *canvas.FontFace, glyph textGlyph) (*canvas.Path, float64) { + key := textGlyphPathCacheKey{ + font: face.Font, + size: face.Size, + fauxBold: face.FauxBold, + fauxItalic: face.FauxItalic, + xOffset: face.XOffset, + yOffset: face.YOffset, + language: face.Language, + script: face.Script, + direction: face.Direction, + glyph: glyph, + } + if cached, ok := r.textGlyphPathCache[key]; ok { + return cached.path, cached.width + } + path, width := textGlyphPath(face, glyph) + r.textGlyphPathCache[key] = textGlyphPathCacheValue{path: path, width: width} + return path, width +} + // hasTextMatrix 判断文本是否需要应用字形变换 // 入参: ctm 变换矩阵 // 返回: bool 是否需要变换