Fix crash when rendering invalid Unicode characters. #41
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This commit proposes a fix for issues #28 and #29, which both have to do with the handling of invalid characters in the Core Text renderer.
The method by which
recurseDrawattempted to find fallback fonts for an untranslatable sequence of characters only used the first character of the sequence to find the fallback, assuming that subsequent iterations of the recursion would then render at least that one character and move on. In the case of invalid surrogate pair characters, however, the underlying Core Text APIs don't behave that way, apparently (CTFontCreateForStringcan return a font for a string thatCTFontGetGlyphsForCharactersstill won't convert).In this change I first modified
lookupFontto take a range, to try to find a font that can convert the entire given range, and verify that the returned font can actually convert the input range.Then, when
recurseDrawtries to render an untranslated glyph range, it first tries to find a font that can convert the entire range. If it fails, it tries half that range, and so on until either a renderable font/range is found or the range has been reduced to a single impossible-to-render character. After the range is drawn, the character/glyph/position pointers are adjusted so that subsequent iterations of the draw loop attempt to convert the upper half of the original untranslated range.This should result in a slightly less-deep recursive callstack when dealing with a large range of untranslatable characters. It may have a slightly increased performance impact because the "slow" path of
lookupFontmay be getting hit slightly more often (my testing hasn't shown noticeable performance degradations, however). Obviously, the referenced crashes will be avoided.The resulting invalid characters tend to display as boxes or other obvious "invalid character" glyphs. They sometimes consume multiple columns. I'm not sure I like this behavior, but it is consistent with the behavior of the regular Cocoa renderer in MacVim, so I'd consider it acceptable.