mirror of
https://github.com/qvacua/vimr.git
synced 2024-10-28 03:38:54 +03:00
Use CoreText's font metric
This commit is contained in:
parent
bbc0096019
commit
d5420f4b78
@ -157,6 +157,7 @@ class Grid: CustomStringConvertible {
|
||||
}
|
||||
|
||||
private func clearRegion(region: Region) {
|
||||
// FIXME: sometimes clearRegion gets called without first resizing the Grid. Should we handle this?
|
||||
guard self.hasData else {
|
||||
return
|
||||
}
|
||||
|
@ -48,7 +48,8 @@ public class NeoVimView: NSView {
|
||||
didSet {
|
||||
self.drawer.font = self.font
|
||||
self.cellSize = self.drawer.cellSize
|
||||
self.lineSpace = self.drawer.lineSpace
|
||||
self.descent = self.drawer.descent
|
||||
self.leading = self.drawer.leading
|
||||
|
||||
// FIXME: resize and redraw
|
||||
}
|
||||
@ -58,21 +59,23 @@ public class NeoVimView: NSView {
|
||||
private let drawer: TextDrawer
|
||||
|
||||
private var cellSize = CGSize.zero
|
||||
private var lineSpace = CGFloat(0)
|
||||
private var descent = CGFloat(0)
|
||||
private var leading = CGFloat(0)
|
||||
|
||||
private let grid = Grid()
|
||||
|
||||
init(frame rect: NSRect = CGRect.zero, xpc: NeoVimXpc) {
|
||||
self.xpc = xpc
|
||||
|
||||
self.font = NSFont(name: "Menlo", size: 13)!
|
||||
self.font = NSFont(name: "Menlo", size: 16)!
|
||||
self.drawer = TextDrawer(font: font)
|
||||
|
||||
super.init(frame: rect)
|
||||
|
||||
self.wantsLayer = true
|
||||
self.cellSize = self.drawer.cellSize
|
||||
self.lineSpace = self.drawer.lineSpace
|
||||
self.descent = self.drawer.descent
|
||||
self.leading = self.drawer.leading
|
||||
}
|
||||
|
||||
override public func keyDown(theEvent: NSEvent) {
|
||||
@ -100,7 +103,7 @@ public class NeoVimView: NSView {
|
||||
self.drawBackground(positions: positions, background: rowFrag.attrs.background)
|
||||
|
||||
let string = self.grid.cells[rowFrag.row][rowFrag.range].reduce("") { $0 + $1.string }
|
||||
let glyphPositions = positions.map { CGPoint(x: $0.x, y: $0.y + self.lineSpace) }
|
||||
let glyphPositions = positions.map { CGPoint(x: $0.x, y: $0.y + self.descent + self.leading) }
|
||||
self.drawer.drawString(string,
|
||||
positions: UnsafeMutablePointer(glyphPositions), positionsCount: positions.count,
|
||||
highlightAttrs: rowFrag.attrs,
|
||||
@ -120,23 +123,26 @@ public class NeoVimView: NSView {
|
||||
private func rowRunIntersecting(rects rects: [CGRect]) -> [RowRun] {
|
||||
return rects
|
||||
.map { rect -> Region in
|
||||
// Get all Regions that intersects with the given rects. There can be overlaps between the Regions, but for the
|
||||
// time being we ignore them; probably not necessary to optimize them away.
|
||||
let rowStart = Int(floor((self.frame.height - (rect.origin.y + rect.size.height)) / self.cellSize.height))
|
||||
let rowEnd = Int(ceil((self.frame.height - rect.origin.y) / self.cellSize.height)) - 1
|
||||
let columnStart = Int(floor(rect.origin.x / self.cellSize.width))
|
||||
let columnEnd = Int(ceil((rect.origin.x + rect.size.width) / self.cellSize.width)) - 1
|
||||
|
||||
return Region(top: rowStart, bottom: rowEnd, left: columnStart, right: columnEnd)
|
||||
} // There can be overlaps between the Regions, but for the time being we ignore them.
|
||||
}
|
||||
.map { region -> [RowRun] in
|
||||
return (region.rowRange)
|
||||
// Map Regions to RowRuns for drawing.
|
||||
return region.rowRange
|
||||
// Map each row in a Region to RowRuns
|
||||
.map { row -> [RowRun] in
|
||||
let range = region.columnRange
|
||||
let columns = region.columnRange
|
||||
let rowCells = self.grid.cells[row]
|
||||
let startIndex = range.startIndex
|
||||
let startIndex = columns.startIndex
|
||||
|
||||
var result = [
|
||||
RowRun(row: row, range: startIndex...startIndex, attrs: rowCells[startIndex].attrs)
|
||||
]
|
||||
range.forEach { idx in
|
||||
var result = [ RowRun(row: row, range: startIndex...startIndex, attrs: rowCells[startIndex].attrs) ]
|
||||
columns.forEach { idx in
|
||||
if rowCells[idx].attrs == result.last!.attrs {
|
||||
let last = result.popLast()!
|
||||
result.append(RowRun(row: row, range: last.range.startIndex...idx, attrs: last.attrs))
|
||||
@ -145,11 +151,11 @@ public class NeoVimView: NSView {
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
} // -> [[RowRun]]
|
||||
.flatMap { $0 } // -> [RowRun]
|
||||
} // -> [[RowRun]]
|
||||
.flatMap { $0 } // -> [RowRun]
|
||||
return result // All RowRuns for a row in a Region.
|
||||
} // All RowRuns for all rows in a Region grouped by row.
|
||||
.flatMap { $0 } // Flattened RowRuns for a Region.
|
||||
} // All RowRuns for all Regions grouped by Region.
|
||||
.flatMap { $0 } // Flattened RowRuns for all Regions.
|
||||
}
|
||||
|
||||
private func positionOnView(row: Int, column: Int) -> CGPoint {
|
||||
|
@ -11,7 +11,8 @@
|
||||
@interface TextDrawer : NSObject
|
||||
|
||||
@property (nonatomic, nonnull, retain) NSFont *font;
|
||||
@property (nonatomic, readonly) CGFloat lineSpace;
|
||||
@property (nonatomic, readonly) CGFloat leading;
|
||||
@property (nonatomic, readonly) CGFloat descent;
|
||||
@property (nonatomic, readonly) CGSize cellSize;
|
||||
|
||||
- (instancetype _Nonnull)initWithFont:(NSFont *_Nonnull)font;
|
||||
|
@ -19,8 +19,8 @@
|
||||
NSLayoutManager *_layoutManager;
|
||||
|
||||
NSFont *_font;
|
||||
CGFloat _fontDescent;
|
||||
CGFloat _lineGap;
|
||||
CGFloat _underlinePosition;
|
||||
CGFloat _underlineThickness;
|
||||
|
||||
NSMutableArray *_fontLookupCache;
|
||||
NSMutableDictionary *_fontTraitCache;
|
||||
@ -30,13 +30,23 @@
|
||||
[_font autorelease];
|
||||
_font = [font retain];
|
||||
|
||||
// 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);
|
||||
CGFloat underlinePosition = CTFontGetUnderlinePosition((CTFontRef) _font);
|
||||
CGFloat underlineThickness = CTFontGetUnderlineThickness((CTFontRef) _font);
|
||||
|
||||
_cellSize = CGSizeMake(
|
||||
round([@"m" sizeWithAttributes:@{ NSFontAttributeName : _font }].width),
|
||||
[_layoutManager defaultLineHeightForFont:_font] + _lineSpace
|
||||
ceil(ascent + descent + leading)
|
||||
);
|
||||
// https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html
|
||||
_lineGap = _cellSize.height - _font.ascender - _font.descender;
|
||||
_fontDescent = CTFontGetDescent((CTFontRef) _font);
|
||||
|
||||
_leading = leading;
|
||||
_descent = descent;
|
||||
_underlinePosition = underlinePosition; // 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 = underlineThickness;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFont:(NSFont *_Nonnull)font {
|
||||
@ -49,7 +59,6 @@
|
||||
_fontLookupCache = [[NSMutableArray alloc] init];
|
||||
_fontTraitCache = [[NSMutableDictionary alloc] init];
|
||||
|
||||
_lineSpace = 4;
|
||||
self.font = font;
|
||||
|
||||
return self;
|
||||
@ -79,11 +88,7 @@
|
||||
CGContextSaveGState(context);
|
||||
|
||||
if (attrs.fontTrait & FontTraitUnderline) {
|
||||
CGRect rect = {
|
||||
{positions[0].x, positions[0].y - 1},
|
||||
{positions[0].x + positions[positionsCount - 1].x + _cellSize.width, 1}
|
||||
};
|
||||
[self drawUnderline:rect color:attrs.special context:context];
|
||||
[self drawUnderline:positions count:positionsCount color:attrs.special context:context];
|
||||
}
|
||||
|
||||
[self drawString:string positions:positions
|
||||
@ -93,8 +98,16 @@
|
||||
CGContextRestoreGState(context);
|
||||
}
|
||||
|
||||
- (void)drawUnderline:(CGRect)rect color:(unsigned int)color context:(CGContextRef _Nonnull)context {
|
||||
- (void)drawUnderline:(const CGPoint *_Nonnull)positions
|
||||
count:(NSInteger)count
|
||||
color:(unsigned int)color
|
||||
context:(CGContextRef _Nonnull)context
|
||||
{
|
||||
CGContextSetRGBFillColor(context, RED(color), GREEN(color), BLUE(color), ALPHA(color));
|
||||
CGRect rect = {
|
||||
{positions[0].x, positions[0].y + _underlinePosition},
|
||||
{positions[0].x + positions[count - 1].x + _cellSize.width, _underlineThickness}
|
||||
};
|
||||
CGContextFillRect(context, rect);
|
||||
}
|
||||
|
||||
@ -115,7 +128,7 @@
|
||||
unichars = unibuffer;
|
||||
}
|
||||
|
||||
CGGlyph *glyphs = malloc(unilength * sizeof(UniChar));
|
||||
CGGlyph *glyphs = malloc(unilength * sizeof(CGGlyph));
|
||||
CTFontRef fontWithTraits = [self fontWithTrait:fontTrait];
|
||||
|
||||
CGContextSetRGBFillColor(context, RED(foreground), GREEN(foreground), BLUE(foreground), 1.0);
|
||||
|
Loading…
Reference in New Issue
Block a user