Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/browser/config/charWidthReader.ts
3294 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { applyFontInfo } from './domFontInfo.js';
7
import { BareFontInfo } from '../../common/config/fontInfo.js';
8
9
export const enum CharWidthRequestType {
10
Regular = 0,
11
Italic = 1,
12
Bold = 2
13
}
14
15
export class CharWidthRequest {
16
17
public readonly chr: string;
18
public readonly type: CharWidthRequestType;
19
public width: number;
20
21
constructor(chr: string, type: CharWidthRequestType) {
22
this.chr = chr;
23
this.type = type;
24
this.width = 0;
25
}
26
27
public fulfill(width: number) {
28
this.width = width;
29
}
30
}
31
32
class DomCharWidthReader {
33
34
private readonly _bareFontInfo: BareFontInfo;
35
private readonly _requests: CharWidthRequest[];
36
37
private _container: HTMLElement | null;
38
private _testElements: HTMLSpanElement[] | null;
39
40
constructor(bareFontInfo: BareFontInfo, requests: CharWidthRequest[]) {
41
this._bareFontInfo = bareFontInfo;
42
this._requests = requests;
43
44
this._container = null;
45
this._testElements = null;
46
}
47
48
public read(targetWindow: Window): void {
49
// Create a test container with all these test elements
50
this._createDomElements();
51
52
// Add the container to the DOM
53
targetWindow.document.body.appendChild(this._container!);
54
55
// Read character widths
56
this._readFromDomElements();
57
58
// Remove the container from the DOM
59
this._container?.remove();
60
61
this._container = null;
62
this._testElements = null;
63
}
64
65
private _createDomElements(): void {
66
const container = document.createElement('div');
67
container.style.position = 'absolute';
68
container.style.top = '-50000px';
69
container.style.width = '50000px';
70
71
const regularDomNode = document.createElement('div');
72
applyFontInfo(regularDomNode, this._bareFontInfo);
73
container.appendChild(regularDomNode);
74
75
const boldDomNode = document.createElement('div');
76
applyFontInfo(boldDomNode, this._bareFontInfo);
77
boldDomNode.style.fontWeight = 'bold';
78
container.appendChild(boldDomNode);
79
80
const italicDomNode = document.createElement('div');
81
applyFontInfo(italicDomNode, this._bareFontInfo);
82
italicDomNode.style.fontStyle = 'italic';
83
container.appendChild(italicDomNode);
84
85
const testElements: HTMLSpanElement[] = [];
86
for (const request of this._requests) {
87
88
let parent: HTMLElement;
89
if (request.type === CharWidthRequestType.Regular) {
90
parent = regularDomNode;
91
}
92
if (request.type === CharWidthRequestType.Bold) {
93
parent = boldDomNode;
94
}
95
if (request.type === CharWidthRequestType.Italic) {
96
parent = italicDomNode;
97
}
98
99
parent!.appendChild(document.createElement('br'));
100
101
const testElement = document.createElement('span');
102
DomCharWidthReader._render(testElement, request);
103
parent!.appendChild(testElement);
104
105
testElements.push(testElement);
106
}
107
108
this._container = container;
109
this._testElements = testElements;
110
}
111
112
private static _render(testElement: HTMLElement, request: CharWidthRequest): void {
113
if (request.chr === ' ') {
114
let htmlString = '\u00a0';
115
// Repeat character 256 (2^8) times
116
for (let i = 0; i < 8; i++) {
117
htmlString += htmlString;
118
}
119
testElement.innerText = htmlString;
120
} else {
121
let testString = request.chr;
122
// Repeat character 256 (2^8) times
123
for (let i = 0; i < 8; i++) {
124
testString += testString;
125
}
126
testElement.textContent = testString;
127
}
128
}
129
130
private _readFromDomElements(): void {
131
for (let i = 0, len = this._requests.length; i < len; i++) {
132
const request = this._requests[i];
133
const testElement = this._testElements![i];
134
135
request.fulfill(testElement.offsetWidth / 256);
136
}
137
}
138
}
139
140
export function readCharWidths(targetWindow: Window, bareFontInfo: BareFontInfo, requests: CharWidthRequest[]): void {
141
const reader = new DomCharWidthReader(bareFontInfo, requests);
142
reader.read(targetWindow);
143
}
144
145