shithub: pain

Download patch

ref: 672d39e9b1697da4b955f7a8b692994dfe916be7
parent: d63e7e5714f4f42a38372fcd57f56e0129fb4c14
author: jmq <jmq@jmq.sh>
date: Fri Aug 22 18:51:52 EDT 2025

I dunno man I haven't touched this in months (Pt.2)

--- a/pill/pill.c
+++ b/pill/pill.c
@@ -3,10 +3,13 @@
 #include <draw.h>
 #include <event.h>
 
+#define INTERNAL_HEIGHT 640
+#define INTERNAL_WIDTH 640
 #define STEPS 3600
 #define RADIUS .60
 #define MAXSATURATION 1.0
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
 #define RAD2DEG(r_) ((180.0)/PI * (r_))
 #define DEG2RAD(r_) (PI/(180.0) * (r_))
 #define BACKGROUNDCOLOR 0x22272EFF
@@ -17,6 +20,15 @@
 #define COLORPICKERRADIUS .25
 #define RECTANGLE(w, h) ((Rectangle){(Point){(0),(0)}, (Point){(w),(h)}})
 
+Image * VirtualWindow = nil;
+Image * HuePicker = nil;
+Image * Gradient = nil;
+u32int * RawGradient = nil;
+u32int RawGradientSize = 0;
+int DrawGradient = 1;
+int DrawHuePicker = 1;
+int WindowMoved = 1;
+
 Image * Circle = nil;
 uint CircleBPL = 0;
 u32int * RawCircle = nil;
@@ -28,6 +40,96 @@
 int RunApp = 1;
 int UpdateCircle = 1;
 
+int resizeimage(Image * d, Image * s)
+{
+	int i;
+	Point p;
+	Image * t, * c;
+	float scale;
+	Rectangle dr, sr, tr, r;
+
+	dr = rectsubpt(d->r, d->r.min);
+	sr = rectsubpt(s->r, s->r.min);
+
+	tr = dr;
+	if (Dx(dr) < Dx(sr)) {
+		tr.max.x = tr.min.x + Dx(sr);
+	}
+	if (Dy(dr) < Dy(sr)) {
+		tr.max.y = tr.min.y + Dy(sr);
+	}
+
+	if ((t = allocimage(display, tr, s->chan, 1, DNofill)) == nil) {
+		werrstr("allocimage: %r");
+		return -1;
+	}
+
+	if ((c = allocimage(display, Rect(0, 0, 1, Dy(tr)), s->chan, 1, DNofill)) == nil)
+	{
+		werrstr("allocimage: %r");
+		freeimage(t);
+		return -1;
+	}
+
+	if (Dx(tr) > Dx(sr)) {
+		scale = ((float)Dx(tr))/((float)Dx(sr));
+	} else {
+		scale = ((float)Dx(sr))/((float)Dx(tr));
+	}
+	p = dr.min;
+	r.min = tr.min;
+	r.max.y = tr.max.y;
+	
+	i = 0;
+	while (r.min.x < tr.max.x) {
+		draw(c, c->r, s, nil, p);
+		p.x += 1;
+
+		r.min.x = (int)(((float)(i))*scale) + tr.min.x;
+		r.max.x = (int)(((float)(i+1))*scale) + tr.min.x;
+		draw(t, r, c, nil, ZP);
+		i+=1;
+	}
+	
+	freeimage(c);
+
+	if ((c = allocimage(display, Rect(0, 0, Dx(tr), 1), s->chan, 1, DNofill)) == nil)
+	{
+		werrstr("allocimage: %r");
+		freeimage(t);
+		return -1;
+	}
+
+	if (Dy(tr) > Dy(sr)) {
+		scale = ((float)Dy(tr))/((float)Dy(sr));
+	} else {
+		scale = ((float)Dy(sr))/((float)Dy(tr));
+	}
+
+	p = dr.min;
+	r.min = tr.min;
+	r.max.x = tr.max.x;
+	r.max.y = r.min.y + MAX(1.0, scale);
+
+	i = 0;
+	while (r.min.y < dr.max.y) {
+		draw(c, c->r, t, nil, p);
+		p.y += 1;
+		
+		// Move the draw rectangle for the temporary image scale
+		// rectangles to the right
+		r.min.y = (int)(((float)(i))*scale) + dr.min.x;
+		r.max.y = (int)(((float)(i+1))*scale) + dr.min.x;
+		draw(d, r, c, nil, ZP);
+		i+=1;
+	}
+
+	freeimage(t);
+	freeimage(c);
+	
+	return 1;
+}
+
 static unsigned int
 hsv2rgb(float h, float s, float v)
 {
@@ -87,40 +189,52 @@
 }
 
 static void
-updatecircle(void)
+initgradient(void)
 {
-	float t, i, l, s, u, g, ct, st;
-	Point c, e, k;
-	int w;
-	uint h;
+	if (Gradient != nil) {
+		freeimage(Gradient);
+	}
 
-	if (Circle != nil) {
-		freeimage(Circle);
+	if (RawGradient != nil) {
+		free(RawGradient);
 	}
-	Circle = allocimage(display, RECTANGLE(Dx(screen->r), Dy(screen->r)), RGBA32, 1, BACKGROUNDCOLOR);
-	if (Circle == nil)
-		sysfatal("initcanvas: %r");
-	if (RawCircle != nil) {
-		free(RawCircle);
+	
+	Gradient = allocimage(display, RECTANGLE(INTERNAL_WIDTH, INTERNAL_HEIGHT), RGBA32, 1, DTransparent);
+	if(Gradient == nil) {
+		sysfatal("initgradient: %r");
 	}
-	CircleBPL = bytesperline(Circle->r, Circle->depth);
-	RawCircleSize = CircleBPL * Dy(Circle->r);
-	RawCircle = malloc(RawCircleSize);
-	unloadimage(Circle, Circle->r, (uchar *)RawCircle, RawCircleSize);
 
-	c.x = Dx(Circle->r)/2;
-	c.y = Dy(Circle->r)/2;
+	RawGradientSize = bytesperline(Gradient->r, Gradient->depth) * Dy(Gradient->r);
+	RawGradient = calloc(RawGradientSize, 1);
+	if (RawGradient == nil) {
+		sysfatal("calloc: out of memory");
+	}
+}
 
-	l = MIN(Dx(screen->r), Dy(screen->r));
+static void
+setgradienthue(void)
+{
+	float t, i, l, s, u, ct, st;
+	Point c, e;
+	int rc, dx, dy;
+
+	dx = Dx(Gradient->r);
+	dy = Dy(Gradient->r);
+	c.x = dx/2;
+	c.y = dy/2;
+
+	l = MIN(dx, dy);
 	l *= RADIUS/2.0;
 	
 	i = 1/(l*2);
 	for (t = 0.0; t < CIRCLEDIAMETER; t += i) {
 		u = t/CIRCLEDIAMETER;
+		ct = cos(t + CIRCLESHIFT);
+		st = sin(t + CIRCLESHIFT);
 		for (s = 0; s < l; s += 0.1) {
-			e.x = c.x + s * cos(t + CIRCLESHIFT);
-			e.y = c.y + s * sin(t + CIRCLESHIFT);
-			RawCircle[Dx(Circle->r) * e.y + e.x] = hsv2rgb(
+			e.x = c.x + s * ct;
+			e.y = c.y + s * st;
+			RawGradient[dx * e.y + e.x] = hsv2rgb(
 				HueStart + u, 
 				(SaturationStart)+(s/l)*(MAXSATURATION - SaturationStart),
 				Value);
@@ -127,6 +241,43 @@
 		}
 	}
 
+	rc = loadimage(Gradient, Gradient->r, (uchar *)RawGradient, RawGradientSize);
+	if (rc < 0) {
+		sysfatal("loadimage: %r");
+	}
+}
+
+static void
+inithuepicker(void)
+{
+	int rc, dx, dy, h;
+	u32int * raw, rawSize;
+	float t, i, s, u, g, st, ct, l;
+	Point c;
+
+	if (HuePicker != nil) {
+		freeimage(HuePicker);
+	}
+	
+	HuePicker = allocimage(display, RECTANGLE(INTERNAL_WIDTH, INTERNAL_HEIGHT), RGBA32, 1, DTransparent);
+	if(HuePicker == nil) {
+		sysfatal("inithuepicker: %r");
+	}
+
+	rawSize = bytesperline(HuePicker->r, HuePicker->depth) * Dy(HuePicker->r);
+	raw = calloc(rawSize, 1);
+	if (raw == nil) {
+		sysfatal("calloc: out of memory");
+	}
+
+	dx = Dx(HuePicker->r);
+	dy = Dy(HuePicker->r);
+	c.x = dx/2;
+	c.y = dy/2;
+
+	l = MIN(dx, dy);
+	l *= RADIUS/2.0;
+
 	s = l * (1+COLORPICKERPADDING);
 	u = s + (l*COLORPICKERRADIUS);
 	i = 1/(u*2);
@@ -133,35 +284,30 @@
 	for (t = .0; t < 2*PI; t+=i) {
 		ct = cos(t);
 		st = sin(t);
-		k.x = c.x + s * ct;
-		k.y = c.y + s * st;
-		e.x = c.x + u * ct;
-		e.y = c.y + u * st;
-
-		if (e.x < k.x) {
-			w = e.x;
-			e.x = k.x;
-			k.x = w;
-		}
 		
 		h = hsv2rgb(t, 1.0, 1.0);
 		for (g = s; g < u; g++) {
-				RawCircle[Dx(Circle->r) * (c.y + ((int)(g * st))) + (c.x + ((int)(g * ct)))] = h;
+				raw[dx * (c.y + ((int)(g * st))) + (c.x + ((int)(g * ct)))] = h;
 		}
 	}
 
-	loadimage(Circle, Circle->r, (uchar *)RawCircle, RawCircleSize);
+	rc = loadimage(HuePicker, HuePicker->r, (uchar *)raw, rawSize);
+	if (rc < 0) {
+		sysfatal("loadimage: %r");
+	}
+
+	if (raw != nil) {
+		free(raw);
+	}
 }
 
 static void
 drawcanvas(void)
 {
-	if (UpdateCircle) {
-		updatecircle();
-		UpdateCircle = 0;
-	}
+	print("VirtualWindow: %R\n", VirtualWindow->r);
+	print("screen: %R\n", screen->r);
 	draw(screen, screen->r, Background, nil, ZP);
-	draw(screen, screen->r, Circle, nil, ZP);
+	draw(screen, screen->r, VirtualWindow, nil, ZP);
 }
 
 void
@@ -178,7 +324,22 @@
 static void
 initcanvas(void)
 {
-	UpdateCircle = 1;
+	int rc;
+
+	if (VirtualWindow != nil) {
+		freeimage(VirtualWindow);
+	}
+
+	VirtualWindow = allocimage(display, screen->r, RGBA32, 1, DTransparent);
+	if (VirtualWindow == nil) {
+		sysfatal("initcanvas: %r");
+	}
+
+	rc = resizeimage(VirtualWindow, HuePicker);
+	if (rc < 0) {
+		sysfatal("resizeimage: %r");
+	}
+
 	setbackground(BACKGROUNDCOLOR);
 	drawcanvas();
 }
@@ -185,7 +346,7 @@
 
 void
 eresized(int)
-{	
+{
 	if(getwindow(display, Refnone) < 0)
 		sysfatal("getwindow: %r");
 	initcanvas();
@@ -201,6 +362,11 @@
 	
 	if (initdraw(nil, nil, "pill") < 0)
 		sysfatal("initdraw: %r\n");
+
+	inithuepicker();
+	initgradient();
+	setgradienthue();
+
 	einit(Emouse | Ekeyboard);
 	initcanvas();
 	for (;RunApp;) {
--