1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-10-27 10:23:12 +03:00

Draw bold/italic/underline and correct color

This commit is contained in:
Tae Won Ha 2016-06-18 11:43:37 +02:00
parent 8e9c532b40
commit c95d2c3201
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
10 changed files with 273 additions and 109 deletions

View File

@ -41,15 +41,15 @@ typedef struct {
// FIXME: dunno whether we need this: copied from tui.c // FIXME: dunno whether we need this: copied from tui.c
bool cont_received; bool cont_received;
SignalWatcher cont_handle; SignalWatcher cont_handle;
} OsxXpcUiData; } XpcUiData;
static void sigcont_cb(SignalWatcher *watcher __unused, int signum __unused, void *data) { static void sigcont_cb(SignalWatcher *watcher __unused, int signum __unused, void *data) {
((OsxXpcUiData *) data)->cont_received = true; ((XpcUiData *) data)->cont_received = true;
} }
static void osx_xpc_ui_scheduler(Event event, void *d) { static void osx_xpc_ui_scheduler(Event event, void *d) {
UI *ui = d; UI *ui = d;
OsxXpcUiData *data = ui->data; XpcUiData *data = ui->data;
loop_schedule(data->loop, event); loop_schedule(data->loop, event);
} }
@ -57,7 +57,7 @@ static void osx_xpc_ui_main(UIBridgeData *bridge, UI *ui) {
Loop loop; Loop loop;
loop_init(&loop, NULL); loop_init(&loop, NULL);
OsxXpcUiData *data = xcalloc(1, sizeof(OsxXpcUiData)); XpcUiData *data = xcalloc(1, sizeof(XpcUiData));
ui->data = data; ui->data = data;
data->bridge = bridge; data->bridge = bridge;
data->loop = &loop; data->loop = &loop;
@ -91,7 +91,7 @@ static void osx_xpc_ui_main(UIBridgeData *bridge, UI *ui) {
// FIXME: dunno whether we need this: copied from tui.c // FIXME: dunno whether we need this: copied from tui.c
static void suspend_event(void **argv) { static void suspend_event(void **argv) {
UI *ui = argv[0]; UI *ui = argv[0];
OsxXpcUiData *data = ui->data; XpcUiData *data = ui->data;
data->cont_received = false; data->cont_received = false;
kill(0, SIGTSTP); kill(0, SIGTSTP);
@ -166,7 +166,30 @@ static void xpc_ui_scroll(UI *ui __unused, int count) {
static void xpc_ui_highlight_set(UI *ui __unused, HlAttrs attrs) { static void xpc_ui_highlight_set(UI *ui __unused, HlAttrs attrs) {
//printf("highlight set\n"); //printf("highlight set\n");
[neo_vim_osx_ui highlightSet:*((HighlightAttributes *)(&attrs))]; FontTrait trait = FontTraitNone;
if (attrs.italic) {
trait |= FontTraitItalic;
}
if (attrs.bold) {
trait |= FontTraitBold;
}
if (attrs.underline) {
trait |= FontTraitUnderline;
}
if (attrs.undercurl) {
trait |= FontTraitUndercurl;
}
CellAttributes cellAttrs;
cellAttrs.fontTrait = trait;
unsigned int fg = attrs.foreground == -1 ? qDefaultForeground : *((unsigned int*)(&attrs.foreground));
unsigned int bg = attrs.background == -1 ? qDefaultBackground : *((unsigned int*)(&attrs.background));
cellAttrs.foreground = attrs.reverse ? bg : fg;
cellAttrs.background = attrs.reverse ? fg : bg;
cellAttrs.special = attrs.special == -1 ? qDefaultSpecial : *((unsigned int*)(&attrs.special));
[neo_vim_osx_ui highlightSet:cellAttrs];
} }
static void xpc_ui_put(UI *ui __unused, uint8_t *str, size_t len) { static void xpc_ui_put(UI *ui __unused, uint8_t *str, size_t len) {
@ -210,7 +233,7 @@ static void xpc_ui_suspend(UI *ui __unused) {
//printf("suspend\n"); //printf("suspend\n");
[neo_vim_osx_ui suspend]; [neo_vim_osx_ui suspend];
OsxXpcUiData *data = ui->data; XpcUiData *data = ui->data;
// FIXME: dunno whether we need this: copied from tui.c // FIXME: dunno whether we need this: copied from tui.c
// kill(0, SIGTSTP) won't stop the UI thread, so we must poll for SIGCONT // kill(0, SIGTSTP) won't stop the UI thread, so we must poll for SIGCONT
// before continuing. This is done in another callback to avoid // before continuing. This is done in another callback to avoid
@ -236,7 +259,7 @@ static void xpc_ui_stop(UI *ui __unused) {
//printf("stop\n"); //printf("stop\n");
[neo_vim_osx_ui stop]; [neo_vim_osx_ui stop];
OsxXpcUiData *data = (OsxXpcUiData *) ui->data; XpcUiData *data = (XpcUiData *) ui->data;
data->stop = true; data->stop = true;
} }

View File

@ -7,10 +7,10 @@ import Cocoa
class ColorUtils { class ColorUtils {
static func colorFromCode(rgb: UInt32) -> NSColor { static func colorFromCodeIgnoringAlpha(rgb: UInt32) -> NSColor {
let red = (CGFloat((rgb >> 16) & 0x000000FF)) / 255.0; let red = (CGFloat((rgb >> 16) & 0xFF)) / 255.0;
let green = (CGFloat((rgb >> 8 ) & 0x000000FF)) / 255.0; let green = (CGFloat((rgb >> 8) & 0xFF)) / 255.0;
let blue = (CGFloat(rgb & 0x000000FF)) / 255.0; let blue = (CGFloat((rgb ) & 0xFF)) / 255.0;
return NSColor(SRGBRed: red, green: green, blue: blue, alpha: 1.0) return NSColor(SRGBRed: red, green: green, blue: blue, alpha: 1.0)
} }

View File

@ -7,7 +7,7 @@ import Foundation
struct Cell: CustomStringConvertible { struct Cell: CustomStringConvertible {
let string: String let string: String
let attrs: HighlightAttributes let attrs: CellAttributes
var description: String { var description: String {
return self.string.characters.count > 0 ? self.string : "*" return self.string.characters.count > 0 ? self.string : "*"
@ -63,23 +63,23 @@ struct Region: CustomStringConvertible {
/// Almost a verbatim copy of ugrid.c of NeoVim /// Almost a verbatim copy of ugrid.c of NeoVim
class Grid: CustomStringConvertible { class Grid: CustomStringConvertible {
private let qEmptyHighlightAttributes = HighlightAttributes( private let qEmptyCellAttributes = CellAttributes(
bold: false, underline: false, undercurl: false, italic: false, fontTrait: .None,
reverse: false, foreground: -1, background: -1, special: -1 foreground: qDefaultForeground, background: qDefaultBackground, special: qDefaultSpecial
) // not static due to https://bugs.swift.org/browse/SR-1739 ) // not static due to https://bugs.swift.org/browse/SR-1739
private(set) var region = Region.zero private(set) var region = Region.zero
private(set) var size = Size.zero private(set) var size = Size.zero
private(set) var position = Position.zero private(set) var position = Position.zero
var foreground: Int32 = -1 var foreground = qDefaultForeground
var background: Int32 = -1 var background = qDefaultBackground
var special: Int32 = -1 var special = qDefaultSpecial
var attrs: HighlightAttributes = HighlightAttributes( var attrs: CellAttributes = CellAttributes(
bold: false, underline: false, undercurl: false, italic: false, fontTrait: .None,
reverse: false, foreground: -1, background: -1, special: -1 foreground: qDefaultForeground, background: qDefaultBackground, special: qDefaultSpecial
) // not using qEmptyHighlightAttributes because not static due to https://bugs.swift.org/browse/SR-1739 ) // not using qEmptyCellAttributes because not static due to https://bugs.swift.org/browse/SR-1739
private(set) var cells: [[Cell]] = [] private(set) var cells: [[Cell]] = []
@ -96,7 +96,7 @@ class Grid: CustomStringConvertible {
self.size = size self.size = size
self.position = Position.zero self.position = Position.zero
let emptyRow = Array(count: size.width, repeatedValue: Cell(string: " ", attrs: qEmptyHighlightAttributes)) let emptyRow = Array(count: size.width, repeatedValue: Cell(string: " ", attrs: qEmptyCellAttributes))
self.cells = Array(count: size.height, repeatedValue: emptyRow) self.cells = Array(count: size.height, repeatedValue: emptyRow)
} }
@ -158,10 +158,8 @@ class Grid: CustomStringConvertible {
return return
} }
let clearedAttrs = HighlightAttributes( let clearedAttrs = CellAttributes(fontTrait: .None,
bold: false, underline: false, undercurl: false, italic: false, foreground: self.foreground, background: self.background, special: self.special)
reverse: false, foreground: self.foreground, background: self.background, special: self.background
)
let clearedCell = Cell(string: " ", attrs: clearedAttrs) let clearedCell = Cell(string: " ", attrs: clearedAttrs)
let clearedRow = Array(count: region.right - region.left + 1, repeatedValue: clearedCell) let clearedRow = Array(count: region.right - region.left + 1, repeatedValue: clearedCell)

View File

@ -6,32 +6,6 @@
import Foundation import Foundation
public class NeoVim { public class NeoVim {
enum UiEvent {
case MoveCursor(position: Position)
case Put(string: String)
case Resize(size: Size)
case SetHighlightAttributes(attrs: HighlightAttributes)
case Clear
case EolClear
case Flush
}
struct Size {
let width: Int
let height: Int
}
struct Position {
var row: Int
var column: Int
}
enum ColorKind {
case Foreground
case Background
case Special
}
private static let qXpcName = "com.qvacua.nvox.xpc" private static let qXpcName = "com.qvacua.nvox.xpc"

View File

@ -5,11 +5,25 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
// TODO: keep in sync with HlAttrs struct in ui.h typedef NS_ENUM(NSUInteger, FontTrait) {
FontTraitNone = 0,
FontTraitItalic = (1 << 0),
FontTraitBold = (1 << 1),
FontTraitUnderline = (1 << 2),
FontTraitUndercurl = (1 << 3)
};
typedef struct { typedef struct {
bool bold, underline, undercurl, italic, reverse; FontTrait fontTrait;
int foreground, background, special;
} HighlightAttributes; unsigned int foreground;
unsigned int background;
unsigned int special;
} CellAttributes;
#define qDefaultForeground 0xFF000000
#define qDefaultBackground 0xFFFFFFFF
#define qDefaultSpecial 0xFFFF0000
@protocol NeoVimUiBridgeProtocol <NSObject> @protocol NeoVimUiBridgeProtocol <NSObject>
@ -50,7 +64,7 @@ typedef struct {
- (void)setScrollRegionToTop:(int)top bottom:(int)bottom left:(int)left right:(int)right; - (void)setScrollRegionToTop:(int)top bottom:(int)bottom left:(int)left right:(int)right;
- (void)scroll:(int)count; - (void)scroll:(int)count;
- (void)highlightSet:(HighlightAttributes)attrs; - (void)highlightSet:(CellAttributes)attrs;
/** /**
* Draw string at the current cursor which was set by a previous cursorGotoRow:column callback. * Draw string at the current cursor which was set by a previous cursorGotoRow:column callback.

View File

@ -4,7 +4,20 @@
*/ */
import Cocoa import Cocoa
import RxSwift
func == (left: CellAttributes, right: CellAttributes) -> Bool {
if left.foreground != right.foreground { return false }
if left.fontTrait != right.fontTrait { return false }
if left.background != right.background { return false }
if left.special != right.special { return false }
return true
}
func != (left: CellAttributes, right: CellAttributes) -> Bool {
return !(left == right)
}
private struct RowFragment: CustomStringConvertible { private struct RowFragment: CustomStringConvertible {
@ -16,35 +29,52 @@ private struct RowFragment: CustomStringConvertible {
} }
} }
private struct AttributedRowFragment: CustomStringConvertible {
let row: Int
let range: Range<Int>
let attrs: CellAttributes
var description: String {
return "AttributedRowFragment<\(row): \(range)\n\(attrs)>"
}
}
public class NeoVimView: NSView { public class NeoVimView: NSView {
public var delegate: NeoVimViewDelegate? public var delegate: NeoVimViewDelegate?
private let qDispatchMainQueue = dispatch_get_main_queue() private let qDispatchMainQueue = dispatch_get_main_queue()
private let qLineGap = CGFloat(4)
private var font: NSFont {
private var foregroundColor = UInt32(0xFF000000) didSet {
private var backgroundColor = UInt32(0xFFFFFFFF) self.drawer.font = self.font
private var font = NSFont(name: "Menlo", size: 13)! self.cellSize = self.drawer.cellSize
self.lineSpace = self.drawer.lineSpace
// FIXME: resize and redraw
}
}
private let xpc: NeoVimXpc private let xpc: NeoVimXpc
private let drawer = TextDrawer() private let drawer: TextDrawer
private var cellSize: CGSize = CGSizeMake(0, 0) private var cellSize = CGSize.zero
private var lineSpace = CGFloat(0)
private let grid = Grid() private let grid = Grid()
init(frame rect: NSRect = CGRect.zero, xpc: NeoVimXpc) { init(frame rect: NSRect = CGRect.zero, xpc: NeoVimXpc) {
self.xpc = xpc self.xpc = xpc
self.font = NSFont(name: "Menlo", size: 13)!
self.drawer = TextDrawer(font: font)
super.init(frame: rect) super.init(frame: rect)
self.wantsLayer = true self.wantsLayer = true
self.cellSize = self.drawer.cellSize
// hard-code some stuff self.lineSpace = self.drawer.lineSpace
let attrs = [ NSFontAttributeName: self.font ]
let width = ceil(" ".sizeWithAttributes(attrs).width)
let height = ceil(self.font.ascender - self.font.descender + self.font.leading) + qLineGap
self.cellSize = CGSize(width: width, height: height)
} }
override public func keyDown(theEvent: NSEvent) { override public func keyDown(theEvent: NSEvent) {
@ -56,36 +86,32 @@ public class NeoVimView: NSView {
return return
} }
// Swift.print("------- DRAW")
let context = NSGraphicsContext.currentContext()!.CGContext let context = NSGraphicsContext.currentContext()!.CGContext
CGContextSetTextMatrix(context, CGAffineTransformIdentity); CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextSetTextDrawingMode(context, .Fill); CGContextSetTextDrawingMode(context, .Fill);
let dirtyRects = self.rectsBeingDrawn() let dirtyRects = self.rectsBeingDrawn()
self.rowFragmentsIntersecting(rects: dirtyRects).forEach { rowFrag in
self.attributedRowFragmentsIntersecting(rects: dirtyRects).forEach { rowFrag in
let positions = rowFrag.range let positions = rowFrag.range
// filter out the put(0, 0)s (after a wide character) // filter out the put(0, 0)s (after a wide character)
.filter { self.grid.cells[rowFrag.row][$0].string.characters.count > 0 } .filter { self.grid.cells[rowFrag.row][$0].string.characters.count > 0 }
.map { self.positionOnView(rowFrag.row, column: $0) } .map { self.positionOnView(rowFrag.row, column: $0) }
self.drawBackground(positions: positions)
ColorUtils.colorFromCode(self.foregroundColor).set() self.drawBackground(positions: positions, background: rowFrag.attrs.background)
let string = self.grid.cells[rowFrag.row][rowFrag.range].reduce("") { $0 + $1.string } let string = self.grid.cells[rowFrag.row][rowFrag.range].reduce("") { $0 + $1.string }
let glyphPositions = positions.map { CGPoint(x: $0.x, y: $0.y + qLineGap) } let glyphPositions = positions.map { CGPoint(x: $0.x, y: $0.y + self.lineSpace) }
self.drawer.drawString( self.drawer.drawString(string,
string, positions: UnsafeMutablePointer(glyphPositions), positions: UnsafeMutablePointer(glyphPositions), positionsCount: positions.count,
font: self.font, foreground: self.foregroundColor, background: self.backgroundColor, highlightAttrs: rowFrag.attrs,
context: context context: context)
)
} }
// Swift.print("------- DRAW END")
} }
private func drawBackground(positions positions: [CGPoint]) { private func drawBackground(positions positions: [CGPoint], background: UInt32) {
ColorUtils.colorFromCode(self.backgroundColor).set() ColorUtils.colorFromCodeIgnoringAlpha(background).set()
let backgroundRect = CGRect( let backgroundRect = CGRect(
x: positions[0].x, y: positions[0].y, x: positions[0].x, y: positions[0].y,
width: positions.last!.x + self.cellSize.width, height: self.cellSize.height width: positions.last!.x + self.cellSize.width, height: self.cellSize.height
@ -93,6 +119,31 @@ public class NeoVimView: NSView {
backgroundRect.fill() backgroundRect.fill()
} }
private func attributedRowFragmentsIntersecting(rects rects: [CGRect]) -> [AttributedRowFragment] {
return self.rowFragmentsIntersecting(rects: rects)
.map { rowFrag -> [AttributedRowFragment] in
let row = rowFrag.row
let rowCells = self.grid.cells[rowFrag.row]
let range = rowFrag.range
let startIndex = range.startIndex
var result = [
AttributedRowFragment(row: row, range: startIndex...startIndex, attrs: rowCells[startIndex].attrs)
]
range.forEach { idx in
if rowCells[idx].attrs == result.last!.attrs {
let last = result.popLast()!
result.append(AttributedRowFragment(row: row, range: last.range.startIndex...idx, attrs: last.attrs))
} else {
result.append(AttributedRowFragment(row: row, range: idx...idx, attrs: rowCells[idx].attrs))
}
}
return result
}
.flatMap { $0 }
}
private func rowFragmentsIntersecting(rects rects: [CGRect]) -> [RowFragment] { private func rowFragmentsIntersecting(rects rects: [CGRect]) -> [RowFragment] {
return rects return rects
.map { rect -> Region in .map { rect -> Region in
@ -222,7 +273,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
} }
} }
public func highlightSet(attrs: HighlightAttributes) { public func highlightSet(attrs: CellAttributes) {
gui { gui {
// Swift.print("### set highlight") // Swift.print("### set highlight")
self.grid.attrs = attrs self.grid.attrs = attrs
@ -274,7 +325,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
} }
public func setTitle(title: String) { public func setTitle(title: String) {
// Swift.print("### set title: \(title)") self.delegate?.setTitle(title)
} }
public func setIcon(icon: String) { public func setIcon(icon: String) {

View File

@ -7,5 +7,6 @@ import Cocoa
public protocol NeoVimViewDelegate { public protocol NeoVimViewDelegate {
func setTitle(title: String)
func resizeToSize(size: CGSize) func resizeToSize(size: CGSize)
} }

View File

@ -6,13 +6,19 @@
@import Cocoa; @import Cocoa;
@import CoreText; @import CoreText;
#import "NeoVimUiBridgeProtocol.h"
@interface TextDrawer : NSObject @interface TextDrawer : NSObject
- (void)drawString:(NSString *_Nonnull)theString @property (nonatomic, nonnull, retain) NSFont *font;
positions:(CGPoint *_Nonnull)positions @property (nonatomic, readonly) CGFloat lineSpace;
font:(NSFont *_Nonnull)font @property (nonatomic, readonly) CGSize cellSize;
foreground:(unsigned int)foreground
background:(unsigned int)background - (instancetype _Nonnull)initWithFont:(NSFont *_Nonnull)font;
- (void)drawString:(NSString *_Nonnull)string
positions:(CGPoint *_Nonnull)positions positionsCount:(NSInteger)positionsCount
highlightAttrs:(CellAttributes)attrs
context:(CGContextRef _Nonnull)context; context:(CGContextRef _Nonnull)context;
@end @end

View File

@ -8,6 +8,7 @@
#import "TextDrawer.h" #import "TextDrawer.h"
#import "MMCoreTextView.h" #import "MMCoreTextView.h"
#import "NeoVimUiBridgeProtocol.h"
#define ALPHA(color_code) (((color_code >> 24) & 0xff) / 255.0f) #define ALPHA(color_code) (((color_code >> 24) & 0xff) / 255.0f)
#define RED(color_code) (((color_code >> 16) & 0xff) / 255.0f) #define RED(color_code) (((color_code >> 16) & 0xff) / 255.0f)
@ -15,41 +16,95 @@
#define BLUE(color_code) (((color_code ) & 0xff) / 255.0f) #define BLUE(color_code) (((color_code ) & 0xff) / 255.0f)
@implementation TextDrawer { @implementation TextDrawer {
NSMutableArray *fontCache; NSLayoutManager *_layoutManager;
NSFont *_font;
CGFloat _fontDescent;
CGFloat _lineGap;
NSMutableArray *_fontLookupCache;
NSMutableDictionary *_fontTraitCache;
} }
- (instancetype)init { - (void)setFont:(NSFont *)font {
[_font autorelease];
_font = [font retain];
_cellSize = CGSizeMake(
round([@"m" sizeWithAttributes:@{ NSFontAttributeName : _font }].width),
[_layoutManager defaultLineHeightForFont:_font] + _lineSpace
);
// https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html
_lineGap = _cellSize.height - _font.ascender - _font.descender;
_fontDescent = CTFontGetDescent((CTFontRef) _font);
}
- (instancetype)initWithFont:(NSFont *_Nonnull)font {
self = [super init]; self = [super init];
if (self == nil) { if (self == nil) {
return nil; return nil;
} }
fontCache = [[NSMutableArray alloc] initWithCapacity:4]; _layoutManager = [[NSLayoutManager alloc] init];
_fontLookupCache = [[NSMutableArray alloc] init];
_fontTraitCache = [[NSMutableDictionary alloc] init];
_lineSpace = 4;
self.font = font;
return self; return self;
} }
- (void)dealloc { - (void)dealloc {
[fontCache release]; [_layoutManager release];
[_font release];
[_fontLookupCache release];
[_fontTraitCache release];
[super dealloc]; [super dealloc];
} }
/** /**
* We assume that the caller has already called * We assume that the background is drawn elsewhere and that the caller has already called
* *
* CGContextSetTextMatrix(context, CGAffineTransformIdentity); // or some other matrix * CGContextSetTextMatrix(context, CGAffineTransformIdentity); // or some other matrix
* CGContextSetTextDrawingMode(context, kCGTextFill); // or some other mode * CGContextSetTextDrawingMode(context, kCGTextFill); // or some other mode
*/ */
- (void)drawString:(NSString *_Nonnull)theString - (void)drawString:(NSString *_Nonnull)string
positions:(CGPoint *_Nonnull)positions positions:(CGPoint *_Nonnull)positions
font:(NSFont *_Nonnull)theFont positionsCount:(NSInteger)positionsCount
foreground:(unsigned int)foreground highlightAttrs:(CellAttributes)attrs
background:(unsigned int)background
context:(CGContextRef _Nonnull)context context:(CGContextRef _Nonnull)context
{ {
CFStringRef string = (CFStringRef) theString; CGContextSaveGState(context);
CTFontRef font = (CTFontRef) theFont;
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 drawString:string positions:positions
fontTrait:attrs.fontTrait foreground:attrs.foreground
context:context];
CGContextRestoreGState(context);
}
- (void)drawUnderline:(CGRect)rect color:(unsigned int)color context:(CGContextRef _Nonnull)context {
CGContextSetRGBFillColor(context, RED(color), GREEN(color), BLUE(color), ALPHA(color));
CGContextFillRect(context, rect);
}
- (void)drawString:(NSString *_Nonnull)nsstring
positions:(CGPoint *_Nonnull)positions
fontTrait:(FontTrait)fontTrait
foreground:(unsigned int)foreground
context:(CGContextRef _Nonnull)context
{
CFStringRef string = (CFStringRef) nsstring;
UniChar *unibuffer = NULL; UniChar *unibuffer = NULL;
UniCharCount unilength = (UniCharCount) CFStringGetLength(string); UniCharCount unilength = (UniCharCount) CFStringGetLength(string);
@ -61,14 +116,52 @@
} }
CGGlyph *glyphs = malloc(unilength * sizeof(UniChar)); CGGlyph *glyphs = malloc(unilength * sizeof(UniChar));
CTFontRef fontWithTraits = [self fontWithTrait:fontTrait];
recurseDraw(unichars, glyphs, positions, unilength, context, font, fontCache, YES); CGContextSetRGBFillColor(context, RED(foreground), GREEN(foreground), BLUE(foreground), 1.0);
recurseDraw(unichars, glyphs, positions, unilength, context, fontWithTraits, _fontLookupCache, YES);
CFRelease(fontWithTraits);
free(glyphs);
if (unibuffer != NULL) { if (unibuffer != NULL) {
free(unibuffer); free(unibuffer);
} }
}
free(glyphs); /**
* 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;
}
NSFont *cachedFont = _fontTraitCache[@(traits)];
if (cachedFont != nil) {
return CFRetain(cachedFont);
}
if (traits == 0) {
return CFRetain(_font);
}
CTFontRef fontWithTraits = CTFontCreateCopyWithSymbolicTraits((CTFontRef) _font, 0.0, NULL, traits, traits);
if (fontWithTraits == NULL) {
return CFRetain(_font);
}
_fontTraitCache[@(traits)] = (NSFont *) fontWithTraits;
return fontWithTraits;
} }
@end @end

View File

@ -40,4 +40,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NeoVimViewDelegate {
func resizeToSize(size: CGSize) { func resizeToSize(size: CGSize) {
self.neoVim.view.setFrameSize(size) self.neoVim.view.setFrameSize(size)
} }
func setTitle(title: String) {
self.window.title = title
}
} }