AnalogTerm2: Monochrome mode now simulates color intensity with luma.
authorMatthew Mondor <mmondor@pulsar-zone.net>
Fri, 28 Apr 2023 23:15:28 +0000 (23:15 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Fri, 28 Apr 2023 23:15:28 +0000 (23:15 +0000)
mmsoftware/analogterm2/TODO.txt
mmsoftware/analogterm2/src/draw.c
mmsoftware/analogterm2/src/state.c

index 052add1..d4923ae 100644 (file)
   jumps.  Was restored in a different way, may need improvement.  It could
   still be improved to more accurately detect when extra scrolling would
   occur.  Long jump may also be considered.
+  The text video memory could theoretically be larger by one line, with line 0
+  usually invisible except partly during smooth scrolling and goto adapted.
 - Check termios(4) IMAXBEL and queue size, also reported by stty(1).
   This may allow to tweak interactive performance when a lot of application
   output happens.
index 0b5361d..5bbe191 100644 (file)
@@ -81,16 +81,20 @@ static double       color_mult[COLOR_MAX][MULT_MAX] = {
        { 1.0, 1.0, 1.0 }       /* User custom */
 };
 
+static double  color_lum[COLOR_MAX];
+
 
 static void            draw_cleanup(void);
 static void            alarm_sighandler(int);
 static inline uint32_t rgb32(uint8_t, uint8_t, uint8_t);
 static inline uint32_t icolor(double);
 static inline uint32_t acolor(double);
+static double          luminance_rgb(double, double, double);
 static void            draw_lines(state_t *, screen_t *, int, int);
 
 
 static int             color = DEFAULT_COLOR;
+static double          lum;
 static int             intensity = INTENSITY_MIN;
 static bool            gun_on = false;
 static state_t         *state = NULL;
@@ -113,12 +117,19 @@ draw_init(state_t *st, screen_t *sc)
 {
        struct sigaction act;
        struct itimerval itv;
+       int i;
+
+       /* Fill color luminance table for monochrome mode */
+       for (i = 0; i < COLOR_MAX; i++)
+               color_lum[i] = luminance_rgb(color_mult[i][MULT_RED],
+                   color_mult[i][MULT_GREEN], color_mult[i][MULT_BLUE]);
 
        (void)memset(empty, 0, FONT_WIDTH);
 
        state = st;
        screen = sc;
        color = cfg_color;
+       lum = color_lum[color];
        intensity = cfg_intmin;
        blink_ticks = 0;
        refresh_expired = false;
@@ -252,6 +263,11 @@ draw_custom_rgb(int r, int g, int b)
        color_mult[COLOR_CUSTOM][MULT_RED] = r / 255.0;
        color_mult[COLOR_CUSTOM][MULT_GREEN] = g / 255.0;
        color_mult[COLOR_CUSTOM][MULT_BLUE] = b / 255.0;
+       /* Also update luminance for monochrome mode */
+       color_lum[COLOR_CUSTOM] =
+           luminance_rgb(color_mult[COLOR_CUSTOM][MULT_RED],
+           color_mult[COLOR_CUSTOM][MULT_GREEN],
+           color_mult[COLOR_CUSTOM][MULT_BLUE]);
 }
 
 static inline uint32_t
@@ -267,11 +283,12 @@ static inline uint32_t
 icolor(double mult)
 {
        const double *col = color_mult[color];
+       double intens = (cfg_mono ? intensity * lum : intensity);
 
        return rgb32(
-           (uint8_t)((intensity * mult) * col[MULT_RED]),
-           (uint8_t)((intensity * mult) * col[MULT_GREEN]),
-           (uint8_t)((intensity * mult) * col[MULT_BLUE]));
+           (uint8_t)((intens * mult) * col[MULT_RED]),
+           (uint8_t)((intens * mult) * col[MULT_GREEN]),
+           (uint8_t)((intens * mult) * col[MULT_BLUE]));
 }
 
 /* Absolute intensity */
@@ -280,10 +297,25 @@ acolor(double mult)
 {
        const double *col = color_mult[color];
 
+       if (cfg_mono)
+               mult *= lum;
+
        return rgb32(
-           (uint8_t)((INTENSITY_MAX * mult) * col[MULT_RED]),
-           (uint8_t)((INTENSITY_MAX * mult) * col[MULT_GREEN]),
-           (uint8_t)((INTENSITY_MAX * mult) * col[MULT_BLUE]));
+           (uint8_t)((((double)INTENSITY_MAX) * mult) * col[MULT_RED]),
+           (uint8_t)((((double)INTENSITY_MAX) * mult) * col[MULT_GREEN]),
+           (uint8_t)((((double)INTENSITY_MAX) * mult) * col[MULT_BLUE]));
+}
+
+/* Convert an RGB color to a luminance intensity for monochrome mode */
+static double
+luminance_rgb(double r, double g, double b)
+{
+       double l = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
+
+       /* To avoid excessively dark rendering, rescale up */
+       l = 0.3 + (l * 0.7);
+
+       return l;
 }
 
 /*
@@ -298,6 +330,7 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
        int row, srow, urow, crow;
 
        color = st->monocolor;
+       lum = color_lum[color];
 
        /* Row to underline or strike if the attribute is enabled */
        srow = (int)ceil(((double)FONT_HEIGHT) / 2.0);
@@ -427,14 +460,15 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                                uint32_t m = row_modes[col];
                                int bit, level, olevel, iblink, fgcolor,
                                    bgcolor;
+                               double fglum = 1.0, bglum = 1.0;
                                bool selected_char = row_selected[col], bg;
 
        /* Process mode phase 1, precalculations for bit-level later */
-       rev = ((m & (TMODE_INVERSE | (cfg_mono ? TMODE_BGCOLOR : 0))) != 0);
+       rev = ((m & TMODE_INVERSE) != 0);
        level = INTENSITY_NORMAL;
        if ((m & (TMODE_BOLD)) != 0)
-               level = ((m & (TMODE_INVERSE | (cfg_mono ? TMODE_BGCOLOR :
-                   0))) == 0 ?  INTENSITY_BRIGHT : INTENSITY_DIM);
+               level = ((m & TMODE_INVERSE) != 0 ?
+                   INTENSITY_DIM : INTENSITY_BRIGHT);
        else if ((m & TMODE_DIM) != 0)
                level = INTENSITY_DIM;
        olevel = level;
@@ -446,7 +480,7 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
        else
                iblink = 0;
 
-                               if (!cfg_mono && (m & TMODE_FGCOLOR) != 0) {
+                               if ((m & TMODE_FGCOLOR) != 0) {
                                        fgcolor = (m & TMODE_FGCOLORMASK) >>
                                            TMODE_FGCOLORSHIFT;
                                        /* If black and bold, produce gray */
@@ -454,7 +488,7 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                                                fgcolor = COLOR_GRAY2;
                                } else
                                        fgcolor = st->monocolor;
-                               if (!cfg_mono && (m & TMODE_BGCOLOR) != 0) {
+                               if ((m & TMODE_BGCOLOR) != 0) {
                                        bgcolor = (m & TMODE_BGCOLORMASK) >>
                                            TMODE_BGCOLORSHIFT;
                                        bg = true;
@@ -462,6 +496,14 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                                        bgcolor = st->monocolor; /* XXX */
                                        bg = false;
                                }
+                               if (cfg_mono) {
+                                       /* Remember luminance but restore */
+                                       fglum = (fgcolor == st->monocolor ?
+                                           1.0 : color_lum[fgcolor]);
+                                       fgcolor = st->monocolor;
+                                       bglum = color_lum[bgcolor];
+                                       bgcolor = st->monocolor;
+                               }
                                for (bit = 0; bit < FONT_WIDTH; bit++) {
                                        bool extra = (cfg_condensed ?
                                            (colpix % 3) == 0 : false);
@@ -486,8 +528,7 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                p = ((p ^ rev) ? level : 0);
 
        /* Thicker bold characters */
-       if ((m & (TMODE_BOLD | TMODE_INVERSE | (cfg_mono ? TMODE_BGCOLOR : 0)))
-           == TMODE_BOLD) {
+       if ((m & (TMODE_BOLD | TMODE_INVERSE)) == TMODE_BOLD) {
                uint8_t old = p;
 
                if (!p && last > 0)
@@ -507,10 +548,11 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                                    (cfg_mono ? st->monocolor : COLOR_WHITE);
                        } else
                                color = st->monocolor;
-                       if ((m & (TMODE_INVERSE | TMODE_BGCOLOR)) != 0)
-                               p = (p == 0 ? INTENSITY_DIM :
-                                   INTENSITY_DIM / 2);
-                       else
+                       fglum = bglum = 1.0;
+                       if ((m & (TMODE_INVERSE | TMODE_BGCOLOR)) != 0) {
+                               fgcolor = bgcolor;
+                               p = (p == 0 ? INTENSITY_MIN : INTENSITY_MAX);
+                       } else
                                p = (p == 0 ? (sc->focus ? INTENSITY_MAX :
                                    INTENSITY_MIN) : 0);
                }
@@ -545,6 +587,7 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                 */
                if (p) {
                        color = fgcolor;
+                       lum = fglum;
                        if (gun_on) {
                                if ((intensity += cfg_intstep) > p)
                                        intensity = p;
@@ -578,6 +621,7 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                                oldintensity = intensity;
                                intensity = INTENSITY_DIM;
                                color = bgcolor;
+                               lum = bglum;
                                /* Background and scanline */
                                if (bg) {
                                        if ((bgintensity += cfg_intstep) >
@@ -592,6 +636,7 @@ draw_lines(state_t *st, screen_t *sc, int low, int high)
                                        bgintensity = cfg_intmin;
                                        if (lastbg) {
                                                color = bgcolor;
+                                               lum = bglum;
                                                scanptr1[0] = icolor(0.6);
                                                scanptr1[1] = icolor(0.3);
                                                scanptr2[0] = icolor(0.3);
index e04c61e..f64be5c 100644 (file)
@@ -1424,13 +1424,6 @@ endh:
                                case 95: /* FALLTHROUGH */
                                case 96: /* FALLTHROUGH */
                                case 97: /* FALLTHROUGH */
-                                       if (cfg_mono &&
-                                           (state->csiparam[i] == 30 ||
-                                           state->csiparam[i] == 90)) {
-                                               state->mode &= ~(TMODE_FGCOLOR
-                                                   | TMODE_FGCOLORMASK);
-                                               break;
-                                       }
                                        col = state->csiparam[i];
                                        if (col > 90)
                                                col -= 60;