diff options
-rw-r--r-- | src/gmdocument.c | 184 | ||||
-rw-r--r-- | src/gmdocument.h | 10 | ||||
-rw-r--r-- | src/ui/color.c | 23 | ||||
-rw-r--r-- | src/ui/color.h | 22 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 74 |
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 | ||
549 | static 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 | |||
552 | void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | 557 | void 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 | ||
790 | enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId) { | 887 | enum 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 | ||
803 | iBool isMediaLink_GmDocument(const iGmDocument *d, iGmLinkId linkId) { | 937 | iBool 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 *); | |||
80 | iRangecc findText_GmDocument (const iGmDocument *, const iString *text, const char *start); | 80 | iRangecc findText_GmDocument (const iGmDocument *, const iString *text, const char *start); |
81 | iRangecc findTextBefore_GmDocument (const iGmDocument *, const iString *text, const char *before); | 81 | iRangecc findTextBefore_GmDocument (const iGmDocument *, const iString *text, const char *before); |
82 | 82 | ||
83 | enum iGmLinkPart { | ||
84 | icon_GmLinkPart, | ||
85 | text_GmLinkPart, | ||
86 | textHover_GmLinkPart, | ||
87 | domain_GmLinkPart, | ||
88 | visited_GmLinkPart, | ||
89 | }; | ||
90 | |||
83 | const iGmRun * findRun_GmDocument (const iGmDocument *, iInt2 pos); | 91 | const iGmRun * findRun_GmDocument (const iGmDocument *, iInt2 pos); |
84 | const char * findLoc_GmDocument (const iGmDocument *, iInt2 pos); | 92 | const char * findLoc_GmDocument (const iGmDocument *, iInt2 pos); |
85 | const iGmRun * findRunAtLoc_GmDocument (const iGmDocument *, const char *loc); | 93 | const iGmRun * findRunAtLoc_GmDocument (const iGmDocument *, const char *loc); |
86 | const iString * linkUrl_GmDocument (const iGmDocument *, iGmLinkId linkId); | 94 | const iString * linkUrl_GmDocument (const iGmDocument *, iGmLinkId linkId); |
87 | uint16_t linkImage_GmDocument (const iGmDocument *, iGmLinkId linkId); | 95 | uint16_t linkImage_GmDocument (const iGmDocument *, iGmLinkId linkId); |
88 | int linkFlags_GmDocument (const iGmDocument *, iGmLinkId linkId); | 96 | int linkFlags_GmDocument (const iGmDocument *, iGmLinkId linkId); |
89 | enum iColorId linkColor_GmDocument (const iGmDocument *, iGmLinkId linkId); | 97 | enum iColorId linkColor_GmDocument (const iGmDocument *, iGmLinkId linkId, enum iGmLinkPart part); |
90 | const iTime * linkTime_GmDocument (const iGmDocument *, iGmLinkId linkId); | 98 | const iTime * linkTime_GmDocument (const iGmDocument *, iGmLinkId linkId); |
91 | iBool isMediaLink_GmDocument (const iGmDocument *, iGmLinkId linkId); | 99 | iBool isMediaLink_GmDocument (const iGmDocument *, iGmLinkId linkId); |
92 | const iString * title_GmDocument (const iGmDocument *); | 100 | const 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 | ||
103 | iColor fromHsl_Color(iHSLColor hsl) { | 103 | iColor 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 | |||
146 | iHSLColor setSat_HSLColor(iHSLColor d, float sat) { | ||
147 | d.sat = iClamp(sat, 0, 1); | ||
148 | return d; | ||
149 | } | ||
150 | |||
151 | iHSLColor setLum_HSLColor(iHSLColor d, float lum) { | ||
152 | d.lum = iClamp(lum, 0, 1); | ||
153 | return d; | ||
154 | } | ||
155 | |||
156 | iHSLColor 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 | ||
143 | iColor ansi_Color(iRangecc escapeSequence, int fallback) { | 162 | iColor 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 | ||
92 | iHSLColor hsl_Color (iColor); | ||
93 | iColor rgb_HSLColor (iHSLColor); | ||
94 | |||
95 | iHSLColor setSat_HSLColor (iHSLColor, float sat); | ||
96 | iHSLColor setLum_HSLColor (iHSLColor, float lum); | ||
97 | iHSLColor addSatLum_HSLColor (iHSLColor, float sat, float lum); | ||
98 | |||
90 | iColor get_Color (int color); | 99 | iColor get_Color (int color); |
91 | void set_Color (int color, iColor rgba); | 100 | void set_Color (int color, iColor rgba); |
92 | 101 | ||
93 | iHSLColor hsl_Color (iColor rgba); | 102 | iLocalDef void setHsl_Color(int color, iHSLColor hsl) { |
94 | iColor fromHsl_Color (iHSLColor hsl); | 103 | set_Color(color, rgb_HSLColor(hsl)); |
104 | } | ||
95 | 105 | ||
96 | iColor ansi_Color (iRangecc escapeSequence, int fallback); | 106 | iColor ansi_Color (iRangecc escapeSequence, int fallback); |
97 | const char * escape_Color (int color); | 107 | const 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); |