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 7bb418eb..200108ed 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -390,8 +390,12 @@ static void deinitCache_Text_(iText *d) { | |||
390 | SDL_DestroyTexture(d->cache); | 390 | SDL_DestroyTexture(d->cache); |
391 | } | 391 | } |
392 | 392 | ||
393 | iRegExp *makeAnsiEscapePattern_Text(void) { | 393 | iRegExp *makeAnsiEscapePattern_Text(iBool includeEscChar) { |
394 | return new_RegExp("[[()][?]?([0-9;AB]*?)([ABCDEFGHJKSTfhilmn])", 0); | 394 | const char *pattern = "\x1b[[()][?]?([0-9;AB]*?)([ABCDEFGHJKSTfhilmn])"; |
395 | if (!includeEscChar) { | ||
396 | pattern++; | ||
397 | } | ||
398 | return new_RegExp(pattern, 0); | ||
395 | } | 399 | } |
396 | 400 | ||
397 | void init_Text(iText *d, SDL_Renderer *render) { | 401 | void init_Text(iText *d, SDL_Renderer *render) { |
@@ -399,7 +403,7 @@ void init_Text(iText *d, SDL_Renderer *render) { | |||
399 | activeText_ = d; | 403 | activeText_ = d; |
400 | init_Array(&d->fonts, sizeof(iFont)); | 404 | init_Array(&d->fonts, sizeof(iFont)); |
401 | d->contentFontSize = contentScale_Text_; | 405 | d->contentFontSize = contentScale_Text_; |
402 | d->ansiEscape = makeAnsiEscapePattern_Text(); | 406 | d->ansiEscape = makeAnsiEscapePattern_Text(iFalse /* no ESC */); |
403 | d->baseFontId = -1; | 407 | d->baseFontId = -1; |
404 | d->baseFgColorId = -1; | 408 | d->baseFgColorId = -1; |
405 | d->missingGlyphs = iFalse; | 409 | d->missingGlyphs = iFalse; |
@@ -697,6 +701,34 @@ struct Impl_AttributedRun { | |||
697 | 701 | ||
698 | static iColor fgColor_AttributedRun_(const iAttributedRun *d) { | 702 | static iColor fgColor_AttributedRun_(const iAttributedRun *d) { |
699 | if (d->fgColor_.a) { | 703 | if (d->fgColor_.a) { |
704 | /* Ensure legibility if only the foreground color is set. */ | ||
705 | if (!d->bgColor_.a) { | ||
706 | iColor fg = d->fgColor_; | ||
707 | const iHSLColor themeBg = get_HSLColor(tmBackground_ColorId); | ||
708 | const float bgLuminance = luma_Color(get_Color(tmBackground_ColorId)); | ||
709 | /* TODO: Actually this should check if the FG is too close to the BG, and | ||
710 | either darken or brighten the FG. Now it only accounts for nearly black/white | ||
711 | backgrounds. */ | ||
712 | if (bgLuminance < 0.1f) { | ||
713 | /* Background is dark. Lighten the foreground. */ | ||
714 | iHSLColor fgHsl = hsl_Color(fg); | ||
715 | fgHsl.lum = iMax(0.2f, fgHsl.lum); | ||
716 | return rgb_HSLColor(fgHsl); | ||
717 | } | ||
718 | if (bgLuminance > 0.4f) { | ||
719 | float dim = (bgLuminance - 0.4f); | ||
720 | fg.r *= 1.0f * dim; | ||
721 | fg.g *= 1.0f * dim; | ||
722 | fg.b *= 1.0f * dim; | ||
723 | } | ||
724 | if (themeBg.sat > 0.15f && themeBg.lum >= 0.5f) { | ||
725 | iHSLColor fgHsl = hsl_Color(fg); | ||
726 | fgHsl.hue = themeBg.hue; | ||
727 | fgHsl.lum = themeBg.lum * 0.5f; | ||
728 | fg = rgb_HSLColor(fgHsl); | ||
729 | } | ||
730 | return fg; | ||
731 | } | ||
700 | return d->fgColor_; | 732 | return d->fgColor_; |
701 | } | 733 | } |
702 | if (d->attrib.fgColorId == none_ColorId) { | 734 | if (d->attrib.fgColorId == none_ColorId) { |
@@ -1559,7 +1591,7 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1559 | iAssert(xAdvance >= 0); | 1591 | iAssert(xAdvance >= 0); |
1560 | if (wrapMode == word_WrapTextMode) { | 1592 | if (wrapMode == word_WrapTextMode) { |
1561 | /* When word wrapping, only consider certain places breakable. */ | 1593 | /* When word wrapping, only consider certain places breakable. */ |
1562 | if ((prevCh == '-' || prevCh == '/') && !isPunct_Char(ch)) { | 1594 | if ((prevCh == '-' || prevCh == '/' || prevCh == '\\') && !isPunct_Char(ch)) { |
1563 | safeBreakPos = logPos; | 1595 | safeBreakPos = logPos; |
1564 | breakAdvance = wrapAdvance; | 1596 | breakAdvance = wrapAdvance; |
1565 | breakRunIndex = runIndex; | 1597 | breakRunIndex = runIndex; |
@@ -1960,6 +1992,7 @@ static iBool cbAdvanceOneLine_(iWrapText *d, iRangecc range, iTextAttrib attrib, | |||
1960 | } | 1992 | } |
1961 | 1993 | ||
1962 | iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) { | 1994 | iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) { |
1995 | *endPos = text.end; | ||
1963 | iWrapText wrap = { .mode = word_WrapTextMode, | 1996 | iWrapText wrap = { .mode = word_WrapTextMode, |
1964 | .text = text, | 1997 | .text = text, |
1965 | .maxWidth = width, | 1998 | .maxWidth = width, |
@@ -1974,6 +2007,7 @@ iInt2 tryAdvanceNoWrap_Text(int fontId, iRangecc text, int width, const char **e | |||
1974 | *endPos = text.start; | 2007 | *endPos = text.start; |
1975 | return zero_I2(); | 2008 | return zero_I2(); |
1976 | } | 2009 | } |
2010 | *endPos = text.end; | ||
1977 | /* "NoWrap" means words aren't wrapped; the line is broken at nearest character. */ | 2011 | /* "NoWrap" means words aren't wrapped; the line is broken at nearest character. */ |
1978 | iWrapText wrap = { .mode = anyCharacter_WrapTextMode, | 2012 | iWrapText wrap = { .mode = anyCharacter_WrapTextMode, |
1979 | .text = text, | 2013 | .text = text, |