Blender V5.0
blf_thumbs.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12
13#include <algorithm>
14#include <cstdlib>
15
16#include <ft2build.h>
17
18#include FT_FREETYPE_H
19#include FT_ADVANCES_H /* For FT_Get_Advance */
20#include FT_TRUETYPE_IDS_H /* Code-point coverage constants. */
21#include FT_TRUETYPE_TABLES_H /* For TT_OS2 */
22
23#include "BLI_math_bits.h"
24#include "BLI_utildefines.h"
25
26#include "blf_internal_types.hh"
27
28#include "BLF_api.hh"
29
30#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
31
32/* Maximum length of text sample in char32_t, including null terminator. */
33#define BLF_SAMPLE_LEN 5
34
37 int field; /* 'OS/2' table ulUnicodeRangeX field (1-4). */
38 FT_ULong mask; /* 'OS/2' table ulUnicodeRangeX bit mask. */
39};
40
41/* The seemingly arbitrary order that follows is to help quickly find the most-likely designed
42 * intent of the font. Many feature-specific fonts contain Latin, Greek, & Coptic characters so
43 * those need to be checked last. */
45 /* Chinese, Japanese, Korean, ordered specific to general. */
46 {U"\ud55c\uad6d\uc5b4", 2, TT_UCR_HANGUL}, /* 한국어 */
47 {U"\u3042\u30a2\u4e9c", 2, TT_UCR_HIRAGANA}, /* あア亜 */
48 {U"\u30a2\u30a4\u4e9c", 2, TT_UCR_KATAKANA}, /* アイ亜 */
49 {U"\u1956\u195b\u1966", 3, TT_UCR_TAI_LE}, /* ᥖᥛᥦ */
50 {U"\u3105\u3106\u3107", 2, TT_UCR_BOPOMOFO}, /* ㄅㄆㄇ */
51 {U"\ua840\ua841\ua85d", 2, TT_UCR_PHAGSPA}, /* ꡀꡁꡝ */
52 {U"\u5e03\u4e01\u4f53", 2, TT_UCR_CJK_UNIFIED_IDEOGRAPHS}, /* 布丁体 */
53 /* Languages in the BMP with a coverage bit. */
54 {U"\u05d0\u05da\u05e4", 1, TT_UCR_HEBREW},
55 {U"\ua500\ua502\ua549", 1, TT_UCR_VAI},
56 {U"\ufee6\ufef4\ufeb3", 1, TT_UCR_ARABIC},
57 {U"\u07C1\u07C2\u07C3", 1, TT_UCR_NKO},
58 {U"\u0905\u093f\u092a", 1, TT_UCR_DEVANAGARI},
59 {U"\u0986\u0987\u098c", 1, TT_UCR_BENGALI},
60 {U"\u0a05\u0a16\u0a30", 1, TT_UCR_GURMUKHI},
61 {U"\u0aaa\u0aaf\u0ab8", 1, TT_UCR_GUJARATI},
62 {U"\u0b2a\u0b30\u0b37", 1, TT_UCR_ORIYA},
63 {U"\u0b85\u0b88\u0b8f", 1, TT_UCR_TAMIL},
64 {U"\u0c05\u0c0c\u0c36", 1, TT_UCR_TELUGU},
65 {U"\u0c85\u0c87\u0c8e", 1, TT_UCR_KANNADA},
66 {U"\u0d05\u0d09\u0d3d", 1, TT_UCR_MALAYALAM},
67 {U"\u0e05\u0e06\u0e07", 1, TT_UCR_THAI},
68 {U"\u0e81\u0e82\u0e84", 1, TT_UCR_LAO},
69 {U"\u10a0\u10a1\u10a2", 1, TT_UCR_GEORGIAN},
70 {U"\u1B05\u1B07\u1B09", 1, TT_UCR_BALINESE},
71 {U"\u0f00\u0f04\u0f08", 3, TT_UCR_TIBETAN},
72 {U"\u0710\u0717\u071c", 3, TT_UCR_SYRIAC},
73 {U"\u0784\u0783\u0798", 3, TT_UCR_THAANA},
74 {U"\u0d85\u0d89\u0daf", 3, TT_UCR_SINHALA},
75 {U"\u1000\u1001\u1014", 3, TT_UCR_MYANMAR},
76 {U"\u1202\u1207\u1250", 3, TT_UCR_ETHIOPIC},
77 {U"\u13a3\u13a4\u13a8", 3, TT_UCR_CHEROKEE},
78 {U"\u1401\u144d\u156e", 3, TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS},
79 {U"\u1681\u1687\u168b", 3, TT_UCR_OGHAM},
80 {U"\u16A0\u16A4\u16AA", 3, TT_UCR_RUNIC},
81 {U"\u1780\u1781\u1783", 3, TT_UCR_KHMER},
82 {U"\u1820\u1826\u1845", 3, TT_UCR_MONGOLIAN},
83 {U"\ua188\ua320\ua4bf", 3, TT_UCR_YI},
84 {U"\u1900\u1901\u1902", 3, TT_UCR_LIMBU},
85 {U"\u1950\u1951\u1952", 3, TT_UCR_TAI_LE},
86 {U"\u1980\u1982\u1986", 3, (FT_ULong)TT_UCR_NEW_TAI_LUE},
87 {U"\u1A00\u1A01\u1A02", 4, TT_UCR_BUGINESE},
88 {U"\u2c01\u2c05\u2c0c", 4, TT_UCR_GLAGOLITIC},
89 {U"\u2d31\u2d33\u2d37", 4, TT_UCR_TIFINAGH},
90 {U"\u2d31\u2d33\u2d37", 4, TT_UCR_YIJING},
91 {U"\u1B83\u1B84\u1B88", 4, TT_UCR_SUNDANESE},
92 {U"\u1C00\u1C01\u1C02", 4, TT_UCR_LEPCHA},
93 {U"\u1C50\u1C51\u1C52", 4, TT_UCR_OL_CHIKI},
94 {U"\uA800\uA801\uA805", 4, TT_UCR_SYLOTI_NAGRI},
95 {U"\uA882\uA88a\uA892", 4, TT_UCR_SAURASHTRA},
96 {U"\uA901\uA902\uA904", 4, TT_UCR_KAYAH_LI},
97 {U"\uA930\uA932\uA943", 4, TT_UCR_REJANG},
98 {U"\uaa00\uaa02\uaa05", 4, TT_UCR_CHAM},
99 /* Indexed languages in the Supplementary Multilingual Plane. */
100 {U"\U00010000\U00010001\U00010002", 4, TT_UCR_LINEAR_B},
101 {U"\U00010300\U00010301\U00010302", 3, TT_UCR_OLD_ITALIC},
102 {U"\U00010330\U00010331\U00010332", 3, TT_UCR_GOTHIC},
103 {U"\U00010380\U00010381\U00010382", 4, TT_UCR_UGARITIC},
104 {U"\U000103A0\U000103A1\U000103A2", 4, TT_UCR_OLD_PERSIAN},
105 {U"\U00010400\U00010401\U00010402", 3, TT_UCR_DESERET},
106 {U"\U00010450\U00010451\U00010452", 4, TT_UCR_SHAVIAN},
107 {U"\U00010480\U00010481\U00010482", 4, TT_UCR_OSMANYA},
108 {U"\U00010800\U00010803\U00010805", 4, TT_UCR_CYPRIOT_SYLLABARY},
109 {U"\U00010900\U00010901\U00010902", 2, TT_UCR_PHOENICIAN},
110 {U"\U00010A10\U00010A11\U00010A12", 4, TT_UCR_KHAROSHTHI},
111 {U"\U00012000\U00012001\U00012002", 4, TT_UCR_CUNEIFORM},
112 /* Philippine languages use a single OS2 coverage bit. */
113 {U"\u1700\u1701\u1702", 3, TT_UCR_PHILIPPINE}, /* Tagalog */
114 {U"\u1720\u1721\u1722", 3, TT_UCR_PHILIPPINE}, /* Hanunoo */
115 {U"\u1740\u1741\u1742", 3, TT_UCR_PHILIPPINE}, /* Buhid */
116 {U"\u1760\u1761\u1762", 3, TT_UCR_PHILIPPINE}, /* Tagbanwa */
117 /* Anatolian languages use a single OS2 coverage bit. */
118 {U"\U000102A3\U000102A8\U000102CB", 4, TT_UCR_OLD_ANATOLIAN}, /* Carian */
119 {U"\U00010280\U00010281\U00010282", 4, TT_UCR_OLD_ANATOLIAN}, /* Lycian */
120 {U"\U00010920\U00010921\U00010922", 4, TT_UCR_OLD_ANATOLIAN}, /* Lydian */
121 /* Symbol blocks. */
122 {U"\U0001f600\U0001f638", 0, 0}, /* Emoticons 😀😸 */
123 {U"\uf021\uf022\uf023", 0, 0}, /* MS Symbols */
124 {U"\u280f\u2815\u283f", 3, TT_UCR_BRAILLE},
125 {U"\U0001D11e\U0001D161\U0001D130", 3, TT_UCR_MUSICAL_SYMBOLS},
126 {U"\u2700\u2708\u2709", 2, TT_UCR_DINGBATS},
127 {U"\u2600\u2601\u2602", 2, TT_UCR_MISCELLANEOUS_SYMBOLS},
128 {U"\ue000\ue001\ue002", 2, TT_UCR_PRIVATE_USE},
129 {U"\ue702\ue703\ue704", 2, TT_UCR_PRIVATE_USE},
130 {U"\U000F0001\U000F0002\U000F0003", 2, TT_UCR_PRIVATE_USE_SUPPLEMENTARY},
131 /* Languages in the Supplementary Multilingual Plane. */
132 {U"\U00010350\U00010352\U00010353", 2, TT_UCR_NON_PLANE_0}, /* Old Permic */
133 {U"\U000104B0\U000104B6\U000104B8", 2, TT_UCR_NON_PLANE_0}, /* Osage */
134 {U"\U00010500\U00010501\U00010502", 2, TT_UCR_NON_PLANE_0}, /* Elbasan */
135 {U"\U00010530\U00010531\U00010532", 2, TT_UCR_NON_PLANE_0}, /* Caucasian Albanian */
136 {U"\U00010600\U00010601\U00010602", 2, TT_UCR_NON_PLANE_0}, /* Linear A */
137 {U"\U00010840\U00010841\U00010842", 2, TT_UCR_NON_PLANE_0}, /* Imperial Aramaic */
138 {U"\U00010860\U00010861\U00010862", 2, TT_UCR_NON_PLANE_0}, /* Palmyrene */
139 {U"\U00010880\U00010881\U00010882", 2, TT_UCR_NON_PLANE_0}, /* Nabataean */
140 {U"\U000108E0\U000108E3\U000108E4", 2, TT_UCR_NON_PLANE_0}, /* Hatran */
141 {U"\U00010980\U00010983\U00010989", 2, TT_UCR_NON_PLANE_0}, /* Meroitic Hieroglyphs */
142 {U"\U000109A0\U000109A1\U000109A2", 2, TT_UCR_NON_PLANE_0}, /* Meroitic Cursive */
143 {U"\U00010A60\U00010A61\U00010A62", 2, TT_UCR_NON_PLANE_0}, /* Old South Arabian */
144 {U"\U00010A80\U00010A81\U00010A82", 2, TT_UCR_NON_PLANE_0}, /* Old North Arabian */
145 {U"\U00010ac0\U00010ac3\U00010ac6", 2, TT_UCR_NON_PLANE_0}, /* Manichaean */
146 {U"\U00010B00\U00010B04\U00010B08", 2, TT_UCR_NON_PLANE_0}, /* Avestan */
147 {U"\U00010B40\U00010B41\U00010B42", 2, TT_UCR_NON_PLANE_0}, /* Inscriptional Parthian */
148 {U"\U00010B60\U00010B61\U00010B62", 2, TT_UCR_NON_PLANE_0}, /* Inscriptional Pahlavi */
149 {U"\U00010B80\U00010B84\U00010B87", 2, TT_UCR_NON_PLANE_0}, /* Psalter Pahlavi */
150 {U"\U00010C00\U00010C01\U00010C02", 2, TT_UCR_NON_PLANE_0}, /* Old Turkic */
151 {U"\U00010C80\U00010C81\U00010C82", 2, TT_UCR_NON_PLANE_0}, /* Old Hungarian */
152 {U"\U00010D00\U00010D07\U00010D0D", 2, TT_UCR_NON_PLANE_0}, /* Hanifi Rohingya */
153 {U"\U00010E80\U00010E81\U00010E82", 2, TT_UCR_NON_PLANE_0}, /* Yezidi */
154 {U"\U00010F00\U00010F01\U00010F02", 2, TT_UCR_NON_PLANE_0}, /* Old Sogdian */
155 {U"\U00010F30\U00010F32\U00010F34", 2, TT_UCR_NON_PLANE_0}, /* Sogdian */
156 {U"\U00010F70\U00010F71\U00010F72", 2, TT_UCR_NON_PLANE_0}, /* Old Uyghur */
157 {U"\U00010FB0\U00010FB1\U00010FB2", 2, TT_UCR_NON_PLANE_0}, /* Chorasmian */
158 {U"\U00010FE0\U00010FE1\U00010FE2", 2, TT_UCR_NON_PLANE_0}, /* Elymaic */
159 {U"\U00011003\U00011004\U00011005", 2, TT_UCR_NON_PLANE_0}, /* Brahmi */
160 {U"\U00011083\U00011085\U00011087", 2, TT_UCR_NON_PLANE_0}, /* Kaithi */
161 {U"\U000110D0\U000110D1\U000110D2", 2, TT_UCR_NON_PLANE_0}, /* Sora Sompeng */
162 {U"\U00011103\U00011104\U00011105", 2, TT_UCR_NON_PLANE_0}, /* Chakma */
163 {U"\U00011150\U00011151\U00011152", 2, TT_UCR_NON_PLANE_0}, /* Mahajani */
164 {U"\U00011183\U00011185\U0001118b", 2, TT_UCR_NON_PLANE_0}, /* Sharada */
165 {U"\U00011200\U00011201\U00011202", 2, TT_UCR_NON_PLANE_0}, /* Khojki */
166 {U"\U00011280\U00011281\U00011282", 2, TT_UCR_NON_PLANE_0}, /* Multani */
167 {U"\U000112B0\U000112B2\U000112B4", 2, TT_UCR_NON_PLANE_0}, /* Khudawadi */
168 {U"\U00011305\U00011309\U0001130b", 2, TT_UCR_NON_PLANE_0}, /* Grantha */
169 {U"\U00011400\U00011404\U00011409", 2, TT_UCR_NON_PLANE_0}, /* Newa */
170 {U"\U00011480\U00011481\U00011482", 2, TT_UCR_NON_PLANE_0}, /* Tirhuta */
171 {U"\U00011580\U00011582\U00011589", 2, TT_UCR_NON_PLANE_0}, /* Siddham */
172 {U"\U00011600\U00011604\U00011609", 2, TT_UCR_NON_PLANE_0}, /* Modi */
173 {U"\U00011680\U00011682\U0001168A", 2, TT_UCR_NON_PLANE_0}, /* Takri */
174 {U"\U00011700\U00011701\U00011702", 2, TT_UCR_NON_PLANE_0}, /* Ahom */
175 {U"\U00011800\U00011801\U00011802", 2, TT_UCR_NON_PLANE_0}, /* Dogri */
176 {U"\U000118A0\U000118A1\U000118AA", 2, TT_UCR_NON_PLANE_0}, /* Warang Citi */
177 {U"\U00011900\U00011901\U00011902", 2, TT_UCR_NON_PLANE_0}, /* Dives Akuru */
178 {U"\U00011A00\U00011A10\U00011A15", 2, TT_UCR_NON_PLANE_0}, /* Zanabazar Square */
179 {U"\U00011A50\U00011A5C\U00011A6B", 2, TT_UCR_NON_PLANE_0}, /* Soyombo */
180 {U"\U00011AC0\U00011AC1\U00011AC2", 2, TT_UCR_NON_PLANE_0}, /* Pau Cin Hau */
181 {U"\U00011C00\U00011C01\U00011C02", 2, TT_UCR_NON_PLANE_0}, /* Bhaiksuki */
182 {U"\U00011C70\U00011C71\U00011C72", 2, TT_UCR_NON_PLANE_0}, /* Marchen */
183 {U"\U00011D00\U00011D02\U00011D08", 2, TT_UCR_NON_PLANE_0}, /* Masaram Gondi */
184 {U"\U00011D60\U00011D62\U00011D6c", 2, TT_UCR_NON_PLANE_0}, /* Gunjala Gondi */
185 {U"\U00011FC1\U00011FC2\U00011FC8", 2, TT_UCR_NON_PLANE_0}, /* Tamil Supplement */
186 {U"\U00012F90\U00012F91\U00012F92", 2, TT_UCR_NON_PLANE_0}, /* Cypro-Minoan */
187 {U"\U00013000\U00013076\U0001307f", 2, TT_UCR_NON_PLANE_0}, /* Egyptian Hieroglyphs */
188 {U"\U00014400\U00014409\U00014447", 2, TT_UCR_NON_PLANE_0}, /* Anatolian Hieroglyphs */
189 {U"\U00016A40\U00016A41\U00016A42", 2, TT_UCR_NON_PLANE_0}, /* Mro */
190 {U"\U00016A70\U00016A71\U00016A72", 2, TT_UCR_NON_PLANE_0}, /* Tangsa */
191 {U"\U00016AD0\U00016AD2\U00016ADA", 2, TT_UCR_NON_PLANE_0}, /* Bassa Vah */
192 {U"\U00016B00\U00016B01\U00016B02", 2, TT_UCR_NON_PLANE_0}, /* Pahawh Hmong */
193 {U"\U00016F01\U00016F05\U00016F09", 2, TT_UCR_NON_PLANE_0}, /* Miao */
194 {U"\U0001BC19\U0001BC1f\U0001BC0e", 2, TT_UCR_NON_PLANE_0}, /* Duployan */
195 {U"\U0001D2E0\U0001D2E6\U0001D2f3", 2, TT_UCR_NON_PLANE_0}, /* Mayan Numerals */
196 {U"\U0001E800\U0001E80A\U0001E80F", 2, TT_UCR_NON_PLANE_0}, /* Mende Kikakui */
197 {U"\U0001E900\U0001E902\U0001E907", 2, TT_UCR_NON_PLANE_0}, /* Adlam */
198 {U"\U0001E2C0\U0001E2C2\U0001E2C7", 2, TT_UCR_NON_PLANE_0}, /* Wancho */
199 {U"\U0001EC71\U0001EC72\U0001EC73", 2, TT_UCR_NON_PLANE_0}, /* Indic Siyaq Numbers */
200 /* Basic Multilingual Plane but are not indexed with an OS2 coverage bit. */
201 {U"\u0638\u0630\u0633", 0, 0}, /* Urdu */
202 {U"\u0800\u0801\u0802", 0, 0}, /* Samaritan */
203 {U"\u0841\u0842\u084c", 0, 0}, /* Mandaic */
204 {U"\u1A20\u1A21\u1A22", 0, 0}, /* Tai Tham */
205 {U"\u1BC0\u1BC1\u1BC2", 0, 0}, /* Batak */
206 {U"\uA4EF\uA4E8\uA4ED", 0, 0}, /* Lisu */
207 {U"\uA6A0\uA6A1\uA6A2", 0, 0}, /* Bamum */
208 {U"\ua983\ua984\ua98d", 0, 0}, /* Javanese */
209 {U"\uaa80\uaa81\uaa82", 0, 0}, /* Tai Viet */
210 {U"\uABC0\uABC1\uABC2", 0, 0}, /* Meetei Mayek */
211 /* Near the end since many fonts contain these. */
212 {U"\u03e2\u03e4\u03e8", 1, TT_UCR_COPTIC},
213 {U"\u1f08\u03a6\u03a8", 1, TT_UCR_GREEK},
214 {U"\u0518\u0409\u040f", 1, TT_UCR_CYRILLIC},
215 {U"\u0533\u0537\u0539", 1, TT_UCR_ARMENIAN},
216};
217
218static const char32_t *blf_get_sample_text(const FT_Face face)
219{
220 /* First check for fonts with MS Symbol character map. */
221 if (face->charmap->encoding == FT_ENCODING_MS_SYMBOL) {
222 /* Many of these have characters starting from F020. */
223 if (FT_Get_Char_Index(face, U'\uf041') != 0) {
224 return U"\uf041\uf044\uf048";
225 }
226 if (FT_Get_Char_Index(face, U'\uf030') != 0) {
227 return U"\uf030\uf031\uf032";
228 }
229 return U"ADH";
230 }
231
232 const char32_t *def = U"Aabg";
233 const char32_t *sample = def;
234
235 /* Fonts too old to have a Unicode character map. */
236 if (face->charmap->encoding != FT_ENCODING_UNICODE) {
237 return def;
238 }
239
240 /* TrueType table with bits to quickly test most Unicode block coverage. */
241 TT_OS2 *os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(face, FT_SFNT_OS2);
242 if (!os2_table) {
243 return def;
244 }
245
246 /* Detect "Last resort" fonts. They have everything, except the last 5 bits. */
247 if (os2_table->ulUnicodeRange1 == 0xffffffffU && os2_table->ulUnicodeRange2 == 0xffffffffU &&
248 os2_table->ulUnicodeRange3 == 0xffffffffU && os2_table->ulUnicodeRange4 >= 0x7FFFFFFU)
249 {
250 return U"\xE000\xFFFF";
251 }
252
253 int language_count = count_bits_i(uint(os2_table->ulUnicodeRange1)) +
254 count_bits_i(uint(os2_table->ulUnicodeRange2)) +
255 count_bits_i(uint(os2_table->ulUnicodeRange3)) +
256 count_bits_i(uint(os2_table->ulUnicodeRange4));
257
258 /* Use OS/2 Table code page range bits to differentiate between (combined) CJK fonts.
259 * See https://learn.microsoft.com/en-us/typography/opentype/spec/os2#cpr */
260 FT_ULong codepages = os2_table->ulCodePageRange1;
261 if (codepages & (1 << 19) || codepages & (1 << 21)) {
262 return U"\ud55c\uad6d\uc5b4"; /* 한국어 Korean. */
263 }
264 if (codepages & (1 << 20)) {
265 return U"\u7E41\u9AD4\u5B57"; /* 繁體字 Traditional Chinese. */
266 }
267 if (codepages & (1 << 17) && !(codepages & (1 << 18))) {
268 return U"\u65E5\u672C\u8A9E"; /* 日本語 Japanese. */
269 }
270 if (codepages & (1 << 18) && !(codepages & (1 << 17))) {
271 return U"\u7B80\u4F53\u5B57"; /* 简体字 Simplified Chinese. */
272 }
273
274 for (uint i = 0; i < ARRAY_SIZE(unicode_samples); ++i) {
275 const UnicodeSample *s = &unicode_samples[i];
276 if (os2_table && s->field && s->mask) {
277 /* OS/2 Table contains 4 contiguous integers of script coverage bit flags. */
278 const FT_ULong *unicode_range = &os2_table->ulUnicodeRange1;
279 const int index = (s->field - 1);
280 BLI_assert(index < 4);
281 if (!(unicode_range[index] & s->mask)) {
282 continue;
283 }
284 }
285 if (FT_Get_Char_Index(face, s->sample[0]) != 0) {
286 sample = s->sample;
287 break;
288 }
289 }
290
291 bool has_latin = (os2_table && (os2_table->ulUnicodeRange1 & TT_UCR_BASIC_LATIN) &&
292 (FT_Get_Char_Index(face, U'A') != 0));
293 bool has_cjk = (os2_table && (os2_table->ulUnicodeRange2 & TT_UCR_CJK_UNIFIED_IDEOGRAPHS));
294
295 if (has_latin && ((has_cjk && language_count > 40) || (!has_cjk && language_count > 5))) {
296 return def;
297 }
298
299 return sample;
300}
301
303 const char *filepath, uchar *buf, const int w, const int h, const int /*channels*/)
304{
305 /* Use own FT_Library and direct FreeType calls as this is called from multiple threads. */
306 FT_Library ft_lib = nullptr;
307 if (FT_Init_FreeType(&ft_lib) != FT_Err_Ok) {
308 return false;
309 }
310
311 FT_Face face;
312 if (FT_New_Face(ft_lib, filepath, 0, &face) != FT_Err_Ok) {
313 FT_Done_FreeType(ft_lib);
314 return false;
315 }
316
317 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
318 return false;
319 }
320
321 FT_Error err = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
322 if (err) {
323 err = FT_Select_Charmap(face, FT_ENCODING_MS_SYMBOL);
324 }
325 if (err) {
326 err = FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN);
327 }
328 if (err && face->num_charmaps > 0) {
329 err = FT_Select_Charmap(face, face->charmaps[0]->encoding);
330 }
331 if (err != FT_Err_Ok) {
332 FT_Done_Face(face);
333 FT_Done_FreeType(ft_lib);
334 return false;
335 }
336
337 const char32_t *codepoints = blf_get_sample_text(face);
338 uint glyph_ids[BLF_SAMPLE_LEN] = {0};
339
340 /* A large initial font size for measuring. Nothing will be rendered this size. */
341 if (FT_Set_Char_Size(face, w * 64, 0, 72, 72) != FT_Err_Ok) {
342 FT_Done_Face(face);
343 FT_Done_FreeType(ft_lib);
344 return false;
345 }
346
347 /* Approximate length of the sample. Uses only advances, ignores bearings. */
348 int width = 0;
349 for (uint i = 0; i < BLF_SAMPLE_LEN && codepoints[i]; i++) {
350 glyph_ids[i] = FT_Get_Char_Index(face, codepoints[i]);
351 /* If sample glyph is not found, use another. */
352 if (!glyph_ids[i]) {
353 glyph_ids[i] = uint(face->num_glyphs / (BLF_SAMPLE_LEN + 1)) * (i + 1);
354 }
355 /* Get advance without loading the glyph. */
356 FT_Fixed advance;
357 FT_Get_Advance(face, glyph_ids[i], FT_LOAD_NO_HINTING, &advance);
358 /* Advance is returned in 16.16 format, so divide by 65536 for pixels. */
359 width += int(advance >> 16);
360 }
361
362 int height = ft_pix_to_int((ft_pix)face->size->metrics.ascender -
363 (ft_pix)face->size->metrics.descender);
364 width = std::max(width, height);
365
366 /* Fill up to 96% horizontally or vertically. */
367 float font_size = std::min({float(w),
368 (float(w) * 0.96f / float(width) * float(w)),
369 float(h) * 0.96f / float(height) * float(h)});
370
371 if (font_size < 1 || FT_Set_Char_Size(face, int(font_size * 64.0f), 0, 72, 72) != FT_Err_Ok) {
372 /* Sizing can fail, but very rarely. */
373 FT_Done_Face(face);
374 FT_Done_FreeType(ft_lib);
375 return false;
376 }
377
378 /* Horizontally center, line up baselines vertically. */
379 int left = int((float(w) - (float(width) * (font_size / float(w)))) / 2.0f);
380 int top = int(float(h) * 0.7f);
381
382 /* Print out to buffer. */
383
384 FT_Pos advance_x = 0;
385 int glyph_count = 0; /* How many are successfully loaded and rendered. */
386
387 for (int i = 0; i < BLF_SAMPLE_LEN && glyph_ids[i]; i++) {
388 if (FT_Load_Glyph(face, glyph_ids[i], FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING) != FT_Err_Ok)
389 {
390 break;
391 }
392
393 if (FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL) != FT_Err_Ok ||
394 face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
395 {
396 break;
397 }
398
399 glyph_count++;
400
401 for (int y = 0; y < int(face->glyph->bitmap.rows); y++) {
402 int dest_row = (h - y - 1 + int(face->glyph->bitmap_top) - top);
403 if (dest_row >= 0 && dest_row < h) {
404 for (int x = 0; x < int(face->glyph->bitmap.width); x++) {
405 int dest_col = (x + ft_pix_to_int((ft_pix)advance_x) + face->glyph->bitmap_left + left);
406 if (dest_col >= 0 && dest_col < w) {
407 uchar *source = &face->glyph->bitmap.buffer[y * int(face->glyph->bitmap.width) + x];
408 uchar *dest = &buf[dest_row * w * 4 + (dest_col * 4 + 3)];
409 *dest = uchar(std::min((uint(*dest) + uint(*source)), 255u));
410 }
411 }
412 }
413 }
414
415 advance_x += face->glyph->advance.x;
416 }
417
418 FT_Done_Face(face);
419 FT_Done_FreeType(ft_lib);
420
421 /* Return success if we printed at least one glyph. */
422 return glyph_count > 0;
423}
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE int count_bits_i(unsigned int n)
unsigned char uchar
unsigned int uint
#define ARRAY_SIZE(arr)
#define U
static FT_Library ft_lib
Definition blf_font.cc:62
int32_t ft_pix
int ft_pix_to_int(ft_pix v)
static const char32_t * blf_get_sample_text(const FT_Face face)
static const UnicodeSample unicode_samples[]
Definition blf_thumbs.cc:44
bool BLF_thumb_preview(const char *filepath, uchar *buf, const int w, const int h, const int)
#define BLF_SAMPLE_LEN
Definition blf_thumbs.cc:33
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
nullptr float
uint top
static int left
char32_t sample[BLF_SAMPLE_LEN]
Definition blf_thumbs.cc:36
FT_ULong mask
Definition blf_thumbs.cc:38
i
Definition text_draw.cc:230