Path: blob/main/src/vs/editor/common/config/fontInfo.ts
3295 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 { EditorFontVariations, EditorOptions, EditorOption, FindComputedEditorOptionValueById, EDITOR_FONT_DEFAULTS } 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 createFromValidatedSettings(options: IValidatedEditorOptions, pixelRatio: number, ignoreEditorZoom: boolean): BareFontInfo {34const fontFamily = options.get(EditorOption.fontFamily);35const fontWeight = options.get(EditorOption.fontWeight);36const fontSize = options.get(EditorOption.fontSize);37const fontFeatureSettings = options.get(EditorOption.fontLigatures);38const fontVariationSettings = options.get(EditorOption.fontVariations);39const lineHeight = options.get(EditorOption.lineHeight);40const letterSpacing = options.get(EditorOption.letterSpacing);41return BareFontInfo._create(fontFamily, fontWeight, fontSize, fontFeatureSettings, fontVariationSettings, lineHeight, letterSpacing, pixelRatio, ignoreEditorZoom);42}4344/**45* @internal46*/47public static createFromRawSettings(opts: { fontFamily?: string; fontWeight?: string; fontSize?: number; fontLigatures?: boolean | string; fontVariations?: boolean | string; lineHeight?: number; letterSpacing?: number }, pixelRatio: number, ignoreEditorZoom: boolean = false): BareFontInfo {48const fontFamily = EditorOptions.fontFamily.validate(opts.fontFamily);49const fontWeight = EditorOptions.fontWeight.validate(opts.fontWeight);50const fontSize = EditorOptions.fontSize.validate(opts.fontSize);51const fontFeatureSettings = EditorOptions.fontLigatures2.validate(opts.fontLigatures);52const fontVariationSettings = EditorOptions.fontVariations.validate(opts.fontVariations);53const lineHeight = EditorOptions.lineHeight.validate(opts.lineHeight);54const letterSpacing = EditorOptions.letterSpacing.validate(opts.letterSpacing);55return BareFontInfo._create(fontFamily, fontWeight, fontSize, fontFeatureSettings, fontVariationSettings, lineHeight, letterSpacing, pixelRatio, ignoreEditorZoom);56}5758/**59* @internal60*/61private static _create(fontFamily: string, fontWeight: string, fontSize: number, fontFeatureSettings: string, fontVariationSettings: string, lineHeight: number, letterSpacing: number, pixelRatio: number, ignoreEditorZoom: boolean): BareFontInfo {62if (lineHeight === 0) {63lineHeight = GOLDEN_LINE_HEIGHT_RATIO * fontSize;64} else if (lineHeight < MINIMUM_LINE_HEIGHT) {65// Values too small to be line heights in pixels are in ems.66lineHeight = lineHeight * fontSize;67}6869// Enforce integer, minimum constraints70lineHeight = Math.round(lineHeight);71if (lineHeight < MINIMUM_LINE_HEIGHT) {72lineHeight = MINIMUM_LINE_HEIGHT;73}7475const editorZoomLevelMultiplier = 1 + (ignoreEditorZoom ? 0 : EditorZoom.getZoomLevel() * 0.1);76fontSize *= editorZoomLevelMultiplier;77lineHeight *= editorZoomLevelMultiplier;7879if (fontVariationSettings === EditorFontVariations.TRANSLATE) {80if (fontWeight === 'normal' || fontWeight === 'bold') {81fontVariationSettings = EditorFontVariations.OFF;82} else {83const fontWeightAsNumber = parseInt(fontWeight, 10);84fontVariationSettings = `'wght' ${fontWeightAsNumber}`;85fontWeight = 'normal';86}87}8889return new BareFontInfo({90pixelRatio: pixelRatio,91fontFamily: fontFamily,92fontWeight: fontWeight,93fontSize: fontSize,94fontFeatureSettings: fontFeatureSettings,95fontVariationSettings,96lineHeight: lineHeight,97letterSpacing: letterSpacing98});99}100101readonly pixelRatio: number;102readonly fontFamily: string;103readonly fontWeight: string;104readonly fontSize: number;105readonly fontFeatureSettings: string;106readonly fontVariationSettings: string;107readonly lineHeight: number;108readonly letterSpacing: number;109110/**111* @internal112*/113protected constructor(opts: {114pixelRatio: number;115fontFamily: string;116fontWeight: string;117fontSize: number;118fontFeatureSettings: string;119fontVariationSettings: string;120lineHeight: number;121letterSpacing: number;122}) {123this.pixelRatio = opts.pixelRatio;124this.fontFamily = String(opts.fontFamily);125this.fontWeight = String(opts.fontWeight);126this.fontSize = opts.fontSize;127this.fontFeatureSettings = opts.fontFeatureSettings;128this.fontVariationSettings = opts.fontVariationSettings;129this.lineHeight = opts.lineHeight | 0;130this.letterSpacing = opts.letterSpacing;131}132133/**134* @internal135*/136public getId(): string {137return `${this.pixelRatio}-${this.fontFamily}-${this.fontWeight}-${this.fontSize}-${this.fontFeatureSettings}-${this.fontVariationSettings}-${this.lineHeight}-${this.letterSpacing}`;138}139140/**141* @internal142*/143public getMassagedFontFamily(): string {144const fallbackFontFamily = EDITOR_FONT_DEFAULTS.fontFamily;145const fontFamily = BareFontInfo._wrapInQuotes(this.fontFamily);146if (fallbackFontFamily && this.fontFamily !== fallbackFontFamily) {147return `${fontFamily}, ${fallbackFontFamily}`;148}149return fontFamily;150}151152private static _wrapInQuotes(fontFamily: string): string {153if (/[,"']/.test(fontFamily)) {154// Looks like the font family might be already escaped155return fontFamily;156}157if (/[+ ]/.test(fontFamily)) {158// Wrap a font family using + or <space> with quotes159return `"${fontFamily}"`;160}161return fontFamily;162}163}164165// change this whenever `FontInfo` members are changed166export const SERIALIZED_FONT_INFO_VERSION = 2;167168export class FontInfo extends BareFontInfo {169readonly _editorStylingBrand: void = undefined;170171readonly version: number = SERIALIZED_FONT_INFO_VERSION;172readonly isTrusted: boolean;173readonly isMonospace: boolean;174readonly typicalHalfwidthCharacterWidth: number;175readonly typicalFullwidthCharacterWidth: number;176readonly canUseHalfwidthRightwardsArrow: boolean;177readonly spaceWidth: number;178readonly middotWidth: number;179readonly wsmiddotWidth: number;180readonly maxDigitWidth: number;181182/**183* @internal184*/185constructor(opts: {186pixelRatio: number;187fontFamily: string;188fontWeight: string;189fontSize: number;190fontFeatureSettings: string;191fontVariationSettings: string;192lineHeight: number;193letterSpacing: number;194isMonospace: boolean;195typicalHalfwidthCharacterWidth: number;196typicalFullwidthCharacterWidth: number;197canUseHalfwidthRightwardsArrow: boolean;198spaceWidth: number;199middotWidth: number;200wsmiddotWidth: number;201maxDigitWidth: number;202}, isTrusted: boolean) {203super(opts);204this.isTrusted = isTrusted;205this.isMonospace = opts.isMonospace;206this.typicalHalfwidthCharacterWidth = opts.typicalHalfwidthCharacterWidth;207this.typicalFullwidthCharacterWidth = opts.typicalFullwidthCharacterWidth;208this.canUseHalfwidthRightwardsArrow = opts.canUseHalfwidthRightwardsArrow;209this.spaceWidth = opts.spaceWidth;210this.middotWidth = opts.middotWidth;211this.wsmiddotWidth = opts.wsmiddotWidth;212this.maxDigitWidth = opts.maxDigitWidth;213}214215/**216* @internal217*/218public equals(other: FontInfo): boolean {219return (220this.fontFamily === other.fontFamily221&& this.fontWeight === other.fontWeight222&& this.fontSize === other.fontSize223&& this.fontFeatureSettings === other.fontFeatureSettings224&& this.fontVariationSettings === other.fontVariationSettings225&& this.lineHeight === other.lineHeight226&& this.letterSpacing === other.letterSpacing227&& this.typicalHalfwidthCharacterWidth === other.typicalHalfwidthCharacterWidth228&& this.typicalFullwidthCharacterWidth === other.typicalFullwidthCharacterWidth229&& this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow230&& this.spaceWidth === other.spaceWidth231&& this.middotWidth === other.middotWidth232&& this.wsmiddotWidth === other.wsmiddotWidth233&& this.maxDigitWidth === other.maxDigitWidth234);235}236}237238239