charWidthReader.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. import { isSafari } from '../../../base/browser/browser.js';
  6. import { EDITOR_FONT_DEFAULTS } from '../../common/config/editorOptions.js';
  7. export class CharWidthRequest {
  8. constructor(chr, type) {
  9. this.chr = chr;
  10. this.type = type;
  11. this.width = 0;
  12. }
  13. fulfill(width) {
  14. this.width = width;
  15. }
  16. }
  17. class DomCharWidthReader {
  18. constructor(bareFontInfo, requests) {
  19. this._bareFontInfo = bareFontInfo;
  20. this._requests = requests;
  21. this._container = null;
  22. this._testElements = null;
  23. }
  24. read() {
  25. // Create a test container with all these test elements
  26. this._createDomElements();
  27. // Add the container to the DOM
  28. document.body.appendChild(this._container);
  29. // Read character widths
  30. this._readFromDomElements();
  31. // Remove the container from the DOM
  32. document.body.removeChild(this._container);
  33. this._container = null;
  34. this._testElements = null;
  35. }
  36. _createDomElements() {
  37. const fontFamily = this._bareFontInfo.getMassagedFontFamily(isSafari ? EDITOR_FONT_DEFAULTS.fontFamily : null);
  38. const container = document.createElement('div');
  39. container.style.position = 'absolute';
  40. container.style.top = '-50000px';
  41. container.style.width = '50000px';
  42. const regularDomNode = document.createElement('div');
  43. regularDomNode.style.fontFamily = fontFamily;
  44. regularDomNode.style.fontWeight = this._bareFontInfo.fontWeight;
  45. regularDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px';
  46. regularDomNode.style.fontFeatureSettings = this._bareFontInfo.fontFeatureSettings;
  47. regularDomNode.style.lineHeight = this._bareFontInfo.lineHeight + 'px';
  48. regularDomNode.style.letterSpacing = this._bareFontInfo.letterSpacing + 'px';
  49. container.appendChild(regularDomNode);
  50. const boldDomNode = document.createElement('div');
  51. boldDomNode.style.fontFamily = fontFamily;
  52. boldDomNode.style.fontWeight = 'bold';
  53. boldDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px';
  54. boldDomNode.style.fontFeatureSettings = this._bareFontInfo.fontFeatureSettings;
  55. boldDomNode.style.lineHeight = this._bareFontInfo.lineHeight + 'px';
  56. boldDomNode.style.letterSpacing = this._bareFontInfo.letterSpacing + 'px';
  57. container.appendChild(boldDomNode);
  58. const italicDomNode = document.createElement('div');
  59. italicDomNode.style.fontFamily = fontFamily;
  60. italicDomNode.style.fontWeight = this._bareFontInfo.fontWeight;
  61. italicDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px';
  62. italicDomNode.style.fontFeatureSettings = this._bareFontInfo.fontFeatureSettings;
  63. italicDomNode.style.lineHeight = this._bareFontInfo.lineHeight + 'px';
  64. italicDomNode.style.letterSpacing = this._bareFontInfo.letterSpacing + 'px';
  65. italicDomNode.style.fontStyle = 'italic';
  66. container.appendChild(italicDomNode);
  67. const testElements = [];
  68. for (const request of this._requests) {
  69. let parent;
  70. if (request.type === 0 /* Regular */) {
  71. parent = regularDomNode;
  72. }
  73. if (request.type === 2 /* Bold */) {
  74. parent = boldDomNode;
  75. }
  76. if (request.type === 1 /* Italic */) {
  77. parent = italicDomNode;
  78. }
  79. parent.appendChild(document.createElement('br'));
  80. const testElement = document.createElement('span');
  81. DomCharWidthReader._render(testElement, request);
  82. parent.appendChild(testElement);
  83. testElements.push(testElement);
  84. }
  85. this._container = container;
  86. this._testElements = testElements;
  87. }
  88. static _render(testElement, request) {
  89. if (request.chr === ' ') {
  90. let htmlString = '\u00a0';
  91. // Repeat character 256 (2^8) times
  92. for (let i = 0; i < 8; i++) {
  93. htmlString += htmlString;
  94. }
  95. testElement.innerText = htmlString;
  96. }
  97. else {
  98. let testString = request.chr;
  99. // Repeat character 256 (2^8) times
  100. for (let i = 0; i < 8; i++) {
  101. testString += testString;
  102. }
  103. testElement.textContent = testString;
  104. }
  105. }
  106. _readFromDomElements() {
  107. for (let i = 0, len = this._requests.length; i < len; i++) {
  108. const request = this._requests[i];
  109. const testElement = this._testElements[i];
  110. request.fulfill(testElement.offsetWidth / 256);
  111. }
  112. }
  113. }
  114. export function readCharWidths(bareFontInfo, requests) {
  115. const reader = new DomCharWidthReader(bareFontInfo, requests);
  116. reader.read();
  117. }