diff options
Diffstat (limited to 'src/ui/text.c')
-rw-r--r-- | src/ui/text.c | 60 |
1 files changed, 47 insertions, 13 deletions
diff --git a/src/ui/text.c b/src/ui/text.c index c19aed2f..83e87d0c 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -258,8 +258,6 @@ static int cmp_PrioMapItem_(const void *a, const void *b) { | |||
258 | } | 258 | } |
259 | 259 | ||
260 | struct Impl_Text { | 260 | struct Impl_Text { |
261 | // enum iTextFont contentFont; | ||
262 | // enum iTextFont headingFont; | ||
263 | float contentFontSize; | 261 | float contentFontSize; |
264 | iArray fonts; /* fonts currently selected for use (incl. all styles/sizes) */ | 262 | iArray fonts; /* fonts currently selected for use (incl. all styles/sizes) */ |
265 | 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 */ |
@@ -276,7 +274,8 @@ struct Impl_Text { | |||
276 | int ansiFlags; | 274 | int ansiFlags; |
277 | int baseFontId; /* base attributes (for restoring via escapes) */ | 275 | int baseFontId; /* base attributes (for restoring via escapes) */ |
278 | int baseFgColorId; | 276 | int baseFgColorId; |
279 | iBool missingGlyphs; /* true if a glyph couldn't be found */ | 277 | iBool missingGlyphs; /* true if a glyph couldn't be found */ |
278 | iChar missingChars[20]; /* rotating buffer of the latest missing characters */ | ||
280 | }; | 279 | }; |
281 | 280 | ||
282 | iDefineTypeConstructionArgs(Text, (SDL_Renderer *render), render) | 281 | iDefineTypeConstructionArgs(Text, (SDL_Renderer *render), render) |
@@ -296,6 +295,7 @@ static void setupFontVariants_Text_(iText *d, const iFontSpec *spec, int baseId) | |||
296 | /* This is the highest priority override font. */ | 295 | /* This is the highest priority override font. */ |
297 | d->overrideFontId = baseId; | 296 | d->overrideFontId = baseId; |
298 | } | 297 | } |
298 | iAssert(activeText_ == d); | ||
299 | pushBack_Array(&d->fontPriorityOrder, &(iPrioMapItem){ spec->priority, baseId }); | 299 | pushBack_Array(&d->fontPriorityOrder, &(iPrioMapItem){ spec->priority, baseId }); |
300 | for (enum iFontStyle style = 0; style < max_FontStyle; style++) { | 300 | for (enum iFontStyle style = 0; style < max_FontStyle; style++) { |
301 | for (enum iFontSize sizeId = 0; sizeId < max_FontSize; sizeId++) { | 301 | for (enum iFontSize sizeId = 0; sizeId < max_FontSize; sizeId++) { |
@@ -357,6 +357,8 @@ static void initFonts_Text_(iText *d) { | |||
357 | printf("[Text] %zu font variants ready\n", size_Array(&d->fonts)); | 357 | printf("[Text] %zu font variants ready\n", size_Array(&d->fonts)); |
358 | #endif | 358 | #endif |
359 | gap_Text = iRound(gap_UI * d->contentFontSize); | 359 | gap_Text = iRound(gap_UI * d->contentFontSize); |
360 | // d->missingGlyphs = iFalse; | ||
361 | // iZap(d->missingChars); | ||
360 | } | 362 | } |
361 | 363 | ||
362 | static void deinitFonts_Text_(iText *d) { | 364 | static void deinitFonts_Text_(iText *d) { |
@@ -424,6 +426,7 @@ void init_Text(iText *d, SDL_Renderer *render) { | |||
424 | d->baseFontId = -1; | 426 | d->baseFontId = -1; |
425 | d->baseFgColorId = -1; | 427 | d->baseFgColorId = -1; |
426 | d->missingGlyphs = iFalse; | 428 | d->missingGlyphs = iFalse; |
429 | iZap(d->missingChars); | ||
427 | d->render = render; | 430 | d->render = render; |
428 | /* A grayscale palette for rasterized glyphs. */ { | 431 | /* A grayscale palette for rasterized glyphs. */ { |
429 | SDL_Color colors[256]; | 432 | SDL_Color colors[256]; |
@@ -497,10 +500,13 @@ static void resetCache_Text_(iText *d) { | |||
497 | } | 500 | } |
498 | 501 | ||
499 | void resetFonts_Text(iText *d) { | 502 | void resetFonts_Text(iText *d) { |
503 | iText *oldActive = activeText_; | ||
504 | setCurrent_Text(d); /* some routines rely on the global `activeText_` pointer */ | ||
500 | deinitFonts_Text_(d); | 505 | deinitFonts_Text_(d); |
501 | deinitCache_Text_(d); | 506 | deinitCache_Text_(d); |
502 | initCache_Text_(d); | 507 | initCache_Text_(d); |
503 | initFonts_Text_(d); | 508 | initFonts_Text_(d); |
509 | setCurrent_Text(oldActive); | ||
504 | } | 510 | } |
505 | 511 | ||
506 | static SDL_Palette *glyphPalette_(void) { | 512 | static SDL_Palette *glyphPalette_(void) { |
@@ -610,8 +616,23 @@ iLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) { | |||
610 | } | 616 | } |
611 | } | 617 | } |
612 | if (!*glyphIndex) { | 618 | if (!*glyphIndex) { |
613 | activeText_->missingGlyphs = iTrue; | 619 | fprintf(stderr, "failed to find %08x (%lc)\n", ch, (int) ch); fflush(stderr); |
614 | fprintf(stderr, "failed to find %08x (%lc)\n", ch, (int)ch); fflush(stderr); | 620 | iText *tx = activeText_; |
621 | tx->missingGlyphs = iTrue; | ||
622 | /* Remember a few of the latest missing characters. */ | ||
623 | iBool gotIt = iFalse; | ||
624 | for (size_t i = 0; i < iElemCount(tx->missingChars); i++) { | ||
625 | if (tx->missingChars[i] == ch) { | ||
626 | gotIt = iTrue; | ||
627 | break; | ||
628 | } | ||
629 | } | ||
630 | if (!gotIt) { | ||
631 | memmove(tx->missingChars + 1, | ||
632 | tx->missingChars, | ||
633 | sizeof(tx->missingChars) - sizeof(tx->missingChars[0])); | ||
634 | tx->missingChars[0] = ch; | ||
635 | } | ||
615 | } | 636 | } |
616 | return d; | 637 | return d; |
617 | } | 638 | } |
@@ -1459,14 +1480,14 @@ static void evenMonospaceAdvances_GlyphBuffer_(iGlyphBuffer *d, iFont *baseFont) | |||
1459 | } | 1480 | } |
1460 | 1481 | ||
1461 | static iRect run_Font_(iFont *d, const iRunArgs *args) { | 1482 | static iRect run_Font_(iFont *d, const iRunArgs *args) { |
1462 | const int mode = args->mode; | 1483 | const int mode = args->mode; |
1463 | const iInt2 orig = args->pos; | 1484 | const iInt2 orig = args->pos; |
1464 | iRect bounds = { orig, init_I2(0, d->height) }; | 1485 | iRect bounds = { orig, init_I2(0, d->height) }; |
1465 | float xCursor = 0.0f; | 1486 | float xCursor = 0.0f; |
1466 | float yCursor = 0.0f; | 1487 | float yCursor = 0.0f; |
1467 | float xCursorMax = 0.0f; | 1488 | float xCursorMax = 0.0f; |
1468 | const iBool isMonospaced = isMonospaced_Font(d); | 1489 | const iBool isMonospaced = isMonospaced_Font(d); |
1469 | iWrapText *wrap = args->wrap; | 1490 | iWrapText *wrap = args->wrap; |
1470 | iAssert(args->text.end >= args->text.start); | 1491 | iAssert(args->text.end >= args->text.start); |
1471 | /* Split the text into a number of attributed runs that specify exactly which | 1492 | /* Split the text into a number of attributed runs that specify exactly which |
1472 | font is used and other attributes such as color. (HarfBuzz shaping is done | 1493 | font is used and other attributes such as color. (HarfBuzz shaping is done |
@@ -2250,6 +2271,19 @@ iBool checkMissing_Text(void) { | |||
2250 | return missing; | 2271 | return missing; |
2251 | } | 2272 | } |
2252 | 2273 | ||
2274 | iChar missing_Text(size_t index) { | ||
2275 | const iText *d = activeText_; | ||
2276 | if (index >= iElemCount(d->missingChars)) { | ||
2277 | return 0; | ||
2278 | } | ||
2279 | return d->missingChars[index]; | ||
2280 | } | ||
2281 | |||
2282 | void resetMissing_Text(iText *d) { | ||
2283 | d->missingGlyphs = iFalse; | ||
2284 | iZap(d->missingChars); | ||
2285 | } | ||
2286 | |||
2253 | SDL_Texture *glyphCache_Text(void) { | 2287 | SDL_Texture *glyphCache_Text(void) { |
2254 | return activeText_->cache; | 2288 | return activeText_->cache; |
2255 | } | 2289 | } |