mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Add PATH_NEGATIVE, simplify 1FBBD-1FBBF
This commit is contained in:
@@ -514,7 +514,7 @@ export class TextureAtlas implements ITextureAtlas {
|
||||
// Draw custom characters if applicable
|
||||
let customGlyph = false;
|
||||
if (this._config.customGlyphs !== false) {
|
||||
customGlyph = tryDrawCustomGlyph(this._tmpCtx, chars, padding, padding, this._config.deviceCellWidth, this._config.deviceCellHeight, this._config.fontSize, this._config.devicePixelRatio);
|
||||
customGlyph = tryDrawCustomGlyph(this._tmpCtx, chars, padding, padding, this._config.deviceCellWidth, this._config.deviceCellHeight, this._config.fontSize, this._config.devicePixelRatio, backgroundColor.css);
|
||||
}
|
||||
|
||||
// Whether to clear pixels based on a threshold difference between the glyph color and the
|
||||
|
||||
@@ -549,9 +549,9 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi
|
||||
// TODO: Consider implementing
|
||||
|
||||
// Negative terminal graphic characters (1FBBD-1FBBF)
|
||||
'\u{1FBBD}': { type: CustomGlyphDefinitionType.PATH, data: 'M.07,0 L.93,0 L.5,.43 Z M1,.07 L1,.93 L.57,.5 Z M.93,1 L.07,1 L.5,.57 Z M0,.93 L0,.07 L.43,.5 Z' }, // NEGATIVE DIAGONAL CROSS
|
||||
'\u{1FBBE}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L1,.43 L.43,1 L0,1 Z M1,.57 L.57,1 L1,1 Z' }, // NEGATIVE DIAGONAL MIDDLE RIGHT TO LOWER CENTRE
|
||||
'\u{1FBBF}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L.43,0 L0,.43 Z M.57,0 L1,0 L1,.43 Z M1,.57 L1,1 L.57,1 Z M0,.57 L.43,1 L0,1 Z M.5,.07 L.93,.5 L.5,.93 L.07,.5 Z' }, // NEGATIVE DIAGONAL DIAMOND
|
||||
'\u{1FBBD}': { type: CustomGlyphDefinitionType.PATH_NEGATIVE, data: { d: 'M0,0 L.5,.5 L1,0 L1,1 L.5,.5 L0,1 Z', type: CustomGlyphVectorType.STROKE } }, // NEGATIVE DIAGONAL CROSS
|
||||
'\u{1FBBE}': { type: CustomGlyphDefinitionType.PATH_NEGATIVE, data: { d: 'M1,.5 L.5,1', type: CustomGlyphVectorType.STROKE } }, // NEGATIVE DIAGONAL MIDDLE RIGHT TO LOWER CENTRE
|
||||
'\u{1FBBF}': { type: CustomGlyphDefinitionType.PATH_NEGATIVE, data: { d: 'M.5,0 L1,.5 L.5,1 L0,.5 Z', type: CustomGlyphVectorType.STROKE } }, // NEGATIVE DIAGONAL DIAMOND
|
||||
|
||||
// Terminal graphic characters (1FBC0-1FBCA)
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@ export function tryDrawCustomGlyph(
|
||||
deviceCellWidth: number,
|
||||
deviceCellHeight: number,
|
||||
fontSize: number,
|
||||
devicePixelRatio: number
|
||||
devicePixelRatio: number,
|
||||
backgroundColor?: string
|
||||
): boolean {
|
||||
const unifiedCharDefinition = customGlyphDefinitions[c];
|
||||
if (unifiedCharDefinition) {
|
||||
@@ -44,6 +45,9 @@ export function tryDrawCustomGlyph(
|
||||
case CustomGlyphDefinitionType.PATH:
|
||||
drawPathDefinitionCharacter(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
|
||||
return true;
|
||||
case CustomGlyphDefinitionType.PATH_NEGATIVE:
|
||||
drawPathNegativeDefinitionCharacter(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight, devicePixelRatio, backgroundColor);
|
||||
return true;
|
||||
case CustomGlyphDefinitionType.VECTOR_SHAPE:
|
||||
drawVectorShape(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight, fontSize, devicePixelRatio);
|
||||
return true;
|
||||
@@ -111,6 +115,75 @@ function drawPathDefinitionCharacter(
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a "negative" path where the background color is used to draw the shape on top of a
|
||||
* foreground-filled cell. This creates the appearance of a cutout without using actual
|
||||
* transparency, which allows SPAA (subpixel anti-aliasing) to work correctly.
|
||||
*
|
||||
* @param ctx The canvas rendering context (fillStyle should be set to foreground color)
|
||||
* @param charDefinition The vector shape definition for the negative shape
|
||||
* @param xOffset The x offset to draw at
|
||||
* @param yOffset The y offset to draw at
|
||||
* @param deviceCellWidth The width of the cell in device pixels
|
||||
* @param deviceCellHeight The height of the cell in device pixels
|
||||
* @param devicePixelRatio The device pixel ratio
|
||||
* @param backgroundColor The background color to use for the "cutout" portion
|
||||
*/
|
||||
function drawPathNegativeDefinitionCharacter(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
charDefinition: ICustomGlyphVectorShape,
|
||||
xOffset: number,
|
||||
yOffset: number,
|
||||
deviceCellWidth: number,
|
||||
deviceCellHeight: number,
|
||||
devicePixelRatio: number,
|
||||
backgroundColor?: string
|
||||
): void {
|
||||
ctx.save();
|
||||
|
||||
// First, fill the entire cell with foreground color
|
||||
ctx.fillRect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
|
||||
|
||||
// Then draw the "negative" shape with the background color
|
||||
if (backgroundColor) {
|
||||
ctx.fillStyle = backgroundColor;
|
||||
ctx.strokeStyle = backgroundColor;
|
||||
}
|
||||
|
||||
ctx.lineWidth = devicePixelRatio;
|
||||
ctx.lineCap = 'square';
|
||||
ctx.beginPath();
|
||||
for (const instruction of charDefinition.d.split(' ')) {
|
||||
const type = instruction[0];
|
||||
const args: string[] = instruction.substring(1).split(',');
|
||||
if (!args[0] || !args[1]) {
|
||||
if (type === 'Z') {
|
||||
ctx.closePath();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const translatedArgs = args.map((e, i) => {
|
||||
const val = parseFloat(e);
|
||||
return i % 2 === 0
|
||||
? xOffset + val * deviceCellWidth
|
||||
: yOffset + val * deviceCellHeight;
|
||||
});
|
||||
if (type === 'M') {
|
||||
ctx.moveTo(translatedArgs[0], translatedArgs[1]);
|
||||
} else if (type === 'L') {
|
||||
ctx.lineTo(translatedArgs[0], translatedArgs[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (charDefinition.type === CustomGlyphVectorType.STROKE) {
|
||||
ctx.stroke();
|
||||
} else {
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
const cachedPatterns: Map<CustomGlyphPatternDefinition, Map</* fillStyle */string, CanvasPattern>> = new Map();
|
||||
|
||||
function drawPatternChar(
|
||||
|
||||
@@ -39,6 +39,7 @@ export const enum CustomGlyphDefinitionType {
|
||||
PATH_FUNCTION,
|
||||
PATH_FUNCTION_WITH_WEIGHT,
|
||||
PATH,
|
||||
PATH_NEGATIVE,
|
||||
VECTOR_SHAPE,
|
||||
}
|
||||
|
||||
@@ -55,5 +56,6 @@ export type CustomGlyphCharacterDefinition = (
|
||||
{ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: CustomGlyphPathDrawFunctionDefinition } |
|
||||
{ type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [fontWeight: number]: string | CustomGlyphPathDrawFunctionDefinition } } |
|
||||
{ type: CustomGlyphDefinitionType.PATH, data: string } |
|
||||
{ type: CustomGlyphDefinitionType.PATH_NEGATIVE, data: ICustomGlyphVectorShape } |
|
||||
{ type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: ICustomGlyphVectorShape }
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user