=> e72764f55b49643160e387fb942ac113d66620cf
[1mdiff --git a/src/gmdocument.c b/src/gmdocument.c[m [1mindex 0027bdb3..11d477c1 100644[m [1m--- a/src/gmdocument.c[m [1m+++ b/src/gmdocument.c[m [36m@@ -2101,7 +2101,7 @@[m [mvoid setSource_GmDocument(iGmDocument *d, const iString *source, int width, int[m set_String(&d->unormSource, source);[m set_String(&d->source, source);[m /* Detect use of ANSI escapes. */ {[m [31m- iRegExp *ansiEsc = new_RegExp("\x1b[[()]([0-9;AB]*?)m", 0);[m [32m+[m[32m iRegExp *ansiEsc = new_RegExp("\x1b[[()]([0-9;AB]*?)[ABCDEFGHJKSTfimn]", 0);[m iRegExpMatch m;[m init_RegExpMatch(&m);[m const iBool found = matchString_RegExp(ansiEsc, &d->unormSource, &m);[m [36m@@ -2125,6 +2125,7 @@[m [mvoid setSource_GmDocument(iGmDocument *d, const iString *source, int width, int[m else {[m d->theme.ansiEscapes = allowAll_AnsiFlag;[m }[m [32m+[m[32m d->theme.ansiEscapes |= allowBg_AnsiFlag; /* TODO: add setting */[m if (isNormalized_GmDocument_(d)) {[m normalize_GmDocument(d);[m }[m [1mdiff --git a/src/ui/color.c b/src/ui/color.c[m [1mindex 0f7d4368..adbe444b 100644[m [1m--- a/src/ui/color.c[m [1m+++ b/src/ui/color.c[m [36m@@ -785,8 +785,14 @@[m [mstatic const iColor ansi8BitColors_[256] = {[m { 255, 255, 255, 255 }[m };[m [m [31m-iColor ansiForeground_Color(iRangecc escapeSequence, int fallback) {[m [31m- iColor clr = get_Color(fallback);[m [32m+[m[32mvoid ansiColors_Color(iRangecc escapeSequence, int fgDefault, int bgDefault,[m [32m+[m[32m iColor *fg_out, iColor *bg_out) {[m [32m+[m[32m if (!fg_out && !bg_out) {[m [32m+[m[32m return;[m [32m+[m[32m }[m [32m+[m[32m iColor fg, bg;[m [32m+[m[32m iZap(fg);[m [32m+[m[32m iZap(bg);[m for (const char *ch = escapeSequence.start; ch < escapeSequence.end; ch++) {[m char *endPtr;[m unsigned long arg = strtoul(ch, &endPtr, 10);[m [36m@@ -802,19 +808,37 @@[m [miColor ansiForeground_Color(iRangecc escapeSequence, int fallback) {[m case 35:[m case 36:[m case 37:[m [31m- clr = ansi8BitColors_[arg - 30];[m [32m+[m[32m fg = ansi8BitColors_[arg - 30];[m break;[m [31m- case 38: {[m [32m+[m[32m case 38:[m [32m+[m[32m case 48: {[m [32m+[m[32m iColor *dst = (arg == 38 ? &fg : &bg);[m /* Extended foreground color. */[m arg = strtoul(ch + 1, &endPtr, 10);[m ch = endPtr;[m if (arg == 5) /* 8-bit palette */ {[m arg = strtoul(ch + 1, &endPtr, 10);[m ch = endPtr;[m [31m- clr = ansi8BitColors_[iClamp(arg, 0, 255)];[m [32m+[m[32m *dst = ansi8BitColors_[iClamp(arg, 0, 255)];[m }[m break;[m }[m [32m+[m[32m case 39:[m [32m+[m[32m fg = get_Color(fgDefault);[m [32m+[m[32m break;[m [32m+[m[32m case 40:[m [32m+[m[32m case 41:[m [32m+[m[32m case 42:[m [32m+[m[32m case 43:[m [32m+[m[32m case 44:[m [32m+[m[32m case 45:[m [32m+[m[32m case 46:[m [32m+[m[32m case 47:[m [32m+[m[32m bg = ansi8BitColors_[arg - 40];[m [32m+[m[32m break;[m [32m+[m[32m case 49:[m [32m+[m[32m bg = get_Color(bgDefault);[m [32m+[m[32m break;[m case 90:[m case 91:[m case 92:[m [36m@@ -823,17 +847,36 @@[m [miColor ansiForeground_Color(iRangecc escapeSequence, int fallback) {[m case 95:[m case 96:[m case 97:[m [31m- clr = ansi8BitColors_[8 + arg - 90];[m [32m+[m[32m fg = ansi8BitColors_[8 + arg - 90];[m break;[m }[m }[m [31m- /* On light backgrounds, darken the colors to make them more legible. */[m [31m- if (get_HSLColor(tmBackground_ColorId).lum > 0.5f) {[m [31m- clr.r /= 2;[m [31m- clr.g /= 2;[m [31m- clr.b /= 2;[m [32m+[m[32m /* Ensure legibility if only one of the colors is set. */[m [32m+[m[32m /* TODO: Force darkening of the background color, unless it is also specified. */[m [32m+[m[32m#if 0[m [32m+[m[32m if (bg.a == 0 && !equal_Color(fg, get_Color(fgDefault))) {[m [32m+[m[32m if (delta_Color(fg, get_Color(tmBackground_ColorId)) < 64) {[m [32m+[m[32m const iHSLColor fgHsl = hsl_Color(fg);[m [32m+[m[32m iHSLColor legibleBg = get_HSLColor(tmBackground_ColorId);[m [32m+[m[32m if ()[m [32m+[m[32m bg = rgb_HSLColor(bgHsl);[m [32m+[m[32m }[m[41m [m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m#endif[m [32m+[m[32m /*[m [32m+[m[32m if (!bg_out || get_HSLColor(tmBackground_ColorId).lum > 0.5f) {[m [32m+[m[32m fg.r /= 2;[m [32m+[m[32m fg.g /= 2;[m [32m+[m[32m fg.b /= 2;[m [32m+[m[32m }[m [32m+[m[32m */[m [32m+[m[32m if (fg.a && fg_out) {[m [32m+[m[32m *fg_out = fg;[m [32m+[m[32m }[m [32m+[m[32m if (bg.a && bg_out) {[m [32m+[m[32m *bg_out = bg;[m }[m [31m- return clr;[m }[m [m iBool loadPalette_Color(const char *path) {[m [1mdiff --git a/src/ui/color.h b/src/ui/color.h[m [1mindex 03172fcb..6602b226 100644[m [1m--- a/src/ui/color.h[m [1m+++ b/src/ui/color.h[m [36m@@ -255,7 +255,8 @@[m [miLocalDef void setHsl_Color(int color, iHSLColor hsl) {[m iBool loadPalette_Color (const char *path);[m void setThemePalette_Color (enum iColorTheme theme);[m [m [31m-iColor ansiForeground_Color (iRangecc escapeSequence, int fallback);[m [32m+[m[32mvoid ansiColors_Color (iRangecc escapeSequence, int fgDefault, int bgDefault,[m [32m+[m[32m iColor *fg_out, iColor *bg_out); /* can be NULL */[m const char * escape_Color (int color);[m enum iColorId parseEscape_Color (const char *cstr, const char **endp);[m [m [1mdiff --git a/src/ui/text.c b/src/ui/text.c[m [1mindex 91633f27..91ff137a 100644[m [1m--- a/src/ui/text.c[m [1m+++ b/src/ui/text.c[m [36m@@ -263,7 +263,7 @@[m [mstruct Impl_Text {[m iRegExp * ansiEscape;[m int ansiFlags;[m int baseFontId; /* base attributes (for restoring via escapes) */[m [31m- int baseColorId;[m [32m+[m[32m int baseFgColorId;[m iBool missingGlyphs; /* true if a glyph couldn't be found */[m };[m [m [36m@@ -390,35 +390,14 @@[m [mstatic void deinitCache_Text_(iText *d) {[m SDL_DestroyTexture(d->cache);[m }[m [m [31m-#if 0[m [31m-void loadUserFonts_Text(void) {[m [31m- if (userFont_) {[m [31m- delete_Block(userFont_);[m [31m- userFont_ = NULL;[m [31m- }[m [31m- /* Load the system font. */[m [31m- const iPrefs *prefs = prefs_App();[m [31m- if (!isEmpty_String(&prefs->symbolFontPath)) {[m [31m- iFile *f = new_File(&prefs->symbolFontPath);[m [31m- if (open_File(f, readOnly_FileMode)) {[m [31m- userFont_ = readAll_File(f);[m [31m- }[m [31m- else {[m [31m- fprintf(stderr, "[Text] failed to open: %s\n", cstr_String(&prefs->symbolFontPath));[m [31m- }[m [31m- iRelease(f);[m [31m- }[m [31m-}[m [31m-#endif[m [31m-[m void init_Text(iText *d, SDL_Renderer *render) {[m iText *oldActive = activeText_;[m activeText_ = d;[m init_Array(&d->fonts, sizeof(iFont));[m d->contentFontSize = contentScale_Text_;[m [31m- d->ansiEscape = new_RegExp("[[()]([0-9;AB]*?)m", 0);[m [32m+[m[32m d->ansiEscape = new_RegExp("[[()][?]?([0-9;AB]*?)([ABCDEFGHJKSTfhilmn])", 0);[m d->baseFontId = -1;[m [31m- d->baseColorId = -1;[m [32m+[m[32m d->baseFgColorId = -1;[m d->render = render;[m /* A grayscale palette for rasterized glyphs. */ {[m SDL_Color colors[256];[m [36m@@ -459,9 +438,10 @@[m [mvoid setOpacity_Text(float opacity) {[m SDL_SetTextureAlphaMod(activeText_->cache, iClamp(opacity, 0.0f, 1.0f) * 255 + 0.5f);[m }[m [m [31m-void setBaseAttributes_Text(int fontId, int colorId) {[m [31m- activeText_->baseFontId = fontId;[m [31m- activeText_->baseColorId = colorId;[m [32m+[m[32mvoid setBaseAttributes_Text(int fontId, int fgColorId) {[m [32m+[m[32m iText *d = activeText_;[m [32m+[m[32m d->baseFontId = fontId;[m [32m+[m[32m d->baseFgColorId = fgColorId;[m }[m [m void setAnsiFlags_Text(int ansiFlags) {[m [36m@@ -574,16 +554,6 @@[m [miLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) {[m return overrideFont;[m }[m }[m [31m-#if 0[m [31m- /* TODO: Put arrows in Smol Emoji. */[m [31m- /* Manual exceptions. */ {[m [31m- if (ch >= 0x2190 && ch <= 0x2193 /* arrows */) {[m [31m- d = font_Text_(iosevka_FontId + d->sizeId);[m [31m- *glyphIndex = glyphIndex_Font_(d, ch);[m [31m- return d;[m [31m- }[m [31m- }[m [31m-#endif[m /* The font's own version of the glyph. */[m if ((*glyphIndex = glyphIndex_Font_(d, ch)) != 0) {[m return d;[m [36m@@ -609,69 +579,6 @@[m [miLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) {[m }[m }[m }[m [31m-#if 0[m [31m- const int fallbacks[] = {[m [31m- notoEmoji_FontId,[m [31m- symbols2_FontId,[m [31m- symbols_FontId[m [31m- };[m [31m- /* First fallback is Smol Emoji. */[m [31m- if (ch != 0x20) {[m [31m- iForIndices(i, fallbacks) {[m [31m- iFont *fallback = font_Text_(fallbacks[i] + d->sizeId);[m [31m- if (fallback != d && (*glyphIndex = glyphIndex_Font_(fallback, ch)) != 0) {[m [31m- return fallback;[m [31m- }[m [31m- }[m [31m- }[m [31m- /* Try Simplified Chinese. */[m [31m- if (ch >= 0x2e80) {[m [31m- iFont *sc = font_Text_(chineseSimplified_FontId + d->sizeId);[m [31m- if (sc != d && (*glyphIndex = glyphIndex_Font_(sc, ch)) != 0) {[m [31m- return sc;[m [31m- }[m [31m- }[m [31m- /* Could be Korean. */[m [31m- if (ch >= 0x3000) {[m [31m- iFont *korean = font_Text_(korean_FontId + d->sizeId);[m [31m- if (korean != d && (*glyphIndex = glyphIndex_Font_(korean, ch)) != 0) {[m [31m- return korean;[m [31m- }[m [31m- }[m [31m- /* Japanese perhaps? */[m [31m- if (ch > 0x3040) {[m [31m- iFont *japanese = font_Text_(japanese_FontId + d->sizeId);[m [31m- if (japanese != d && (*glyphIndex = glyphIndex_Font_(japanese, ch)) != 0) {[m [31m- return japanese;[m [31m- }[m [31m- }[m [31m- /* Maybe Arabic. */[m [31m- if (ch >= 0x600) {[m [31m- iFont *arabic = font_Text_(arabic_FontId + d->sizeId);[m [31m- if (arabic != d && (*glyphIndex = glyphIndex_Font_(arabic, ch)) != 0) {[m [31m- return arabic;[m [31m- }[m [31m- }[m [31m-#if defined (iPlatformApple)[m [31m- /* White up arrow is used for the Shift key on macOS. Symbola's glyph is not a great[m [31m- match to the other text, so use the UI font instead. */[m [31m- if ((ch == 0x2318 || ch == 0x21e7) && d == font_Text_(regular_FontId)) {[m [31m- *glyphIndex = glyphIndex_Font_(d = font_Text_(defaultContentRegular_FontId), ch);[m [31m- return d;[m [31m- }[m [31m-#endif[m [31m- /* User's symbols font. */ {[m [31m- iFont *sys = font_Text_(userSymbols_FontId + d->sizeId);[m [31m- if (sys != d && (*glyphIndex = glyphIndex_Font_(sys, ch)) != 0) {[m [31m- return sys;[m [31m- }[m [31m- }[m [31m- /* Final fallback. */[m [31m- iFont *font = font_Text_(iosevka_FontId + d->sizeId);[m [31m- if (d != font) {[m [31m- *glyphIndex = glyphIndex_Font_(font, ch);[m [31m- }[m [31m-#endif // 0[m if (!*glyphIndex) {[m activeText_->missingGlyphs = iTrue;[m fprintf(stderr, "failed to find %08x (%lc)\n", ch, (int)ch); fflush(stderr);[m [36m@@ -680,7 +587,9 @@[m [miLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) {[m }[m [m static iGlyph *glyphByIndex_Font_(iFont *d, uint32_t glyphIndex) {[m [31m- iAssert(d->table);[m [32m+[m[32m if (!d->table) {[m [32m+[m[32m d->table = new_GlyphTable();[m [32m+[m[32m }[m[41m [m iGlyph* glyph = NULL;[m void * node = value_Hash(&d->table->glyphs, glyphIndex);[m if (node) {[m [36m@@ -739,6 +648,7 @@[m [mstruct Impl_AttributedRun {[m iTextAttrib attrib;[m iFont *font;[m iColor fgColor_; /* any RGB color; A > 0 */[m [32m+[m[32m iColor bgColor_; /* any RGB color; A > 0 */[m struct {[m uint8_t isLineBreak : 1;[m // uint8_t isRTL : 1;[m [36m@@ -750,29 +660,45 @@[m [mstatic iColor fgColor_AttributedRun_(const iAttributedRun *d) {[m if (d->fgColor_.a) {[m return d->fgColor_;[m }[m [31m- if (d->attrib.colorId == none_ColorId) {[m [32m+[m[32m if (d->attrib.fgColorId == none_ColorId) {[m return (iColor){ 255, 255, 255, 255 };[m }[m [31m- return get_Color(d->attrib.colorId);[m [32m+[m[32m return get_Color(d->attrib.fgColorId);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic iColor bgColor_AttributedRun_(const iAttributedRun *d) {[m [32m+[m[32m if (d->bgColor_.a) {[m [32m+[m[32m return d->bgColor_;[m [32m+[m[32m }[m [32m+[m[32m return (iColor){ 255, 255, 255, 0 };[m [32m+[m[32m if (d->attrib.bgColorId == none_ColorId) {[m [32m+[m[32m return (iColor){ 255, 255, 255, 0 };[m [32m+[m[32m }[m [32m+[m[32m return get_Color(d->attrib.bgColorId);[m }[m [m static void setFgColor_AttributedRun_(iAttributedRun *d, int colorId) {[m [31m- d->attrib.colorId = colorId;[m [32m+[m[32m d->attrib.fgColorId = colorId;[m d->fgColor_.a = 0;[m }[m [m [32m+[m[32mstatic void setBgColor_AttributedRun_(iAttributedRun *d, int colorId) {[m [32m+[m[32m d->attrib.bgColorId = colorId;[m [32m+[m[32m d->bgColor_.a = 0;[m [32m+[m[32m}[m [32m+[m iDeclareType(AttributedText)[m iDeclareTypeConstructionArgs(AttributedText, iRangecc text, size_t maxLen, iFont *font,[m [31m- int colorId, int baseDir, iFont *baseFont, int baseColorId,[m [32m+[m[32m int colorId, int baseDir, iFont *baseFont, int baseFgColorId,[m iChar overrideChar)[m [m struct Impl_AttributedText {[m iRangecc source; /* original source text */[m size_t maxLen;[m iFont * font;[m [31m- int colorId;[m [32m+[m[32m int fgColorId;[m iFont * baseFont;[m [31m- int baseColorId;[m [32m+[m[32m int baseFgColorId;[m iBool isBaseRTL;[m iArray runs;[m iArray logical; /* UTF-32 text in logical order (mixed directions; matches source) */[m [36m@@ -785,9 +711,9 @@[m [mstruct Impl_AttributedText {[m [m iDefineTypeConstructionArgs(AttributedText,[m (iRangecc text, size_t maxLen, iFont *font, int colorId,[m [31m- int baseDir, iFont *baseFont, int baseColorId,[m [32m+[m[32m int baseDir, iFont *baseFont, int baseFgColorId,[m iChar overrideChar),[m [31m- text, maxLen, font, colorId, baseDir, baseFont, baseColorId,[m [32m+[m[32m text, maxLen, font, colorId, baseDir, baseFont, baseFgColorId,[m overrideChar)[m [m static const char *sourcePtr_AttributedText_(const iAttributedText *d, int logicalPos) {[m [36m@@ -897,7 +823,8 @@[m [mstatic void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iCh[m }[m iAttributedRun run = {[m .logical = { 0, length },[m [31m- .attrib = { .colorId = d->colorId, .isBaseRTL = d->isBaseRTL },[m [32m+[m[32m .attrib = { .fgColorId = d->fgColorId, .bgColorId = none_ColorId,[m [32m+[m[32m .isBaseRTL = d->isBaseRTL },[m .font = d->font,[m };[m const int *logToSource = constData_Array(&d->logicalToSourceOffset);[m [36m@@ -935,12 +862,13 @@[m [mstatic void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iCh[m if (match_RegExp(activeText_->ansiEscape, srcPos, d->source.end - srcPos, &m)) {[m finishRun_AttributedText_(d, &run, pos - 1);[m const int ansi = activeText_->ansiFlags;[m [31m- if (ansi) {[m [32m+[m[32m if (ansi && capturedRange_RegExpMatch(&m, 2).start[0] ==[m [32m+[m[32m 'm' /* Select Graphic Rendition */) {[m const iRangecc sequence = capturedRange_RegExpMatch(&m, 1);[m /* Note: This styling is hardcoded to match `typesetOneLine_RunTypesetter_()`. */[m if (ansi & allowFontStyle_AnsiFlag && equal_Rangecc(sequence, "1")) {[m run.attrib.bold = iTrue;[m [31m- if (d->baseColorId == tmParagraph_ColorId) {[m [32m+[m[32m if (d->baseFgColorId == tmParagraph_ColorId) {[m setFgColor_AttributedRun_(&run, tmFirstParagraph_ColorId);[m }[m attribFont = font_Text_(fontWithStyle_Text(fontId_Text_(d->baseFont),[m [36m@@ -962,10 +890,13 @@[m [mstatic void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iCh[m run.attrib.italic = iFalse;[m run.attrib.monospace = iFalse;[m attribFont = run.font = d->baseFont;[m [31m- setFgColor_AttributedRun_(&run, d->baseColorId);[m [32m+[m[32m setFgColor_AttributedRun_(&run, d->baseFgColorId);[m [32m+[m[32m setBgColor_AttributedRun_(&run, none_ColorId);[m }[m [31m- else if (ansi & allowFg_AnsiFlag) {[m [31m- run.fgColor_ = ansiForeground_Color(sequence, tmParagraph_ColorId);[m [32m+[m[32m else {[m [32m+[m[32m ansiColors_Color(sequence, d->baseFgColorId, none_ColorId,[m [32m+[m[32m ansi & allowFg_AnsiFlag ? &run.fgColor_ : NULL,[m [32m+[m[32m ansi & allowBg_AnsiFlag ? &run.bgColor_ : NULL);[m }[m }[m pos += length_Rangecc(capturedRange_RegExpMatch(&m, 0));[m [36m@@ -988,7 +919,7 @@[m [mstatic void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iCh[m colorNum = esc - asciiBase_ColorEscape;[m }[m run.logical.start = pos + 1;[m [31m- setFgColor_AttributedRun_(&run, colorNum >= 0 ? colorNum : d->colorId);[m [32m+[m[32m setFgColor_AttributedRun_(&run, colorNum >= 0 ? colorNum : d->fgColorId);[m continue;[m }[m if (ch == '\n') {[m [36m@@ -1051,14 +982,15 @@[m [mstatic void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iCh[m }[m [m void init_AttributedText(iAttributedText *d, iRangecc text, size_t maxLen, iFont *font, int colorId,[m [31m- int baseDir, iFont *baseFont, int baseColorId, iChar overrideChar) {[m [31m- d->source = text;[m [31m- d->maxLen = maxLen ? maxLen : iInvalidSize;[m [31m- d->font = font;[m [31m- d->colorId = colorId;[m [31m- d->baseFont = baseFont;[m [31m- d->baseColorId = baseColorId;[m [31m- d->isBaseRTL = iFalse;[m [32m+[m[32m int baseDir, iFont *baseFont, int baseFgColorId,[m[41m [m [32m+[m[32m iChar overrideChar) {[m [32m+[m[32m d->source = text;[m [32m+[m[32m d->maxLen = maxLen ? maxLen : iInvalidSize;[m [32m+[m[32m d->font = font;[m [32m+[m[32m d->fgColorId = colorId;[m [32m+[m[32m d->baseFont = baseFont;[m [32m+[m[32m d->baseFgColorId = baseFgColorId;[m [32m+[m[32m d->isBaseRTL = iFalse;[m init_Array(&d->runs, sizeof(iAttributedRun));[m init_Array(&d->logical, sizeof(iChar));[m init_Array(&d->visual, sizeof(iChar));[m [36m@@ -1412,7 +1344,7 @@[m [mstatic iRect run_Font_(iFont *d, const iRunArgs *args) {[m init_AttributedText(&attrText, args->text, args->maxLen, d, args->color,[m args->baseDir,[m activeText_->baseFontId >= 0 ? font_Text_(activeText_->baseFontId) : d,[m [31m- activeText_->baseColorId,[m [32m+[m[32m activeText_->baseFgColorId,[m[41m [m wrap ? wrap->overrideChar : 0);[m if (wrap) {[m wrap->baseDir = attrText.isBaseRTL ? -1 : +1;[m [36m@@ -1464,7 +1396,9 @@[m [mstatic iRect run_Font_(iFont *d, const iRunArgs *args) {[m iRangei wrapPosRange = { 0, textLen };[m int wrapResumePos = textLen; /* logical position where next line resumes */[m size_t wrapResumeRunIndex = runCount; /* index of run where next line resumes */[m [31m- iTextAttrib attrib = { .colorId = args->color, .isBaseRTL = attrText.isBaseRTL };[m [32m+[m[32m iTextAttrib attrib = { .fgColorId = args->color,[m [32m+[m[32m .bgColorId = none_ColorId,[m [32m+[m[32m .isBaseRTL = attrText.isBaseRTL };[m iTextAttrib wrapAttrib = attrib;[m iTextAttrib lastAttrib = attrib;[m const int layoutBound = (wrap ? wrap->maxWidth : 0);[m [36m@@ -1712,6 +1646,12 @@[m [mstatic iRect run_Font_(iFont *d, const iRunArgs *args) {[m yCursor += d->height;[m continue;[m }[m [32m+[m[32m const iColor fgClr = fgColor_AttributedRun_(run);[m [32m+[m[32m const iColor bgClr = bgColor_AttributedRun_(run);[m [32m+[m[32m iBool isBgFilled = iFalse;[m [32m+[m[32m if (~mode & permanentColorFlag_RunMode) {[m [32m+[m[32m isBgFilled = (bgClr.a != 0) || (mode & fillBackground_RunMode);[m [32m+[m[32m }[m iGlyphBuffer *buf = at_Array(&buffers, runIndex);[m shape_GlyphBuffer_(buf);[m iAssert(run->font == buf->font);[m [36m@@ -1772,34 +1712,46 @@[m [mstatic iRect run_Font_(iFont *d, const iRunArgs *args) {[m bounds.size.x = iMax(bounds.size.x, dst.x + dst.w - orig.x);[m bounds.size.y = iMax(bounds.size.y, yCursor + glyph->font->height);[m }[m [31m- if (mode & draw_RunMode && logicalText[logPos] > 0x20) {[m [32m+[m[32m const iBool isSpace = (logicalText[logPos] == 0x20);[m [32m+[m[32m if (mode & draw_RunMode && (isBgFilled || !isSpace)) {[m /* Draw the glyph. */[m [31m- if (!isRasterized_Glyph_(glyph, hoff)) {[m [32m+[m[32m if (!isSpace && !isRasterized_Glyph_(glyph, hoff)) {[m cacheSingleGlyph_Font_(run->font, glyphId); /* may cause cache reset */[m glyph = glyphByIndex_Font_(run->font, glyphId);[m iAssert(isRasterized_Glyph_(glyph, hoff));[m }[m if (~mode & permanentColorFlag_RunMode) {[m [31m- const iColor clr = fgColor_AttributedRun_(run);[m [31m- SDL_SetTextureColorMod(activeText_->cache, clr.r, clr.g, clr.b);[m [31m- if (args->mode & fillBackground_RunMode) {[m [31m- SDL_SetRenderDrawColor(activeText_->render, clr.r, clr.g, clr.b, 0);[m [31m- }[m [32m+[m[32m SDL_SetTextureColorMod(activeText_->cache, fgClr.r, fgClr.g, fgClr.b);[m }[m [31m- SDL_Rect src;[m [31m- memcpy(&src, &glyph->rect[hoff], sizeof(SDL_Rect));[m dst.x += origin_Paint.x;[m dst.y += origin_Paint.y;[m [31m- if (args->mode & fillBackground_RunMode) {[m [31m- /* Alpha blending looks much better if the RGB components don't change in[m [31m- the partially transparent pixels. */[m [32m+[m[32m if (isBgFilled) {[m /* TODO: Backgrounds of all glyphs should be cleared before drawing anything else. */[m [31m- SDL_RenderFillRect(activeText_->render, &dst);[m [32m+[m[32m if (bgClr.a) {[m [32m+[m[32m SDL_SetRenderDrawColor(activeText_->render, bgClr.r, bgClr.g, bgClr.b, 255);[m [32m+[m[32m const SDL_Rect bgRect = {[m [32m+[m[32m origin_Paint.x + orig.x + xCursor,[m [32m+[m[32m origin_Paint.y + orig.y + yCursor,[m [32m+[m[32m xAdvance,[m [32m+[m[32m d->height,[m [32m+[m[32m };[m [32m+[m[32m SDL_RenderFillRect(activeText_->render, &bgRect);[m [32m+[m[32m }[m [32m+[m[32m else if (args->mode & fillBackground_RunMode) {[m [32m+[m[32m /* Alpha blending looks much better if the RGB components don't change[m [32m+[m[32m in the partially transparent pixels. */[m [32m+[m[32m SDL_SetRenderDrawColor(activeText_->render, fgClr.r, fgClr.g, fgClr.b, 0);[m [32m+[m[32m SDL_RenderFillRect(activeText_->render, &dst);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m if (!isSpace) {[m [32m+[m[32m SDL_Rect src;[m [32m+[m[32m memcpy(&src, &glyph->rect[hoff], sizeof(SDL_Rect));[m [32m+[m[32m SDL_RenderCopy(activeText_->render, activeText_->cache, &src, &dst);[m }[m [31m- SDL_RenderCopy(activeText_->render, activeText_->cache, &src, &dst);[m #if 0[m /* Show spaces and direction. */[m [31m- if (logicalText[logPos] == 0x20) {[m [32m+[m[32m if (isSpace) {[m const iColor debug = get_Color(run->flags.isRTL ? yellow_ColorId : red_ColorId);[m SDL_SetRenderDrawColor(text_.render, debug.r, debug.g, debug.b, 255);[m dst.w = xAdvance;[m [1mdiff --git a/src/ui/text.h b/src/ui/text.h[m [1mindex 13a636d4..de76ed09 100644[m [1m--- a/src/ui/text.h[m [1m+++ b/src/ui/text.h[m [36m@@ -157,7 +157,7 @@[m [menum iAnsiFlag {[m };[m [m void setOpacity_Text (float opacity);[m [31m-void setBaseAttributes_Text (int fontId, int colorId); /* current "normal" text attributes */[m [32m+[m[32mvoid setBaseAttributes_Text (int fontId, int fgColorId); /* current "normal" text attributes */[m void setAnsiFlags_Text (int ansiFlags);[m [m void cache_Text (int fontId, iRangecc text); /* pre-render glyphs */[m [36m@@ -187,7 +187,8 @@[m [miDeclareType(TextAttrib)[m /* Initial attributes at the start of a text string. These may be modified by control[m sequences inside a text run. */[m struct Impl_TextAttrib {[m [31m- int16_t colorId;[m [32m+[m[32m int16_t fgColorId;[m [32m+[m[32m int16_t bgColorId;[m struct {[m uint16_t bold : 1;[m uint16_t italic : 1;[m
text/gemini; charset=utf-8
This content has been proxied by September (3851b).