mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #3856 from Tyriar/custom_powerline_glyphs
Custom common powerline glyph rendering
This commit is contained in:
@@ -585,6 +585,32 @@ function powerlineSymbolTest() {
|
||||
term.writeln(`0xA_ ${s('\ue0a0')}${s('\ue0a1')}${s('\ue0a2')}`);
|
||||
term.writeln(`0xB_ ${s('\ue0b0')}${s('\ue0b1')}${s('\ue0b2')}${s('\ue0b3')}`);
|
||||
term.writeln('');
|
||||
term.writeln(
|
||||
`\x1b[7m` +
|
||||
` inverse \ue0b1 \x1b[0;40m\ue0b0` +
|
||||
` 0 \ue0b1 \x1b[30;41m\ue0b0\x1b[39m` +
|
||||
` 1 \ue0b1 \x1b[31;42m\ue0b0\x1b[39m` +
|
||||
` 2 \ue0b1 \x1b[32;43m\ue0b0\x1b[39m` +
|
||||
` 3 \ue0b1 \x1b[33;44m\ue0b0\x1b[39m` +
|
||||
` 4 \ue0b1 \x1b[34;45m\ue0b0\x1b[39m` +
|
||||
` 5 \ue0b1 \x1b[35;46m\ue0b0\x1b[39m` +
|
||||
` 6 \ue0b1 \x1b[36;47m\ue0b0\x1b[39m` +
|
||||
` 7 \ue0b1 \x1b[37;49m\ue0b0\x1b[0m`
|
||||
);
|
||||
term.writeln('');
|
||||
term.writeln(
|
||||
`\x1b[7m` +
|
||||
` inverse \ue0b3 \x1b[0;7;40m\ue0b2\x1b[27m` +
|
||||
` 0 \ue0b3 \x1b[7;30;41m\ue0b2\x1b[27;39m` +
|
||||
` 1 \ue0b3 \x1b[7;31;42m\ue0b2\x1b[27;39m` +
|
||||
` 2 \ue0b3 \x1b[7;32;43m\ue0b2\x1b[27;39m` +
|
||||
` 3 \ue0b3 \x1b[7;33;44m\ue0b2\x1b[27;39m` +
|
||||
` 4 \ue0b3 \x1b[7;34;45m\ue0b2\x1b[27;39m` +
|
||||
` 5 \ue0b3 \x1b[7;35;46m\ue0b2\x1b[27;39m` +
|
||||
` 6 \ue0b3 \x1b[7;36;47m\ue0b2\x1b[27;39m` +
|
||||
` 7 \ue0b3 \x1b[7;37;49m\ue0b2\x1b[0m`
|
||||
);
|
||||
term.writeln('');
|
||||
term.writeln('Powerline extra symbols:');
|
||||
term.writeln(' 0 1 2 3 4 5 6 7 8 9 A B C D E F');
|
||||
term.writeln(`0xA_ ${s('\ue0a3')}`);
|
||||
|
||||
@@ -325,6 +325,37 @@ export const boxDrawingDefinitions: { [character: string]: { [fontWeight: number
|
||||
'╰': { [Style.NORMAL]: 'C.5,0,.5,.5,1,.5' }
|
||||
};
|
||||
|
||||
interface IVectorShape {
|
||||
d: string;
|
||||
type: VectorType;
|
||||
/** Padding to apply to the vector's x axis in CSS pixels. */
|
||||
horizontalPadding?: number;
|
||||
}
|
||||
|
||||
const enum VectorType {
|
||||
FILL,
|
||||
STROKE
|
||||
}
|
||||
|
||||
/**
|
||||
* This contains the definitions of the primarily used box drawing characters as vector shapes. The
|
||||
* reason these characters are defined specially is to avoid common problems if a user's font has
|
||||
* not been patched with powerline characters and also to get pixel perfect rendering as rendering
|
||||
* issues can occur around AA/SPAA.
|
||||
*
|
||||
* Original symbols defined in https://github.com/powerline/fontpatcher
|
||||
*/
|
||||
export const powerlineDefinitions: { [index: string]: IVectorShape } = {
|
||||
// Right triangle solid
|
||||
'\u{E0B0}': { d: 'M0,0 L1,.5 L0,1', type: VectorType.FILL },
|
||||
// Right triangle line
|
||||
'\u{E0B1}': { d: 'M0,0 L1,.5 L0,1', type: VectorType.STROKE, horizontalPadding: 0.5 },
|
||||
// Left triangle solid
|
||||
'\u{E0B2}': { d: 'M1,0 L0,.5 L1,1', type: VectorType.FILL },
|
||||
// Left triangle line
|
||||
'\u{E0B3}': { d: 'M1,0 L0,.5 L1,1', type: VectorType.STROKE, horizontalPadding: 0.5 }
|
||||
};
|
||||
|
||||
/**
|
||||
* Try drawing a custom block element or box drawing character, returning whether it was
|
||||
* successfully drawn.
|
||||
@@ -355,6 +386,12 @@ export function tryDrawCustomChar(
|
||||
return true;
|
||||
}
|
||||
|
||||
const powerlineDefinition = powerlineDefinitions[c];
|
||||
if (powerlineDefinition) {
|
||||
drawPowerlineChar(ctx, powerlineDefinition, xOffset, yOffset, scaledCellWidth, scaledCellHeight);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -518,6 +555,38 @@ function drawBoxDrawingChar(
|
||||
}
|
||||
}
|
||||
|
||||
function drawPowerlineChar(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
charDefinition: IVectorShape,
|
||||
xOffset: number,
|
||||
yOffset: number,
|
||||
scaledCellWidth: number,
|
||||
scaledCellHeight: number
|
||||
): void {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = window.devicePixelRatio;
|
||||
for (const instruction of charDefinition.d.split(' ')) {
|
||||
const type = instruction[0];
|
||||
const f = svgToCanvasInstructionMap[type];
|
||||
if (!f) {
|
||||
console.error(`Could not find drawing instructions for "${type}"`);
|
||||
continue;
|
||||
}
|
||||
const args: string[] = instruction.substring(1).split(',');
|
||||
if (!args[0] || !args[1]) {
|
||||
continue;
|
||||
}
|
||||
f(ctx, translateArgs(args, scaledCellWidth, scaledCellHeight, xOffset, yOffset, charDefinition.horizontalPadding));
|
||||
}
|
||||
if (charDefinition.type === VectorType.STROKE) {
|
||||
ctx.strokeStyle = ctx.fillStyle;
|
||||
ctx.stroke();
|
||||
} else {
|
||||
ctx.fill();
|
||||
}
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
function clamp(value: number, max: number, min: number = 0): number {
|
||||
return Math.max(Math.min(value, max), min);
|
||||
}
|
||||
@@ -528,7 +597,7 @@ const svgToCanvasInstructionMap: { [index: string]: any } = {
|
||||
'M': (ctx: CanvasRenderingContext2D, args: number[]) => ctx.moveTo(args[0], args[1])
|
||||
};
|
||||
|
||||
function translateArgs(args: string[], cellWidth: number, cellHeight: number, xOffset: number, yOffset: number): number[] {
|
||||
function translateArgs(args: string[], cellWidth: number, cellHeight: number, xOffset: number, yOffset: number, horizontalPadding: number = 0): number[] {
|
||||
const result = args.map(e => parseFloat(e) || parseInt(e));
|
||||
|
||||
if (result.length < 2) {
|
||||
@@ -537,14 +606,14 @@ function translateArgs(args: string[], cellWidth: number, cellHeight: number, xO
|
||||
|
||||
for (let x = 0; x < result.length; x += 2) {
|
||||
// Translate from 0-1 to 0-cellWidth
|
||||
result[x] *= cellWidth;
|
||||
result[x] *= cellWidth - (horizontalPadding * 2 * window.devicePixelRatio);
|
||||
// Ensure coordinate doesn't escape cell bounds and round to the nearest 0.5 to ensure a crisp
|
||||
// line at 100% devicePixelRatio
|
||||
if (result[x] !== 0) {
|
||||
result[x] = clamp(Math.round(result[x] + 0.5) - 0.5, cellWidth, 0);
|
||||
}
|
||||
// Apply the cell's offset (ie. x*cellWidth)
|
||||
result[x] += xOffset;
|
||||
result[x] += xOffset + (horizontalPadding * window.devicePixelRatio);
|
||||
}
|
||||
|
||||
for (let y = 1; y < result.length; y += 2) {
|
||||
|
||||
Reference in New Issue
Block a user