Skip to content

Commit

Permalink
GH-666 Try out CGLayer (again)
Browse files Browse the repository at this point in the history
  • Loading branch information
qvacua committed Sep 2, 2018
1 parent d531835 commit c0433ac
Show file tree
Hide file tree
Showing 9 changed files with 404 additions and 116 deletions.
4 changes: 4 additions & 0 deletions NvimView/NvimView.xcodeproj/project.pbxproj
Expand Up @@ -20,6 +20,7 @@
1929B738A3677586230704F7 /* MessagePackCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9290D503536FFDA9C49 /* MessagePackCommons.swift */; };
1929B74691D92B9F369787E5 /* ColorUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDE2C6003A6EDC02129C /* ColorUtils.swift */; };
1929B7D2EB80FEA7BFBC3D2C /* Typesetter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B47330DAD129520A2273 /* Typesetter.swift */; };
1929B82654E5CA3C9237257C /* NvimView+Buffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF2E69A8BC0E20E5ACAD /* NvimView+Buffer.swift */; };
1929B83EAD32DC419FEC68DB /* CocoaCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0C89838D8402BB80BFC /* CocoaCommons.swift */; };
1929B86897DAEFDBABAB1C14 /* NvimApiExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBD7F88AE4F01E626691 /* NvimApiExtension.swift */; };
1929B9485C40C954CAC586E5 /* OldCellAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BD4C55D5EA933BFFB16B /* OldCellAttributes.swift */; };
Expand Down Expand Up @@ -187,6 +188,7 @@
1929BDC8F32F4A0D2299B5C5 /* NvimView+Debug.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+Debug.swift"; sourceTree = "<group>"; };
1929BDE2C6003A6EDC02129C /* ColorUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorUtils.swift; sourceTree = "<group>"; };
1929BE45756C88F8B43804D2 /* CellAttributes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellAttributes.swift; sourceTree = "<group>"; };
1929BF2E69A8BC0E20E5ACAD /* NvimView+Buffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+Buffer.swift"; sourceTree = "<group>"; };
1929BFCCDE5C7145BE5A7387 /* TypesetterTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypesetterTest.swift; sourceTree = "<group>"; };
4B0A1B112129F49500F1E02F /* NvimViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NvimViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
4B0A1B132129F49500F1E02F /* SwiftCommonsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftCommonsTest.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -378,6 +380,7 @@
1929B4355610D4E5607EAA40 /* Drawing */,
1929B2BA05AC3E1A11D6EBFC /* Commons */,
1929BDC8F32F4A0D2299B5C5 /* NvimView+Debug.swift */,
1929BF2E69A8BC0E20E5ACAD /* NvimView+Buffer.swift */,
);
path = NvimView;
sourceTree = "<group>";
Expand Down Expand Up @@ -655,6 +658,7 @@
1929BAB9A0399206FB7EBC76 /* CellAttributesCollection.swift in Sources */,
1929B3B70C96A78FD63DE737 /* NvimView+Debug.swift in Sources */,
1929B738A3677586230704F7 /* MessagePackCommons.swift in Sources */,
1929B82654E5CA3C9237257C /* NvimView+Buffer.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
51 changes: 51 additions & 0 deletions NvimView/NvimView/NvimView+Buffer.swift
@@ -0,0 +1,51 @@
//
// Created by Tae Won Ha on 02.09.18.
// Copyright (c) 2018 Tae Won Ha. All rights reserved.
//

import Cocoa

extension NvimView {

var bufferLayer: CGLayer? {
if self._bufferLayer == nil && self.lockFocusIfCanDraw(),
let current = NSGraphicsContext.current?.cgContext {

self._bufferLayer = CGLayer(
current, size: self.bounds.size.scaling(self.scaleFactor),
auxiliaryInfo: nil
)
self.unlockFocus()
}

return self._bufferLayer
}

var bufferContext: CGContext? {
if self._bufferContext == nil {
self._bufferContext = self.bufferLayer?.context

self._bufferContext?.scaleBy(x: self.scaleFactor, y: self.scaleFactor)

// When both anti-aliasing and font smoothing is turned on,
// then the "Use LCD font smoothing when available" setting is used
// to render texts, cf. chapter 11 from "Programming with Quartz".
self._bufferContext?.setShouldSmoothFonts(true);
self._bufferContext?.setTextDrawingMode(.fill);
}

return self._bufferContext
}

func resetBuffer() {
self._bufferLayer = nil
self._bufferContext = nil
}

override public func viewDidChangeBackingProperties() {
self.scaleFactor = self.window?.screen?.backingScaleFactor ?? 1
self.scaleMatrix = CGAffineTransform.identity.scaledBy(
x: self.scaleFactor, y: self.scaleFactor
)
}
}
2 changes: 1 addition & 1 deletion NvimView/NvimView/NvimView+Debug.swift
Expand Up @@ -59,7 +59,7 @@ extension NvimView {
}
}

lines.forEach { $0.fill() }
context.fill(lines)
}
}
#endif
75 changes: 15 additions & 60 deletions NvimView/NvimView/NvimView+Draw.swift
Expand Up @@ -14,79 +14,34 @@ extension NvimView {
override public func draw(_ dirtyUnionRect: NSRect) {
guard self.ugrid.hasData else { return }

guard let context = NSGraphicsContext.current?.cgContext else { return }
context.saveGState()
defer { context.restoreGState() }
guard let viewContext = NSGraphicsContext.current?.cgContext else { return }
viewContext.saveGState()
defer { viewContext.restoreGState() }

if (self.inLiveResize || self.currentlyResizing) && !self.usesLiveResize {
self.drawResizeInfo(in: context, with: dirtyUnionRect)
self.drawResizeInfo(in: viewContext, with: dirtyUnionRect)
return
}

if self.isCurrentlyPinching {
self.drawPinchImage(in: context)
self.drawPinchImage(in: viewContext)
return
}

// When both anti-aliasing and font smoothing is turned on,
// then the "Use LCD font smoothing when available" setting is used
// to render texts, cf. chapter 11 from "Programming with Quartz".
context.setShouldSmoothFonts(true);
context.setTextDrawingMode(.fill);

let dirtyRects = self.rectsBeingDrawn()
ColorUtils.colorIgnoringAlpha(
self.cellAttributesCollection.defaultAttributes.background
).set()
dirtyRects.fill()

let attrsRuns = self.runs(intersecting: dirtyRects)
let runs = attrsRuns.parallelMap {
// let runs = attrsRuns.map {
run -> (attrsRun: AttributesRun, fontGlyphRuns: [FontGlyphRun]) in

let font = FontUtils.font(adding: run.attrs.fontTrait, to: self.font)

let fontGlyphRuns = self.typesetter.fontGlyphRunsWithLigatures(
nvimUtf16Cells: run.cells.map { Array($0.string.utf16) },
startColumn: run.cells.startIndex,
offset: CGPoint(
x: self.xOffset, y: run.location.y + self.baselineOffset
),
font: font,
cellWidth: self.cellSize.width
)

return (attrsRun: run, fontGlyphRuns: fontGlyphRuns)
}

let defaultAttrs = self.cellAttributesCollection.defaultAttributes
runs.forEach { (attrsRun, fontGlyphRuns) in
self.runDrawer.draw(
attrsRun,
fontGlyphRuns: fontGlyphRuns,
defaultAttributes: defaultAttrs,
in: context
)
}

// self.drawCursor(context: context)

#if DEBUG
// self.draw(cellGridIn: context)
#endif
}

private func draw(_ run: AttributesRun, in context: CGContext) {
context.saveGState()
defer { context.restoreGState() }

self.runDrawer.draw(
run,
with: self.cellAttributesCollection.defaultAttributes,
xOffset: self.xOffset,
in: context
)
guard let bufferLayer = self.bufferLayer else { return }
self.rectsBeingDrawn().forEach { rect in
viewContext.saveGState()
viewContext.clip(to: rect)
viewContext.setBlendMode(.copy)
viewContext.draw(bufferLayer, in: self.bounds)
viewContext.restoreGState()
}
}

private func cursorRegion() -> Region {
Expand Down Expand Up @@ -184,7 +139,7 @@ extension NvimView {
hints: nil)
}

private func runs(intersecting rects: [CGRect]) -> [AttributesRun] {
func runs(intersecting rects: [CGRect]) -> [AttributesRun] {
return rects
.map { rect in
// Get all Regions that intersects with the given rects.
Expand All @@ -200,7 +155,7 @@ extension NvimView {
.flatMap { $0 }
}

private func runs(
func runs(
forRowRange rowRange: CountableClosedRange<Int>,
columnRange: CountableClosedRange<Int>
) -> [AttributesRun] {
Expand Down
1 change: 1 addition & 0 deletions NvimView/NvimView/NvimView+Resize.swift
Expand Up @@ -11,6 +11,7 @@ extension NvimView {

override public func setFrameSize(_ newSize: NSSize) {
super.setFrameSize(newSize)
self.resetBuffer()

if self.isInitialResize {
self.isInitialResize = false
Expand Down

0 comments on commit c0433ac

Please sign in to comment.