diff --git a/src/vs/editor/browser/gpu/css/decorationStyleCache.ts b/src/vs/editor/browser/gpu/css/decorationStyleCache.ts index 5e023e8407843..879b72470f14b 100644 --- a/src/vs/editor/browser/gpu/css/decorationStyleCache.ts +++ b/src/vs/editor/browser/gpu/css/decorationStyleCache.ts @@ -12,6 +12,10 @@ export interface IDecorationStyleSet { * Whether the text should be rendered in bold. */ bold: boolean | undefined; + /** + * A number between 0 and 1 representing the opacity of the text. + */ + opacity: number | undefined; } export interface IDecorationStyleCacheEntry extends IDecorationStyleSet { @@ -27,8 +31,12 @@ export class DecorationStyleCache { private readonly _cache = new Map(); - getOrCreateEntry(color: number | undefined, bold: boolean | undefined): number { - if (color === undefined && bold === undefined) { + getOrCreateEntry( + color: number | undefined, + bold: boolean | undefined, + opacity: number | undefined + ): number { + if (color === undefined && bold === undefined && opacity === undefined) { return 0; } const id = this._nextId++; @@ -36,6 +44,7 @@ export class DecorationStyleCache { id, color, bold, + opacity, }; this._cache.set(id, entry); return id; diff --git a/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts b/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts index fa696796d1d4a..ccf57a7f4070e 100644 --- a/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts +++ b/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts @@ -258,6 +258,7 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend let decorationStyleSetBold: boolean | undefined; let decorationStyleSetColor: number | undefined; + let decorationStyleSetOpacity: number | undefined; let lineData: ViewLineRenderingData; let decoration: InlineDecoration; @@ -363,6 +364,7 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend chars = content.charAt(x); decorationStyleSetColor = undefined; decorationStyleSetBold = undefined; + decorationStyleSetOpacity = undefined; // Apply supported inline decoration styles to the cell metadata for (decoration of lineData.inlineDecorations) { @@ -402,6 +404,11 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend } break; } + case 'opacity': { + const parsedValue = parseCssOpacity(value); + decorationStyleSetOpacity = parsedValue; + break; + } default: throw new BugIndicatingError('Unexpected inline decoration style'); } } @@ -419,7 +426,7 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend continue; } - const decorationStyleSetId = ViewGpuContext.decorationStyleCache.getOrCreateEntry(decorationStyleSetColor, decorationStyleSetBold); + const decorationStyleSetId = ViewGpuContext.decorationStyleCache.getOrCreateEntry(decorationStyleSetColor, decorationStyleSetBold, decorationStyleSetOpacity); glyph = this._viewGpuContext.atlas.getGlyph(this._glyphRasterizer.value, chars, tokenMetadata, decorationStyleSetId); // TODO: Support non-standard character widths @@ -511,3 +518,13 @@ function parseCssFontWeight(value: string) { } return parseInt(value); } + +function parseCssOpacity(value: string): number { + if (value.endsWith('%')) { + return parseFloat(value.substring(0, value.length - 1)) / 100; + } + if (value.match(/^\d+(?:\.\d*)/)) { + return parseFloat(value); + } + return 1; +} diff --git a/src/vs/editor/browser/gpu/raster/glyphRasterizer.ts b/src/vs/editor/browser/gpu/raster/glyphRasterizer.ts index 0375d305f1556..d7f39647d82ae 100644 --- a/src/vs/editor/browser/gpu/raster/glyphRasterizer.ts +++ b/src/vs/editor/browser/gpu/raster/glyphRasterizer.ts @@ -106,6 +106,8 @@ export class GlyphRasterizer extends Disposable implements IGlyphRasterizer { this._canvas.height = canvasDim; } + this._ctx.save(); + const decorationStyleSet = ViewGpuContext.decorationStyleCache.getStyleSet(decorationStyleSetId); // TODO: Support workbench.fontAliasing @@ -139,7 +141,12 @@ export class GlyphRasterizer extends Disposable implements IGlyphRasterizer { } this._ctx.textBaseline = 'top'; + if (decorationStyleSet?.opacity !== undefined) { + this._ctx.globalAlpha = decorationStyleSet.opacity; + } + this._ctx.fillText(chars, originX, originY); + this._ctx.restore(); const imageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height); this._findGlyphBoundingBox(imageData, this._workGlyph.boundingBox); diff --git a/src/vs/editor/browser/gpu/viewGpuContext.ts b/src/vs/editor/browser/gpu/viewGpuContext.ts index 7c0985a376b23..f33b9ee6fa11a 100644 --- a/src/vs/editor/browser/gpu/viewGpuContext.ts +++ b/src/vs/editor/browser/gpu/viewGpuContext.ts @@ -268,6 +268,7 @@ export class ViewGpuContext extends Disposable { const gpuSupportedDecorationCssRules = [ 'color', 'font-weight', + 'opacity', ]; function supportsCssRule(rule: string, style: CSSStyleDeclaration) {