diff options
Diffstat (limited to 'src/ui/text.c')
-rw-r--r-- | src/ui/text.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/src/ui/text.c b/src/ui/text.c index 86ac709b..ab2af2b2 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -391,8 +391,12 @@ static void deinitCache_Text_(iText *d) { | |||
391 | SDL_DestroyTexture(d->cache); | 391 | SDL_DestroyTexture(d->cache); |
392 | } | 392 | } |
393 | 393 | ||
394 | iRegExp *makeAnsiEscapePattern_Text(void) { | 394 | iRegExp *makeAnsiEscapePattern_Text(iBool includeEscChar) { |
395 | return new_RegExp("[[()][?]?([0-9;AB]*?)([ABCDEFGHJKSTfhilmn])", 0); | 395 | const char *pattern = "\x1b[[()][?]?([0-9;AB]*?)([ABCDEFGHJKSTfhilmn])"; |
396 | if (!includeEscChar) { | ||
397 | pattern++; | ||
398 | } | ||
399 | return new_RegExp(pattern, 0); | ||
396 | } | 400 | } |
397 | 401 | ||
398 | void init_Text(iText *d, SDL_Renderer *render) { | 402 | void init_Text(iText *d, SDL_Renderer *render) { |
@@ -400,7 +404,7 @@ void init_Text(iText *d, SDL_Renderer *render) { | |||
400 | activeText_ = d; | 404 | activeText_ = d; |
401 | init_Array(&d->fonts, sizeof(iFont)); | 405 | init_Array(&d->fonts, sizeof(iFont)); |
402 | d->contentFontSize = contentScale_Text_; | 406 | d->contentFontSize = contentScale_Text_; |
403 | d->ansiEscape = makeAnsiEscapePattern_Text(); | 407 | d->ansiEscape = makeAnsiEscapePattern_Text(iFalse /* no ESC */); |
404 | d->baseFontId = -1; | 408 | d->baseFontId = -1; |
405 | d->baseFgColorId = -1; | 409 | d->baseFgColorId = -1; |
406 | d->missingGlyphs = iFalse; | 410 | d->missingGlyphs = iFalse; |
@@ -714,6 +718,34 @@ struct Impl_AttributedRun { | |||
714 | 718 | ||
715 | static iColor fgColor_AttributedRun_(const iAttributedRun *d) { | 719 | static iColor fgColor_AttributedRun_(const iAttributedRun *d) { |
716 | if (d->fgColor_.a) { | 720 | if (d->fgColor_.a) { |
721 | /* Ensure legibility if only the foreground color is set. */ | ||
722 | if (!d->bgColor_.a) { | ||
723 | iColor fg = d->fgColor_; | ||
724 | const iHSLColor themeBg = get_HSLColor(tmBackground_ColorId); | ||
725 | const float bgLuminance = luma_Color(get_Color(tmBackground_ColorId)); | ||
726 | /* TODO: Actually this should check if the FG is too close to the BG, and | ||
727 | either darken or brighten the FG. Now it only accounts for nearly black/white | ||
728 | backgrounds. */ | ||
729 | if (bgLuminance < 0.1f) { | ||
730 | /* Background is dark. Lighten the foreground. */ | ||
731 | iHSLColor fgHsl = hsl_Color(fg); | ||
732 | fgHsl.lum = iMax(0.2f, fgHsl.lum); | ||
733 | return rgb_HSLColor(fgHsl); | ||
734 | } | ||
735 | if (bgLuminance > 0.4f) { | ||
736 | float dim = (bgLuminance - 0.4f); | ||
737 | fg.r *= 1.0f * dim; | ||
738 | fg.g *= 1.0f * dim; | ||
739 | fg.b *= 1.0f * dim; | ||
740 | } | ||
741 | if (themeBg.sat > 0.15f && themeBg.lum >= 0.5f) { | ||
742 | iHSLColor fgHsl = hsl_Color(fg); | ||
743 | fgHsl.hue = themeBg.hue; | ||
744 | fgHsl.lum = themeBg.lum * 0.5f; | ||
745 | fg = rgb_HSLColor(fgHsl); | ||
746 | } | ||
747 | return fg; | ||
748 | } | ||
717 | return d->fgColor_; | 749 | return d->fgColor_; |
718 | } | 750 | } |
719 | if (d->attrib.fgColorId == none_ColorId) { | 751 | if (d->attrib.fgColorId == none_ColorId) { |
@@ -1576,7 +1608,7 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1576 | iAssert(xAdvance >= 0); | 1608 | iAssert(xAdvance >= 0); |
1577 | if (wrapMode == word_WrapTextMode) { | 1609 | if (wrapMode == word_WrapTextMode) { |
1578 | /* When word wrapping, only consider certain places breakable. */ | 1610 | /* When word wrapping, only consider certain places breakable. */ |
1579 | if ((prevCh == '-' || prevCh == '/') && !isPunct_Char(ch)) { | 1611 | if ((prevCh == '-' || prevCh == '/' || prevCh == '\\') && !isPunct_Char(ch)) { |
1580 | safeBreakPos = logPos; | 1612 | safeBreakPos = logPos; |
1581 | breakAdvance = wrapAdvance; | 1613 | breakAdvance = wrapAdvance; |
1582 | breakRunIndex = runIndex; | 1614 | breakRunIndex = runIndex; |
@@ -1977,6 +2009,7 @@ static iBool cbAdvanceOneLine_(iWrapText *d, iRangecc range, iTextAttrib attrib, | |||
1977 | } | 2009 | } |
1978 | 2010 | ||
1979 | iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) { | 2011 | iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) { |
2012 | *endPos = text.end; | ||
1980 | iWrapText wrap = { .mode = word_WrapTextMode, | 2013 | iWrapText wrap = { .mode = word_WrapTextMode, |
1981 | .text = text, | 2014 | .text = text, |
1982 | .maxWidth = width, | 2015 | .maxWidth = width, |
@@ -1991,6 +2024,7 @@ iInt2 tryAdvanceNoWrap_Text(int fontId, iRangecc text, int width, const char **e | |||
1991 | *endPos = text.start; | 2024 | *endPos = text.start; |
1992 | return zero_I2(); | 2025 | return zero_I2(); |
1993 | } | 2026 | } |
2027 | *endPos = text.end; | ||
1994 | /* "NoWrap" means words aren't wrapped; the line is broken at nearest character. */ | 2028 | /* "NoWrap" means words aren't wrapped; the line is broken at nearest character. */ |
1995 | iWrapText wrap = { .mode = anyCharacter_WrapTextMode, | 2029 | iWrapText wrap = { .mode = anyCharacter_WrapTextMode, |
1996 | .text = text, | 2030 | .text = text, |