Add basic support for CoreText ligatures.

(cherry picked from commit 1497587763)
This commit is contained in:
René Köcher
2015-07-12 14:21:50 +02:00
committed by Douglas Drumond
parent 186c34883d
commit e5adcec141
7 changed files with 417 additions and 1723 deletions
File diff suppressed because it is too large Load Diff
Binary file not shown.
+25
View File
@@ -208,6 +208,7 @@ fsEventCallback(ConstFSEventStreamRef streamRef,
[NSNumber numberWithBool:NO], MMNoFontSubstitutionKey,
[NSNumber numberWithBool:YES], MMLoginShellKey,
[NSNumber numberWithInt:2], MMRendererKey,
[NSNumber numberWithBool:NO], MMRendererLigaturesSupportKey,
[NSNumber numberWithInt:MMUntitledWindowAlways],
MMUntitledWindowKey,
[NSNumber numberWithBool:NO], MMTexturedWindowKey,
@@ -1225,6 +1226,30 @@ fsEventCallback(ConstFSEventStreamRef streamRef,
[self rebuildPreloadCache];
}
- (IBAction)ligaturesButtonClicked:(id)sender
{
ASLogDebug(@"Toggle CoreText ligatures");
BOOL enable = ([sender state] == NSOnState);
if (enable) {
}
// Update the user default MMRendererLigaturesSupport and synchronize the
// change so that any new Vim process will pick up on the changed setting.
CFPreferencesSetAppValue(
(CFStringRef)MMRendererLigaturesSupportKey,
(CFPropertyListRef)[NSNumber numberWithBool:enable],
kCFPreferencesCurrentApplication);
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
ASLogInfo(@"Use ligatures=%ld", enable);
// This action is called when the user clicks the "enable support for ligatures"
// button in the advanced preferences pane.
[self rebuildPreloadCache];
}
- (IBAction)loginShellButtonClicked:(id)sender
{
ASLogDebug(@"Toggle login shell option");
+1
View File
@@ -31,6 +31,7 @@
float fontDescent;
BOOL antialias;
BOOL useLigatures;
NSMutableArray *drawData;
MMTextViewHelper *helper;
+68 -4
View File
@@ -132,6 +132,17 @@ defaultAdvanceForFont(NSFont *font)
[self registerForDraggedTypes:[NSArray arrayWithObjects:
NSFilenamesPboardType, NSStringPboardType, nil]];
// Check if ligatures should be used or not
{
Boolean val;
Boolean keyValid;
val = CFPreferencesGetAppBooleanValue((CFStringRef)MMRendererLigaturesSupportKey,
kCFPreferencesCurrentApplication,
&keyValid);
useLigatures = NO;
if(keyValid) { useLigatures = val; }
}
return self;
}
@@ -1017,14 +1028,67 @@ lookupFont(NSMutableArray *fontCache, const unichar *chars, UniCharCount count,
return newFontRef;
}
static void
ligatureGlyphsForChars(const unichar *chars, CGGlyph *glyphs, UniCharCount *length, CTFontRef font )
{
/* CoreText has no simple wait of retrieving a ligature for a set of UniChars.
* The way proposed on the CoreText ML is to convert the text to an attributed
* string, create a CTLine from it and retrieve the Glyphs from the CTRuns in it.
*/
NSString *text = [NSString stringWithCharacters:chars
length:*length];
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
(id)font, kCTFontAttributeName,
// 2 - full ligatures including rare
[NSNumber numberWithInteger: 2], kCTLigatureAttributeName,
nil
];
NSAttributedString *attrText = [[NSAttributedString alloc] initWithString:text
attributes:attrs];
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attrText);
UniCharCount offset = 0;
NSArray *glyphRuns = (NSArray*)CTLineGetGlyphRuns(line);
for (id item in glyphRuns) {
CTRunRef run = (CTRunRef)item;
CFIndex count = CTRunGetGlyphCount(run);
if(count > 0) {
if(count - offset > *length) {
count = (*length) - offset;
}
}
CFRange range = CFRangeMake(0, count);
CTRunGetGlyphs(run, range, &glyphs[offset]);
offset += count;
if(offset >= *length) {
// don't copy more glyphs then there is space for
break;
}
}
// as ligatures combine characters it is required to adjust the
// original length value
*length = offset;
}
static void
recurseDraw(const unichar *chars, CGGlyph *glyphs, CGPoint *positions,
UniCharCount length, CGContextRef context, CTFontRef fontRef,
NSMutableArray *fontCache)
NSMutableArray *fontCache, BOOL useLigatures)
{
if (CTFontGetGlyphsForCharacters(fontRef, chars, glyphs, length)) {
// All chars were mapped to glyphs, so draw all at once and return.
if (useLigatures) {
memset(glyphs, 0, sizeof(CGGlyph) * length);
ligatureGlyphsForChars(chars, glyphs, &length, fontRef);
}
CGFontRef cgFontRef = CTFontCopyGraphicsFont(fontRef, NULL);
CGContextSetFont(context, cgFontRef);
CGContextShowGlyphsAtPositions(context, glyphs, positions, length);
@@ -1077,7 +1141,7 @@ recurseDraw(const unichar *chars, CGGlyph *glyphs, CGPoint *positions,
}
recurseDraw(chars, glyphs, positions, attemptedCount, context,
fallback, fontCache);
fallback, fontCache, useLigatures);
// If only a portion of the invalid range was rendered above,
// the remaining range needs to be attempted by subsequent
@@ -1201,7 +1265,7 @@ recurseDraw(const unichar *chars, CGGlyph *glyphs, CGPoint *positions,
}
CGContextSetTextPosition(context, x, y+fontDescent);
recurseDraw(chars, glyphs, positions, length, context, fontRef, fontCache);
recurseDraw(chars, glyphs, positions, length, context, fontRef, fontCache, useLigatures);
CFRelease(fontRef);
CGContextRestoreGState(context);
+1
View File
@@ -275,6 +275,7 @@ extern NSString *MMNoWindowKey;
extern NSString *MMAutosaveRowsKey;
extern NSString *MMAutosaveColumnsKey;
extern NSString *MMRendererKey;
extern NSString *MMRendererLigaturesSupportKey;
enum {
MMRendererDefault = 0,
+1
View File
@@ -117,6 +117,7 @@ NSString *MMNoWindowKey = @"MMNoWindow";
NSString *MMAutosaveRowsKey = @"MMAutosaveRows";
NSString *MMAutosaveColumnsKey = @"MMAutosaveColumns";
NSString *MMRendererKey = @"MMRenderer";
NSString *MMRendererLigaturesSupportKey = @"MMRendererLigaturesSupport";
// Vim find pasteboard type (string contains Vim regex patterns)
NSString *VimFindPboardType = @"VimFindPboardType";