Merge branch 'double-lines' into work

pull/2/head
Ondřej Hruška 7 years ago
commit 68a467c33e
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 15
      js/term/screen.js
  2. 5
      js/term/screen_layout.js
  3. 30
      js/term/screen_parser.js
  4. 62
      js/term/screen_renderer.js

@ -90,6 +90,14 @@ module.exports = class TermScreen extends EventEmitter {
this.screenFG = [] this.screenFG = []
this.screenBG = [] this.screenBG = []
this.screenAttrs = [] this.screenAttrs = []
this.screenLines = []
// For testing TODO remove
// this.screenLines[0] = 0b001
// this.screenLines[1] = 0b010
// this.screenLines[2] = 0b100
// this.screenLines[3] = 0b011
// this.screenLines[4] = 0b101
let selecting = false let selecting = false
@ -266,6 +274,7 @@ module.exports = class TermScreen extends EventEmitter {
this.screen.screenFG = new Array(width * height).fill(0) this.screen.screenFG = new Array(width * height).fill(0)
this.screen.screenBG = new Array(width * height).fill(0) this.screen.screenBG = new Array(width * height).fill(0)
this.screen.screenAttrs = new Array(width * height).fill(0) this.screen.screenAttrs = new Array(width * height).fill(0)
this.screen.screenLines = new Array(height).fill(0)
} }
updateLayout () { updateLayout () {
@ -288,6 +297,7 @@ module.exports = class TermScreen extends EventEmitter {
screenBG: this.screenBG, screenBG: this.screenBG,
screenSelection: selection, screenSelection: selection,
screenAttrs: this.screenAttrs, screenAttrs: this.screenAttrs,
screenLines: this.screenLines,
cursor: this.cursor, cursor: this.cursor,
statusScreen: this.window.statusScreen, statusScreen: this.window.statusScreen,
reverseVideo: this.reverseVideo, reverseVideo: this.reverseVideo,
@ -490,6 +500,11 @@ module.exports = class TermScreen extends EventEmitter {
this.emit('opts-update') this.emit('opts-update')
break break
case 'double-lines':
this.screenLines = update.lines
this.renderScreen('double-lines')
break
case 'static-opts': case 'static-opts':
this.layout.window.fontFamily = update.fontStack || null this.layout.window.fontFamily = update.fontStack || null
this.layout.window.fontSize = update.fontSize this.layout.window.fontSize = update.fontSize

@ -135,8 +135,9 @@ module.exports = class ScreenLayout extends EventEmitter {
x = x / this._windowScale - this._padding x = x / this._windowScale - this._padding
y = y / this._windowScale - this._padding y = y / this._windowScale - this._padding
x = Math.floor((x + (rounded ? cellSize.width / 2 : 0)) / cellSize.width)
y = Math.floor(y / cellSize.height) y = Math.floor(y / cellSize.height)
if (this.renderer.drawnScreenLines[y]) x /= 2 // double size
x = Math.floor((x + (rounded ? cellSize.width / 2 : 0)) / cellSize.width)
x = Math.max(0, Math.min(this.window.width - 1, x)) x = Math.max(0, Math.min(this.window.width - 1, x))
y = Math.max(0, Math.min(this.window.height - 1, y)) y = Math.max(0, Math.min(this.window.height - 1, y))
@ -153,6 +154,8 @@ module.exports = class ScreenLayout extends EventEmitter {
gridToScreen (x, y, withScale = false) { gridToScreen (x, y, withScale = false) {
let cellSize = this.getCellSize() let cellSize = this.getCellSize()
if (this.renderer.drawnScreenLines[y]) x *= 2 // double size
return [x * cellSize.width, y * cellSize.height].map(v => this._padding + (withScale ? v * this._windowScale : v)) return [x * cellSize.width, y * cellSize.height].map(v => this._padding + (withScale ? v * this._windowScale : v))
} }

@ -27,15 +27,17 @@ function du (str) {
} }
/* eslint-disable no-multi-spaces */ /* eslint-disable no-multi-spaces */
const TOPIC_SCREEN_OPTS = 'O' // mnemonic
const TOPIC_STATIC_OPTS = 'P' const TOPIC_SCREEN_OPTS = 'O' // O-ptions
const TOPIC_CONTENT = 'S' const TOPIC_STATIC_OPTS = 'P' // P-arams
const TOPIC_TITLE = 'T' const TOPIC_CONTENT = 'S' // S-creen
const TOPIC_BUTTONS = 'B' const TOPIC_TITLE = 'T' // T-itle
const TOPIC_CURSOR = 'C' const TOPIC_BUTTONS = 'B' // B-uttons
const TOPIC_INTERNAL = 'D' const TOPIC_CURSOR = 'C' // C-ursor
const TOPIC_BELL = '!' const TOPIC_INTERNAL = 'D' // D-ebug
const TOPIC_BACKDROP = 'W' const TOPIC_BELL = '!' // !!!
const TOPIC_BACKDROP = 'W' // W-allpaper
const TOPIC_DOUBLE_LINES = 'H' // H-uge
const OPT_CURSOR_VISIBLE = (1 << 0) const OPT_CURSOR_VISIBLE = (1 << 0)
const OPT_DEBUGBAR = (1 << 1) const OPT_DEBUGBAR = (1 << 1)
@ -188,6 +190,16 @@ module.exports = class ScreenParser {
fontSize fontSize
}) })
} else if (topic === TOPIC_DOUBLE_LINES) {
let lines = []
const count = du(strArray[ci++])
for (let i = 0; i < count; i++) {
// format: INDEX<<3 | (dbl-h-bot : dbl-h-top : dbl-w)
let n = du(strArray[ci++])
lines[n >> 3] = n & 0b111
}
updates.push({ topic: 'double-lines', lines: lines })
} else if (topic === TOPIC_TITLE) { } else if (topic === TOPIC_TITLE) {
updates.push({ topic: 'title', title: collectOneTerminatedString() }) updates.push({ topic: 'title', title: collectOneTerminatedString() })

@ -60,6 +60,7 @@ module.exports = class CanvasRenderer extends EventEmitter {
this.screenBG = [] this.screenBG = []
this.screenAttrs = [] this.screenAttrs = []
this.screenSelection = [] this.screenSelection = []
this.screenLines = []
this.cursor = {} this.cursor = {}
this.reverseVideo = false this.reverseVideo = false
this.hasBlinkingCells = false this.hasBlinkingCells = false
@ -96,6 +97,7 @@ module.exports = class CanvasRenderer extends EventEmitter {
this.drawnScreenFG = [] this.drawnScreenFG = []
this.drawnScreenBG = [] this.drawnScreenBG = []
this.drawnScreenAttrs = [] this.drawnScreenAttrs = []
this.drawnScreenLines = []
this.drawnCursor = [-1, -1, '', false] this.drawnCursor = [-1, -1, '', false]
} }
@ -209,6 +211,9 @@ module.exports = class CanvasRenderer extends EventEmitter {
drawBackground ({ x, y, cellWidth, cellHeight, bg, isDefaultBG }) { drawBackground ({ x, y, cellWidth, cellHeight, bg, isDefaultBG }) {
const { ctx, width, height, padding } = this const { ctx, width, height, padding } = this
// is a double-width/double-height line
if (this.screenLines[y] & 0b001) cellWidth *= 2
ctx.fillStyle = this.getColor(bg) ctx.fillStyle = this.getColor(bg)
let screenX = x * cellWidth + padding let screenX = x * cellWidth + padding
let screenY = y * cellHeight + padding let screenY = y * cellHeight + padding
@ -276,6 +281,39 @@ module.exports = class CanvasRenderer extends EventEmitter {
let screenX = x * cellWidth + padding let screenX = x * cellWidth + padding
let screenY = y * cellHeight + padding let screenY = y * cellHeight + padding
const dblWidth = this.screenLines[y] & 0b001
const dblHeightTop = this.screenLines[y] & 0b010
const dblHeightBot = this.screenLines[y] & 0b100
if (this.screenLines[y]) {
// is a double-width/double-height line
if (dblWidth) cellWidth *= 2
ctx.save()
ctx.translate(padding, screenY + 0.5 * cellHeight)
if (dblWidth) ctx.scale(2, 1)
if (dblHeightTop) {
// top half
ctx.scale(1, 2)
ctx.translate(0, cellHeight / 4)
} else if (dblHeightBot) {
// bottom half
ctx.scale(1, 2)
ctx.translate(0, -cellHeight / 4)
}
ctx.translate(-padding, -screenY - 0.5 * cellHeight)
if (dblWidth) ctx.translate(-cellWidth / 4, 0)
if (dblHeightBot || dblHeightTop) {
// characters overflow -- needs clipping
// TODO: clipping is really expensive
ctx.beginPath()
if (dblHeightTop) ctx.rect(screenX, screenY, cellWidth, cellHeight / 2)
else ctx.rect(screenX, screenY + cellHeight / 2, cellWidth, cellHeight / 2)
ctx.clip()
}
}
let codePoint = text.codePointAt(0) let codePoint = text.codePointAt(0)
if (codePoint >= 0x2580 && codePoint <= 0x259F) { if (codePoint >= 0x2580 && codePoint <= 0x259F) {
// block elements // block elements
@ -450,6 +488,8 @@ module.exports = class CanvasRenderer extends EventEmitter {
ctx.stroke() ctx.stroke()
} }
if (this.screenLines[y]) ctx.restore()
ctx.globalAlpha = 1 ctx.globalAlpha = 1
} }
@ -558,6 +598,7 @@ module.exports = class CanvasRenderer extends EventEmitter {
fg !== this.drawnScreenFG[cell] || // foreground updated, and this cell has text fg !== this.drawnScreenFG[cell] || // foreground updated, and this cell has text
bg !== this.drawnScreenBG[cell] || // background updated bg !== this.drawnScreenBG[cell] || // background updated
attrs !== this.drawnScreenAttrs[cell] || // attributes updated attrs !== this.drawnScreenAttrs[cell] || // attributes updated
this.screenLines[y] !== this.drawnScreenLines[y] || // line updated
// TODO: fix artifacts or keep this hack: // TODO: fix artifacts or keep this hack:
isCursor || wasCursor || // cursor blink/position updated isCursor || wasCursor || // cursor blink/position updated
(isCursor && this.cursor.style !== this.drawnCursor[2]) || // cursor style updated (isCursor && this.cursor.style !== this.drawnCursor[2]) || // cursor style updated
@ -570,6 +611,9 @@ module.exports = class CanvasRenderer extends EventEmitter {
updateMap.set(cell, didUpdate) updateMap.set(cell, didUpdate)
} }
// set drawn screen lines
this.drawnScreenLines = this.screenLines.slice()
let debugFilledUpdates = [] let debugFilledUpdates = []
if (this.graphics >= 1) { if (this.graphics >= 1) {
@ -613,7 +657,10 @@ module.exports = class CanvasRenderer extends EventEmitter {
// update this cell if: // 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 (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 // - the adjacent cell updated and this cell or the adjacent cell is wide
if (updateMap.get(adjacentCell) && (this.graphics < 2 || isWideCell || isTextWide(this.screen[adjacentCell]))) { // - this or the adjacent cell is not double-sized
if (updateMap.get(adjacentCell) &&
(this.graphics < 2 || isWideCell || isTextWide(this.screen[adjacentCell])) &&
(!this.screenLines[Math.floor(cell / this.width)] && !this.screenLines[Math.floor(adjacentCell / this.width)])) {
adjacentDidUpdate = true adjacentDidUpdate = true
if (this.getAdjacentCells(cell, 1).includes(adjacentCell)) { if (this.getAdjacentCells(cell, 1).includes(adjacentCell)) {
@ -680,8 +727,6 @@ module.exports = class CanvasRenderer extends EventEmitter {
i++ i++
} }
console.log(regions)
ctx.save() ctx.save()
ctx.beginPath() ctx.beginPath()
for (let region of regions) { for (let region of regions) {
@ -763,17 +808,22 @@ module.exports = class CanvasRenderer extends EventEmitter {
let cursorX = x let cursorX = x
let cursorY = y let cursorY = y
let cursorWidth = cellWidth // JS doesn't allow same-name assignment
if (this.cursor.hanging) { if (this.cursor.hanging) {
// draw hanging cursor in the margin // draw hanging cursor in the margin
cursorX += 1 cursorX += 1
} }
let screenX = cursorX * cellWidth + this.padding // double-width lines
if (this.screenLines[cursorY] & 0b001) cursorWidth *= 2
let screenX = cursorX * cursorWidth + this.padding
let screenY = cursorY * cellHeight + this.padding let screenY = cursorY * cellHeight + this.padding
if (this.cursor.style === 'block') { if (this.cursor.style === 'block') {
// block // block
ctx.rect(screenX, screenY, cellWidth, cellHeight) ctx.rect(screenX, screenY, cursorWidth, cellHeight)
} else if (this.cursor.style === 'bar') { } else if (this.cursor.style === 'bar') {
// vertical bar // vertical bar
let barWidth = 2 let barWidth = 2
@ -781,7 +831,7 @@ module.exports = class CanvasRenderer extends EventEmitter {
} else if (this.cursor.style === 'line') { } else if (this.cursor.style === 'line') {
// underline // underline
let lineHeight = 2 let lineHeight = 2
ctx.rect(screenX, screenY + charSize.height, cellWidth, lineHeight) ctx.rect(screenX, screenY + charSize.height, cursorWidth, lineHeight)
} }
ctx.clip() ctx.clip()

Loading…
Cancel
Save