mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-05-28 00:21:57 +02:00
patch 9.2.0321: MS-Windows: No OpenType font support
Problem: MS-Windows: No OpenType font support
Solution: Allow specifying OpenType font features directly in 'guifont'
(Yasuhiro Matsumoto).
Allow specifying OpenType font features directly in 'guifont' using
the ':f' option (e.g., :set guifont=Cascadia_Code:h14:fss19=1:fcalt=0).
Each ':fXXXX=N' sets a single OpenType feature tag with a parameter
value. 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, clig, rlig, kern) are
preserved unless explicitly overridden.
closes: #19857
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
ff41e9d853
commit
ea7bf9aa8a
+12
-1
@@ -1,4 +1,4 @@
|
||||
*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
|
||||
@@ -1150,11 +1150,22 @@ For the Win32 GUI *E244* *E245*
|
||||
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|.
|
||||
|
||||
|
||||
@@ -52614,12 +52614,16 @@ Other ~
|
||||
- |system()| and |systemlist()| functions accept a list as first argument,
|
||||
bypassing the shell completely.
|
||||
|
||||
Platform specific ~
|
||||
-----------------
|
||||
- support OpenType font features in 'guifont' for DirectWrite (Win32)
|
||||
|
||||
xxd ~
|
||||
---
|
||||
Add "-t" option to append a terminating NUL byte to C include output (-i).
|
||||
|
||||
*changed-9.3*
|
||||
Changed~
|
||||
Changed ~
|
||||
-------
|
||||
- Support for NeXTStep was dropped with patch v9.2.0122
|
||||
- |json_decode()| is stricter: keywords must be lowercase, lone surrogates are
|
||||
|
||||
+79
-1
@@ -313,6 +313,9 @@ struct DWriteContext {
|
||||
|
||||
D2D1_TEXT_ANTIALIAS_MODE mTextAntialiasMode;
|
||||
|
||||
DWriteFontFeature mFontFeatures[DWRITE_MAX_FONT_FEATURES];
|
||||
int mFontFeatureCount;
|
||||
|
||||
// METHODS
|
||||
|
||||
DWriteContext();
|
||||
@@ -357,6 +360,8 @@ struct DWriteContext {
|
||||
|
||||
DWriteRenderingParams *GetRenderingParams(
|
||||
DWriteRenderingParams *params);
|
||||
|
||||
void SetFontFeatures(const DWriteFontFeature *features, int count);
|
||||
};
|
||||
|
||||
class AdjustedGlyphRun : public DWRITE_GLYPH_RUN
|
||||
@@ -648,8 +653,10 @@ DWriteContext::DWriteContext() :
|
||||
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,
|
||||
@@ -1086,6 +1093,56 @@ DWriteContext::DrawText(const WCHAR *text, int len,
|
||||
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
|
||||
@@ -1413,3 +1470,24 @@ DWriteContext_GetRenderingParams(
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,13 @@ typedef struct DWriteRenderingParams {
|
||||
int textAntialiasMode;
|
||||
} DWriteRenderingParams;
|
||||
|
||||
#define DWRITE_MAX_FONT_FEATURES 32
|
||||
|
||||
typedef struct DWriteFontFeature {
|
||||
unsigned int tag; // OpenType feature tag (4 bytes)
|
||||
unsigned int parameter; // Feature parameter (0 = disable, 1 = enable)
|
||||
} DWriteFontFeature;
|
||||
|
||||
void DWrite_Init(void);
|
||||
void DWrite_Final(void);
|
||||
|
||||
@@ -86,6 +93,11 @@ DWriteRenderingParams *DWriteContext_GetRenderingParams(
|
||||
DWriteContext *ctx,
|
||||
DWriteRenderingParams *params);
|
||||
|
||||
void DWriteContext_SetFontFeatures(
|
||||
DWriteContext *ctx,
|
||||
const DWriteFontFeature *features,
|
||||
int count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+54
-1
@@ -145,7 +145,6 @@ gui_mch_set_rendering_options(char_u *s)
|
||||
int dx_geom = 0;
|
||||
int dx_renmode = 0;
|
||||
int dx_taamode = 0;
|
||||
|
||||
// parse string as rendering options.
|
||||
for (p = s; p != NULL && *p != NUL; )
|
||||
{
|
||||
@@ -3956,6 +3955,60 @@ gui_mch_init_font(char_u *font_name, int fontset UNUSED)
|
||||
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
|
||||
|
||||
@@ -3210,6 +3210,12 @@ get_logfont(
|
||||
}
|
||||
}
|
||||
break;
|
||||
case L'f':
|
||||
// Font features (e.g., "fss19=1").
|
||||
// Parsed separately by gui_mch_init_font(); skip here.
|
||||
while (*p && *p != L':')
|
||||
p++;
|
||||
break;
|
||||
case L'q':
|
||||
for (i = 0; i < (int)ARRAY_LENGTH(quality_pairs); ++i)
|
||||
{
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
321,
|
||||
/**/
|
||||
320,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user