271 lines
13 KiB
JavaScript
271 lines
13 KiB
JavaScript
|
"use strict";
|
||
|
var __extends = (this && this.__extends) || (function () {
|
||
|
var extendStatics = function (d, b) {
|
||
|
extendStatics = Object.setPrototypeOf ||
|
||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||
|
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||
|
return extendStatics(d, b);
|
||
|
};
|
||
|
return function (d, b) {
|
||
|
extendStatics(d, b);
|
||
|
function __() { this.constructor = d; }
|
||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||
|
};
|
||
|
})();
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
var GlyphRenderer_1 = require("./GlyphRenderer");
|
||
|
var LinkRenderLayer_1 = require("./renderLayer/LinkRenderLayer");
|
||
|
var CursorRenderLayer_1 = require("./renderLayer/CursorRenderLayer");
|
||
|
var CharAtlasCache_1 = require("./atlas/CharAtlasCache");
|
||
|
var RectangleRenderer_1 = require("./RectangleRenderer");
|
||
|
var Constants_1 = require("browser/renderer/atlas/Constants");
|
||
|
var RenderModel_1 = require("./RenderModel");
|
||
|
var Lifecycle_1 = require("common/Lifecycle");
|
||
|
var Constants_2 = require("common/buffer/Constants");
|
||
|
var ColorUtils_1 = require("./ColorUtils");
|
||
|
var CharDataCompat_1 = require("./CharDataCompat");
|
||
|
exports.INDICIES_PER_CELL = 4;
|
||
|
var WebglRenderer = (function (_super) {
|
||
|
__extends(WebglRenderer, _super);
|
||
|
function WebglRenderer(_terminal, _colors, preserveDrawingBuffer) {
|
||
|
var _this = _super.call(this) || this;
|
||
|
_this._terminal = _terminal;
|
||
|
_this._colors = _colors;
|
||
|
_this._model = new RenderModel_1.RenderModel();
|
||
|
_this._core = _this._terminal._core;
|
||
|
_this._applyBgLuminanceBasedSelection();
|
||
|
_this._renderLayers = [
|
||
|
new LinkRenderLayer_1.LinkRenderLayer(_this._core.screenElement, 2, _this._colors, _this._core),
|
||
|
new CursorRenderLayer_1.CursorRenderLayer(_this._core.screenElement, 3, _this._colors)
|
||
|
];
|
||
|
_this.dimensions = {
|
||
|
scaledCharWidth: 0,
|
||
|
scaledCharHeight: 0,
|
||
|
scaledCellWidth: 0,
|
||
|
scaledCellHeight: 0,
|
||
|
scaledCharLeft: 0,
|
||
|
scaledCharTop: 0,
|
||
|
scaledCanvasWidth: 0,
|
||
|
scaledCanvasHeight: 0,
|
||
|
canvasWidth: 0,
|
||
|
canvasHeight: 0,
|
||
|
actualCellWidth: 0,
|
||
|
actualCellHeight: 0
|
||
|
};
|
||
|
_this._devicePixelRatio = window.devicePixelRatio;
|
||
|
_this._updateDimensions();
|
||
|
_this._canvas = document.createElement('canvas');
|
||
|
var contextAttributes = {
|
||
|
antialias: false,
|
||
|
depth: false,
|
||
|
preserveDrawingBuffer: preserveDrawingBuffer
|
||
|
};
|
||
|
_this._gl = _this._canvas.getContext('webgl2', contextAttributes);
|
||
|
if (!_this._gl) {
|
||
|
throw new Error('WebGL2 not supported');
|
||
|
}
|
||
|
_this._core.screenElement.appendChild(_this._canvas);
|
||
|
_this._rectangleRenderer = new RectangleRenderer_1.RectangleRenderer(_this._terminal, _this._colors, _this._gl, _this.dimensions);
|
||
|
_this._glyphRenderer = new GlyphRenderer_1.GlyphRenderer(_this._terminal, _this._colors, _this._gl, _this.dimensions);
|
||
|
_this.onCharSizeChanged();
|
||
|
return _this;
|
||
|
}
|
||
|
WebglRenderer.prototype.dispose = function () {
|
||
|
this._renderLayers.forEach(function (l) { return l.dispose(); });
|
||
|
this._core.screenElement.removeChild(this._canvas);
|
||
|
_super.prototype.dispose.call(this);
|
||
|
};
|
||
|
WebglRenderer.prototype._applyBgLuminanceBasedSelection = function () {
|
||
|
if (ColorUtils_1.getLuminance(this._colors.background) > 0.5) {
|
||
|
this._colors.selection = { css: '#000', rgba: 255 };
|
||
|
}
|
||
|
else {
|
||
|
this._colors.selection = { css: '#fff', rgba: 4294967295 };
|
||
|
}
|
||
|
};
|
||
|
WebglRenderer.prototype.setColors = function (colors) {
|
||
|
var _this = this;
|
||
|
this._colors = colors;
|
||
|
this._applyBgLuminanceBasedSelection();
|
||
|
this._renderLayers.forEach(function (l) {
|
||
|
l.setColors(_this._terminal, _this._colors);
|
||
|
l.reset(_this._terminal);
|
||
|
});
|
||
|
this._rectangleRenderer.setColors();
|
||
|
this._glyphRenderer.setColors();
|
||
|
this._refreshCharAtlas();
|
||
|
this._model.clear();
|
||
|
};
|
||
|
WebglRenderer.prototype.onDevicePixelRatioChange = function () {
|
||
|
if (this._devicePixelRatio !== window.devicePixelRatio) {
|
||
|
this._devicePixelRatio = window.devicePixelRatio;
|
||
|
this.onResize(this._terminal.cols, this._terminal.rows);
|
||
|
}
|
||
|
};
|
||
|
WebglRenderer.prototype.onResize = function (cols, rows) {
|
||
|
var _this = this;
|
||
|
this._updateDimensions();
|
||
|
this._model.resize(this._terminal.cols, this._terminal.rows);
|
||
|
this._rectangleRenderer.onResize();
|
||
|
this._renderLayers.forEach(function (l) { return l.resize(_this._terminal, _this.dimensions); });
|
||
|
this._canvas.width = this.dimensions.scaledCanvasWidth;
|
||
|
this._canvas.height = this.dimensions.scaledCanvasHeight;
|
||
|
this._canvas.style.width = this.dimensions.canvasWidth + "px";
|
||
|
this._canvas.style.height = this.dimensions.canvasHeight + "px";
|
||
|
this._core.screenElement.style.width = this.dimensions.canvasWidth + "px";
|
||
|
this._core.screenElement.style.height = this.dimensions.canvasHeight + "px";
|
||
|
this._glyphRenderer.setDimensions(this.dimensions);
|
||
|
this._glyphRenderer.onResize();
|
||
|
this._refreshCharAtlas();
|
||
|
this._model.clear();
|
||
|
};
|
||
|
WebglRenderer.prototype.onCharSizeChanged = function () {
|
||
|
this.onResize(this._terminal.cols, this._terminal.rows);
|
||
|
};
|
||
|
WebglRenderer.prototype.onBlur = function () {
|
||
|
var _this = this;
|
||
|
this._renderLayers.forEach(function (l) { return l.onBlur(_this._terminal); });
|
||
|
};
|
||
|
WebglRenderer.prototype.onFocus = function () {
|
||
|
var _this = this;
|
||
|
this._renderLayers.forEach(function (l) { return l.onFocus(_this._terminal); });
|
||
|
};
|
||
|
WebglRenderer.prototype.onSelectionChanged = function (start, end, columnSelectMode) {
|
||
|
var _this = this;
|
||
|
this._renderLayers.forEach(function (l) { return l.onSelectionChanged(_this._terminal, start, end, columnSelectMode); });
|
||
|
this._updateSelectionModel(start, end);
|
||
|
this._rectangleRenderer.updateSelection(this._model.selection, columnSelectMode);
|
||
|
this._glyphRenderer.updateSelection(this._model, columnSelectMode);
|
||
|
this._core.refresh(0, this._terminal.rows - 1);
|
||
|
};
|
||
|
WebglRenderer.prototype.onCursorMove = function () {
|
||
|
var _this = this;
|
||
|
this._renderLayers.forEach(function (l) { return l.onCursorMove(_this._terminal); });
|
||
|
};
|
||
|
WebglRenderer.prototype.onOptionsChanged = function () {
|
||
|
var _this = this;
|
||
|
this._renderLayers.forEach(function (l) { return l.onOptionsChanged(_this._terminal); });
|
||
|
this._updateDimensions();
|
||
|
this._refreshCharAtlas();
|
||
|
};
|
||
|
WebglRenderer.prototype._refreshCharAtlas = function () {
|
||
|
if (this.dimensions.scaledCharWidth <= 0 && this.dimensions.scaledCharHeight <= 0) {
|
||
|
return;
|
||
|
}
|
||
|
var atlas = CharAtlasCache_1.acquireCharAtlas(this._terminal, this._colors, this.dimensions.scaledCharWidth, this.dimensions.scaledCharHeight);
|
||
|
if (!('getRasterizedGlyph' in atlas)) {
|
||
|
throw new Error('The webgl renderer only works with the webgl char atlas');
|
||
|
}
|
||
|
this._charAtlas = atlas;
|
||
|
this._charAtlas.warmUp();
|
||
|
this._glyphRenderer.setAtlas(this._charAtlas);
|
||
|
};
|
||
|
WebglRenderer.prototype.clear = function () {
|
||
|
var _this = this;
|
||
|
this._renderLayers.forEach(function (l) { return l.reset(_this._terminal); });
|
||
|
};
|
||
|
WebglRenderer.prototype.registerCharacterJoiner = function (handler) {
|
||
|
return -1;
|
||
|
};
|
||
|
WebglRenderer.prototype.deregisterCharacterJoiner = function (joinerId) {
|
||
|
return false;
|
||
|
};
|
||
|
WebglRenderer.prototype.renderRows = function (start, end) {
|
||
|
var _this = this;
|
||
|
this._renderLayers.forEach(function (l) { return l.onGridChanged(_this._terminal, start, end); });
|
||
|
if (this._glyphRenderer.beginFrame()) {
|
||
|
this._model.clear();
|
||
|
}
|
||
|
this._updateModel(start, end);
|
||
|
this._rectangleRenderer.render();
|
||
|
this._glyphRenderer.render(this._model, this._model.selection.hasSelection);
|
||
|
};
|
||
|
WebglRenderer.prototype._updateModel = function (start, end) {
|
||
|
var terminal = this._core;
|
||
|
for (var y = start; y <= end; y++) {
|
||
|
var row = y + terminal.buffer.ydisp;
|
||
|
var line = terminal.buffer.lines.get(row);
|
||
|
this._model.lineLengths[y] = 0;
|
||
|
for (var x = 0; x < terminal.cols; x++) {
|
||
|
var charData = line.get(x);
|
||
|
var chars = charData[Constants_2.CHAR_DATA_CHAR_INDEX];
|
||
|
var code = charData[Constants_2.CHAR_DATA_CODE_INDEX];
|
||
|
var attr = CharDataCompat_1.getCompatAttr(line, x);
|
||
|
var i = ((y * terminal.cols) + x) * exports.INDICIES_PER_CELL;
|
||
|
if (code !== Constants_2.NULL_CELL_CODE) {
|
||
|
this._model.lineLengths[y] = x + 1;
|
||
|
}
|
||
|
if (this._model.cells[i] === code && this._model.cells[i + 1] === attr) {
|
||
|
continue;
|
||
|
}
|
||
|
var flags = attr >> 18;
|
||
|
var bg = attr & 0x1ff;
|
||
|
var fg = (attr >> 9) & 0x1ff;
|
||
|
if (flags & 8) {
|
||
|
var temp = bg;
|
||
|
bg = fg;
|
||
|
fg = temp;
|
||
|
if (fg === Constants_2.DEFAULT_COLOR) {
|
||
|
fg = Constants_1.INVERTED_DEFAULT_COLOR;
|
||
|
}
|
||
|
if (bg === Constants_2.DEFAULT_COLOR) {
|
||
|
bg = Constants_1.INVERTED_DEFAULT_COLOR;
|
||
|
}
|
||
|
}
|
||
|
var drawInBrightColor = terminal.options.drawBoldTextInBrightColors && !!(flags & 1) && fg < 8 && fg !== Constants_1.INVERTED_DEFAULT_COLOR;
|
||
|
fg += drawInBrightColor ? 8 : 0;
|
||
|
if (chars.length > 1) {
|
||
|
code = code | RenderModel_1.COMBINED_CHAR_BIT_MASK;
|
||
|
}
|
||
|
this._model.cells[i] = code;
|
||
|
this._model.cells[i + 1] = attr;
|
||
|
this._model.cells[i + 2] = bg;
|
||
|
this._model.cells[i + 3] = fg;
|
||
|
this._glyphRenderer.updateCell(x, y, code, attr, bg, fg, chars);
|
||
|
}
|
||
|
}
|
||
|
this._rectangleRenderer.updateBackgrounds(this._model);
|
||
|
};
|
||
|
WebglRenderer.prototype._updateSelectionModel = function (start, end) {
|
||
|
var terminal = this._terminal;
|
||
|
if (!start || !end || (start[0] === end[0] && start[1] === end[1])) {
|
||
|
this._model.clearSelection();
|
||
|
return;
|
||
|
}
|
||
|
var viewportStartRow = start[1] - terminal.buffer.viewportY;
|
||
|
var viewportEndRow = end[1] - terminal.buffer.viewportY;
|
||
|
var viewportCappedStartRow = Math.max(viewportStartRow, 0);
|
||
|
var viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1);
|
||
|
if (viewportCappedStartRow >= terminal.rows || viewportCappedEndRow < 0) {
|
||
|
this._model.clearSelection();
|
||
|
return;
|
||
|
}
|
||
|
this._model.selection.hasSelection = true;
|
||
|
this._model.selection.viewportStartRow = viewportStartRow;
|
||
|
this._model.selection.viewportEndRow = viewportEndRow;
|
||
|
this._model.selection.viewportCappedStartRow = viewportCappedStartRow;
|
||
|
this._model.selection.viewportCappedEndRow = viewportCappedEndRow;
|
||
|
this._model.selection.startCol = start[0];
|
||
|
this._model.selection.endCol = end[0];
|
||
|
};
|
||
|
WebglRenderer.prototype._updateDimensions = function () {
|
||
|
if (!this._core._charSizeService.width || !this._core._charSizeService.height) {
|
||
|
return;
|
||
|
}
|
||
|
this.dimensions.scaledCharWidth = Math.floor(this._core._charSizeService.width * this._devicePixelRatio);
|
||
|
this.dimensions.scaledCharHeight = Math.ceil(this._core._charSizeService.height * this._devicePixelRatio);
|
||
|
this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.getOption('lineHeight'));
|
||
|
this.dimensions.scaledCharTop = this._terminal.getOption('lineHeight') === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2);
|
||
|
this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.getOption('letterSpacing'));
|
||
|
this.dimensions.scaledCharLeft = Math.floor(this._terminal.getOption('letterSpacing') / 2);
|
||
|
this.dimensions.scaledCanvasHeight = this._terminal.rows * this.dimensions.scaledCellHeight;
|
||
|
this.dimensions.scaledCanvasWidth = this._terminal.cols * this.dimensions.scaledCellWidth;
|
||
|
this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / this._devicePixelRatio);
|
||
|
this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / this._devicePixelRatio);
|
||
|
this.dimensions.actualCellHeight = this.dimensions.scaledCellHeight / this._devicePixelRatio;
|
||
|
this.dimensions.actualCellWidth = this.dimensions.scaledCellWidth / this._devicePixelRatio;
|
||
|
};
|
||
|
return WebglRenderer;
|
||
|
}(Lifecycle_1.Disposable));
|
||
|
exports.WebglRenderer = WebglRenderer;
|
||
|
//# sourceMappingURL=WebglRenderer.js.map
|