summaryrefslogtreecommitdiff
path: root/src/ui/text.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/text.c')
-rw-r--r--src/ui/text.c42
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
394iRegExp *makeAnsiEscapePattern_Text(void) { 394iRegExp *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
398void init_Text(iText *d, SDL_Renderer *render) { 402void 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
715static iColor fgColor_AttributedRun_(const iAttributedRun *d) { 719static 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
1979iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) { 2011iInt2 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,