Skip to content

Commit db92058

Browse files
committed
Emoji!
1 parent ccb82d1 commit db92058

File tree

9 files changed

+118
-25
lines changed

9 files changed

+118
-25
lines changed

src/MacVim/MMBackend.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,9 +998,11 @@ - (void)setFont:(GuiFont)font wide:(BOOL)wide
998998
}
999999

10001000
int len = [fontName lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1001+
int emojiEnabled = vim_strchr(p_go, GO_EMOJI) != NULL;
10011002
NSMutableData *data = [NSMutableData data];
10021003
[data appendBytes:&size length:sizeof(float)];
10031004
[data appendBytes:&len length:sizeof(int)];
1005+
[data appendBytes:&emojiEnabled length:sizeof(int)];
10041006

10051007
if (len > 0)
10061008
[data appendBytes:[fontName UTF8String] length:len];

src/MacVim/MMCoreTextView.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
unsigned maxlen;
3939
CGGlyph *glyphs;
4040
CGSize *advances;
41+
CGPoint *positions;
4142
NSMutableArray *fontCache;
43+
BOOL emojiEnabled;
4244

4345
// These are used in MMCoreTextView+ToolTip.m
4446
id trackingRectOwner_; // (not retained)

src/MacVim/MMCoreTextView.m

Lines changed: 99 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ - (void)dealloc
150150

151151
if (glyphs) { free(glyphs); glyphs = NULL; }
152152
if (advances) { free(advances); advances = NULL; }
153+
if (positions) { free(positions); positions = NULL; }
153154

154155
[super dealloc];
155156
}
@@ -307,7 +308,23 @@ - (void)setWideFont:(NSFont *)newFont
307308
// NOTE: No need to set point size etc. since this is taken from the
308309
// regular font when drawing.
309310
[fontWide release];
310-
fontWide = [newFont retain];
311+
312+
emojiEnabled = [[self vimController] emojiEnabled];
313+
if (emojiEnabled) {
314+
// Use 'Apple Color Emoji' font for rendering emoji
315+
CGFloat size = [newFont pointSize];
316+
NSFontDescriptor *emojiDesc = [NSFontDescriptor
317+
fontDescriptorWithName:@"Apple Color Emoji" size:size];
318+
NSFontDescriptor *newFontDesc = [newFont fontDescriptor];
319+
NSDictionary *attrs = [NSDictionary
320+
dictionaryWithObject:[NSArray arrayWithObject:newFontDesc]
321+
forKey:NSFontCascadeListAttribute];
322+
NSFontDescriptor *desc =
323+
[emojiDesc fontDescriptorByAddingAttributes:attrs];
324+
fontWide = [[NSFont fontWithDescriptor:desc size:size] retain];
325+
} else {
326+
fontWide = [newFont retain];
327+
}
311328
}
312329
}
313330

@@ -1017,19 +1034,60 @@ - (void)batchDrawData:(NSData *)data
10171034
return newFontRef;
10181035
}
10191036

1037+
static UniCharCount
1038+
gatherGlyphs(CGGlyph glyphs[], UniCharCount count)
1039+
{
1040+
// Gather scattered glyphs that was happended by Surrogate pair chars
1041+
UniCharCount glyphLength = 0;
1042+
NSUInteger pos = NSIntegerMax;
1043+
NSUInteger i;
1044+
for (i = 0; i < count; ++i) {
1045+
if (glyphs[i] == 0) {
1046+
pos = i;
1047+
} else {
1048+
++glyphLength;
1049+
if (pos != NSIntegerMax)
1050+
glyphs[pos++] = glyphs[i];
1051+
}
1052+
}
1053+
return glyphLength;
1054+
}
1055+
1056+
static void
1057+
drawGlyphs(CTFontRef fontRef, const CGGlyph glyphs[], const CGSize advances[],
1058+
CGPoint positions[], size_t count, CGContextRef context)
1059+
{
1060+
CGAffineTransform matrix =
1061+
CGAffineTransformInvert(CGContextGetTextMatrix(context));
1062+
positions[0] = CGPointZero;
1063+
NSUInteger i;
1064+
for (i = 1; i < count; ++i) {
1065+
CGSize advance = CGSizeApplyAffineTransform(advances[i - 1], matrix);
1066+
positions[i].x = positions[i - 1].x + advance.width;
1067+
positions[i].y = positions[i - 1].y + advance.height;
1068+
}
1069+
CTFontDrawGlyphs(fontRef, glyphs, positions, count, context);
1070+
}
1071+
10201072
static void
10211073
recurseDraw(const unichar *chars, CGGlyph *glyphs, CGSize *advances,
1022-
UniCharCount length, CGContextRef context, CTFontRef fontRef,
1023-
float x, float y, NSMutableArray *fontCache)
1074+
CGPoint *positions, UniCharCount length, CGContextRef context,
1075+
CTFontRef fontRef, float x, float y, NSMutableArray *fontCache,
1076+
BOOL emojiEnabled)
10241077
{
10251078

10261079
if (CTFontGetGlyphsForCharacters(fontRef, chars, glyphs, length)) {
10271080
// All chars were mapped to glyphs, so draw all at once and return.
1028-
CGFontRef cgFontRef = CTFontCopyGraphicsFont(fontRef, NULL);
1029-
CGContextSetFont(context, cgFontRef);
10301081
CGContextSetTextPosition(context, x, y);
1031-
CGContextShowGlyphsWithAdvances(context, glyphs, advances, length);
1032-
CGFontRelease(cgFontRef);
1082+
if (emojiEnabled) {
1083+
length = gatherGlyphs(glyphs, length);
1084+
drawGlyphs(fontRef, glyphs, advances, positions, length, context);
1085+
} else {
1086+
CGFontRef cgFontRef = CTFontCopyGraphicsFont(fontRef, NULL);
1087+
CGContextSetFont(context, cgFontRef);
1088+
CGContextShowGlyphsWithAdvances(context, glyphs, advances, length);
1089+
CGFontRelease(cgFontRef);
1090+
}
10331091
return;
10341092
}
10351093

@@ -1042,25 +1100,45 @@ - (void)batchDrawData:(NSData *)data
10421100
// Draw as many consecutive glyphs as possible in the current font
10431101
// (if a glyph is 0 that means it does not exist in the current
10441102
// font).
1103+
BOOL surrogatePair = NO;
10451104
while (*g && g < glyphsEnd) {
1046-
++g;
1047-
++c;
1105+
if (emojiEnabled && CFStringIsSurrogateHighCharacter(*c)) {
1106+
surrogatePair = YES;
1107+
g += 2;
1108+
c += 2;
1109+
} else {
1110+
++g;
1111+
++c;
1112+
}
10481113
x += a->width;
10491114
++a;
10501115
}
10511116

10521117
int count = g-glyphs;
1053-
CGFontRef cgFontRef = CTFontCopyGraphicsFont(fontRef, NULL);
1054-
CGContextSetFont(context, cgFontRef);
10551118
CGContextSetTextPosition(context, x0, y);
1056-
CGContextShowGlyphsWithAdvances(context, glyphs, advances, count);
1057-
CGFontRelease(cgFontRef);
1119+
if (emojiEnabled) {
1120+
if (surrogatePair)
1121+
count = gatherGlyphs(glyphs, count);
1122+
drawGlyphs(fontRef,
1123+
glyphs, advances, positions, count, context);
1124+
} else {
1125+
CGFontRef cgFontRef = CTFontCopyGraphicsFont(fontRef, NULL);
1126+
CGContextSetFont(context, cgFontRef);
1127+
CGContextShowGlyphsWithAdvances(
1128+
context, glyphs, advances, count);
1129+
CGFontRelease(cgFontRef);
1130+
}
10581131
} else {
10591132
// Skip past as many consecutive chars as possible which cannot be
10601133
// drawn in the current font.
10611134
while (0 == *g && g < glyphsEnd) {
1062-
++g;
1063-
++c;
1135+
if (emojiEnabled && CFStringIsSurrogateHighCharacter(*c)) {
1136+
g += 2;
1137+
c += 2;
1138+
} else {
1139+
++g;
1140+
++c;
1141+
}
10641142
x += a->width;
10651143
++a;
10661144
}
@@ -1071,8 +1149,8 @@ - (void)batchDrawData:(NSData *)data
10711149
if (!newFontRef)
10721150
return;
10731151

1074-
recurseDraw(chars, glyphs, advances, count, context, newFontRef,
1075-
x0, y, fontCache);
1152+
recurseDraw(chars, glyphs, advances, positions, count, context,
1153+
newFontRef, x0, y, fontCache, emojiEnabled);
10761154

10771155
CFRelease(newFontRef);
10781156
}
@@ -1160,8 +1238,10 @@ - (void)drawString:(const UniChar *)chars length:(UniCharCount)length
11601238
if (length > maxlen) {
11611239
if (glyphs) free(glyphs);
11621240
if (advances) free(advances);
1241+
if (positions) free(positions);
11631242
glyphs = (CGGlyph*)malloc(length*sizeof(CGGlyph));
11641243
advances = (CGSize*)calloc(length, sizeof(CGSize));
1244+
positions = (CGPoint*)calloc(length, sizeof(CGPoint));
11651245
maxlen = length;
11661246
}
11671247

@@ -1191,8 +1271,8 @@ - (void)drawString:(const UniChar *)chars length:(UniCharCount)length
11911271
}
11921272
}
11931273

1194-
recurseDraw(chars, glyphs, advances, length, context, fontRef, x,
1195-
y+fontDescent, fontCache);
1274+
recurseDraw(chars, glyphs, advances, positions, length, context, fontRef, x,
1275+
y+fontDescent, fontCache, emojiEnabled);
11961276

11971277
CFRelease(fontRef);
11981278
CGContextRestoreGState(context);

src/MacVim/MMVimController.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
BOOL isPreloading;
3939
NSDate *creationDate;
4040
BOOL hasModifiedBuffer;
41+
BOOL emojiEnabled;
4142
}
4243

4344
- (id)initWithBackend:(id)backend pid:(int)processIdentifier;
@@ -68,4 +69,5 @@
6869
- (id)evaluateVimExpressionCocoa:(NSString *)expr
6970
errorString:(NSString **)errstr;
7071
- (void)processInputQueue:(NSArray *)queue;
72+
- (BOOL)emojiEnabled;
7173
@end

src/MacVim/MMVimController.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ - (void)setIsPreloading:(BOOL)yn
221221
isPreloading = yn;
222222
}
223223

224+
- (BOOL)emojiEnabled
225+
{
226+
return emojiEnabled;
227+
}
228+
224229
- (BOOL)hasModifiedBuffer
225230
{
226231
return hasModifiedBuffer;
@@ -693,6 +698,7 @@ - (void)handleMessage:(int)msgid data:(NSData *)data
693698
const void *bytes = [data bytes];
694699
float size = *((float*)bytes); bytes += sizeof(float);
695700
int len = *((int*)bytes); bytes += sizeof(int);
701+
emojiEnabled = *((int*)bytes); bytes += sizeof(int);
696702
NSString *name = [[NSString alloc]
697703
initWithBytes:(void*)bytes length:len
698704
encoding:NSUTF8StringEncoding];
@@ -710,6 +716,7 @@ - (void)handleMessage:(int)msgid data:(NSData *)data
710716
const void *bytes = [data bytes];
711717
float size = *((float*)bytes); bytes += sizeof(float);
712718
int len = *((int*)bytes); bytes += sizeof(int);
719+
emojiEnabled = *((int*)bytes); bytes += sizeof(int);
713720
if (len > 0) {
714721
NSString *name = [[NSString alloc]
715722
initWithBytes:(void*)bytes length:len
@@ -1662,3 +1669,4 @@ - (void)beginSheetModalForWindow:(NSWindow *)window
16621669

16631670
return NO;
16641671
}
1672+

src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2568,7 +2568,7 @@ objects/fold.o: fold.c
25682568
objects/getchar.o: getchar.c
25692569
$(CCC) -o $@ getchar.c
25702570

2571-
objects/guess.o: guess.c
2571+
objects/guess.o: guess.c guess_tab.c
25722572
$(CCC) -o $@ guess.c
25732573

25742574
objects/hardcopy.o: hardcopy.c

src/mbyte.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,9 +1273,7 @@ utf_char2cells(c)
12731273
{0xfe68, 0xfe6b},
12741274
{0xff01, 0xff60},
12751275
{0xffe0, 0xffe6},
1276-
{0x1f200, 0x1f200},
1277-
{0x1f210, 0x1f231},
1278-
{0x1f240, 0x1f248},
1276+
{0x10000, 0x1fffd},
12791277
{0x20000, 0x2fffd},
12801278
{0x30000, 0x3fffd}
12811279
};

src/option.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,7 @@ static struct vimoption
13691369
# if defined(UNIX) && !defined(MACOS)
13701370
{(char_u *)"aegimrLtT", (char_u *)0L}
13711371
# elif defined(FEAT_GUI_MACVIM)
1372-
{(char_u *)"egmrL", (char_u *)0L}
1372+
{(char_u *)"eEgmrL", (char_u *)0L}
13731373
# else
13741374
{(char_u *)"egmrLtT", (char_u *)0L}
13751375
# endif

src/option.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@
237237
#define GO_FOOTER 'F' /* add footer */
238238
#define GO_VERTICAL 'v' /* arrange dialog buttons vertically */
239239
#define GO_NOCAPTION 'C' /* remove caption bar */
240-
#define GO_ALL "aAbcCefFghilmMprtTv" /* all possible flags for 'go' */
240+
#define GO_EMOJI 'E' /* use emoji */
241+
#define GO_ALL "aAbcCeEfFghilmMprtTv" /* all possible flags for 'go' */
241242

242243
/* flags for 'comments' option */
243244
#define COM_NEST 'n' /* comments strings nest */

0 commit comments

Comments
 (0)