diff options
Diffstat (limited to 'src/ui/text.c')
-rw-r--r-- | src/ui/text.c | 61 |
1 files changed, 39 insertions, 22 deletions
diff --git a/src/ui/text.c b/src/ui/text.c index ab2af2b2..51531057 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -246,10 +246,22 @@ struct Impl_CacheRow { | |||
246 | iInt2 pos; | 246 | iInt2 pos; |
247 | }; | 247 | }; |
248 | 248 | ||
249 | iDeclareType(PrioMapItem) | ||
250 | struct Impl_PrioMapItem { | ||
251 | int priority; | ||
252 | uint32_t fontIndex; | ||
253 | }; | ||
254 | |||
255 | static int cmp_PrioMapItem_(const void *a, const void *b) { | ||
256 | const iPrioMapItem *i = a, *j = b; | ||
257 | return -iCmp(i->priority, j->priority); | ||
258 | } | ||
259 | |||
249 | struct Impl_Text { | 260 | struct Impl_Text { |
250 | float contentFontSize; | 261 | float contentFontSize; |
251 | iArray fonts; /* fonts currently selected for use (incl. all styles/sizes) */ | 262 | iArray fonts; /* fonts currently selected for use (incl. all styles/sizes) */ |
252 | int overrideFontId; /* always checked for glyphs first, regardless of which font is used */ | 263 | int overrideFontId; /* always checked for glyphs first, regardless of which font is used */ |
264 | iArray fontPriorityOrder; | ||
253 | SDL_Renderer * render; | 265 | SDL_Renderer * render; |
254 | SDL_Texture * cache; | 266 | SDL_Texture * cache; |
255 | iInt2 cacheSize; | 267 | iInt2 cacheSize; |
@@ -283,8 +295,9 @@ static void setupFontVariants_Text_(iText *d, const iFontSpec *spec, int baseId) | |||
283 | /* This is the highest priority override font. */ | 295 | /* This is the highest priority override font. */ |
284 | d->overrideFontId = baseId; | 296 | d->overrideFontId = baseId; |
285 | } | 297 | } |
298 | pushBack_Array(&d->fontPriorityOrder, &(iPrioMapItem){ spec->priority, baseId }); | ||
286 | for (enum iFontStyle style = 0; style < max_FontStyle; style++) { | 299 | for (enum iFontStyle style = 0; style < max_FontStyle; style++) { |
287 | for (enum iFontSize sizeId = 0; sizeId < max_FontSize; sizeId++) { | 300 | for (enum iFontSize sizeId = 0; sizeId < max_FontSize; sizeId++) { |
288 | init_Font(font_Text_(FONT_ID(baseId, style, sizeId)), | 301 | init_Font(font_Text_(FONT_ID(baseId, style, sizeId)), |
289 | spec, | 302 | spec, |
290 | spec->styles[style], | 303 | spec->styles[style], |
@@ -321,6 +334,7 @@ static void initFonts_Text_(iText *d) { | |||
321 | and styles for each available font. Indices to `fonts` act as font runtime IDs. */ | 334 | and styles for each available font. Indices to `fonts` act as font runtime IDs. */ |
322 | /* First the mandatory fonts. */ | 335 | /* First the mandatory fonts. */ |
323 | d->overrideFontId = -1; | 336 | d->overrideFontId = -1; |
337 | clear_Array(&d->fontPriorityOrder); | ||
324 | resize_Array(&d->fonts, auxiliary_FontId); /* room for the built-ins */ | 338 | resize_Array(&d->fonts, auxiliary_FontId); /* room for the built-ins */ |
325 | setupFontVariants_Text_(d, tryFindSpec_(uiFont_PrefsString, "default"), default_FontId); | 339 | setupFontVariants_Text_(d, tryFindSpec_(uiFont_PrefsString, "default"), default_FontId); |
326 | setupFontVariants_Text_(d, tryFindSpec_(monospaceFont_PrefsString, "iosevka"), monospace_FontId); | 340 | setupFontVariants_Text_(d, tryFindSpec_(monospaceFont_PrefsString, "iosevka"), monospace_FontId); |
@@ -330,12 +344,14 @@ static void initFonts_Text_(iText *d) { | |||
330 | /* Check if there are auxiliary fonts available and set those up, too. */ | 344 | /* Check if there are auxiliary fonts available and set those up, too. */ |
331 | iConstForEach(PtrArray, s, listSpecsByPriority_Fonts()) { | 345 | iConstForEach(PtrArray, s, listSpecsByPriority_Fonts()) { |
332 | const iFontSpec *spec = s.ptr; | 346 | const iFontSpec *spec = s.ptr; |
347 | // printf("spec '%s': prio=%d\n", cstr_String(&spec->name), spec->priority); | ||
333 | if (spec->flags & (auxiliary_FontSpecFlag | user_FontSpecFlag)) { | 348 | if (spec->flags & (auxiliary_FontSpecFlag | user_FontSpecFlag)) { |
334 | const int fontId = size_Array(&d->fonts); | 349 | const int fontId = size_Array(&d->fonts); |
335 | resize_Array(&d->fonts, fontId + maxVariants_Fonts); | 350 | resize_Array(&d->fonts, fontId + maxVariants_Fonts); |
336 | setupFontVariants_Text_(d, spec, fontId); | 351 | setupFontVariants_Text_(d, spec, fontId); |
337 | } | 352 | } |
338 | } | 353 | } |
354 | sort_Array(&d->fontPriorityOrder, cmp_PrioMapItem_); | ||
339 | #if !defined (NDEBUG) | 355 | #if !defined (NDEBUG) |
340 | printf("[Text] %zu font variants ready\n", size_Array(&d->fonts)); | 356 | printf("[Text] %zu font variants ready\n", size_Array(&d->fonts)); |
341 | #endif | 357 | #endif |
@@ -403,6 +419,7 @@ void init_Text(iText *d, SDL_Renderer *render) { | |||
403 | iText *oldActive = activeText_; | 419 | iText *oldActive = activeText_; |
404 | activeText_ = d; | 420 | activeText_ = d; |
405 | init_Array(&d->fonts, sizeof(iFont)); | 421 | init_Array(&d->fonts, sizeof(iFont)); |
422 | init_Array(&d->fontPriorityOrder, sizeof(iPrioMapItem)); | ||
406 | d->contentFontSize = contentScale_Text_; | 423 | d->contentFontSize = contentScale_Text_; |
407 | d->ansiEscape = makeAnsiEscapePattern_Text(iFalse /* no ESC */); | 424 | d->ansiEscape = makeAnsiEscapePattern_Text(iFalse /* no ESC */); |
408 | d->baseFontId = -1; | 425 | d->baseFontId = -1; |
@@ -438,6 +455,7 @@ void deinit_Text(iText *d) { | |||
438 | deinitCache_Text_(d); | 455 | deinitCache_Text_(d); |
439 | d->render = NULL; | 456 | d->render = NULL; |
440 | iRelease(d->ansiEscape); | 457 | iRelease(d->ansiEscape); |
458 | deinit_Array(&d->fontPriorityOrder); | ||
441 | deinit_Array(&d->fonts); | 459 | deinit_Array(&d->fonts); |
442 | } | 460 | } |
443 | 461 | ||
@@ -573,25 +591,24 @@ iLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) { | |||
573 | if ((*glyphIndex = glyphIndex_Font_(d, ch)) != 0) { | 591 | if ((*glyphIndex = glyphIndex_Font_(d, ch)) != 0) { |
574 | return d; | 592 | return d; |
575 | } | 593 | } |
576 | /* As a fallback, check all other available fonts of this size. */ | 594 | /* As a fallback, check all other available fonts of this size in priority order. */ |
577 | for (int aux = 0; aux < 2; aux++) { | 595 | iConstForEach(Array, i, &activeText_->fontPriorityOrder) { |
578 | for (iFont *font = font_Text_(FONT_ID(0, styleId, sizeId)); | 596 | iFont *font = font_Text_(FONT_ID(((const iPrioMapItem *) i.value)->fontIndex, |
579 | font < (iFont *) end_Array(&activeText_->fonts); | 597 | styleId, sizeId)); |
580 | font += maxVariants_Fonts) { | 598 | if (font == d || font == overrideFont) { |
581 | const iBool isAuxiliary = (font->fontSpec->flags & auxiliary_FontSpecFlag) ? 1 : 0; | 599 | continue; /* already checked this one */ |
582 | if (aux == isAuxiliary) { | 600 | } |
583 | /* First try auxiliary fonts, then other remaining fonts. */ | 601 | if ((*glyphIndex = glyphIndex_Font_(font, ch)) != 0) { |
584 | continue; | 602 | #if 0 |
585 | } | 603 | printf("using '%s' (pr:%d) for %lc (%x) => %d [missing in '%s']\n", |
586 | if (font == d || font == overrideFont) { | 604 | cstr_String(&font->fontSpec->id), |
587 | continue; /* already checked this one */ | 605 | font->fontSpec->priority, |
588 | } | 606 | (int) ch, |
589 | if ((*glyphIndex = glyphIndex_Font_(font, ch)) != 0) { | 607 | ch, |
590 | // printf("using %s[%f] for %lc (%x) => %d\n", | 608 | glyphIndex_Font_(font, ch), |
591 | // cstr_String(&font->fontSpec->name), font->fontSpec->scaling, | 609 | cstr_String(&d->fontSpec->id)); |
592 | // (int) ch, ch, glyphIndex_Font_(font, ch)); | 610 | #endif |
593 | return font; | 611 | return font; |
594 | } | ||
595 | } | 612 | } |
596 | } | 613 | } |
597 | if (!*glyphIndex) { | 614 | if (!*glyphIndex) { |
@@ -1450,7 +1467,7 @@ static void evenMonospaceAdvances_GlyphBuffer_(iGlyphBuffer *d, iFont *baseFont) | |||
1450 | if (d->glyphPos[i].x_advance > 0 && d->font != baseFont) { | 1467 | if (d->glyphPos[i].x_advance > 0 && d->font != baseFont) { |
1451 | const iChar ch = d->logicalText[info->cluster]; | 1468 | const iChar ch = d->logicalText[info->cluster]; |
1452 | if (isPictograph_Char(ch) || isEmoji_Char(ch)) { | 1469 | if (isPictograph_Char(ch) || isEmoji_Char(ch)) { |
1453 | const float dw = d->font->xScale * d->glyphPos[i].x_advance - monoAdvance; | 1470 | const float dw = d->font->xScale * d->glyphPos[i].x_advance - (isEmoji_Char(ch) ? 2 : 1) * monoAdvance; |
1454 | d->glyphPos[i].x_offset -= dw / 2 / d->font->xScale - 1; | 1471 | d->glyphPos[i].x_offset -= dw / 2 / d->font->xScale - 1; |
1455 | d->glyphPos[i].x_advance -= dw / d->font->xScale - 1; | 1472 | d->glyphPos[i].x_advance -= dw / d->font->xScale - 1; |
1456 | } | 1473 | } |