diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-06 09:57:42 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-06 09:57:42 +0300 |
commit | 54950e9ccc384a8000f6d39a74dc3dc615f38fbb (patch) | |
tree | 24f708c9a2d4db2859425e67885bd1a8309f8611 /src | |
parent | cde2c55d15eb912735dac1ea0c2743959cc85be9 (diff) |
GmDocument: Improvements to color themes
Better light mode, and in dark mode either saturate the background or the foreground, but not both.
Diffstat (limited to 'src')
-rw-r--r-- | src/gmdocument.c | 93 | ||||
-rw-r--r-- | src/ui/color.h | 17 |
2 files changed, 88 insertions, 22 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c index a631739f..53538c3d 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -576,15 +576,16 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
576 | static const float hues[] = { | 576 | static const float hues[] = { |
577 | 0, 60, 90, 100, 180, 210, 230, 260, 330 | 577 | 0, 60, 90, 100, 180, 210, 230, 260, 330 |
578 | }; | 578 | }; |
579 | const iBool isDesaturated = iFalse; | 579 | const float saturationLevel = 1.0f; /* TODO: user setting */ |
580 | const iBool isLowSaturated = iFalse; | 580 | const iBool isLightMode = !iFalse; /* TODO: user setting */ |
581 | const iBool isLightMode = iFalse; | ||
582 | const iBool isBannerLighter = (d->themeSeed & 0x4000) != 0; | 581 | const iBool isBannerLighter = (d->themeSeed & 0x4000) != 0; |
582 | const iBool isDarkBgSat = (d->themeSeed & 0x200000) != 0; | ||
583 | iHSLColor base = { hues[(d->themeSeed & 0xff) % iElemCount(hues)], | 583 | iHSLColor base = { hues[(d->themeSeed & 0xff) % iElemCount(hues)], |
584 | 0.8f * (d->themeSeed >> 24) / 255.0f, | 584 | 0.8f * (d->themeSeed >> 24) / 255.0f, |
585 | 0.06f + 0.09f * ((d->themeSeed >> 5) & 0x7) / 7.0f, | 585 | 0.06f + 0.09f * ((d->themeSeed >> 5) & 0x7) / 7.0f, |
586 | 1.0f }; | 586 | 1.0f }; |
587 | printf("background: %d %f %f\n", (int) base.hue, base.sat, base.lum); | 587 | printf("background: %d %f %f\n", (int) base.hue, base.sat, base.lum); |
588 | printf("isDarkBgSat: %d\n", isDarkBgSat); | ||
588 | setHsl_Color(tmBackground_ColorId, base); | 589 | setHsl_Color(tmBackground_ColorId, base); |
589 | 590 | ||
590 | setHsl_Color(tmBannerBackground_ColorId, addSatLum_HSLColor(base, 0.1f, 0.04f * (isBannerLighter ? 1 : -1))); | 591 | setHsl_Color(tmBannerBackground_ColorId, addSatLum_HSLColor(base, 0.1f, 0.04f * (isBannerLighter ? 1 : -1))); |
@@ -593,7 +594,8 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
593 | 594 | ||
594 | const iBool altDir = (d->themeSeed & 0x4) != 0; | 595 | const iBool altDir = (d->themeSeed & 0x4) != 0; |
595 | const float altHue = fixHue_(iWrapf(base.hue + (altDir ? 90 : -90), 0, 360)); | 596 | 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 | float altHue2 = fixHue_(iWrapf(base.hue + (altDir ? -30 : 30), 0, 360)); |
598 | if (altHue2 > 230) altHue2 = fixHue_(iWrapf(base.hue + (altDir ? 45 : -45), 0, 360)); | ||
597 | iHSLColor altBase = base; | 599 | iHSLColor altBase = base; |
598 | altBase.hue = altHue; | 600 | altBase.hue = altHue; |
599 | const float titleLum = 0.2f * ((d->themeSeed >> 17) & 0x7) / 7.0f; | 601 | const float titleLum = 0.2f * ((d->themeSeed >> 17) & 0x7) / 7.0f; |
@@ -629,34 +631,80 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
629 | set_Color(tmGopherLinkDomain_ColorId, get_Color(magenta_ColorId)); | 631 | set_Color(tmGopherLinkDomain_ColorId, get_Color(magenta_ColorId)); |
630 | set_Color(tmGopherLinkLastVisitDate_ColorId, get_Color(blue_ColorId)); | 632 | set_Color(tmGopherLinkLastVisitDate_ColorId, get_Color(blue_ColorId)); |
631 | 633 | ||
634 | /* Adjust colors based on light/dark mode. */ | ||
632 | for (int i = tmFirst_ColorId; i < max_ColorId; i++) { | 635 | for (int i = tmFirst_ColorId; i < max_ColorId; i++) { |
633 | iHSLColor color = hsl_Color(get_Color(i)); | 636 | iHSLColor color = hsl_Color(get_Color(i)); |
634 | if (isLightMode) { | 637 | if (isLightMode) { |
635 | color.lum = 1.0f - color.lum; | 638 | color.lum = 1.0f - color.lum; /* All colors invert lightness. */ |
636 | } | 639 | if (isRegularText_ColorId(i)) { |
637 | if (i < tmBadLink_ColorId) { /* Not a link? */ | 640 | /* Darken paragraphs and default state link text. */ |
638 | if (isLowSaturated) { | 641 | color.lum *= 0.5f; |
639 | color.sat *= 0.3f; | ||
640 | } | 642 | } |
641 | if (isDesaturated) { | 643 | else if (i == tmBackground_ColorId) { |
642 | color.sat = 0; | 644 | color.sat = (color.sat + 1) / 2; |
643 | } | 645 | } |
644 | if (isLightMode) { | 646 | else if (i == tmHeader3_ColorId) { |
645 | /* Darken text. */ | 647 | color.lum *= 0.75f; |
646 | if (i == tmParagraph_ColorId || i == tmLinkText_ColorId || | 648 | } |
647 | i == tmHypertextLinkText_ColorId || i == tmGopherLinkText_ColorId) { | 649 | else if (isLink_ColorId(i)) { |
648 | color.lum *= 0.5f; | 650 | /* Darken links generally to improve visibility against a |
649 | } | 651 | light background. */ |
650 | else if (i == tmBannerIcon_ColorId) { | 652 | color.lum *= 0.5f; |
653 | color.sat = 1.0f; | ||
654 | } | ||
655 | else if (i == tmBannerIcon_ColorId || i == tmBannerTitle_ColorId) { | ||
656 | if (isBannerLighter) { | ||
651 | color.lum *= 0.75f; | 657 | color.lum *= 0.75f; |
652 | } | 658 | } |
659 | else { | ||
660 | color.lum = 0.98f; | ||
661 | } | ||
662 | } | ||
663 | else if (i == tmBannerBackground_ColorId) { | ||
664 | if (isBannerLighter) { | ||
665 | color.sat = (color.sat + 1) / 2; | ||
666 | color.lum = (color.lum + 2) / 3; | ||
667 | } | ||
668 | else { | ||
669 | color.sat = 0.8f; | ||
670 | color.lum = 0.4f; | ||
671 | } | ||
672 | } | ||
673 | else if (isText_ColorId(i)) { | ||
674 | color.sat = 0.9f; | ||
675 | color.lum = (9 * color.lum + 0.5f) / 10; | ||
653 | } | 676 | } |
654 | } | 677 | } |
655 | else if (isLightMode) { | 678 | else { /* dark mode */ |
656 | /* Darken links. */ | 679 | if (!isLink_ColorId(i)) { |
657 | color.lum *= 0.75f; | 680 | if (isDarkBgSat) { |
658 | color.sat = 1.0f; | 681 | /* Saturate background, desaturate text. */ |
682 | if (isBackground_ColorId(i)) { | ||
683 | color.sat = (color.sat + 1) / 2; | ||
684 | // color.lum = (color.lum + 2 * 0.5f) / 3; | ||
685 | color.lum *= 0.75f; | ||
686 | } | ||
687 | else if (isText_ColorId(i)) { | ||
688 | // color.sat *= 0.85f; | ||
689 | color.lum = (color.lum + 1) / 2; | ||
690 | } | ||
691 | } | ||
692 | else { | ||
693 | /* Desaturate background, saturate text. */ | ||
694 | if (isBackground_ColorId(i)) { | ||
695 | color.sat *= 0.333f; | ||
696 | // color.lum *= 0.5f; | ||
697 | } | ||
698 | else if (isText_ColorId(i)) { | ||
699 | color.sat = (color.sat + 2) / 3; | ||
700 | color.lum = (2 * color.lum + 1) / 3; | ||
701 | // color.lum = (color.lum + 0.5f) / 2; | ||
702 | } | ||
703 | } | ||
704 | } | ||
659 | } | 705 | } |
706 | /* Modify overall saturation. */ | ||
707 | color.sat *= saturationLevel; | ||
660 | setHsl_Color(i, color); | 708 | setHsl_Color(i, color); |
661 | } | 709 | } |
662 | } | 710 | } |
@@ -667,6 +715,7 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
667 | d->siteIcon = 0x264a; /* gemini symbol */ | 715 | d->siteIcon = 0x264a; /* gemini symbol */ |
668 | } | 716 | } |
669 | } | 717 | } |
718 | fflush(stdout); | ||
670 | } | 719 | } |
671 | 720 | ||
672 | void setFormat_GmDocument(iGmDocument *d, enum iGmDocumentFormat format) { | 721 | void setFormat_GmDocument(iGmDocument *d, enum iGmDocumentFormat format) { |
diff --git a/src/ui/color.h b/src/ui/color.h index c3cacf77..4f179534 100644 --- a/src/ui/color.h +++ b/src/ui/color.h | |||
@@ -60,6 +60,23 @@ enum iColorId { | |||
60 | max_ColorId | 60 | max_ColorId |
61 | }; | 61 | }; |
62 | 62 | ||
63 | iLocalDef isLink_ColorId(enum iColorId d) { | ||
64 | return d >= tmBadLink_ColorId; | ||
65 | } | ||
66 | iLocalDef isBackground_ColorId(enum iColorId d) { | ||
67 | return d == tmBackground_ColorId || d == tmBannerBackground_ColorId; | ||
68 | } | ||
69 | iLocalDef isText_ColorId(enum iColorId d) { | ||
70 | return d >= tmFirst_ColorId && !isBackground_ColorId(d); | ||
71 | } | ||
72 | iLocalDef isLinkText_ColorId(enum iColorId d) { | ||
73 | return d == tmLinkText_ColorId || d == tmHypertextLinkText_ColorId || | ||
74 | d == tmGopherLinkText_ColorId; | ||
75 | } | ||
76 | iLocalDef isRegularText_ColorId(enum iColorId d) { | ||
77 | return isLinkText_ColorId(d) || d == tmParagraph_ColorId || d == tmFirstParagraph_ColorId; | ||
78 | } | ||
79 | |||
63 | #define mask_ColorId 0x3f | 80 | #define mask_ColorId 0x3f |
64 | #define permanent_ColorId 0x80 /* cannot be changed via escapes */ | 81 | #define permanent_ColorId 0x80 /* cannot be changed via escapes */ |
65 | 82 | ||