summary refs log tree commit diff
path: root/src/PackedCol.c
diff options
context:
space:
mode:
authorWlodekM <[email protected]>2024-06-16 10:35:45 +0300
committerWlodekM <[email protected]>2024-06-16 10:35:45 +0300
commitabef6da56913f1c55528103e60a50451a39628b1 (patch)
treeb3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/PackedCol.c
initial commit
Diffstat (limited to 'src/PackedCol.c')
-rw-r--r--src/PackedCol.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/PackedCol.c b/src/PackedCol.c
new file mode 100644
index 0000000..465f480
--- /dev/null
+++ b/src/PackedCol.c
@@ -0,0 +1,95 @@
+#include "PackedCol.h"
+#include "String.h"
+#include "ExtMath.h"
+
+PackedCol PackedCol_Scale(PackedCol a, float t) {
+	cc_uint8 R = (cc_uint8)(PackedCol_R(a) * t);
+	cc_uint8 G = (cc_uint8)(PackedCol_G(a) * t);
+	cc_uint8 B = (cc_uint8)(PackedCol_B(a) * t);
+	return (a & PACKEDCOL_A_MASK) | PackedCol_R_Bits(R) | PackedCol_G_Bits(G) | PackedCol_B_Bits(B);
+}
+
+PackedCol PackedCol_Lerp(PackedCol a, PackedCol b, float t) {
+	cc_uint8 R = (cc_uint8)Math_Lerp(PackedCol_R(a), PackedCol_R(b), t);
+	cc_uint8 G = (cc_uint8)Math_Lerp(PackedCol_G(a), PackedCol_G(b), t);
+	cc_uint8 B = (cc_uint8)Math_Lerp(PackedCol_B(a), PackedCol_B(b), t);
+	return (a & PACKEDCOL_A_MASK) | PackedCol_R_Bits(R) | PackedCol_G_Bits(G) | PackedCol_B_Bits(B);
+}
+
+PackedCol PackedCol_Tint(PackedCol a, PackedCol b) {
+	cc_uint32 R = PackedCol_R(a) * PackedCol_R(b) / 255;
+	cc_uint32 G = PackedCol_G(a) * PackedCol_G(b) / 255;
+	cc_uint32 B = PackedCol_B(a) * PackedCol_B(b) / 255;
+	/* TODO: don't shift when multiplying */
+	return (a & PACKEDCOL_A_MASK) | (R << PACKEDCOL_R_SHIFT) | (G << PACKEDCOL_G_SHIFT) | (B << PACKEDCOL_B_SHIFT);
+}
+
+PackedCol PackedCol_ScreenBlend(PackedCol a, PackedCol b) {
+	PackedCol finalColor, aInverted, bInverted;
+	cc_uint8 R, G, B;
+	/* With Screen blend mode, the values of the pixels in the two layers are inverted, multiplied, and then inverted again. */
+	R = 255 - PackedCol_R(a);
+	G = 255 - PackedCol_G(a);
+	B = 255 - PackedCol_B(a);
+	aInverted = PackedCol_Make(R, G, B, 255);
+
+	R = 255 - PackedCol_R(b);
+	G = 255 - PackedCol_G(b);
+	B = 255 - PackedCol_B(b);
+	bInverted = PackedCol_Make(R, G, B, 255);
+
+	finalColor = PackedCol_Tint(aInverted, bInverted);
+	R = 255 - PackedCol_R(finalColor);
+	G = 255 - PackedCol_G(finalColor);
+	B = 255 - PackedCol_B(finalColor);
+	return PackedCol_Make(R, G, B, 255);
+}
+
+void PackedCol_GetShaded(PackedCol normal, PackedCol* xSide, PackedCol* zSide, PackedCol* yMin) {
+	*xSide = PackedCol_Scale(normal, PACKEDCOL_SHADE_X);
+	*zSide = PackedCol_Scale(normal, PACKEDCOL_SHADE_Z);
+	*yMin  = PackedCol_Scale(normal, PACKEDCOL_SHADE_YMIN);
+}
+
+int PackedCol_DeHex(char hex) {
+	if (hex >= '0' && hex <= '9') {
+		return (hex - '0');
+	} else if (hex >= 'a' && hex <= 'f') {
+		return (hex - 'a') + 10;
+	} else if (hex >= 'A' && hex <= 'F') {
+		return (hex - 'A') + 10;
+	}
+	return -1;
+}
+
+cc_bool PackedCol_Unhex(const char* src, int* dst, int count) {
+	int i;
+	for (i = 0; i < count; i++) {
+		dst[i] = PackedCol_DeHex(src[i]);
+		if (dst[i] == -1) return false;
+	}
+	return true;
+}
+
+void PackedCol_ToHex(cc_string* str, PackedCol value) {
+	String_AppendHex(str, PackedCol_R(value));
+	String_AppendHex(str, PackedCol_G(value));
+	String_AppendHex(str, PackedCol_B(value));
+}
+
+cc_bool PackedCol_TryParseHex(const cc_string* str, cc_uint8* rgb) {
+	int bits[6];
+	char* buffer = str->buffer;
+
+	/* accept XXYYZZ or #XXYYZZ forms */
+	if (str->length < 6) return false;
+	if (str->length > 6 && (str->buffer[0] != '#' || str->length > 7)) return false;
+
+	if (buffer[0] == '#') buffer++;
+	if (!PackedCol_Unhex(buffer, bits, 6)) return false;
+
+	rgb[0] = (cc_uint8)((bits[0] << 4) | bits[1]);
+	rgb[1] = (cc_uint8)((bits[2] << 4) | bits[3]);
+	rgb[2] = (cc_uint8)((bits[4] << 4) | bits[5]);
+	return true;
+}