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;) {--
⑨