From 3bb02a5eed6a4883e772d24d77a628d22a21b749 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Sun, 17 Sep 2017 12:11:56 +0200 Subject: [PATCH] Fix invisible cursor with graphics=1 --- js/debug_screen.js | 39 +++++++++++++++++ js/term_screen.js | 101 ++++++++++++++++++++++++--------------------- 2 files changed, 94 insertions(+), 46 deletions(-) diff --git a/js/debug_screen.js b/js/debug_screen.js index 97e2444..06df806 100644 --- a/js/debug_screen.js +++ b/js/debug_screen.js @@ -25,6 +25,7 @@ window.attachDebugScreen = function (screen) { let startTime, endTime, lastReason let cells = new Map() + let clippedRects = [] let startDrawing @@ -32,6 +33,7 @@ window.attachDebugScreen = function (screen) { drawStart (reason) { lastReason = reason startTime = Date.now() + clippedRects = [] }, drawEnd () { endTime = Date.now() @@ -40,9 +42,34 @@ window.attachDebugScreen = function (screen) { }, setCell (cell, flags) { cells.set(cell, [flags, Date.now()]) + }, + clipRect (...args) { + clippedRects.push(args) } } + let clipPattern + { + let patternCanvas = document.createElement('canvas') + patternCanvas.width = patternCanvas.height = 12 + let pctx = patternCanvas.getContext('2d') + pctx.lineWidth = 1 + pctx.strokeStyle = '#00f' + pctx.beginPath() + pctx.moveTo(0, 0) + pctx.lineTo(0 - 4, 12) + pctx.moveTo(4, 0) + pctx.lineTo(4 - 4, 12) + pctx.moveTo(8, 0) + pctx.lineTo(8 - 4, 12) + pctx.moveTo(12, 0) + pctx.lineTo(12 - 4, 12) + pctx.moveTo(16, 0) + pctx.lineTo(16 - 4, 12) + pctx.stroke() + clipPattern = ctx.createPattern(patternCanvas, 'repeat') + } + let isDrawing = false let drawLoop = function () { @@ -90,6 +117,18 @@ window.attachDebugScreen = function (screen) { } } + if (clippedRects.length) { + ctx.globalAlpha = 0.5 + ctx.beginPath() + + for (let rect of clippedRects) { + ctx.rect(...rect) + } + + ctx.fillStyle = clipPattern + ctx.fill() + } + if (activeCells === 0) { isDrawing = false removeCanvas() diff --git a/js/term_screen.js b/js/term_screen.js index 8b9635e..d75b15f 100644 --- a/js/term_screen.js +++ b/js/term_screen.js @@ -708,7 +708,7 @@ window.TermScreen = class TermScreen extends EventEmitter { let overline = false if (attrs & (1 << 1)) ctx.globalAlpha = 0.5 if (attrs & (1 << 3)) underline = true - if (attrs & (1 << 5)) text = TermScreen.alphaToFraktur(text) + if (attrs & (1 << 5)) text = this.alphaToFraktur(text) if (attrs & (1 << 6)) strike = true if (attrs & (1 << 7)) overline = true @@ -963,12 +963,12 @@ window.TermScreen = class TermScreen extends EventEmitter { bg = -2 } - let didUpdate = text !== this.drawnScreen[cell] || - fg !== this.drawnScreenFG[cell] || - bg !== this.drawnScreenBG[cell] || - attrs !== this.drawnScreenAttrs[cell] || - isCursor !== wasCursor || - (isCursor && this.cursor.style !== this.drawnCursor[2]) + let didUpdate = text !== this.drawnScreen[cell] || // text updated + fg !== this.drawnScreenFG[cell] || // foreground updated, and this cell has text + bg !== this.drawnScreenBG[cell] || // background updated + attrs !== this.drawnScreenAttrs[cell] || // attributes updated + isCursor !== wasCursor || // cursor blink/position updated + (isCursor && this.cursor.style !== this.drawnCursor[2]) // cursor style updated let font = attrs & FONT_MASK if (!fontGroups.has(font)) fontGroups.set(font, []) @@ -985,7 +985,7 @@ window.TermScreen = class TermScreen extends EventEmitter { // decide for each cell if it should be redrawn let updateRedrawMapAt = cell => { - let shouldUpdate = updateMap.get(cell) || redrawMap.get(cell) + let shouldUpdate = updateMap.get(cell) || redrawMap.get(cell) || false // TODO: fonts (necessary?) let text = this.screen[cell] @@ -997,7 +997,10 @@ window.TermScreen = class TermScreen extends EventEmitter { let adjacentDidUpdate = false for (let adjacentCell of this.getAdjacentCells(cell, checkRadius)) { - if (updateMap.get(adjacentCell)) { + // update this cell if: + // - the adjacent cell updated (For now, this'll always be true because characters can be slightly larger than they say they are) + // - the adjacent cell updated and this cell or the adjacent cell is wide + if (updateMap.get(adjacentCell) && (this.window.graphics < 2 || isWideCell || isTextWide(this.screen[adjacentCell]))) { adjacentDidUpdate = true break } @@ -1013,6 +1016,7 @@ window.TermScreen = class TermScreen extends EventEmitter { // mask to redrawing regions only if (this.window.graphics >= 1) { + let debug = this.window.debug && this._debug ctx.save() ctx.beginPath() for (let y = 0; y < height; y++) { @@ -1023,11 +1027,13 @@ window.TermScreen = class TermScreen extends EventEmitter { if (redrawing && regionStart === null) regionStart = x if (!redrawing && regionStart !== null) { ctx.rect(regionStart * cellWidth, y * cellHeight, (x - regionStart) * cellWidth, cellHeight) + if (debug) this._debug.clipRect(regionStart * cellWidth, y * cellHeight, (x - regionStart) * cellWidth, cellHeight) regionStart = null } } if (regionStart !== null) { ctx.rect(regionStart * cellWidth, y * cellHeight, (width - regionStart) * cellWidth, cellHeight) + if (debug) this._debug.clipRect(regionStart * cellWidth, y * cellHeight, (width - regionStart) * cellWidth, cellHeight) } } ctx.clip() @@ -1040,10 +1046,21 @@ window.TermScreen = class TermScreen extends EventEmitter { if (redrawMap.get(cell)) { this.drawCellBackground({ x, y, cellWidth, cellHeight, bg }) + + if (this.window.debug && this._debug) { + // set cell flags + let flags = (+redrawMap.get(cell)) + flags |= (+updateMap.get(cell)) << 1 + flags |= (+isTextWide(text)) << 2 + this._debug.setCell(cell, flags) + } } } } + // reset drawn cursor + this.drawnCursor = [-1, -1, -1] + // pass 2: characters for (let font of fontGroups.keys()) { // set font once because in Firefox, this is a really slow action for some @@ -1068,43 +1085,35 @@ window.TermScreen = class TermScreen extends EventEmitter { if (isCursor) this.drawnCursor = [x, y, this.cursor.style] - if (this.window.debug && this._debug) { - // set cell flags - let flags = 1 // always redrawn - flags |= (+updateMap.get(cell)) << 1 - flags |= (+isTextWide(text)) << 2 - this._debug.setCell(cell, flags) - } - } - - if (isCursor && !inSelection) { - ctx.save() - ctx.beginPath() - if (this.cursor.style === 'block') { - // block - ctx.rect(x * cellWidth, y * cellHeight, cellWidth, cellHeight) - } else if (this.cursor.style === 'bar') { - // vertical bar - let barWidth = 2 - ctx.rect(x * cellWidth, y * cellHeight, barWidth, cellHeight) - } else if (this.cursor.style === 'line') { - // underline - let lineHeight = 2 - ctx.rect(x * cellWidth, y * cellHeight + charSize.height, cellWidth, lineHeight) + if (isCursor && !inSelection) { + ctx.save() + ctx.beginPath() + if (this.cursor.style === 'block') { + // block + ctx.rect(x * cellWidth, y * cellHeight, cellWidth, cellHeight) + } else if (this.cursor.style === 'bar') { + // vertical bar + let barWidth = 2 + ctx.rect(x * cellWidth, y * cellHeight, barWidth, cellHeight) + } else if (this.cursor.style === 'line') { + // underline + let lineHeight = 2 + ctx.rect(x * cellWidth, y * cellHeight + charSize.height, cellWidth, lineHeight) + } + ctx.clip() + + // swap foreground/background + ;[fg, bg] = [bg, fg] + + // HACK: ensure cursor is visible + if (fg === bg) bg = fg === 0 ? 7 : 0 + + this.drawCellBackground({ x, y, cellWidth, cellHeight, bg }) + this.drawCell({ + x, y, charSize, cellWidth, cellHeight, text, fg, attrs + }) + ctx.restore() } - ctx.clip() - - // swap foreground/background - ;[fg, bg] = [bg, fg] - - // HACK: ensure cursor is visible - if (fg === bg) bg = fg === 0 ? 7 : 0 - - this.drawCellBackground({ x, y, cellWidth, cellHeight, bg }) - this.drawCell({ - x, y, charSize, cellWidth, cellHeight, text, fg, attrs - }) - ctx.restore() } } } @@ -1483,7 +1492,7 @@ window.TermScreen = class TermScreen extends EventEmitter { * @param {string} character - the character * @returns {string} the converted character */ - static alphaToFraktur (character) { + alphaToFraktur (character) { if (character >= 'a' && character <= 'z') { character = String.fromCodePoint(0x1d51e - 0x61 + character.charCodeAt(0)) } else if (character >= 'A' && character <= 'Z') {