shithub: slug

Download patch

ref: c3b6c54fe0c7ad567a5e6843c7339275e88d49fe
parent: d4e9ed1e23f08ffc95abc4143c3af6713f67bf69
author: phil9 <telephil9@gmail.com>
date: Thu Dec 1 14:38:55 EST 2022

implement HSV color mode and add colorMode() function

	it is now possible to specify colors in HSV format by first calling `colorMode(HSV)`
	The two constants RGB and HSV are used to switch between color modes.

--- a/a.h
+++ b/a.h
@@ -15,7 +15,7 @@
 void	initstate(lua_State*);
 void	registerapi(lua_State*);
 
-Image*	color(int, int, int);
+Image*	color(int, int, int, int);
 
 extern int		drawing;
 extern Image	*canvas;
--- a/api.c
+++ b/api.c
@@ -1,8 +1,15 @@
 #include "a.h"
 
+enum
+{
+	Crgb,
+	Chsv,
+};
+
 Image	*canvas;
 int		width;
 int		height;
+int		colormode;
 int		nostroke;
 int		strokecap;
 Image	*stroke;
@@ -20,6 +27,7 @@
 	height = 500;
 	r = Rect(0, 0, width, height);
 	canvas = allocimage(display, r, screen->chan, 0, DWhite);
+	colormode = Crgb;
 	nostroke = 0;
 	strokecap = Endsquare;
 	stroke = display->black;
@@ -63,22 +71,35 @@
 
 	c = lua_gettop(L);
 	if(c == 1){
-		r = luaL_checkinteger(L, 1);
-		g = r;
-		b = r;
+		g = luaL_checkinteger(L, 1);
+		i = color(g, g, g, 0);
 	}else if(c == 3){
 		r = luaL_checkinteger(L, 1);
 		g = luaL_checkinteger(L, 2);
 		b = luaL_checkinteger(L, 3);
+		i = color(r, g, b, colormode == Chsv);
 	}else{
 		fprint(2, "invalid color request\n");
 		return nil;
 	}
-	i = color(r, g, b);
 	return i;
 }
 
 int
+ccolormode(lua_State *L)
+{
+	int n;
+
+	n = luaL_checkinteger(L, 1);
+	if(n != Crgb && n != Chsv){
+		fprint(2, "error: invalid color mode\n");
+		return LUA_ERRRUN;
+	}
+	colormode = n;
+	return LUA_OK;
+}
+
+int
 cbackground(lua_State *L)
 {
 	Image *i;
@@ -354,10 +375,13 @@
 void
 registerapi(lua_State *L)
 {
+	lset(L, "RGB", Crgb);
+	lset(L, "HSV", Chsv);
 	lset(L, "SQUARE", Endsquare);
 	lset(L, "ROUND", Enddisc);
 
 	registerfunc(L, "size", csize);
+	registerfunc(L, "colorMode", ccolormode);
 	registerfunc(L, "background", cbackground);
 	registerfunc(L, "noStroke", cnostroke);
 	registerfunc(L, "strokeCap", cstrokecap);
--- a/color.c
+++ b/color.c
@@ -22,13 +22,79 @@
 	return i;
 }
 
+void
+hsvtorgb(int h, int s, int v, int *r, int *g, int *b)
+{
+	double dh, ds, dv, hh, p, q, t, ff;
+	long i;
+
+	dh = h;
+	ds = s/100.0;
+	dv = v/100.0;
+	if(ds <= 0.0){
+		*r = v;
+		*g = v;
+		*b = v;
+	}
+	hh = dh;
+	if(hh >= 360.0)
+		hh = 0.0;
+	hh /= 60.0;
+	i = (long)hh;
+	ff = hh - i;
+	p = dv * (1.0 - ds);
+	q = dv * (1.0 - (ds * ff));
+	t = dv * (1.0 - (ds * (1.0 - ff)));
+
+	switch(i) {
+		case 0:
+			*r = 255 * dv;
+			*g = 255 * t;
+			*b = 255 * p;
+			break;
+		case 1:
+			*r = 255 * q;
+			*g = 255 * dv;
+			*b = 255 * p;
+			break;
+		case 2:
+			*r = 255 * p;
+			*g = 255 * dv;
+			*b = 255 * t;
+			break;
+		case 3:
+			*r = 255 * p;
+			*g = 255 * q;
+			*b = 255 * dv;
+			break;
+		case 4:
+			*r = 255 * t;
+			*g = 255 * p;
+			*b = 255 * dv;
+			break;
+		case 5:
+		default:
+			*r = 255 * dv;
+			*g = 255 * p;
+			*b = 255 * q;
+			break;
+	}
+}
+
 Image*
-color(int r, int g, int b)
+color(int x, int y, int z, int hsv)
 {
 	ulong n;
 	Image *c;
-	int i;
+	int i, r, g, b;
 
+	if(hsv)
+		hsvtorgb(x, y, z, &r, &g, &b);
+	else{
+		r = x;
+		g = y;
+		b = z;
+	}
 	c = nil;
 	n = (r << 24) | (g << 16) | (b << 8) | 0xFF;
 	for(i = 0; i < nelem(cache); i++){