Do padding in canvas instead of CSS

box-drawing
cpsdqs 7 years ago
parent 57a295b544
commit 4c1da9aaac
Signed by untrusted user: cpsdqs
GPG Key ID: 3F59586BB7448DD1
  1. 25
      js/term/screen.js
  2. 62
      js/term/screen_renderer.js
  3. 1
      sass/pages/_term.scss

@ -55,6 +55,7 @@ module.exports = class TermScreen extends EventEmitter {
devicePixelRatio: 1,
fontFamily: '"DejaVu Sans Mono", "Liberation Mono", "Inconsolata", "Menlo", monospace',
fontSize: 20,
padding: 6,
gridScaleX: 1.0,
gridScaleY: 1.2,
fitIntoWidth: 0,
@ -67,11 +68,15 @@ module.exports = class TermScreen extends EventEmitter {
// scaling caused by fitIntoWidth/fitIntoHeight
this._windowScale = 1
// actual padding, as it may be disabled by fullscreen mode etc.
this._padding = 0
// properties of this.window that require updating size and redrawing
this.windowState = {
width: 0,
height: 0,
devicePixelRatio: 0,
padding: 0,
gridScaleX: 0,
gridScaleY: 0,
fontFamily: '',
@ -313,8 +318,8 @@ module.exports = class TermScreen extends EventEmitter {
let cellSize = this.getCellSize()
return [
Math.floor((x + (rounded ? cellSize.width / 2 : 0)) / cellSize.width),
Math.floor(y / cellSize.height)
Math.floor((x - this._padding + (rounded ? cellSize.width / 2 : 0)) / cellSize.width),
Math.floor((y - this._padding) / cellSize.height)
]
}
@ -328,7 +333,7 @@ module.exports = class TermScreen extends EventEmitter {
gridToScreen (x, y, withScale = false) {
let cellSize = this.getCellSize()
return [x * cellSize.width, y * cellSize.height].map(v => withScale ? v * this._windowScale : v)
return [x * cellSize.width, y * cellSize.height].map(v => this._padding + (withScale ? v * this._windowScale : v))
}
/**
@ -378,13 +383,14 @@ module.exports = class TermScreen extends EventEmitter {
width,
height,
fitIntoWidth,
fitIntoHeight
fitIntoHeight,
padding
} = this.window
const cellSize = this.getCellSize()
// real height of the canvas element in pixels
let realWidth = width * cellSize.width
let realHeight = height * cellSize.height
let realWidth = width * cellSize.width + 2 * padding
let realHeight = height * cellSize.height + 2 * padding
if (fitIntoWidth && fitIntoHeight) {
let terminalAspect = realWidth / realHeight
@ -409,13 +415,16 @@ module.exports = class TermScreen extends EventEmitter {
// store new window scale
this._windowScale = realWidth / (width * cellSize.width)
// and padding
// TODO: disable in fullscreen mode
this._padding = padding
// the DPR must be rounded to a very nice value to prevent gaps between cells
let devicePixelRatio = this._window.devicePixelRatio = Math.round(this._windowScale * (window.devicePixelRatio || 1) * 2) / 2
this.canvas.width = width * devicePixelRatio * cellSize.width
this.canvas.width = (width * cellSize.width + 2 * padding) * devicePixelRatio
this.canvas.style.width = `${realWidth}px`
this.canvas.height = height * devicePixelRatio * cellSize.height
this.canvas.height = (height * cellSize.height + 2 * padding) * devicePixelRatio
this.canvas.style.height = `${realHeight}px`
// the screen has been cleared (by changing canvas width)

@ -159,9 +159,26 @@ module.exports = class ScreenRenderer {
*/
drawBackground ({ x, y, cellWidth, cellHeight, bg }) {
const ctx = this.ctx
const { width, height } = this.screen.window
ctx.fillStyle = this.getColor(bg)
ctx.clearRect(x * cellWidth, y * cellHeight, cellWidth, cellHeight)
ctx.fillRect(x * cellWidth, y * cellHeight, cellWidth, cellHeight)
let screenX = x * cellWidth + this.screen._padding
let screenY = y * cellHeight + this.screen._padding
let isBorderCell = x === 0 || y === 0 || x === width - 1 || y === height - 1
if (isBorderCell) {
let left = screenX
let top = screenY
let right = screenX + cellWidth
let bottom = screenY + cellHeight
if (x === 0) left -= this.screen._padding
else if (x === width - 1) right += this.screen._padding
if (y === 0) top -= this.screen._padding
else if (y === height - 1) bottom += this.screen._padding
ctx.clearRect(left, top, right - left, bottom - top)
ctx.fillRect(left, top, right - left, bottom - top)
} else {
ctx.clearRect(screenX, screenY, cellWidth, cellHeight)
ctx.fillRect(screenX, screenY, cellWidth, cellHeight)
}
}
/**
@ -194,12 +211,15 @@ module.exports = class ScreenRenderer {
ctx.fillStyle = this.getColor(fg)
let screenX = x * cellWidth + this.screen._padding
let screenY = y * cellHeight + this.screen._padding
let codePoint = text.codePointAt(0)
if (codePoint >= 0x2580 && codePoint <= 0x259F) {
// block elements
ctx.beginPath()
const left = x * cellWidth
const top = y * cellHeight
const left = screenX
const top = screenY
const cw = cellWidth
const ch = cellHeight
const c2w = cellWidth / 2
@ -251,16 +271,16 @@ module.exports = class ScreenRenderer {
for (let dx = 0; dx < cw; dx += dotSpacingX) {
// prevent overflow
let dotSizeY = Math.min(dotSize, ch - dy)
ctx.rect(x * cw + (alignRight ? cw - dx - dotSize : dx), y * ch + dy, dotSize, dotSizeY)
ctx.rect(left + (alignRight ? cw - dx - dotSize : dx), top + dy, dotSize, dotSizeY)
}
alignRight = !alignRight
}
} else if (codePoint === 0x2594) {
// upper one eighth block >▔<
ctx.rect(x * cw, y * ch, cw, ch / 8)
ctx.rect(left, top, cw, ch / 8)
} else if (codePoint === 0x2595) {
// right one eighth block >▕<
ctx.rect((x + 7 / 8) * cw, y * ch, cw / 8, ch)
ctx.rect(left + (7 / 8) * cw, top, cw / 8, ch)
} else if (codePoint === 0x2596) {
// left bottom quadrant >▖<
ctx.rect(left, top + c2h, c2w, c2h)
@ -302,7 +322,7 @@ module.exports = class ScreenRenderer {
ctx.fill()
} else {
// Draw other characters using the text renderer
ctx.fillText(text, (x + 0.5) * cellWidth, (y + 0.5) * cellHeight)
ctx.fillText(text, screenX + 0.5 * cellWidth, screenY + 0.5 * cellHeight)
}
// -- line drawing - a reference for a possible future rect/line implementation ---
@ -324,21 +344,21 @@ module.exports = class ScreenRenderer {
ctx.beginPath()
if (underline) {
let lineY = Math.round(y * cellHeight + charSize.height) + 0.5
ctx.moveTo(x * cellWidth, lineY)
ctx.lineTo((x + 1) * cellWidth, lineY)
let lineY = Math.round(screenY + charSize.height) + 0.5
ctx.moveTo(screenX, lineY)
ctx.lineTo(screenX + cellWidth, lineY)
}
if (strike) {
let lineY = Math.round((y + 0.5) * cellHeight) + 0.5
ctx.moveTo(x * cellWidth, lineY)
ctx.lineTo((x + 1) * cellWidth, lineY)
let lineY = Math.round(screenY + 0.5 * cellHeight) + 0.5
ctx.moveTo(screenX, lineY)
ctx.lineTo(screenX + cellWidth, lineY)
}
if (overline) {
let lineY = Math.round(y * cellHeight) + 0.5
ctx.moveTo(x * cellWidth, lineY)
ctx.lineTo((x + 1) * cellWidth, lineY)
let lineY = Math.round(screenY) + 0.5
ctx.moveTo(screenX, lineY)
ctx.lineTo(screenX + cellWidth, lineY)
}
ctx.stroke()
@ -570,17 +590,19 @@ module.exports = class ScreenRenderer {
if (isCursor && !inSelection) {
ctx.save()
ctx.beginPath()
let screenX = x * cellWidth + this.screen._padding
let screenY = y * cellHeight + this.screen._padding
if (this.screen.cursor.style === 'block') {
// block
ctx.rect(x * cellWidth, y * cellHeight, cellWidth, cellHeight)
ctx.rect(screenX, screenY, cellWidth, cellHeight)
} else if (this.screen.cursor.style === 'bar') {
// vertical bar
let barWidth = 2
ctx.rect(x * cellWidth, y * cellHeight, barWidth, cellHeight)
ctx.rect(screenX, screenY, barWidth, cellHeight)
} else if (this.screen.cursor.style === 'line') {
// underline
let lineHeight = 2
ctx.rect(x * cellWidth, y * cellHeight + charSize.height, cellWidth, lineHeight)
ctx.rect(screenX, screenY + charSize.height, cellWidth, lineHeight)
}
ctx.clip()

@ -18,7 +18,6 @@ body.term {
#screen {
white-space: nowrap;
background: #111213;
padding: 6px;
display: inline-block;
border: 2px solid #3983CD;
position: relative;

Loading…
Cancel
Save