-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1198 from Tyriar/955_worker_refactor
Refactor char atlas to enable generation with worker
- Loading branch information
Showing
11 changed files
with
187 additions
and
147 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/** | ||
* Copyright (c) 2018 The xterm.js authors. All rights reserved. | ||
* @license MIT | ||
*/ | ||
|
||
import { isFirefox } from './utils/Browser'; | ||
import { FontWeight } from './Types'; | ||
|
||
declare const Promise: any; | ||
|
||
export interface IOffscreenCanvas { | ||
width: number; | ||
height: number; | ||
getContext(type: '2d', config?: Canvas2DContextAttributes): CanvasRenderingContext2D; | ||
transferToImageBitmap(): ImageBitmap; | ||
} | ||
|
||
export interface ICharAtlasRequest { | ||
scaledCharWidth: number; | ||
scaledCharHeight: number; | ||
fontSize: number; | ||
fontFamily: string; | ||
fontWeight: FontWeight; | ||
fontWeightBold: FontWeight; | ||
background: string; | ||
foreground: string; | ||
ansiColors: string[]; | ||
devicePixelRatio: number; | ||
} | ||
|
||
export const CHAR_ATLAS_CELL_SPACING = 1; | ||
|
||
/** | ||
* Generates a char atlas. | ||
* @param context The window or worker context. | ||
* @param canvasFactory A function to generate a canvas with a width or height. | ||
* @param request The config for the new char atlas. | ||
*/ | ||
export function generateCharAtlas(context: Window, canvasFactory: (width: number, height: number) => HTMLCanvasElement | IOffscreenCanvas, request: ICharAtlasRequest): HTMLCanvasElement | Promise<ImageBitmap> { | ||
const cellWidth = request.scaledCharWidth + CHAR_ATLAS_CELL_SPACING; | ||
const cellHeight = request.scaledCharHeight + CHAR_ATLAS_CELL_SPACING; | ||
const canvas = canvasFactory( | ||
/*255 ascii chars*/255 * cellWidth, | ||
(/*default+default bold*/2 + /*0-15*/16) * cellHeight | ||
); | ||
const ctx = canvas.getContext('2d', {alpha: false}); | ||
|
||
ctx.fillStyle = request.background; | ||
ctx.fillRect(0, 0, canvas.width, canvas.height); | ||
|
||
ctx.save(); | ||
ctx.fillStyle = request.foreground; | ||
ctx.font = getFont(request.fontWeight, request); | ||
ctx.textBaseline = 'top'; | ||
|
||
// Default color | ||
for (let i = 0; i < 256; i++) { | ||
ctx.save(); | ||
ctx.beginPath(); | ||
ctx.rect(i * cellWidth, 0, cellWidth, cellHeight); | ||
ctx.clip(); | ||
ctx.fillText(String.fromCharCode(i), i * cellWidth, 0); | ||
ctx.restore(); | ||
} | ||
// Default color bold | ||
ctx.save(); | ||
ctx.font = getFont(request.fontWeightBold, request); | ||
for (let i = 0; i < 256; i++) { | ||
ctx.save(); | ||
ctx.beginPath(); | ||
ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight); | ||
ctx.clip(); | ||
ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight); | ||
ctx.restore(); | ||
} | ||
ctx.restore(); | ||
|
||
// Colors 0-15 | ||
ctx.font = getFont(request.fontWeight, request); | ||
for (let colorIndex = 0; colorIndex < 16; colorIndex++) { | ||
// colors 8-15 are bold | ||
if (colorIndex === 8) { | ||
ctx.font = getFont(request.fontWeightBold, request); | ||
} | ||
const y = (colorIndex + 2) * cellHeight; | ||
// Draw ascii characters | ||
for (let i = 0; i < 256; i++) { | ||
ctx.save(); | ||
ctx.beginPath(); | ||
ctx.rect(i * cellWidth, y, cellWidth, cellHeight); | ||
ctx.clip(); | ||
ctx.fillStyle = request.ansiColors[colorIndex]; | ||
ctx.fillText(String.fromCharCode(i), i * cellWidth, y); | ||
ctx.restore(); | ||
} | ||
} | ||
ctx.restore(); | ||
|
||
// Support is patchy for createImageBitmap at the moment, pass a canvas back | ||
// if support is lacking as drawImage works there too. Firefox is also | ||
// included here as ImageBitmap appears both buggy and has horrible | ||
// performance (tested on v55). | ||
if (!('createImageBitmap' in context) || isFirefox) { | ||
// Don't attempt to clear background colors if createImageBitmap is not supported | ||
if (canvas instanceof HTMLCanvasElement) { | ||
// Just return the HTMLCanvas if it's a HTMLCanvasElement | ||
return canvas; | ||
} else { | ||
// Transfer to an ImageBitmap is this is an OffscreenCanvas | ||
return new Promise(r => r(canvas.transferToImageBitmap())); | ||
} | ||
} | ||
|
||
const charAtlasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height); | ||
|
||
// Remove the background color from the image so characters may overlap | ||
const r = parseInt(request.background.substr(1, 2), 16); | ||
const g = parseInt(request.background.substr(3, 2), 16); | ||
const b = parseInt(request.background.substr(5, 2), 16); | ||
clearColor(charAtlasImageData, r, g, b); | ||
|
||
return context.createImageBitmap(charAtlasImageData); | ||
} | ||
|
||
/** | ||
* Makes a partiicular rgb color in an ImageData completely transparent. | ||
*/ | ||
function clearColor(imageData: ImageData, r: number, g: number, b: number): void { | ||
for (let offset = 0; offset < imageData.data.length; offset += 4) { | ||
if (imageData.data[offset] === r && | ||
imageData.data[offset + 1] === g && | ||
imageData.data[offset + 2] === b) { | ||
imageData.data[offset + 3] = 0; | ||
} | ||
} | ||
} | ||
|
||
function getFont(fontWeight: FontWeight, request: ICharAtlasRequest): string { | ||
return `${fontWeight} ${request.fontSize * request.devicePixelRatio}px ${request.fontFamily}`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/** | ||
* Copyright (c) 2018 The xterm.js authors. All rights reserved. | ||
* @license MIT | ||
*/ | ||
|
||
export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.