@@ -1051,7 +1051,7 @@ - (void)batchDrawData:(NSData *)data
10511051 nil
10521052 ];
10531053
1054- return CFAttributedStringCreate (NULL , string, attrs);
1054+ return CFAttributedStringCreate (NULL , (CFStringRef) string, (CFDictionaryRef) attrs);
10551055}
10561056
10571057 static UniCharCount
@@ -1109,37 +1109,47 @@ - (void)batchDrawData:(NSData *)data
11091109 * The way proposed on the CoreText ML is to convert the text to an attributed
11101110 * string, create a CTLine from it and retrieve the Glyphs from the CTRuns in it.
11111111 */
1112- NSString *plainText = [NSString stringWithCharacters: chars length: *length];
1113-
1114- CFAttributedStringRef regularText = attributedStringForString (plainText, font, NO );
1115- CFAttributedStringRef ligatureText = attributedStringForString (plainText, font, YES );
1116-
1112+ CGGlyph refGlyphs[*length];
11171113 CGPoint refPositions[*length];
1114+
1115+ memcpy (refGlyphs, glyphs, sizeof (CGGlyph) * (*length));
11181116 memcpy (refPositions, positions, sizeof (CGSize) * (*length));
11191117
1120- CTLineRef regular = CTLineCreateWithAttributedString ((CFAttributedStringRef)regularText);
1121- CTLineRef ligature = CTLineCreateWithAttributedString ((CFAttributedStringRef)ligatureText);
1118+ memset (glyphs, 0 , sizeof (CGGlyph) * (*length));
11221119
1123- CFRelease (regularText);
1124- CFRelease (ligatureText);
1120+ NSString *plainText = [NSString stringWithCharacters: chars length: *length];
1121+ CFAttributedStringRef ligatureText = attributedStringForString (plainText, font, YES );
1122+
1123+ CTLineRef ligature = CTLineCreateWithAttributedString (ligatureText);
11251124
11261125 CGSize ligatureRanges[*length], regularRanges[*length];
11271126
11281127 // get the (ligature)glyphs and advances for the new text
11291128 UniCharCount offset = fetchGlyphsAndAdvances (ligature, glyphs, ligatureRanges, length);
1130- // do the same but only for the advances for the base text
1131- fetchGlyphsAndAdvances (regular, NULL , regularRanges, length);
1129+ // fetch the advances for the base text
1130+ CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault , refGlyphs, regularRanges, *length);
1131+
1132+ CFRelease (ligatureText);
1133+ CFRelease (ligature);
11321134
11331135 // tricky part: compare both advance ranges and chomp positions which
1134- // are covered by a single ligature
1136+ // are covered by a single ligature while keeping glyphs not in the ligature font.
11351137#define fequal (a, b ) (fabs( (a) - (b) ) < FLT_EPSILON)
1138+ #define fless (a, b )((a) - (b) < FLT_EPSILON) && (fabs( (a) - (b) ) > FLT_EPSILON)
1139+
11361140 CFIndex skip = 0 ;
11371141 for ( CFIndex i = 0 ; i < offset && skip + i < *length; ++i ) {
11381142 memcpy (&positions[i], &refPositions[skip + i], sizeof (CGSize));
11391143
11401144 if ( fequal (ligatureRanges[i].width , regularRanges[skip + i].width ) ) {
11411145 // [mostly] same width
11421146 continue ;
1147+
1148+ } else if ( fless (ligatureRanges[i].width , regularRanges[skip + i].width ) ) {
1149+ // original is wider than our result - use the original glyph
1150+ // FIXME: this is currently the only way to detect emoji (except for 'glyph[i] == 5')
1151+ glyphs[i] = refGlyphs[skip + i];
1152+ continue ;
11431153 }
11441154
11451155 // no, that's a ligature
@@ -1154,14 +1164,13 @@ - (void)batchDrawData:(NSData *)data
11541164 }
11551165 skip += j;
11561166 }
1167+
1168+ #undef fless
11571169#undef fequal
11581170
11591171 // as ligatures combine characters it is required to adjust the
11601172 // original length value
11611173 *length = offset;
1162-
1163- CFRelease (regular);
1164- CFRelease (ligature);
11651174}
11661175
11671176 static void
@@ -1171,10 +1180,11 @@ - (void)batchDrawData:(NSData *)data
11711180{
11721181 if (CTFontGetGlyphsForCharacters (fontRef, chars, glyphs, length)) {
11731182 // All chars were mapped to glyphs, so draw all at once and return.
1174- length = gatherGlyphs (glyphs, length);
11751183 if (useLigatures) {
1176- memset (glyphs, 0 , sizeof (CGGlyph) * length);
1177- ligatureGlyphsForChars (chars, glyphs, positions, &length, fontRef);
1184+ ligatureGlyphsForChars (chars, glyphs, positions, &length, fontRef);
1185+ } else {
1186+ // only fixup surrogate pairs if we're not using ligatures
1187+ length = gatherGlyphs (glyphs, length);
11781188 }
11791189
11801190 CTFontDrawGlyphs (fontRef, glyphs, positions, length, context);
0 commit comments