From 7fa15d2658f2acf3d111cbaddb4226ad6e09f78d Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Thu, 25 Dec 2003 21:28:55 +0000 Subject: [PATCH] * NOTES BUGS: + Updated information about the S-Lang colour pair shortage bug. * src/graphics.c: + Implemented the solution explained in NOTES. --- BUGS | 3 +- NOTES | 44 ++++---- configure.ac | 1 + src/graphics.c | 298 +++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 287 insertions(+), 59 deletions(-) diff --git a/BUGS b/BUGS index e0f0a35..8b502eb 100644 --- a/BUGS +++ b/BUGS @@ -6,7 +6,8 @@ Video rendering occasionally flicker because it tries to optimize the vertical scrolling. - o Slang cannot display 256 colour pairs under Unix. + o Slang cannot display 256 colour pairs under Unix. This is partially + solved by the OPTIMISE_SLANG_PALETTE code. o the X11 driver is very slow. diff --git a/NOTES b/NOTES index 50d507e..0257c2c 100644 --- a/NOTES +++ b/NOTES @@ -128,22 +128,22 @@ $Id$ fg 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 0 (black) C C C C C C F B c c c c c c F - 1 (blue) A h D h D * f C C h E h E F g - 2 (green) A h D h * D f C h C E h * E g - 3 (cyan) A D D * h h f C E E C * h h g - 4 (red) A h h * D D f C h h * C E E g - 5 (magenta) A D * h D h f C E * h E C h g - 6 (brown) A * D h D h f C * E h E h C g - 7 (light gray) A a a a a a a B C C C C C C B - - 8 (dark gray) A C C C C C C B d d d d d d C - 9 (light blue) A C h E h E * C e h D h D * C - 10 (light green) A h C E h * E C e h D h * D C - 11 (light cyan) A E E C * h h C e D D * h h C - 12 (light red) A h h * C E E C e h h * D D C - 13 (light magenta) A E * h E C h C e D * h D h C - 14 (yellow) A F E h E h C C e * D h D h C - 15 (white) A b b b b b b B C C C C C C C + 1 (blue) A h D h D i f C C h E h E k g + 2 (green) A h D h i D f C h C E h k E g + 3 (cyan) A D D i h h f C E E C k h h g + 4 (red) A h h i D D f C h h k C E E g + 5 (magenta) A D i h D h f C E k h E C h g + 6 (brown) A i D h D h f C k E h E h C g + 7 (light gray) A F a a a a a B C C C C C C B + + 8 (dark gray) A C C C C C C B d d d d d d F + 9 (light blue) A C h E h E j C e h D h D l C + 10 (light green) A h C E h j E C e h D h l D C + 11 (light cyan) A E E C j h h C e D D l h h C + 12 (light red) A h h j C E E C e h h l D D C + 13 (light magenta) A E j h E C h C e D l h D h C + 14 (yellow) A j E h E h C C e l D h D h C + 15 (white) A F b b b b b B F C C C C C C ' ': useless colour pairs that can be emulated by printing a space in any other colour pair that has the same background @@ -157,14 +157,14 @@ $Id$ and so on) 'E': next colour combinations for hue/value dithering (blue/lightgreen, green/lightblue and so on) - 'F': black on light gray, black on white, and yellow/blue (chosen - arbitrarily) + 'F': black on light gray, black on white, white on dark gray, dark gray + on white, white on blue, light gray on blue (chosen arbitrarily) 'A': 15 colour pairs 'A'+'B': 20 colour pairs - 'A'+'B'+'C': 76 colour pairs - 'A'+'B'+'C'+'D': 100 colour pairs - 'A'+'B'+'C'+'D'+'E': 124 colour pairs + 'A'+'B'+'C': 74 colour pairs + 'A'+'B'+'C'+'D': 98 colour pairs + 'A'+'B'+'C'+'D'+'E': 122 colour pairs 'A'+'B'+'C'+'D'+'E'+'F': 128 colour pairs The remaining slightly important colour pairs are: @@ -174,7 +174,7 @@ $Id$ 'c': black on light colour: emulate with dark gray on dark colour 'd': dark gray on light colour: emulate with dark colour on light colour 'e': light colour on dark gray: emulate with dark colour on dark gray - 'f': dark colour on light gray: emulate with light colour on dark gray + 'f': dark colour on light gray: emulate with light colour on light gray 'g': dark colour on white: emulate with light colour on white And now the seldom used pairs: diff --git a/configure.ac b/configure.ac index f232078..5338cf6 100644 --- a/configure.ac +++ b/configure.ac @@ -44,6 +44,7 @@ if test "${enable_slang}" = "yes"; then AC_CHECK_HEADERS(slang.h,:,AC_MSG_ERROR([cannot find slang headers])) AC_CHECK_LIB(slang,SLkp_init,:,AC_MSG_ERROR([cannot find slang library])) AC_DEFINE(USE_SLANG, 1, Define to activate the slang backend driver) + CPPFLAGS="${CPPFLAGS} -DOPTIMISE_SLANG_PALETTE=1" CACA_LIBS="${CACA_LIBS} -lslang" fi diff --git a/src/graphics.c b/src/graphics.c index 4996026..51510ac 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -73,6 +73,10 @@ unsigned int _caca_height = 0; static int ncurses_attr[16*16]; #endif +#if defined(USE_SLANG) +static int slang_assoc[16*16]; +#endif + #if defined(USE_CONIO) static struct text_info conio_ti; static char *conio_screen; @@ -97,9 +101,21 @@ static char *_caca_scratch_line; static unsigned int _caca_delay; static unsigned int _caca_rendertime; +#if defined(OPTIMISE_SLANG_PALETTE) +static int _caca_fgisbg = 0; +#endif static enum caca_color _caca_fgcolor = CACA_COLOR_LIGHTGRAY; static enum caca_color _caca_bgcolor = CACA_COLOR_BLACK; +/* + * Local functions + */ +#if defined(USE_SLANG) +static void slang_init_palette(void); +#endif + +static unsigned int _caca_getticks(void); + /** \brief Set the default colour pair. * * This function sets the default colour pair. String functions such as @@ -116,11 +132,42 @@ void caca_set_color(enum caca_color fgcolor, enum caca_color bgcolor) _caca_fgcolor = fgcolor; _caca_bgcolor = bgcolor; + switch(_caca_driver) { #if defined(USE_SLANG) case CACA_DRIVER_SLANG: - SLsmg_set_color((bgcolor + 16 * fgcolor) /*% 128*/); + +#if defined(OPTIMISE_SLANG_PALETTE) + /* If foreground == background, discard this colour pair. Functions + * such as caca_putchar will print spaces instead of characters */ + if(fgcolor != bgcolor) + _caca_fgisbg = 0; + else + { + _caca_fgisbg = 1; + switch(fgcolor) + { + case CACA_COLOR_BLACK: + fgcolor = CACA_COLOR_WHITE; + break; + case CACA_COLOR_WHITE: + fgcolor = CACA_COLOR_BLACK; + break; + default: + if(fgcolor <= CACA_COLOR_LIGHTGRAY) + fgcolor = CACA_COLOR_BLACK; + else + fgcolor = CACA_COLOR_WHITE; + } + } +#endif + +#if defined(OPTIMISE_SLANG_PALETTE) + SLsmg_set_color(slang_assoc[fgcolor + 16 * bgcolor]); +#else + SLsmg_set_color(fgcolor + 16 * bgcolor); +#endif break; #endif #if defined(USE_NCURSES) @@ -192,7 +239,12 @@ void caca_putchar(int x, int y, char c) #if defined(USE_SLANG) case CACA_DRIVER_SLANG: SLsmg_gotorc(y, x); - SLsmg_write_char(c); +#if defined(OPTIMISE_SLANG_PALETTE) + if(_caca_fgisbg) + SLsmg_write_char(' '); + else +#endif + SLsmg_write_char(c); break; #endif #if defined(USE_NCURSES) @@ -258,8 +310,9 @@ void caca_putstr(int x, int y, const char *s) if(x + len >= _caca_width) { - memcpy(_caca_scratch_line, s, _caca_width - x); - _caca_scratch_line[_caca_width - x] = '\0'; + len = _caca_width - x; + memcpy(_caca_scratch_line, s, len); + _caca_scratch_line[len] = '\0'; s = _caca_scratch_line; } @@ -268,7 +321,12 @@ void caca_putstr(int x, int y, const char *s) #if defined(USE_SLANG) case CACA_DRIVER_SLANG: SLsmg_gotorc(y, x); - SLsmg_write_string((char *)(intptr_t)s); +#if defined(OPTIMISE_SLANG_PALETTE) + if(_caca_fgisbg) + SLsmg_write_string(_caca_empty_line + _caca_width - len); + else +#endif + SLsmg_write_string((char *)(intptr_t)s); break; #endif #if defined(USE_NCURSES) @@ -366,37 +424,7 @@ int _caca_init_graphics(void) #if defined(USE_SLANG) if(_caca_driver == CACA_DRIVER_SLANG) { - /* See SLang ref., 5.4.4. */ - static char *slang_colors[16] = - { - /* Standard colours */ - "black", - "blue", - "green", - "cyan", - "red", - "magenta", - "brown", - "lightgray", - /* Bright colours */ - "gray", - "brightblue", - "brightgreen", - "brightcyan", - "brightred", - "brightmagenta", - "yellow", - "white", - }; - - int fg, bg; - - for(fg = 0; fg < 16; fg++) - for(bg = 0; bg < 16; bg++) - { - int i = bg + 16 * fg; - SLtt_set_color(i, NULL, slang_colors[fg], slang_colors[bg]); - } + slang_init_palette(); /* Disable alt charset support so that we get all 256 colour pairs */ SLtt_Has_Alt_Charset = 0; @@ -801,3 +829,201 @@ void caca_refresh(void) lastticks = 0; } +#if defined(USE_SLANG) + +#if defined(OPTIMISE_SLANG_PALETTE) +#endif + +static void slang_init_palette(void) +{ + /* See SLang ref., 5.4.4. */ + static char *slang_colors[16] = + { + /* Standard colours */ + "black", + "blue", + "green", + "cyan", + "red", + "magenta", + "brown", + "lightgray", + /* Bright colours */ + "gray", + "brightblue", + "brightgreen", + "brightcyan", + "brightred", + "brightmagenta", + "yellow", + "white", + }; + +#if !defined(OPTIMISE_SLANG_PALETTE) + int fg, bg; + + for(bg = 0; bg < 16; bg++) + for(fg = 0; fg < 16; fg++) + { + int i = fg + 16 * bg; + SLtt_set_color(i, NULL, slang_colors[fg], slang_colors[bg]); + } +#else + int i, cur = 0; + + /* 6 colours in hue order */ + static const enum caca_color hue_list[] = + { + CACA_COLOR_RED, + CACA_COLOR_BROWN, + CACA_COLOR_GREEN, + CACA_COLOR_CYAN, + CACA_COLOR_BLUE, + CACA_COLOR_MAGENTA + }; + +#define SETPAIR(_fg, _bg, _n) \ + do \ + { \ + int fg = _fg, bg = _bg, n = _n; \ + SLtt_set_color(n, NULL, slang_colors[fg], slang_colors[bg]); \ + slang_assoc[fg + 16 * bg] = n; \ + } \ + while(0); + + /* + * XXX: See the NOTES file for what follows + */ + + /* black background colour pairs that are needed for the old renderer */ + for(i = 1; i < 16; i++) + SETPAIR(i, CACA_COLOR_BLACK, cur++); + + /* gray combinations used for grayscale dithering */ + SETPAIR(CACA_COLOR_BLACK, CACA_COLOR_DARKGRAY, cur++); + SETPAIR(CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY, cur++); + SETPAIR(CACA_COLOR_LIGHTGRAY, CACA_COLOR_DARKGRAY, cur++); + SETPAIR(CACA_COLOR_WHITE, CACA_COLOR_LIGHTGRAY, cur++); + SETPAIR(CACA_COLOR_LIGHTGRAY, CACA_COLOR_WHITE, cur++); + + /* white/light, light/dark, lightgray/light, darkgray/dark, dark/black + * combinations often used for saturation/value dithering (the two + * other possible combinations, lightgray/dark and darkgray/light, are + * not considered here) */ + for(i = 1; i < 7; i++) + { + SETPAIR(CACA_COLOR_WHITE, i + 8, cur++); + SETPAIR(i + 8, CACA_COLOR_WHITE, cur++); + SETPAIR(i, i + 8, cur++); + SETPAIR(i + 8, i, cur++); + SETPAIR(CACA_COLOR_LIGHTGRAY, i + 8, cur++); + SETPAIR(i + 8, CACA_COLOR_LIGHTGRAY, cur++); + SETPAIR(CACA_COLOR_DARKGRAY, i, cur++); + SETPAIR(i, CACA_COLOR_DARKGRAY, cur++); + SETPAIR(CACA_COLOR_BLACK, i, cur++); + } + + /* next colour combinations for hue dithering (magenta/blue, blue/green + * and so on) */ + for(i = 0; i < 6; i++) + { + SETPAIR(hue_list[i], hue_list[(i + 1) % 6], cur++); + SETPAIR(hue_list[(i + 1) % 6], hue_list[i], cur++); + SETPAIR(hue_list[i] + 8, hue_list[(i + 1) % 6] + 8, cur++); + SETPAIR(hue_list[(i + 1) % 6] + 8, hue_list[i] + 8, cur++); + } + + /* next colour combinations for hue/value dithering (blue/lightgreen, + * green/lightblue and so on) */ + for(i = 0; i < 6; i++) + { + SETPAIR(hue_list[i], hue_list[(i + 1) % 6] + 8, cur++); + SETPAIR(hue_list[(i + 1) % 6], hue_list[i] + 8, cur++); + SETPAIR(hue_list[i] + 8, hue_list[(i + 1) % 6], cur++); + SETPAIR(hue_list[(i + 1) % 6] + 8, hue_list[i], cur++); + } + + /* black on light gray, black on white, white on dark gray, dark gray + * on white, white on blue, light gray on blue (chosen arbitrarily) */ + SETPAIR(CACA_COLOR_BLACK, CACA_COLOR_LIGHTGRAY, cur++); + SETPAIR(CACA_COLOR_BLACK, CACA_COLOR_WHITE, cur++); + SETPAIR(CACA_COLOR_WHITE, CACA_COLOR_DARKGRAY, cur++); + SETPAIR(CACA_COLOR_DARKGRAY, CACA_COLOR_WHITE, cur++); + SETPAIR(CACA_COLOR_WHITE, CACA_COLOR_BLUE, cur++); + SETPAIR(CACA_COLOR_LIGHTGRAY, CACA_COLOR_BLUE, cur++); + + /* + * Now the possibly emulated pairs + */ + + /* light gray on dark colour: emulate with light colour on dark colour + * white on dark colour: emulate with light gray on light colour + * black on light colour: emulate with dark gray on dark colour + * dark gray on light colour: emulate with dark colour on light colour + * light colour on dark gray: emulate with dark colour on dark gray + * dark colour on light gray: emulate with light colour on light gray + * dark colour on white: emulate with light colour on white */ + for(i = 1; i < 7; i++) + { + if(i != CACA_COLOR_BLUE) + { + SETPAIR(CACA_COLOR_LIGHTGRAY, i, 128 + + slang_assoc[i + 8 + 16 * i]); + SETPAIR(CACA_COLOR_WHITE, i, 128 + + slang_assoc[CACA_COLOR_LIGHTGRAY + 16 * (i + 8)]); + } + SETPAIR(CACA_COLOR_BLACK, i + 8, + 128 + slang_assoc[CACA_COLOR_DARKGRAY + 16 * i]); + SETPAIR(CACA_COLOR_DARKGRAY, i + 8, + 128 + slang_assoc[i + 16 * (i + 8)]); + SETPAIR(i + 8, CACA_COLOR_DARKGRAY, + 128 + slang_assoc[i + 16 * CACA_COLOR_DARKGRAY]); + SETPAIR(i, CACA_COLOR_LIGHTGRAY, + 128 + slang_assoc[i + 8 + 16 * CACA_COLOR_LIGHTGRAY]); + SETPAIR(i, CACA_COLOR_WHITE, + 128 + slang_assoc[i + 8 + 16 * CACA_COLOR_WHITE]); + } + + /* 120 degree hue pairs can be emulated as well; for instance blue on + * red can be emulated using magenta on red, and blue on green using + * cyan on green */ + for(i = 0; i < 6; i++) + { + SETPAIR(hue_list[(i + 2) % 6], hue_list[i], + 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i]]); + SETPAIR(hue_list[(i + 2) % 6] + 8, hue_list[i] + 8, + 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 136]); + SETPAIR(hue_list[(i + 2) % 6] + 8, hue_list[i], + 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 8]); + SETPAIR(hue_list[(i + 2) % 6], hue_list[i] + 8, + 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 128]); + + SETPAIR(hue_list[(i + 4) % 6], hue_list[i], + 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i]]); + SETPAIR(hue_list[(i + 4) % 6] + 8, hue_list[i] + 8, + 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 136]); + SETPAIR(hue_list[(i + 4) % 6] + 8, hue_list[i], + 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 8]); + SETPAIR(hue_list[(i + 4) % 6], hue_list[i] + 8, + 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 128]); + } + + /* dark opposite on dark: emulate with dark opposite on black + * light opposite on dark: emulate with light opposite on black + * dark opposite on light: emulate with black on dark + * light opposite on light: emulate with white on light */ + for(i = 0; i < 6; i++) + { + SETPAIR(hue_list[i], hue_list[(i + 3) % 6], + 128 + slang_assoc[hue_list[i] + 16 * CACA_COLOR_BLACK]); + SETPAIR(hue_list[i] + 8, hue_list[(i + 3) % 6], + 128 + slang_assoc[hue_list[i] + 8 + 16 * CACA_COLOR_BLACK]); + SETPAIR(hue_list[(i + 3) % 6], hue_list[i] + 8, + 128 + slang_assoc[CACA_COLOR_BLACK + 16 * hue_list[i]]); + SETPAIR(hue_list[(i + 3) % 6] + 8, hue_list[i] + 8, + 128 + slang_assoc[CACA_COLOR_WHITE + 16 * (hue_list[i] + 8)]); + } +#endif +} +#endif /* USE_SLANG */ +