notepad4 icon indicating copy to clipboard operation
notepad4 copied to clipboard

Fallback font

Open maboroshin opened this issue 2 years ago • 7 comments

Asians want to change fonts to ASCII or CJK characters. English speakers want to display emoji and symbols. If a character is missing from one font, it is brought from another font. Current Scintilla doesn’t appear to have this feature.

  • https://github.com/zufuliu/notepad2/issues/250
  • https://github.com/rizonesoft/Notepad3/issues/4120
  • https://github.com/notepad-plus-plus/notepad-plus-plus/issues/5465

VS Code

The font MS Gothic contains Kanji characters. Old "MS Gothic" is the default fallback font in VS Code. Specify editor.fontFamily in VS Code.

The following specified fonts don't include Kanji characters, so Kanji characters are rendered in MS Gothic font.

"editor.fontFamily": "Consolas,'Courier New'"

Meiryo is a newer font that includes Kanji characters. If you want to give priority to Meiryo, write as follows. Kanji characters are rendered in Meiryo font.

"editor.fontFamily": "Consolas, Meiryo"

English fonts suitable for programming are specified first. It is easy to distinguish between 0 and O, 1 and I and l. Because MS Gothic and Meiryo are difficult to distinguish.

Another way

Some people merge any two fonts for editors without font fallback. e.g. https://myrica.estable.jp/

CSS font-family

It seems to work the same as MS Code.

The font-family property specifies a list of fonts, from highest priority to lowest. Font selection does not stop at the first font in the list that is on the user's system. Rather, font selection is done one character at a time, so that if an available font does not have a glyph for a needed character, the latter fonts are tried. https://developer.mozilla.org/en-US/docs/Web/CSS/font-family

maboroshin avatar Jul 24 '23 22:07 maboroshin

Current Scintilla uses system default fallback font that depends on rendering technology, GDI uses legacy font, DirectWrite uses new font.

Implement this requires lower level layout, which Scintilla is not planing to implement (at least in short term as far as I know).

zufuliu avatar Jul 24 '23 22:07 zufuliu

Thank you. I'm not sure if I'm right. Is this what you mean?

  1. For example, specify an alphabet-only font on Scintilla.
  2. With that setting, try display Kanji characters on Scintilla.
  3. Then, the Windows fallback font is working.

maboroshin avatar Jul 24 '23 22:07 maboroshin

Yes. it works for Chinese (SimSun used in GDI and Microsoft YaHei (UI) used in DirectWrite), I think it should also works for Japanese and Korean.

zufuliu avatar Jul 24 '23 22:07 zufuliu

Thank you. There are several ways to changing font.

  • Solution 1: Specify the Windows fallback font. Change FontLink in the registry. 1 2 (Japanese)
  • Solution 2: Combine the two fonts. 1 (Japanese) & NexusFont :Fonts can be used just selection without font installation.

maboroshin avatar Jul 24 '23 23:07 maboroshin

Custom fallback font is possible on Windows 8.1 (which add colored emoji) and later with DirectWrite, https://learn.microsoft.com/en-us/windows/win32/api/dwrite_2/nn-dwrite_2-idwritefontfallbackbuilder, will need to do some experiments.

https://sourceforge.net/p/scintilla/feature-requests/1456/

zufuliu avatar Aug 05 '23 03:08 zufuliu

following code can be used to changed default font for CJK, however word wrap (maybe rendering too) is low after the change:

IDWriteFontFallback *customFontFallback = nullptr;

IDWriteFactory2 *pIDWriteFactory2 = static_cast<IDWriteFactory2 *>(pIDWriteFactory);
IDWriteFontFallbackBuilder *fontFallbackBuilder = nullptr;
hr = pIDWriteFactory2->CreateFontFallbackBuilder(&fontFallbackBuilder);
if (SUCCEEDED(hr)) {
	const DWRITE_UNICODE_RANGE ranges[] = {
		{0x3400, 0x4DBF}, // U+3400..U+4DBF CJK Unified Ideographs Extension A
		{0x4E00, 0x9FFF}, // U+4E00..U+9FFF CJK Unified Ideographs
		{0xF900, 0xFAFF}, // U+F900..U+FAFF CJK Compatibility Ideographs
	};
	const WCHAR *targetFamilyNames[] = {
		L"SimSun",
	};
	hr = fontFallbackBuilder->AddMapping(ranges, 3, targetFamilyNames, 1,
		nullptr, nullptr, nullptr, 1.0f);
	IDWriteFontFallback *fontFallback = nullptr;
	hr = pIDWriteFactory2->GetSystemFontFallback(&fontFallback);
	if (SUCCEEDED(hr)) {
		hr = fontFallbackBuilder->AddMappings(fontFallback);
		ReleaseUnknown(fontFallback);
	}
	hr = fontFallbackBuilder->CreateFontFallback(&fontFallback);
	if (SUCCEEDED(hr)) {
		customFontFallback = fontFallback;
	}
	ReleaseUnknown(fontFallbackBuilder);
}

static_cast<IDWriteTextLayout2 *>(pTextLayout)->SetFontFallback(customFontFallback);

zufuliu avatar Aug 05 '23 04:08 zufuliu

I'm not sure how it should be implemented. If a CJK-only font existed, it would be in this range.

Blocks.txt

  • {4352 - 4607}, // Hangul Jamo
  • {11904 - 12031}, // CJK Radicals Supplement
  • {12288 - 12351}, // CJK Symbols and Punctuation
  • {12352 - 12447}, // Hiragana
  • {12448 - 12543}, // Katakana
  • {12544 - 12591}, // Bopomofo
  • {12592 - 12687}, // Hangul Compatibility Jamo
  • {12688 - 12703}, // Kanbun
  • {12704 - 12735}, // Bopomofo Extended
  • {12736 - 12783}, // CJK Strokes
  • {12784 - 12799}, // Katakana Phonetic Extensions
  • {12800 - 13055}, // Enclosed CJK Letters and Months
  • {13056 - 13311}, // CJK Compatibility
  • {13312 - 19903}, // CJK Unified Ideographs Extension A
  • {19904 - 19967}, // Yijing Hexagram Symbols
  • {19968 - 40959}, // CJK Unified Ideographs
  • {43360 - 43391}, // Hangul Jamo Extended-A
  • {44032 - 55215}, // Hangul Syllables
  • {55216 - 55295}, // Hangul Jamo Extended-B
  • {57344 - 63743}, // Private Use Area
  • {63744 - 64255}, // CJK Compatibility Ideographs
  • {65280 - 65519}, // Halfwidth and Fullwidth Forms
  • {130048 - 205743}, // CJK Unified Ideographs Extension B to H

maboroshin avatar Aug 05 '23 06:08 maboroshin