Update other files

This commit is contained in:
Daniel Imms
2022-10-15 15:32:02 -07:00
parent 89e0b87eac
commit 171ba446bd
7 changed files with 77 additions and 91 deletions
@@ -992,8 +992,8 @@ async function getCellColor(col: number, row: number): Promise<number[]> {
window.result = new Uint8Array(4);
window.d = window.term._core._renderService.dimensions;
window.gl.readPixels(
Math.floor((${col - 0.5}) * window.d.scaledCellWidth),
Math.floor(window.gl.drawingBufferHeight - 1 - (${row - 0.5}) * window.d.scaledCellHeight),
Math.floor((${col - 0.5}) * window.d.canvas.cell.width),
Math.floor(window.gl.drawingBufferHeight - 1 - (${row - 0.5}) * window.d.canvas.cell.height),
1, 1, window.gl.RGBA, window.gl.UNSIGNED_BYTE, window.result
);
`);
@@ -1003,12 +1003,12 @@ async function getCellColor(col: number, row: number): Promise<number[]> {
async function getCellPixels(col: number, row: number): Promise<number[]> {
await page.evaluate(`
window.gl = window.term._core._renderService._renderer._gl;
window.result = new Uint8Array(window.d.scaledCellWidth * window.d.scaledCellHeight * 4);
window.result = new Uint8Array(window.d.canvas.cell.width * window.d.canvas.cell.height * 4);
window.d = window.term._core._renderService.dimensions;
window.gl.readPixels(
Math.floor(${col - 1} * window.d.scaledCellWidth),
Math.floor(window.gl.drawingBufferHeight - ${row} * window.d.scaledCellHeight),
window.d.scaledCellWidth, window.d.scaledCellHeight, window.gl.RGBA, window.gl.UNSIGNED_BYTE, window.result
Math.floor(${col - 1} * window.d.canvas.cell.width),
Math.floor(window.gl.drawingBufferHeight - ${row} * window.d.canvas.cell.height),
window.d.canvas.cell.width, window.d.canvas.cell.height, window.gl.RGBA, window.gl.UNSIGNED_BYTE, window.result
);
`);
return await page.evaluate(`Array.from(window.result)`);
@@ -28,13 +28,13 @@ const charAtlasCache: ITextureAtlasCacheEntry[] = [];
export function acquireTextureAtlas(
terminal: Terminal,
colors: ReadonlyColorSet,
scaledCellWidth: number,
scaledCellHeight: number,
scaledCharWidth: number,
scaledCharHeight: number,
deviceCellWidth: number,
deviceCellHeight: number,
deviceCharWidth: number,
deviceCharHeight: number,
devicePixelRatio: number
): ITextureAtlas {
const newConfig = generateConfig(scaledCellWidth, scaledCellHeight, scaledCharWidth, scaledCharHeight, terminal, colors, devicePixelRatio);
const newConfig = generateConfig(deviceCellWidth, deviceCellHeight, deviceCharWidth, deviceCharHeight, terminal, colors, devicePixelRatio);
// Check to see if the terminal already owns this config
for (let i = 0; i < charAtlasCache.length; i++) {
@@ -9,7 +9,7 @@ import { Terminal } from 'xterm';
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
import { NULL_COLOR } from 'common/Color';
export function generateConfig(scaledCellWidth: number, scaledCellHeight: number, scaledCharWidth: number, scaledCharHeight: number, terminal: Terminal, colors: ReadonlyColorSet, devicePixelRatio: number): ICharAtlasConfig {
export function generateConfig(deviceCellWidth: number, deviceCellHeight: number, deviceCharWidth: number, deviceCharHeight: number, terminal: Terminal, colors: ReadonlyColorSet, devicePixelRatio: number): ICharAtlasConfig {
// null out some fields that don't matter
const clonedColors: IColorSet = {
foreground: colors.foreground,
@@ -31,10 +31,10 @@ export function generateConfig(scaledCellWidth: number, scaledCellHeight: number
devicePixelRatio,
letterSpacing: terminal.options.letterSpacing,
lineHeight: terminal.options.lineHeight,
scaledCellWidth,
scaledCellHeight,
scaledCharWidth,
scaledCharHeight,
deviceCellWidth: deviceCellWidth,
deviceCellHeight: deviceCellHeight,
deviceCharWidth: deviceCharWidth,
deviceCharHeight: deviceCharHeight,
fontFamily: terminal.options.fontFamily,
fontSize: terminal.options.fontSize,
fontWeight: terminal.options.fontWeight,
@@ -61,8 +61,8 @@ export function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean
a.fontWeight === b.fontWeight &&
a.fontWeightBold === b.fontWeightBold &&
a.allowTransparency === b.allowTransparency &&
a.scaledCharWidth === b.scaledCharWidth &&
a.scaledCharHeight === b.scaledCharHeight &&
a.deviceCharWidth === b.deviceCharWidth &&
a.deviceCharHeight === b.deviceCharHeight &&
a.drawBoldTextInBrightColors === b.drawBoldTextInBrightColors &&
a.minimumContrastRatio === b.minimumContrastRatio &&
a.colors.foreground.rgba === b.colors.foreground.rgba &&
+21 -21
View File
@@ -381,32 +381,32 @@ export function tryDrawCustomChar(
c: string,
xOffset: number,
yOffset: number,
scaledCellWidth: number,
scaledCellHeight: number,
deviceCellWidth: number,
deviceCellHeight: number,
fontSize: number,
devicePixelRatio: number
): boolean {
const blockElementDefinition = blockElementDefinitions[c];
if (blockElementDefinition) {
drawBlockElementChar(ctx, blockElementDefinition, xOffset, yOffset, scaledCellWidth, scaledCellHeight);
drawBlockElementChar(ctx, blockElementDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
}
const patternDefinition = patternCharacterDefinitions[c];
if (patternDefinition) {
drawPatternChar(ctx, patternDefinition, xOffset, yOffset, scaledCellWidth, scaledCellHeight);
drawPatternChar(ctx, patternDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
}
const boxDrawingDefinition = boxDrawingDefinitions[c];
if (boxDrawingDefinition) {
drawBoxDrawingChar(ctx, boxDrawingDefinition, xOffset, yOffset, scaledCellWidth, scaledCellHeight, devicePixelRatio);
drawBoxDrawingChar(ctx, boxDrawingDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight, devicePixelRatio);
return true;
}
const powerlineDefinition = powerlineDefinitions[c];
if (powerlineDefinition) {
drawPowerlineChar(ctx, powerlineDefinition, xOffset, yOffset, scaledCellWidth, scaledCellHeight, fontSize, devicePixelRatio);
drawPowerlineChar(ctx, powerlineDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight, fontSize, devicePixelRatio);
return true;
}
@@ -418,13 +418,13 @@ function drawBlockElementChar(
charDefinition: IBlockVector[],
xOffset: number,
yOffset: number,
scaledCellWidth: number,
scaledCellHeight: number
deviceCellWidth: number,
deviceCellHeight: number
): void {
for (let i = 0; i < charDefinition.length; i++) {
const box = charDefinition[i];
const xEighth = scaledCellWidth / 8;
const yEighth = scaledCellHeight / 8;
const xEighth = deviceCellWidth / 8;
const yEighth = deviceCellHeight / 8;
ctx.fillRect(
xOffset + box.x * xEighth,
yOffset + box.y * yEighth,
@@ -441,8 +441,8 @@ function drawPatternChar(
charDefinition: number[][],
xOffset: number,
yOffset: number,
scaledCellWidth: number,
scaledCellHeight: number
deviceCellWidth: number,
deviceCellHeight: number
): void {
let patternSet = cachedPatterns.get(charDefinition);
if (!patternSet) {
@@ -492,7 +492,7 @@ function drawPatternChar(
patternSet.set(fillStyle, pattern);
}
ctx.fillStyle = pattern;
ctx.fillRect(xOffset, yOffset, scaledCellWidth, scaledCellHeight);
ctx.fillRect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
}
/**
@@ -540,8 +540,8 @@ function drawBoxDrawingChar(
charDefinition: { [fontWeight: number]: string | ((xp: number, yp: number) => string) },
xOffset: number,
yOffset: number,
scaledCellWidth: number,
scaledCellHeight: number,
deviceCellWidth: number,
deviceCellHeight: number,
devicePixelRatio: number
): void {
ctx.strokeStyle = ctx.fillStyle;
@@ -551,7 +551,7 @@ function drawBoxDrawingChar(
let actualInstructions: string;
if (typeof instructions === 'function') {
const xp = .15;
const yp = .15 / scaledCellHeight * scaledCellWidth;
const yp = .15 / deviceCellHeight * deviceCellWidth;
actualInstructions = instructions(xp, yp);
} else {
actualInstructions = instructions;
@@ -567,7 +567,7 @@ function drawBoxDrawingChar(
if (!args[0] || !args[1]) {
continue;
}
f(ctx, translateArgs(args, scaledCellWidth, scaledCellHeight, xOffset, yOffset, true, devicePixelRatio));
f(ctx, translateArgs(args, deviceCellWidth, deviceCellHeight, xOffset, yOffset, true, devicePixelRatio));
}
ctx.stroke();
ctx.closePath();
@@ -579,8 +579,8 @@ function drawPowerlineChar(
charDefinition: IVectorShape,
xOffset: number,
yOffset: number,
scaledCellWidth: number,
scaledCellHeight: number,
deviceCellWidth: number,
deviceCellHeight: number,
fontSize: number,
devicePixelRatio: number
): void {
@@ -601,8 +601,8 @@ function drawPowerlineChar(
}
f(ctx, translateArgs(
args,
scaledCellWidth,
scaledCellHeight,
deviceCellWidth,
deviceCellHeight,
xOffset,
yOffset,
false,
+30 -30
View File
@@ -98,8 +98,8 @@ export class TextureAtlas implements ITextureAtlas {
this._cacheCtx = throwIfFalsy(this.cacheCanvas.getContext('2d', { alpha: true }));
this._tmpCanvas = document.createElement('canvas');
this._tmpCanvas.width = this._config.scaledCellWidth * 4 + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCanvas.height = this._config.scaledCellHeight + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCanvas.width = this._config.deviceCellWidth * 4 + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCanvas.height = this._config.deviceCellHeight + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCtx = throwIfFalsy(this._tmpCanvas.getContext('2d', {
alpha: this._config.allowTransparency,
willReadFrequently: true
@@ -345,12 +345,12 @@ export class TextureAtlas implements ITextureAtlas {
// Allow 1 cell width per character, with a minimum of 2 (CJK), plus some padding. This is used
// to draw the glyph to the canvas as well as to restrict the bounding box search to ensure
// giant ligatures (eg. =====>) don't impact overall performance.
const allowedWidth = this._config.scaledCellWidth * Math.max(chars.length, 2) + TMP_CANVAS_GLYPH_PADDING * 2;
const allowedWidth = this._config.deviceCellWidth * Math.max(chars.length, 2) + TMP_CANVAS_GLYPH_PADDING * 2;
if (this._tmpCanvas.width < allowedWidth) {
this._tmpCanvas.width = allowedWidth;
}
// Include line height when drawing glyphs
const allowedHeight = this._config.scaledCellHeight + TMP_CANVAS_GLYPH_PADDING * 4;
const allowedHeight = this._config.deviceCellHeight + TMP_CANVAS_GLYPH_PADDING * 4;
if (this._tmpCanvas.height < allowedHeight) {
this._tmpCanvas.height = allowedHeight;
}
@@ -411,7 +411,7 @@ export class TextureAtlas implements ITextureAtlas {
// Draw custom characters if applicable
let customGlyph = false;
if (this._config.customGlyphs !== false) {
customGlyph = tryDrawCustomChar(this._tmpCtx, chars, padding, padding, this._config.scaledCellWidth, this._config.scaledCellHeight, this._config.fontSize, this._config.devicePixelRatio);
customGlyph = tryDrawCustomChar(this._tmpCtx, chars, padding, padding, this._config.deviceCellWidth, this._config.deviceCellHeight, this._config.fontSize, this._config.devicePixelRatio);
}
// Whether to clear pixels based on a threshold difference between the glyph color and the
@@ -452,15 +452,15 @@ export class TextureAtlas implements ITextureAtlas {
// Underline style/stroke
this._tmpCtx.beginPath();
const xLeft = padding;
const yTop = Math.ceil(padding + this._config.scaledCharHeight) - yOffset;
const yMid = padding + this._config.scaledCharHeight + lineWidth - yOffset;
const yBot = Math.ceil(padding + this._config.scaledCharHeight + lineWidth * 2) - yOffset;
const yTop = Math.ceil(padding + this._config.deviceCharHeight) - yOffset;
const yMid = padding + this._config.deviceCharHeight + lineWidth - yOffset;
const yBot = Math.ceil(padding + this._config.deviceCharHeight + lineWidth * 2) - yOffset;
for (let i = 0; i < chWidth; i++) {
this._tmpCtx.save();
const xChLeft = xLeft + i * this._config.scaledCellWidth;
const xChRight = xLeft + (i + 1) * this._config.scaledCellWidth;
const xChMid = xChLeft + this._config.scaledCellWidth / 2;
const xChLeft = xLeft + i * this._config.deviceCellWidth;
const xChRight = xLeft + (i + 1) * this._config.deviceCellWidth;
const xChMid = xChLeft + this._config.deviceCellWidth / 2;
switch (this._workAttributeData.extended.underlineStyle) {
case UnderlineStyle.DOUBLE:
this._tmpCtx.moveTo(xChLeft, yTop);
@@ -471,18 +471,18 @@ export class TextureAtlas implements ITextureAtlas {
case UnderlineStyle.CURLY:
// Choose the bezier top and bottom based on the device pixel ratio, the curly line is
// made taller when the line width is as otherwise it's not very clear otherwise.
const yCurlyBot = lineWidth <= 1 ? yBot : Math.ceil(padding + this._config.scaledCharHeight - lineWidth / 2) - yOffset;
const yCurlyTop = lineWidth <= 1 ? yTop : Math.ceil(padding + this._config.scaledCharHeight + lineWidth / 2) - yOffset;
const yCurlyBot = lineWidth <= 1 ? yBot : Math.ceil(padding + this._config.deviceCharHeight - lineWidth / 2) - yOffset;
const yCurlyTop = lineWidth <= 1 ? yTop : Math.ceil(padding + this._config.deviceCharHeight + lineWidth / 2) - yOffset;
// Clip the left and right edges of the underline such that it can be drawn just outside
// the edge of the cell to ensure a continuous stroke when there are multiple underlined
// glyphs adjacent to one another.
const clipRegion = new Path2D();
clipRegion.rect(xChLeft, yTop, this._config.scaledCellWidth, yBot - yTop);
clipRegion.rect(xChLeft, yTop, this._config.deviceCellWidth, yBot - yTop);
this._tmpCtx.clip(clipRegion);
// Start 1/2 cell before and end 1/2 cells after to ensure a smooth curve with other cells
this._tmpCtx.moveTo(xChLeft - this._config.scaledCellWidth / 2, yMid);
this._tmpCtx.moveTo(xChLeft - this._config.deviceCellWidth / 2, yMid);
this._tmpCtx.bezierCurveTo(
xChLeft - this._config.scaledCellWidth / 2, yCurlyTop,
xChLeft - this._config.deviceCellWidth / 2, yCurlyTop,
xChLeft, yCurlyTop,
xChLeft, yMid
);
@@ -498,8 +498,8 @@ export class TextureAtlas implements ITextureAtlas {
);
this._tmpCtx.bezierCurveTo(
xChRight, yCurlyBot,
xChRight + this._config.scaledCellWidth / 2, yCurlyBot,
xChRight + this._config.scaledCellWidth / 2, yMid
xChRight + this._config.deviceCellWidth / 2, yCurlyBot,
xChRight + this._config.deviceCellWidth / 2, yMid
);
break;
case UnderlineStyle.DOTTED:
@@ -543,11 +543,11 @@ export class TextureAtlas implements ITextureAtlas {
// outline around the whole glyph, as well as additional pixels in the glyph at the top
// which would increase GPU memory demands
const clipRegion = new Path2D();
clipRegion.rect(xLeft, yTop - Math.ceil(lineWidth / 2), this._config.scaledCellWidth, yBot - yTop + Math.ceil(lineWidth / 2));
clipRegion.rect(xLeft, yTop - Math.ceil(lineWidth / 2), this._config.deviceCellWidth, yBot - yTop + Math.ceil(lineWidth / 2));
this._tmpCtx.clip(clipRegion);
this._tmpCtx.lineWidth = this._config.devicePixelRatio * 3;
this._tmpCtx.strokeStyle = backgroundColor.css;
this._tmpCtx.strokeText(chars, padding, padding + this._config.scaledCharHeight);
this._tmpCtx.strokeText(chars, padding, padding + this._config.deviceCharHeight);
this._tmpCtx.restore();
}
}
@@ -556,21 +556,21 @@ export class TextureAtlas implements ITextureAtlas {
// Draw the character
if (!customGlyph) {
this._tmpCtx.fillText(chars, padding, padding + this._config.scaledCharHeight);
this._tmpCtx.fillText(chars, padding, padding + this._config.deviceCharHeight);
}
// If this charcater is underscore and beyond the cell bounds, shift it up until it is visible
// even on the bottom row, try for a maximum of 5 pixels.
if (chars === '_' && !this._config.allowTransparency) {
let isBeyondCellBounds = clearColor(this._tmpCtx.getImageData(padding, padding, this._config.scaledCellWidth, this._config.scaledCellHeight), backgroundColor, foregroundColor, enableClearThresholdCheck);
let isBeyondCellBounds = clearColor(this._tmpCtx.getImageData(padding, padding, this._config.deviceCellWidth, this._config.deviceCellHeight), backgroundColor, foregroundColor, enableClearThresholdCheck);
if (isBeyondCellBounds) {
for (let offset = 1; offset <= 5; offset++) {
this._tmpCtx.save();
this._tmpCtx.fillStyle = backgroundColor.css;
this._tmpCtx.fillRect(0, 0, this._tmpCanvas.width, this._tmpCanvas.height);
this._tmpCtx.restore();
this._tmpCtx.fillText(chars, padding, padding + this._config.scaledCharHeight - offset);
isBeyondCellBounds = clearColor(this._tmpCtx.getImageData(padding, padding, this._config.scaledCellWidth, this._config.scaledCellHeight), backgroundColor, foregroundColor, enableClearThresholdCheck);
this._tmpCtx.fillText(chars, padding, padding + this._config.deviceCharHeight - offset);
isBeyondCellBounds = clearColor(this._tmpCtx.getImageData(padding, padding, this._config.deviceCellWidth, this._config.deviceCellHeight), backgroundColor, foregroundColor, enableClearThresholdCheck);
if (!isBeyondCellBounds) {
break;
}
@@ -585,8 +585,8 @@ export class TextureAtlas implements ITextureAtlas {
this._tmpCtx.lineWidth = lineWidth;
this._tmpCtx.strokeStyle = this._tmpCtx.fillStyle;
this._tmpCtx.beginPath();
this._tmpCtx.moveTo(padding, padding + Math.floor(this._config.scaledCharHeight / 2) - yOffset);
this._tmpCtx.lineTo(padding + this._config.scaledCharWidth * chWidth, padding + Math.floor(this._config.scaledCharHeight / 2) - yOffset);
this._tmpCtx.moveTo(padding, padding + Math.floor(this._config.deviceCharHeight / 2) - yOffset);
this._tmpCtx.lineTo(padding + this._config.deviceCharWidth * chWidth, padding + Math.floor(this._config.deviceCharHeight / 2) - yOffset);
this._tmpCtx.stroke();
}
@@ -697,8 +697,8 @@ export class TextureAtlas implements ITextureAtlas {
*/
private _findGlyphBoundingBox(imageData: ImageData, boundingBox: IBoundingBox, allowedWidth: number, restrictedGlyph: boolean, customGlyph: boolean, padding: number): IRasterizedGlyph {
boundingBox.top = 0;
const height = restrictedGlyph ? this._config.scaledCellHeight : this._tmpCanvas.height;
const width = restrictedGlyph ? this._config.scaledCellWidth : allowedWidth;
const height = restrictedGlyph ? this._config.deviceCellHeight : this._tmpCanvas.height;
const width = restrictedGlyph ? this._config.deviceCellWidth : allowedWidth;
let found = false;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
@@ -770,8 +770,8 @@ export class TextureAtlas implements ITextureAtlas {
y: (boundingBox.bottom - boundingBox.top + 1) / TEXTURE_HEIGHT
},
offset: {
x: -boundingBox.left + padding + ((restrictedGlyph || customGlyph) ? Math.floor((this._config.scaledCellWidth - this._config.scaledCharWidth) / 2) : 0),
y: -boundingBox.top + padding + ((restrictedGlyph || customGlyph) ? this._config.lineHeight === 1 ? 0 : Math.round((this._config.scaledCellHeight - this._config.scaledCharHeight) / 2) : 0)
x: -boundingBox.left + padding + ((restrictedGlyph || customGlyph) ? Math.floor((this._config.deviceCellWidth - this._config.deviceCharWidth) / 2) : 0),
y: -boundingBox.top + padding + ((restrictedGlyph || customGlyph) ? this._config.lineHeight === 1 ? 0 : Math.round((this._config.deviceCellHeight - this._config.deviceCharHeight) / 2) : 0)
}
};
}
+5 -5
View File
@@ -4,7 +4,7 @@
*/
import { FontWeight, Terminal } from 'xterm';
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
import { IColorSet } from 'browser/Types';
import { IDisposable } from 'common/Types';
import { IEvent } from 'common/EventEmitter';
@@ -17,10 +17,10 @@ export interface ICharAtlasConfig {
fontFamily: string;
fontWeight: FontWeight;
fontWeightBold: FontWeight;
scaledCellWidth: number;
scaledCellHeight: number;
scaledCharWidth: number;
scaledCharHeight: number;
deviceCellWidth: number;
deviceCellHeight: number;
deviceCharWidth: number;
deviceCharHeight: number;
allowTransparency: boolean;
drawBoldTextInBrightColors: boolean;
minimumContrastRatio: number;
+3 -17
View File
@@ -7,6 +7,7 @@ import { assert } from 'chai';
import { pollFor, timeout, writeSync, openTerminal, launchBrowser } from './TestUtils';
import { Browser, Page } from 'playwright';
import { fail } from 'assert';
import { IRenderDimensions } from 'browser/renderer/shared/Types';
const APP = 'http://127.0.0.1:3001/test';
@@ -1032,21 +1033,6 @@ interface IDimensions {
renderDimensions: IRenderDimensions;
}
interface IRenderDimensions {
scaledCharWidth: number;
scaledCharHeight: number;
scaledCellWidth: number;
scaledCellHeight: number;
scaledCharLeft: number;
scaledCharTop: number;
scaledCanvasWidth: number;
scaledCanvasHeight: number;
canvasWidth: number;
canvasHeight: number;
actualCellWidth: number;
actualCellHeight: number;
}
async function getDimensions(): Promise<IDimensions> {
return await page.evaluate(`
(function() {
@@ -1062,8 +1048,8 @@ async function getDimensions(): Promise<IDimensions> {
async function getCellCoordinates(dimensions: IDimensions, col: number, row: number): Promise<{ x: number, y: number }> {
return {
x: dimensions.left + dimensions.renderDimensions.scaledCellWidth * (col - 0.5),
y: dimensions.top + dimensions.renderDimensions.scaledCellHeight * (row - 0.5)
x: dimensions.left + dimensions.renderDimensions.device.cell.width * (col - 0.5),
y: dimensions.top + dimensions.renderDimensions.device.cell.height * (row - 0.5)
};
}