Skip to content

Commit eefa5d1

Browse files
committed
Better approach at rendering the bottom exposed region of the buffer, and in the
process, I cleaned up some historical baggage and a nice upgrade. The nice upgrade is that I am using the exposed region as intended for the Mac, over time, the code regressed and was redrawing the whole buffer, now it does what it is supposed to do. The parameter "offset" to "drawTerminalContents" was deprecated when I moved to the UIScrollView backing for the iOS terminal, so I have eliminated it. Rather than computing "remains" at the start, we compute at the end, and rather than the float->int->float conversions, we use: bounds.height.truncatingRemainder(dividingBy: cellHeight) Additionally, given that there is a font change redraw issue not addressed here, I am keeping the old clearing code (and I have fixed it now), but I have also implemented the alterantive which should draw a lot less, so as soon as I fix the font change issue, I can remove the code from the caller of "drawTerminalContents".
1 parent 98d1440 commit eefa5d1

File tree

4 files changed

+40
-18
lines changed

4 files changed

+40
-18
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,9 @@ slow-unit-*
33
timeout-*
44
slow-unit-*
55
fuzz-*.log
6+
xcuserdata
7+
crash-*
8+
DerivedData
9+
.deriveddata
10+
.build
11+
.DS_Store

Sources/SwiftTerm/Apple/AppleTerminalView.swift

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -529,30 +529,28 @@ extension TerminalView {
529529

530530

531531
// TODO: this should not render any lines outside the dirtyRect
532-
func drawTerminalContents (dirtyRect: TTRect, context: CGContext, offset: CGFloat, bufferOffset: Int)
532+
func drawTerminalContents (dirtyRect: TTRect, context: CGContext, bufferOffset: Int)
533533
{
534534
let lineDescent = CTFontGetDescent(fontSet.normal)
535535
let lineLeading = CTFontGetLeading(fontSet.normal)
536536
let yOffset = ceil(lineDescent+lineLeading)
537-
537+
538538
func calcLineOffset (forRow: Int) -> CGFloat {
539-
cellDimension.height * CGFloat (forRow-bufferOffset+1) + offset
539+
cellDimension.height * CGFloat (forRow-bufferOffset+1)
540540
}
541541

542542
// draw lines
543-
544543
#if os(iOS)
545544
// On iOS, we are drawing the exposed region
546545
let cellHeight = cellDimension.height
547546
let firstRow = Int (dirtyRect.minY/cellHeight)
548547
let lastRow = Int(dirtyRect.maxY/cellHeight)
549-
let remains = CGFloat (lastRow) * cellHeight
550548
#else
551549
// On Mac, we are drawing the terminal buffer
552550
let cellHeight = cellDimension.height
553-
let remains = trunc (dirtyRect.height/cellHeight) * cellHeight
554-
let firstRow = terminal.buffer.yDisp
555-
let lastRow = terminal.rows + terminal.buffer.yDisp
551+
let boundsMaxY = bounds.maxY
552+
let firstRow = terminal.buffer.yDisp+Int ((boundsMaxY-dirtyRect.maxY)/cellHeight)
553+
let lastRow = terminal.buffer.yDisp+Int((boundsMaxY-dirtyRect.minY)/cellHeight)
556554
#endif
557555

558556
for row in firstRow...lastRow {
@@ -618,7 +616,7 @@ extension TerminalView {
618616
let line = terminal.buffer.lines [row]
619617
let lineInfo = buildAttributedString(row: row, line: line, cols: terminal.cols)
620618
let ctline = CTLineCreateWithAttributedString(lineInfo.attrStr)
621-
619+
622620
var col = 0
623621
for run in CTLineGetGlyphRuns(ctline) as? [CTRun] ?? [] {
624622
let runGlyphsCount = CTRunGetGlyphCount(run)
@@ -663,21 +661,21 @@ extension TerminalView {
663661
origin.y -= missing
664662
}
665663
#endif
666-
664+
667665
if col + runGlyphsCount >= terminal.cols {
668666
size.width += frame.width - size.width
669667
}
670668

671669
let rect = CGRect (origin: origin, size: size)
672-
670+
673671
#if os(macOS)
674672
rect.applying(transform).fill(using: .destinationOver)
675673
#else
676674
context.fill(rect.applying(transform))
677675
#endif
678676
context.restoreGState()
679677
}
680-
678+
681679
nativeForegroundColor.set()
682680

683681
if runAttributes.keys.contains(.foregroundColor) {
@@ -696,6 +694,7 @@ extension TerminalView {
696694

697695
col += runGlyphsCount
698696
}
697+
699698
// Render any sixel content last
700699
if let images = lineInfo.images {
701700
let rowBase = frame.height - (CGFloat(row) * cellDimension.height)
@@ -712,7 +711,6 @@ extension TerminalView {
712711
image.image.draw (in: rect)
713712
}
714713
}
715-
716714
switch renderMode {
717715
case .single:
718716
break
@@ -724,11 +722,28 @@ extension TerminalView {
724722
context.restoreGState()
725723
}
726724
}
727-
let box = CGRect (x: 0, y: 0, width: bounds.width, height: bounds.height-remains)
725+
726+
#if os(macOS)
727+
// Fills gaps at the end with the default terminal background
728+
let box = CGRect (x: 0, y: 0, width: bounds.width, height: bounds.height.truncatingRemainder(dividingBy: cellHeight))
728729
if dirtyRect.intersects(box) {
729730
nativeBackgroundColor.setFill()
730731
context.fill ([box])
731732
}
733+
#elseif false
734+
// Currently the caller on iOS is clearing the entire dirty region due to the ordering of
735+
// font change sizes, but once we fix that, we should remove the clearing of the dirty
736+
// region in the calling code, and enable this code instead.
737+
let lineOffset = calcLineOffset(forRow: lastRow)
738+
let lineOrigin = CGPoint(x: 0, y: frame.height - lineOffset)
739+
740+
let inter = dirtyRect.intersection(CGRect (x: 0, y: lineOrigin.y, width: bounds.width, height: cellHeight))
741+
if !inter.isEmpty {
742+
nativeBackgroundColor.setFill()
743+
context.fill ([inter])
744+
}
745+
#endif
746+
732747
#if os(iOS)
733748
if selection.active {
734749
let start, end: Position
@@ -811,7 +826,6 @@ extension TerminalView {
811826
region = CGRect (x: 0, y: 0, width: frame.width, height: oh + oy)
812827
}
813828
setNeedsDisplay(region)
814-
setNeedsDisplay(bounds)
815829
#else
816830
// TODO iOS: need to update the code above, but will do that when I get some real
817831
// life data being fed into it.

Sources/SwiftTerm/Mac/MacTerminalView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ open class TerminalView: NSView, NSTextInputClient, NSUserInterfaceValidations,
388388
guard let currentContext = getCurrentGraphicsContext() else {
389389
return
390390
}
391-
drawTerminalContents (dirtyRect: dirtyRect, context: currentContext, offset: 0, bufferOffset: terminal.buffer.yDisp)
391+
drawTerminalContents (dirtyRect: dirtyRect, context: currentContext, bufferOffset: terminal.buffer.yDisp)
392392
}
393393

394394
public override func cursorUpdate(with event: NSEvent)

Sources/SwiftTerm/iOS/iOSTerminalView.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -963,14 +963,16 @@ open class TerminalView: UIScrollView, UITextInputTraits, UIKeyInput, UIScrollVi
963963
}
964964

965965
// Without these two lines, on font changes, some junk is being displayed
966+
// Once we test the font change, we could disable these two lines, and
967+
// enable the #if false in drawterminalContents that should be coping with this now
966968
nativeBackgroundColor.set ()
967-
context.clear(dirtyRect)
969+
context.fill ([dirtyRect])
968970

969971
// drawTerminalContents and CoreText expect the AppKit coordinate system
970972
context.scaleBy (x: 1, y: -1)
971973
context.translateBy(x: 0, y: -frame.height)
972974

973-
drawTerminalContents (dirtyRect: dirtyRect, context: context, offset: 0, bufferOffset: 0)
975+
drawTerminalContents (dirtyRect: dirtyRect, context: context, bufferOffset: 0)
974976
}
975977

976978
open override var bounds: CGRect {

0 commit comments

Comments
 (0)