File: optipal.c

package info (click to toggle)
libcaca 0.99.beta19-2.2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 7,436 kB
  • sloc: ansic: 22,372; python: 2,316; cs: 1,213; cpp: 1,125; java: 916; objc: 836; makefile: 606; sh: 457; ruby: 193; asm: 65
file content (311 lines) | stat: -rw-r--r-- 11,833 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/*
 *  optipal       S-Lang optimised palette generator for libcaca
 *  Copyright (c) 2003-2012 Sam Hocevar <sam@hocevar.net>
 *                All Rights Reserved
 *
 *
 *  This program is free software. It comes without any warranty, to
 *  the extent permitted by applicable law. You can redistribute it
 *  and/or modify it under the terms of the Do What the Fuck You Want
 *  to Public License, Version 2, as published by Sam Hocevar. See
 *  http://www.wtfpl.net/ for more details.
 */

#include "config.h"

#if !defined(__KERNEL__)
#   include <stdio.h>
#endif

#include "caca.h" /* Only necessary for CACA_* macros */

static void base_colors(void);
static void emulated_colors(void);
static void unused_colors(void);

static int slang_assoc[16*16], palette[16*16];

/* 6 colours in hue order */
static unsigned int const hue_list[] =
{
    CACA_RED, CACA_BROWN, CACA_GREEN,
    CACA_CYAN, CACA_BLUE, CACA_MAGENTA
};

#define SETPAIR(_fg, _bg, _n) \
    do \
    { \
        int fg = _fg, bg = _bg, n = _n; \
        slang_assoc[fg + 16 * bg] = n; \
        palette[n] = fg + 16 * bg; \
    } \
    while(0);

int main(int argc, char *argv[])
{
    int i;

    for(i = 0; i < 16 * 16; i++)
    {
        slang_assoc[i] = -1;
        palette[i] = -1;
    }

    /* The base colour pairs (0-127) */
    base_colors();

    /* Now the less important pairs that we can afford to emulate using
     * previously defined colour pairs. */
    emulated_colors();

    /* Fill the rest of the palette with equal colour pairs such as black
     * on black. They will never be used, but nevermind. */
    unused_colors();

    /* Output the palette */
    printf("static int const slang_palette[2*16*16] =\n{\n");
    for(i = 0; i < 16 * 16; i++)
    {
        if((i % 8) == 0) printf("    ");
        printf("%2i, %2i,  ", palette[i] % 16, palette[i] / 16);
        if((i % 8) == 7) printf("\n");
    }
    printf("};\n\n");

    /* Output the association table */
    printf("static int const slang_assoc[16*16] =\n{\n");
    for(i = 0; i < 16 * 16; i++)
    {
        if((i % 16) == 0) printf("    ");
        printf("%i, ", slang_assoc[i]);
        if((i % 16) == 15) printf("\n");
    }
    printf("};\n");

    return 0;
}

/*
 *  256 character pairs are definable, but only 128 can be used. This is
 *  because slsmg.c's This_Color variable uses its 8th bit to indicate an
 *  alternate character set. Replacing a few 0x7F with 0xFF in sldisply.c
 *  works around the problem but gets rid of the alternate charset.
 *
 *  We can work around this problem. See this usage grid:
 *
 *                  bg                         1 1 1 1 1 1
 *    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 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
 *  'A': black background colour pairs that are needed for the old renderer
 *  'B': gray combinations used for grayscale dithering
 *  'C': 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)
 *  'D': next colour combinations for hue dithering (magenta/blue, blue/green
 *       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, 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': 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:
 *
 *  'a': light gray on dark colour: emulate with light colour on dark colour
 *  'b': white on dark colour: emulate with light gray on light colour
 *  '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 light gray
 *  'g': dark colour on white: emulate with light colour on white
 *
 *  And now the seldom used pairs:
 *
 *  'h': 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
 *
 *  And the almost never used pairs:
 *
 *  'i': dark opposite on dark: emulate with dark opposite on black
 *  'j': light opposite on dark: emulate with light opposite on black
 *  'k': dark opposite on light: emulate with black on dark
 *  'l': light opposite on light: emulate with white on light
 */

static void base_colors(void)
{
    int i, cur = 0;

    /* black background colour pairs that are needed for the old renderer */
    for(i = 1; i < 16; i++)
        SETPAIR(i, CACA_BLACK, cur++);

    /* gray combinations used for grayscale dithering */
    SETPAIR(CACA_BLACK, CACA_DARKGRAY, cur++);
    SETPAIR(CACA_DARKGRAY, CACA_LIGHTGRAY, cur++);
    SETPAIR(CACA_LIGHTGRAY, CACA_DARKGRAY, cur++);
    SETPAIR(CACA_WHITE, CACA_LIGHTGRAY, cur++);
    SETPAIR(CACA_LIGHTGRAY, CACA_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_WHITE, i + 8, cur++);
        SETPAIR(i + 8, CACA_WHITE, cur++);
        SETPAIR(i, i + 8, cur++);
        SETPAIR(i + 8, i, cur++);
        SETPAIR(CACA_LIGHTGRAY, i + 8, cur++);
        SETPAIR(i + 8, CACA_LIGHTGRAY, cur++);
        SETPAIR(CACA_DARKGRAY, i, cur++);
        SETPAIR(i, CACA_DARKGRAY, cur++);
        SETPAIR(CACA_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_BLACK, CACA_LIGHTGRAY, cur++);
    SETPAIR(CACA_BLACK, CACA_WHITE, cur++);
    SETPAIR(CACA_WHITE, CACA_DARKGRAY, cur++);
    SETPAIR(CACA_DARKGRAY, CACA_WHITE, cur++);
    SETPAIR(CACA_WHITE, CACA_BLUE, cur++);
    SETPAIR(CACA_LIGHTGRAY, CACA_BLUE, cur++);
}

static void emulated_colors(void)
{
    int i;

    /* 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_BLUE)
        {
            SETPAIR(CACA_LIGHTGRAY, i, 128 +
                    slang_assoc[i + 8 + 16 * i]);
            SETPAIR(CACA_WHITE, i, 128 +
                    slang_assoc[CACA_LIGHTGRAY + 16 * (i + 8)]);
        }
        SETPAIR(CACA_BLACK, i + 8,
                128 + slang_assoc[CACA_DARKGRAY + 16 * i]);
        SETPAIR(CACA_DARKGRAY, i + 8,
                128 + slang_assoc[i + 16 * (i + 8)]);
        SETPAIR(i + 8, CACA_DARKGRAY,
                128 + slang_assoc[i + 16 * CACA_DARKGRAY]);
        SETPAIR(i, CACA_LIGHTGRAY,
                128 + slang_assoc[i + 8 + 16 * CACA_LIGHTGRAY]);
        SETPAIR(i, CACA_WHITE,
                128 + slang_assoc[i + 8 + 16 * CACA_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_BLACK]);
        SETPAIR(hue_list[i] + 8, hue_list[(i + 3) % 6],
                128 + slang_assoc[hue_list[i] + 8 + 16 * CACA_BLACK]);
        SETPAIR(hue_list[(i + 3) % 6], hue_list[i] + 8,
                128 + slang_assoc[CACA_BLACK + 16 * hue_list[i]]);
        SETPAIR(hue_list[(i + 3) % 6] + 8, hue_list[i] + 8,
                128 + slang_assoc[CACA_WHITE + 16 * (hue_list[i] + 8)]);
    }
}

static void unused_colors(void)
{
    int i, j;

    for(i = 0, j = 0; i < 16 * 16; i++)
    {
        if(palette[i] == -1)
        {
            SETPAIR(j, j, i);
            j++;
        }
    }
}