mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Fix DynamicCharAtlas with transparency
There were two bugs: - We need to clear the background of _tmpCtx instead of just drawing on top if the background color is transparent. - We should set the background to fully transparent if it's partially transparent, to avoid drawing the transparent background twice.
This commit is contained in:
@@ -26,6 +26,9 @@
|
||||
<p>
|
||||
<label><input type="checkbox" id="option-mac-option-is-meta"> macOptionIsMeta</label>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="checkbox" id="option-transparency"> transparency</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
cursorStyle
|
||||
|
||||
+9
-3
@@ -31,6 +31,7 @@ var terminalContainer = document.getElementById('terminal-container'),
|
||||
cursorStyle: document.querySelector('#option-cursor-style'),
|
||||
macOptionIsMeta: document.querySelector('#option-mac-option-is-meta'),
|
||||
scrollback: document.querySelector('#option-scrollback'),
|
||||
transparency: document.querySelector('#option-transparency'),
|
||||
tabstopwidth: document.querySelector('#option-tabstopwidth'),
|
||||
experimentalCharAtlas: document.querySelector('#option-experimental-char-atlas'),
|
||||
bellStyle: document.querySelector('#option-bell-style'),
|
||||
@@ -75,15 +76,20 @@ actionElements.findPrevious.addEventListener('keypress', function (e) {
|
||||
optionElements.cursorBlink.addEventListener('change', function () {
|
||||
term.setOption('cursorBlink', optionElements.cursorBlink.checked);
|
||||
});
|
||||
optionElements.macOptionIsMeta.addEventListener('change', function () {
|
||||
term.setOption('macOptionIsMeta', optionElements.macOptionIsMeta.checked);
|
||||
});
|
||||
optionElements.transparency.addEventListener('change', function () {
|
||||
var checked = optionElements.transparency.checked;
|
||||
term.setOption('allowTransparency', checked);
|
||||
term.setOption('theme', checked ? {background: 'rgba(0, 0, 0, .5)'} : {});
|
||||
});
|
||||
optionElements.cursorStyle.addEventListener('change', function () {
|
||||
term.setOption('cursorStyle', optionElements.cursorStyle.value);
|
||||
});
|
||||
optionElements.bellStyle.addEventListener('change', function () {
|
||||
term.setOption('bellStyle', optionElements.bellStyle.value);
|
||||
});
|
||||
optionElements.macOptionIsMeta.addEventListener('change', function () {
|
||||
term.setOption('macOptionIsMeta', optionElements.macOptionIsMeta.checked);
|
||||
});
|
||||
optionElements.scrollback.addEventListener('change', function () {
|
||||
term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10));
|
||||
});
|
||||
|
||||
@@ -150,6 +150,7 @@ export class Renderer extends EventEmitter implements IRenderer {
|
||||
}
|
||||
|
||||
public onOptionsChanged(): void {
|
||||
this.colorManager.allowTransparency = this._terminal.options.allowTransparency;
|
||||
this._runOperation(l => l.onOptionsChanged(this._terminal));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@ import LRUMap from './LRUMap';
|
||||
const TEXTURE_WIDTH = 1024;
|
||||
const TEXTURE_HEIGHT = 1024;
|
||||
|
||||
const TRANSPARENT_COLOR = {
|
||||
css: 'rgba(0, 0, 0, 0)',
|
||||
rgba: 0,
|
||||
}
|
||||
|
||||
interface IGlyphCacheValue {
|
||||
index: number;
|
||||
isEmpty: boolean;
|
||||
@@ -137,7 +142,6 @@ export default class DynamicCharAtlas extends BaseCharAtlas {
|
||||
// into a shared function.
|
||||
private _drawToCache(glyph: IGlyphIdentifier, index: number): IGlyphCacheValue {
|
||||
this._tmpCtx.save();
|
||||
// no need to clear _tmpCtx, since we're going to draw a fully opaque background
|
||||
|
||||
// draw the background
|
||||
let backgroundColor = this._config.colors.background;
|
||||
@@ -146,8 +150,25 @@ export default class DynamicCharAtlas extends BaseCharAtlas {
|
||||
} else if (glyph.bg < 256) {
|
||||
backgroundColor = this._config.colors.ansi[glyph.bg];
|
||||
}
|
||||
|
||||
let backgroundIsTransparent = false;
|
||||
if ((backgroundColor.rgba & 0xFF) !== 0xFF) {
|
||||
// The background color has some transparency, so we need to render it as fully transparent
|
||||
// in the atlas. Otherwise we'd end up drawing the transparent background twice around the
|
||||
// anti-aliased edges of the glyph, and it would look too dark.
|
||||
//
|
||||
// This has the side-effect of disabling RGB subpixel antialiasing, but most compositors will
|
||||
// disable that anyways on a partially transparent background for similar reasons.
|
||||
backgroundColor = TRANSPARENT_COLOR;
|
||||
backgroundIsTransparent = true;
|
||||
}
|
||||
|
||||
// Use a 'copy' composite operation to clear any existing glyph out of _tmpCtx, regardless of
|
||||
// transparency in backgroundColor
|
||||
this._tmpCtx.globalCompositeOperation = 'copy';
|
||||
this._tmpCtx.fillStyle = backgroundColor.css;
|
||||
this._tmpCtx.fillRect(0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight);
|
||||
this._tmpCtx.globalCompositeOperation = 'source-over';
|
||||
|
||||
// draw the foreground/glyph
|
||||
this._tmpCtx.font =
|
||||
@@ -179,7 +200,10 @@ export default class DynamicCharAtlas extends BaseCharAtlas {
|
||||
const imageData = this._tmpCtx.getImageData(
|
||||
0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight,
|
||||
);
|
||||
const isEmpty = clearColor(imageData, backgroundColor);
|
||||
let isEmpty = false;
|
||||
if (!backgroundIsTransparent) {
|
||||
isEmpty = clearColor(imageData, backgroundColor);
|
||||
}
|
||||
|
||||
// copy the data from _tmpCanvas to _cacheCanvas
|
||||
const [x, y] = this._toCoordinates(index);
|
||||
|
||||
Reference in New Issue
Block a user