Path: blob/main/src/vs/editor/common/config/fontInfo.ts
5272 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as platform from '../../../base/common/platform.js';6import { EditorOption, FindComputedEditorOptionValueById } from './editorOptions.js';7import { EditorZoom } from './editorZoom.js';89/**10* Determined from empirical observations.11* @internal12*/13export const GOLDEN_LINE_HEIGHT_RATIO = platform.isMacintosh ? 1.5 : 1.35;1415/**16* @internal17*/18export const MINIMUM_LINE_HEIGHT = 8;1920/**21* @internal22*/23export interface IValidatedEditorOptions {24get<T extends EditorOption>(id: T): FindComputedEditorOptionValueById<T>;25}2627export class BareFontInfo {28readonly _bareFontInfoBrand: void = undefined;2930/**31* @internal32*/33public static _create(fontFamily: string, fontWeight: string, fontSize: number, fontFeatureSettings: string, fontVariationSettings: string, lineHeight: number, letterSpacing: number, pixelRatio: number, ignoreEditorZoom: boolean): BareFontInfo {34if (lineHeight === 0) {35lineHeight = GOLDEN_LINE_HEIGHT_RATIO * fontSize;36} else if (lineHeight < MINIMUM_LINE_HEIGHT) {37// Values too small to be line heights in pixels are in ems.38lineHeight = lineHeight * fontSize;39}4041// Enforce integer, minimum constraints42lineHeight = Math.round(lineHeight);43if (lineHeight < MINIMUM_LINE_HEIGHT) {44lineHeight = MINIMUM_LINE_HEIGHT;45}4647const editorZoomLevelMultiplier = 1 + (ignoreEditorZoom ? 0 : EditorZoom.getZoomLevel() * 0.1);48fontSize *= editorZoomLevelMultiplier;49lineHeight *= editorZoomLevelMultiplier;5051if (fontVariationSettings === FONT_VARIATION_TRANSLATE) {52if (fontWeight === 'normal' || fontWeight === 'bold') {53fontVariationSettings = FONT_VARIATION_OFF;54} else {55const fontWeightAsNumber = parseInt(fontWeight, 10);56fontVariationSettings = `'wght' ${fontWeightAsNumber}`;57fontWeight = 'normal';58}59}6061return new BareFontInfo({62pixelRatio: pixelRatio,63fontFamily: fontFamily,64fontWeight: fontWeight,65fontSize: fontSize,66fontFeatureSettings: fontFeatureSettings,67fontVariationSettings,68lineHeight: lineHeight,69letterSpacing: letterSpacing70});71}7273readonly pixelRatio: number;74readonly fontFamily: string;75readonly fontWeight: string;76readonly fontSize: number;77readonly fontFeatureSettings: string;78readonly fontVariationSettings: string;79readonly lineHeight: number;80readonly letterSpacing: number;8182/**83* @internal84*/85protected constructor(opts: {86pixelRatio: number;87fontFamily: string;88fontWeight: string;89fontSize: number;90fontFeatureSettings: string;91fontVariationSettings: string;92lineHeight: number;93letterSpacing: number;94}) {95this.pixelRatio = opts.pixelRatio;96this.fontFamily = String(opts.fontFamily);97this.fontWeight = String(opts.fontWeight);98this.fontSize = opts.fontSize;99this.fontFeatureSettings = opts.fontFeatureSettings;100this.fontVariationSettings = opts.fontVariationSettings;101this.lineHeight = opts.lineHeight | 0;102this.letterSpacing = opts.letterSpacing;103}104105/**106* @internal107*/108public getId(): string {109return `${this.pixelRatio}-${this.fontFamily}-${this.fontWeight}-${this.fontSize}-${this.fontFeatureSettings}-${this.fontVariationSettings}-${this.lineHeight}-${this.letterSpacing}`;110}111112/**113* @internal114*/115public getMassagedFontFamily(): string {116const fallbackFontFamily = EDITOR_FONT_DEFAULTS.fontFamily;117const fontFamily = BareFontInfo._wrapInQuotes(this.fontFamily);118if (fallbackFontFamily && this.fontFamily !== fallbackFontFamily) {119return `${fontFamily}, ${fallbackFontFamily}`;120}121return fontFamily;122}123124private static _wrapInQuotes(fontFamily: string): string {125if (/[,"']/.test(fontFamily)) {126// Looks like the font family might be already escaped127return fontFamily;128}129if (/[+ ]/.test(fontFamily)) {130// Wrap a font family using + or <space> with quotes131return `"${fontFamily}"`;132}133return fontFamily;134}135}136137// change this whenever `FontInfo` members are changed138export const SERIALIZED_FONT_INFO_VERSION = 2;139140export class FontInfo extends BareFontInfo {141readonly _editorStylingBrand: void = undefined;142143readonly version: number = SERIALIZED_FONT_INFO_VERSION;144readonly isTrusted: boolean;145readonly isMonospace: boolean;146readonly typicalHalfwidthCharacterWidth: number;147readonly typicalFullwidthCharacterWidth: number;148readonly canUseHalfwidthRightwardsArrow: boolean;149readonly spaceWidth: number;150readonly middotWidth: number;151readonly wsmiddotWidth: number;152readonly maxDigitWidth: number;153154/**155* @internal156*/157constructor(opts: {158pixelRatio: number;159fontFamily: string;160fontWeight: string;161fontSize: number;162fontFeatureSettings: string;163fontVariationSettings: string;164lineHeight: number;165letterSpacing: number;166isMonospace: boolean;167typicalHalfwidthCharacterWidth: number;168typicalFullwidthCharacterWidth: number;169canUseHalfwidthRightwardsArrow: boolean;170spaceWidth: number;171middotWidth: number;172wsmiddotWidth: number;173maxDigitWidth: number;174}, isTrusted: boolean) {175super(opts);176this.isTrusted = isTrusted;177this.isMonospace = opts.isMonospace;178this.typicalHalfwidthCharacterWidth = opts.typicalHalfwidthCharacterWidth;179this.typicalFullwidthCharacterWidth = opts.typicalFullwidthCharacterWidth;180this.canUseHalfwidthRightwardsArrow = opts.canUseHalfwidthRightwardsArrow;181this.spaceWidth = opts.spaceWidth;182this.middotWidth = opts.middotWidth;183this.wsmiddotWidth = opts.wsmiddotWidth;184this.maxDigitWidth = opts.maxDigitWidth;185}186187/**188* @internal189*/190public equals(other: FontInfo): boolean {191return (192this.fontFamily === other.fontFamily193&& this.fontWeight === other.fontWeight194&& this.fontSize === other.fontSize195&& this.fontFeatureSettings === other.fontFeatureSettings196&& this.fontVariationSettings === other.fontVariationSettings197&& this.lineHeight === other.lineHeight198&& this.letterSpacing === other.letterSpacing199&& this.typicalHalfwidthCharacterWidth === other.typicalHalfwidthCharacterWidth200&& this.typicalFullwidthCharacterWidth === other.typicalFullwidthCharacterWidth201&& this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow202&& this.spaceWidth === other.spaceWidth203&& this.middotWidth === other.middotWidth204&& this.wsmiddotWidth === other.wsmiddotWidth205&& this.maxDigitWidth === other.maxDigitWidth206);207}208}209/**210* @internal211*/212export const FONT_VARIATION_OFF = 'normal';213/**214* @internal215*/216export const FONT_VARIATION_TRANSLATE = 'translate';217218/**219* @internal220*/221export const DEFAULT_WINDOWS_FONT_FAMILY = 'Consolas, \'Courier New\', monospace';222/**223* @internal224*/225export const DEFAULT_MAC_FONT_FAMILY = 'Menlo, Monaco, \'Courier New\', monospace';226/**227* @internal228*/229export const DEFAULT_LINUX_FONT_FAMILY = '\'Droid Sans Mono\', monospace';230/**231* @internal232*/233export const EDITOR_FONT_DEFAULTS = {234fontFamily: (235platform.isMacintosh ? DEFAULT_MAC_FONT_FAMILY : (platform.isWindows ? DEFAULT_WINDOWS_FONT_FAMILY : DEFAULT_LINUX_FONT_FAMILY)236),237fontWeight: 'normal',238fontSize: (239platform.isMacintosh ? 12 : 14240),241lineHeight: 0,242letterSpacing: 0,243};244245246