BLF: Fallback Font Stack
Allow use of multiple fonts acting together like a fallback stack, where if a glyph is not found in one it can be retrieved from another. See D12622 for much more detail Differential Revision: https://developer.blender.org/D12622 Reviewed by Brecht Van Lommel
This commit is contained in:
parent
5485057a27
commit
524a9e3db8
Notes:
blender-bot
2023-02-14 11:25:11 +01:00
Referenced by commit600c391a65
, Cleanup: Compiler Warning of Sign Conversion #2 Referenced by commit3d3c0dfe30
, Cleanup: Compiler Warning of Sign Conversion
|
@ -14,6 +14,15 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Name of subfolder inside BLENDER_DATAFILES that contains font files. */
|
||||
#define BLF_DATAFILES_FONTS_DIR "fonts"
|
||||
|
||||
/* File name of the default variable-width font. */
|
||||
#define BLF_DEFAULT_PROPORTIONAL_FONT "droidsans.ttf"
|
||||
|
||||
/* File name of the default fixed-pitch font. */
|
||||
#define BLF_DEFAULT_MONOSPACED_FONT "bmonofont-i18n.ttf"
|
||||
|
||||
/* enable this only if needed (unused circa 2016) */
|
||||
#define BLF_BLUR_ENABLE 0
|
||||
|
||||
|
@ -37,12 +46,14 @@ void BLF_cache_flush_set_fn(void (*cache_flush_fn)(void));
|
|||
*/
|
||||
int BLF_load(const char *name) ATTR_NONNULL();
|
||||
int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size) ATTR_NONNULL();
|
||||
bool BLF_is_loaded(const char *name) ATTR_NONNULL();
|
||||
|
||||
int BLF_load_unique(const char *name) ATTR_NONNULL();
|
||||
int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size) ATTR_NONNULL();
|
||||
|
||||
void BLF_unload(const char *name) ATTR_NONNULL();
|
||||
void BLF_unload_id(int fontid);
|
||||
void BLF_unload_all(void);
|
||||
|
||||
char *BLF_display_name_from_file(const char *filepath);
|
||||
|
||||
|
@ -312,6 +323,7 @@ int BLF_set_default(void);
|
|||
|
||||
int BLF_load_default(bool unique);
|
||||
int BLF_load_mono_default(bool unique);
|
||||
void BLF_load_font_stack(void);
|
||||
|
||||
#ifdef DEBUG
|
||||
void BLF_state_print(int fontid);
|
||||
|
@ -331,6 +343,9 @@ void BLF_state_print(int fontid);
|
|||
#define BLF_HINTING_FULL (1 << 10)
|
||||
#define BLF_BOLD (1 << 11)
|
||||
#define BLF_ITALIC (1 << 12)
|
||||
#define BLF_MONOSPACED (1 << 13) /* Intended USE is monospaced, regardless of font type. */
|
||||
#define BLF_DEFAULT (1 << 14) /* A font within the default stack of fonts. */
|
||||
#define BLF_LAST_RESORT (1 << 15) /* Must only be used as last font in the stack. */
|
||||
|
||||
#define BLF_DRAW_STR_DUMMY_MAX 1024
|
||||
|
||||
|
|
|
@ -34,13 +34,6 @@
|
|||
#include "blf_internal.h"
|
||||
#include "blf_internal_types.h"
|
||||
|
||||
/* Max number of font in memory.
|
||||
* Take care that now every font have a glyph cache per size/dpi,
|
||||
* so we don't need load the same font with different size, just
|
||||
* load one and call BLF_size.
|
||||
*/
|
||||
#define BLF_MAX_FONT 16
|
||||
|
||||
#define BLF_RESULT_CHECK_INIT(r_info) \
|
||||
if (r_info) { \
|
||||
memset(r_info, 0, sizeof(*(r_info))); \
|
||||
|
@ -48,7 +41,7 @@
|
|||
((void)0)
|
||||
|
||||
/* Font array. */
|
||||
static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
|
||||
FontBLF *global_font[BLF_MAX_FONT] = {NULL};
|
||||
|
||||
/* XXX: should these be made into global_font_'s too? */
|
||||
|
||||
|
@ -134,6 +127,11 @@ bool BLF_has_glyph(int fontid, unsigned int unicode)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool BLF_is_loaded(const char *name)
|
||||
{
|
||||
return blf_search(name) >= 0;
|
||||
}
|
||||
|
||||
int BLF_load(const char *name)
|
||||
{
|
||||
/* check if we already load this font. */
|
||||
|
@ -255,6 +253,20 @@ void BLF_unload_id(int fontid)
|
|||
}
|
||||
}
|
||||
|
||||
void BLF_unload_all(void)
|
||||
{
|
||||
for (int i = 0; i < BLF_MAX_FONT; i++) {
|
||||
FontBLF *font = global_font[i];
|
||||
if (font) {
|
||||
blf_font_free(font);
|
||||
global_font[i] = NULL;
|
||||
}
|
||||
}
|
||||
blf_mono_font = -1;
|
||||
blf_mono_font_render = -1;
|
||||
BLF_default_set(-1);
|
||||
}
|
||||
|
||||
void BLF_enable(int fontid, int option)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
#include FT_TRUETYPE_TABLES_H /* For TT_OS2 */
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
@ -1288,6 +1289,25 @@ FontBLF *blf_font_new(const char *name, const char *filepath)
|
|||
font->filepath = BLI_strdup(filepath);
|
||||
blf_font_fill(font);
|
||||
|
||||
/* Save TrueType table with bits to quickly test most unicode block coverage. */
|
||||
TT_OS2 *os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(font->face, FT_SFNT_OS2);
|
||||
if (os2_table) {
|
||||
font->UnicodeRanges[0] = (uint)os2_table->ulUnicodeRange1;
|
||||
font->UnicodeRanges[1] = (uint)os2_table->ulUnicodeRange2;
|
||||
font->UnicodeRanges[2] = (uint)os2_table->ulUnicodeRange3;
|
||||
font->UnicodeRanges[3] = (uint)os2_table->ulUnicodeRange4;
|
||||
}
|
||||
|
||||
/* Detect "Last resort" fonts. They have everything. Usually except last 5 bits. */
|
||||
if (font->UnicodeRanges[0] == 0xffffffffU && font->UnicodeRanges[1] == 0xffffffffU &&
|
||||
font->UnicodeRanges[2] == 0xffffffffU && font->UnicodeRanges[3] >= 0x7FFFFFFU) {
|
||||
font->flags |= BLF_LAST_RESORT;
|
||||
}
|
||||
|
||||
if (FT_IS_FIXED_WIDTH(font->face)) {
|
||||
font->flags |= BLF_MONOSPACED;
|
||||
}
|
||||
|
||||
if (FT_HAS_KERNING(font->face)) {
|
||||
/* Create kerning cache table and fill with value indicating "unset". */
|
||||
font->kerning_cache = MEM_mallocN(sizeof(KerningCacheBLF), __func__);
|
||||
|
|
|
@ -11,13 +11,14 @@
|
|||
|
||||
#include "BLF_api.h"
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_path_util.h"
|
||||
|
||||
#include "BKE_appdir.h"
|
||||
|
||||
static int blf_load_font_default(const char *filename, const bool unique)
|
||||
{
|
||||
const char *dir = BKE_appdir_folder_id(BLENDER_DATAFILES, "fonts");
|
||||
const char *dir = BKE_appdir_folder_id(BLENDER_DATAFILES, BLF_DATAFILES_FONTS_DIR);
|
||||
if (dir == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: 'fonts' data path not found for '%s', will not be able to display text\n",
|
||||
|
@ -34,10 +35,46 @@ static int blf_load_font_default(const char *filename, const bool unique)
|
|||
|
||||
int BLF_load_default(const bool unique)
|
||||
{
|
||||
return blf_load_font_default("droidsans.ttf", unique);
|
||||
int font_id = blf_load_font_default(BLF_DEFAULT_PROPORTIONAL_FONT, unique);
|
||||
BLF_enable(font_id, BLF_DEFAULT);
|
||||
return font_id;
|
||||
}
|
||||
|
||||
int BLF_load_mono_default(const bool unique)
|
||||
{
|
||||
return blf_load_font_default("bmonofont-i18n.ttf", unique);
|
||||
int font_id = blf_load_font_default(BLF_DEFAULT_MONOSPACED_FONT, unique);
|
||||
BLF_enable(font_id, BLF_MONOSPACED | BLF_DEFAULT);
|
||||
return font_id;
|
||||
}
|
||||
|
||||
void BLF_load_font_stack()
|
||||
{
|
||||
/* Load these if not already, might have been replaced by user custom. */
|
||||
BLF_load_default(false);
|
||||
BLF_load_mono_default(false);
|
||||
|
||||
const char *path = BKE_appdir_folder_id(BLENDER_DATAFILES, BLF_DATAFILES_FONTS_DIR SEP_STR);
|
||||
if (path && BLI_exists(path)) {
|
||||
struct direntry *dir;
|
||||
uint num_files = BLI_filelist_dir_contents(path, &dir);
|
||||
for (int f = 0; f < num_files; f++) {
|
||||
if (!FILENAME_IS_CURRPAR(dir[f].relname) && !BLI_is_dir(dir[f].path)) {
|
||||
if (!BLF_is_loaded(dir[f].path)) {
|
||||
int font_id = BLF_load(dir[f].path);
|
||||
if (font_id == -1) {
|
||||
fprintf(stderr, "Unable to load font: %s\n", dir[f].path);
|
||||
}
|
||||
else {
|
||||
BLF_enable(font_id, BLF_DEFAULT);
|
||||
/* TODO: FontBLF will later load FT_Face on demand. When this is in
|
||||
* place we can drop this face now since we have all needed data. */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BLI_filelist_free(dir, num_files);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Fonts not found at %s\n", path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_strict_flags.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Internal Utilities
|
||||
|
@ -222,6 +223,335 @@ static GlyphBLF *blf_glyph_cache_add_glyph(
|
|||
return g;
|
||||
}
|
||||
|
||||
/* This table can be used to find a coverage bit based on a charcode. later we can get default
|
||||
* language and script from codepoint. */
|
||||
|
||||
typedef struct eUnicodeBlock {
|
||||
unsigned int first;
|
||||
unsigned int last;
|
||||
int coverage_bit; /* 0-122. -1 is N/A. */
|
||||
/* Later we add primary script and language for Harfbuzz, data from
|
||||
* https://en.wikipedia.org/wiki/Unicode_block */
|
||||
} eUnicodeBlock;
|
||||
|
||||
static eUnicodeBlock unicode_blocks[] = {
|
||||
/* Must be in ascending order by start of range. */
|
||||
{0x0, 0x7F, 0}, /* Basic Latin. */
|
||||
{0x80, 0xFF, 1}, /* Latin-1 Supplement. */
|
||||
{0x100, 0x17F, 2}, /* Latin Extended-A. */
|
||||
{0x180, 0x24F, 3}, /* Latin Extended-B. */
|
||||
{0x250, 0x2AF, 4}, /* IPA Extensions. */
|
||||
{0x2B0, 0x2FF, 5}, /* Spacing Modifier Letters. */
|
||||
{0x300, 0x36F, 6}, /* Combining Diacritical Marks. */
|
||||
{0x370, 0x3FF, 7}, /* Greek. */
|
||||
{0x400, 0x52F, 9}, /* Cyrillic. */
|
||||
{0x530, 0x58F, 10}, /* Armenian. */
|
||||
{0x590, 0x5FF, 11}, /* Hebrew. */
|
||||
{0x600, 0x6FF, 13}, /* Arabic. */
|
||||
{0x700, 0x74F, 71}, /* Syriac. */
|
||||
{0x750, 0x77F, 13}, /* Arabic Supplement. */
|
||||
{0x780, 0x7BF, 72}, /* Thaana. */
|
||||
{0x7C0, 0x7FF, 14}, /* NKo. */
|
||||
{0x800, 0x83F, -1}, /* Samaritan. */
|
||||
{0x840, 0x85F, -1}, /* Mandaic. */
|
||||
{0x900, 0x97F, 15}, /* Devanagari. */
|
||||
{0x980, 0x9FF, 16}, /* Bengali. */
|
||||
{0xA00, 0xA7F, 17}, /* Gurmukhi. */
|
||||
{0xA80, 0xAFF, 18}, /* Gujarati. */
|
||||
{0xB00, 0xB7F, 19}, /* Oriya. */
|
||||
{0xB80, 0xBFF, 20}, /* Tamil. */
|
||||
{0xC00, 0xC7F, 21}, /* Telugu. */
|
||||
{0xC80, 0xCFF, 22}, /* Kannada. */
|
||||
{0xD00, 0xD7F, 23}, /* Malayalam. */
|
||||
{0xD80, 0xDFF, 73}, /* Sinhala. */
|
||||
{0xE00, 0xE7F, 24}, /* Thai. */
|
||||
{0xE80, 0xEFF, 25}, /* Lao. */
|
||||
{0xF00, 0xFFF, 70}, /* Tibetan. */
|
||||
{0x1000, 0x109F, 74}, /* Myanmar. */
|
||||
{0x10A0, 0x10FF, 26}, /* Georgian. */
|
||||
{0x1100, 0x11FF, 28}, /* Hangul Jamo. */
|
||||
{0x1200, 0x139F, 75}, /* Ethiopic. */
|
||||
{0x13A0, 0x13FF, 76}, /* Cherokee. */
|
||||
{0x1400, 0x167F, 77}, /* Canadian Aboriginal. */
|
||||
{0x1680, 0x169F, 78}, /* Ogham. */
|
||||
{0x16A0, 0x16FF, 79}, /* unic. */
|
||||
{0x1700, 0x171F, 84}, /* Tagalog. */
|
||||
{0x1720, 0x173F, 84}, /* Hanunoo. */
|
||||
{0x1740, 0x175F, 84}, /* Buhid. */
|
||||
{0x1760, 0x177F, 84}, /* Tagbanwa. */
|
||||
{0x1780, 0x17FF, 80}, /* Khmer. */
|
||||
{0x1800, 0x18AF, 81}, /* Mongolian. */
|
||||
{0x1900, 0x194F, 93}, /* Limbu. */
|
||||
{0x1950, 0x197F, 94}, /* Tai Le. */
|
||||
{0x1980, 0x19DF, 95}, /* New Tai Lue". */
|
||||
{0x19E0, 0x19FF, 80}, /* Khmer. */
|
||||
{0x1A00, 0x1A1F, 96}, /* Buginese. */
|
||||
{0x1A20, 0x1AAF, -1}, /* Tai Tham. */
|
||||
{0x1B00, 0x1B7F, 27}, /* Balinese. */
|
||||
{0x1B80, 0x1BBF, 112}, /* Sundanese. */
|
||||
{0x1BC0, 0x1BFF, -1}, /* Batak. */
|
||||
{0x1C00, 0x1C4F, 113}, /* Lepcha. */
|
||||
{0x1C50, 0x1C7F, 114}, /* Ol Chiki. */
|
||||
{0x1D00, 0x1DBF, 4}, /* IPA Extensions. */
|
||||
{0x1DC0, 0x1DFF, 6}, /* Combining Diacritical Marks. */
|
||||
{0x1E00, 0x1EFF, 29}, /* Latin Extended Additional. */
|
||||
{0x1F00, 0x1FFF, 30}, /* Greek Extended. */
|
||||
{0x2000, 0x206F, 31}, /* General Punctuation. */
|
||||
{0x2070, 0x209F, 32}, /* Superscripts And Subscripts. */
|
||||
{0x20A0, 0x20CF, 33}, /* Currency Symbols. */
|
||||
{0x20D0, 0x20FF, 34}, /* Combining Diacritical Marks For Symbols. */
|
||||
{0x2100, 0x214F, 35}, /* Letterlike Symbols. */
|
||||
{0x2150, 0x218F, 36}, /* Number Forms. */
|
||||
{0x2190, 0x21FF, 37}, /* Arrows. */
|
||||
{0x2200, 0x22FF, 38}, /* Mathematical Operators. */
|
||||
{0x2300, 0x23FF, 39}, /* Miscellaneous Technical. */
|
||||
{0x2400, 0x243F, 40}, /* Control Pictures. */
|
||||
{0x2440, 0x245F, 41}, /* Optical Character Recognition. */
|
||||
{0x2460, 0x24FF, 42}, /* Enclosed Alphanumerics. */
|
||||
{0x2500, 0x257F, 43}, /* Box Drawing. */
|
||||
{0x2580, 0x259F, 44}, /* Block Elements. */
|
||||
{0x25A0, 0x25FF, 45}, /* Geometric Shapes. */
|
||||
{0x2600, 0x26FF, 46}, /* Miscellaneous Symbols. */
|
||||
{0x2700, 0x27BF, 47}, /* Dingbats. */
|
||||
{0x27C0, 0x27EF, 38}, /* Mathematical Operators. */
|
||||
{0x27F0, 0x27FF, 37}, /* Arrows. */
|
||||
{0x2800, 0x28FF, 82}, /* Braille. */
|
||||
{0x2900, 0x297F, 37}, /* Arrows. */
|
||||
{0x2980, 0x2AFF, 38}, /* Mathematical Operators. */
|
||||
{0x2B00, 0x2BFF, 37}, /* Arrows. */
|
||||
{0x2C00, 0x2C5F, 97}, /* Glagolitic. */
|
||||
{0x2C60, 0x2C7F, 29}, /* Latin Extended Additional. */
|
||||
{0x2C80, 0x2CFF, 8}, /* Coptic. */
|
||||
{0x2D00, 0x2D2F, 26}, /* Georgian. */
|
||||
{0x2D30, 0x2D7F, 98}, /* Tifinagh. */
|
||||
{0x2D80, 0x2DDF, 75}, /* Ethiopic. */
|
||||
{0x2DE0, 0x2DFF, 9}, /* Cyrillic. */
|
||||
{0x2E00, 0x2E7F, 31}, /* General Punctuation. */
|
||||
{0x2E80, 0x2FFF, 59}, /* CJK Unified Ideographs. */
|
||||
{0x3000, 0x303F, 48}, /* CJK Symbols And Punctuation. */
|
||||
{0x3040, 0x309F, 49}, /* Hiragana. */
|
||||
{0x30A0, 0x30FF, 50}, /* Katakana. */
|
||||
{0x3100, 0x312F, 51}, /* Bopomofo. */
|
||||
{0x3130, 0x318F, 52}, /* Hangul Compatibility Jamo. */
|
||||
{0x3190, 0x319F, 59}, /* CJK Unified Ideographs. */
|
||||
{0x31A0, 0x31BF, 51}, /* Bopomofo. */
|
||||
{0x31C0, 0x31EF, 59}, /* CJK Unified Ideographs. */
|
||||
{0x31F0, 0x31FF, 50}, /* Katakana. */
|
||||
{0x3200, 0x32FF, 54}, /* Enclosed CJK Letters And Months. */
|
||||
{0x3300, 0x33FF, 55}, /* CJK Compatibility. */
|
||||
{0x3400, 0x4DBF, 59}, /* CJK Unified Ideographs. */
|
||||
{0x4DC0, 0x4DFF, 99}, /* Yijing. */
|
||||
{0x4E00, 0x9FFF, 59}, /* CJK Unified Ideographs. */
|
||||
{0xA000, 0xA4CF, 83}, /* Yi. */
|
||||
{0xA4D0, 0xA4FF, -1}, /* Lisu. */
|
||||
{0xA500, 0xA63F, 12}, /* Vai. */
|
||||
{0xA640, 0xA69F, 9}, /* Cyrillic. */
|
||||
{0xA6A0, 0xA6FF, -1}, /* Bamum. */
|
||||
{0xA700, 0xA71F, 5}, /* Spacing Modifier Letters. */
|
||||
{0xA720, 0xA7FF, 29}, /* Latin Extended Additional. */
|
||||
{0xA800, 0xA82F, 100}, /* Syloti Nagri. */
|
||||
{0xA840, 0xA87F, 53}, /* Phags-pa. */
|
||||
{0xA880, 0xA8DF, 115}, /* Saurashtra. */
|
||||
{0xA900, 0xA92F, 116}, /* Kayah Li. */
|
||||
{0xA930, 0xA95F, 117}, /* Rejang. */
|
||||
{0xA960, 0xA97F, 56}, /* Hangul Syllables. */
|
||||
{0xA980, 0xA9DF, -1}, /* Javanese. */
|
||||
{0xA9E0, 0xA9FF, 74}, /* Myanmar. */
|
||||
{0xAA00, 0xAA5F, 118}, /* Cham. */
|
||||
{0xAA60, 0xAA7F, 74}, /* Myanmar. */
|
||||
{0xAA80, 0xAADF, -1}, /* Tai Viet. */
|
||||
{0xAAE0, 0xAAFF, -1}, /* Meetei Mayek. */
|
||||
{0xAB00, 0xAB2F, 75}, /* Ethiopic. */
|
||||
{0xAB70, 0xABBF, 76}, /* Cherokee. */
|
||||
{0xABC0, 0xABFF, -1}, /* Meetei Mayek. */
|
||||
{0xAC00, 0xD7AF, 56}, /* Hangul Syllables. */
|
||||
{0xD800, 0xDFFF, 57}, /* Non-Plane 0. */
|
||||
{0xE000, 0xF6FF, 60}, /* Private Use Area. */
|
||||
{0xE700, 0xEFFF, -1}, /* MS Wingdings. */
|
||||
{0xF000, 0xF8FF, -1}, /* MS Symbols. */
|
||||
{0xF900, 0xFAFF, 61}, /* CJK Compatibility Ideographs. */
|
||||
{0xFB00, 0xFB4F, 62}, /* Alphabetic Presentation Forms. */
|
||||
{0xFB50, 0xFDFF, 63}, /* Arabic Presentation Forms-A. */
|
||||
{0xFE00, 0xFE0F, 91}, /* Variation Selectors. */
|
||||
{0xFE10, 0xFE1F, 65}, /* CJK Compatibility Forms. */
|
||||
{0xFE20, 0xFE2F, 64}, /* Combining Half Marks. */
|
||||
{0xFE30, 0xFE4F, 65}, /* CJK Compatibility Forms. */
|
||||
{0xFE50, 0xFE6F, 66}, /* Small Form Variants. */
|
||||
{0xFE70, 0xFEFF, 67}, /* Arabic Presentation Forms-B. */
|
||||
{0xFF00, 0xFFEF, 68}, /* Halfwidth And Fullwidth Forms. */
|
||||
{0xFFF0, 0xFFFF, 69}, /* Specials. */
|
||||
{0x10000, 0x1013F, 101}, /* Linear B. */
|
||||
{0x10140, 0x1018F, 102}, /* Ancient Greek Numbers. */
|
||||
{0x10190, 0x101CF, 119}, /* Ancient Symbols. */
|
||||
{0x101D0, 0x101FF, 120}, /* Phaistos Disc. */
|
||||
{0x10280, 0x1029F, 121}, /* Lycian. */
|
||||
{0x102A0, 0x102DF, 121}, /* Carian. */
|
||||
{0x10300, 0x1032F, 85}, /* Old Italic. */
|
||||
{0x10330, 0x1034F, 86}, /* Gothic. */
|
||||
{0x10350, 0x1037F, -1}, /* Old Permic. */
|
||||
{0x10380, 0x1039F, 103}, /* Ugaritic. */
|
||||
{0x103A0, 0x103DF, 104}, /* Old Persian. */
|
||||
{0x10400, 0x1044F, 87}, /* Deseret. */
|
||||
{0x10450, 0x1047F, 105}, /* Shavian. */
|
||||
{0x10480, 0x104AF, 106}, /* Osmanya. */
|
||||
{0x104B0, 0x104FF, -1}, /* Osage. */
|
||||
{0x10500, 0x1052F, -1}, /* Elbasan. */
|
||||
{0x10530, 0x1056F, -1}, /* Caucasian Albanian. */
|
||||
{0x10570, 0x105BF, -1}, /* Vithkuqi. */
|
||||
{0x10600, 0x1077F, -1}, /* Linear A. */
|
||||
{0x10780, 0x107BF, 3}, /* Latin Extended-B. */
|
||||
{0x10800, 0x1083F, 107}, /* Cypriot Syllabary. */
|
||||
{0x10840, 0x1085F, -1}, /* Imperial Aramaic. */
|
||||
{0x10860, 0x1087F, -1}, /* Palmyrene. */
|
||||
{0x10880, 0x108AF, -1}, /* Nabataean. */
|
||||
{0x108E0, 0x108FF, -1}, /* Hatran. */
|
||||
{0x10900, 0x1091F, 58}, /* Phoenician. */
|
||||
{0x10920, 0x1093F, 121}, /* Lydian. */
|
||||
{0x10980, 0x1099F, -1}, /* Meroitic Hieroglyphs. */
|
||||
{0x109A0, 0x109FF, -1}, /* Meroitic Cursive. */
|
||||
{0x10A00, 0x10A5F, 108}, /* Kharoshthi. */
|
||||
{0x10A60, 0x10A7F, -1}, /* Old South Arabian. */
|
||||
{0x10A80, 0x10A9F, -1}, /* Old North Arabian. */
|
||||
{0x10AC0, 0x10AFF, -1}, /* Manichaean. */
|
||||
{0x10B00, 0x10B3F, -1}, /* Avestan. */
|
||||
{0x10B40, 0x10B5F, -1}, /* Inscriptional Parthian. */
|
||||
{0x10B60, 0x10B7F, -1}, /* Inscriptional Pahlavi. */
|
||||
{0x10B80, 0x10BAF, -1}, /* Psalter Pahlavi. */
|
||||
{0x10C00, 0x10C4F, -1}, /* Old Turkic. */
|
||||
{0x10C80, 0x10CFF, -1}, /* Old Hungarian. */
|
||||
{0x10D00, 0x10D3F, -1}, /* Hanifi Rohingya. */
|
||||
{0x108E0, 0x10E7F, -1}, /* Rumi Numeral Symbols. */
|
||||
{0x10E80, 0x10EBF, -1}, /* Yezidi. */
|
||||
{0x10F00, 0x10F2F, -1}, /* Old Sogdian. */
|
||||
{0x10F30, 0x10F6F, -1}, /* Sogdian. */
|
||||
{0x10F70, 0x10FAF, -1}, /* Old Uyghur. */
|
||||
{0x10FB0, 0x10FDF, -1}, /* Chorasmian. */
|
||||
{0x10FE0, 0x10FFF, -1}, /* Elymaic. */
|
||||
{0x11000, 0x1107F, -1}, /* Brahmi. */
|
||||
{0x11080, 0x110CF, -1}, /* Kaithi. */
|
||||
{0x110D0, 0x110FF, -1}, /* Sora Sompeng. */
|
||||
{0x11100, 0x1114F, -1}, /* Chakma. */
|
||||
{0x11150, 0x1117F, -1}, /* Mahajani. */
|
||||
{0x11180, 0x111DF, -1}, /* Sharada. */
|
||||
{0x111E0, 0x111FF, -1}, /* Sinhala Archaic Numbers. */
|
||||
{0x11200, 0x1124F, -1}, /* Khojki. */
|
||||
{0x11280, 0x112AF, -1}, /* Multani. */
|
||||
{0x112B0, 0x112FF, -1}, /* Khudawadi. */
|
||||
{0x11300, 0x1137F, -1}, /* Grantha. */
|
||||
{0x11400, 0x1147F, -1}, /* Newa. */
|
||||
{0x11480, 0x114DF, -1}, /* Tirhuta. */
|
||||
{0x11580, 0x115FF, -1}, /* Siddham. */
|
||||
{0x11600, 0x1165F, -1}, /* Modi. */
|
||||
{0x11660, 0x1167F, 81}, /* Mongolian. */
|
||||
{0x11680, 0x116CF, -1}, /* Takri. */
|
||||
{0x11700, 0x1174F, -1}, /* Ahom. */
|
||||
{0x11800, 0x1184F, -1}, /* Dogra. */
|
||||
{0x118A0, 0x118FF, -1}, /* Warang Citi. */
|
||||
{0x11900, 0x1195F, -1}, /* Dives Akuru. */
|
||||
{0x119A0, 0x119FF, -1}, /* Nandinagari. */
|
||||
{0x11A00, 0x11A4F, -1}, /* Zanabazar Square. */
|
||||
{0x11A50, 0x11AAF, -1}, /* Soyombo. */
|
||||
{0x11AB0, 0x11ABF, 77}, /* Canadian Aboriginal Syllabics. */
|
||||
{0x11AC0, 0x11AFF, -1}, /* Pau Cin Hau. */
|
||||
{0x11C00, 0x11C6F, -1}, /* Bhaiksuki. */
|
||||
{0x11C70, 0x11CBF, -1}, /* Marchen. */
|
||||
{0x11D00, 0x11D5F, -1}, /* Masaram Gondi. */
|
||||
{0x11D60, 0x11DAF, -1}, /* Gunjala Gondi. */
|
||||
{0x11EE0, 0x11EFF, -1}, /* Makasar. */
|
||||
{0x11FB0, 0x11FBF, -1}, /* Lisu. */
|
||||
{0x11FC0, 0x11FFF, 20}, /* Tamil. */
|
||||
{0x12000, 0x1254F, 110}, /* Cuneiform. */
|
||||
{0x12F90, 0x12FFF, -1}, /* Cypro-Minoan. */
|
||||
{0x13000, 0x1343F, -1}, /* Egyptian Hieroglyphs. */
|
||||
{0x14400, 0x1467F, -1}, /* Anatolian Hieroglyphs. */
|
||||
{0x16800, 0x16A3F, -1}, /* Bamum. */
|
||||
{0x16A40, 0x16A6F, -1}, /* Mro. */
|
||||
{0x16A70, 0x16ACF, -1}, /* Tangsa. */
|
||||
{0x16AD0, 0x16AFF, -1}, /* Bassa Vah. */
|
||||
{0x16B00, 0x16B8F, -1}, /* Pahawh Hmong. */
|
||||
{0x16E40, 0x16E9F, -1}, /* Medefaidrin. */
|
||||
{0x16F00, 0x16F9F, -1}, /* Miao. */
|
||||
{0x16FE0, 0x16FFF, -1}, /* Ideographic Symbols. */
|
||||
{0x17000, 0x18AFF, -1}, /* Tangut. */
|
||||
{0x1B170, 0x1B2FF, -1}, /* Nushu. */
|
||||
{0x1BC00, 0x1BC9F, -1}, /* Duployan. */
|
||||
{0x1D000, 0x1D24F, 88}, /* Musical Symbols. */
|
||||
{0x1D2E0, 0x1D2FF, -1}, /* Mayan Numerals. */
|
||||
{0x1D300, 0x1D35F, 109}, /* Tai Xuan Jing. */
|
||||
{0x1D360, 0x1D37F, 111}, /* Counting Rod Numerals. */
|
||||
{0x1D400, 0x1D7FF, 89}, /* Mathematical Alphanumeric Symbols. */
|
||||
{0x1E2C0, 0x1E2FF, -1}, /* Wancho. */
|
||||
{0x1E800, 0x1E8DF, -1}, /* Mende Kikakui. */
|
||||
{0x1E900, 0x1E95F, -1}, /* Adlam. */
|
||||
{0x1EC70, 0x1ECBF, -1}, /* Indic Siyaq Numbers. */
|
||||
{0x1F000, 0x1F02F, 122}, /* Mahjong Tiles. */
|
||||
{0x1F030, 0x1F09F, 122}, /* Domino Tiles. */
|
||||
{0x1F600, 0x1F64F, -1}, /* Emoticons. */
|
||||
{0x20000, 0x2A6DF, 59}, /* CJK Unified Ideographs. */
|
||||
{0x2F800, 0x2FA1F, 61}, /* CJK Compatibility Ideographs. */
|
||||
{0xE0000, 0xE007F, 92}, /* Tags. */
|
||||
{0xE0100, 0xE01EF, 91}, /* Variation Selectors. */
|
||||
{0xF0000, 0x10FFFD, 90}}; /* Private Use Supplementary. */
|
||||
|
||||
/* Find a unicode block that a charcode belongs to. */
|
||||
static eUnicodeBlock *blf_charcode_to_unicode_block(uint charcode)
|
||||
{
|
||||
if (charcode < 0x80) {
|
||||
/* Shortcut to Basic Latin. */
|
||||
return &unicode_blocks[0];
|
||||
}
|
||||
|
||||
/* Binary search for other blocks. */
|
||||
|
||||
int min = 0;
|
||||
int max = ARRAY_SIZE(unicode_blocks) - 1;
|
||||
int mid;
|
||||
|
||||
if (charcode < unicode_blocks[0].first || charcode > unicode_blocks[max].last) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (max >= min) {
|
||||
mid = (min + max) / 2;
|
||||
if (charcode > unicode_blocks[mid].last) {
|
||||
min = mid + 1;
|
||||
}
|
||||
else if (charcode < unicode_blocks[mid].first) {
|
||||
max = mid - 1;
|
||||
}
|
||||
else {
|
||||
return &unicode_blocks[mid];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int blf_charcode_to_coverage_bit(uint charcode)
|
||||
{
|
||||
int coverage_bit = -1;
|
||||
eUnicodeBlock *block = blf_charcode_to_unicode_block(charcode);
|
||||
if (block) {
|
||||
coverage_bit = block->coverage_bit;
|
||||
}
|
||||
|
||||
if (coverage_bit < 0 && charcode > 0xFFFF) {
|
||||
/* No coverage bit, but OpenType specs v.1.3+ says bit 57 implies that there
|
||||
* are codepoints supported beyond the BMP, so only check fonts with this set. */
|
||||
coverage_bit = 57;
|
||||
}
|
||||
|
||||
return coverage_bit;
|
||||
}
|
||||
|
||||
static bool blf_font_has_coverage_bit(FontBLF *font, int coverage_bit)
|
||||
{
|
||||
if (coverage_bit < 0) {
|
||||
return false;
|
||||
}
|
||||
return (font->UnicodeRanges[coverage_bit >> 5] & (1 << (coverage_bit % 32)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a glyph index from `charcode`. Not found returns zero, which is a valid
|
||||
* printable character (`.notdef` or `tofu`). Font is allowed to change here.
|
||||
|
@ -229,8 +559,42 @@ static GlyphBLF *blf_glyph_cache_add_glyph(
|
|||
static FT_UInt blf_glyph_index_from_charcode(FontBLF **font, const uint charcode)
|
||||
{
|
||||
FT_UInt glyph_index = FT_Get_Char_Index((*font)->face, charcode);
|
||||
/* TODO: If not found in this font, check others, update font pointer. */
|
||||
return glyph_index;
|
||||
if (glyph_index) {
|
||||
return glyph_index;
|
||||
}
|
||||
|
||||
/* Not found in main font, so look in the others. */
|
||||
FontBLF *last_resort = NULL;
|
||||
int coverage_bit = blf_charcode_to_coverage_bit(charcode);
|
||||
for (int i = 0; i < BLF_MAX_FONT; i++) {
|
||||
FontBLF *f = global_font[i];
|
||||
if (!f || f == *font || !(f->flags & BLF_DEFAULT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (f->flags & BLF_LAST_RESORT) {
|
||||
last_resort = f;
|
||||
continue;
|
||||
}
|
||||
if (coverage_bit < 0 || blf_font_has_coverage_bit(f, coverage_bit)) {
|
||||
glyph_index = FT_Get_Char_Index(f->face, charcode);
|
||||
if (glyph_index) {
|
||||
*font = f;
|
||||
return glyph_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found in the stack, return from Last Resort if there is one. */
|
||||
if (last_resort) {
|
||||
glyph_index = FT_Get_Char_Index(last_resort->face, charcode);
|
||||
if (glyph_index) {
|
||||
*font = last_resort;
|
||||
return glyph_index;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -377,24 +741,24 @@ static bool UNUSED_FUNCTION(blf_glyph_transform_width)(FT_GlyphSlot glyph, float
|
|||
/**
|
||||
* Transform glyph to fit nicely within a fixed column width.
|
||||
*/
|
||||
static bool UNUSED_FUNCTION(blf_glyph_transform_monospace)(FT_GlyphSlot glyph, int width)
|
||||
static bool blf_glyph_transform_monospace(FT_GlyphSlot glyph, int width)
|
||||
{
|
||||
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||
int gwidth = (int)(glyph->linearHoriAdvance >> 16);
|
||||
if (gwidth > width) {
|
||||
float scale = (float)width / (float)gwidth;
|
||||
FT_Matrix matrix = {to_16dot16(scale), 0, 0, to_16dot16(1)};
|
||||
/* Narrowing all points also thins vertical strokes. */
|
||||
FT_Outline_Transform(&glyph->outline, &matrix);
|
||||
const FT_Pos extra_x = (int)((float)(gwidth - width) * 5.65f);
|
||||
FT_Fixed current = glyph->linearHoriAdvance;
|
||||
FT_Fixed target = width << 16; /* Do math in 16.16 values. */
|
||||
if (target < current) {
|
||||
const FT_Pos embolden = (FT_Pos)((current - target) >> 13);
|
||||
/* Horizontally widen strokes to counteract narrowing. */
|
||||
FT_Outline_EmboldenXY(&glyph->outline, extra_x, 0);
|
||||
FT_Outline_EmboldenXY(&glyph->outline, embolden, 0);
|
||||
const float scale = (float)(target - (embolden << 9)) / (float)current;
|
||||
FT_Matrix matrix = {to_16dot16(scale), 0, 0, to_16dot16(1)};
|
||||
FT_Outline_Transform(&glyph->outline, &matrix);
|
||||
}
|
||||
else if (gwidth < width) {
|
||||
/* Narrow glyphs only need to be centered. */
|
||||
int nudge = (width - gwidth) / 2;
|
||||
FT_Outline_Translate(&glyph->outline, (FT_Pos)nudge * 64, 0);
|
||||
else if (target > current) {
|
||||
/* Center narrow glyphs. */
|
||||
FT_Outline_Translate(&glyph->outline, (FT_Pos)((target - current) >> 11), 0);
|
||||
}
|
||||
glyph->advance.x = width << 6;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -411,7 +775,9 @@ static bool UNUSED_FUNCTION(blf_glyph_transform_monospace)(FT_GlyphSlot glyph, i
|
|||
*/
|
||||
static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font,
|
||||
FontBLF *glyph_font,
|
||||
FT_UInt glyph_index)
|
||||
FT_UInt glyph_index,
|
||||
uint charcode,
|
||||
int fixed_width)
|
||||
{
|
||||
if (glyph_font != settings_font) {
|
||||
FT_Set_Char_Size(glyph_font->face,
|
||||
|
@ -428,6 +794,10 @@ static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if ((settings_font->flags & BLF_MONOSPACED) && (settings_font != glyph_font)) {
|
||||
blf_glyph_transform_monospace(glyph, BLI_wcwidth((char32_t)charcode) * fixed_width);
|
||||
}
|
||||
|
||||
if ((settings_font->flags & BLF_ITALIC) != 0) {
|
||||
/* 37.5% of maximum rightward slant results in 6 degree slope, matching italic
|
||||
* version (`DejaVuSans-Oblique.ttf`) of our current font. But a nice median when
|
||||
|
@ -466,7 +836,8 @@ GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode)
|
|||
* renderer uses a shared buffer internally. */
|
||||
BLI_spin_lock(font_with_glyph->ft_lib_mutex);
|
||||
|
||||
FT_GlyphSlot glyph = blf_glyph_render(font, font_with_glyph, glyph_index);
|
||||
FT_GlyphSlot glyph = blf_glyph_render(
|
||||
font, font_with_glyph, glyph_index, charcode, gc->fixed_width);
|
||||
|
||||
if (glyph) {
|
||||
/* Save this glyph in the initial font's cache. */
|
||||
|
|
|
@ -14,6 +14,12 @@ struct ResultBLF;
|
|||
struct rctf;
|
||||
struct rcti;
|
||||
|
||||
/* Max number of fonts in memory. Take care that every font has a glyph cache per size/dpi,
|
||||
* so we don't need load the same font with different size, just load one and call BLF_size. */
|
||||
#define BLF_MAX_FONT 32
|
||||
|
||||
extern struct FontBLF *global_font[BLF_MAX_FONT];
|
||||
|
||||
void blf_batch_draw_begin(struct FontBLF *font);
|
||||
void blf_batch_draw(void);
|
||||
|
||||
|
|
|
@ -226,6 +226,11 @@ typedef struct FontBLF {
|
|||
/** File-path or NULL. */
|
||||
char *filepath;
|
||||
|
||||
/* Copied from the SFNT OS/2 table. Bit flags for unicode blocks and ranges
|
||||
* considered "functional". Cached here because face might not always exist.
|
||||
* See: https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur */
|
||||
uint UnicodeRanges[4];
|
||||
|
||||
/* aspect ratio or scale. */
|
||||
float aspect[3];
|
||||
|
||||
|
|
|
@ -363,6 +363,10 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w,
|
|||
|
||||
int BLI_wcwidth(char32_t ucs)
|
||||
{
|
||||
/* Treat private use areas (icon fonts), symbols, and emoticons as double-width. */
|
||||
if (ucs >= 0xf0000 || (ucs >= 0xe000 && ucs < 0xf8ff) || (ucs >= 0x1f300 && ucs < 0x1fbff)) {
|
||||
return 2;
|
||||
}
|
||||
return mk_wcwidth(ucs);
|
||||
}
|
||||
|
||||
|
|
|
@ -382,19 +382,8 @@ void uiStyleInit(void)
|
|||
}
|
||||
CLAMP(U.dpi, 48, 144);
|
||||
|
||||
LISTBASE_FOREACH (uiFont *, font, &U.uifonts) {
|
||||
BLF_unload_id(font->blf_id);
|
||||
}
|
||||
|
||||
if (blf_mono_font != -1) {
|
||||
BLF_unload_id(blf_mono_font);
|
||||
blf_mono_font = -1;
|
||||
}
|
||||
|
||||
if (blf_mono_font_render != -1) {
|
||||
BLF_unload_id(blf_mono_font_render);
|
||||
blf_mono_font_render = -1;
|
||||
}
|
||||
/* Needed so that custom fonts are always first. */
|
||||
BLF_unload_all();
|
||||
|
||||
uiFont *font_first = static_cast<uiFont *>(U.uifonts.first);
|
||||
|
||||
|
@ -498,6 +487,9 @@ void uiStyleInit(void)
|
|||
const bool unique = true;
|
||||
blf_mono_font_render = BLF_load_mono_default(unique);
|
||||
}
|
||||
|
||||
/* Load the fallback fonts last. */
|
||||
BLF_load_font_stack();
|
||||
}
|
||||
|
||||
void UI_fontstyle_set(const uiFontStyle *fs)
|
||||
|
|
|
@ -1555,6 +1555,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
|
|||
|
||||
/* initialize the font */
|
||||
BLF_init();
|
||||
BLF_load_font_stack();
|
||||
ps.fontid = BLF_load_mono_default(false);
|
||||
BLF_size(ps.fontid, 11.0f, 72);
|
||||
|
||||
|
|
Loading…
Reference in New Issue