225 lines
4.5 KiB
D

module arsd.color;
char toHex(int a) {
if(a < 10)
return cast(char) (a + '0');
else
return cast(char) (a - 10 + 'a');
}
struct Color {
int r, g, b, a;
this(int r, int g, int b, int a = 255) {
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
void toTempString(char[] data) {
data[0] = '#';
data[1] = toHex(r >> 4);
data[2] = toHex(r & 0x0f);
data[3] = toHex(g >> 4);
data[4] = toHex(g & 0x0f);
data[5] = toHex(b >> 4);
data[6] = toHex(b & 0x0f);
}
static Color fromHsl(double h, double s, double l, double a = 255) {
h = h % 360;
double C = (1 - absInternal(2 * l - 1)) * s;
double hPrime = h / 60;
double X = C * (1 - absInternal(hPrime % 2 - 1));
double r, g, b;
if(h is double.nan)
r = g = b = 0;
else if (hPrime >= 0 && hPrime < 1) {
r = C;
g = X;
b = 0;
} else if (hPrime >= 1 && hPrime < 2) {
r = X;
g = C;
b = 0;
} else if (hPrime >= 2 && hPrime < 3) {
r = 0;
g = C;
b = X;
} else if (hPrime >= 3 && hPrime < 4) {
r = 0;
g = X;
b = C;
} else if (hPrime >= 4 && hPrime < 5) {
r = X;
g = 0;
b = C;
} else if (hPrime >= 5 && hPrime < 6) {
r = C;
g = 0;
b = X;
}
double m = l - C / 2;
r += m;
g += m;
b += m;
return Color(
cast(int)(r * 255),
cast(int)(g * 255),
cast(int)(b * 255),
cast(int)(a));
}
static immutable Color white = Color(255, 255, 255, 255);
static immutable Color black = Color(0, 0, 0, 255);
static immutable Color red = Color(255, 0, 0, 255);
static immutable Color blue = Color(0, 0, 255, 255);
static immutable Color green = Color(0, 255, 0, 255);
static immutable Color yellow = Color(255, 255, 0, 255);
static immutable Color teal = Color(0, 255, 255, 255);
static immutable Color purple = Color(255, 0, 255, 255);
static immutable Color gray = Color(127, 127, 127, 255);
static immutable Color transparent = Color(0, 0, 0, 0);
}
struct Point {
int x;
int y;
pure const nothrow @safe:
Point opBinary(string op)(in Point rhs) @nogc {
return Point(mixin("x" ~ op ~ "rhs.x"), mixin("y" ~ op ~ "rhs.y"));
}
Point opBinary(string op)(int rhs) @nogc {
return Point(mixin("x" ~ op ~ "rhs"), mixin("y" ~ op ~ "rhs"));
}
}
struct Size {
int width;
int height;
}
nothrow @safe @nogc pure
double absInternal(double a) { return a < 0 ? -a : a; }
struct Rectangle {
int left; ///
int top; ///
int right; ///
int bottom; ///
pure const nothrow @safe @nogc:
///
this(int left, int top, int right, int bottom) {
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
///
this(in Point upperLeft, in Point lowerRight) {
this(upperLeft.x, upperLeft.y, lowerRight.x, lowerRight.y);
}
///
this(in Point upperLeft, in Size size) {
this(upperLeft.x, upperLeft.y, upperLeft.x + size.width, upperLeft.y + size.height);
}
///
@property Point upperLeft() {
return Point(left, top);
}
///
@property Point upperRight() {
return Point(right, top);
}
///
@property Point lowerLeft() {
return Point(left, bottom);
}
///
@property Point lowerRight() {
return Point(right, bottom);
}
///
@property Point center() {
return Point((right + left) / 2, (bottom + top) / 2);
}
///
@property Size size() {
return Size(width, height);
}
///
@property int width() {
return right - left;
}
///
@property int height() {
return bottom - top;
}
/// Returns true if this rectangle entirely contains the other
bool contains(in Rectangle r) {
return contains(r.upperLeft) && contains(r.lowerRight);
}
/// ditto
bool contains(in Point p) {
return (p.x >= left && p.x < right && p.y >= top && p.y < bottom);
}
/// Returns true of the two rectangles at any point overlap
bool overlaps(in Rectangle r) {
// the -1 in here are because right and top are exclusive
return !((right-1) < r.left || (r.right-1) < left || (bottom-1) < r.top || (r.bottom-1) < top);
}
/++
Returns a Rectangle representing the intersection of this and the other given one.
History:
Added July 1, 2021
+/
Rectangle intersectionOf(in Rectangle r) {
auto tmp = Rectangle(max(left, r.left), max(top, r.top), min(right, r.right), min(bottom, r.bottom));
if(tmp.left >= tmp.right || tmp.top >= tmp.bottom)
tmp = Rectangle.init;
return tmp;
}
}
private int max(int a, int b) @nogc nothrow pure @safe {
return a >= b ? a : b;
}
private int min(int a, int b) @nogc nothrow pure @safe {
return a <= b ? a : b;
}
enum arsd_jsvar_compatible = "arsd_jsvar_compatible";
class MemoryImage {}