summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--bin/README1
-rw-r--r--bin/bin.73
-rw-r--r--bin/man1/scheme.135
-rw-r--r--bin/scheme.c280
4 files changed, 143 insertions, 176 deletions
diff --git a/bin/README b/bin/README
index 74de8a52..bd12df94 100644
--- a/bin/README
+++ b/bin/README
@@ -23,6 +23,7 @@ DESCRIPTION
      pngo(1)     PNG optimizer
      psf2png(1)  PSF2 to PNG renderer
      psfed(1)    PSF2 font editor
+     scheme(1)   color scheme
      ttpre(1)    man output to HTML
      up(1)       upload file
      wake(1)     wake-on-LAN
diff --git a/bin/bin.7 b/bin/bin.7
index 8d5239c1..e6ab3cc0 100644
--- a/bin/bin.7
+++ b/bin/bin.7
@@ -64,6 +64,9 @@ PSF2 to PNG renderer
 .It Xr psfed 1
 PSF2 font editor
 .
+.It Xr scheme 1
+color scheme
+.
 .It Xr ttpre 1
 man output to HTML
 .
diff --git a/bin/man1/scheme.1 b/bin/man1/scheme.1
index fe13b367..738d9cd7 100644
--- a/bin/man1/scheme.1
+++ b/bin/man1/scheme.1
@@ -1,10 +1,10 @@
-.Dd September 7, 2018
+.Dd February 12, 2019
 .Dt SCHEME 1
 .Os
 .
 .Sh NAME
 .Nm scheme
-.Nd terminal color scheme
+.Nd color scheme
 .
 .Sh SYNOPSIS
 .Nm
@@ -13,51 +13,38 @@
 .
 .Sh DESCRIPTION
 .Nm
-generates a terminal color scheme
+generates a color scheme
 and outputs it in a number of formats.
 .
 .Pp
 The arguments are as follows:
 .Bl -tag -width Ds
 .It Fl a
-Output only the 16 ANSI colors.
+Generate the 16 ANSI colors.
 This is the default.
-.
 .It Fl c
 Output a C enum.
-.
 .It Fl g
 Output a swatch PNG.
-.
 .It Fl h
-Output HSV.
-.
+Output floating point HSV.
 .It Fl i
-Swap white and black.
-.
+Swap black and white.
 .It Fl l
 Output Linux console OSC sequences.
-.
 .It Fl m
 Output a
 .Xr mintty 1
 theme.
-Should be used with
+Use with
 .Fl t .
-.
 .It Fl p Ar n
-Only output the color
+Generate only the color
 .Ar n .
-.
 .It Fl t
-Additionally output terminal
-background,
-foreground,
-bold,
-selection
-and cursor
-colors.
-.
+Generate the 16 ANSI colors as well as
+background, foreground, bold, selection and cursor colors.
 .It Fl x
 Output hexadecimal RGB.
+This is the default.
 .El
diff --git a/bin/scheme.c b/bin/scheme.c
index 1bd1cea0..43fc26fc 100644
--- a/bin/scheme.c
+++ b/bin/scheme.c
@@ -31,23 +31,15 @@ struct HSV {
 	double h, s, v;
 };
 
-static const struct HSV
-	R = {   0.0, 1.0, 1.0 },
-	Y = {  60.0, 1.0, 1.0 },
-	G = { 120.0, 1.0, 1.0 },
-	C = { 180.0, 1.0, 1.0 },
-	B = { 240.0, 1.0, 1.0 },
-	M = { 300.0, 1.0, 1.0 };
-
 struct RGB {
 	byte r, g, b;
 };
 
-static struct RGB rgb(struct HSV hsv) {
-	double c = hsv.v * hsv.s;
-	double h = hsv.h / 60.0;
+static struct RGB convert(struct HSV o) {
+	double c = o.v * o.s;
+	double h = o.h / 60.0;
 	double x = c * (1.0 - fabs(fmod(h, 2.0) - 1.0));
-	double m = hsv.v - c;
+	double m = o.v - c;
 	double r = m, g = m, b = m;
 	if      (h <= 1.0) { r += c; g += x; }
 	else if (h <= 2.0) { r += x; g += c; }
@@ -58,6 +50,14 @@ static struct RGB rgb(struct HSV hsv) {
 	return (struct RGB) { r * 255.0, g * 255.0, b * 255.0 };
 }
 
+static const struct HSV
+R = {   0.0, 1.0, 1.0 },
+Y = {  60.0, 1.0, 1.0 },
+G = { 120.0, 1.0, 1.0 },
+C = { 180.0, 1.0, 1.0 },
+B = { 240.0, 1.0, 1.0 },
+M = { 300.0, 1.0, 1.0 };
+
 static struct HSV x(struct HSV o, double hd, double sf, double vf) {
 	return (struct HSV) {
 		fmod(o.h + hd, 360.0),
@@ -68,196 +68,172 @@ static struct HSV x(struct HSV o, double hd, double sf, double vf) {
 
 enum {
 	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White,
-	Dark = 0, Light = 8,
-	Background = 16, Foreground, Bold, Selection, Cursor,
+	Dark = 0,
+	Light = 8,
+	Background = 16,
+	Foreground,
+	Bold,
+	Selection,
+	Cursor,
 	SchemeLen,
 };
 static struct HSV scheme[SchemeLen];
+static struct HSV *dark = &scheme[Dark];
+static struct HSV *light = &scheme[Light];
 
 static void generate(void) {
-	scheme[Light + Black]   = x(R, +45.0, 0.3, 0.3);
-	scheme[Light + Red]     = x(R, +10.0, 0.9, 0.8);
-	scheme[Light + Green]   = x(G, -55.0, 0.8, 0.6);
-	scheme[Light + Yellow]  = x(Y, -20.0, 0.8, 0.8);
-	scheme[Light + Blue]    = x(B, -55.0, 0.4, 0.5);
-	scheme[Light + Magenta] = x(M, +45.0, 0.4, 0.6);
-	scheme[Light + Cyan]    = x(C, -60.0, 0.3, 0.6);
-	scheme[Light + White]   = x(R, +45.0, 0.3, 0.8);
-
-	scheme[Dark + Black] = x(scheme[Light + Black], 0.0, 1.0, 0.3);
-	scheme[Dark + White] = x(scheme[Light + White], 0.0, 1.0, 0.6);
+	light[Black]   = x(R, +45.0, 0.3, 0.3);
+	light[Red]     = x(R, +10.0, 0.9, 0.8);
+	light[Green]   = x(G, -55.0, 0.8, 0.6);
+	light[Yellow]  = x(Y, -20.0, 0.8, 0.8);
+	light[Blue]    = x(B, -55.0, 0.4, 0.5);
+	light[Magenta] = x(M, +45.0, 0.4, 0.6);
+	light[Cyan]    = x(C, -60.0, 0.3, 0.6);
+	light[White]   = x(R, +45.0, 0.3, 0.8);
+
+	dark[Black] = x(light[Black], 0.0, 1.0, 0.3);
+	dark[White] = x(light[White], 0.0, 1.0, 0.6);
 	for (uint i = Red; i < White; ++i) {
-		scheme[Dark + i] = x(scheme[Light + i], 0.0, 1.0, 0.8);
+		dark[i] = x(light[i], 0.0, 1.0, 0.8);
 	}
 
-	scheme[Background] = x(scheme[Dark + Black],    0.0, 1.0, 0.9);
-	scheme[Foreground] = x(scheme[Light + White],   0.0, 1.0, 0.9);
-	scheme[Bold]       = x(scheme[Light + White],   0.0, 1.0, 1.0);
-	scheme[Selection]  = x(scheme[Light + Red],   +10.0, 1.0, 0.8);
-	scheme[Cursor]     = x(scheme[Dark + White],    0.0, 1.0, 0.8);
+	scheme[Background] = x(dark[Black],  0.0, 1.0, 0.9);
+	scheme[Foreground] = x(light[White], 0.0, 1.0, 0.9);
+	scheme[Bold]       = x(light[White], 0.0, 1.0, 1.0);
+	scheme[Selection]  = x(light[Red], +10.0, 1.0, 0.8);
+	scheme[Cursor]     = x(dark[White],  0.0, 1.0, 0.8);
 }
 
-static void swap(uint a, uint b) {
-	struct HSV t = scheme[a];
-	scheme[a] = scheme[b];
-	scheme[b] = t;
+static void swap(struct HSV *a, struct HSV *b) {
+	struct HSV c = *a;
+	*a = *b;
+	*b = c;
 }
 
 static void invert(void) {
-	swap(Dark + Black, Light + White);
-	swap(Light + Black, Dark + White);
+	swap(&dark[Black], &light[White]);
+	swap(&dark[White], &light[Black]);
+}
+
+typedef void OutputFn(const struct HSV *hsv, uint len);
+
+static void outputHSV(const struct HSV *hsv, uint len) {
+	for (uint i = 0; i < len; ++i) {
+		printf("%g,%g,%g\n", hsv[i].h, hsv[i].s, hsv[i].v);
+	}
 }
 
-static void printHSV(uint n) {
-	printf("%g,%g,%g\n", scheme[n].h, scheme[n].s, scheme[n].v);
+#define FORMAT_RGB "%02hhX%02hhX%02hhX"
+
+static void outputRGB(const struct HSV *hsv, uint len) {
+	for (uint i = 0; i < len; ++i) {
+		struct RGB rgb = convert(hsv[i]);
+		printf(FORMAT_RGB "\n", rgb.r, rgb.g, rgb.b);
+	}
 }
 
-static void printRGB(uint n) {
-	printf(
-		"%02hhX%02hhX%02hhX\n",
-		rgb(scheme[n]).r, rgb(scheme[n]).g, rgb(scheme[n]).b
-	);
+static void outputLinux(const struct HSV *hsv, uint len) {
+	for (uint i = 0; i < len; ++i) {
+		struct RGB rgb = convert(hsv[i]);
+		printf("\x1B]P%X" FORMAT_RGB, i, rgb.r, rgb.g, rgb.b);
+	}
 }
 
-static const char *CNames[SchemeLen] = {
-	[Dark + Black]    = "DarkBlack",
-	[Dark + Red]      = "DarkRed",
-	[Dark + Green]    = "DarkGreen",
-	[Dark + Yellow]   = "DarkYellow",
-	[Dark + Blue]     = "DarkBlue",
-	[Dark + Magenta]  = "DarkMagenta",
-	[Dark + Cyan]     = "DarkCyan",
-	[Dark + White]    = "DarkWhite",
-	[Light + Black]   = "LightBlack",
-	[Light + Red]     = "LightRed",
-	[Light + Green]   = "LightGreen",
-	[Light + Yellow]  = "LightYellow",
-	[Light + Blue]    = "LightBlue",
-	[Light + Magenta] = "LightMagenta",
-	[Light + Cyan]    = "LightCyan",
-	[Light + White]   = "LightWhite",
-	[Background]      = "Background",
-	[Foreground]      = "Foreground",
-	[Bold]            = "Bold",
-	[Selection]       = "Selection",
-	[Cursor]          = "Cursor",
+static const char *Enum[SchemeLen] = {
+	"DarkBlack", "DarkRed", "DarkGreen", "DarkYellow",
+	"DarkBlue", "DarkMagenta", "DarkCyan", "DarkWhite",
+	"LightBlack", "LightRed", "LightGreen", "LightYellow",
+	"LightBlue", "LightMagenta", "LightCyan", "LightWhite",
+	"Background", "Foreground", "Bold", "Selection", "Cursor",
 };
-static void printCHead(void) {
+
+static void outputEnum(const struct HSV *hsv, uint len) {
 	printf("enum {\n");
-}
-static void printC(uint n) {
-	printf(
-		"\t%s = 0x%02hhX%02hhX%02hhX,\n",
-		CNames[n], rgb(scheme[n]).r, rgb(scheme[n]).g, rgb(scheme[n]).b
-	);
-}
-static void printCTail(void) {
+	for (uint i = 0; i < len; ++i) {
+		struct RGB rgb = convert(hsv[i]);
+		printf("\t%s = 0x" FORMAT_RGB ",\n", Enum[i], rgb.r, rgb.g, rgb.b);
+	}
 	printf("};\n");
 }
 
-static void printLinux(uint n) {
-	printf(
-		"\x1B]P%X%02hhX%02hhX%02hhX",
-		n, rgb(scheme[n]).r, rgb(scheme[n]).g, rgb(scheme[n]).b
-	);
-}
-
-static const char *MinttyNames[SchemeLen] = {
-	[Dark + Black]    = "Black",
-	[Dark + Red]      = "Red",
-	[Dark + Green]    = "Green",
-	[Dark + Yellow]   = "Yellow",
-	[Dark + Blue]     = "Blue",
-	[Dark + Magenta]  = "Magenta",
-	[Dark + Cyan]     = "Cyan",
-	[Dark + White]    = "White",
-	[Light + Black]   = "BoldBlack",
-	[Light + Red]     = "BoldRed",
-	[Light + Green]   = "BoldGreen",
-	[Light + Yellow]  = "BoldYellow",
-	[Light + Blue]    = "BoldBlue",
-	[Light + Magenta] = "BoldMagenta",
-	[Light + Cyan]    = "BoldCyan",
-	[Light + White]   = "BoldWhite",
-	[Background]      = "BackgroundColour",
-	[Foreground]      = "ForegroundColour",
-	[Cursor]          = "CursorColour",
+static const char *Mintty[SchemeLen] = {
+	"Black", "Red", "Green", "Yellow",
+	"Blue", "Magenta", "Cyan", "White",
+	"BoldBlack", "BoldRed", "BoldGreen", "BoldYellow",
+	"BoldBlue", "BoldMagenta", "BoldCyan", "BoldWhite",
+	[Background] = "BackgroundColour",
+	[Foreground] = "ForegroundColour",
+	[Cursor]     = "CursorColour",
 };
-static void printMintty(uint n) {
-	if (!MinttyNames[n]) return;
-	printf(
-		"%s=%hhu,%hhu,%hhu\n",
-		MinttyNames[n], rgb(scheme[n]).r, rgb(scheme[n]).g, rgb(scheme[n]).b
-	);
-}
 
-static void png(uint at, uint to) {
-	if (to - at > 256) to = at + 256;
+static void outputMintty(const struct HSV *hsv, uint len) {
+	for (uint i = 0; i < len; ++i) {
+		if (!Mintty[i]) continue;
+		struct RGB rgb = convert(hsv[i]);
+		printf("%s=%hhu,%hhu,%hhu\n", Mintty[i], rgb.r, rgb.g, rgb.b);
+	}
+}
 
-	uint len = to - at;
-	uint swatchWidth = 64;
-	uint swatchHeight = 64;
-	uint cols = 8;
-	uint rows = (len + cols - 1) / cols;
-	uint width = swatchWidth * cols;
-	uint height = swatchHeight * rows;
+enum {
+	SwatchWidth = 64,
+	SwatchHeight = 64,
+	SwatchCols = 8,
+};
 
+static void outputPNG(const struct HSV *hsv, uint len) {
+	uint rows = (len + SwatchCols - 1) / SwatchCols;
+	uint width = SwatchWidth * SwatchCols;
+	uint height = SwatchHeight * rows;
 	pngHead(stdout, width, height, 8, PNGIndexed);
 
 	struct RGB pal[len];
 	for (uint i = 0; i < len; ++i) {
-		pal[i] = rgb(scheme[at + i]);
+		pal[i] = convert(hsv[i]);
 	}
 	pngPalette(stdout, (byte *)pal, sizeof(pal));
 
-	uint8_t data[height][1 + width];
+	byte data[height][1 + width];
 	memset(data, 0, sizeof(data));
-	for (uint32_t y = 0; y < height; ++y) {
-		data[y][0] = (y % swatchHeight) ? PNGUp : PNGSub;
+	for (uint y = 0; y < height; ++y) {
+		data[y][0] = (y % SwatchHeight ? PNGUp : PNGSub);
 	}
-	for (uint i = at; i < to; ++i) {
-		uint p = i - at;
-		uint32_t y = swatchHeight * (p / cols);
-		uint32_t x = swatchWidth * (p % cols);
-		data[y][1 + x] = x ? 1 : p;
+	for (uint i = 0; i < len; ++i) {
+		uint y = SwatchHeight * (i / SwatchCols);
+		uint x = SwatchWidth * (i % SwatchCols);
+		data[y][1 + x] = (x ? 1 : i);
 	}
-
 	pngData(stdout, (byte *)data, sizeof(data));
 	pngTail(stdout);
 }
 
-static void print(void fn(uint), uint at, uint to) {
-	for (uint i = at; i < to; ++i) {
-		fn(i);
-	}
-}
-
 int main(int argc, char *argv[]) {
 	generate();
-	uint at = 0;
-	uint to = Background;
-	char out = 'x';
+
+	OutputFn *output = outputRGB;
+	const struct HSV *hsv = scheme;
+	uint len = 16;
 
 	int opt;
 	while (0 < (opt = getopt(argc, argv, "acghilmp:tx"))) {
 		switch (opt) {
-			break; case 'a': to = Background;
+			break; case 'a': len = 16;
+			break; case 'c': output = outputEnum;
+			break; case 'g': output = outputPNG;
+			break; case 'h': output = outputHSV;
 			break; case 'i': invert();
-			break; case 'p': at = strtoul(optarg, NULL, 0); to = at + 1;
-			break; case 't': to = SchemeLen;
-			break; case '?': return EX_USAGE;
-			break; default: out = opt;
+			break; case 'l': output = outputLinux;
+			break; case 'm': output = outputMintty;
+			break; case 'p': {
+				uint p = strtoul(optarg, NULL, 0);
+				if (p >= SchemeLen) return EX_USAGE;
+				hsv = &scheme[p];
+				len = 1;
+			}
+			break; case 't': len = SchemeLen;
+			break; case 'x': output = outputRGB;
+			break; default:  return EX_USAGE;
 		}
 	}
 
-	switch (out) {
-		break; case 'c': printCHead(); print(printC, at, to); printCTail();
-		break; case 'g': png(at, to);
-		break; case 'h': print(printHSV, at, to);
-		break; case 'l': print(printLinux, at, to);
-		break; case 'm': print(printMintty, at, to);
-		break; case 'x': print(printRGB, at, to);
-	}
-
-	return EX_OK;
+	output(hsv, len);
 }