shithub: picker

Download patch

ref: db3441295e5660984a4a4f13f419d5f119c06d7b
parent: 3897a967274ce9d36bb9ea10432bb7bec5de8b16
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Fri Mar 13 14:53:01 EDT 2020

actually support multiple colors

--- a/picker.c
+++ b/picker.c
@@ -93,84 +93,88 @@
 };
 
 static double *colors;
-static int ncolors, alpha;
+static int ncolors, curcolor, alpha;
 static Mode *mode;
 
 static Image *
-gradient(double *color, int w, int e)
+slider(int si, int w)
 {
+	static Image *s, *sliders[3];
+	static u8int *b, *buf[3];
 	Rectangle rect;
-	u8int *data;
-	Image *im;
 	double c[3];
-	double r, g, b, x;
+	double rgb[3], dt;
 	int i, mi;
 
 	rect = Rect(0, 0, w, 1);
-	if ((im = allocimage(display, rect, BGR24, 1, DNofill)) == nil)
-		sysfatal("allocimage: %r");
+	s = sliders[si];
+	if (s == nil || Dx(s->r) != w) {
+		buf[si] = realloc(buf[si], 3*w);
+		if (s != nil)
+			freeimage(s);
+		if ((s = sliders[si] = allocimage(display, rect, BGR24, 1, DNofill)) == nil)
+			sysfatal("allocimage: %r");
+	}
+	b = buf[si];
 
-	memmove(c, color, sizeof(c));
-	data = malloc(3*w);
-	x = mode->max[e] / w;
-	mi = c[e] / x;
-	c[e] = 0.0;
+	memmove(c, &colors[4*curcolor], sizeof(c));
+	dt = mode->max[si] / w;
+	mi = c[si] / dt;
+	c[si] = 0.0;
 	for (i = 0; i < w; i++) {
-		mode->torgb(c, &r, &g, &b);
-		data[i*3+0] = r*255.0;
-		data[i*3+1] = g*255.0;
-		data[i*3+2] = b*255.0;
+		mode->torgb(c, &rgb[0], &rgb[1], &rgb[2]);
+		b[i*3+0] = rgb[0]*255.0;
+		b[i*3+1] = rgb[1]*255.0;
+		b[i*3+2] = rgb[2]*255.0;
 		if (mi == i) {
-			data[i*3+0] = ~data[i*3+0];
-			data[i*3+1] = ~data[i*3+1];
-			data[i*3+2] = ~data[i*3+2];
+			b[i*3+0] = ~b[i*3+0];
+			b[i*3+1] = ~b[i*3+1];
+			b[i*3+2] = ~b[i*3+2];
 		}
-		c[e] += x;
-		if (c[e] > mode->max[e])
-			c[e] = mode->max[e];
+		c[si] = MIN(mode->max[si], c[si] + dt);
 	}
-	loadimage(im, rect, data, 3*w);
-	free(data);
+	loadimage(s, rect, b, 3*w);
 
-	return im;
+	return s;
 }
 
 static void
 redraw(void)
 {
-	Rectangle re;
+	Rectangle r;
 	int dh, i;
 	Image *im;
-	double r, g, b;
+	double rgb[3];
 	ulong u;
 	char hex[8];
 
 	lockdisplay(display);
 
-	//draw(screen, screen->r, display->white, nil, ZP);
-	re = screen->r;
-	dh = Dy(re) / 4;
-	re.max.y = re.min.y + dh;
+	//draw(screen, screen->r, display->black, nil, ZP);
+	r = screen->r;
+	dh = Dy(r) / 4;
+	r.max.y = r.min.y + dh;
 
 	for (i = 0; i < 3; i++) {
-		im = gradient(&colors[4*0], Dx(screen->r), i);
-		draw(screen, re, im, nil, ZP);
-		freeimage(im);
-		re.min.y += dh;
-		re.max.y += dh;
+		im = slider(i, Dx(screen->r));
+		draw(screen, r, im, nil, ZP);
+		r.min.y += dh;
+		r.max.y += dh;
 	}
 
-	mode->torgb(&colors[4*0], &r, &g, &b);
-	u = (int)(r*255.0)<<24 | (int)(r*255.0)<<24 | (int)(g*255.0)<<16 | (int)(b*255.0)<<8 | 0xff;
+	mode->torgb(&colors[4*curcolor], &rgb[0], &rgb[1], &rgb[2]);
+	for (i = 0; i < 3; i++)
+		rgb[i] = MAX(0.0, MIN(255.0, rgb[i]*255.0));
+	u = (ulong)rgb[0]<<24 | (ulong)rgb[1]<<16 | (ulong)rgb[2]<<8 | 0xff;
 	im = allocimage(display, Rect(0, 0, 1, 1), BGR24, 1, u);
-	draw(screen, re, im, nil, ZP);
+	draw(screen, r, im, nil, ZP);
 	freeimage(im);
 
 	im = allocimage(display, Rect(0, 0, 1, 1), BGR24, 1, ~u);
 	sprint(hex, "#%06lux", u>>8);
-	re.min.x += Dx(re)/2 - 7*stringwidth(font, "#")/2;
-	re.max.x += dh/2 - font->height/2;
-	string(screen, re.min, im, ZP, font, hex);
+	r.min.x += Dx(r)/2 - 7*stringwidth(font, "#")/2;
+	r.min.y += dh/2 - font->height/2;
+	string(screen, r.min, im, ZP, font, hex);
 	freeimage(im);
 
 	flushimage(display, 1);
@@ -271,6 +275,14 @@
 
 		case Ckey:
 			switch (r) {
+			case Kleft:
+				curcolor = MAX(0, curcolor-1);
+				redraw();
+				break;
+			case Kright:
+				curcolor = MIN(ncolors-1, curcolor+1);
+				redraw();
+				break;
 			case Kdel:
 				goto end;
 			}
@@ -285,7 +297,7 @@
 				m.xy.x = MAX(screen->r.min.x, MIN(screen->r.max.x, m.xy.x));
 				for (i = 0; i < 3; i++) {
 					if (m.xy.y >= p.y && m.xy.y < p.y+dh) {
-						colors[4*0 + i] = MIN(mode->max[i], (m.xy.x - screen->r.min.x) * mode->max[i]/Dx(screen->r));
+						colors[4*curcolor+i] = MIN(mode->max[i], (m.xy.x - screen->r.min.x) * mode->max[i]/Dx(screen->r));
 						redraw();
 						break;
 					}