The repository formerly known as dotfiles
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.

scheme.c 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /* Copyright (C) 2018 Curtis McEnroe <june@causal.agency>
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU Affero General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <err.h>
  17. #include <math.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <sysexits.h>
  22. #include <unistd.h>
  23. #include "png.h"
  24. typedef unsigned uint;
  25. typedef unsigned char byte;
  26. static const struct HSV { double h, s, v; }
  27. R = { 0.0, 1.0, 1.0 },
  28. Y = { 60.0, 1.0, 1.0 },
  29. G = { 120.0, 1.0, 1.0 },
  30. C = { 180.0, 1.0, 1.0 },
  31. B = { 240.0, 1.0, 1.0 },
  32. M = { 300.0, 1.0, 1.0 };
  33. static struct RGB { byte r, g, b; } toRGB(struct HSV hsv) {
  34. double c = hsv.v * hsv.s;
  35. double h = hsv.h / 60.0;
  36. double x = c * (1.0 - fabs(fmod(h, 2.0) - 1.0));
  37. double m = hsv.v - c;
  38. double r = m, g = m, b = m;
  39. if (h <= 1.0) { r += c; g += x; }
  40. else if (h <= 2.0) { r += x; g += c; }
  41. else if (h <= 3.0) { g += c; b += x; }
  42. else if (h <= 4.0) { g += x; b += c; }
  43. else if (h <= 5.0) { r += x; b += c; }
  44. else if (h <= 6.0) { r += c; b += x; }
  45. return (struct RGB) { r * 255.0, g * 255.0, b * 255.0 };
  46. }
  47. static struct HSV x(struct HSV o, double hd, double sf, double vf) {
  48. return (struct HSV) {
  49. fmod(o.h + hd, 360.0),
  50. fmin(o.s * sf, 1.0),
  51. fmin(o.v * vf, 1.0),
  52. };
  53. }
  54. enum {
  55. Black,
  56. Red,
  57. Green,
  58. Yellow,
  59. Blue,
  60. Magenta,
  61. Cyan,
  62. White,
  63. Dark = 0,
  64. Light = 8,
  65. Background = 16,
  66. Foreground,
  67. Bold,
  68. Selection,
  69. Cursor,
  70. SchemeLen,
  71. };
  72. static struct HSV scheme[SchemeLen];
  73. static void generate(void) {
  74. scheme[Light + Black] = x(R, +45.0, 0.3, 0.3);
  75. scheme[Light + Red] = x(R, +10.0, 0.9, 0.8);
  76. scheme[Light + Green] = x(G, -55.0, 0.8, 0.6);
  77. scheme[Light + Yellow] = x(Y, -20.0, 0.8, 0.8);
  78. scheme[Light + Blue] = x(B, -55.0, 0.4, 0.5);
  79. scheme[Light + Magenta] = x(M, +45.0, 0.4, 0.6);
  80. scheme[Light + Cyan] = x(C, -60.0, 0.3, 0.6);
  81. scheme[Light + White] = x(R, +45.0, 0.3, 0.8);
  82. scheme[Dark + Black] = x(scheme[Light + Black], 0.0, 1.0, 0.3);
  83. scheme[Dark + White] = x(scheme[Light + White], 0.0, 1.0, 0.6);
  84. for (uint i = Red; i < White; ++i) {
  85. scheme[Dark + i] = x(scheme[Light + i], 0.0, 1.0, 0.8);
  86. }
  87. scheme[Background] = x(scheme[Dark + Black], 0.0, 1.0, 0.9);
  88. scheme[Foreground] = x(scheme[Light + White], 0.0, 1.0, 0.9);
  89. scheme[Bold] = x(scheme[Light + White], 0.0, 1.0, 1.0);
  90. scheme[Selection] = x(scheme[Light + Red], +10.0, 1.0, 0.8);
  91. scheme[Cursor] = x(scheme[Dark + White], 0.0, 1.0, 0.8);
  92. }
  93. static void swap(uint a, uint b) {
  94. struct HSV t = scheme[a];
  95. scheme[a] = scheme[b];
  96. scheme[b] = t;
  97. }
  98. static void invert(void) {
  99. swap(Dark + Black, Light + White);
  100. swap(Light + Black, Dark + White);
  101. }
  102. static void printHSV(uint n) {
  103. printf("%g,%g,%g\n", scheme[n].h, scheme[n].s, scheme[n].v);
  104. }
  105. static void printRGB(uint n) {
  106. struct RGB rgb = toRGB(scheme[n]);
  107. printf("%02hhX%02hhX%02hhX\n", rgb.r, rgb.g, rgb.b);
  108. }
  109. static const char *CNames[SchemeLen] = {
  110. [Dark + Black] = "DarkBlack",
  111. [Dark + Red] = "DarkRed",
  112. [Dark + Green] = "DarkGreen",
  113. [Dark + Yellow] = "DarkYellow",
  114. [Dark + Blue] = "DarkBlue",
  115. [Dark + Magenta] = "DarkMagenta",
  116. [Dark + Cyan] = "DarkCyan",
  117. [Dark + White] = "DarkWhite",
  118. [Light + Black] = "LightBlack",
  119. [Light + Red] = "LightRed",
  120. [Light + Green] = "LightGreen",
  121. [Light + Yellow] = "LightYellow",
  122. [Light + Blue] = "LightBlue",
  123. [Light + Magenta] = "LightMagenta",
  124. [Light + Cyan] = "LightCyan",
  125. [Light + White] = "LightWhite",
  126. [Background] = "Background",
  127. [Foreground] = "Foreground",
  128. [Bold] = "Bold",
  129. [Selection] = "Selection",
  130. [Cursor] = "Cursor",
  131. };
  132. static void printCHead(void) {
  133. printf("enum {\n");
  134. }
  135. static void printC(uint n) {
  136. struct RGB rgb = toRGB(scheme[n]);
  137. printf("\t%s = 0x%02hhX%02hhX%02hhX,\n", CNames[n], rgb.r, rgb.g, rgb.b);
  138. }
  139. static void printCTail(void) {
  140. printf("};\n");
  141. }
  142. static void printLinux(uint n) {
  143. struct RGB rgb = toRGB(scheme[n]);
  144. printf("\x1B]P%X%02hhX%02hhX%02hhX", n, rgb.r, rgb.g, rgb.b);
  145. }
  146. static const char *MinttyNames[SchemeLen] = {
  147. [Dark + Black] = "Black",
  148. [Dark + Red] = "Red",
  149. [Dark + Green] = "Green",
  150. [Dark + Yellow] = "Yellow",
  151. [Dark + Blue] = "Blue",
  152. [Dark + Magenta] = "Magenta",
  153. [Dark + Cyan] = "Cyan",
  154. [Dark + White] = "White",
  155. [Light + Black] = "BoldBlack",
  156. [Light + Red] = "BoldRed",
  157. [Light + Green] = "BoldGreen",
  158. [Light + Yellow] = "BoldYellow",
  159. [Light + Blue] = "BoldBlue",
  160. [Light + Magenta] = "BoldMagenta",
  161. [Light + Cyan] = "BoldCyan",
  162. [Light + White] = "BoldWhite",
  163. [Background] = "BackgroundColour",
  164. [Foreground] = "ForegroundColour",
  165. [Cursor] = "CursorColour",
  166. };
  167. static void printMintty(uint n) {
  168. if (!MinttyNames[n]) return;
  169. struct RGB rgb = toRGB(scheme[n]);
  170. printf("%s=%hhd,%hhd,%hhd\n", MinttyNames[n], rgb.r, rgb.g, rgb.b);
  171. }
  172. static void png(uint at, uint to) {
  173. if (to - at > 256) to = at + 256;
  174. uint len = to - at;
  175. uint swatchWidth = 64;
  176. uint swatchHeight = 64;
  177. uint cols = 8;
  178. uint rows = (len + cols - 1) / cols;
  179. uint width = swatchWidth * cols;
  180. uint height = swatchHeight * rows;
  181. pngHead(stdout, width, height, 8, PNGIndexed);
  182. struct RGB rgb[len];
  183. for (uint i = 0; i < len; ++i) {
  184. rgb[i] = toRGB(scheme[at + i]);
  185. }
  186. pngPalette(stdout, (byte *)rgb, sizeof(rgb));
  187. uint8_t data[height][1 + width];
  188. memset(data, 0, sizeof(data));
  189. for (uint32_t y = 0; y < height; ++y) {
  190. data[y][0] = (y % swatchHeight) ? PNGUp : PNGSub;
  191. }
  192. for (uint i = at; i < to; ++i) {
  193. uint p = i - at;
  194. uint32_t y = swatchHeight * (p / cols);
  195. uint32_t x = swatchWidth * (p % cols);
  196. data[y][1 + x] = x ? 1 : p;
  197. }
  198. pngData(stdout, (byte *)data, sizeof(data));
  199. pngTail(stdout);
  200. }
  201. static void print(void (*fn)(uint), uint at, uint to) {
  202. for (uint i = at; i < to; ++i) {
  203. fn(i);
  204. }
  205. }
  206. int main(int argc, char *argv[]) {
  207. generate();
  208. uint at = 0;
  209. uint to = Background;
  210. char out = 'x';
  211. int opt;
  212. while (0 < (opt = getopt(argc, argv, "acghilmp:tx"))) {
  213. switch (opt) {
  214. break; case 'a': to = Background;
  215. break; case 'i': invert();
  216. break; case 'p': at = strtoul(optarg, NULL, 0); to = at + 1;
  217. break; case 't': to = SchemeLen;
  218. break; case '?': return EX_USAGE;
  219. break; default: out = opt;
  220. }
  221. }
  222. switch (out) {
  223. break; case 'c': printCHead(); print(printC, at, to); printCTail();
  224. break; case 'g': png(at, to);
  225. break; case 'h': print(printHSV, at, to);
  226. break; case 'l': print(printLinux, at, to);
  227. break; case 'm': print(printMintty, at, to);
  228. break; case 'x': print(printRGB, at, to);
  229. }
  230. return EX_OK;
  231. }