Add fontSize and fontFamily options

This commit is contained in:
Daniel Imms
2017-08-31 22:42:39 -07:00
parent c88824155f
commit 15c73ef94f
14 changed files with 107 additions and 114 deletions
+5
View File
@@ -19,6 +19,11 @@ export class BackgroundRenderLayer extends BaseRenderLayer implements IDataRende
this._state.resize(terminal.cols, terminal.rows);
}
public clear(terminal: ITerminal): void {
this._state.clear();
this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
}
public render(terminal: ITerminal, startRow: number, endRow: number): void {
const scaledCharWidth = Math.ceil(terminal.charMeasure.width) * window.devicePixelRatio;
const scaledCharHeight = Math.ceil(terminal.charMeasure.height) * window.devicePixelRatio;
+11 -8
View File
@@ -39,14 +39,16 @@ export abstract class BaseRenderLayer implements IRenderLayer {
BaseRenderLayer._charAtlas = null;
BaseRenderLayer._charAtlasCharWidth = terminal.charMeasure.width;
BaseRenderLayer._charAtlasCharHeight = terminal.charMeasure.height;
BaseRenderLayer._charAtlasGenerator.generate(terminal.charMeasure.width, terminal.charMeasure.height).then(bitmap => {
BaseRenderLayer._charAtlasGenerator.generate(terminal, terminal.charMeasure.width, terminal.charMeasure.height).then(bitmap => {
BaseRenderLayer._charAtlas = bitmap;
});
}
}
}
protected drawChar(char: string, code: number, fg: number, x: number, y: number, scaledCharWidth: number, scaledCharHeight: number): void {
public abstract clear(terminal: ITerminal): void;
protected drawChar(terminal: ITerminal, char: string, code: number, fg: number, x: number, y: number, scaledCharWidth: number, scaledCharHeight: number): void {
let colorIndex = 0;
if (fg < 256) {
colorIndex = fg + 1;
@@ -57,15 +59,15 @@ export abstract class BaseRenderLayer implements IRenderLayer {
code * scaledCharWidth, colorIndex * scaledCharHeight, scaledCharWidth, scaledCharHeight,
x * scaledCharWidth, y * scaledCharHeight, scaledCharWidth, scaledCharHeight);
} else {
this._drawUncachedChar(char, fg, x, y, scaledCharWidth, scaledCharHeight);
this._drawUncachedChar(terminal, char, fg, x, y, scaledCharWidth, scaledCharHeight);
}
// This draws the atlas (for debugging purposes)
// this._ctx.drawImage(BaseRenderLayer._charAtlas, 0, 0);
}
private _drawUncachedChar(char: string, fg: number, x: number, y: number, scaledCharWidth: number, scaledCharHeight: number): void {
private _drawUncachedChar(terminal: ITerminal, char: string, fg: number, x: number, y: number, scaledCharWidth: number, scaledCharHeight: number): void {
this._ctx.save();
this._ctx.font = `${16 * window.devicePixelRatio}px courier`;
this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;
this._ctx.textBaseline = 'top';
// 256 color support
@@ -91,16 +93,17 @@ class CharAtlasGenerator {
this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
}
public generate(charWidth: number, charHeight: number): Promise<ImageBitmap> {
public generate(terminal: ITerminal, charWidth: number, charHeight: number): Promise<ImageBitmap> {
const scaledCharWidth = Math.ceil(charWidth) * window.devicePixelRatio;
const scaledCharHeight = Math.ceil(charHeight) * window.devicePixelRatio;
console.log('generate');
this._canvas.width = 255 * scaledCharWidth;
this._canvas.height = (/*default*/1 + /*0-15*/16) * scaledCharHeight;
this._ctx.save();
this._ctx.fillStyle = '#ffffff';
this._ctx.font = `${16 * window.devicePixelRatio}px courier`;
this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;
console.log(this._ctx.font, scaledCharWidth, scaledCharHeight);
this._ctx.textBaseline = 'top';
// Default color
+7 -1
View File
@@ -14,6 +14,12 @@ export class CursorRenderLayer extends BaseRenderLayer implements IDataRenderLay
this._state = null;
}
public clear(terminal: ITerminal): void {
const scaledCharWidth = Math.ceil(terminal.charMeasure.width) * window.devicePixelRatio;
const scaledCharHeight = Math.ceil(terminal.charMeasure.height) * window.devicePixelRatio;
this._clearCursor(scaledCharWidth, scaledCharHeight);
}
public render(terminal: ITerminal, startRow: number, endRow: number): void {
// TODO: Track blur/focus somehow, support unfocused cursor
@@ -50,7 +56,7 @@ export class CursorRenderLayer extends BaseRenderLayer implements IDataRenderLay
this._ctx.restore();
const charData = terminal.buffer.lines.get(viewportRelativeCursorY)[terminal.buffer.x];
this.drawChar(charData[CHAR_DATA_CHAR_INDEX], <number>charData[CHAR_DATA_CODE_INDEX], COLOR_CODES.BLACK, terminal.buffer.x, viewportRelativeCursorY, scaledCharWidth, scaledCharHeight);
this.drawChar(terminal, charData[CHAR_DATA_CHAR_INDEX], <number>charData[CHAR_DATA_CODE_INDEX], COLOR_CODES.BLACK, terminal.buffer.x, viewportRelativeCursorY, scaledCharWidth, scaledCharHeight);
this._state = [terminal.buffer.x, viewportRelativeCursorY];
}
+6 -5
View File
@@ -20,6 +20,11 @@ export class ForegroundRenderLayer extends BaseRenderLayer implements IDataRende
this._state.resize(terminal.cols, terminal.rows);
}
public clear(terminal: ITerminal): void {
this._state.clear();
this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
}
public render(terminal: ITerminal, startRow: number, endRow: number): void {
const scaledCharWidth = Math.ceil(terminal.charMeasure.width) * window.devicePixelRatio;
const scaledCharHeight = Math.ceil(terminal.charMeasure.height) * window.devicePixelRatio;
@@ -31,10 +36,6 @@ export class ForegroundRenderLayer extends BaseRenderLayer implements IDataRende
return;
}
this._ctx.fillStyle = '#ffffff';
this._ctx.textBaseline = 'top';
this._ctx.font = `${16 * window.devicePixelRatio}px courier`;
for (let y = startRow; y <= endRow; y++) {
const row = y + terminal.buffer.ydisp;
const line = terminal.buffer.lines.get(row);
@@ -82,7 +83,7 @@ export class ForegroundRenderLayer extends BaseRenderLayer implements IDataRende
}
}
this.drawChar(char, code, fg, x, y, scaledCharWidth, scaledCharHeight);
this.drawChar(terminal, char, code, fg, x, y, scaledCharWidth, scaledCharHeight);
}
}
}
+8
View File
@@ -17,4 +17,12 @@ export class GridCache<T> {
}
this.cache.length = width;
}
public clear() {
for (let x = 0; x < this.cache.length; x++) {
for (let y = 0; y < this.cache[x].length; y++) {
this.cache[x][y] = null;
}
}
}
}
+8
View File
@@ -1,7 +1,15 @@
import { ITerminal } from '../Interfaces';
export interface IRenderLayer {
/**
* Resize the render layer.
*/
resize(terminal: ITerminal, canvasWidth: number, canvasHeight: number, charSizeChanged: boolean): void;
/**
* Clear the state of the render layer.
*/
clear(terminal: ITerminal): void;
}
export interface IDataRenderLayer extends IRenderLayer {
+10 -60
View File
@@ -40,6 +40,7 @@ export class Renderer {
}
public onCharSizeChanged(charWidth: number, charHeight: number): void {
console.log('Renderer.onCharSizeChanged', charWidth, charHeight);
const width = Math.ceil(charWidth) * this._terminal.cols;
const height = Math.ceil(charHeight) * this._terminal.rows;
for (let i = 0; i < this._dataRenderLayers.length; i++) {
@@ -56,6 +57,15 @@ export class Renderer {
}
}
public clear(): void {
for (let i = 0; i < this._dataRenderLayers.length; i++) {
this._dataRenderLayers[i].clear(this._terminal);
}
for (let i = 0; i < this._selectionRenderLayers.length; i++) {
this._selectionRenderLayers[i].clear(this._terminal);
}
}
/**
* Queues a refresh between two rows (inclusive), to be done on next animation
* frame.
@@ -102,64 +112,4 @@ export class Renderer {
}
this._terminal.emit('refresh', {start, end});
}
/**
* Refreshes the selection in the DOM.
* @param start The selection start.
* @param end The selection end.
*/
public refreshSelection(start: [number, number], end: [number, number]): void {
// Remove all selections
while (this._terminal.selectionContainer.children.length) {
this._terminal.selectionContainer.removeChild(this._terminal.selectionContainer.children[0]);
}
// Selection does not exist
if (!start || !end) {
return;
}
// Translate from buffer position to viewport position
const viewportStartRow = start[1] - this._terminal.buffer.ydisp;
const viewportEndRow = end[1] - this._terminal.buffer.ydisp;
const viewportCappedStartRow = Math.max(viewportStartRow, 0);
const viewportCappedEndRow = Math.min(viewportEndRow, this._terminal.rows - 1);
// No need to draw the selection
if (viewportCappedStartRow >= this._terminal.rows || viewportCappedEndRow < 0) {
return;
}
// Create the selections
const documentFragment = document.createDocumentFragment();
// Draw first row
const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;
const endCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : this._terminal.cols;
documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow, startCol, endCol));
// Draw middle rows
const middleRowsCount = viewportCappedEndRow - viewportCappedStartRow - 1;
documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow + 1, 0, this._terminal.cols, middleRowsCount));
// Draw final row
if (viewportCappedStartRow !== viewportCappedEndRow) {
// Only draw viewportEndRow if it's not the same as viewporttartRow
const endCol = viewportEndRow === viewportCappedEndRow ? end[0] : this._terminal.cols;
documentFragment.appendChild(this._createSelectionElement(viewportCappedEndRow, 0, endCol));
}
this._terminal.selectionContainer.appendChild(documentFragment);
}
/**
* Creates a selection element at the specified position.
* @param row The row of the selection.
* @param colStart The start column.
* @param colEnd The end columns.
*/
private _createSelectionElement(row: number, colStart: number, colEnd: number, rowCount: number = 1): HTMLElement {
const element = document.createElement('div');
element.style.height = `${rowCount * this._terminal.charMeasure.height}px`;
element.style.top = `${row * this._terminal.charMeasure.height}px`;
element.style.left = `${colStart * this._terminal.charMeasure.width}px`;
element.style.width = `${this._terminal.charMeasure.width * (colEnd - colStart)}px`;
return element;
}
}
+10
View File
@@ -16,6 +16,16 @@ export class SelectionRenderLayer extends BaseRenderLayer implements ISelectionR
};
}
public clear(terminal: ITerminal): void {
if (this._state.start && this._state.end) {
this._state = {
start: null,
end: null
};
this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
}
}
public render(terminal: ITerminal, start: [number, number], end: [number, number]): void {
const scaledCharWidth = Math.ceil(terminal.charMeasure.width) * window.devicePixelRatio;
const scaledCharHeight = Math.ceil(terminal.charMeasure.height) * window.devicePixelRatio;