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:
parent
8e9c532b40
commit
c95d2c3201
@ -41,15 +41,15 @@ typedef struct {
|
||||
// FIXME: dunno whether we need this: copied from tui.c
|
||||
bool cont_received;
|
||||
SignalWatcher cont_handle;
|
||||
} OsxXpcUiData;
|
||||
} XpcUiData;
|
||||
|
||||
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) {
|
||||
UI *ui = d;
|
||||
OsxXpcUiData *data = ui->data;
|
||||
XpcUiData *data = ui->data;
|
||||
loop_schedule(data->loop, event);
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ static void osx_xpc_ui_main(UIBridgeData *bridge, UI *ui) {
|
||||
Loop loop;
|
||||
loop_init(&loop, NULL);
|
||||
|
||||
OsxXpcUiData *data = xcalloc(1, sizeof(OsxXpcUiData));
|
||||
XpcUiData *data = xcalloc(1, sizeof(XpcUiData));
|
||||
ui->data = data;
|
||||
data->bridge = bridge;
|
||||
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
|
||||
static void suspend_event(void **argv) {
|
||||
UI *ui = argv[0];
|
||||
OsxXpcUiData *data = ui->data;
|
||||
XpcUiData *data = ui->data;
|
||||
data->cont_received = false;
|
||||
|
||||
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) {
|
||||
//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) {
|
||||
@ -210,7 +233,7 @@ static void xpc_ui_suspend(UI *ui __unused) {
|
||||
//printf("suspend\n");
|
||||
[neo_vim_osx_ui suspend];
|
||||
|
||||
OsxXpcUiData *data = ui->data;
|
||||
XpcUiData *data = ui->data;
|
||||
// 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
|
||||
// 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");
|
||||
[neo_vim_osx_ui stop];
|
||||
|
||||
OsxXpcUiData *data = (OsxXpcUiData *) ui->data;
|
||||
XpcUiData *data = (XpcUiData *) ui->data;
|
||||
data->stop = true;
|
||||
}
|
||||
|
||||
|
@ -7,10 +7,10 @@ import Cocoa
|
||||
|
||||
class ColorUtils {
|
||||
|
||||
static func colorFromCode(rgb: UInt32) -> NSColor {
|
||||
let red = (CGFloat((rgb >> 16) & 0x000000FF)) / 255.0;
|
||||
let green = (CGFloat((rgb >> 8 ) & 0x000000FF)) / 255.0;
|
||||
let blue = (CGFloat(rgb & 0x000000FF)) / 255.0;
|
||||
static func colorFromCodeIgnoringAlpha(rgb: UInt32) -> NSColor {
|
||||
let red = (CGFloat((rgb >> 16) & 0xFF)) / 255.0;
|
||||
let green = (CGFloat((rgb >> 8) & 0xFF)) / 255.0;
|
||||
let blue = (CGFloat((rgb ) & 0xFF)) / 255.0;
|
||||
|
||||
return NSColor(SRGBRed: red, green: green, blue: blue, alpha: 1.0)
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import Foundation
|
||||
|
||||
struct Cell: CustomStringConvertible {
|
||||
let string: String
|
||||
let attrs: HighlightAttributes
|
||||
let attrs: CellAttributes
|
||||
|
||||
var description: 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
|
||||
class Grid: CustomStringConvertible {
|
||||
|
||||
private let qEmptyHighlightAttributes = HighlightAttributes(
|
||||
bold: false, underline: false, undercurl: false, italic: false,
|
||||
reverse: false, foreground: -1, background: -1, special: -1
|
||||
private let qEmptyCellAttributes = CellAttributes(
|
||||
fontTrait: .None,
|
||||
foreground: qDefaultForeground, background: qDefaultBackground, special: qDefaultSpecial
|
||||
) // not static due to https://bugs.swift.org/browse/SR-1739
|
||||
|
||||
private(set) var region = Region.zero
|
||||
private(set) var size = Size.zero
|
||||
private(set) var position = Position.zero
|
||||
|
||||
var foreground: Int32 = -1
|
||||
var background: Int32 = -1
|
||||
var special: Int32 = -1
|
||||
var foreground = qDefaultForeground
|
||||
var background = qDefaultBackground
|
||||
var special = qDefaultSpecial
|
||||
|
||||
var attrs: HighlightAttributes = HighlightAttributes(
|
||||
bold: false, underline: false, undercurl: false, italic: false,
|
||||
reverse: false, foreground: -1, background: -1, special: -1
|
||||
) // not using qEmptyHighlightAttributes because not static due to https://bugs.swift.org/browse/SR-1739
|
||||
var attrs: CellAttributes = CellAttributes(
|
||||
fontTrait: .None,
|
||||
foreground: qDefaultForeground, background: qDefaultBackground, special: qDefaultSpecial
|
||||
) // not using qEmptyCellAttributes because not static due to https://bugs.swift.org/browse/SR-1739
|
||||
|
||||
private(set) var cells: [[Cell]] = []
|
||||
|
||||
@ -96,7 +96,7 @@ class Grid: CustomStringConvertible {
|
||||
self.size = size
|
||||
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)
|
||||
}
|
||||
|
||||
@ -158,10 +158,8 @@ class Grid: CustomStringConvertible {
|
||||
return
|
||||
}
|
||||
|
||||
let clearedAttrs = HighlightAttributes(
|
||||
bold: false, underline: false, undercurl: false, italic: false,
|
||||
reverse: false, foreground: self.foreground, background: self.background, special: self.background
|
||||
)
|
||||
let clearedAttrs = CellAttributes(fontTrait: .None,
|
||||
foreground: self.foreground, background: self.background, special: self.special)
|
||||
|
||||
let clearedCell = Cell(string: " ", attrs: clearedAttrs)
|
||||
let clearedRow = Array(count: region.right - region.left + 1, repeatedValue: clearedCell)
|
||||
|
@ -6,32 +6,6 @@
|
||||
import Foundation
|
||||
|
||||
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"
|
||||
|
||||
|
@ -5,11 +5,25 @@
|
||||
|
||||
#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 {
|
||||
bool bold, underline, undercurl, italic, reverse;
|
||||
int foreground, background, special;
|
||||
} HighlightAttributes;
|
||||
FontTrait fontTrait;
|
||||
|
||||
unsigned int foreground;
|
||||
unsigned int background;
|
||||
unsigned int special;
|
||||
} CellAttributes;
|
||||
|
||||
#define qDefaultForeground 0xFF000000
|
||||
#define qDefaultBackground 0xFFFFFFFF
|
||||
#define qDefaultSpecial 0xFFFF0000
|
||||
|
||||
@protocol NeoVimUiBridgeProtocol <NSObject>
|
||||
|
||||
@ -50,7 +64,7 @@ typedef struct {
|
||||
|
||||
- (void)setScrollRegionToTop:(int)top bottom:(int)bottom left:(int)left right:(int)right;
|
||||
- (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.
|
||||
|
@ -4,7 +4,20 @@
|
||||
*/
|
||||
|
||||
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 {
|
||||
|
||||
@ -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 var delegate: NeoVimViewDelegate?
|
||||
|
||||
private let qDispatchMainQueue = dispatch_get_main_queue()
|
||||
private let qLineGap = CGFloat(4)
|
||||
|
||||
private var foregroundColor = UInt32(0xFF000000)
|
||||
private var backgroundColor = UInt32(0xFFFFFFFF)
|
||||
private var font = NSFont(name: "Menlo", size: 13)!
|
||||
|
||||
private var font: NSFont {
|
||||
didSet {
|
||||
self.drawer.font = self.font
|
||||
self.cellSize = self.drawer.cellSize
|
||||
self.lineSpace = self.drawer.lineSpace
|
||||
|
||||
// FIXME: resize and redraw
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
init(frame rect: NSRect = CGRect.zero, xpc: NeoVimXpc) {
|
||||
self.xpc = xpc
|
||||
|
||||
self.font = NSFont(name: "Menlo", size: 13)!
|
||||
self.drawer = TextDrawer(font: font)
|
||||
|
||||
super.init(frame: rect)
|
||||
|
||||
|
||||
self.wantsLayer = true
|
||||
|
||||
// hard-code some stuff
|
||||
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)
|
||||
self.cellSize = self.drawer.cellSize
|
||||
self.lineSpace = self.drawer.lineSpace
|
||||
}
|
||||
|
||||
override public func keyDown(theEvent: NSEvent) {
|
||||
@ -56,36 +86,32 @@ public class NeoVimView: NSView {
|
||||
return
|
||||
}
|
||||
|
||||
// Swift.print("------- DRAW")
|
||||
|
||||
let context = NSGraphicsContext.currentContext()!.CGContext
|
||||
|
||||
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
|
||||
CGContextSetTextDrawingMode(context, .Fill);
|
||||
|
||||
let dirtyRects = self.rectsBeingDrawn()
|
||||
self.rowFragmentsIntersecting(rects: dirtyRects).forEach { rowFrag in
|
||||
|
||||
self.attributedRowFragmentsIntersecting(rects: dirtyRects).forEach { rowFrag in
|
||||
let positions = rowFrag.range
|
||||
// filter out the put(0, 0)s (after a wide character)
|
||||
.filter { self.grid.cells[rowFrag.row][$0].string.characters.count > 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 glyphPositions = positions.map { CGPoint(x: $0.x, y: $0.y + qLineGap) }
|
||||
self.drawer.drawString(
|
||||
string, positions: UnsafeMutablePointer(glyphPositions),
|
||||
font: self.font, foreground: self.foregroundColor, background: self.backgroundColor,
|
||||
context: context
|
||||
)
|
||||
let glyphPositions = positions.map { CGPoint(x: $0.x, y: $0.y + self.lineSpace) }
|
||||
self.drawer.drawString(string,
|
||||
positions: UnsafeMutablePointer(glyphPositions), positionsCount: positions.count,
|
||||
highlightAttrs: rowFrag.attrs,
|
||||
context: context)
|
||||
}
|
||||
// Swift.print("------- DRAW END")
|
||||
}
|
||||
|
||||
private func drawBackground(positions positions: [CGPoint]) {
|
||||
ColorUtils.colorFromCode(self.backgroundColor).set()
|
||||
private func drawBackground(positions positions: [CGPoint], background: UInt32) {
|
||||
ColorUtils.colorFromCodeIgnoringAlpha(background).set()
|
||||
let backgroundRect = CGRect(
|
||||
x: positions[0].x, y: positions[0].y,
|
||||
width: positions.last!.x + self.cellSize.width, height: self.cellSize.height
|
||||
@ -93,6 +119,31 @@ public class NeoVimView: NSView {
|
||||
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] {
|
||||
return rects
|
||||
.map { rect -> Region in
|
||||
@ -222,7 +273,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
public func highlightSet(attrs: HighlightAttributes) {
|
||||
public func highlightSet(attrs: CellAttributes) {
|
||||
gui {
|
||||
// Swift.print("### set highlight")
|
||||
self.grid.attrs = attrs
|
||||
@ -274,7 +325,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
}
|
||||
|
||||
public func setTitle(title: String) {
|
||||
// Swift.print("### set title: \(title)")
|
||||
self.delegate?.setTitle(title)
|
||||
}
|
||||
|
||||
public func setIcon(icon: String) {
|
||||
|
@ -7,5 +7,6 @@ import Cocoa
|
||||
|
||||
public protocol NeoVimViewDelegate {
|
||||
|
||||
func setTitle(title: String)
|
||||
func resizeToSize(size: CGSize)
|
||||
}
|
||||
|
@ -6,13 +6,19 @@
|
||||
@import Cocoa;
|
||||
@import CoreText;
|
||||
|
||||
#import "NeoVimUiBridgeProtocol.h"
|
||||
|
||||
@interface TextDrawer : NSObject
|
||||
|
||||
- (void)drawString:(NSString *_Nonnull)theString
|
||||
positions:(CGPoint *_Nonnull)positions
|
||||
font:(NSFont *_Nonnull)font
|
||||
foreground:(unsigned int)foreground
|
||||
background:(unsigned int)background
|
||||
@property (nonatomic, nonnull, retain) NSFont *font;
|
||||
@property (nonatomic, readonly) CGFloat lineSpace;
|
||||
@property (nonatomic, readonly) CGSize cellSize;
|
||||
|
||||
- (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;
|
||||
|
||||
@end
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#import "TextDrawer.h"
|
||||
#import "MMCoreTextView.h"
|
||||
#import "NeoVimUiBridgeProtocol.h"
|
||||
|
||||
#define ALPHA(color_code) (((color_code >> 24) & 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)
|
||||
|
||||
@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];
|
||||
if (self == 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;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[fontCache release];
|
||||
[_layoutManager release];
|
||||
[_font release];
|
||||
[_fontLookupCache release];
|
||||
[_fontTraitCache release];
|
||||
|
||||
[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
|
||||
* CGContextSetTextDrawingMode(context, kCGTextFill); // or some other mode
|
||||
*/
|
||||
- (void)drawString:(NSString *_Nonnull)theString
|
||||
- (void)drawString:(NSString *_Nonnull)string
|
||||
positions:(CGPoint *_Nonnull)positions
|
||||
font:(NSFont *_Nonnull)theFont
|
||||
foreground:(unsigned int)foreground
|
||||
background:(unsigned int)background
|
||||
positionsCount:(NSInteger)positionsCount
|
||||
highlightAttrs:(CellAttributes)attrs
|
||||
context:(CGContextRef _Nonnull)context
|
||||
{
|
||||
CFStringRef string = (CFStringRef) theString;
|
||||
CTFontRef font = (CTFontRef) theFont;
|
||||
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 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;
|
||||
UniCharCount unilength = (UniCharCount) CFStringGetLength(string);
|
||||
@ -61,14 +116,52 @@
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
|
@ -40,4 +40,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NeoVimViewDelegate {
|
||||
func resizeToSize(size: CGSize) {
|
||||
self.neoVim.view.setFrameSize(size)
|
||||
}
|
||||
|
||||
func setTitle(title: String) {
|
||||
self.window.title = title
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user