|
197 | 197 | return ans;
|
198 | 198 | }
|
199 | 199 |
|
| 200 | +static CTFontDescriptorRef _nerd_font_descriptor = NULL; |
| 201 | + |
| 202 | +static CTFontRef nerd_font(CGFloat sz) { |
| 203 | + static bool searched = false; |
| 204 | + if (!searched) { |
| 205 | + searched = true; |
| 206 | + CFArrayRef fonts = CTFontCollectionCreateMatchingFontDescriptors(all_fonts_collection()); |
| 207 | + const CFIndex count = CFArrayGetCount(fonts); |
| 208 | + for (CFIndex i = 0; i < count; i++) { |
| 209 | + CTFontDescriptorRef descriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i); |
| 210 | + CFStringRef name = CTFontDescriptorCopyAttribute(descriptor, kCTFontNameAttribute); |
| 211 | + bool is_nerd_font = cf_string_equals(name, CFSTR("SymbolsNFM")); |
| 212 | + CFRelease(name); |
| 213 | + if (is_nerd_font) { |
| 214 | + _nerd_font_descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, CTFontDescriptorCopyAttributes(descriptor)); |
| 215 | + break; |
| 216 | + } |
| 217 | + } |
| 218 | + CFRelease(fonts); |
| 219 | + } |
| 220 | + return _nerd_font_descriptor ? CTFontCreateWithFontDescriptor(_nerd_font_descriptor, sz, NULL) : NULL; |
| 221 | +} |
| 222 | + |
| 223 | +static bool |
| 224 | +font_can_render_cell(CTFontRef font, CPUCell *cell) { |
| 225 | + char_type ch = cell->ch ? cell->ch : ' '; |
| 226 | + bool found = true; |
| 227 | + if (!glyph_id_for_codepoint_ctfont(font, ch)) found = false; |
| 228 | + for (unsigned i = 0; i < arraysz(cell->cc_idx) && cell->cc_idx[i] && found; i++) { |
| 229 | + char_type cch = codepoint_for_mark(cell->cc_idx[i]); |
| 230 | + if (!glyph_id_for_codepoint_ctfont(font, cch)) found = false; |
| 231 | + } |
| 232 | + return found; |
| 233 | +} |
| 234 | + |
200 | 235 | static CTFontRef
|
201 | 236 | manually_search_fallback_fonts(CTFontRef current_font, CPUCell *cell) {
|
| 237 | + char_type ch = cell->ch ? cell->ch : ' '; |
| 238 | + const bool in_first_pua = 0xe000 <= ch && ch <= 0xf8ff; |
| 239 | + // preferentially load from NERD fonts |
| 240 | + if (in_first_pua) { |
| 241 | + CTFontRef nf = nerd_font(CTFontGetSize(current_font)); |
| 242 | + if (nf) { |
| 243 | + if (font_can_render_cell(nf, cell)) return nf; |
| 244 | + CFRelease(nf); |
| 245 | + } |
| 246 | + } |
202 | 247 | CFArrayRef fonts = CTFontCollectionCreateMatchingFontDescriptors(all_fonts_collection());
|
203 | 248 | CTFontRef ans = NULL;
|
204 | 249 | const CFIndex count = CFArrayGetCount(fonts);
|
205 |
| - char_type ch = cell->ch ? cell->ch : ' '; |
206 |
| - bool in_first_pua = 0xe000 <= ch && ch <= 0xf8ff; |
207 |
| - // preferentially load from NERD fonts |
208 | 250 | for (CFIndex i = 0; i < count; i++) {
|
209 | 251 | CTFontDescriptorRef descriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i);
|
210 |
| - CFStringRef name = CTFontDescriptorCopyAttribute(descriptor, kCTFontNameAttribute); |
211 |
| - bool is_last_resort_font = cf_string_equals(name, CFSTR(LAST_RESORT_FONT_NAME)); |
212 |
| - bool is_nerd_font = cf_string_equals(name, CFSTR("SymbolsNFM")); |
213 |
| - CFRelease(name); |
214 |
| - if (is_last_resort_font) continue; |
215 | 252 | CTFontRef new_font = CTFontCreateWithFontDescriptor(descriptor, CTFontGetSize(current_font), NULL);
|
216 |
| - bool found = true; |
217 |
| - if (!glyph_id_for_codepoint_ctfont(new_font, ch)) found = false; |
218 |
| - for (unsigned i = 0; i < arraysz(cell->cc_idx) && cell->cc_idx[i] && found; i++) { |
219 |
| - char_type cch = codepoint_for_mark(cell->cc_idx[i]); |
220 |
| - if (!glyph_id_for_codepoint_ctfont(new_font, cch)) found = false; |
221 |
| - } |
222 |
| - if (found) { |
223 |
| - // preferentially use NERD font for glyphs in first PUA |
224 |
| - if (!ans || is_nerd_font) { if (ans) CFRelease(ans); ans = new_font; CFRetain(ans); } |
225 |
| - if (is_nerd_font || !in_first_pua) break; |
| 253 | + if (!is_last_resort_font(new_font)) { |
| 254 | + if (font_can_render_cell(new_font, cell)) { |
| 255 | + ans = new_font; |
| 256 | + break; |
| 257 | + } |
226 | 258 | }
|
227 | 259 | CFRelease(new_font);
|
228 | 260 | }
|
|
473 | 505 | if (all_fonts_collection_data) CFRelease(all_fonts_collection_data);
|
474 | 506 | if (window_title_font) CFRelease(window_title_font);
|
475 | 507 | window_title_font = nil;
|
| 508 | + if (_nerd_font_descriptor) CFRelease(_nerd_font_descriptor); |
476 | 509 | }
|
477 | 510 |
|
478 | 511 |
|
|
0 commit comments