Merge pull request #607 from UnknownShadow200/BitmapColRewrite

Bitmap col rewrite
This commit is contained in:
UnknownShadow200 2019-10-10 10:49:48 +11:00 committed by GitHub
commit 5513d49b85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 245 additions and 216 deletions

View File

@ -54,7 +54,6 @@ void Bitmap_Scale(Bitmap* dst, Bitmap* src, int srcX, int srcY, int srcWidth, in
*#########################################################################################################################*/
#define PNG_SIG_SIZE 8
#define PNG_IHDR_SIZE 13
#define PNG_RGB_MASK 0xFFFFFFUL
#define PNG_PALETTE 256
#define PNG_FourCC(a, b, c, d) (((cc_uint32)a << 24) | ((cc_uint32)b << 16) | ((cc_uint32)c << 8) | (cc_uint32)d)
@ -127,7 +126,7 @@ static void Png_Reconstruct(cc_uint8 type, cc_uint8 bytesPerPixel, cc_uint8* lin
}
}
#define Bitmap_Set(dst, r,g,b,a) dst.B = b; dst.G = g; dst.R = r; dst.A = a;
#define Bitmap_Set(dst, r,g,b,a) dst = BitmapCol_Make(r, g, b, a);
#define PNG_Do_Grayscale(dstI, src, scale) rgb = (src) * scale; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255);
#define PNG_Do_Grayscale_8(dstI, srcI) rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255);
@ -307,14 +306,15 @@ static Png_RowExpander Png_GetExpander(cc_uint8 col, cc_uint8 bitsPerSample) {
return NULL;
}
static void Png_ComputeTransparency(Bitmap* bmp, BitmapCol col) {
cc_uint32 trnsRGB = col.B | (col.G << 8) | (col.R << 16); /* TODO: Remove this!! */
/* Sets alpha to 0 for any pixels in the bitmap whose RGB is same as col */
static void ComputeTransparency(Bitmap* bmp, BitmapCol col) {
BitmapCol trnsRGB = col & BITMAPCOL_RGB_MASK;
int x, y, width = bmp->Width, height = bmp->Height;
for (y = 0; y < height; y++) {
cc_uint32* row = Bitmap_RawRow(bmp, y);
BitmapCol* row = Bitmap_GetRow(bmp, y);
for (x = 0; x < width; x++) {
cc_uint32 rgb = row[x] & PNG_RGB_MASK;
BitmapCol rgb = row[x] & BITMAPCOL_RGB_MASK;
row[x] = (rgb == trnsRGB) ? trnsRGB : row[x];
}
}
@ -337,8 +337,7 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
cc_uint32 scanlineSize, scanlineBytes;
/* palette data */
BitmapCol black = BITMAPCOL_CONST(0, 0, 0, 255);
BitmapCol transparentCol;
BitmapCol trnsCol;
BitmapCol palette[PNG_PALETTE];
cc_uint32 i;
@ -360,8 +359,8 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res;
if (!Png_Detect(tmp, PNG_SIG_SIZE)) return PNG_ERR_INVALID_SIG;
transparentCol = black;
for (i = 0; i < PNG_PALETTE; i++) { palette[i] = black; }
trnsCol = BITMAPCOL_BLACK;
for (i = 0; i < PNG_PALETTE; i++) { palette[i] = BITMAPCOL_BLACK; }
Inflate_MakeStream(&compStream, &inflate, stream);
ZLibHeader_Init(&zlibHeader);
@ -411,9 +410,10 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res;
for (i = 0; i < dataSize; i += 3) {
palette[i / 3].R = tmp[i];
palette[i / 3].G = tmp[i + 1];
palette[i / 3].B = tmp[i + 2];
palette[i / 3] &= BITMAPCOL_A_MASK; /* set RGB to 0 */
palette[i / 3] |= tmp[i ] << BITMAPCOL_R_SHIFT;
palette[i / 3] |= tmp[i + 1] << BITMAPCOL_G_SHIFT;
palette[i / 3] |= tmp[i + 2] << BITMAPCOL_B_SHIFT;
}
} break;
@ -424,8 +424,7 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res;
/* RGB is 16 bits big endian, ignore least significant 8 bits */
transparentCol.R = tmp[0]; transparentCol.G = tmp[0];
transparentCol.B = tmp[0]; transparentCol.A = 0;
trnsCol = BitmapCol_Make(tmp[0], tmp[0], tmp[0], 0);
} else if (col == PNG_COL_INDEXED) {
if (dataSize > PNG_PALETTE) return PNG_ERR_TRANS_COUNT;
res = Stream_Read(stream, tmp, dataSize);
@ -433,7 +432,8 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
/* set alpha component of palette */
for (i = 0; i < dataSize; i++) {
palette[i].A = tmp[i];
palette[i] &= BITMAPCOL_RGB_MASK; /* set A to 0 */
palette[i] |= tmp[i] << PACKEDCOL_A_SHIFT;
}
} else if (col == PNG_COL_RGB) {
if (dataSize != 6) return PNG_ERR_TRANS_COUNT;
@ -441,8 +441,7 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res;
/* R,G,B is 16 bits big endian, ignore least significant 8 bits */
transparentCol.R = tmp[0]; transparentCol.G = tmp[2];
transparentCol.B = tmp[4]; transparentCol.A = 0;
trnsCol = BitmapCol_Make(tmp[0], tmp[2], tmp[4], 0);
} else {
return PNG_ERR_TRANS_INVALID;
}
@ -499,7 +498,7 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
case PNG_FourCC('I','E','N','D'): {
if (dataSize) return PNG_ERR_INVALID_END_SIZE;
if (!transparentCol.A) Png_ComputeTransparency(bmp, transparentCol);
if (!BitmapCol_A(trnsCol)) ComputeTransparency(bmp, trnsCol);
return bmp->Scan0 ? 0 : PNG_ERR_NO_DATA;
} break;
@ -565,14 +564,19 @@ static void Png_Filter(cc_uint8 filter, const cc_uint8* cur, const cc_uint8* pri
static void Png_MakeRow(const BitmapCol* src, cc_uint8* dst, int lineLen, bool alpha) {
cc_uint8* end = dst + lineLen;
BitmapCol col; /* if we use *src, register gets reloaded each time */
if (alpha) {
for (; dst < end; src++, dst += 4) {
dst[0] = src->R; dst[1] = src->G; dst[2] = src->B; dst[3] = src->A;
col = *src;
dst[0] = BitmapCol_R(col); dst[1] = BitmapCol_G(col);
dst[2] = BitmapCol_B(col); dst[3] = BitmapCol_A(col);
}
} else {
for (; dst < end; src++, dst += 3) {
dst[0] = src->R; dst[1] = src->G; dst[2] = src->B;
col = *src;
dst[0] = BitmapCol_R(col); dst[1] = BitmapCol_G(col);
dst[2] = BitmapCol_B(col);
}
}
}

View File

@ -6,37 +6,52 @@
*/
struct Stream;
/* Represents an ARGB colour, suitable for native graphics API texture pixels. */
typedef union BitmapCol_ {
/* Represents a packed 32 bit RGBA colour, suitable for native graphics API texture pixels. */
typedef cc_uint32 BitmapCol;
#if defined CC_BUILD_WEB || defined CC_BUILD_ANDROID
struct { cc_uint8 R, G, B, A; };
#define BITMAPCOL_R_SHIFT 0
#define BITMAPCOL_G_SHIFT 8
#define BITMAPCOL_B_SHIFT 16
#define BITMAPCOL_A_SHIFT 24
#elif defined CC_BIG_ENDIAN
#define BITMAPCOL_A_SHIFT 0
#define BITMAPCOL_R_SHIFT 8
#define BITMAPCOL_G_SHIFT 16
#define BITMAPCOL_B_SHIFT 24
#else
struct { cc_uint8 B, G, R, A; };
#define BITMAPCOL_B_SHIFT 0
#define BITMAPCOL_G_SHIFT 8
#define BITMAPCOL_R_SHIFT 16
#define BITMAPCOL_A_SHIFT 24
#endif
cc_uint32 _raw;
} BitmapCol;
/* Whether components of two colours are all equal. */
#define BitmapCol_Equals(a,b) ((a)._raw == (b)._raw)
#define PackedCol_ARGB(r, g, b, a) (((cc_uint32)(r) << 16) | ((cc_uint32)(g) << 8) | ((cc_uint32)(b)) | ((cc_uint32)(a) << 24))
#define BITMAPCOL_R_MASK (0xFFU << BITMAPCOL_R_SHIFT)
#define BITMAPCOL_G_MASK (0xFFU << BITMAPCOL_G_SHIFT)
#define BITMAPCOL_B_MASK (0xFFU << BITMAPCOL_B_SHIFT)
#define BITMAPCOL_A_MASK (0xFFU << BITMAPCOL_A_SHIFT)
#define BitmapCol_R(col) ((cc_uint8)(col >> BITMAPCOL_R_SHIFT))
#define BitmapCol_G(col) ((cc_uint8)(col >> BITMAPCOL_G_SHIFT))
#define BitmapCol_B(col) ((cc_uint8)(col >> BITMAPCOL_B_SHIFT))
#define BitmapCol_A(col) ((cc_uint8)(col >> BITMAPCOL_A_SHIFT))
#define BitmapCol_R_Bits(col) ((cc_uint8)(col) << BITMAPCOL_R_SHIFT)
#define BitmapCol_G_Bits(col) ((cc_uint8)(col) << BITMAPCOL_G_SHIFT)
#define BitmapCol_B_Bits(col) ((cc_uint8)(col) << BITMAPCOL_B_SHIFT)
#define BitmapCol_A_Bits(col) ((cc_uint8)(col) << BITMAPCOL_A_SHIFT)
#define BitmapCol_Make(r, g, b, a) (BitmapCol_R_Bits(r) | BitmapCol_G_Bits(g) | BitmapCol_B_Bits(b) | BitmapCol_A_Bits(a))
#define BITMAPCOL_RGB_MASK (BITMAPCOL_R_MASK | BITMAPCOL_G_MASK | BITMAPCOL_B_MASK)
#define BITMAPCOL_BLACK BitmapCol_Make( 0, 0, 0, 255)
#define BITMAPCOL_WHITE BitmapCol_Make(255, 255, 255, 255)
/* A 2D array of BitmapCol pixels */
typedef struct Bitmap_ { cc_uint8* Scan0; int Width, Height; } Bitmap;
#define PNG_MAX_DIMS 0x8000
#if defined CC_BUILD_WEB || defined CC_BUILD_ANDROID
#define BITMAPCOL_CONST(r, g, b, a) { r, g, b, a }
#else
#define BITMAPCOL_CONST(r, g, b, a) { b, g, r, a }
#endif
/* Returns number of bytes a bitmap consumes. */
#define Bitmap_DataSize(width, height) ((cc_uint32)(width) * (cc_uint32)(height) * 4)
/* Gets the yth row of a bitmap as raw cc_uint32* pointer. */
/* NOTE: You SHOULD not rely on the order of the 4 bytes in the pointer. */
/* Different platforms may have different endian, or different component order. */
#define Bitmap_RawRow(bmp, y) ((cc_uint32*)(bmp)->Scan0 + (y) * (bmp)->Width)
/* Gets the yth row of the given bitmap. */
#define Bitmap_GetRow(bmp, y) ((BitmapCol*)(bmp)->Scan0 + (y) * (bmp)->Width)
/* Gets the pixel at (x,y) in the given bitmap. */

View File

@ -352,7 +352,7 @@ static float Block_GetSpriteBB_MinX(int size, int tileX, int tileY, const Bitmap
for (x = 0; x < size; x++) {
for (y = 0; y < size; y++) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
if (row[x].A) { return (float)x / size; }
if (BitmapCol_A(row[x])) { return (float)x / size; }
}
}
return 1.0f;
@ -365,7 +365,7 @@ static float Block_GetSpriteBB_MinY(int size, int tileX, int tileY, const Bitmap
for (y = size - 1; y >= 0; y--) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
for (x = 0; x < size; x++) {
if (row[x].A) { return 1.0f - (float)(y + 1) / size; }
if (BitmapCol_A(row[x])) { return 1.0f - (float)(y + 1) / size; }
}
}
return 1.0f;
@ -378,7 +378,7 @@ static float Block_GetSpriteBB_MaxX(int size, int tileX, int tileY, const Bitmap
for (x = size - 1; x >= 0; x--) {
for (y = 0; y < size; y++) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
if (row[x].A) { return (float)(x + 1) / size; }
if (BitmapCol_A(row[x])) { return (float)(x + 1) / size; }
}
}
return 0.0f;
@ -391,7 +391,7 @@ static float Block_GetSpriteBB_MaxY(int size, int tileX, int tileY, const Bitmap
for (y = 0; y < size; y++) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
for (x = 0; x < size; x++) {
if (row[x].A) { return 1.0f - (float)y / size; }
if (BitmapCol_A(row[x])) { return 1.0f - (float)y / size; }
}
}
return 0.0f;

View File

@ -30,8 +30,9 @@ typedef unsigned int cc_uintptr;
#define CC_HAS_TYPES
#define CC_HAS_MISC
#elif __GNUC__
/* really old GCC/clang might not have these */
/* really old GCC/clang might not have these defined */
#ifdef __INT8_TYPE__
/* avoid including <stdint.h> because it breaks defining UNICODE in Platform.c with MinGW */
typedef __INT8_TYPE__ cc_int8;
typedef __INT16_TYPE__ cc_int16;
typedef __INT32_TYPE__ cc_int32;
@ -74,7 +75,7 @@ typedef unsigned __INTPTR_TYPE__ cc_uintptr;
#define CC_BIG_ENDIAN
#endif
/* Unrecognised compiler, so just go with sensisble defaults */
/* Unrecognised compiler, so just go with sensible defaults */
#ifndef CC_HAS_TYPES
#include <stdint.h>
typedef int8_t cc_int8;
@ -89,7 +90,7 @@ typedef uint64_t cc_uint64;
typedef uintptr_t cc_uintptr;
#endif
#ifndef CC_HAS_MISC
#define CC_INLINE inline
#define CC_INLINE
#define CC_NOINLINE
#define CC_API
#define CC_VAR

View File

@ -115,7 +115,7 @@ static void Drawer2D_CalculateTextWidths(void) {
/* Iterate through each pixel of the given character, on the current scanline */
for (xx = tileSize - 1; xx >= 0; xx--) {
if (!row[x + xx].A) continue;
if (!BitmapCol_A(row[x + xx])) continue;
/* Check if this is the pixel furthest to the right, for the current character */
tileWidths[i] = max(tileWidths[i], xx + 1);
@ -172,7 +172,7 @@ bool Drawer2D_Clamp(Bitmap* bmp, int* x, int* y, int* width, int* height) {
void Gradient_Noise(Bitmap* bmp, BitmapCol col, int variation,
int x, int y, int width, int height) {
BitmapCol* dst;
int xx, yy, n;
int R, G, B, xx, yy, n;
float noise;
if (!Drawer2D_Clamp(bmp, &x, &y, &width, &height)) return;
@ -184,14 +184,11 @@ void Gradient_Noise(Bitmap* bmp, BitmapCol col, int variation,
n = (n << 13) ^ n;
noise = 1.0f - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f;
n = col.B + (int)(noise * variation);
dst->B = Drawer2D_ClampPixel(n);
n = col.G + (int)(noise * variation);
dst->G = Drawer2D_ClampPixel(n);
n = col.R + (int)(noise * variation);
dst->R = Drawer2D_ClampPixel(n);
R = BitmapCol_R(col) + (int)(noise * variation); Drawer2D_ClampPixel(R);
G = BitmapCol_G(col) + (int)(noise * variation); Drawer2D_ClampPixel(G);
B = BitmapCol_B(col) + (int)(noise * variation); Drawer2D_ClampPixel(B);
dst->A = 255;
*dst = BitmapCol_Make(R, G, B, 255);
}
}
}
@ -202,15 +199,16 @@ void Gradient_Vertical(Bitmap* bmp, BitmapCol a, BitmapCol b,
int xx, yy;
float t;
if (!Drawer2D_Clamp(bmp, &x, &y, &width, &height)) return;
col.A = 255;
for (yy = 0; yy < height; yy++) {
row = Bitmap_GetRow(bmp, y + yy) + x;
t = (float)yy / (height - 1); /* so last row has colour of b */
col.B = (cc_uint8)Math_Lerp(a.B, b.B, t);
col.G = (cc_uint8)Math_Lerp(a.G, b.G, t);
col.R = (cc_uint8)Math_Lerp(a.R, b.R, t);
col = BitmapCol_Make(
Math_Lerp(BitmapCol_R(a), BitmapCol_R(b), t),
Math_Lerp(BitmapCol_G(a), BitmapCol_G(b), t),
Math_Lerp(BitmapCol_B(a), BitmapCol_B(b), t),
255);
for (xx = 0; xx < width; xx++) { row[xx] = col; }
}
@ -219,35 +217,35 @@ void Gradient_Vertical(Bitmap* bmp, BitmapCol a, BitmapCol b,
void Gradient_Blend(Bitmap* bmp, BitmapCol col, int blend,
int x, int y, int width, int height) {
BitmapCol* dst;
int xx, yy, t;
int R, G, B, xx, yy;
if (!Drawer2D_Clamp(bmp, &x, &y, &width, &height)) return;
/* Pre compute the alpha blended source colour */
col.R = (cc_uint8)(col.R * blend / 255);
col.G = (cc_uint8)(col.G * blend / 255);
col.B = (cc_uint8)(col.B * blend / 255);
/* TODO: Avoid shift when multiplying */
col = BitmapCol_Make(
BitmapCol_R(col) * blend / 255,
BitmapCol_G(col) * blend / 255,
BitmapCol_B(col) * blend / 255,
0);
blend = 255 - blend; /* inverse for existing pixels */
t = 0;
for (yy = 0; yy < height; yy++) {
dst = Bitmap_GetRow(bmp, y + yy) + x;
for (xx = 0; xx < width; xx++, dst++) {
t = col.B + (dst->B * blend) / 255;
dst->B = Drawer2D_ClampPixel(t);
t = col.G + (dst->G * blend) / 255;
dst->G = Drawer2D_ClampPixel(t);
t = col.R + (dst->R * blend) / 255;
dst->R = Drawer2D_ClampPixel(t);
/* TODO: Not shift when multiplying */
R = BitmapCol_R(col) + (BitmapCol_R(*dst) * blend) / 255;
G = BitmapCol_G(col) + (BitmapCol_G(*dst) * blend) / 255;
B = BitmapCol_B(col) + (BitmapCol_B(*dst) * blend) / 255;
dst->A = 255;
*dst = BitmapCol_Make(R, G, B, 255);
}
}
}
void Gradient_Tint(Bitmap* bmp, cc_uint8 tintA, cc_uint8 tintB,
int x, int y, int width, int height) {
BitmapCol* row;
BitmapCol* row, col;
cc_uint8 tint;
int xx, yy;
if (!Drawer2D_Clamp(bmp, &x, &y, &width, &height)) return;
@ -257,9 +255,14 @@ void Gradient_Tint(Bitmap* bmp, cc_uint8 tintA, cc_uint8 tintB,
tint = (cc_uint8)Math_Lerp(tintA, tintB, (float)yy / height);
for (xx = 0; xx < width; xx++) {
row[xx].B = (row[xx].B * tint) / 255;
row[xx].G = (row[xx].G * tint) / 255;
row[xx].R = (row[xx].R * tint) / 255;
/* TODO: Not shift when multiplying */
col = BitmapCol_Make(
BitmapCol_R(row[xx]) * tint / 255,
BitmapCol_G(row[xx]) * tint / 255,
BitmapCol_B(row[xx]) * tint / 255,
0);
row[xx] = col | (row[xx] & BITMAPCOL_A_MASK);
}
}
}
@ -278,7 +281,7 @@ void Drawer2D_BmpIndexed(Bitmap* bmp, int x, int y, int size,
for (xx = 0; xx < size; xx++) {
col = palette[*indices++];
if (col._raw == 0) continue; /* transparent pixel */
if (col == 0) continue; /* transparent pixel */
if ((x + xx) < 0 || (x + xx) >= bmp->Width) continue;
row[xx] = col;
}
@ -343,7 +346,7 @@ void Drawer2D_Make2DTexture(struct Texture* tex, Bitmap* bmp, Size2D used) {
bool Drawer2D_ValidColCodeAt(const String* text, int i) {
if (i >= text->length) return false;
return Drawer2D_GetCol(text->buffer[i]).A > 0;
return BitmapCol_A(Drawer2D_GetCol(text->buffer[i])) != 0;
}
bool Drawer2D_IsEmptyText(const String* text) {
@ -373,8 +376,13 @@ char Drawer2D_LastCol(const String* text, int start) {
bool Drawer2D_IsWhiteCol(char c) { return c == '\0' || c == 'f' || c == 'F'; }
/* Divides R/G/B by 4 */
#define SHADOW_MASK ((0x3F << BITMAPCOL_R_SHIFT) | (0x3F << BITMAPCOL_G_SHIFT) | (0x3F << BITMAPCOL_B_SHIFT))
CC_NOINLINE static BitmapCol Drawer2D_ShadowCol(BitmapCol c) {
c.R >>= 2; c.G >>= 2; c.B >>= 2; return c;
/* Initial layout: aaaa_aaaa|rrrr_rrrr|gggg_gggg|bbbb_bbbb */
/* Shift right 2: 00aa_aaaa|aarr_rrrr|rrgg_gggg|ggbb_bbbb */
/* And by 3f3f3f: 0000_0000|00rr_rrrr|00gg_gggg|00bb_bbbb */
/* Or by alpha : aaaa_aaaa|00rr_rrrr|00gg_gggg|00bb_bbbb */
return (c & BITMAPCOL_A_MASK) | ((c >> 2) & SHADOW_MASK);
}
/* TODO: Needs to account for DPI */
@ -433,7 +441,6 @@ void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, Bitmap
}
static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int y, bool shadow) {
BitmapCol black = BITMAPCOL_CONST(0, 0, 0, 255);
BitmapCol col;
String text = args->text;
int i, point = args->font->size, count = 0;
@ -454,7 +461,7 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
col = Drawer2D_Cols['f'];
if (shadow) {
col = Drawer2D_BlackTextShadows ? black : Drawer2D_ShadowCol(col);
col = Drawer2D_BlackTextShadows ? BITMAPCOL_BLACK : Drawer2D_ShadowCol(col);
}
for (i = 0; i < text.length; i++) {
@ -462,7 +469,7 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
if (c == '&' && Drawer2D_ValidColCodeAt(&text, i + 1)) {
col = Drawer2D_GetCol(text.buffer[i + 1]);
if (shadow) {
col = Drawer2D_BlackTextShadows ? black : Drawer2D_ShadowCol(col);
col = Drawer2D_BlackTextShadows ? BITMAPCOL_BLACK : Drawer2D_ShadowCol(col);
}
i++; continue; /* skip over the colour code */
}
@ -497,16 +504,19 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
for (xx = 0; xx < dstWidth; xx++) {
fontX = srcX + xx * srcWidth / dstWidth;
src = srcRow[fontX];
if (!src.A) continue;
if (!BitmapCol_A(src)) continue;
dstX = x + xx;
if ((unsigned)dstX >= (unsigned)bmp->Width) continue;
dst.B = src.B * col.B / 255;
dst.G = src.G * col.G / 255;
dst.R = src.R * col.R / 255;
dst.A = src.A;
dstRow[dstX] = dst;
/* TODO: Transparent text by multiplying by col.A */
/* TODO: Not shift when multiplying */
/* TODO: avoid BitmapCol_A shift */
dstRow[dstX] = BitmapCol_Make(
BitmapCol_R(src) * BitmapCol_R(col) / 255,
BitmapCol_G(src) * BitmapCol_G(col) / 255,
BitmapCol_B(src) * BitmapCol_B(col) / 255,
BitmapCol_A(src));
}
x += dstWidth + xPadding;
}
@ -523,7 +533,7 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
dstWidth = 0;
col = cols[i];
for (; i < count && BitmapCol_Equals(col, cols[i]); i++) {
for (; i < count && col == cols[i]; i++) {
dstWidth += dstWidths[i] + xPadding;
}
Drawer2D_Underline(bmp, x, underlineY, dstWidth, underlineHeight, col);
@ -567,7 +577,7 @@ static int Drawer2D_MeasureBitmapWidth(const struct DrawTextArgs* args) {
}
void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y) {
BitmapCol col, backCol, black = BITMAPCOL_CONST(0, 0, 0, 255);
BitmapCol col, backCol;
String value = args->text;
char colCode, nextCol = 'f';
int i, partWidth;
@ -582,7 +592,7 @@ void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y) {
col = Drawer2D_GetCol(colCode);
if (args->useShadow) {
backCol = Drawer2D_BlackTextShadows ? black : Drawer2D_ShadowCol(col);
backCol = Drawer2D_BlackTextShadows ? BITMAPCOL_BLACK : Drawer2D_ShadowCol(col);
Font_SysTextDraw(args, bmp, x, y, backCol, true);
}
@ -672,18 +682,17 @@ void Drawer2D_DrawClippedText(Bitmap* bmp, struct DrawTextArgs* args, int x, int
*---------------------------------------------------Drawer2D component----------------------------------------------------*
*#########################################################################################################################*/
static void Drawer2D_HexEncodedCol(int i, int hex, cc_uint8 lo, cc_uint8 hi) {
Drawer2D_Cols[i].R = (cc_uint8)(lo * ((hex >> 2) & 1) + hi * (hex >> 3));
Drawer2D_Cols[i].G = (cc_uint8)(lo * ((hex >> 1) & 1) + hi * (hex >> 3));
Drawer2D_Cols[i].B = (cc_uint8)(lo * ((hex >> 0) & 1) + hi * (hex >> 3));
Drawer2D_Cols[i].A = 255;
Drawer2D_Cols[i] = BitmapCol_Make(
lo * ((hex >> 2) & 1) + hi * (hex >> 3),
lo * ((hex >> 1) & 1) + hi * (hex >> 3),
lo * ((hex >> 0) & 1) + hi * (hex >> 3),
255);
}
static void Drawer2D_Reset(void) {
BitmapCol col = BITMAPCOL_CONST(0, 0, 0, 0);
int i;
int i;
for (i = 0; i < DRAWER2D_MAX_COLS; i++) {
Drawer2D_Cols[i] = col;
Drawer2D_Cols[i] = 0;
}
for (i = 0; i <= 9; i++) {
@ -820,6 +829,9 @@ static ReturnCode SysFont_Init(const String* path, struct SysFont* font, FT_Open
FileHandle file;
cc_uint32 size;
ReturnCode res;
#ifdef CC_BUILD_OSX
String filename;
#endif
if ((res = File_Open(&file, path))) return res;
if ((res = File_Length(file, &size))) { File_Close(file); return res; }
@ -845,7 +857,7 @@ static ReturnCode SysFont_Init(const String* path, struct SysFont* font, FT_Open
/* For OSX font suitcase files */
#ifdef CC_BUILD_OSX
String filename = String_NT_Array(font->filename);
String_InitArray_NT(filename, font->filename);
String_Copy(&filename, path);
font->filename[filename.length] = '\0';
args->pathname = font->filename;
@ -1069,7 +1081,7 @@ static int Font_SysTextWidth(struct DrawTextArgs* args) {
static void DrawGrayscaleGlyph(FT_Bitmap* img, Bitmap* bmp, int x, int y, BitmapCol col) {
cc_uint8* src;
BitmapCol* dst;
cc_uint8 intensity, invIntensity;
cc_uint8 I, invI; /* intensity */
int xx, yy;
for (yy = 0; yy < img->rows; yy++) {
@ -1079,13 +1091,17 @@ static void DrawGrayscaleGlyph(FT_Bitmap* img, Bitmap* bmp, int x, int y, Bitmap
for (xx = 0; xx < img->width; xx++, src++, dst++) {
if ((unsigned)(x + xx) >= (unsigned)bmp->Width) continue;
intensity = *src; invIntensity = UInt8_MaxValue - intensity;
I = *src; invI = UInt8_MaxValue - I;
dst->B = ((col.B * intensity) >> 8) + ((dst->B * invIntensity) >> 8);
dst->G = ((col.G * intensity) >> 8) + ((dst->G * invIntensity) >> 8);
dst->R = ((col.R * intensity) >> 8) + ((dst->R * invIntensity) >> 8);
/*dst->A = ((col.A * intensity) >> 8) + ((dst->A * invIntensity) >> 8);*/
dst->A = intensity + ((dst->A * invIntensity) >> 8);
/* TODO: Support transparent text */
/* dst->A = ((col.A * intensity) >> 8) + ((dst->A * invIntensity) >> 8);*/
/* TODO: Not shift when multiplying */
*dst = BitmapCol_Make(
((BitmapCol_R(col) * I) >> 8) + ((BitmapCol_R(*dst) * invI) >> 8),
((BitmapCol_G(col) * I) >> 8) + ((BitmapCol_G(*dst) * invI) >> 8),
((BitmapCol_B(col) * I) >> 8) + ((BitmapCol_B(*dst) * invI) >> 8),
((BitmapCol_A(*dst) * invI) >> 8)
);
}
}
}
@ -1105,15 +1121,15 @@ static void DrawBlackWhiteGlyph(FT_Bitmap* img, Bitmap* bmp, int x, int y, Bitma
if ((unsigned)(x + xx) >= (unsigned)bmp->Width) continue;
intensity = src[xx >> 3];
/* TODO: transparent text (don't set A to 255) */
if (intensity & (1 << (7 - (xx & 7)))) {
dst->B = col.B; dst->G = col.G; dst->R = col.R;
/*dst->A = col.A*/
dst->A = 255;
*dst = col | BitmapCol_A_Bits(255);
}
}
}
}
static FT_Vector shadow_delta = { 83, -83 };
static int Font_SysTextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, BitmapCol col, bool shadow) {
struct SysFont* font = (struct SysFont*)args->font->handle;
FT_BitmapGlyph* glyphs = font->glyphs;
@ -1131,8 +1147,7 @@ static int Font_SysTextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y
if (shadow) {
glyphs = font->shadow_glyphs;
FT_Vector delta = { 83, -83 };
FT_Set_Transform(face, NULL, &delta);
FT_Set_Transform(face, NULL, &shadow_delta);
}
height = args->font->height;

View File

@ -229,7 +229,7 @@ bool Entity_TouchesAnyWater(struct Entity* e) {
static void Entity_MakeNameTexture(struct Entity* e) {
String colorlessName; char colorlessBuffer[STRING_SIZE];
BitmapCol shadowCol = BITMAPCOL_CONST(80, 80, 80, 255);
BitmapCol shadowCol = BitmapCol_Make(80, 80, 80, 255);
BitmapCol origWhiteCol;
struct DrawTextArgs args;
@ -396,18 +396,16 @@ static void Entity_ClearHat(Bitmap* bmp, cc_uint8 skinType) {
for (y = 0; y < sizeY; y++) {
BitmapCol* row = Bitmap_GetRow(bmp, y) + sizeX;
for (x = 0; x < sizeX; x++) {
if (row[x].A != 255) return;
if (BitmapCol_A(row[x]) != 255) return;
}
}
/* only perform filtering when the entire hat is opaque */
cc_uint32 white = PackedCol_ARGB(255, 255, 255, 255);
cc_uint32 black = PackedCol_ARGB(0, 0, 0, 255);
for (y = 0; y < sizeY; y++) {
cc_uint32* row = Bitmap_RawRow(bmp, y) + sizeX;
BitmapCol* row = Bitmap_GetRow(bmp, y) + sizeX;
for (x = 0; x < sizeX; x++) {
cc_uint32 pixel = row[x];
if (pixel == white || pixel == black) row[x] = 0;
BitmapCol c = row[x];
if (c == BITMAPCOL_WHITE || c == BITMAPCOL_BLACK) row[x] = 0;
}
}
}

View File

@ -586,8 +586,7 @@ static bool ShadowComponent_GetBlocks(struct Entity* e, int x, int y, int z, str
#define sh_half (sh_size / 2)
static void ShadowComponent_MakeTex(void) {
cc_uint8 pixels[Bitmap_DataSize(sh_size, sh_size)];
BitmapCol inPix = BITMAPCOL_CONST(0, 0, 0, 200);
BitmapCol outPix = BITMAPCOL_CONST(0, 0, 0, 0);
BitmapCol col = BitmapCol_Make(0, 0, 0, 200);
Bitmap bmp;
cc_uint32 x, y;
@ -599,7 +598,7 @@ static void ShadowComponent_MakeTex(void) {
double dist =
(sh_half - (x + 0.5)) * (sh_half - (x + 0.5)) +
(sh_half - (y + 0.5)) * (sh_half - (y + 0.5));
row[x] = dist < sh_half * sh_half ? inPix : outPix;
row[x] = dist < sh_half * sh_half ? col : 0;
}
}
ShadowComponent_ShadowTex = Gfx_CreateTexture(&bmp, false, false);

View File

@ -206,25 +206,25 @@ static BitmapCol AverageCol(BitmapCol p1, BitmapCol p2) {
cc_uint32 a1, a2, aSum;
cc_uint32 b1, g1, r1;
cc_uint32 b2, g2, r2;
BitmapCol ave;
a1 = p1.A; a2 = p2.A;
a1 = BitmapCol_A(p1); a2 = BitmapCol_A(p2);
aSum = (a1 + a2);
aSum = aSum > 0 ? aSum : 1; /* avoid divide by 0 below */
/* Convert RGB to pre-multiplied form */
b1 = p1.B * a1; g1 = p1.G * a1; r1 = p1.R * a1;
b2 = p2.B * a2; g2 = p2.G * a2; r2 = p2.R * a2;
/* TODO: Don't shift when multiplying/averaging */
r1 = BitmapCol_R(p1) * a1; g1 = BitmapCol_G(p1) * a1; b1 = BitmapCol_B(p1) * a1;
r2 = BitmapCol_R(p2) * a2; g2 = BitmapCol_G(p2) * a2; b2 = BitmapCol_B(p2) * a2;
/* https://stackoverflow.com/a/347376 */
/* We need to convert RGB back from the pre-multiplied average into normal form */
/* ((r1 + r2) / 2) / ((a1 + a2) / 2) */
/* but we just cancel out the / 2 */
ave.B = (b1 + b2) / aSum;
ave.G = (g1 + g2) / aSum;
ave.R = (r1 + r2) / aSum;
ave.A = aSum >> 1;
return ave;
return BitmapCol_Make(
(r1 + r2) / aSum,
(g1 + g2) / aSum,
(b1 + b2) / aSum,
aSum >> 1);
}
/* Generates the next mipmaps level bitmap for the given bitmap. */

View File

@ -330,15 +330,15 @@ CC_NOINLINE static void ColoursScreen_Update(struct ColoursScreen* s, int i, Bit
String tmp; char tmpBuffer[3];
String_InitArray(tmp, tmpBuffer);
String_AppendInt(&tmp, col.R);
String_AppendInt(&tmp, BitmapCol_R(col));
LInput_SetText(&s->iptColours[i + 0], &tmp);
tmp.length = 0;
String_AppendInt(&tmp, col.G);
String_AppendInt(&tmp, BitmapCol_G(col));
LInput_SetText(&s->iptColours[i + 1], &tmp);
tmp.length = 0;
String_AppendInt(&tmp, col.B);
String_AppendInt(&tmp, BitmapCol_B(col));
LInput_SetText(&s->iptColours[i + 2], &tmp);
}
@ -368,7 +368,7 @@ static void ColoursScreen_TextChanged(struct LInput* w) {
if (!Convert_ParseUInt8(&s->iptColours[index + 1].Text, &g)) return;
if (!Convert_ParseUInt8(&s->iptColours[index + 2].Text, &b)) return;
col->R = r; col->G = g; col->B = b;
*col = BitmapCol_Make(r, g, b, 255);
Launcher_SaveSkin();
Launcher_Redraw();
}
@ -952,7 +952,7 @@ static void ResourcesScreen_Next(void* w, int x, int y) {
static void ResourcesScreen_Init(struct LScreen* s_) {
String str; char buffer[STRING_SIZE];
BitmapCol progressCol = BITMAPCOL_CONST(0, 220, 0, 255);
BitmapCol progressCol = BitmapCol_Make(0, 220, 0, 255);
struct ResourcesScreen* s = (struct ResourcesScreen*)s_;
float size;
@ -1001,13 +1001,13 @@ static void ResourcesScreen_Layout(struct LScreen* s_) {
}
CC_NOINLINE static void ResourcesScreen_ResetArea(int x, int y, int width, int height) {
BitmapCol boxCol = BITMAPCOL_CONST(120, 85, 151, 255);
BitmapCol boxCol = BitmapCol_Make(120, 85, 151, 255);
Gradient_Noise(&Launcher_Framebuffer, boxCol, 4, x, y, width, height);
Launcher_MarkDirty(x, y, width, height);
}
static void ResourcesScreen_Draw(struct LScreen* s) {
BitmapCol backCol = BITMAPCOL_CONST(12, 12, 12, 255);
BitmapCol backCol = BitmapCol_Make(12, 12, 12, 255);
int x, y, width, height;
Drawer2D_Clear(&Launcher_Framebuffer, backCol,

View File

@ -50,15 +50,15 @@ void LWidget_Redraw(void* widget) {
*#########################################################################################################################*/
static BitmapCol LButton_Expand(BitmapCol a, int amount) {
int r, g, b;
r = a.R + amount; Math_Clamp(r, 0, 255); a.R = r;
g = a.G + amount; Math_Clamp(g, 0, 255); a.G = g;
b = a.B + amount; Math_Clamp(b, 0, 255); a.B = b;
return a;
r = BitmapCol_R(a) + amount; Math_Clamp(r, 0, 255);
g = BitmapCol_G(a) + amount; Math_Clamp(g, 0, 255);
b = BitmapCol_B(a) + amount; Math_Clamp(b, 0, 255);
return BitmapCol_Make(r, g, b, 255);
}
static void LButton_DrawBackground(struct LButton* w) {
BitmapCol activeCol = BITMAPCOL_CONST(126, 136, 191, 255);
BitmapCol inactiveCol = BITMAPCOL_CONST(111, 111, 111, 255);
BitmapCol activeCol = BitmapCol_Make(126, 136, 191, 255);
BitmapCol inactiveCol = BitmapCol_Make(111, 111, 111, 255);
BitmapCol col;
if (Launcher_ClassicBackground) {
@ -75,7 +75,7 @@ static void LButton_DrawBackground(struct LButton* w) {
}
static void LButton_DrawBorder(struct LButton* w) {
BitmapCol black = BITMAPCOL_CONST(0, 0, 0, 255);
BitmapCol black = BitmapCol_Make(0, 0, 0, 255);
BitmapCol backCol = Launcher_ClassicBackground ? black : Launcher_ButtonBorderCol;
Drawer2D_Clear(&Launcher_Framebuffer, backCol,
@ -93,8 +93,8 @@ static void LButton_DrawBorder(struct LButton* w) {
}
static void LButton_DrawHighlight(struct LButton* w) {
BitmapCol activeCol = BITMAPCOL_CONST(189, 198, 255, 255);
BitmapCol inactiveCol = BITMAPCOL_CONST(168, 168, 168, 255);
BitmapCol activeCol = BitmapCol_Make(189, 198, 255, 255);
BitmapCol inactiveCol = BitmapCol_Make(168, 168, 168, 255);
BitmapCol highlightCol;
if (Launcher_ClassicBackground) {
@ -176,7 +176,7 @@ CC_NOINLINE static void LInput_GetText(struct LInput* w, String* text) {
}
static void LInput_DrawOuterBorder(struct LInput* w) {
BitmapCol col = BITMAPCOL_CONST(97, 81, 110, 255);
BitmapCol col = BitmapCol_Make(97, 81, 110, 255);
if (w->Selected) {
Drawer2D_Clear(&Launcher_Framebuffer, col,
@ -204,7 +204,7 @@ static void LInput_DrawOuterBorder(struct LInput* w) {
}
static void LInput_DrawInnerBorder(struct LInput* w) {
BitmapCol col = BITMAPCOL_CONST(165, 142, 168, 255);
BitmapCol col = BitmapCol_Make(165, 142, 168, 255);
Drawer2D_Clear(&Launcher_Framebuffer, col,
w->X + BORDER, w->Y + BORDER,
@ -221,7 +221,7 @@ static void LInput_DrawInnerBorder(struct LInput* w) {
}
static void LInput_BlendBoxTop(struct LInput* w) {
BitmapCol col = BITMAPCOL_CONST(0, 0, 0, 255);
BitmapCol col = BitmapCol_Make(0, 0, 0, 255);
Gradient_Blend(&Launcher_Framebuffer, col, 75,
w->X + BORDER, w->Y + BORDER,
@ -255,7 +255,6 @@ static void LInput_Draw(void* widget) {
String text; char textBuffer[STRING_SIZE];
struct DrawTextArgs args;
Size2D size;
BitmapCol white = BITMAPCOL_CONST(255, 255, 255, 255);
String_InitArray(text, textBuffer);
LInput_GetText(w, &text);
@ -267,7 +266,7 @@ static void LInput_Draw(void* widget) {
LInput_DrawOuterBorder(w);
LInput_DrawInnerBorder(w);
Drawer2D_Clear(&Launcher_Framebuffer, white,
Drawer2D_Clear(&Launcher_Framebuffer, BITMAPCOL_WHITE,
w->X + BORDER2, w->Y + BORDER2,
w->Width - BORDER4, w->Height - BORDER4);
LInput_BlendBoxTop(w);
@ -309,7 +308,6 @@ static Rect2D lastCaretRec;
static void LInput_TickCaret(void* widget) {
struct LInput* w = (struct LInput*)widget;
BitmapCol col = BITMAPCOL_CONST(0, 0, 0, 255);
int elapsed;
bool caretShow;
Rect2D r;
@ -325,7 +323,7 @@ static void LInput_TickCaret(void* widget) {
r = LInput_MeasureCaret(w);
if (caretShow) {
Drawer2D_Clear(&Launcher_Framebuffer, col,
Drawer2D_Clear(&Launcher_Framebuffer, BITMAPCOL_BLACK,
r.X, r.Y, r.Width, r.Height);
}
@ -607,8 +605,8 @@ void LLine_Init(struct LScreen* s, struct LLine* w, int width) {
*------------------------------------------------------SliderWidget-------------------------------------------------------*
*#########################################################################################################################*/
static void LSlider_DrawBoxBounds(struct LSlider* w) {
BitmapCol boundsTop = BITMAPCOL_CONST(119, 100, 132, 255);
BitmapCol boundsBottom = BITMAPCOL_CONST(150, 130, 165, 255);
BitmapCol boundsTop = BitmapCol_Make(119, 100, 132, 255);
BitmapCol boundsBottom = BitmapCol_Make(150, 130, 165, 255);
/* TODO: Check these are actually right */
Drawer2D_Clear(&Launcher_Framebuffer, boundsTop,
@ -627,8 +625,8 @@ static void LSlider_DrawBoxBounds(struct LSlider* w) {
}
static void LSlider_DrawBox(struct LSlider* w) {
BitmapCol progTop = BITMAPCOL_CONST(220, 204, 233, 255);
BitmapCol progBottom = BITMAPCOL_CONST(207, 181, 216, 255);
BitmapCol progTop = BitmapCol_Make(220, 204, 233, 255);
BitmapCol progBottom = BitmapCol_Make(207, 181, 216, 255);
int halfHeight = (w->Height - BORDER2) / 2;
Gradient_Vertical(&Launcher_Framebuffer, progTop, progBottom,
@ -775,7 +773,7 @@ static void LTable_SetSelectedTo(struct LTable* w, int index) {
/* Draws background behind column headers */
static void LTable_DrawHeaderBackground(struct LTable* w) {
BitmapCol gridCol = BITMAPCOL_CONST(20, 20, 10, 255);
BitmapCol gridCol = BitmapCol_Make(20, 20, 10, 255);
if (!Launcher_ClassicBackground) {
Drawer2D_Clear(&Launcher_Framebuffer, gridCol,
@ -787,11 +785,10 @@ static void LTable_DrawHeaderBackground(struct LTable* w) {
/* Works out the background colour of the given row */
static BitmapCol LTable_RowCol(struct LTable* w, struct ServerInfo* row) {
BitmapCol emptyCol = BITMAPCOL_CONST(0, 0, 0, 0);
BitmapCol gridCol = BITMAPCOL_CONST(20, 20, 10, 255);
BitmapCol featSelCol = BITMAPCOL_CONST( 50, 53, 0, 255);
BitmapCol featuredCol = BITMAPCOL_CONST(101, 107, 0, 255);
BitmapCol selectedCol = BITMAPCOL_CONST( 40, 40, 40, 255);
BitmapCol gridCol = BitmapCol_Make( 20, 20, 10, 255);
BitmapCol featSelCol = BitmapCol_Make( 50, 53, 0, 255);
BitmapCol featuredCol = BitmapCol_Make(101, 107, 0, 255);
BitmapCol selectedCol = BitmapCol_Make( 40, 40, 40, 255);
bool selected;
if (row) {
@ -802,7 +799,7 @@ static BitmapCol LTable_RowCol(struct LTable* w, struct ServerInfo* row) {
return selectedCol;
}
}
return Launcher_ClassicBackground ? emptyCol : gridCol;
return Launcher_ClassicBackground ? 0 : gridCol;
}
/* Draws background behind each row in the table */
@ -821,7 +818,7 @@ static void LTable_DrawRowsBackground(struct LTable* w) {
/* hit the end of the table */
if (height < 0) break;
if (col.A) {
if (col) {
Drawer2D_Clear(&Launcher_Framebuffer, col,
w->X, y, w->Width, height);
} else {
@ -912,8 +909,8 @@ static void LTable_DrawRows(struct LTable* w) {
/* Draws scrollbar on the right edge of the table */
static void LTable_DrawScrollbar(struct LTable* w) {
BitmapCol classicBack = BITMAPCOL_CONST( 80, 80, 80, 255);
BitmapCol classicScroll = BITMAPCOL_CONST(160, 160, 160, 255);
BitmapCol classicBack = BitmapCol_Make( 80, 80, 80, 255);
BitmapCol classicScroll = BitmapCol_Make(160, 160, 160, 255);
BitmapCol backCol = Launcher_ClassicBackground ? classicBack : Launcher_ButtonBorderCol;
BitmapCol scrollCol = Launcher_ClassicBackground ? classicScroll : Launcher_ButtonForeActiveCol;

View File

@ -161,8 +161,6 @@ static void Launcher_Display(void) {
}
static void Launcher_Init(void) {
BitmapCol col = BITMAPCOL_CONST(125, 125, 125, 255);
Event_RegisterVoid(&WindowEvents.Resized, NULL, Launcher_OnResize);
Event_RegisterVoid(&WindowEvents.StateChanged, NULL, Launcher_OnResize);
Event_RegisterVoid(&WindowEvents.Redraw, NULL, Launcher_ReqeustRedraw);
@ -179,7 +177,7 @@ static void Launcher_Init(void) {
Drawer2D_MakeFont(&Launcher_TextFont, 14, FONT_STYLE_NORMAL);
Drawer2D_MakeFont(&Launcher_HintFont, 12, FONT_STYLE_ITALIC);
Drawer2D_Cols['g'] = col;
Drawer2D_Cols['g'] = BitmapCol_Make(125, 125, 125, 255);
Utils_EnsureDirectory("texpacks");
Utils_EnsureDirectory("audio");
}
@ -302,34 +300,33 @@ void Launcher_Run(void) {
/*########################################################################################################################*
*---------------------------------------------------------Colours/Skin----------------------------------------------------*
*#########################################################################################################################*/
BitmapCol Launcher_BackgroundCol = BITMAPCOL_CONST(153, 127, 172, 255);
BitmapCol Launcher_ButtonBorderCol = BITMAPCOL_CONST( 97, 81, 110, 255);
BitmapCol Launcher_ButtonForeActiveCol = BITMAPCOL_CONST(189, 168, 206, 255);
BitmapCol Launcher_ButtonForeCol = BITMAPCOL_CONST(141, 114, 165, 255);
BitmapCol Launcher_ButtonHighlightCol = BITMAPCOL_CONST(162, 131, 186, 255);
#define DEFAULT_BACKGROUND_COL BitmapCol_Make(153, 127, 172, 255);
#define DEFAULT_BUTTON_BORDER_COL BitmapCol_Make( 97, 81, 110, 255);
#define DEFAULT_BUTTON_FORE_ACTIVE_COL BitmapCol_Make(189, 168, 206, 255);
#define DEFAULT_BUTTON_FORE_COL BitmapCol_Make(141, 114, 165, 255);
#define DEFAULT_BUTTON_HIGHLIGHT_COL BitmapCol_Make(162, 131, 186, 255);
BitmapCol Launcher_BackgroundCol = DEFAULT_BACKGROUND_COL;
BitmapCol Launcher_ButtonBorderCol = DEFAULT_BUTTON_BORDER_COL;
BitmapCol Launcher_ButtonForeActiveCol = DEFAULT_BUTTON_FORE_ACTIVE_COL;
BitmapCol Launcher_ButtonForeCol = DEFAULT_BUTTON_FORE_COL;
BitmapCol Launcher_ButtonHighlightCol = DEFAULT_BUTTON_HIGHLIGHT_COL;
void Launcher_ResetSkin(void) {
/* Have to duplicate it here, sigh */
BitmapCol defaultBackgroundCol = BITMAPCOL_CONST(153, 127, 172, 255);
BitmapCol defaultButtonBorderCol = BITMAPCOL_CONST( 97, 81, 110, 255);
BitmapCol defaultButtonForeActiveCol = BITMAPCOL_CONST(189, 168, 206, 255);
BitmapCol defaultButtonForeCol = BITMAPCOL_CONST(141, 114, 165, 255);
BitmapCol defaultButtonHighlightCol = BITMAPCOL_CONST(162, 131, 186, 255);
Launcher_BackgroundCol = defaultBackgroundCol;
Launcher_ButtonBorderCol = defaultButtonBorderCol;
Launcher_ButtonForeActiveCol = defaultButtonForeActiveCol;
Launcher_ButtonForeCol = defaultButtonForeCol;
Launcher_ButtonHighlightCol = defaultButtonHighlightCol;
Launcher_BackgroundCol = DEFAULT_BACKGROUND_COL;
Launcher_ButtonBorderCol = DEFAULT_BUTTON_BORDER_COL;
Launcher_ButtonForeActiveCol = DEFAULT_BUTTON_FORE_ACTIVE_COL;
Launcher_ButtonForeCol = DEFAULT_BUTTON_FORE_COL;
Launcher_ButtonHighlightCol = DEFAULT_BUTTON_HIGHLIGHT_COL;
}
CC_NOINLINE static void Launcher_GetCol(const char* key, BitmapCol* col) {
cc_uint8 rgb[3];
String value;
if (!Options_UNSAFE_Get(key, &value)) return;
if (!Options_UNSAFE_Get(key, &value)) return;
if (!PackedCol_TryParseHex(&value, rgb)) return;
col->R = rgb[0]; col->G = rgb[1]; col->B = rgb[2];
*col = BitmapCol_Make(rgb[0], rgb[1], rgb[2], 255);
}
void Launcher_LoadSkin(void) {
@ -343,7 +340,7 @@ void Launcher_LoadSkin(void) {
CC_NOINLINE static void Launcher_SetCol(const char* key, BitmapCol col) {
String value; char valueBuffer[8];
/* Component order might be different to BitmapCol */
PackedCol tmp = PackedCol_Make(col.R, col.G, col.B, 0);
PackedCol tmp = PackedCol_Make(BitmapCol_R(col), BitmapCol_G(col), BitmapCol_B(col), 0);
String_InitArray(value, valueBuffer);
PackedCol_ToHex(&value, tmp);

View File

@ -19,6 +19,7 @@ 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);
}

View File

@ -1161,15 +1161,12 @@ static void CPE_BulkBlockUpdate(cc_uint8* data) {
}
static void CPE_SetTextColor(cc_uint8* data) {
BitmapCol c;
cc_uint8 code;
c.R = *data++; c.G = *data++; c.B = *data++; c.A = *data++;
code = *data;
BitmapCol c = BitmapCol_Make(data[0], data[1], data[2], data[3]);
cc_uint8 code = data[4];
/* disallow space, null, and colour code specifiers */
if (code == '\0' || code == ' ' || code == 0xFF) return;
if (code == '%' || code == '&') return;
if (code == '%' || code == '&') return;
Drawer2D_Cols[code] = c;
Event_RaiseInt(&ChatEvents.ColCodeChanged, code);

View File

@ -86,10 +86,11 @@ static void LavaAnimation_Tick(BitmapCol* ptr, int size) {
col = 2.0f * L_soupHeat[i];
Math_Clamp(col, 0.0f, 1.0f);
ptr->R = (cc_uint8)(col * 100.0f + 155.0f);
ptr->G = (cc_uint8)(col * col * 255.0f);
ptr->B = (cc_uint8)(col * col * col * col * 128.0f);
ptr->A = 255;
*ptr = BitmapCol_Make(
col * 100.0f + 155.0f,
col * col * 255.0f,
col * col * col * col * 128.0f,
255);
ptr++; i++;
}
@ -137,10 +138,11 @@ static void WaterAnimation_Tick(BitmapCol* ptr, int size) {
Math_Clamp(col, 0.0f, 1.0f);
col = col * col;
ptr->R = (cc_uint8)(32.0f + col * 32.0f);
ptr->G = (cc_uint8)(50.0f + col * 64.0f);
ptr->A = (cc_uint8)(146.0f + col * 50.0f);
ptr->B = 255;
*ptr = BitmapCol_Make(
32.0f + col * 32.0f,
50.0f + col * 64.0f,
255,
146.0f + col * 50.0f);
ptr++; i++;
}

View File

@ -61,26 +61,27 @@ int Utils_AccumulateWheelDelta(float* accumulator, float delta) {
/* Checks if an area is completely black, so Alex skins edited with Microsoft Paint are still treated as Alex */
static bool Utils_IsAllBlack(const Bitmap* bmp, int x1, int y1, int width, int height) {
cc_uint32 black = PackedCol_ARGB(0, 0, 0, 255);
int x, y;
for (y = y1; y < y1 + height; y++) {
cc_uint32* row = Bitmap_RawRow(bmp, y);
BitmapCol* row = Bitmap_GetRow(bmp, y);
for (x = x1; x < x1 + width; x++) {
if (row[x] != black) return false;
if (row[x] != BITMAPCOL_BLACK) return false;
}
}
return true;
}
cc_uint8 Utils_CalcSkinType(const Bitmap* bmp) {
BitmapCol col;
int scale;
if (bmp->Width == bmp->Height * 2) return SKIN_64x32;
if (bmp->Width != bmp->Height) return SKIN_INVALID;
scale = bmp->Width / 64;
/* Minecraft alex skins have this particular pixel with alpha of 0 */
if (Bitmap_GetPixel(bmp, 54 * scale, 20 * scale).A < 128) return SKIN_64x64_SLIM;
col = Bitmap_GetPixel(bmp, 54 * scale, 20 * scale);
if (BitmapCol_A(col) < 128) return SKIN_64x64_SLIM;
return Utils_IsAllBlack(bmp, 54 * scale, 20 * scale, 2 * scale, 12 * scale)
&& Utils_IsAllBlack(bmp, 50 * scale, 16 * scale, 2 * scale, 4 * scale) ? SKIN_64x64_SLIM : SKIN_64x64;

View File

@ -928,7 +928,9 @@ static void InputWidget_UpdateCaret(struct InputWidget* w) {
if (colCode) {
col = Drawer2D_GetCol(colCode);
w->caretCol = PackedCol_Make(col.R, col.G, col.B, col.A);
/* Component order might be different to BitmapCol */
w->caretCol = PackedCol_Make(BitmapCol_R(col), BitmapCol_G(col),
BitmapCol_B(col), BitmapCol_A(col));
} else {
w->caretCol = PackedCol_Scale(PACKEDCOL_WHITE, 0.8f);
}
@ -1018,7 +1020,7 @@ static bool InputWidget_CheckCol(struct InputWidget* w, int index) {
code = w->text.buffer[index];
col = w->text.buffer[index + 1];
return (code == '%' || code == '&') && Drawer2D_GetCol(col).A;
return (code == '%' || code == '&') && BitmapCol_A(Drawer2D_GetCol(col));
}
static void InputWidget_BackspaceKey(struct InputWidget* w) {
@ -2468,8 +2470,8 @@ static void SpecialInputWidget_UpdateColString(struct SpecialInputWidget* w) {
String_InitArray(w->colString, w->_colBuffer);
for (i = 0; i < DRAWER2D_MAX_COLS; i++) {
if (i >= 'A' && i <= 'F') continue;
if (!Drawer2D_Cols[i].A) continue;
if (i >= 'A' && i <= 'F') continue;
if (!BitmapCol_A(Drawer2D_Cols[i])) continue;
String_Append(&w->colString, '&'); String_Append(&w->colString, (char)i);
String_Append(&w->colString, '%'); String_Append(&w->colString, (char)i);
@ -2557,8 +2559,8 @@ static Size2D SpecialInputWidget_MeasureTitles(struct SpecialInputWidget* w) {
}
static void SpecialInputWidget_DrawTitles(struct SpecialInputWidget* w, Bitmap* bmp) {
BitmapCol col_selected = BITMAPCOL_CONST(30, 30, 30, 200);
BitmapCol col_inactive = BITMAPCOL_CONST( 0, 0, 0, 127);
BitmapCol col_selected = BitmapCol_Make(30, 30, 30, 200);
BitmapCol col_inactive = BitmapCol_Make( 0, 0, 0, 127);
BitmapCol col;
struct DrawTextArgs args;
int i, width, x = 0;
@ -2618,7 +2620,7 @@ static void SpecialInputWidget_DrawContent(struct SpecialInputWidget* w, struct
}
static void SpecialInputWidget_Make(struct SpecialInputWidget* w, struct SpecialInputTab* tab) {
BitmapCol col = BITMAPCOL_CONST(30, 30, 30, 200);
BitmapCol col = BitmapCol_Make(30, 30, 30, 200);
Size2D size, titles, content;
Bitmap bmp;