mirror of
https://github.com/qvacua/vimr.git
synced 2024-12-25 23:02:35 +03:00
GH-666 Delete MMCoreTextView.m and TextDrawer.m
This commit is contained in:
parent
71fad2ebc2
commit
c5e0736efe
@ -52,13 +52,9 @@
|
|||||||
4B90F03A1FD2AFAE008A39E0 /* NvimView+Key.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F01C1FD2AFAC008A39E0 /* NvimView+Key.swift */; };
|
4B90F03A1FD2AFAE008A39E0 /* NvimView+Key.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F01C1FD2AFAC008A39E0 /* NvimView+Key.swift */; };
|
||||||
4B90F03B1FD2AFAE008A39E0 /* NvimObjectsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F01D1FD2AFAC008A39E0 /* NvimObjectsExtensions.swift */; };
|
4B90F03B1FD2AFAE008A39E0 /* NvimObjectsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F01D1FD2AFAC008A39E0 /* NvimObjectsExtensions.swift */; };
|
||||||
4B90F03C1FD2AFAE008A39E0 /* NvimView+TouchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F01E1FD2AFAC008A39E0 /* NvimView+TouchBar.swift */; };
|
4B90F03C1FD2AFAE008A39E0 /* NvimView+TouchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F01E1FD2AFAC008A39E0 /* NvimView+TouchBar.swift */; };
|
||||||
4B90F03E1FD2AFAE008A39E0 /* MMCoreTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0201FD2AFAD008A39E0 /* MMCoreTextView.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
|
||||||
4B90F03F1FD2AFAE008A39E0 /* NvimView+Draw.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0211FD2AFAD008A39E0 /* NvimView+Draw.swift */; };
|
4B90F03F1FD2AFAE008A39E0 /* NvimView+Draw.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0211FD2AFAD008A39E0 /* NvimView+Draw.swift */; };
|
||||||
4B90F0401FD2AFAE008A39E0 /* TextDrawer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0221FD2AFAD008A39E0 /* TextDrawer.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
|
||||||
4B90F0411FD2AFAE008A39E0 /* TextDrawer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90F0231FD2AFAD008A39E0 /* TextDrawer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
4B90F0421FD2AFAE008A39E0 /* NvimView+UiBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0241FD2AFAD008A39E0 /* NvimView+UiBridge.swift */; };
|
4B90F0421FD2AFAE008A39E0 /* NvimView+UiBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0241FD2AFAD008A39E0 /* NvimView+UiBridge.swift */; };
|
||||||
4B90F0431FD2AFAE008A39E0 /* NvimView+MenuItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0251FD2AFAD008A39E0 /* NvimView+MenuItems.swift */; };
|
4B90F0431FD2AFAE008A39E0 /* NvimView+MenuItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0251FD2AFAD008A39E0 /* NvimView+MenuItems.swift */; };
|
||||||
4B90F0441FD2AFAE008A39E0 /* MMCoreTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90F0261FD2AFAD008A39E0 /* MMCoreTextView.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
|
||||||
4B90F0451FD2AFAE008A39E0 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0271FD2AFAD008A39E0 /* Logger.swift */; };
|
4B90F0451FD2AFAE008A39E0 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0271FD2AFAD008A39E0 /* Logger.swift */; };
|
||||||
4B90F0461FD2AFAE008A39E0 /* Grid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0281FD2AFAD008A39E0 /* Grid.swift */; };
|
4B90F0461FD2AFAE008A39E0 /* Grid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0281FD2AFAD008A39E0 /* Grid.swift */; };
|
||||||
4B90F0521FD2AFD3008A39E0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0511FD2AFD3008A39E0 /* main.m */; };
|
4B90F0521FD2AFD3008A39E0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0511FD2AFD3008A39E0 /* main.m */; };
|
||||||
@ -210,13 +206,9 @@
|
|||||||
4B90F01D1FD2AFAC008A39E0 /* NvimObjectsExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NvimObjectsExtensions.swift; sourceTree = "<group>"; };
|
4B90F01D1FD2AFAC008A39E0 /* NvimObjectsExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NvimObjectsExtensions.swift; sourceTree = "<group>"; };
|
||||||
4B90F01E1FD2AFAC008A39E0 /* NvimView+TouchBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+TouchBar.swift"; sourceTree = "<group>"; };
|
4B90F01E1FD2AFAC008A39E0 /* NvimView+TouchBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+TouchBar.swift"; sourceTree = "<group>"; };
|
||||||
4B90F01F1FD2AFAD008A39E0 /* InputTestView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputTestView.swift; sourceTree = "<group>"; };
|
4B90F01F1FD2AFAD008A39E0 /* InputTestView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputTestView.swift; sourceTree = "<group>"; };
|
||||||
4B90F0201FD2AFAD008A39E0 /* MMCoreTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMCoreTextView.m; sourceTree = "<group>"; };
|
|
||||||
4B90F0211FD2AFAD008A39E0 /* NvimView+Draw.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+Draw.swift"; sourceTree = "<group>"; };
|
4B90F0211FD2AFAD008A39E0 /* NvimView+Draw.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+Draw.swift"; sourceTree = "<group>"; };
|
||||||
4B90F0221FD2AFAD008A39E0 /* TextDrawer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextDrawer.m; sourceTree = "<group>"; };
|
|
||||||
4B90F0231FD2AFAD008A39E0 /* TextDrawer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextDrawer.h; sourceTree = "<group>"; };
|
|
||||||
4B90F0241FD2AFAD008A39E0 /* NvimView+UiBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+UiBridge.swift"; sourceTree = "<group>"; };
|
4B90F0241FD2AFAD008A39E0 /* NvimView+UiBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+UiBridge.swift"; sourceTree = "<group>"; };
|
||||||
4B90F0251FD2AFAD008A39E0 /* NvimView+MenuItems.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+MenuItems.swift"; sourceTree = "<group>"; };
|
4B90F0251FD2AFAD008A39E0 /* NvimView+MenuItems.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+MenuItems.swift"; sourceTree = "<group>"; };
|
||||||
4B90F0261FD2AFAD008A39E0 /* MMCoreTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMCoreTextView.h; sourceTree = "<group>"; };
|
|
||||||
4B90F0271FD2AFAD008A39E0 /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
|
4B90F0271FD2AFAD008A39E0 /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
|
||||||
4B90F0281FD2AFAD008A39E0 /* Grid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Grid.swift; sourceTree = "<group>"; };
|
4B90F0281FD2AFAD008A39E0 /* Grid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Grid.swift; sourceTree = "<group>"; };
|
||||||
4B90F04F1FD2AFD3008A39E0 /* NvimServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NvimServer; sourceTree = BUILT_PRODUCTS_DIR; };
|
4B90F04F1FD2AFD3008A39E0 /* NvimServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NvimServer; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@ -365,8 +357,6 @@
|
|||||||
4B90F01F1FD2AFAD008A39E0 /* InputTestView.swift */,
|
4B90F01F1FD2AFAD008A39E0 /* InputTestView.swift */,
|
||||||
4B90F0121FD2AFAC008A39E0 /* KeyUtils.swift */,
|
4B90F0121FD2AFAC008A39E0 /* KeyUtils.swift */,
|
||||||
4B90F0271FD2AFAD008A39E0 /* Logger.swift */,
|
4B90F0271FD2AFAD008A39E0 /* Logger.swift */,
|
||||||
4B90F0261FD2AFAD008A39E0 /* MMCoreTextView.h */,
|
|
||||||
4B90F0201FD2AFAD008A39E0 /* MMCoreTextView.m */,
|
|
||||||
4BD8742F2014C25F0039888E /* NvimAutoCommandEvent.generated.swift */,
|
4BD8742F2014C25F0039888E /* NvimAutoCommandEvent.generated.swift */,
|
||||||
4B90F01D1FD2AFAC008A39E0 /* NvimObjectsExtensions.swift */,
|
4B90F01D1FD2AFAC008A39E0 /* NvimObjectsExtensions.swift */,
|
||||||
4B90F0101FD2AFAC008A39E0 /* NvimView.swift */,
|
4B90F0101FD2AFAC008A39E0 /* NvimView.swift */,
|
||||||
@ -379,8 +369,6 @@
|
|||||||
4B90F0111FD2AFAC008A39E0 /* NvimView+Resize.swift */,
|
4B90F0111FD2AFAC008A39E0 /* NvimView+Resize.swift */,
|
||||||
4B90F01E1FD2AFAC008A39E0 /* NvimView+TouchBar.swift */,
|
4B90F01E1FD2AFAC008A39E0 /* NvimView+TouchBar.swift */,
|
||||||
4B90F0241FD2AFAD008A39E0 /* NvimView+UiBridge.swift */,
|
4B90F0241FD2AFAD008A39E0 /* NvimView+UiBridge.swift */,
|
||||||
4B90F0231FD2AFAD008A39E0 /* TextDrawer.h */,
|
|
||||||
4B90F0221FD2AFAD008A39E0 /* TextDrawer.m */,
|
|
||||||
1929B22A0CAD417EC3790F02 /* NvimViewObjects.swift */,
|
1929B22A0CAD417EC3790F02 /* NvimViewObjects.swift */,
|
||||||
1929BBD7F88AE4F01E626691 /* NvimApiExtension.swift */,
|
1929BBD7F88AE4F01E626691 /* NvimApiExtension.swift */,
|
||||||
1929B52174EC68D2974B5BAE /* UiBridge.swift */,
|
1929B52174EC68D2974B5BAE /* UiBridge.swift */,
|
||||||
@ -443,9 +431,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
4BF18C5D1FD2EEE400DF95D1 /* NvimView.h in Headers */,
|
4BF18C5D1FD2EEE400DF95D1 /* NvimView.h in Headers */,
|
||||||
4B90F0411FD2AFAE008A39E0 /* TextDrawer.h in Headers */,
|
|
||||||
4B177886201220F300E32FF0 /* SharedTypes.h in Headers */,
|
4B177886201220F300E32FF0 /* SharedTypes.h in Headers */,
|
||||||
4B90F0441FD2AFAE008A39E0 /* MMCoreTextView.h in Headers */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -633,12 +619,10 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
4B90F03E1FD2AFAE008A39E0 /* MMCoreTextView.m in Sources */,
|
|
||||||
4B90F03F1FD2AFAE008A39E0 /* NvimView+Draw.swift in Sources */,
|
4B90F03F1FD2AFAE008A39E0 /* NvimView+Draw.swift in Sources */,
|
||||||
4B90F02F1FD2AFAE008A39E0 /* NvimView+Resize.swift in Sources */,
|
4B90F02F1FD2AFAE008A39E0 /* NvimView+Resize.swift in Sources */,
|
||||||
4B90F0461FD2AFAE008A39E0 /* Grid.swift in Sources */,
|
4B90F0461FD2AFAE008A39E0 /* Grid.swift in Sources */,
|
||||||
4B90F0421FD2AFAE008A39E0 /* NvimView+UiBridge.swift in Sources */,
|
4B90F0421FD2AFAE008A39E0 /* NvimView+UiBridge.swift in Sources */,
|
||||||
4B90F0401FD2AFAE008A39E0 /* TextDrawer.m in Sources */,
|
|
||||||
4BD874302014C2600039888E /* NvimAutoCommandEvent.generated.swift in Sources */,
|
4BD874302014C2600039888E /* NvimAutoCommandEvent.generated.swift in Sources */,
|
||||||
4B90F02E1FD2AFAE008A39E0 /* NvimView.swift in Sources */,
|
4B90F02E1FD2AFAE008A39E0 /* NvimView.swift in Sources */,
|
||||||
4B90F03C1FD2AFAE008A39E0 /* NvimView+TouchBar.swift in Sources */,
|
4B90F03C1FD2AFAE008A39E0 /* NvimView+TouchBar.swift in Sources */,
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#import <CoreText/CoreText.h>
|
|
||||||
|
|
||||||
void recurseDraw(
|
|
||||||
const unichar *chars,
|
|
||||||
CGGlyph *glyphs, CGPoint *positions, UniCharCount length,
|
|
||||||
CGContextRef context,
|
|
||||||
CTFontRef fontRef,
|
|
||||||
NSMutableArray *fontCache,
|
|
||||||
BOOL useLigatures
|
|
||||||
);
|
|
@ -1,295 +0,0 @@
|
|||||||
/* vi:set ts=8 sts=4 sw=4 ft=objc:
|
|
||||||
*
|
|
||||||
* VIM - Vi IMproved by Bram Moolenaar
|
|
||||||
* MacVim GUI port by Bjorn Winckler
|
|
||||||
*
|
|
||||||
* Do ":help uganda" in Vim to read copying and usage conditions.
|
|
||||||
* Do ":help credits" in Vim to see a list of people who contributed.
|
|
||||||
* See README.txt for an overview of the Vim source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracted from snapshot-146 of MacVim
|
|
||||||
* https://github.com/macvim-dev/macvim
|
|
||||||
* See VIM.LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
// We suppress the following warnings since the original code does have it...
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
|
|
||||||
|
|
||||||
#import "MMCoreTextView.h"
|
|
||||||
|
|
||||||
static CTFontRef
|
|
||||||
lookupFont(NSMutableArray *fontCache, const unichar *chars, UniCharCount count,
|
|
||||||
CTFontRef currFontRef)
|
|
||||||
{
|
|
||||||
CGGlyph glyphs[count];
|
|
||||||
|
|
||||||
// See if font in cache can draw at least one character
|
|
||||||
NSUInteger i;
|
|
||||||
for (i = 0; i < [fontCache count]; ++i) {
|
|
||||||
NSFont *font = [fontCache objectAtIndex:i];
|
|
||||||
|
|
||||||
if (CTFontGetGlyphsForCharacters((CTFontRef)font, chars, glyphs, count))
|
|
||||||
return (CTFontRef)[font retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask Core Text for a font (can be *very* slow, which is why we cache
|
|
||||||
// fonts in the first place)
|
|
||||||
CFRange r = { 0, count };
|
|
||||||
CFStringRef strRef = CFStringCreateWithCharacters(NULL, chars, count);
|
|
||||||
CTFontRef newFontRef = CTFontCreateForString(currFontRef, strRef, r);
|
|
||||||
CFRelease(strRef);
|
|
||||||
|
|
||||||
// Verify the font can actually convert all the glyphs.
|
|
||||||
if (!CTFontGetGlyphsForCharacters(newFontRef, chars, glyphs, count))
|
|
||||||
return nil;
|
|
||||||
|
|
||||||
if (newFontRef)
|
|
||||||
[fontCache addObject:(NSFont *)newFontRef];
|
|
||||||
|
|
||||||
return newFontRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CFAttributedStringRef
|
|
||||||
attributedStringForString(NSString *string, const CTFontRef font,
|
|
||||||
BOOL useLigatures)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static UniCharCount
|
|
||||||
fetchGlyphsAndAdvances(const CTLineRef line, CGGlyph *glyphs, CGSize *advances,
|
|
||||||
UniCharCount length)
|
|
||||||
{
|
|
||||||
NSArray *glyphRuns = (NSArray*)CTLineGetGlyphRuns(line);
|
|
||||||
|
|
||||||
// get a hold on the actual character widths and glyphs in line
|
|
||||||
UniCharCount offset = 0;
|
|
||||||
for (id item in glyphRuns) {
|
|
||||||
CTRunRef run = (CTRunRef)item;
|
|
||||||
CFIndex count = CTRunGetGlyphCount(run);
|
|
||||||
|
|
||||||
if (count > 0 && count - offset > length)
|
|
||||||
count = length - offset;
|
|
||||||
|
|
||||||
CFRange range = CFRangeMake(0, count);
|
|
||||||
|
|
||||||
if (glyphs != NULL)
|
|
||||||
CTRunGetGlyphs(run, range, &glyphs[offset]);
|
|
||||||
if (advances != NULL)
|
|
||||||
CTRunGetAdvances(run, range, &advances[offset]);
|
|
||||||
|
|
||||||
offset += count;
|
|
||||||
if (offset >= length)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UniCharCount
|
|
||||||
gatherGlyphs(CGGlyph glyphs[], UniCharCount count)
|
|
||||||
{
|
|
||||||
// Gather scattered glyphs that was happended by Surrogate pair chars
|
|
||||||
UniCharCount glyphCount = 0;
|
|
||||||
NSUInteger pos = 0;
|
|
||||||
NSUInteger i;
|
|
||||||
for (i = 0; i < count; ++i) {
|
|
||||||
if (glyphs[i] != 0) {
|
|
||||||
++glyphCount;
|
|
||||||
glyphs[pos++] = glyphs[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return glyphCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UniCharCount
|
|
||||||
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 ligatureText = attributedStringForString(plainText,
|
|
||||||
font, YES);
|
|
||||||
|
|
||||||
CTLineRef ligature = CTLineCreateWithAttributedString(ligatureText);
|
|
||||||
|
|
||||||
CGSize ligatureRanges[length], regularRanges[length];
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
recurseDraw(const unichar *chars, CGGlyph *glyphs, CGPoint *positions,
|
|
||||||
UniCharCount length, CGContextRef context, CTFontRef fontRef,
|
|
||||||
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) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGGlyph *glyphsEnd = glyphs+length, *g = glyphs;
|
|
||||||
CGPoint *p = positions;
|
|
||||||
const unichar *c = chars;
|
|
||||||
while (glyphs < glyphsEnd) {
|
|
||||||
if (*g) {
|
|
||||||
// Draw as many consecutive glyphs as possible in the current font
|
|
||||||
// (if a glyph is 0 that means it does not exist in the current
|
|
||||||
// font).
|
|
||||||
BOOL surrogatePair = NO;
|
|
||||||
while (*g && g < glyphsEnd) {
|
|
||||||
if (CFStringIsSurrogateHighCharacter(*c)) {
|
|
||||||
surrogatePair = YES;
|
|
||||||
g += 2;
|
|
||||||
c += 2;
|
|
||||||
} else {
|
|
||||||
++g;
|
|
||||||
++c;
|
|
||||||
}
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = g-glyphs;
|
|
||||||
if (surrogatePair)
|
|
||||||
count = gatherGlyphs(glyphs, count);
|
|
||||||
CTFontDrawGlyphs(fontRef, glyphs, positions, count, context);
|
|
||||||
} else {
|
|
||||||
// Skip past as many consecutive chars as possible which cannot be
|
|
||||||
// drawn in the current font.
|
|
||||||
while (0 == *g && g < glyphsEnd) {
|
|
||||||
if (CFStringIsSurrogateHighCharacter(*c)) {
|
|
||||||
g += 2;
|
|
||||||
c += 2;
|
|
||||||
} else {
|
|
||||||
++g;
|
|
||||||
++c;
|
|
||||||
}
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find a fallback font that can render the entire
|
|
||||||
// invalid range. If that fails, repeatedly halve the attempted
|
|
||||||
// range until a font is found.
|
|
||||||
UniCharCount count = c - chars;
|
|
||||||
UniCharCount attemptedCount = count;
|
|
||||||
CTFontRef fallback = nil;
|
|
||||||
while (fallback == nil && attemptedCount > 0) {
|
|
||||||
fallback = lookupFont(fontCache, chars, attemptedCount,
|
|
||||||
fontRef);
|
|
||||||
if (!fallback)
|
|
||||||
attemptedCount /= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fallback)
|
|
||||||
return;
|
|
||||||
|
|
||||||
recurseDraw(chars, glyphs, positions, attemptedCount, context,
|
|
||||||
fallback, fontCache, useLigatures);
|
|
||||||
|
|
||||||
// If only a portion of the invalid range was rendered above,
|
|
||||||
// the remaining range needs to be attempted by subsequent
|
|
||||||
// iterations of the draw loop.
|
|
||||||
c -= count - attemptedCount;
|
|
||||||
g -= count - attemptedCount;
|
|
||||||
p -= count - attemptedCount;
|
|
||||||
|
|
||||||
CFRelease(fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glyphs == g) {
|
|
||||||
// No valid chars in the glyphs. Exit from the possible infinite
|
|
||||||
// recursive call.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
chars = c;
|
|
||||||
glyphs = g;
|
|
||||||
positions = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
|
@ -272,7 +272,6 @@ extension NvimView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateFontMetaData(_ newFont: NSFont) {
|
func updateFontMetaData(_ newFont: NSFont) {
|
||||||
self.drawer.font = newFont
|
|
||||||
self.runDrawer.baseFont = newFont
|
self.runDrawer.baseFont = newFont
|
||||||
|
|
||||||
self.cellSize = FontUtils.cellSize(
|
self.cellSize = FontUtils.cellSize(
|
||||||
|
@ -214,14 +214,14 @@ extension NvimView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func makeFontBigger(_ sender: Any?) {
|
@IBAction func makeFontBigger(_ sender: Any?) {
|
||||||
let curFont = self.drawer.font
|
let curFont = self.runDrawer.baseFont
|
||||||
let font = NSFontManager.shared
|
let font = NSFontManager.shared
|
||||||
.convert(curFont, toSize: min(curFont.pointSize + 1, NvimView.maxFontSize))
|
.convert(curFont, toSize: min(curFont.pointSize + 1, NvimView.maxFontSize))
|
||||||
self.updateFontMetaData(font)
|
self.updateFontMetaData(font)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func makeFontSmaller(_ sender: Any?) {
|
@IBAction func makeFontSmaller(_ sender: Any?) {
|
||||||
let curFont = self.drawer.font
|
let curFont = self.runDrawer.baseFont
|
||||||
let font = NSFontManager.shared
|
let font = NSFontManager.shared
|
||||||
.convert(curFont, toSize: max(curFont.pointSize - 1, NvimView.minFontSize))
|
.convert(curFont, toSize: max(curFont.pointSize - 1, NvimView.minFontSize))
|
||||||
self.updateFontMetaData(font)
|
self.updateFontMetaData(font)
|
||||||
|
@ -14,5 +14,4 @@ FOUNDATION_EXPORT const unsigned char NvimViewVersionString[];
|
|||||||
// In this header, you should import all the public headers of your framework using statements like #import <NvimView/PublicHeader.h>
|
// In this header, you should import all the public headers of your framework using statements like #import <NvimView/PublicHeader.h>
|
||||||
|
|
||||||
// TODO: this header should not be public, but we cannot use a bridging header in a framework.
|
// TODO: this header should not be public, but we cannot use a bridging header in a framework.
|
||||||
#import <NvimView/TextDrawer.h>
|
|
||||||
#import <NvimView/SharedTypes.h>
|
#import <NvimView/SharedTypes.h>
|
||||||
|
@ -124,7 +124,6 @@ public class NvimView: NSView,
|
|||||||
|
|
||||||
public var usesLigatures = false {
|
public var usesLigatures = false {
|
||||||
didSet {
|
didSet {
|
||||||
self.drawer.usesLigatures = self.usesLigatures
|
|
||||||
self.runDrawer.usesLigatures = self.usesLigatures
|
self.runDrawer.usesLigatures = self.usesLigatures
|
||||||
self.needsDisplay = true
|
self.needsDisplay = true
|
||||||
}
|
}
|
||||||
@ -141,7 +140,6 @@ public class NvimView: NSView,
|
|||||||
}
|
}
|
||||||
|
|
||||||
self._linespacing = newValue
|
self._linespacing = newValue
|
||||||
self.drawer.linespacing = self.linespacing
|
|
||||||
self.runDrawer.linespacing = self.linespacing
|
self.runDrawer.linespacing = self.linespacing
|
||||||
|
|
||||||
self.updateFontMetaData(self._font)
|
self.updateFontMetaData(self._font)
|
||||||
@ -198,7 +196,6 @@ public class NvimView: NSView,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public init(frame rect: NSRect, config: Config) {
|
public init(frame rect: NSRect, config: Config) {
|
||||||
self.drawer = TextDrawer(font: self._font)
|
|
||||||
self.runDrawer = AttributesRunDrawer(
|
self.runDrawer = AttributesRunDrawer(
|
||||||
baseFont: self._font,
|
baseFont: self._font,
|
||||||
linespacing: self._linespacing,
|
linespacing: self._linespacing,
|
||||||
@ -347,7 +344,6 @@ public class NvimView: NSView,
|
|||||||
let ugrid = UGrid()
|
let ugrid = UGrid()
|
||||||
|
|
||||||
let cellAttributesCollection = CellAttributesCollection()
|
let cellAttributesCollection = CellAttributesCollection()
|
||||||
let drawer: TextDrawer
|
|
||||||
let runDrawer: AttributesRunDrawer
|
let runDrawer: AttributesRunDrawer
|
||||||
|
|
||||||
var markedText: String?
|
var markedText: String?
|
||||||
|
@ -5,7 +5,13 @@
|
|||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
extension OldCellAttributes: CustomStringConvertible, Equatable {
|
struct OldCellAttributes: CustomStringConvertible, Equatable {
|
||||||
|
|
||||||
|
var fontTrait: FontTrait
|
||||||
|
var foreground: Int
|
||||||
|
var background: Int
|
||||||
|
var special: Int
|
||||||
|
var reverse: Bool
|
||||||
|
|
||||||
public static var debug: OldCellAttributes {
|
public static var debug: OldCellAttributes {
|
||||||
return OldCellAttributes(fontTrait: [], foreground: 0, background: 0, special: 0, reverse: false)
|
return OldCellAttributes(fontTrait: [], foreground: 0, background: 0, special: 0, reverse: false)
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
/**
|
|
||||||
* Tae Won Ha - http://taewon.de - @hataewon
|
|
||||||
* See LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#import <CoreText/CoreText.h>
|
|
||||||
|
|
||||||
|
|
||||||
#import "SharedTypes.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
FontTrait fontTrait;
|
|
||||||
|
|
||||||
NSInteger foreground;
|
|
||||||
NSInteger background;
|
|
||||||
NSInteger special;
|
|
||||||
bool reverse;
|
|
||||||
} OldCellAttributes;
|
|
||||||
|
|
||||||
@interface TextDrawer : NSObject
|
|
||||||
|
|
||||||
@property (nonatomic, nonnull, retain) NSFont *font;
|
|
||||||
@property (nonatomic) bool usesLigatures;
|
|
||||||
@property (nonatomic, readonly) CGFloat baselineOffset;
|
|
||||||
@property (nonatomic, readonly) CGFloat leading;
|
|
||||||
@property (nonatomic, readonly) CGFloat descent;
|
|
||||||
@property (nonatomic) CGFloat linespacing;
|
|
||||||
@property (nonatomic, readonly) CGSize cellSize;
|
|
||||||
|
|
||||||
- (instancetype _Nonnull)initWithFont:(NSFont *_Nonnull)font;
|
|
||||||
|
|
||||||
- (void)drawString:(NSString *_Nonnull)string
|
|
||||||
positions:(CGPoint *_Nonnull)positions positionsCount:(NSInteger)positionsCount
|
|
||||||
highlightAttrs:(OldCellAttributes)attrs
|
|
||||||
context:(CGContextRef _Nonnull)context;
|
|
||||||
|
|
||||||
@end
|
|
@ -1,278 +0,0 @@
|
|||||||
/**
|
|
||||||
* Tae Won Ha - http://taewon.de - @hataewon
|
|
||||||
* See LICENSE
|
|
||||||
*
|
|
||||||
* Almost a verbatim copy from MacVim by Bjorn Winckler
|
|
||||||
* See VIM.LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import "TextDrawer.h"
|
|
||||||
#import "MMCoreTextView.h"
|
|
||||||
|
|
||||||
#define ALPHA(color_code) (((color_code >> 24) & 0xff) / 255.0f)
|
|
||||||
#define RED(color_code) (((color_code >> 16) & 0xff) / 255.0f)
|
|
||||||
#define GREEN(color_code) (((color_code >> 8) & 0xff) / 255.0f)
|
|
||||||
#define BLUE(color_code) (((color_code ) & 0xff) / 255.0f)
|
|
||||||
|
|
||||||
static dispatch_once_t token;
|
|
||||||
static NSCache *colorCache;
|
|
||||||
|
|
||||||
static CGColorRef color_for(NSInteger value) {
|
|
||||||
NSColor *color = [colorCache objectForKey:@(value)];
|
|
||||||
if (color != nil) {
|
|
||||||
return color.CGColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
color = [NSColor colorWithSRGBRed:RED(value) green:GREEN(value) blue:BLUE(value) alpha:1];
|
|
||||||
[colorCache setObject:color forKey:@(value)];
|
|
||||||
|
|
||||||
return color.CGColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@implementation TextDrawer {
|
|
||||||
NSLayoutManager *_layoutManager;
|
|
||||||
|
|
||||||
NSFont *_font;
|
|
||||||
CGFloat _ascent;
|
|
||||||
CGFloat _underlinePosition;
|
|
||||||
CGFloat _underlineThickness;
|
|
||||||
CGFloat _linespacing;
|
|
||||||
|
|
||||||
NSMutableArray *_fontLookupCache;
|
|
||||||
NSMutableDictionary *_fontTraitCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGFloat)baselineOffset {
|
|
||||||
return _cellSize.height - _ascent;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setLinespacing:(CGFloat)linespacing {
|
|
||||||
// FIXME: reasonable min and max
|
|
||||||
_linespacing = linespacing;
|
|
||||||
_cellSize = [self cellSizeWithFont:_font linespacing:_linespacing];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setFont:(NSFont *)font {
|
|
||||||
[_font autorelease];
|
|
||||||
|
|
||||||
_font = [font retain];
|
|
||||||
[_fontTraitCache removeAllObjects];
|
|
||||||
[_fontLookupCache removeAllObjects];
|
|
||||||
|
|
||||||
_cellSize = [self cellSizeWithFont:font linespacing:_linespacing];
|
|
||||||
|
|
||||||
_ascent = CTFontGetAscent((CTFontRef) _font);
|
|
||||||
_leading = CTFontGetLeading((CTFontRef) _font);
|
|
||||||
_descent = CTFontGetDescent((CTFontRef) _font);
|
|
||||||
_underlinePosition = CTFontGetUnderlinePosition((CTFontRef) _font); // This seems to take the thickness into account
|
|
||||||
// TODO: Maybe we should use 0.5 or 1 as minimum thickness for Retina and non-Retina, respectively.
|
|
||||||
_underlineThickness = CTFontGetUnderlineThickness((CTFontRef) _font);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype _Nonnull)initWithFont:(NSFont *_Nonnull)font {
|
|
||||||
dispatch_once (&token, ^{
|
|
||||||
colorCache = [NSCache new];
|
|
||||||
colorCache.countLimit = 1000;
|
|
||||||
});
|
|
||||||
|
|
||||||
self = [super init];
|
|
||||||
if (self == nil) {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
_usesLigatures = NO;
|
|
||||||
_linespacing = 1;
|
|
||||||
|
|
||||||
_layoutManager = [[NSLayoutManager alloc] init];
|
|
||||||
_fontLookupCache = [[NSMutableArray alloc] init];
|
|
||||||
_fontTraitCache = [[NSMutableDictionary alloc] init];
|
|
||||||
|
|
||||||
self.font = font;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc {
|
|
||||||
[_layoutManager release];
|
|
||||||
[_font release];
|
|
||||||
[_fontLookupCache release];
|
|
||||||
[_fontTraitCache release];
|
|
||||||
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We assume that the background is drawn elsewhere and that the caller has already called
|
|
||||||
*
|
|
||||||
* CGContextSetTextMatrix(context, CGAffineTransformIdentity); // or some other matrix
|
|
||||||
* CGContextSetTextDrawingMode(context, kCGTextFill); // or some other mode
|
|
||||||
*/
|
|
||||||
- (void)drawString:(NSString *_Nonnull)string
|
|
||||||
positions:(CGPoint *_Nonnull)positions
|
|
||||||
positionsCount:(NSInteger)positionsCount
|
|
||||||
highlightAttrs:(OldCellAttributes)attrs
|
|
||||||
context:(CGContextRef _Nonnull)context
|
|
||||||
{
|
|
||||||
CGContextSaveGState(context);
|
|
||||||
|
|
||||||
[self drawString:string positions:positions
|
|
||||||
fontTrait:attrs.fontTrait foreground:attrs.foreground
|
|
||||||
context:context];
|
|
||||||
|
|
||||||
if (attrs.fontTrait & FontTraitUnderline) {
|
|
||||||
[self drawUnderline:positions count:positionsCount color:attrs.foreground context:context];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.fontTrait & FontTraitUndercurl) {
|
|
||||||
[self drawUntercurl:positions count:positionsCount color:attrs.special context:context];
|
|
||||||
}
|
|
||||||
|
|
||||||
CGContextRestoreGState(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)drawUntercurl:(const CGPoint *_Nonnull)positions
|
|
||||||
count:(NSInteger)count
|
|
||||||
color:(NSInteger)color
|
|
||||||
context:(CGContextRef _Nonnull)context
|
|
||||||
{
|
|
||||||
CGFloat x0 = positions[0].x;
|
|
||||||
CGFloat y0 = positions[0].y - 0.1 * _cellSize.height;
|
|
||||||
CGFloat w = _cellSize.width;
|
|
||||||
CGFloat h = 0.5 * _descent;
|
|
||||||
|
|
||||||
CGContextMoveToPoint(context, x0, y0);
|
|
||||||
for (int k = 0; k < count; k++) {
|
|
||||||
CGContextAddCurveToPoint(context, x0 + 0.25 * w, y0, x0 + 0.25 * w, y0 + h, x0 + 0.5 * w, y0 + h);
|
|
||||||
CGContextAddCurveToPoint(context, x0 + 0.75 * w, y0 + h, x0 + 0.75 * w, y0, x0 + w, y0);
|
|
||||||
x0 += w;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGContextSetStrokeColorWithColor(context, color_for(color));
|
|
||||||
CGContextStrokePath(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)drawUnderline:(const CGPoint *_Nonnull)positions
|
|
||||||
count:(NSInteger)count
|
|
||||||
color:(NSInteger)color
|
|
||||||
context:(CGContextRef _Nonnull)context
|
|
||||||
{
|
|
||||||
CGContextSetFillColorWithColor(context, color_for(color));
|
|
||||||
CGRect rect = {
|
|
||||||
{positions[0].x, positions[0].y + _underlinePosition},
|
|
||||||
{count * _cellSize.width, _underlineThickness}
|
|
||||||
};
|
|
||||||
CGContextFillRect(context, rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)drawString:(NSString *_Nonnull)nsstring
|
|
||||||
positions:(CGPoint *_Nonnull)positions
|
|
||||||
fontTrait:(FontTrait)fontTrait
|
|
||||||
foreground:(NSInteger)foreground
|
|
||||||
context:(CGContextRef _Nonnull)context
|
|
||||||
{
|
|
||||||
CFStringRef string = (CFStringRef) nsstring;
|
|
||||||
|
|
||||||
UniChar *unibuffer = NULL;
|
|
||||||
UniCharCount unilength = (UniCharCount) CFStringGetLength(string);
|
|
||||||
const UniChar *unichars = CFStringGetCharactersPtr(string);
|
|
||||||
if (unichars == NULL) {
|
|
||||||
unibuffer = malloc(unilength * sizeof(UniChar));
|
|
||||||
CFStringGetCharacters(string, CFRangeMake(0, unilength), unibuffer);
|
|
||||||
unichars = unibuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGGlyph *glyphs = malloc(unilength * sizeof(CGGlyph));
|
|
||||||
CTFontRef fontWithTraits = [self fontWithTrait:fontTrait];
|
|
||||||
|
|
||||||
CGContextSetFillColorWithColor(context, color_for(foreground));
|
|
||||||
CGGlyph *g = glyphs;
|
|
||||||
CGPoint *p = positions;
|
|
||||||
const UniChar *b = unichars;
|
|
||||||
const UniChar *bStart = unichars;
|
|
||||||
const UniChar *bEnd = unichars + unilength;
|
|
||||||
UniCharCount choppedLength;
|
|
||||||
bool wide;
|
|
||||||
bool pWide = NO;
|
|
||||||
|
|
||||||
while (b < bEnd) {
|
|
||||||
wide = CFStringIsSurrogateHighCharacter(*b) || CFStringIsSurrogateLowCharacter(*b);
|
|
||||||
if ((b > unichars) && (wide != pWide)) {
|
|
||||||
choppedLength = b - bStart;
|
|
||||||
// NSString *logged = [NSString stringWithCharacters:bStart length:choppedLength];
|
|
||||||
// NSLog(@"C(%d,%p..%p)[%@]", pWide, bStart, b, logged);
|
|
||||||
recurseDraw(bStart, glyphs, p, choppedLength, context, fontWithTraits, _fontLookupCache, _usesLigatures);
|
|
||||||
UniCharCount step = pWide ? choppedLength / 2 : choppedLength;
|
|
||||||
p += step;
|
|
||||||
g += step;
|
|
||||||
bStart = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
pWide = wide;
|
|
||||||
b++;
|
|
||||||
}
|
|
||||||
if (bStart < bEnd) {
|
|
||||||
choppedLength = b - bStart;
|
|
||||||
// NSString *logged = [NSString stringWithCharacters:bStart length:choppedLength];
|
|
||||||
// NSLog(@"T(%d,%p..%p)[%@]", pWide, bStart, b, logged);
|
|
||||||
recurseDraw(bStart, glyphs, p, choppedLength, context, fontWithTraits, _fontLookupCache, _usesLigatures);
|
|
||||||
}
|
|
||||||
// NSLog(@"S(-,%p..%p)[%@]", unichars, unichars + unilength, string);
|
|
||||||
|
|
||||||
CFRelease(fontWithTraits);
|
|
||||||
free(glyphs);
|
|
||||||
if (unibuffer != NULL) {
|
|
||||||
free(unibuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGSize)cellSizeWithFont:(NSFont *)font linespacing:(CGFloat)linespacing {
|
|
||||||
// cf. https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html
|
|
||||||
CGFloat ascent = CTFontGetAscent((CTFontRef) _font);
|
|
||||||
CGFloat descent = CTFontGetDescent((CTFontRef) _font);
|
|
||||||
CGFloat leading = CTFontGetLeading((CTFontRef) _font);
|
|
||||||
|
|
||||||
CGSize result = CGSizeMake(
|
|
||||||
round([@"m" sizeWithAttributes:@{ NSFontAttributeName : _font }].width),
|
|
||||||
ceil(linespacing * (ascent + descent + leading))
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The caller _must_ CFRelease the returned CTFont!
|
|
||||||
*/
|
|
||||||
- (CTFontRef)fontWithTrait:(FontTrait)fontTrait {
|
|
||||||
if (fontTrait == FontTraitNone) {
|
|
||||||
return CFRetain(_font);
|
|
||||||
}
|
|
||||||
|
|
||||||
CTFontSymbolicTraits traits = (CTFontSymbolicTraits) 0;
|
|
||||||
if (fontTrait & FontTraitBold) {
|
|
||||||
traits |= kCTFontBoldTrait;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fontTrait & FontTraitItalic) {
|
|
||||||
traits |= kCTFontItalicTrait;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (traits == 0) {
|
|
||||||
return CFRetain(_font);
|
|
||||||
}
|
|
||||||
|
|
||||||
NSFont *cachedFont = _fontTraitCache[@(traits)];
|
|
||||||
if (cachedFont != nil) {
|
|
||||||
return CFRetain(cachedFont);
|
|
||||||
}
|
|
||||||
|
|
||||||
CTFontRef fontWithTraits = CTFontCreateCopyWithSymbolicTraits((CTFontRef) _font, 0.0, NULL, traits, traits);
|
|
||||||
if (fontWithTraits == NULL) {
|
|
||||||
return CFRetain(_font);
|
|
||||||
}
|
|
||||||
|
|
||||||
_fontTraitCache[@(traits)] = (NSFont *) fontWithTraits;
|
|
||||||
|
|
||||||
return fontWithTraits;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
@ -1,78 +0,0 @@
|
|||||||
VIM LICENSE
|
|
||||||
|
|
||||||
I) There are no restrictions on distributing unmodified copies of Vim except
|
|
||||||
that they must include this license text. You can also distribute
|
|
||||||
unmodified parts of Vim, likewise unrestricted except that they must
|
|
||||||
include this license text. You are also allowed to include executables
|
|
||||||
that you made from the unmodified Vim sources, plus your own usage
|
|
||||||
examples and Vim scripts.
|
|
||||||
|
|
||||||
II) It is allowed to distribute a modified (or extended) version of Vim,
|
|
||||||
including executables and/or source code, when the following four
|
|
||||||
conditions are met:
|
|
||||||
1) This license text must be included unmodified.
|
|
||||||
2) The modified Vim must be distributed in one of the following five ways:
|
|
||||||
a) If you make changes to Vim yourself, you must clearly describe in
|
|
||||||
the distribution how to contact you. When the maintainer asks you
|
|
||||||
(in any way) for a copy of the modified Vim you distributed, you
|
|
||||||
must make your changes, including source code, available to the
|
|
||||||
maintainer without fee. The maintainer reserves the right to
|
|
||||||
include your changes in the official version of Vim. What the
|
|
||||||
maintainer will do with your changes and under what license they
|
|
||||||
will be distributed is negotiable. If there has been no negotiation
|
|
||||||
then this license, or a later version, also applies to your changes.
|
|
||||||
The current maintainer is Bram Moolenaar <Bram@vim.org>. If this
|
|
||||||
changes it will be announced in appropriate places (most likely
|
|
||||||
vim.sf.net, www.vim.org and/or comp.editors). When it is completely
|
|
||||||
impossible to contact the maintainer, the obligation to send him
|
|
||||||
your changes ceases. Once the maintainer has confirmed that he has
|
|
||||||
received your changes they will not have to be sent again.
|
|
||||||
b) If you have received a modified Vim that was distributed as
|
|
||||||
mentioned under a) you are allowed to further distribute it
|
|
||||||
unmodified, as mentioned at I). If you make additional changes the
|
|
||||||
text under a) applies to those changes.
|
|
||||||
c) Provide all the changes, including source code, with every copy of
|
|
||||||
the modified Vim you distribute. This may be done in the form of a
|
|
||||||
context diff. You can choose what license to use for new code you
|
|
||||||
add. The changes and their license must not restrict others from
|
|
||||||
making their own changes to the official version of Vim.
|
|
||||||
d) When you have a modified Vim which includes changes as mentioned
|
|
||||||
under c), you can distribute it without the source code for the
|
|
||||||
changes if the following three conditions are met:
|
|
||||||
- The license that applies to the changes permits you to distribute
|
|
||||||
the changes to the Vim maintainer without fee or restriction, and
|
|
||||||
permits the Vim maintainer to include the changes in the official
|
|
||||||
version of Vim without fee or restriction.
|
|
||||||
- You keep the changes for at least three years after last
|
|
||||||
distributing the corresponding modified Vim. When the maintainer
|
|
||||||
or someone who you distributed the modified Vim to asks you (in
|
|
||||||
any way) for the changes within this period, you must make them
|
|
||||||
available to him.
|
|
||||||
- You clearly describe in the distribution how to contact you. This
|
|
||||||
contact information must remain valid for at least three years
|
|
||||||
after last distributing the corresponding modified Vim, or as long
|
|
||||||
as possible.
|
|
||||||
e) When the GNU General Public License (GPL) applies to the changes,
|
|
||||||
you can distribute the modified Vim under the GNU GPL version 2 or
|
|
||||||
any later version.
|
|
||||||
3) A message must be added, at least in the output of the ":version"
|
|
||||||
command and in the intro screen, such that the user of the modified Vim
|
|
||||||
is able to see that it was modified. When distributing as mentioned
|
|
||||||
under 2)e) adding the message is only required for as far as this does
|
|
||||||
not conflict with the license used for the changes.
|
|
||||||
4) The contact information as required under 2)a) and 2)d) must not be
|
|
||||||
removed or changed, except that the person himself can make
|
|
||||||
corrections.
|
|
||||||
|
|
||||||
III) If you distribute a modified version of Vim, you are encouraged to use
|
|
||||||
the Vim license for your changes and make them available to the
|
|
||||||
maintainer, including the source code. The preferred way to do this is
|
|
||||||
by e-mail or by uploading the files to a server and e-mailing the URL.
|
|
||||||
If the number of changes is small (e.g., a modified Makefile) e-mailing a
|
|
||||||
context diff will do. The e-mail address to be used is
|
|
||||||
<maintainer@vim.org>
|
|
||||||
|
|
||||||
IV) It is not allowed to remove this license from the distribution of the Vim
|
|
||||||
sources, parts of it or from a modified version. You may use this
|
|
||||||
license for previous Vim releases instead of the license that they came
|
|
||||||
with, at your option.
|
|
Loading…
Reference in New Issue
Block a user