Skip to content

Commit

Permalink
Merge pull request #985 from ychin/fix-recurse-draw
Browse files Browse the repository at this point in the history
Fix potential CoreText font rendering infinite recursion
  • Loading branch information
ychin committed Nov 4, 2019
2 parents 67aa513 + 61c8fa4 commit 9823bad
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions src/MacVim/MMCoreTextView.m
Expand Up @@ -1710,7 +1710,7 @@ - (void)batchDrawData:(NSData *)data

static CTFontRef
lookupFont(NSMutableArray *fontCache, const unichar *chars, UniCharCount count,
CTFontRef currFontRef)
CTFontRef currFontRef, CGGlyph *glyphsOut)
{
CGGlyph glyphs[count];

Expand All @@ -1720,7 +1720,10 @@ - (void)batchDrawData:(NSData *)data
NSFont *font = [fontCache objectAtIndex:i];

if (CTFontGetGlyphsForCharacters((CTFontRef)font, chars, glyphs, count))
{
memcpy(glyphsOut, glyphs, count * sizeof(CGGlyph));
return (CTFontRef)[font retain];
}
}

// Ask Core Text for a font (can be *very* slow, which is why we cache
Expand All @@ -1737,6 +1740,7 @@ - (void)batchDrawData:(NSData *)data
if (newFontRef)
[fontCache addObject:(NSFont *)newFontRef];

memcpy(glyphsOut, glyphs, count * sizeof(CGGlyph));
return newFontRef;
}

Expand Down Expand Up @@ -1840,6 +1844,8 @@ - (void)batchDrawData:(NSData *)data
UniCharCount length, CGContextRef context, CTFontRef fontRef,
NSMutableArray *fontCache, BOOL isComposing, BOOL useLigatures)
{
// Note: This function is misnamed. It does not actually use recursion and
// will be renamed in future.
if (CTFontGetGlyphsForCharacters(fontRef, chars, glyphs, length)) {
// All chars were mapped to glyphs, so draw all at once and return.
length = isComposing || useLigatures
Expand Down Expand Up @@ -1897,17 +1903,21 @@ - (void)batchDrawData:(NSData *)data
CTFontRef fallback = nil;
while (fallback == nil && attemptedCount > 0) {
fallback = lookupFont(fontCache, chars, attemptedCount,
fontRef);
fontRef, glyphs);
if (!fallback)
attemptedCount /= 2;
}

if (!fallback)
return;

recurseDraw(chars, glyphs, positions, attemptedCount, context,
fallback, fontCache, isComposing, useLigatures);
UniCharCount actualAttemptLength = isComposing || useLigatures
? composeGlyphsForChars(chars, glyphs, positions, attemptedCount,
fallback, isComposing, useLigatures)
: gatherGlyphs(glyphs, attemptedCount);
CTFontDrawGlyphs(fallback, glyphs, positions, actualAttemptLength, context);

// TODO: This doesn't take into account surrogate pairs for 'p'. Clean this up.
// If only a portion of the invalid range was rendered above,
// the remaining range needs to be attempted by subsequent
// iterations of the draw loop.
Expand Down

0 comments on commit 9823bad

Please sign in to comment.