2 * Copyright (c) 2018 The xterm.js authors. All rights reserved.
6 import { IBufferLine } from 'common/Types';
7 import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
8 import { AttributeData } from 'common/buffer/AttributeData';
9 import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from 'common/buffer/Constants';
10 import { CellData } from 'common/buffer/CellData';
11 import { IOptionsService } from 'common/services/Services';
13 export const BOLD_CLASS = 'xterm-bold';
14 export const DIM_CLASS = 'xterm-dim';
15 export const ITALIC_CLASS = 'xterm-italic';
16 export const UNDERLINE_CLASS = 'xterm-underline';
17 export const CURSOR_CLASS = 'xterm-cursor';
18 export const CURSOR_BLINK_CLASS = 'xterm-cursor-blink';
19 export const CURSOR_STYLE_BLOCK_CLASS = 'xterm-cursor-block';
20 export const CURSOR_STYLE_BAR_CLASS = 'xterm-cursor-bar';
21 export const CURSOR_STYLE_UNDERLINE_CLASS = 'xterm-cursor-underline';
23 export class DomRendererRowFactory {
24 private _workCell: CellData = new CellData();
27 private _document: Document,
28 private _optionsService: IOptionsService
32 public createRow(lineData: IBufferLine, isCursorRow: boolean, cursorStyle: string | undefined, cursorX: number, cursorBlink: boolean, cellWidth: number, cols: number): DocumentFragment {
33 const fragment = this._document.createDocumentFragment();
35 // Find the line length first, this prevents the need to output a bunch of
36 // empty cells at the end. This cannot easily be integrated into the main
37 // loop below because of the colCount feature (which can be removed after we
38 // properly support reflow and disallow data to go beyond the right-side of
41 for (let x = Math.min(lineData.length, cols) - 1; x >= 0; x--) {
42 if (lineData.loadCell(x, this._workCell).getCode() !== NULL_CELL_CODE || (isCursorRow && x === cursorX)) {
48 for (let x = 0; x < lineLength; x++) {
49 lineData.loadCell(x, this._workCell);
50 const width = this._workCell.getWidth();
52 // The character to the left is a wide character, drawing is owned by the char at x-1
57 const charElement = this._document.createElement('span');
59 charElement.style.width = `${cellWidth * width}px`;
62 if (isCursorRow && x === cursorX) {
63 charElement.classList.add(CURSOR_CLASS);
66 charElement.classList.add(CURSOR_BLINK_CLASS);
69 switch (cursorStyle) {
71 charElement.classList.add(CURSOR_STYLE_BAR_CLASS);
74 charElement.classList.add(CURSOR_STYLE_UNDERLINE_CLASS);
77 charElement.classList.add(CURSOR_STYLE_BLOCK_CLASS);
82 if (this._workCell.isBold()) {
83 charElement.classList.add(BOLD_CLASS);
86 if (this._workCell.isItalic()) {
87 charElement.classList.add(ITALIC_CLASS);
90 if (this._workCell.isDim()) {
91 charElement.classList.add(DIM_CLASS);
94 if (this._workCell.isUnderline()) {
95 charElement.classList.add(UNDERLINE_CLASS);
98 charElement.textContent = this._workCell.getChars() || WHITESPACE_CELL_CHAR;
100 const swapColor = this._workCell.isInverse();
103 if (this._workCell.isFgRGB()) {
104 let style = charElement.getAttribute('style') || '';
105 style += `${swapColor ? 'background-' : ''}color:rgb(${(AttributeData.toColorRGB(this._workCell.getFgColor())).join(',')});`;
106 charElement.setAttribute('style', style);
107 } else if (this._workCell.isFgPalette()) {
108 let fg = this._workCell.getFgColor();
109 if (this._workCell.isBold() && fg < 8 && !swapColor && this._optionsService.options.drawBoldTextInBrightColors) {
112 charElement.classList.add(`xterm-${swapColor ? 'b' : 'f'}g-${fg}`);
113 } else if (swapColor) {
114 charElement.classList.add(`xterm-bg-${INVERTED_DEFAULT_COLOR}`);
118 if (this._workCell.isBgRGB()) {
119 let style = charElement.getAttribute('style') || '';
120 style += `${swapColor ? '' : 'background-'}color:rgb(${(AttributeData.toColorRGB(this._workCell.getBgColor())).join(',')});`;
121 charElement.setAttribute('style', style);
122 } else if (this._workCell.isBgPalette()) {
123 charElement.classList.add(`xterm-${swapColor ? 'f' : 'b'}g-${this._workCell.getBgColor()}`);
124 } else if (swapColor) {
125 charElement.classList.add(`xterm-fg-${INVERTED_DEFAULT_COLOR}`);
128 fragment.appendChild(charElement);