Skip to content

Commit 5d19c5c

Browse files
committed
cache glyph in one pass
1 parent 0aa8564 commit 5d19c5c

File tree

1 file changed

+60
-18
lines changed

1 file changed

+60
-18
lines changed

src/font.ts

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -164,21 +164,21 @@ export default class FontLoader {
164164
// @ts-ignore
165165
{ lowMemory: true }
166166
)
167-
cachedParsedFont.set(data, font)
168-
}
169-
170-
// Modify the `charToGlyphIndex` method, so we can know which char is
171-
// being mapped to which glyph.
172-
const originalCharToGlyphIndex = font.charToGlyphIndex
173-
font.charToGlyphIndex = (char) => {
174-
const index = originalCharToGlyphIndex.call(font, char)
175-
if (index === 0) {
176-
// The current requested char is missing a glyph.
177-
if ((font as any)._trackBrokenChars) {
178-
;(font as any)._trackBrokenChars.push(char)
167+
// Modify the `charToGlyphIndex` method, so we can know which char is
168+
// being mapped to which glyph.
169+
const originalCharToGlyphIndex = font.charToGlyphIndex
170+
font.charToGlyphIndex = (char) => {
171+
const index = originalCharToGlyphIndex.call(font, char)
172+
if (index === 0) {
173+
// The current requested char is missing a glyph.
174+
if ((font as any)._trackBrokenChars) {
175+
;(font as any)._trackBrokenChars.push(char)
176+
}
179177
}
178+
return index
180179
}
181-
return index
180+
181+
cachedParsedFont.set(data, font)
182182
}
183183

184184
// We use the first font as the default font fallback.
@@ -506,11 +506,53 @@ export default class FontLoader {
506506
if (fontSize === 0) {
507507
return ''
508508
}
509-
return font
510-
.getPath(content.replace(/\n/g, ''), left, top, fontSize, {
511-
letterSpacing: letterSpacing / fontSize,
512-
})
513-
.toPathData(1)
509+
510+
const fullPath = new opentype.Path()
511+
512+
const options = {
513+
letterSpacing: letterSpacing / fontSize,
514+
}
515+
516+
const cachedPath = new WeakMap<
517+
opentype.Glyph,
518+
[number, number, opentype.Path]
519+
>()
520+
521+
font.forEachGlyph(
522+
content.replace(/\n/g, ''),
523+
left,
524+
top,
525+
fontSize,
526+
options,
527+
function (glyph, gX, gY, gFontSize) {
528+
let glyphPath: opentype.Path
529+
if (!cachedPath.has(glyph)) {
530+
glyphPath = glyph.getPath(gX, gY, gFontSize, options)
531+
cachedPath.set(glyph, [gX, gY, glyphPath])
532+
} else {
533+
const [_x, _y, _glyphPath] = cachedPath.get(glyph)
534+
glyphPath = new opentype.Path()
535+
glyphPath.commands = _glyphPath.commands.map((command) => {
536+
const movedCommand = { ...command }
537+
for (let k in movedCommand) {
538+
if (typeof movedCommand[k] === 'number') {
539+
if (k === 'x' || k === 'x1' || k === 'x2') {
540+
movedCommand[k] += gX - _x
541+
}
542+
if (k === 'y' || k === 'y1' || k === 'y2') {
543+
movedCommand[k] += gY - _y
544+
}
545+
}
546+
}
547+
return movedCommand
548+
})
549+
}
550+
551+
fullPath.extend(glyphPath)
552+
}
553+
)
554+
555+
return fullPath.toPathData(1)
514556
} finally {
515557
unpatch()
516558
}

0 commit comments

Comments
 (0)