-*gui.txt* For Vim version 9.2. Last change: 2026 Feb 14
+*gui.txt* For Vim version 9.2. Last change: 2026 Apr 07
VIM REFERENCE MANUAL by Bram Moolenaar
NONANTIALIASED, CLEARTYPE and DEFAULT. Normally you would use
"qDEFAULT".
Some quality values are not supported in legacy OSs.
+ fXX - OpenType font feature. Specify a single feature as
+ tag=value, where tag is a 4-character OpenType feature
+ tag and value is the parameter (0 to disable, 1 or
+ higher to enable/select variant). Multiple features
+ can be specified by repeating the ":f" option.
+ This only takes effect when 'renderoptions' is set to use
+ DirectWrite (type:directx). Default features (calt, liga,
+ etc.) are preserved unless explicitly overridden.
+ Example: ":fss19=1:fcalt=0" enables Stylistic Set 19
+ and disables Contextual Alternates.
- A '_' can be used in the place of a space, so you don't need to use
backslashes to escape the spaces.
Examples: >
:set guifont=courier_new:h12:w5:b:cRUSSIAN
:set guifont=Andale_Mono:h7.5:w4.5
+ :set guifont=Cascadia_Code:h14:fss19=1:fcalt=1:fliga=1
See also |font-sizes|.
D2D1_TEXT_ANTIALIAS_MODE mTextAntialiasMode;
+ DWriteFontFeature mFontFeatures[DWRITE_MAX_FONT_FEATURES];
+ int mFontFeatureCount;
+
// METHODS
DWriteContext();
DWriteRenderingParams *GetRenderingParams(
DWriteRenderingParams *params);
+
+ void SetFontFeatures(const DWriteFontFeature *features, int count);
};
class AdjustedGlyphRun : public DWRITE_GLYPH_RUN
mFontStyle(DWRITE_FONT_STYLE_NORMAL),
mFontSize(0.0f),
mFontAscent(0.0f),
- mTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
+ mTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_DEFAULT),
+ mFontFeatureCount(0)
{
+ ZeroMemory(mFontFeatures, sizeof(mFontFeatures));
HRESULT hr;
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
textLayout->SetFontWeight(mFontWeight, textRange);
textLayout->SetFontStyle(mFontStyle, textRange);
+ if (mFontFeatureCount > 0)
+ {
+ // Default OpenType features that DirectWrite normally enables.
+ // SetTypography() overrides all defaults, so we must
+ // re-add them here explicitly.
+ static const DWRITE_FONT_FEATURE defaultFeatures[] = {
+ { DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_ALTERNATES, 1 },
+ { DWRITE_FONT_FEATURE_TAG_STANDARD_LIGATURES, 1 },
+ { DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_LIGATURES, 1 },
+ { DWRITE_FONT_FEATURE_TAG_REQUIRED_LIGATURES, 1 },
+ { DWRITE_FONT_FEATURE_TAG_KERNING, 1 },
+ };
+ static const int numDefaults = sizeof(defaultFeatures)
+ / sizeof(defaultFeatures[0]);
+
+ IDWriteTypography *typography = NULL;
+ hr = mDWriteFactory->CreateTypography(&typography);
+ if (SUCCEEDED(hr))
+ {
+ // Add default features, skipping any that the user
+ // has explicitly specified (either + or -).
+ for (int d = 0; d < numDefaults; ++d)
+ {
+ int overridden = 0;
+ for (int u = 0; u < mFontFeatureCount; ++u)
+ {
+ if ((DWRITE_FONT_FEATURE_TAG)mFontFeatures[u].tag
+ == defaultFeatures[d].nameTag)
+ {
+ overridden = 1;
+ break;
+ }
+ }
+ if (!overridden)
+ typography->AddFontFeature(defaultFeatures[d]);
+ }
+ // Add user-specified features.
+ for (int i = 0; i < mFontFeatureCount; ++i)
+ {
+ DWRITE_FONT_FEATURE ff = {
+ (DWRITE_FONT_FEATURE_TAG)mFontFeatures[i].tag,
+ mFontFeatures[i].parameter
+ };
+ typography->AddFontFeature(ff);
+ }
+ textLayout->SetTypography(typography, textRange);
+ SafeRelease(&typography);
+ }
+ }
+
// Calculate baseline using font ascent from font metrics.
// Do NOT use GetLineMetrics() because it returns different values
// depending on text content (e.g., when CJK characters trigger
else
return NULL;
}
+
+ void
+DWriteContext::SetFontFeatures(
+ const DWriteFontFeature *features, int count)
+{
+ if (count > DWRITE_MAX_FONT_FEATURES)
+ count = DWRITE_MAX_FONT_FEATURES;
+ mFontFeatureCount = count;
+ if (count > 0 && features != NULL)
+ memcpy(mFontFeatures, features, sizeof(DWriteFontFeature) * count);
+}
+
+ void
+DWriteContext_SetFontFeatures(
+ DWriteContext *ctx,
+ const DWriteFontFeature *features,
+ int count)
+{
+ if (ctx != NULL)
+ ctx->SetFontFeatures(features, count);
+}
int dx_geom = 0;
int dx_renmode = 0;
int dx_taamode = 0;
-
// parse string as rendering options.
for (p = s; p != NULL && *p != NUL; )
{
if (font == NOFONT)
return FAIL;
+#if defined(FEAT_DIRECTX)
+ // Parse font features from guifont (e.g., ":fss19=1:fcalt=0:fliga=1").
+ {
+ DWriteFontFeature features[DWRITE_MAX_FONT_FEATURES];
+ int feat_count = 0;
+ char_u *fp;
+
+ if (font_name != NULL)
+ {
+ // Find each ":f" option in font_name.
+ for (fp = font_name; *fp != NUL; fp++)
+ {
+ if (*fp == ':' && *(fp + 1) == 'f')
+ {
+ char_u tag[5];
+ int ti = 0;
+ unsigned int param = 1;
+
+ fp += 2; // skip ":f"
+ while (*fp != NUL && *fp != '=' && *fp != ':'
+ && ti < 4)
+ tag[ti++] = *fp++;
+ tag[ti] = NUL;
+
+ if (ti != 4)
+ continue; // invalid tag length
+
+ if (*fp == '=')
+ {
+ fp++;
+ param = (unsigned int)atoi((char *)fp);
+ while (*fp >= '0' && *fp <= '9')
+ fp++;
+ }
+
+ if (feat_count < DWRITE_MAX_FONT_FEATURES)
+ {
+ features[feat_count].tag =
+ ((unsigned int)tag[0])
+ | ((unsigned int)tag[1] << 8)
+ | ((unsigned int)tag[2] << 16)
+ | ((unsigned int)tag[3] << 24);
+ features[feat_count].parameter = param;
+ feat_count++;
+ }
+
+ fp--; // adjust for loop increment
+ }
+ }
+ }
+ DWriteContext_SetFontFeatures(s_dwc, features, feat_count);
+ }
+#endif
+
if (font_name == NULL)
font_name = (char_u *)"";
#ifdef FEAT_MBYTE_IME