diff --git a/NvimView/NvimView.xcodeproj/project.pbxproj b/NvimView/NvimView.xcodeproj/project.pbxproj
index 40456763..bc8bfc4c 100644
--- a/NvimView/NvimView.xcodeproj/project.pbxproj
+++ b/NvimView/NvimView.xcodeproj/project.pbxproj
@@ -470,7 +470,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 287;
+ CURRENT_PROJECT_VERSION = 288;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -530,7 +530,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 287;
+ CURRENT_PROJECT_VERSION = 288;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -557,7 +557,7 @@
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 287;
+ DYLIB_CURRENT_VERSION = 288;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
FRAMEWORK_VERSION = A;
@@ -579,7 +579,7 @@
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 287;
+ DYLIB_CURRENT_VERSION = 288;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
FRAMEWORK_VERSION = A;
diff --git a/NvimView/NvimView/Info.plist b/NvimView/NvimView/Info.plist
index e3674b7b..8cc63bfa 100644
--- a/NvimView/NvimView/Info.plist
+++ b/NvimView/NvimView/Info.plist
@@ -15,9 +15,9 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- SNAPSHOT-287
+ SNAPSHOT-288
CFBundleVersion
- 287
+ 288
NSHumanReadableCopyright
Copyright © 2017 Tae Won Ha. All rights reserved.
NSPrincipalClass
diff --git a/NvimView/NvimView/MMCoreTextView.h b/NvimView/NvimView/MMCoreTextView.h
index 82e05767..c6aca758 100644
--- a/NvimView/NvimView/MMCoreTextView.h
+++ b/NvimView/NvimView/MMCoreTextView.h
@@ -3,12 +3,9 @@
void recurseDraw(
const unichar *chars,
- CGGlyph *glyphs,
- CGPoint *positions,
- UniCharCount length,
+ CGGlyph *glyphs, CGPoint *positions, UniCharCount length,
CGContextRef context,
CTFontRef fontRef,
NSMutableArray *fontCache,
- BOOL isComposing,
BOOL useLigatures
);
diff --git a/NvimView/NvimView/MMCoreTextView.m b/NvimView/NvimView/MMCoreTextView.m
index 3a4fe8ac..98c7572d 100644
--- a/NvimView/NvimView/MMCoreTextView.m
+++ b/NvimView/NvimView/MMCoreTextView.m
@@ -9,7 +9,7 @@
*/
/**
- * Extracted from 351faf929e4abe32ea4cc31078d1a625fc86a69f of MacVim, 2018-07-03
+ * Extracted from snapshot-146 of MacVim
* https://github.com/macvim-dev/macvim
* See VIM.LICENSE
*/
@@ -20,9 +20,7 @@
#import "MMCoreTextView.h"
-// @formatter:off
-
- static CTFontRef
+ static CTFontRef
lookupFont(NSMutableArray *fontCache, const unichar *chars, UniCharCount count,
CTFontRef currFontRef)
{
@@ -58,20 +56,15 @@ lookupFont(NSMutableArray *fontCache, const unichar *chars, UniCharCount count,
attributedStringForString(NSString *string, const CTFontRef font,
BOOL useLigatures)
{
- NSDictionary *attrs = nil;
- if (useLigatures) {
- attrs = [NSDictionary dictionaryWithObjectsAndKeys:
- (id)font, kCTFontAttributeName,
- // 2 - full ligatures including rare
- // 1 - basic ligatures
- // 0 - only ligatures essential for proper rendering of text
- // this option seems to render ligatures for some
- // monospace fonts with ligatures, eg Iosevka, ...
- [NSNumber numberWithInt:1],
- kCTLigatureAttributeName,
- nil
- ];
- }
+ NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
+ (id)font, kCTFontAttributeName,
+ // 2 - full ligatures including rare
+ // 1 - basic ligatures
+ // 0 - no ligatures
+ [NSNumber numberWithInteger:(useLigatures ? 1 : 0)],
+ kCTLigatureAttributeName,
+ nil
+ ];
return CFAttributedStringCreate(NULL, (CFStringRef)string,
(CFDictionaryRef)attrs);
@@ -79,7 +72,7 @@ attributedStringForString(NSString *string, const CTFontRef font,
static UniCharCount
fetchGlyphsAndAdvances(const CTLineRef line, CGGlyph *glyphs, CGSize *advances,
- CGPoint *positions, UniCharCount length)
+ UniCharCount length)
{
NSArray *glyphRuns = (NSArray*)CTLineGetGlyphRuns(line);
@@ -89,23 +82,19 @@ fetchGlyphsAndAdvances(const CTLineRef line, CGGlyph *glyphs, CGSize *advances,
CTRunRef run = (CTRunRef)item;
CFIndex count = CTRunGetGlyphCount(run);
- if (count > 0) {
- if (count > length - offset)
- count = length - offset;
+ if (count > 0 && count - offset > length)
+ count = length - offset;
- CFRange range = CFRangeMake(0, count);
+ CFRange range = CFRangeMake(0, count);
- if (glyphs != NULL)
- CTRunGetGlyphs(run, range, &glyphs[offset]);
- if (advances != NULL)
- CTRunGetAdvances(run, range, &advances[offset]);
- if (positions != NULL)
- CTRunGetPositions(run, range, &positions[offset]);
+ if (glyphs != NULL)
+ CTRunGetGlyphs(run, range, &glyphs[offset]);
+ if (advances != NULL)
+ CTRunGetAdvances(run, range, &advances[offset]);
- offset += count;
- if (offset >= length)
- break;
- }
+ offset += count;
+ if (offset >= length)
+ break;
}
return offset;
@@ -128,28 +117,78 @@ gatherGlyphs(CGGlyph glyphs[], UniCharCount count)
}
static UniCharCount
-composeGlyphsForChars(const unichar *chars, CGGlyph *glyphs,
- CGPoint *positions, UniCharCount length, CTFontRef font,
- BOOL isComposing, BOOL useLigatures)
+ligatureGlyphsForChars(const unichar *chars, CGGlyph *glyphs,
+ CGPoint *positions, 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.
+ CGGlyph refGlyphs[length];
+ CGPoint refPositions[length];
+
+ memcpy(refGlyphs, glyphs, sizeof(CGGlyph) * length);
+ memcpy(refPositions, positions, sizeof(CGSize) * length);
+
memset(glyphs, 0, sizeof(CGGlyph) * length);
NSString *plainText = [NSString stringWithCharacters:chars length:length];
- CFAttributedStringRef composedText = attributedStringForString(plainText,
- font,
- useLigatures);
+ CFAttributedStringRef ligatureText = attributedStringForString(plainText,
+ font, YES);
- CTLineRef line = CTLineCreateWithAttributedString(composedText);
+ CTLineRef ligature = CTLineCreateWithAttributedString(ligatureText);
- // get the (composing)glyphs and advances for the new text
- UniCharCount offset = fetchGlyphsAndAdvances(line, glyphs, NULL,
- isComposing ? positions : NULL,
- length);
+ CGSize ligatureRanges[length], regularRanges[length];
- CFRelease(composedText);
- CFRelease(line);
+ // get the (ligature)glyphs and advances for the new text
+ UniCharCount offset = fetchGlyphsAndAdvances(ligature, glyphs,
+ ligatureRanges, length);
+ // fetch the advances for the base text
+ CTFontGetAdvancesForGlyphs(font, kCTFontOrientationDefault, refGlyphs,
+ regularRanges, length);
- // as ligatures composing characters it is required to adjust the
+ CFRelease(ligatureText);
+ CFRelease(ligature);
+
+ // tricky part: compare both advance ranges and chomp positions which are
+ // covered by a single ligature while keeping glyphs not in the ligature
+ // font.
+#define fequal(a, b) (fabs((a) - (b)) < FLT_EPSILON)
+#define fless(a, b)((a) - (b) < FLT_EPSILON) && (fabs((a) - (b)) > FLT_EPSILON)
+
+ CFIndex skip = 0;
+ CFIndex i;
+ for (i = 0; i < offset && skip + i < length; ++i) {
+ memcpy(&positions[i], &refPositions[skip + i], sizeof(CGSize));
+
+ if (fequal(ligatureRanges[i].width, regularRanges[skip + i].width)) {
+ // [mostly] same width
+ continue;
+ } else if (fless(ligatureRanges[i].width,
+ regularRanges[skip + i].width)) {
+ // original is wider than our result - use the original glyph
+ // FIXME: this is currently the only way to detect emoji (except
+ // for 'glyph[i] == 5')
+ glyphs[i] = refGlyphs[skip + i];
+ continue;
+ }
+
+ // no, that's a ligature
+ // count how many positions this glyph would take up in the base text
+ CFIndex j = 0;
+ float width = ceil(regularRanges[skip + i].width);
+
+ while ((int)width < (int)ligatureRanges[i].width
+ && skip + i + j < length) {
+ width += ceil(regularRanges[++j + skip + i].width);
+ }
+ skip += j;
+ }
+
+#undef fless
+#undef fequal
+
+ // as ligatures combine characters it is required to adjust the
// original length value
return offset;
}
@@ -157,12 +196,18 @@ composeGlyphsForChars(const unichar *chars, CGGlyph *glyphs,
void
recurseDraw(const unichar *chars, CGGlyph *glyphs, CGPoint *positions,
UniCharCount length, CGContextRef context, CTFontRef fontRef,
- NSMutableArray *fontCache, BOOL isComposing, BOOL useLigatures)
+ NSMutableArray *fontCache, BOOL useLigatures)
{
if (CTFontGetGlyphsForCharacters(fontRef, chars, glyphs, length)) {
// All chars were mapped to glyphs, so draw all at once and return.
- length = composeGlyphsForChars(chars, glyphs, positions, length,
- fontRef, isComposing, useLigatures);
+ if (useLigatures) {
+ length = ligatureGlyphsForChars(chars, glyphs, positions, length,
+ fontRef);
+ } else {
+ // only fixup surrogate pairs if we're not using ligatures
+ length = gatherGlyphs(glyphs, length);
+ }
+
CTFontDrawGlyphs(fontRef, glyphs, positions, length, context);
return;
}
@@ -223,7 +268,7 @@ recurseDraw(const unichar *chars, CGGlyph *glyphs, CGPoint *positions,
return;
recurseDraw(chars, glyphs, positions, attemptedCount, context,
- fallback, fontCache, isComposing, useLigatures);
+ fallback, fontCache, useLigatures);
// If only a portion of the invalid range was rendered above,
// the remaining range needs to be attempted by subsequent
@@ -247,6 +292,4 @@ recurseDraw(const unichar *chars, CGGlyph *glyphs, CGPoint *positions,
}
}
-// @formatter:on
-
#pragma clang diagnostic pop
diff --git a/NvimView/NvimView/TextDrawer.m b/NvimView/NvimView/TextDrawer.m
index 352fac8e..a391e44d 100644
--- a/NvimView/NvimView/TextDrawer.m
+++ b/NvimView/NvimView/TextDrawer.m
@@ -192,7 +192,7 @@ static CGColorRef color_for(NSInteger value) {
const UniChar *bEnd = unichars + unilength;
UniCharCount choppedLength;
bool wide;
- bool pWide = false;
+ bool pWide = NO;
while (b < bEnd) {
wide = CFStringIsSurrogateHighCharacter(*b) || CFStringIsSurrogateLowCharacter(*b);
@@ -200,8 +200,7 @@ static CGColorRef color_for(NSInteger value) {
choppedLength = b - bStart;
// NSString *logged = [NSString stringWithCharacters:bStart length:choppedLength];
// NSLog(@"C(%d,%p..%p)[%@]", pWide, bStart, b, logged);
- // We use isComposing = false to retain the old behavior of Macvim's recurseDraw
- recurseDraw(bStart, glyphs, p, choppedLength, context, fontWithTraits, _fontLookupCache, false, _usesLigatures);
+ recurseDraw(bStart, glyphs, p, choppedLength, context, fontWithTraits, _fontLookupCache, _usesLigatures);
UniCharCount step = pWide ? choppedLength / 2 : choppedLength;
p += step;
g += step;
@@ -215,8 +214,7 @@ static CGColorRef color_for(NSInteger value) {
choppedLength = b - bStart;
// NSString *logged = [NSString stringWithCharacters:bStart length:choppedLength];
// NSLog(@"T(%d,%p..%p)[%@]", pWide, bStart, b, logged);
- // We use isComposing = false to retain the old behavior of Macvim's recurseDraw
- recurseDraw(bStart, glyphs, p, choppedLength, context, fontWithTraits, _fontLookupCache, false, _usesLigatures);
+ recurseDraw(bStart, glyphs, p, choppedLength, context, fontWithTraits, _fontLookupCache, _usesLigatures);
}
// NSLog(@"S(-,%p..%p)[%@]", unichars, unichars + unilength, string);
diff --git a/VimR/VimR.xcodeproj/project.pbxproj b/VimR/VimR.xcodeproj/project.pbxproj
index 2d9d0be2..111153bb 100644
--- a/VimR/VimR.xcodeproj/project.pbxproj
+++ b/VimR/VimR.xcodeproj/project.pbxproj
@@ -1234,7 +1234,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 287;
+ CURRENT_PROJECT_VERSION = 288;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -1291,7 +1291,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 287;
+ CURRENT_PROJECT_VERSION = 288;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
diff --git a/VimR/VimR/Info.plist b/VimR/VimR/Info.plist
index 169e08bf..ad90124c 100644
--- a/VimR/VimR/Info.plist
+++ b/VimR/VimR/Info.plist
@@ -1224,7 +1224,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- SNAPSHOT-287
+ SNAPSHOT-288
CFBundleSignature
????
CFBundleURLTypes
@@ -1241,7 +1241,7 @@
CFBundleVersion
- 287
+ 288
LSApplicationCategoryType
public.app-category.productivity
LSMinimumSystemVersion
diff --git a/VimR/VimRTests/Info.plist b/VimR/VimRTests/Info.plist
index d945dfcc..6f081c21 100644
--- a/VimR/VimRTests/Info.plist
+++ b/VimR/VimRTests/Info.plist
@@ -15,10 +15,10 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- SNAPSHOT-287
+ SNAPSHOT-288
CFBundleSignature
????
CFBundleVersion
- 287
+ 288
diff --git a/appcast_snapshot.xml b/appcast_snapshot.xml
index 28a1b03c..967bc588 100644
--- a/appcast_snapshot.xml
+++ b/appcast_snapshot.xml
@@ -7,22 +7,25 @@
Most recent changes with links to updates for VimR.
en
-
- SNAPSHOT-287
+ SNAPSHOT-288
-GH-659: Bugfix (introduced in a snapshot): Turning off ligatures does not really turn off ligatures.
+GH-659: Bugfix (introduced in a snapshot): Turning off ligatures does not really turn off ligatures.
+- Reverts the update on
MMCoreTextView
.
+
+
]]>
- https://github.com/qvacua/vimr/releases/tag/snapshot/287
+ https://github.com/qvacua/vimr/releases/tag/snapshot/288
- 2018-07-17T21:47:39.216538
+ 2018-07-18T17:04:18.666713
10.10.0
-
diff --git a/resources/release-notes.md b/resources/release-notes.md
index 4e0e03a7..1df38ad6 100644
--- a/resources/release-notes.md
+++ b/resources/release-notes.md
@@ -7,7 +7,6 @@
* Dependencies updates:
- ReactiveX/RxSwift@4.2.0
- httpswift/swifter@1.4.2
- - `MMCoreTextView` of MacVim: macvim-dev/macvim@351faf929e4abe32ea4cc31078d1a625fc86a69f
# 0.24.0-282