summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-08-05 16:30:34 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-08-05 16:30:34 +0300
commitf38a940d722064e4b3fb2df6a6c0bcc025383ca0 (patch)
treef3df6097a60b04ff324cf9105f9cb1a4dbd825c9 /src
parent2b1de0641335ab1a88aeafcc8911056f155e94c9 (diff)
Color palette theming
Diffstat (limited to 'src')
-rw-r--r--src/gmdocument.c184
-rw-r--r--src/gmdocument.h10
-rw-r--r--src/ui/color.c23
-rw-r--r--src/ui/color.h22
-rw-r--r--src/ui/documentwidget.c74
5 files changed, 252 insertions, 61 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c
index e23d5836..a631739f 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -265,14 +265,14 @@ static void doLayout_GmDocument_(iGmDocument *d) {
265 regular_FontId, 265 regular_FontId,
266 }; 266 };
267 static const int colors[max_GmLineType] = { 267 static const int colors[max_GmLineType] = {
268 gray75_ColorId, 268 tmParagraph_ColorId,
269 gray75_ColorId, 269 tmParagraph_ColorId,
270 cyan_ColorId, 270 tmPreformatted_ColorId,
271 gray75_ColorId, 271 tmQuote_ColorId,
272 white_ColorId, 272 tmHeader1_ColorId,
273 white_ColorId, 273 tmHeader2_ColorId,
274 white_ColorId, 274 tmHeader3_ColorId,
275 white_ColorId, 275 tmLinkText_ColorId,
276 }; 276 };
277 static const int indents[max_GmLineType] = { 277 static const int indents[max_GmLineType] = {
278 5, 10, 5, 10, 0, 0, 0, 5 278 5, 10, 5, 10, 0, 0, 0, 5
@@ -363,7 +363,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
363 banner.visBounds = init_Rect(0, 0, d->size.x, lineHeight_Text(banner_FontId) * 2); 363 banner.visBounds = init_Rect(0, 0, d->size.x, lineHeight_Text(banner_FontId) * 2);
364 banner.font = banner_FontId; 364 banner.font = banner_FontId;
365 banner.text = bannerText; 365 banner.text = bannerText;
366 banner.color = gray50_ColorId; 366 banner.color = tmBannerTitle_ColorId;
367 pushBack_Array(&d->layout, &banner); 367 pushBack_Array(&d->layout, &banner);
368 pos.y += height_Rect(banner.visBounds) + lineHeight_Text(paragraph_FontId); 368 pos.y += height_Rect(banner.visBounds) + lineHeight_Text(paragraph_FontId);
369 } 369 }
@@ -419,10 +419,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
419 if (link->flags & remote_GmLinkFlag) { 419 if (link->flags & remote_GmLinkFlag) {
420 run.visBounds.pos.x -= gap_Text / 2; 420 run.visBounds.pos.x -= gap_Text / 2;
421 } 421 }
422 run.color = linkColor_GmDocument(d, run.linkId); 422 run.color = linkColor_GmDocument(d, run.linkId, icon_GmLinkPart);
423 if (link->flags & visited_GmLinkFlag) {
424 run.color--; /* darker */
425 }
426 pushBack_Array(&d->layout, &run); 423 pushBack_Array(&d->layout, &run);
427 } 424 }
428 run.color = colors[type]; 425 run.color = colors[type];
@@ -433,7 +430,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
433 int bigCount = 0; 430 int bigCount = 0;
434 if (type == text_GmLineType && isFirstText) { 431 if (type == text_GmLineType && isFirstText) {
435 run.font = firstParagraph_FontId; 432 run.font = firstParagraph_FontId;
436 run.color = white_ColorId; 433 run.color = tmFirstParagraph_ColorId;
437 bigCount = 15; /* max lines -- what if the whole document is one paragraph? */ 434 bigCount = 15; /* max lines -- what if the whole document is one paragraph? */
438 isFirstText = iFalse; 435 isFirstText = iFalse;
439 } 436 }
@@ -549,6 +546,14 @@ void reset_GmDocument(iGmDocument *d) {
549 d->themeSeed = 0; 546 d->themeSeed = 0;
550} 547}
551 548
549static float fixHue_(float hue) {
550 if (hue > 260 && hue < 330) {
551 if (hue < 295) return hue - 90;
552 return hue + 90;
553 }
554 return hue;
555}
556
552void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { 557void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) {
553 static const iChar siteIcons[] = { 558 static const iChar siteIcons[] = {
554 0x25ed, 0x2600, 0x2601, 0x2604, 0x2605, 0x2606, 0x265c, 0x265e, 0x2690, 559 0x25ed, 0x2600, 0x2601, 0x2604, 0x2605, 0x2606, 0x265c, 0x265e, 0x2690,
@@ -560,14 +565,106 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) {
560 }; 565 };
561 d->themeSeed = 0; 566 d->themeSeed = 0;
562 d->siteIcon = 0; 567 d->siteIcon = 0;
568 /* Default colors. */ {
569 const iHSLColor base = { 0, 0, 0.15f, 1.0f };
570 setHsl_Color(tmBackground_ColorId, base);
571 }
563 if (seed && !isEmpty_Block(seed)) { 572 if (seed && !isEmpty_Block(seed)) {
564 d->themeSeed = crc32_Block(seed); 573 d->themeSeed = crc32_Block(seed);
565 d->siteIcon = siteIcons[(d->themeSeed >> 7) % iElemCount(siteIcons)]; 574 d->siteIcon = siteIcons[(d->themeSeed >> 7) % iElemCount(siteIcons)];
575 /* Set up colors. */ {
576 static const float hues[] = {
577 0, 60, 90, 100, 180, 210, 230, 260, 330
578 };
579 const iBool isDesaturated = iFalse;
580 const iBool isLowSaturated = iFalse;
581 const iBool isLightMode = iFalse;
582 const iBool isBannerLighter = (d->themeSeed & 0x4000) != 0;
583 iHSLColor base = { hues[(d->themeSeed & 0xff) % iElemCount(hues)],
584 0.8f * (d->themeSeed >> 24) / 255.0f,
585 0.06f + 0.09f * ((d->themeSeed >> 5) & 0x7) / 7.0f,
586 1.0f };
587 printf("background: %d %f %f\n", (int) base.hue, base.sat, base.lum);
588 setHsl_Color(tmBackground_ColorId, base);
589
590 setHsl_Color(tmBannerBackground_ColorId, addSatLum_HSLColor(base, 0.1f, 0.04f * (isBannerLighter ? 1 : -1)));
591 setHsl_Color(tmBannerTitle_ColorId, setLum_HSLColor(addSatLum_HSLColor(base, 0.1f, 0), 0.55f));
592 setHsl_Color(tmBannerIcon_ColorId, setLum_HSLColor(addSatLum_HSLColor(base, 0.35f, 0), 0.65f));
593
594 const iBool altDir = (d->themeSeed & 0x4) != 0;
595 const float altHue = fixHue_(iWrapf(base.hue + (altDir ? 90 : -90), 0, 360));
596 const float altHue2 = fixHue_(iWrapf(base.hue + (altDir ? -30 : 30), 0, 360));
597 iHSLColor altBase = base;
598 altBase.hue = altHue;
599 const float titleLum = 0.2f * ((d->themeSeed >> 17) & 0x7) / 7.0f;
600 setHsl_Color(tmHeader1_ColorId, setLum_HSLColor(altBase, titleLum + 0.80f));
601 setHsl_Color(tmHeader2_ColorId, setLum_HSLColor(altBase, titleLum + 0.70f));
602 setHsl_Color(tmHeader3_ColorId, setLum_HSLColor(altBase, titleLum + 0.60f));
603
604 setHsl_Color(tmParagraph_ColorId, addSatLum_HSLColor(base, 0.1f, 0.6f));
605 setHsl_Color(tmFirstParagraph_ColorId, addSatLum_HSLColor(base, 0.2f, 0.8f));
606 setHsl_Color(tmPreformatted_ColorId, (iHSLColor){ altHue2, 1.0f, 0.75f, 1.0f });
607 set_Color(tmQuote_ColorId, get_Color(tmPreformatted_ColorId));
608 set_Color(tmInlineContentMetadata_ColorId, get_Color(tmHeader3_ColorId));
609 set_Color(tmBadLink_ColorId, get_Color(red_ColorId));
610
611 set_Color(tmLinkText_ColorId, get_Color(white_ColorId));
612 set_Color(tmLinkIcon_ColorId, get_Color(cyan_ColorId));
613 set_Color(tmLinkTextHover_ColorId, get_Color(cyan_ColorId));
614 set_Color(tmLinkIconVisited_ColorId, get_Color(teal_ColorId));
615 set_Color(tmLinkDomain_ColorId, get_Color(teal_ColorId));
616 set_Color(tmLinkLastVisitDate_ColorId, get_Color(cyan_ColorId));
617
618 set_Color(tmHypertextLinkText_ColorId, get_Color(white_ColorId));
619 set_Color(tmHypertextLinkIcon_ColorId, get_Color(orange_ColorId));
620 set_Color(tmHypertextLinkTextHover_ColorId, get_Color(orange_ColorId));
621 set_Color(tmHypertextLinkIconVisited_ColorId, get_Color(brown_ColorId));
622 set_Color(tmHypertextLinkDomain_ColorId, get_Color(brown_ColorId));
623 set_Color(tmHypertextLinkLastVisitDate_ColorId, get_Color(orange_ColorId));
624
625 set_Color(tmGopherLinkText_ColorId, get_Color(white_ColorId));
626 set_Color(tmGopherLinkIcon_ColorId, get_Color(blue_ColorId));
627 set_Color(tmGopherLinkTextHover_ColorId, get_Color(blue_ColorId));
628 set_Color(tmGopherLinkIconVisited_ColorId, get_Color(magenta_ColorId));
629 set_Color(tmGopherLinkDomain_ColorId, get_Color(magenta_ColorId));
630 set_Color(tmGopherLinkLastVisitDate_ColorId, get_Color(blue_ColorId));
631
632 for (int i = tmFirst_ColorId; i < max_ColorId; i++) {
633 iHSLColor color = hsl_Color(get_Color(i));
634 if (isLightMode) {
635 color.lum = 1.0f - color.lum;
636 }
637 if (i < tmBadLink_ColorId) { /* Not a link? */
638 if (isLowSaturated) {
639 color.sat *= 0.3f;
640 }
641 if (isDesaturated) {
642 color.sat = 0;
643 }
644 if (isLightMode) {
645 /* Darken text. */
646 if (i == tmParagraph_ColorId || i == tmLinkText_ColorId ||
647 i == tmHypertextLinkText_ColorId || i == tmGopherLinkText_ColorId) {
648 color.lum *= 0.5f;
649 }
650 else if (i == tmBannerIcon_ColorId) {
651 color.lum *= 0.75f;
652 }
653 }
654 }
655 else if (isLightMode) {
656 /* Darken links. */
657 color.lum *= 0.75f;
658 color.sat = 1.0f;
659 }
660 setHsl_Color(i, color);
661 }
662 }
566 } 663 }
567 /* Special exceptions. */ { 664 /* Special exceptions. */
568 const iRangecc host = urlHost_String(&d->url); 665 if (seed) {
569 if (equalCase_Rangecc(&host, "gemini.circumlunar.space")) { 666 if (equal_CStr(cstr_Block(seed), "gemini.circumlunar.space")) {
570 d->siteIcon = 0x264a; /* gemini */ 667 d->siteIcon = 0x264a; /* gemini symbol */
571 } 668 }
572 } 669 }
573} 670}
@@ -787,17 +884,54 @@ uint16_t linkImage_GmDocument(const iGmDocument *d, iGmLinkId linkId) {
787 return 0; 884 return 0;
788} 885}
789 886
790enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId) { 887enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId, enum iGmLinkPart part) {
791 const iGmLink *link = link_GmDocument_(d, linkId); 888 const iGmLink *link = link_GmDocument_(d, linkId);
792 if (link) { 889 if (link) {
793 if ((link->flags & supportedProtocol_GmLinkFlag) == 0) { 890 const iBool isBad = (link->flags & supportedProtocol_GmLinkFlag) == 0;
794 return red_ColorId; 891 if (part == icon_GmLinkPart) {
892 if (isBad) {
893 return tmBadLink_ColorId;
894 }
895 if (link->flags & visited_GmLinkFlag) {
896 return link->flags & http_GmLinkFlag
897 ? tmHypertextLinkIconVisited_ColorId
898 : link->flags & gopher_GmLinkFlag ? tmGopherLinkIconVisited_ColorId
899 : tmLinkIconVisited_ColorId;
900 }
901 return link->flags & http_GmLinkFlag
902 ? tmHypertextLinkIcon_ColorId
903 : link->flags & gopher_GmLinkFlag ? tmGopherLinkIcon_ColorId
904 : tmLinkIcon_ColorId;
905 }
906 if (part == text_GmLinkPart) {
907 return link->flags & http_GmLinkFlag
908 ? tmHypertextLinkText_ColorId
909 : link->flags & gopher_GmLinkFlag ? tmGopherLinkText_ColorId
910 : tmLinkText_ColorId;
911 }
912 if (part == textHover_GmLinkPart) {
913 return link->flags & http_GmLinkFlag
914 ? tmHypertextLinkTextHover_ColorId
915 : link->flags & gopher_GmLinkFlag ? tmGopherLinkTextHover_ColorId
916 : tmLinkTextHover_ColorId;
917 }
918 if (part == domain_GmLinkPart) {
919 if (isBad) {
920 return tmBadLink_ColorId;
921 }
922 return link->flags & http_GmLinkFlag
923 ? tmHypertextLinkDomain_ColorId
924 : link->flags & gopher_GmLinkFlag ? tmGopherLinkDomain_ColorId
925 : tmLinkDomain_ColorId;
926 }
927 if (part == visited_GmLinkPart) {
928 return link->flags & http_GmLinkFlag
929 ? tmHypertextLinkLastVisitDate_ColorId
930 : link->flags & gopher_GmLinkFlag ? tmGopherLinkLastVisitDate_ColorId
931 : tmLinkLastVisitDate_ColorId;
795 } 932 }
796 return link->flags & http_GmLinkFlag
797 ? orange_ColorId
798 : link->flags & gopher_GmLinkFlag ? blue_ColorId : cyan_ColorId;
799 } 933 }
800 return white_ColorId; 934 return tmLinkText_ColorId;
801} 935}
802 936
803iBool isMediaLink_GmDocument(const iGmDocument *d, iGmLinkId linkId) { 937iBool isMediaLink_GmDocument(const iGmDocument *d, iGmLinkId linkId) {
diff --git a/src/gmdocument.h b/src/gmdocument.h
index b0a7df22..42639357 100644
--- a/src/gmdocument.h
+++ b/src/gmdocument.h
@@ -80,13 +80,21 @@ iInt2 sizeWithoutBanner_GmDocument (const iGmDocument *);
80iRangecc findText_GmDocument (const iGmDocument *, const iString *text, const char *start); 80iRangecc findText_GmDocument (const iGmDocument *, const iString *text, const char *start);
81iRangecc findTextBefore_GmDocument (const iGmDocument *, const iString *text, const char *before); 81iRangecc findTextBefore_GmDocument (const iGmDocument *, const iString *text, const char *before);
82 82
83enum iGmLinkPart {
84 icon_GmLinkPart,
85 text_GmLinkPart,
86 textHover_GmLinkPart,
87 domain_GmLinkPart,
88 visited_GmLinkPart,
89};
90
83const iGmRun * findRun_GmDocument (const iGmDocument *, iInt2 pos); 91const iGmRun * findRun_GmDocument (const iGmDocument *, iInt2 pos);
84const char * findLoc_GmDocument (const iGmDocument *, iInt2 pos); 92const char * findLoc_GmDocument (const iGmDocument *, iInt2 pos);
85const iGmRun * findRunAtLoc_GmDocument (const iGmDocument *, const char *loc); 93const iGmRun * findRunAtLoc_GmDocument (const iGmDocument *, const char *loc);
86const iString * linkUrl_GmDocument (const iGmDocument *, iGmLinkId linkId); 94const iString * linkUrl_GmDocument (const iGmDocument *, iGmLinkId linkId);
87uint16_t linkImage_GmDocument (const iGmDocument *, iGmLinkId linkId); 95uint16_t linkImage_GmDocument (const iGmDocument *, iGmLinkId linkId);
88int linkFlags_GmDocument (const iGmDocument *, iGmLinkId linkId); 96int linkFlags_GmDocument (const iGmDocument *, iGmLinkId linkId);
89enum iColorId linkColor_GmDocument (const iGmDocument *, iGmLinkId linkId); 97enum iColorId linkColor_GmDocument (const iGmDocument *, iGmLinkId linkId, enum iGmLinkPart part);
90const iTime * linkTime_GmDocument (const iGmDocument *, iGmLinkId linkId); 98const iTime * linkTime_GmDocument (const iGmDocument *, iGmLinkId linkId);
91iBool isMediaLink_GmDocument (const iGmDocument *, iGmLinkId linkId); 99iBool isMediaLink_GmDocument (const iGmDocument *, iGmLinkId linkId);
92const iString * title_GmDocument (const iGmDocument *); 100const iString * title_GmDocument (const iGmDocument *);
diff --git a/src/ui/color.c b/src/ui/color.c
index 0402d0fb..a2ff6e27 100644
--- a/src/ui/color.c
+++ b/src/ui/color.c
@@ -100,9 +100,12 @@ static float hueToRgb_(float p, float q, float t) {
100 return p; 100 return p;
101} 101}
102 102
103iColor fromHsl_Color(iHSLColor hsl) { 103iColor rgb_HSLColor(iHSLColor hsl) {
104 float r, g, b; 104 float r, g, b;
105 hsl.hue /= 360.0f; 105 hsl.hue /= 360.0f;
106 hsl.hue = iWrapf(hsl.hue, 0, 1);
107 hsl.sat = iClamp(hsl.sat, 0.0f, 1.0f);
108 hsl.lum = iClamp(hsl.lum, 0.0f, 1.0f);
106 if (hsl.sat < 0.00001f) { 109 if (hsl.sat < 0.00001f) {
107 r = g = b = hsl.lum; 110 r = g = b = hsl.lum;
108 } 111 }
@@ -137,7 +140,23 @@ const char *escape_Color(int color) {
137 if (color >= 0 && color < (int) iElemCount(esc)) { 140 if (color >= 0 && color < (int) iElemCount(esc)) {
138 return esc[color]; 141 return esc[color];
139 } 142 }
140 return white_ColorEscape; 143 return format_CStr("\r%c", color + '0');
144}
145
146iHSLColor setSat_HSLColor(iHSLColor d, float sat) {
147 d.sat = iClamp(sat, 0, 1);
148 return d;
149}
150
151iHSLColor setLum_HSLColor(iHSLColor d, float lum) {
152 d.lum = iClamp(lum, 0, 1);
153 return d;
154}
155
156iHSLColor addSatLum_HSLColor(iHSLColor d, float sat, float lum) {
157 d.sat = iClamp(d.sat + sat, 0, 1);
158 d.lum = iClamp(d.lum + lum, 0, 1);
159 return d;
141} 160}
142 161
143iColor ansi_Color(iRangecc escapeSequence, int fallback) { 162iColor ansi_Color(iRangecc escapeSequence, int fallback) {
diff --git a/src/ui/color.h b/src/ui/color.h
index 11feb63e..c3cacf77 100644
--- a/src/ui/color.h
+++ b/src/ui/color.h
@@ -19,6 +19,7 @@ enum iColorId {
19 magenta_ColorId, 19 magenta_ColorId,
20 blue_ColorId, 20 blue_ColorId,
21 green_ColorId, 21 green_ColorId,
22
22 /* content theme colors */ 23 /* content theme colors */
23 tmFirst_ColorId, 24 tmFirst_ColorId,
24 tmBackground_ColorId = tmFirst_ColorId, 25 tmBackground_ColorId = tmFirst_ColorId,
@@ -29,6 +30,11 @@ enum iColorId {
29 tmHeader1_ColorId, 30 tmHeader1_ColorId,
30 tmHeader2_ColorId, 31 tmHeader2_ColorId,
31 tmHeader3_ColorId, 32 tmHeader3_ColorId,
33 tmBannerBackground_ColorId,
34 tmBannerTitle_ColorId,
35 tmBannerIcon_ColorId,
36 tmInlineContentMetadata_ColorId,
37 tmBadLink_ColorId,
32 38
33 tmLinkIcon_ColorId, 39 tmLinkIcon_ColorId,
34 tmLinkIconVisited_ColorId, 40 tmLinkIconVisited_ColorId,
@@ -51,10 +57,6 @@ enum iColorId {
51 tmGopherLinkDomain_ColorId, 57 tmGopherLinkDomain_ColorId,
52 tmGopherLinkLastVisitDate_ColorId, 58 tmGopherLinkLastVisitDate_ColorId,
53 59
54 tmInlineContentMetadata_ColorId,
55 tmBannerBackground_ColorId,
56 tmBannerTitle_ColorId,
57 tmBannerIcon_ColorId,
58 max_ColorId 60 max_ColorId
59}; 61};
60 62
@@ -87,11 +89,19 @@ struct Impl_HSLColor {
87 float hue, sat, lum, a; 89 float hue, sat, lum, a;
88}; 90};
89 91
92iHSLColor hsl_Color (iColor);
93iColor rgb_HSLColor (iHSLColor);
94
95iHSLColor setSat_HSLColor (iHSLColor, float sat);
96iHSLColor setLum_HSLColor (iHSLColor, float lum);
97iHSLColor addSatLum_HSLColor (iHSLColor, float sat, float lum);
98
90iColor get_Color (int color); 99iColor get_Color (int color);
91void set_Color (int color, iColor rgba); 100void set_Color (int color, iColor rgba);
92 101
93iHSLColor hsl_Color (iColor rgba); 102iLocalDef void setHsl_Color(int color, iHSLColor hsl) {
94iColor fromHsl_Color (iHSLColor hsl); 103 set_Color(color, rgb_HSLColor(hsl));
104}
95 105
96iColor ansi_Color (iRangecc escapeSequence, int fallback); 106iColor ansi_Color (iRangecc escapeSequence, int fallback);
97const char * escape_Color (int color); 107const char * escape_Color (int color);
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index dbcf57eb..48eb482f 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -841,6 +841,16 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
841 return iTrue; 841 return iTrue;
842 } 842 }
843 break; 843 break;
844 case SDLK_9: {
845 iBlock *seed = new_Block(64);
846 for (size_t i = 0; i < 64; ++i) {
847 setByte_Block(seed, i, iRandom(0, 255));
848 }
849 setThemeSeed_GmDocument(d->doc, seed);
850 delete_Block(seed);
851 refresh_Widget(w);
852 break;
853 }
844#if 0 854#if 0
845 case '0': { 855 case '0': {
846 extern int enableHalfPixelGlyphs_Text; 856 extern int enableHalfPixelGlyphs_Text;
@@ -1013,34 +1023,38 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1013 !isEmpty_Rect(run->bounds)); 1023 !isEmpty_Rect(run->bounds));
1014 const iInt2 visPos = add_I2(run->visBounds.pos, origin); 1024 const iInt2 visPos = add_I2(run->visBounds.pos, origin);
1015 /* Text markers. */ 1025 /* Text markers. */
1026 /* TODO: Add themed palette entries */
1016 fillRange_DrawContext_(d, run, teal_ColorId, d->widget->foundMark, &d->inFoundMark); 1027 fillRange_DrawContext_(d, run, teal_ColorId, d->widget->foundMark, &d->inFoundMark);
1017 fillRange_DrawContext_(d, run, brown_ColorId, d->widget->selectMark, &d->inSelectMark); 1028 fillRange_DrawContext_(d, run, brown_ColorId, d->widget->selectMark, &d->inSelectMark);
1018 if (run->linkId && !isEmpty_Rect(run->bounds)) { 1029 if (run->linkId && !isEmpty_Rect(run->bounds)) {
1019// const int flags = linkFlags_GmDocument(doc, run->linkId); 1030 fg = linkColor_GmDocument(doc, run->linkId, isHover ? textHover_GmLinkPart : text_GmLinkPart);
1020 fg = /*flags & visited_GmLinkFlag ? gray88_ColorId :*/ white_ColorId; 1031 if (linkFlags_GmDocument(doc, run->linkId) & content_GmLinkFlag) {
1021 if (isHover || linkFlags_GmDocument(doc, run->linkId) & content_GmLinkFlag) { 1032 fg = linkColor_GmDocument(doc, run->linkId, textHover_GmLinkPart); /* link is inactive */
1022 fg = linkColor_GmDocument(doc, run->linkId);
1023 } 1033 }
1024 } 1034 }
1025 if (run->flags & siteBanner_GmRunFlag) { 1035 if (run->flags & siteBanner_GmRunFlag) {
1036 /* Draw the site banner. */
1026 fillRect_Paint( 1037 fillRect_Paint(
1027 &d->paint, 1038 &d->paint,
1028 initCorners_Rect(topLeft_Rect(d->widgetBounds), 1039 initCorners_Rect(topLeft_Rect(d->widgetBounds),
1029 init_I2(right_Rect(bounds_Widget(constAs_Widget(d->widget))), 1040 init_I2(right_Rect(bounds_Widget(constAs_Widget(d->widget))),
1030 visPos.y + height_Rect(run->visBounds))), 1041 visPos.y + height_Rect(run->visBounds))),
1031 black_ColorId); 1042 tmBannerBackground_ColorId);
1032 const iChar icon = siteIcon_GmDocument(doc); 1043 const iChar icon = siteIcon_GmDocument(doc);
1033 iString bannerText; 1044 iString bannerText;
1034 init_String(&bannerText); 1045 init_String(&bannerText);
1035 format_String(&bannerText, "%lc", (int) icon);
1036 //appendRange_String(&bannerText, run->text);
1037 const iInt2 iconSize = advanceN_Text(banner_FontId, cstr_String(&bannerText), 2);
1038 iInt2 bpos = add_I2(visPos, init_I2(0, lineHeight_Text(banner_FontId) / 2)); 1046 iInt2 bpos = add_I2(visPos, init_I2(0, lineHeight_Text(banner_FontId) / 2));
1039// draw_Text(run->font, bpos, fg, "%s", buf); 1047 if (icon) {
1040// bpos.x += iconSize.x; 1048 format_String(&bannerText, "%lc", (int) icon);
1041 drawRange_Text(run->font, bpos, fg, range_String(&bannerText)); 1049 const iInt2 iconSize = advanceN_Text(banner_FontId, cstr_String(&bannerText), 2);
1042 bpos.x += iconSize.x + 3 * gap_Text; 1050 drawRange_Text(run->font, bpos, tmBannerIcon_ColorId, range_String(&bannerText));
1043 drawRange_Text(run->font, bpos, fg, run->text); 1051 bpos.x += iconSize.x + 3 * gap_Text;
1052 }
1053 drawRange_Text(run->font,
1054 bpos,
1055 tmBannerTitle_ColorId,
1056 isEmpty_String(d->widget->titleUser) ? run->text
1057 : range_String(d->widget->titleUser));
1044 deinit_String(&bannerText); 1058 deinit_String(&bannerText);
1045 } 1059 }
1046 else { 1060 else {
@@ -1053,8 +1067,9 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1053 const int flags = linkFlags_GmDocument(doc, run->linkId); 1067 const int flags = linkFlags_GmDocument(doc, run->linkId);
1054 const iRect linkRect = moved_Rect(run->visBounds, origin); 1068 const iRect linkRect = moved_Rect(run->visBounds, origin);
1055 iMediaRequest *mr = NULL; 1069 iMediaRequest *mr = NULL;
1070 /* Show inline content. */
1056 if (flags & content_GmLinkFlag) { 1071 if (flags & content_GmLinkFlag) {
1057 fg = linkColor_GmDocument(doc, run->linkId); 1072 fg = linkColor_GmDocument(doc, run->linkId, textHover_GmLinkPart);
1058 if (!isEmpty_Rect(run->bounds)) { 1073 if (!isEmpty_Rect(run->bounds)) {
1059 iGmImageInfo info; 1074 iGmImageInfo info;
1060 imageInfo_GmDocument(doc, linkImage_GmDocument(doc, run->linkId), &info); 1075 imageInfo_GmDocument(doc, linkImage_GmDocument(doc, run->linkId), &info);
@@ -1064,7 +1079,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1064 info.mime, info.size.x, info.size.y, info.numBytes / 1.0e6f); 1079 info.mime, info.size.x, info.size.y, info.numBytes / 1.0e6f);
1065 if (findMediaRequest_DocumentWidget_(d->widget, run->linkId)) { 1080 if (findMediaRequest_DocumentWidget_(d->widget, run->linkId)) {
1066 appendFormat_String( 1081 appendFormat_String(
1067 &text, " %s\U0001f7a8", isHover ? white_ColorEscape : ""); 1082 &text, " %s\U0001f7a8", isHover ? escape_Color(tmLinkText_ColorId) : "");
1068 } 1083 }
1069 drawAlign_Text(metaFont, 1084 drawAlign_Text(metaFont,
1070 add_I2(topRight_Rect(run->bounds), origin), 1085 add_I2(topRight_Rect(run->bounds), origin),
@@ -1079,7 +1094,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1079 if (!isFinished_GmRequest(mr->req)) { 1094 if (!isFinished_GmRequest(mr->req)) {
1080 draw_Text(metaFont, 1095 draw_Text(metaFont,
1081 topRight_Rect(linkRect), 1096 topRight_Rect(linkRect),
1082 linkColor_GmDocument(doc, run->linkId), 1097 tmInlineContentMetadata_ColorId,
1083 " \u2014 Fetching\u2026"); 1098 " \u2014 Fetching\u2026");
1084 } 1099 }
1085 } 1100 }
@@ -1090,7 +1105,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1090 iUrl parts; 1105 iUrl parts;
1091 init_Url(&parts, url); 1106 init_Url(&parts, url);
1092 const iString *host = collect_String(newRange_String(parts.host)); 1107 const iString *host = collect_String(newRange_String(parts.host));
1093 fg = linkColor_GmDocument(doc, linkId); 1108 fg = linkColor_GmDocument(doc, linkId, textHover_GmLinkPart);
1094 const iBool showHost = (!isEmpty_String(host) && flags & userFriendly_GmLinkFlag); 1109 const iBool showHost = (!isEmpty_String(host) && flags & userFriendly_GmLinkFlag);
1095 const iBool showImage = (flags & imageFileExtension_GmLinkFlag) != 0; 1110 const iBool showImage = (flags & imageFileExtension_GmLinkFlag) != 0;
1096 const iBool showAudio = (flags & audioFileExtension_GmLinkFlag) != 0; 1111 const iBool showAudio = (flags & audioFileExtension_GmLinkFlag) != 0;
@@ -1099,20 +1114,25 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1099 if (run->flags & endOfLine_GmRunFlag && 1114 if (run->flags & endOfLine_GmRunFlag &&
1100 (flags & (imageFileExtension_GmLinkFlag | audioFileExtension_GmLinkFlag) || 1115 (flags & (imageFileExtension_GmLinkFlag | audioFileExtension_GmLinkFlag) ||
1101 showHost)) { 1116 showHost)) {
1102 format_String(&str, " \u2014%s%s%s\r%c%s", 1117 format_String(
1103 showHost ? " " : "", 1118 &str,
1104 showHost ? cstr_String(host) : "", 1119 " \u2014%s%s%s\r%c%s",
1105 showHost && (showImage || showAudio) ? " \u2014" : "", 1120 showHost ? " " : "",
1106 showImage || showAudio ? '0' + fg : ('0' + fg - 1), 1121 showHost ? cstr_String(host) : "",
1107 showImage ? " View Image \U0001f5bc" 1122 showHost && (showImage || showAudio) ? " \u2014" : "",
1108 : showAudio ? " Play Audio \U0001f3b5" : ""); 1123 showImage || showAudio
1124 ? '0' + fg
1125 : ('0' + linkColor_GmDocument(doc, run->linkId, domain_GmLinkPart)),
1126 showImage ? " View Image \U0001f5bc"
1127 : showAudio ? " Play Audio \U0001f3b5" : "");
1109 } 1128 }
1110 if (run->flags & endOfLine_GmRunFlag && flags & visited_GmLinkFlag) { 1129 if (run->flags & endOfLine_GmRunFlag && flags & visited_GmLinkFlag) {
1111 iDate date; 1130 iDate date;
1112 init_Date(&date, linkTime_GmDocument(doc, run->linkId)); 1131 init_Date(&date, linkTime_GmDocument(doc, run->linkId));
1113 appendFormat_String(&str, 1132 appendFormat_String(&str,
1114 " \u2014 %s%s", 1133 " \u2014 %s%s",
1115 escape_Color(fg), 1134 escape_Color(linkColor_GmDocument(doc, run->linkId,
1135 visited_GmLinkPart)),
1116 cstr_String(collect_String(format_Date(&date, "%b %d")))); 1136 cstr_String(collect_String(format_Date(&date, "%b %d"))));
1117 } 1137 }
1118 if (!isEmpty_String(&str)) { 1138 if (!isEmpty_String(&str)) {
@@ -1128,7 +1148,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1128 } 1148 }
1129 drawAlign_Text(metaFont, 1149 drawAlign_Text(metaFont,
1130 init_I2(tx, top_Rect(linkRect)), 1150 init_I2(tx, top_Rect(linkRect)),
1131 fg - 1, 1151 linkColor_GmDocument(doc, run->linkId, domain_GmLinkPart),
1132 left_Alignment, 1152 left_Alignment,
1133 "%s", 1153 "%s",
1134 msg); 1154 msg);
@@ -1152,7 +1172,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
1152 .bounds = documentBounds_DocumentWidget_(d) 1172 .bounds = documentBounds_DocumentWidget_(d)
1153 }; 1173 };
1154 init_Paint(&ctx.paint); 1174 init_Paint(&ctx.paint);
1155 fillRect_Paint(&ctx.paint, bounds, black_ColorId); 1175 fillRect_Paint(&ctx.paint, bounds, tmBackground_ColorId);
1156 setClip_Paint(&ctx.paint, bounds); 1176 setClip_Paint(&ctx.paint, bounds);
1157 render_GmDocument(d->doc, visibleRange_DocumentWidget_(d), drawRun_DrawContext_, &ctx); 1177 render_GmDocument(d->doc, visibleRange_DocumentWidget_(d), drawRun_DrawContext_, &ctx);
1158 clearClip_Paint(&ctx.paint); 1178 clearClip_Paint(&ctx.paint);