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 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
393iRegExp *makeAnsiEscapePattern_Text(void) { 393iRegExp *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
397void init_Text(iText *d, SDL_Renderer *render) { 401void 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
698static iColor fgColor_AttributedRun_(const iAttributedRun *d) { 702static 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
1962iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) { 1994iInt2 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,