summaryrefslogtreecommitdiff
path: root/src/gmdocument.c
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/gmdocument.c
parent2b1de0641335ab1a88aeafcc8911056f155e94c9 (diff)
Color palette theming
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r--src/gmdocument.c184
1 files changed, 159 insertions, 25 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) {