{ 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;
{
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;
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
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 */
{
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;
}
/*
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);
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;
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 */
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;
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);
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)
(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);
}
*/
if (p) {
color = fgcolor;
+ lum = fglum;
if (gun_on) {
if ((intensity += cfg_intstep) > p)
intensity = p;
oldintensity = intensity;
intensity = INTENSITY_DIM;
color = bgcolor;
+ lum = bglum;
/* Background and scanline */
if (bg) {
if ((bgintensity += cfg_intstep) >
bgintensity = cfg_intmin;
if (lastbg) {
color = bgcolor;
+ lum = bglum;
scanptr1[0] = icolor(0.6);
scanptr1[1] = icolor(0.3);
scanptr2[0] = icolor(0.3);