You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * optipal S-Lang optimised palette generator for libcaca
  3. * Copyright (c) 2003 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the Do What The Fuck You Want To
  10. * Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. #include "config.h"
  14. #include "common.h"
  15. #include <stdio.h>
  16. #include "cucul.h" /* Only necessary for CUCUL_* macros */
  17. static void base_colors(void);
  18. static void emulated_colors(void);
  19. static void unused_colors(void);
  20. static int slang_assoc[16*16], palette[16*16];
  21. /* 6 colours in hue order */
  22. static unsigned int const hue_list[] =
  23. {
  24. CUCUL_COLOR_RED,
  25. CUCUL_COLOR_BROWN,
  26. CUCUL_COLOR_GREEN,
  27. CUCUL_COLOR_CYAN,
  28. CUCUL_COLOR_BLUE,
  29. CUCUL_COLOR_MAGENTA
  30. };
  31. #define SETPAIR(_fg, _bg, _n) \
  32. do \
  33. { \
  34. int fg = _fg, bg = _bg, n = _n; \
  35. slang_assoc[fg + 16 * bg] = n; \
  36. palette[n] = fg + 16 * bg; \
  37. } \
  38. while(0);
  39. int main(void)
  40. {
  41. int i;
  42. for(i = 0; i < 16 * 16; i++)
  43. {
  44. slang_assoc[i] = -1;
  45. palette[i] = -1;
  46. }
  47. /* The base colour pairs (0-127) */
  48. base_colors();
  49. /* Now the less important pairs that we can afford to emulate using
  50. * previously defined colour pairs. */
  51. emulated_colors();
  52. /* Fill the rest of the palette with equal colour pairs such as black
  53. * on black. They will never be used, but nevermind. */
  54. unused_colors();
  55. /* Output the palette */
  56. printf("static int const slang_palette[2*16*16] =\n{\n");
  57. for(i = 0; i < 16 * 16; i++)
  58. {
  59. if((i % 8) == 0) printf(" ");
  60. printf("%2i, %2i, ", palette[i] % 16, palette[i] / 16);
  61. if((i % 8) == 7) printf("\n");
  62. }
  63. printf("};\n\n");
  64. /* Output the association table */
  65. printf("static int const slang_assoc[16*16] =\n{\n");
  66. for(i = 0; i < 16 * 16; i++)
  67. {
  68. if((i % 16) == 0) printf(" ");
  69. printf("%i, ", slang_assoc[i]);
  70. if((i % 16) == 15) printf("\n");
  71. }
  72. printf("};\n");
  73. return 0;
  74. }
  75. /*
  76. * 256 character pairs are definable, but only 128 can be used. This is
  77. * because slsmg.c's This_Color variable uses its 8th bit to indicate an
  78. * alternate character set. Replacing a few 0x7F with 0xFF in sldisply.c
  79. * works around the problem but gets rid of the alternate charset.
  80. *
  81. * We can work around this problem. See this usage grid:
  82. *
  83. * bg 1 1 1 1 1 1
  84. * fg 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  85. *
  86. * 0 (black) C C C C C C F B c c c c c c F
  87. * 1 (blue) A h D h D i f C C h E h E k g
  88. * 2 (green) A h D h i D f C h C E h k E g
  89. * 3 (cyan) A D D i h h f C E E C k h h g
  90. * 4 (red) A h h i D D f C h h k C E E g
  91. * 5 (magenta) A D i h D h f C E k h E C h g
  92. * 6 (brown) A i D h D h f C k E h E h C g
  93. * 7 (light gray) A F a a a a a B C C C C C C B
  94. *
  95. * 8 (dark gray) A C C C C C C B d d d d d d F
  96. * 9 (light blue) A C h E h E j C e h D h D l C
  97. * 10 (light green) A h C E h j E C e h D h l D C
  98. * 11 (light cyan) A E E C j h h C e D D l h h C
  99. * 12 (light red) A h h j C E E C e h h l D D C
  100. * 13 (light magenta) A E j h E C h C e D l h D h C
  101. * 14 (yellow) A j E h E h C C e l D h D h C
  102. * 15 (white) A F b b b b b B F C C C C C C
  103. *
  104. * ' ': useless colour pairs that can be emulated by printing a space in
  105. * any other colour pair that has the same background
  106. * 'A': black background colour pairs that are needed for the old renderer
  107. * 'B': gray combinations used for grayscale dithering
  108. * 'C': white/light, light/dark, lightgray/light, darkgray/dark, dark/black
  109. * combinations often used for saturation/value dithering (the two
  110. * other possible combinations, lightgray/dark and darkgray/light, are
  111. * not considered here)
  112. * 'D': next colour combinations for hue dithering (magenta/blue, blue/green
  113. * and so on)
  114. * 'E': next colour combinations for hue/value dithering (blue/lightgreen,
  115. * green/lightblue and so on)
  116. * 'F': black on light gray, black on white, white on dark gray, dark gray
  117. * on white, white on blue, light gray on blue (chosen arbitrarily)
  118. *
  119. * 'A': 15 colour pairs
  120. * 'A'+'B': 20 colour pairs
  121. * 'A'+'B'+'C': 74 colour pairs
  122. * 'A'+'B'+'C'+'D': 98 colour pairs
  123. * 'A'+'B'+'C'+'D'+'E': 122 colour pairs
  124. * 'A'+'B'+'C'+'D'+'E'+'F': 128 colour pairs
  125. *
  126. * The remaining slightly important colour pairs are:
  127. *
  128. * 'a': light gray on dark colour: emulate with light colour on dark colour
  129. * 'b': white on dark colour: emulate with light gray on light colour
  130. * 'c': black on light colour: emulate with dark gray on dark colour
  131. * 'd': dark gray on light colour: emulate with dark colour on light colour
  132. * 'e': light colour on dark gray: emulate with dark colour on dark gray
  133. * 'f': dark colour on light gray: emulate with light colour on light gray
  134. * 'g': dark colour on white: emulate with light colour on white
  135. *
  136. * And now the seldom used pairs:
  137. *
  138. * 'h': 120 degree hue pairs can be emulated as well; for instance blue on
  139. * red can be emulated using magenta on red, and blue on green using
  140. * cyan on green
  141. *
  142. * And the almost never used pairs:
  143. *
  144. * 'i': dark opposite on dark: emulate with dark opposite on black
  145. * 'j': light opposite on dark: emulate with light opposite on black
  146. * 'k': dark opposite on light: emulate with black on dark
  147. * 'l': light opposite on light: emulate with white on light
  148. */
  149. static void base_colors(void)
  150. {
  151. int i, cur = 0;
  152. /* black background colour pairs that are needed for the old renderer */
  153. for(i = 1; i < 16; i++)
  154. SETPAIR(i, CUCUL_COLOR_BLACK, cur++);
  155. /* gray combinations used for grayscale dithering */
  156. SETPAIR(CUCUL_COLOR_BLACK, CUCUL_COLOR_DARKGRAY, cur++);
  157. SETPAIR(CUCUL_COLOR_DARKGRAY, CUCUL_COLOR_LIGHTGRAY, cur++);
  158. SETPAIR(CUCUL_COLOR_LIGHTGRAY, CUCUL_COLOR_DARKGRAY, cur++);
  159. SETPAIR(CUCUL_COLOR_WHITE, CUCUL_COLOR_LIGHTGRAY, cur++);
  160. SETPAIR(CUCUL_COLOR_LIGHTGRAY, CUCUL_COLOR_WHITE, cur++);
  161. /* white/light, light/dark, lightgray/light, darkgray/dark, dark/black
  162. * combinations often used for saturation/value dithering (the two
  163. * other possible combinations, lightgray/dark and darkgray/light, are
  164. * not considered here) */
  165. for(i = 1; i < 7; i++)
  166. {
  167. SETPAIR(CUCUL_COLOR_WHITE, i + 8, cur++);
  168. SETPAIR(i + 8, CUCUL_COLOR_WHITE, cur++);
  169. SETPAIR(i, i + 8, cur++);
  170. SETPAIR(i + 8, i, cur++);
  171. SETPAIR(CUCUL_COLOR_LIGHTGRAY, i + 8, cur++);
  172. SETPAIR(i + 8, CUCUL_COLOR_LIGHTGRAY, cur++);
  173. SETPAIR(CUCUL_COLOR_DARKGRAY, i, cur++);
  174. SETPAIR(i, CUCUL_COLOR_DARKGRAY, cur++);
  175. SETPAIR(CUCUL_COLOR_BLACK, i, cur++);
  176. }
  177. /* next colour combinations for hue dithering (magenta/blue, blue/green
  178. * and so on) */
  179. for(i = 0; i < 6; i++)
  180. {
  181. SETPAIR(hue_list[i], hue_list[(i + 1) % 6], cur++);
  182. SETPAIR(hue_list[(i + 1) % 6], hue_list[i], cur++);
  183. SETPAIR(hue_list[i] + 8, hue_list[(i + 1) % 6] + 8, cur++);
  184. SETPAIR(hue_list[(i + 1) % 6] + 8, hue_list[i] + 8, cur++);
  185. }
  186. /* next colour combinations for hue/value dithering (blue/lightgreen,
  187. * green/lightblue and so on) */
  188. for(i = 0; i < 6; i++)
  189. {
  190. SETPAIR(hue_list[i], hue_list[(i + 1) % 6] + 8, cur++);
  191. SETPAIR(hue_list[(i + 1) % 6], hue_list[i] + 8, cur++);
  192. SETPAIR(hue_list[i] + 8, hue_list[(i + 1) % 6], cur++);
  193. SETPAIR(hue_list[(i + 1) % 6] + 8, hue_list[i], cur++);
  194. }
  195. /* black on light gray, black on white, white on dark gray, dark gray
  196. * on white, white on blue, light gray on blue (chosen arbitrarily) */
  197. SETPAIR(CUCUL_COLOR_BLACK, CUCUL_COLOR_LIGHTGRAY, cur++);
  198. SETPAIR(CUCUL_COLOR_BLACK, CUCUL_COLOR_WHITE, cur++);
  199. SETPAIR(CUCUL_COLOR_WHITE, CUCUL_COLOR_DARKGRAY, cur++);
  200. SETPAIR(CUCUL_COLOR_DARKGRAY, CUCUL_COLOR_WHITE, cur++);
  201. SETPAIR(CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE, cur++);
  202. SETPAIR(CUCUL_COLOR_LIGHTGRAY, CUCUL_COLOR_BLUE, cur++);
  203. }
  204. static void emulated_colors(void)
  205. {
  206. int i;
  207. /* light gray on dark colour: emulate with light colour on dark colour
  208. * white on dark colour: emulate with light gray on light colour
  209. * black on light colour: emulate with dark gray on dark colour
  210. * dark gray on light colour: emulate with dark colour on light colour
  211. * light colour on dark gray: emulate with dark colour on dark gray
  212. * dark colour on light gray: emulate with light colour on light gray
  213. * dark colour on white: emulate with light colour on white */
  214. for(i = 1; i < 7; i++)
  215. {
  216. if(i != CUCUL_COLOR_BLUE)
  217. {
  218. SETPAIR(CUCUL_COLOR_LIGHTGRAY, i, 128 +
  219. slang_assoc[i + 8 + 16 * i]);
  220. SETPAIR(CUCUL_COLOR_WHITE, i, 128 +
  221. slang_assoc[CUCUL_COLOR_LIGHTGRAY + 16 * (i + 8)]);
  222. }
  223. SETPAIR(CUCUL_COLOR_BLACK, i + 8,
  224. 128 + slang_assoc[CUCUL_COLOR_DARKGRAY + 16 * i]);
  225. SETPAIR(CUCUL_COLOR_DARKGRAY, i + 8,
  226. 128 + slang_assoc[i + 16 * (i + 8)]);
  227. SETPAIR(i + 8, CUCUL_COLOR_DARKGRAY,
  228. 128 + slang_assoc[i + 16 * CUCUL_COLOR_DARKGRAY]);
  229. SETPAIR(i, CUCUL_COLOR_LIGHTGRAY,
  230. 128 + slang_assoc[i + 8 + 16 * CUCUL_COLOR_LIGHTGRAY]);
  231. SETPAIR(i, CUCUL_COLOR_WHITE,
  232. 128 + slang_assoc[i + 8 + 16 * CUCUL_COLOR_WHITE]);
  233. }
  234. /* 120 degree hue pairs can be emulated as well; for instance blue on
  235. * red can be emulated using magenta on red, and blue on green using
  236. * cyan on green */
  237. for(i = 0; i < 6; i++)
  238. {
  239. SETPAIR(hue_list[(i + 2) % 6], hue_list[i],
  240. 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i]]);
  241. SETPAIR(hue_list[(i + 2) % 6] + 8, hue_list[i] + 8,
  242. 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 136]);
  243. SETPAIR(hue_list[(i + 2) % 6] + 8, hue_list[i],
  244. 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 8]);
  245. SETPAIR(hue_list[(i + 2) % 6], hue_list[i] + 8,
  246. 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 128]);
  247. SETPAIR(hue_list[(i + 4) % 6], hue_list[i],
  248. 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i]]);
  249. SETPAIR(hue_list[(i + 4) % 6] + 8, hue_list[i] + 8,
  250. 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 136]);
  251. SETPAIR(hue_list[(i + 4) % 6] + 8, hue_list[i],
  252. 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 8]);
  253. SETPAIR(hue_list[(i + 4) % 6], hue_list[i] + 8,
  254. 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 128]);
  255. }
  256. /* dark opposite on dark: emulate with dark opposite on black
  257. * light opposite on dark: emulate with light opposite on black
  258. * dark opposite on light: emulate with black on dark
  259. * light opposite on light: emulate with white on light */
  260. for(i = 0; i < 6; i++)
  261. {
  262. SETPAIR(hue_list[i], hue_list[(i + 3) % 6],
  263. 128 + slang_assoc[hue_list[i] + 16 * CUCUL_COLOR_BLACK]);
  264. SETPAIR(hue_list[i] + 8, hue_list[(i + 3) % 6],
  265. 128 + slang_assoc[hue_list[i] + 8 + 16 * CUCUL_COLOR_BLACK]);
  266. SETPAIR(hue_list[(i + 3) % 6], hue_list[i] + 8,
  267. 128 + slang_assoc[CUCUL_COLOR_BLACK + 16 * hue_list[i]]);
  268. SETPAIR(hue_list[(i + 3) % 6] + 8, hue_list[i] + 8,
  269. 128 + slang_assoc[CUCUL_COLOR_WHITE + 16 * (hue_list[i] + 8)]);
  270. }
  271. }
  272. static void unused_colors(void)
  273. {
  274. int i, j;
  275. for(i = 0, j = 0; i < 16 * 16; i++)
  276. {
  277. if(palette[i] == -1)
  278. {
  279. SETPAIR(j, j, i);
  280. j++;
  281. }
  282. }
  283. }