use more efficient bitmapcol

This commit is contained in:
UnknownShadow200 2018-11-16 15:05:51 +11:00
parent ad78ab8d0d
commit e7738b50fa
27 changed files with 307 additions and 302 deletions

View File

@ -23,10 +23,9 @@ static float L_flameHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
static RNGState L_rnd; static RNGState L_rnd;
static bool L_rndInitalised; static bool L_rndInitalised;
static void LavaAnimation_Tick(uint32_t* ptr, int size) { static void LavaAnimation_Tick(BitmapCol* ptr, int size) {
int mask = size - 1, shift = Math_Log2(size); int mask = size - 1, shift = Math_Log2(size);
float soupHeat, potHeat, col; float soupHeat, potHeat, col;
uint8_t r, g, b;
int x, y, i = 0; int x, y, i = 0;
if (!L_rndInitalised) { if (!L_rndInitalised) {
@ -74,10 +73,10 @@ static void LavaAnimation_Tick(uint32_t* ptr, int size) {
col = 2.0f * L_soupHeat[i]; col = 2.0f * L_soupHeat[i];
Math_Clamp(col, 0.0f, 1.0f); Math_Clamp(col, 0.0f, 1.0f);
r = (uint8_t)(col * 100.0f + 155.0f); ptr->R = (uint8_t)(col * 100.0f + 155.0f);
g = (uint8_t)(col * col * 255.0f); ptr->G = (uint8_t)(col * col * 255.0f);
b = (uint8_t)(col * col * col * col * 128.0f); ptr->B = (uint8_t)(col * col * col * col * 128.0f);
*ptr = PackedCol_ARGB(r, g, b, 255); ptr->A = 255;
ptr++; i++; ptr++; i++;
} }
@ -94,10 +93,9 @@ static float W_flameHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
static RNGState W_rnd; static RNGState W_rnd;
static bool W_rndInitalised; static bool W_rndInitalised;
static void WaterAnimation_Tick(uint32_t* ptr, int size) { static void WaterAnimation_Tick(BitmapCol* ptr, int size) {
int mask = size - 1, shift = Math_Log2(size); int mask = size - 1, shift = Math_Log2(size);
float soupHeat, col; float soupHeat, col;
uint8_t r, g, a;
int x, y, i = 0; int x, y, i = 0;
if (!W_rndInitalised) { if (!W_rndInitalised) {
@ -126,10 +124,10 @@ static void WaterAnimation_Tick(uint32_t* ptr, int size) {
Math_Clamp(col, 0.0f, 1.0f); Math_Clamp(col, 0.0f, 1.0f);
col = col * col; col = col * col;
r = (uint8_t)(32.0f + col * 32.0f); ptr->R = (uint8_t)(32.0f + col * 32.0f);
g = (uint8_t)(50.0f + col * 64.0f); ptr->G = (uint8_t)(50.0f + col * 64.0f);
a = (uint8_t)(146.0f + col * 50.0f); ptr->A = (uint8_t)(146.0f + col * 50.0f);
*ptr = PackedCol_ARGB(r, g, 255, a); ptr->B = 255;
ptr++; i++; ptr++; i++;
} }
@ -230,9 +228,9 @@ static void Animations_Draw(struct AnimationData* data, TextureLoc texLoc, int s
if (!data) { if (!data) {
if (texLoc == 30) { if (texLoc == 30) {
LavaAnimation_Tick((uint32_t*)frame.Scan0, size); LavaAnimation_Tick((BitmapCol*)frame.Scan0, size);
} else if (texLoc == 14) { } else if (texLoc == 14) {
WaterAnimation_Tick((uint32_t*)frame.Scan0, size); WaterAnimation_Tick((BitmapCol*)frame.Scan0, size);
} }
} else { } else {
srcX = data->FrameX + data->State * size; srcX = data->FrameX + data->State * size;

View File

@ -37,7 +37,11 @@ void AxisLinesRenderer_Render(double delta) {
1,2,2, 1,2,4, 3,2,4, 3,2,2, /* Z arrow */ 1,2,2, 1,2,4, 3,2,4, 3,2,2, /* Z arrow */
1,2,3, 1,4,3, 3,4,1, 3,2,1, /* Y arrow */ 1,2,3, 1,4,3, 3,4,1, 3,2,1, /* Y arrow */
}; };
static PackedCol cols[3] = { PACKEDCOL_RED, PACKEDCOL_BLUE, PACKEDCOL_GREEN }; static PackedCol cols[3] = {
PACKEDCOL_CONST(255, 0, 0, 255), /* Red */
PACKEDCOL_CONST( 0, 255, 0, 255), /* Green */
PACKEDCOL_CONST( 0, 0, 255, 255), /* Blue */
};
Vector3 coords[5], pos; Vector3 coords[5], pos;
VertexP3fC4b vertices[AXISLINES_NUM_VERTICES]; VertexP3fC4b vertices[AXISLINES_NUM_VERTICES];

View File

@ -7,6 +7,13 @@
#include "Stream.h" #include "Stream.h"
#include "Errors.h" #include "Errors.h"
BitmapCol BitmapCol_Scale(BitmapCol value, float t) {
value.R = (uint8_t)(value.R * t);
value.G = (uint8_t)(value.G * t);
value.B = (uint8_t)(value.B * t);
return value;
}
void Bitmap_Create(Bitmap* bmp, int width, int height, uint8_t* scan0) { void Bitmap_Create(Bitmap* bmp, int width, int height, uint8_t* scan0) {
bmp->Width = width; bmp->Height = height; bmp->Scan0 = scan0; bmp->Width = width; bmp->Height = height; bmp->Scan0 = scan0;
} }
@ -14,11 +21,9 @@ void Bitmap_Create(Bitmap* bmp, int width, int height, uint8_t* scan0) {
void Bitmap_CopyBlock(int srcX, int srcY, int dstX, int dstY, Bitmap* src, Bitmap* dst, int size) { void Bitmap_CopyBlock(int srcX, int srcY, int dstX, int dstY, Bitmap* src, Bitmap* dst, int size) {
int x, y; int x, y;
for (y = 0; y < size; y++) { for (y = 0; y < size; y++) {
uint32_t* srcRow = Bitmap_GetRow(src, srcY + y); BitmapCol* srcRow = Bitmap_GetRow(src, srcY + y) + srcX;
uint32_t* dstRow = Bitmap_GetRow(dst, dstY + y); BitmapCol* dstRow = Bitmap_GetRow(dst, dstY + y) + dstX;
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) { dstRow[x] = srcRow[x]; }
dstRow[dstX + x] = srcRow[srcX + x];
}
} }
} }
@ -54,7 +59,7 @@ enum PngFilter {
PNG_FILTER_NONE, PNG_FILTER_SUB, PNG_FILTER_UP, PNG_FILTER_AVERAGE, PNG_FILTER_PAETH PNG_FILTER_NONE, PNG_FILTER_SUB, PNG_FILTER_UP, PNG_FILTER_AVERAGE, PNG_FILTER_PAETH
}; };
typedef void (*Png_RowExpander)(int width, uint32_t* palette, uint8_t* src, uint32_t* dst); typedef void (*Png_RowExpander)(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst);
static uint8_t png_sig[PNG_SIG_SIZE] = { 137, 80, 78, 71, 13, 10, 26, 10 }; static uint8_t png_sig[PNG_SIG_SIZE] = { 137, 80, 78, 71, 13, 10, 26, 10 };
bool Png_Detect(const uint8_t* data, uint32_t len) { bool Png_Detect(const uint8_t* data, uint32_t len) {
@ -118,58 +123,60 @@ static void Png_Reconstruct(uint8_t type, uint8_t bytesPerPixel, uint8_t* line,
} }
} }
static void Png_Expand_GRAYSCALE_1(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { #define Bitmap_Set(dst, r,g,b,a) dst.B = b; dst.G = g; dst.R = r; dst.A = a;
int i; /* NOTE: not optimised*/
#define PNG_Do_Grayscale(tmp, dstI, srcI, scale) tmp = src[srcI] * scale; dst[dstI] = PackedCol_ARGB(tmp, tmp, tmp, 255); #define PNG_Do_Grayscale(dstI, srcI, scale) rgb = src[srcI] * scale; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255);
for (i = 0; i < width; i++) { #define PNG_Do_Grayscale_8(dstI, srcI) rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255);
int mask = (7 - (i & 7)); uint8_t rgb; #define PNG_Do_Grayscale_A__8(dstI, srcI) rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, src[srcI + 1]);
PNG_Do_Grayscale(rgb, i, (src[i >> 3] >> mask) & 1, 255); #define PNG_Do_RGB__8(dstI, srcI) Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], 255);
} #define PNG_Do_RGB_A__8(dstI, srcI) Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], src[srcI + 3]);
#define PNG_Mask_1(i) (7 - (i & 7))
#define PNG_Mask_2(i) ((3 - (i & 3)) * 2)
#define PNG_Mask_4(i) ((1 - (i & 1)) * 4)
#define PNG_Get__1(i) ((src[i >> 3] >> PNG_Mask_1(i)) & 1)
#define PNG_Get__2(i) ((src[i >> 2] >> PNG_Mask_2(i)) & 3)
static void Png_Expand_GRAYSCALE_1(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; uint8_t rgb; /* NOTE: not optimised*/
for (i = 0; i < width; i++) { PNG_Do_Grayscale(i, PNG_Get__1(i), 255); }
} }
static void Png_Expand_GRAYSCALE_2(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_GRAYSCALE_2(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; /* NOTE: not optimised */ int i; uint8_t rgb; /* NOTE: not optimised */
for (i = 0; i < width; i++) { for (i = 0; i < width; i++) { PNG_Do_Grayscale(i, PNG_Get__2(i), 85); }
int mask = (3 - (i & 3)) * 2; uint8_t rgb;
PNG_Do_Grayscale(rgb, i, (src[i >> 3] >> mask) & 3, 85);
}
} }
static void Png_Expand_GRAYSCALE_4(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_GRAYSCALE_4(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j, mask; uint8_t cur, rgb1, rgb2; int i, j; uint8_t rgb;
for (i = 0, j = 0; i < (width & ~0x1); i += 2, j++) { for (i = 0, j = 0; i < (width & ~0x1); i += 2, j++) {
cur = src[j]; PNG_Do_Grayscale(i, src[j] >> 4, 17); PNG_Do_Grayscale(i + 1, src[j] & 0x0F, 17);
PNG_Do_Grayscale(rgb1, i, cur >> 4, 17); PNG_Do_Grayscale(rgb2, i + 1, cur & 0x0F, 17);
} }
for (; i < width; i++) { for (; i < width; i++) {
mask = (1 - (i & 1)) * 4; PNG_Do_Grayscale(i, (src[j] >> PNG_Mask_4(i)) & 15, 17);
PNG_Do_Grayscale(rgb1, i, (src[j] >> mask) & 15, 17);
} }
} }
static void Png_Expand_GRAYSCALE_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_GRAYSCALE_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; uint8_t rgb1, rgb2, rgb3, rgb4; int i; uint8_t rgb;
#define PNG_Do_Grayscale_8(tmp, dstI, srcI) tmp = src[srcI]; dst[dstI] = PackedCol_ARGB(tmp, tmp, tmp, 255);
for (i = 0; i < (width & ~0x3); i += 4) { for (i = 0; i < (width & ~0x3); i += 4) {
PNG_Do_Grayscale_8(rgb1, i , i ); PNG_Do_Grayscale_8(rgb2, i + 1, i + 1); PNG_Do_Grayscale_8(i , i ); PNG_Do_Grayscale_8(i + 1, i + 1);
PNG_Do_Grayscale_8(rgb3, i + 2, i + 2); PNG_Do_Grayscale_8(rgb4, i + 3, i + 3); PNG_Do_Grayscale_8(i + 2, i + 2); PNG_Do_Grayscale_8(i + 3, i + 3);
} }
for (; i < width; i++) { PNG_Do_Grayscale_8(rgb1, i, i); } for (; i < width; i++) { PNG_Do_Grayscale_8(i, i); }
} }
static void Png_Expand_GRAYSCALE_16(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_GRAYSCALE_16(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; int i; uint8_t rgb; /* NOTE: not optimised */
for (i = 0; i < width; i++) { for (i = 0; i < width; i++) {
uint8_t rgb = src[i * 2]; rgb = src[i * 2]; Bitmap_Set(dst[i], rgb, rgb, rgb, 255);
dst[i] = PackedCol_ARGB(rgb, rgb, rgb, 255);
} }
} }
static void Png_Expand_RGB_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_RGB_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; int i, j;
#define PNG_Do_RGB__8(dstI, srcI) dst[dstI] = PackedCol_ARGB(src[srcI], src[srcI + 1], src[srcI + 2], 255);
for (i = 0, j = 0; i < (width & ~0x03); i += 4, j += 12) { for (i = 0, j = 0; i < (width & ~0x03); i += 4, j += 12) {
PNG_Do_RGB__8(i , j ); PNG_Do_RGB__8(i + 1, j + 3); PNG_Do_RGB__8(i , j ); PNG_Do_RGB__8(i + 1, j + 3);
@ -178,75 +185,64 @@ static void Png_Expand_RGB_8(int width, uint32_t* palette, uint8_t* src, uint32_
for (; i < width; i++, j += 3) { PNG_Do_RGB__8(i, j); } for (; i < width; i++, j += 3) { PNG_Do_RGB__8(i, j); }
} }
static void Png_Expand_RGB_16(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_RGB_16(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; int i, j; /* NOTE: not optimised */
for (i = 0, j = 0; i < width; i++, j += 6) { for (i = 0, j = 0; i < width; i++, j += 6) {
dst[i] = PackedCol_ARGB(src[j], src[j + 2], src[j + 4], 255); Bitmap_Set(dst[i], src[j], src[j + 2], src[j + 4], 255);
} }
} }
static void Png_Expand_INDEXED_1(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_INDEXED_1(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; /* NOTE: not optimised*/ int i; /* NOTE: not optimised */
for (i = 0; i < width; i++) { for (i = 0; i < width; i++) { dst[i] = palette[PNG_Get__1(i)]; }
int mask = (7 - (i & 7));
dst[i] = palette[(src[i >> 3] >> mask) & 1];
}
} }
static void Png_Expand_INDEXED_2(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_INDEXED_2(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; /* NOTE: not optimised*/ int i; /* NOTE: not optimised */
for (i = 0; i < width; i++) { for (i = 0; i < width; i++) { dst[i] = palette[PNG_Get__2(i)]; }
int mask = (3 - (i & 3)) * 2;
dst[i] = palette[(src[i >> 3] >> mask) & 3];
}
} }
static void Png_Expand_INDEXED_4(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_INDEXED_4(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j, mask; uint8_t cur; int i, j; uint8_t cur;
#define PNG_Do_Indexed(dstI, srcI) dst[dstI] = palette[srcI];
for (i = 0, j = 0; i < (width & ~0x1); i += 2, j++) { for (i = 0, j = 0; i < (width & ~0x1); i += 2, j++) {
cur = src[j]; cur = src[j];
PNG_Do_Indexed(i, cur >> 4); PNG_Do_Indexed(i + 1, cur & 0x0F); dst[i] = palette[cur >> 4]; dst[i + 1] = palette[cur & 0x0F];
} }
for (; i < width; i++) { for (; i < width; i++) {
mask = (1 - (i & 1)) * 4; dst[i] = palette[(src[j] >> PNG_Mask_4(i)) & 15];
PNG_Do_Indexed(i, (src[j] >> mask) & 15);
} }
} }
static void Png_Expand_INDEXED_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_INDEXED_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; int i;
for (i = 0; i < (width & ~0x3); i += 4) { for (i = 0; i < (width & ~0x3); i += 4) {
PNG_Do_Indexed(i , src[i] ); PNG_Do_Indexed(i + 1, src[i + 1]); dst[i] = palette[src[i]]; dst[i + 1] = palette[src[i + 1]];
PNG_Do_Indexed(i + 2, src[i + 2]); PNG_Do_Indexed(i + 3, src[i + 3]); dst[i + 2] = palette[src[i + 2]]; dst[i + 3] = palette[src[i + 3]];
} }
for (; i < width; i++) { PNG_Do_Indexed(i, src[i]); } for (; i < width; i++) { dst[i] = palette[src[i]]; }
} }
static void Png_Expand_GRAYSCALE_A_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_GRAYSCALE_A_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; uint8_t rgb1, rgb2, rgb3, rgb4; int i, j; uint8_t rgb;
#define PNG_Do_Grayscale_A__8(tmp, dstI, srcI) tmp = src[srcI]; dst[dstI] = PackedCol_ARGB(tmp, tmp, tmp, src[srcI + 1]);
for (i = 0, j = 0; i < (width & ~0x3); i += 4, j += 8) { for (i = 0, j = 0; i < (width & ~0x3); i += 4, j += 8) {
PNG_Do_Grayscale_A__8(rgb1, i , j ); PNG_Do_Grayscale_A__8(rgb2, i + 1, j + 2); PNG_Do_Grayscale_A__8(i , j ); PNG_Do_Grayscale_A__8(i + 1, j + 2);
PNG_Do_Grayscale_A__8(rgb3, i + 2, j + 4); PNG_Do_Grayscale_A__8(rgb4, i + 3, j + 6); PNG_Do_Grayscale_A__8(i + 2, j + 4); PNG_Do_Grayscale_A__8(i + 3, j + 6);
} }
for (; i < width; i++, j += 2) { PNG_Do_Grayscale_A__8(rgb1, i, j); } for (; i < width; i++, j += 2) { PNG_Do_Grayscale_A__8(i, j); }
} }
static void Png_Expand_GRAYSCALE_A_16(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_GRAYSCALE_A_16(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; /* NOTE: not optimised*/ int i; uint8_t rgb; /* NOTE: not optimised*/
for (i = 0, j = 0; i < width; i++, j += 4) { for (i = 0; i < width; i++) {
uint8_t rgb = src[j]; rgb = src[i * 4]; Bitmap_Set(dst[i], rgb, rgb, rgb, src[i * 4 + 2]);
dst[i] = PackedCol_ARGB(rgb, rgb, rgb, src[j + 2]);
} }
} }
static void Png_Expand_RGB_A_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_RGB_A_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; int i, j;
#define PNG_Do_RGB_A__8(dstI, srcI) dst[dstI] = PackedCol_ARGB(src[srcI], src[srcI + 1], src[srcI + 2], src[srcI + 3]);
for (i = 0, j = 0; i < (width & ~0x3); i += 4, j += 16) { for (i = 0, j = 0; i < (width & ~0x3); i += 4, j += 16) {
PNG_Do_RGB_A__8(i , j ); PNG_Do_RGB_A__8(i + 1, j + 4 ); PNG_Do_RGB_A__8(i , j ); PNG_Do_RGB_A__8(i + 1, j + 4 );
@ -255,10 +251,10 @@ static void Png_Expand_RGB_A_8(int width, uint32_t* palette, uint8_t* src, uint3
for (; i < width; i++, j += 4) { PNG_Do_RGB_A__8(i, j); } for (; i < width; i++, j += 4) { PNG_Do_RGB_A__8(i, j); }
} }
static void Png_Expand_RGB_A_16(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) { static void Png_Expand_RGB_A_16(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; /* NOTE: not optimised*/ int i, j; /* NOTE: not optimised*/
for (i = 0, j = 0; i < width; i++, j += 8) { for (i = 0, j = 0; i < width; i++, j += 8) {
dst[i] = PackedCol_ARGB(src[j], src[j + 2], src[j + 4], src[j + 6]); Bitmap_Set(dst[i], src[j], src[j + 2], src[j + 4], src[j + 6]);
} }
} }
@ -307,12 +303,12 @@ Png_RowExpander Png_GetExpander(uint8_t col, uint8_t bitsPerSample) {
return NULL; return NULL;
} }
static void Png_ComputeTransparency(Bitmap* bmp, uint32_t transparentCol) { static void Png_ComputeTransparency(Bitmap* bmp, BitmapCol col) {
uint32_t trnsRGB = transparentCol & PNG_RGB_MASK; uint32_t trnsRGB = col.B | (col.G << 8) | (col.R << 16); /* TODO: Remove this!! */
int x, y, width = bmp->Width, height = bmp->Height; int x, y, width = bmp->Width, height = bmp->Height;
for (y = 0; y < height; y++) { for (y = 0; y < height; y++) {
uint32_t* row = Bitmap_GetRow(bmp, y); uint32_t* row = Bitmap_RawRow(bmp, y);
for (x = 0; x < width; x++) { for (x = 0; x < width; x++) {
uint32_t rgb = row[x] & PNG_RGB_MASK; uint32_t rgb = row[x] & PNG_RGB_MASK;
row[x] = (rgb == trnsRGB) ? trnsRGB : row[x]; row[x] = (rgb == trnsRGB) ? trnsRGB : row[x];
@ -335,8 +331,9 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
uint32_t scanlineSize, scanlineBytes; uint32_t scanlineSize, scanlineBytes;
/* palette data */ /* palette data */
uint32_t transparentCol = PackedCol_ARGB(0, 0, 0, 255); BitmapCol black = BITMAPCOL_CONST(0, 0, 0, 255);
uint32_t palette[PNG_PALETTE]; BitmapCol transparentCol;
BitmapCol palette[PNG_PALETTE];
uint32_t i; uint32_t i;
/* idat state */ /* idat state */
@ -355,15 +352,13 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res; if (res) return res;
if (!Png_Detect(tmp, PNG_SIG_SIZE)) return PNG_ERR_INVALID_SIG; if (!Png_Detect(tmp, PNG_SIG_SIZE)) return PNG_ERR_INVALID_SIG;
for (i = 0; i < PNG_PALETTE; i++) { transparentCol = black;
palette[i] = PackedCol_ARGB(0, 0, 0, 255); for (i = 0; i < PNG_PALETTE; i++) { palette[i] = black; }
}
bool readingChunks = true;
Inflate_MakeStream(&compStream, &inflate, stream); Inflate_MakeStream(&compStream, &inflate, stream);
ZLibHeader_Init(&zlibHeader); ZLibHeader_Init(&zlibHeader);
while (readingChunks) { for (;;) {
res = Stream_Read(stream, tmp, 8); res = Stream_Read(stream, tmp, 8);
if (res) return res; if (res) return res;
dataSize = Stream_GetU32_BE(&tmp[0]); dataSize = Stream_GetU32_BE(&tmp[0]);
@ -407,7 +402,9 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res; if (res) return res;
for (i = 0; i < dataSize; i += 3) { for (i = 0; i < dataSize; i += 3) {
palette[i / 3] = PackedCol_ARGB(tmp[i], tmp[i + 1], tmp[i + 2], 255); palette[i / 3].R = tmp[i];
palette[i / 3].G = tmp[i + 1];
palette[i / 3].B = tmp[i + 2];
} }
} break; } break;
@ -418,8 +415,8 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res; if (res) return res;
/* RGB is 16 bits big endian, ignore least significant 8 bits */ /* RGB is 16 bits big endian, ignore least significant 8 bits */
uint8_t palRGB = tmp[0]; transparentCol.B = tmp[0]; transparentCol.G = tmp[0];
transparentCol = PackedCol_ARGB(palRGB, palRGB, palRGB, 0); transparentCol.R = tmp[0]; transparentCol.A = 0;
} else if (col == PNG_COL_INDEXED) { } else if (col == PNG_COL_INDEXED) {
if (dataSize > PNG_PALETTE) return PNG_ERR_TRANS_COUNT; if (dataSize > PNG_PALETTE) return PNG_ERR_TRANS_COUNT;
res = Stream_Read(stream, tmp, dataSize); res = Stream_Read(stream, tmp, dataSize);
@ -427,8 +424,7 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
/* set alpha component of palette*/ /* set alpha component of palette*/
for (i = 0; i < dataSize; i++) { for (i = 0; i < dataSize; i++) {
palette[i] &= PNG_RGB_MASK; palette[i].A = tmp[i];
palette[i] |= (uint32_t)tmp[i] << 24;
} }
} else if (col == PNG_COL_RGB) { } else if (col == PNG_COL_RGB) {
if (dataSize != 6) return PNG_ERR_TRANS_COUNT; if (dataSize != 6) return PNG_ERR_TRANS_COUNT;
@ -436,8 +432,8 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res; if (res) return res;
/* R,G,B is 16 bits big endian, ignore least significant 8 bits */ /* R,G,B is 16 bits big endian, ignore least significant 8 bits */
uint8_t palR = tmp[0], palG = tmp[2], palB = tmp[4]; transparentCol.B = tmp[4]; transparentCol.G = tmp[2];
transparentCol = PackedCol_ARGB(palR, palG, palB, 0); transparentCol.R = tmp[0]; transparentCol.A = 0;
} else { } else {
return PNG_ERR_TRANS_INVALID; return PNG_ERR_TRANS_INVALID;
} }
@ -491,8 +487,9 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
} break; } break;
case PNG_FourCC('I','E','N','D'): { case PNG_FourCC('I','E','N','D'): {
readingChunks = false;
if (dataSize) return PNG_ERR_INVALID_END_SIZE; if (dataSize) return PNG_ERR_INVALID_END_SIZE;
if (!transparentCol.A) Png_ComputeTransparency(bmp, transparentCol);
return bmp->Scan0 ? 0 : PNG_ERR_NO_DATA;
} break; } break;
default: default:
@ -502,11 +499,6 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if ((res = stream->Skip(stream, 4))) return res; /* Skip CRC32 */ if ((res = stream->Skip(stream, 4))) return res; /* Skip CRC32 */
} }
if (transparentCol <= PNG_RGB_MASK) {
Png_ComputeTransparency(bmp, transparentCol);
}
return bmp->Scan0 ? 0 : PNG_ERR_NO_DATA;
} }
@ -589,14 +581,14 @@ static void Png_Filter(uint8_t filter, uint8_t* cur, uint8_t* prior, uint8_t* be
} }
} }
static void Png_EncodeRow(const uint8_t* src, uint8_t* cur, uint8_t* prior, uint8_t* best, int lineLen) { static void Png_EncodeRow(const BitmapCol* src, uint8_t* cur, uint8_t* prior, uint8_t* best, int lineLen) {
uint8_t* dst = cur; uint8_t* dst = cur;
int bestFilter, bestEstimate = Int32_MaxValue; int bestFilter, bestEstimate = Int32_MaxValue;
int x, filter, estimate; int x, filter, estimate;
for (x = 0; x < lineLen; x += 3) { for (x = 0; x < lineLen; x += 3) {
dst[0] = src[2]; dst[1] = src[1]; dst[2] = src[0]; dst[0] = src->R; dst[1] = src->G; dst[2] = src->B;
src += 4; dst += 3; src++; dst += 3;
} }
dst = best + 1; dst = best + 1;
@ -665,9 +657,9 @@ ReturnCode Png_Encode(Bitmap* bmp, struct Stream* stream, Png_RowSelector select
for (y = 0; y < bmp->Height; y++) { for (y = 0; y < bmp->Height; y++) {
int row = selectRow(bmp, y); int row = selectRow(bmp, y);
uint8_t* src = (uint8_t*)Bitmap_GetRow(bmp, row); BitmapCol* src = Bitmap_GetRow(bmp, row);
uint8_t* prev = (y & 1) == 0 ? prevLine : curLine; uint8_t* prev = (y & 1) == 0 ? prevLine : curLine;
uint8_t* cur = (y & 1) == 0 ? curLine : prevLine; uint8_t* cur = (y & 1) == 0 ? curLine : prevLine;
Png_EncodeRow(src, cur, prev, bestLine, lineSize); Png_EncodeRow(src, cur, prev, bestLine, lineSize);
/* +1 for filter byte */ /* +1 for filter byte */

View File

@ -6,12 +6,26 @@
*/ */
struct Stream; struct Stream;
/* Represents an ARGB colour, suitable for native graphics API texture pixels. */
typedef CC_ALIGN_HINT(4) struct BitmapCol_ {
uint8_t B, G, R, A;
} BitmapCol;
/* Represents an ARGB colour, suitable for native graphics API texture pixels. */
/* Unioned with Packed member for efficient equality comparison */
typedef union BitmapColUnion_ { BitmapCol C; uint32_t Raw; } BitmapColUnion;
typedef struct Bitmap_ { uint8_t* Scan0; int Width, Height; } Bitmap;
#define PNG_MAX_DIMS 0x8000 #define PNG_MAX_DIMS 0x8000
#define BITMAPCOL_CONST(r, g, b, a) { b, g, r, a }
#define BITMAP_SIZEOF_PIXEL 4 /* 32 bit ARGB */ #define BITMAP_SIZEOF_PIXEL 4 /* 32 bit ARGB */
#define Bitmap_DataSize(width, height) ((uint32_t)(width) * (uint32_t)(height) * (uint32_t)BITMAP_SIZEOF_PIXEL) #define Bitmap_DataSize(width, height) ((uint32_t)(width) * (uint32_t)(height) * (uint32_t)BITMAP_SIZEOF_PIXEL)
#define Bitmap_GetRow(bmp, y) ((uint32_t*)((bmp)->Scan0 + ((y) * ((bmp)->Width << 2)))) #define Bitmap_RawRow(bmp, y) ((uint32_t*)((bmp)->Scan0 + ((y) * ((bmp)->Width << 2))))
#define Bitmap_GetRow(bmp, y) ((BitmapCol*)((bmp)->Scan0 + ((y) * ((bmp)->Width << 2))))
#define Bitmap_GetPixel(bmp, x, y) (Bitmap_GetRow(bmp, y)[x]) #define Bitmap_GetPixel(bmp, x, y) (Bitmap_GetRow(bmp, y)[x])
BitmapCol BitmapCol_Scale(BitmapCol value, float t);
void Bitmap_Create(Bitmap* bmp, int width, int height, uint8_t* scan0); void Bitmap_Create(Bitmap* bmp, int width, int height, uint8_t* scan0);
void Bitmap_CopyBlock(int srcX, int srcY, int dstX, int dstY, Bitmap* src, Bitmap* dst, int size); void Bitmap_CopyBlock(int srcX, int srcY, int dstX, int dstY, Bitmap* src, Bitmap* dst, int size);
/* Allocates a new bitmap of the given dimensions. You are responsible for freeing its memory! */ /* Allocates a new bitmap of the given dimensions. You are responsible for freeing its memory! */

View File

@ -89,7 +89,7 @@ void Block_SetCustomDefined(BlockID block, bool defined) {
} }
void Block_DefineCustom(BlockID block) { void Block_DefineCustom(BlockID block) {
PackedCol black = PACKEDCOL_BLACK; PackedCol black = PACKEDCOL_CONST(0, 0, 0, 255);
String name = Block_UNSAFE_GetName(block); String name = Block_UNSAFE_GetName(block);
Block_Tinted[block] = !PackedCol_Equals(Block_FogCol[block], black) && String_IndexOf(&name, '#', 0) >= 0; Block_Tinted[block] = !PackedCol_Equals(Block_FogCol[block], black) && String_IndexOf(&name, '#', 0) >= 0;
@ -283,60 +283,52 @@ void Block_RecalculateSpriteBB(void) {
} }
static float Block_GetSpriteBB_MinX(int size, int tileX, int tileY, Bitmap* bmp) { static float Block_GetSpriteBB_MinX(int size, int tileX, int tileY, Bitmap* bmp) {
uint32_t* row; BitmapCol* row;
int x, y; int x, y;
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
for (y = 0; y < size; y++) { for (y = 0; y < size; y++) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size); row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
if (row[x].A) { return (float)x / size; }
if (PackedCol_ARGB_A(row[x]) != 0) {
return (float)x / size;
}
} }
} }
return 1.0f; return 1.0f;
} }
static float Block_GetSpriteBB_MinY(int size, int tileX, int tileY, Bitmap* bmp) { static float Block_GetSpriteBB_MinY(int size, int tileX, int tileY, Bitmap* bmp) {
uint32_t* row; BitmapCol* row;
int x, y; int x, y;
for (y = size - 1; y >= 0; y--) { for (y = size - 1; y >= 0; y--) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size); row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
if (PackedCol_ARGB_A(row[x]) != 0) { if (row[x].A) { return 1.0f - (float)(y + 1) / size; }
return 1.0f - (float)(y + 1) / size;
}
} }
} }
return 1.0f; return 1.0f;
} }
static float Block_GetSpriteBB_MaxX(int size, int tileX, int tileY, Bitmap* bmp) { static float Block_GetSpriteBB_MaxX(int size, int tileX, int tileY, Bitmap* bmp) {
uint32_t* row; BitmapCol* row;
int x, y; int x, y;
for (x = size - 1; x >= 0; x--) { for (x = size - 1; x >= 0; x--) {
for (y = 0; y < size; y++) { for (y = 0; y < size; y++) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size); row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
if (row[x].A) { return (float)(x + 1) / size; }
if (PackedCol_ARGB_A(row[x]) != 0) {
return (float)(x + 1) / size;
}
} }
} }
return 0.0f; return 0.0f;
} }
static float Block_GetSpriteBB_MaxY(int size, int tileX, int tileY, Bitmap* bmp) { static float Block_GetSpriteBB_MaxY(int size, int tileX, int tileY, Bitmap* bmp) {
uint32_t* row; BitmapCol* row;
int x, y; int x, y;
for (y = 0; y < size; y++) { for (y = 0; y < size; y++) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size); row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
if (PackedCol_ARGB_A(row[x]) != 0) { if (row[x].A) { return 1.0f - (float)y / size; }
return 1.0f - (float)y / size;
}
} }
} }
return 0.0f; return 0.0f;

View File

@ -508,7 +508,7 @@ static PackedCol Normal_LightCol(int x, int y, int z, Face face, BlockID block)
return y >= World_MaxY ? Env_SunCol : Lighting_Col_YMax_Fast(x, (y + 1) - offset, z); return y >= World_MaxY ? Env_SunCol : Lighting_Col_YMax_Fast(x, (y + 1) - offset, z);
} }
PackedCol black = PACKEDCOL_BLACK; return black; PackedCol invalid = PACKEDCOL_CONST(0, 0, 0, 0); return invalid;
} }
static bool Normal_CanStretch(BlockID initial, int chunkIndex, int x, int y, int z, Face face) { static bool Normal_CanStretch(BlockID initial, int chunkIndex, int x, int y, int z, Face face) {

View File

@ -270,25 +270,28 @@ static int ChunkUpdater_UpdateChunksStill(int* chunkUpdates) {
return j; return j;
} }
void ChunkUpdater_UpdateChunks(double delta) { static void ChunkUpdater_UpdateChunks(double delta) {
struct LocalPlayer* p;
bool samePos;
int chunkUpdates = 0; int chunkUpdates = 0;
cu_chunksTarget += delta < cu_targetTime ? 1 : -1; /* build more chunks if 30 FPS or over, otherwise slowdown. */
/* Build more chunks if 30 FPS or over, otherwise slowdown */
cu_chunksTarget += delta < cu_targetTime ? 1 : -1;
Math_Clamp(cu_chunksTarget, 4, Game_MaxChunkUpdates); Math_Clamp(cu_chunksTarget, 4, Game_MaxChunkUpdates);
struct LocalPlayer* p = &LocalPlayer_Instance; p = &LocalPlayer_Instance;
Vector3 pos = Camera_CurrentPos; samePos = Vector3_Equals(&Camera_CurrentPos, &cu_lastCamPos)
float headX = p->Base.HeadX; && p->Base.HeadX == cu_lastHeadX && p->Base.HeadY == cu_lastHeadY;
float headY = p->Base.HeadY;
bool samePos = Vector3_Equals(&pos, &cu_lastCamPos) && headX == cu_lastHeadX && headY == cu_lastHeadY;
MapRenderer_RenderChunksCount = samePos ? MapRenderer_RenderChunksCount = samePos ?
ChunkUpdater_UpdateChunksStill(&chunkUpdates) : ChunkUpdater_UpdateChunksStill(&chunkUpdates) :
ChunkUpdater_UpdateChunksAndVisibility(&chunkUpdates); ChunkUpdater_UpdateChunksAndVisibility(&chunkUpdates);
cu_lastCamPos = pos; cu_lastCamPos = Camera_CurrentPos;
cu_lastHeadX = headX; cu_lastHeadY = headY; cu_lastHeadX = p->Base.HeadX;
cu_lastHeadY = p->Base.HeadY;
if (!samePos || chunkUpdates != 0) { if (!samePos || chunkUpdates) {
ChunkUpdater_ResetPartFlags(); ChunkUpdater_ResetPartFlags();
} }
} }

View File

@ -72,7 +72,6 @@ typedef struct Point2D_ { int X, Y; } Point2D;
typedef struct Size2D_ { int Width, Height; } Size2D; typedef struct Size2D_ { int Width, Height; } Size2D;
typedef struct FontDesc_ { void* Handle; uint16_t Size, Style; } FontDesc; typedef struct FontDesc_ { void* Handle; uint16_t Size, Style; } FontDesc;
typedef struct TextureRec_ { float U1, V1, U2, V2; } TextureRec; typedef struct TextureRec_ { float U1, V1, U2, V2; } TextureRec;
typedef struct Bitmap_ { uint8_t* Scan0; int Width, Height; } Bitmap;
/*#define CC_BUILD_GL11*/ /*#define CC_BUILD_GL11*/
/*#define CC_BUILD_SOLARIS*/ /*#define CC_BUILD_SOLARIS*/

View File

@ -38,7 +38,7 @@ static int Drawer2D_Widths[256];
static void Drawer2D_CalculateTextWidths(void) { static void Drawer2D_CalculateTextWidths(void) {
int width = Drawer2D_FontBitmap.Width, height = Drawer2D_FontBitmap.Height; int width = Drawer2D_FontBitmap.Width, height = Drawer2D_FontBitmap.Height;
uint32_t* row; BitmapCol* row;
int i, x, y, xx, tileX, tileY; int i, x, y, xx, tileX, tileY;
for (i = 0; i < Array_Elems(Drawer2D_Widths); i++) { for (i = 0; i < Array_Elems(Drawer2D_Widths); i++) {
@ -55,9 +55,7 @@ static void Drawer2D_CalculateTextWidths(void) {
/* Iterate through each pixel of the given character, on the current scanline */ /* Iterate through each pixel of the given character, on the current scanline */
for (xx = Drawer2D_TileSize - 1; xx >= 0; xx--) { for (xx = Drawer2D_TileSize - 1; xx >= 0; xx--) {
uint32_t pixel = row[x + xx]; if (row[x + xx].A < 127) continue;
uint8_t a = PackedCol_ARGB_A(pixel);
if (a < 127) continue;
/* Check if this is the pixel furthest to the right, for the current character */ /* Check if this is the pixel furthest to the right, for the current character */
Drawer2D_Widths[i] = max(Drawer2D_Widths[i], xx + 1); Drawer2D_Widths[i] = max(Drawer2D_Widths[i], xx + 1);
@ -82,15 +80,14 @@ void Drawer2D_SetFontBitmap(Bitmap* bmp) {
void Drawer2D_HexEncodedCol(int i, int hex, uint8_t lo, uint8_t hi) { void Drawer2D_HexEncodedCol(int i, int hex, uint8_t lo, uint8_t hi) {
PackedCol* col = &Drawer2D_Cols[i]; Drawer2D_Cols[i].R = (uint8_t)(lo * ((hex >> 2) & 1) + hi * (hex >> 3));
col->R = (uint8_t)(lo * ((hex >> 2) & 1) + hi * (hex >> 3)); Drawer2D_Cols[i].G = (uint8_t)(lo * ((hex >> 1) & 1) + hi * (hex >> 3));
col->G = (uint8_t)(lo * ((hex >> 1) & 1) + hi * (hex >> 3)); Drawer2D_Cols[i].B = (uint8_t)(lo * ((hex >> 0) & 1) + hi * (hex >> 3));
col->B = (uint8_t)(lo * ((hex >> 0) & 1) + hi * (hex >> 3)); Drawer2D_Cols[i].A = 255;
col->A = UInt8_MaxValue;
} }
void Drawer2D_Init(void) { void Drawer2D_Init(void) {
PackedCol col = PACKEDCOL_CONST(0, 0, 0, 0); BitmapCol col = BITMAPCOL_CONST(0, 0, 0, 0);
int i; int i;
for (i = 0; i < DRAWER2D_MAX_COLS; i++) { for (i = 0; i < DRAWER2D_MAX_COLS; i++) {
@ -109,11 +106,10 @@ void Drawer2D_Init(void) {
void Drawer2D_Free(void) { Drawer2D_FreeFontBitmap(); } void Drawer2D_Free(void) { Drawer2D_FreeFontBitmap(); }
/* Draws a 2D flat rectangle. */ /* Draws a 2D flat rectangle. */
void Drawer2D_Rect(Bitmap* bmp, PackedCol col, int x, int y, int width, int height); void Drawer2D_Rect(Bitmap* bmp, BitmapCol col, int x, int y, int width, int height);
void Drawer2D_Clear(Bitmap* bmp, PackedCol col, int x, int y, int width, int height) { void Drawer2D_Clear(Bitmap* bmp, BitmapCol col, int x, int y, int width, int height) {
uint32_t argb = PackedCol_ToARGB(col); BitmapCol* row;
uint32_t* row;
int xx, yy; int xx, yy;
if (x < 0 || y < 0 || (x + width) > bmp->Width || (y + height) > bmp->Height) { if (x < 0 || y < 0 || (x + width) > bmp->Width || (y + height) > bmp->Height) {
@ -122,7 +118,7 @@ void Drawer2D_Clear(Bitmap* bmp, PackedCol col, int x, int y, int width, int hei
for (yy = 0; yy < height; yy++) { for (yy = 0; yy < height; yy++) {
row = Bitmap_GetRow(bmp, y + yy) + x; row = Bitmap_GetRow(bmp, y + yy) + x;
for (xx = 0; xx < width; xx++) { row[xx] = argb; } for (xx = 0; xx < width; xx++) { row[xx] = col; }
} }
} }
@ -233,9 +229,8 @@ static int Drawer2D_NextPart(int i, STRING_REF String* value, String* part, char
return i; return i;
} }
void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, PackedCol col) { void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, BitmapCol col) {
uint32_t argb = PackedCol_ToARGB(col); BitmapCol* row;
uint32_t* row;
int xx, yy; int xx, yy;
for (yy = y; yy < y + height; yy++) { for (yy = y; yy < y + height; yy++) {
@ -244,14 +239,14 @@ void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, Packed
for (xx = x; xx < x + width; xx++) { for (xx = x; xx < x + width; xx++) {
if (xx >= bmp->Width) break; if (xx >= bmp->Width) break;
row[xx] = argb; row[xx] = col;
} }
} }
} }
static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int y, bool shadow) { static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int y, bool shadow) {
PackedCol black = PACKEDCOL_BLACK; BitmapCol black = BITMAPCOL_CONST(0, 0, 0, 255);
PackedColUnion col; BitmapColUnion col;
String text = args->Text; String text = args->Text;
int i, point = args->Font.Size, count = 0; int i, point = args->Font.Size, count = 0;
@ -262,13 +257,16 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
int dstHeight, begX, xx, yy; int dstHeight, begX, xx, yy;
int cellY, underlineY, underlineHeight; int cellY, underlineY, underlineHeight;
BitmapCol* srcRow, src;
BitmapCol* dstRow, dst;
uint8_t coords[256]; uint8_t coords[256];
PackedColUnion cols[256]; BitmapColUnion cols[256];
uint16_t dstWidths[256]; uint16_t dstWidths[256];
col.C = Drawer2D_Cols['f']; col.C = Drawer2D_Cols['f'];
if (shadow) { if (shadow) {
col.C = Drawer2D_BlackTextShadows ? black : PackedCol_Scale(col.C, 0.25f); col.C = Drawer2D_BlackTextShadows ? black : BitmapCol_Scale(col.C, 0.25f);
} }
for (i = 0; i < text.length; i++) { for (i = 0; i < text.length; i++) {
@ -276,7 +274,7 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
if (c == '&' && Drawer2D_ValidColCodeAt(&text, i + 1)) { if (c == '&' && Drawer2D_ValidColCodeAt(&text, i + 1)) {
col.C = Drawer2D_GetCol(text.buffer[i + 1]); col.C = Drawer2D_GetCol(text.buffer[i + 1]);
if (shadow) { if (shadow) {
col.C = Drawer2D_BlackTextShadows ? black : PackedCol_Scale(col.C, 0.25f); col.C = Drawer2D_BlackTextShadows ? black : BitmapCol_Scale(col.C, 0.25f);
} }
i++; continue; /* skip over the colour code */ i++; continue; /* skip over the colour code */
} }
@ -296,13 +294,13 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
dstY = y + (yy + yPadding); dstY = y + (yy + yPadding);
if (dstY >= bmp->Height) break; if (dstY >= bmp->Height) break;
fontY = 0 + yy * Drawer2D_TileSize / dstHeight; fontY = 0 + yy * Drawer2D_TileSize / dstHeight;
uint32_t* dstRow = Bitmap_GetRow(bmp, dstY); dstRow = Bitmap_GetRow(bmp, dstY);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
srcX = (coords[i] & 0x0F) * Drawer2D_TileSize; srcX = (coords[i] & 0x0F) * Drawer2D_TileSize;
srcY = (coords[i] >> 4) * Drawer2D_TileSize; srcY = (coords[i] >> 4) * Drawer2D_TileSize;
uint32_t* fontRow = Bitmap_GetRow(&Drawer2D_FontBitmap, fontY + srcY); srcRow = Bitmap_GetRow(&Drawer2D_FontBitmap, fontY + srcY);
srcWidth = Drawer2D_Widths[coords[i]]; srcWidth = Drawer2D_Widths[coords[i]];
dstWidth = dstWidths[i]; dstWidth = dstWidths[i];
@ -310,17 +308,17 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
for (xx = 0; xx < dstWidth; xx++) { for (xx = 0; xx < dstWidth; xx++) {
fontX = srcX + xx * srcWidth / dstWidth; fontX = srcX + xx * srcWidth / dstWidth;
uint32_t src = fontRow[fontX]; src = srcRow[fontX];
if (PackedCol_ARGB_A(src) == 0) continue; if (!src.A) continue;
dstX = x + xx; dstX = x + xx;
if (dstX >= bmp->Width) break; if (dstX >= bmp->Width) break;
uint32_t pixel = src & ~0xFFFFFF; dst.B = src.B * col.C.B / 255;
pixel |= ((src & 0xFF) * col.C.B / 255); dst.G = src.G * col.C.G / 255;
pixel |= (((src >> 8) & 0xFF) * col.C.G / 255) << 8; dst.R = src.R * col.C.R / 255;
pixel |= (((src >> 16) & 0xFF) * col.C.R / 255) << 16; dst.A = src.A;
dstRow[dstX] = pixel; dstRow[dstX] = dst;
} }
x += dstWidth + xPadding; x += dstWidth + xPadding;
} }
@ -382,7 +380,7 @@ static Size2D Drawer2D_MeasureBitmapText(struct DrawTextArgs* args) {
} }
void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y) { void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y) {
PackedCol col, backCol, black = PACKEDCOL_BLACK; BitmapCol col, backCol, black = BITMAPCOL_CONST(0, 0, 0, 255);
Size2D partSize; Size2D partSize;
String value = args->Text; String value = args->Text;
char colCode, nextCol = 'f'; char colCode, nextCol = 'f';
@ -398,7 +396,7 @@ void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y) {
col = Drawer2D_GetCol(colCode); col = Drawer2D_GetCol(colCode);
if (args->UseShadow) { if (args->UseShadow) {
backCol = Drawer2D_BlackTextShadows ? black : PackedCol_Scale(col, 0.25f); backCol = Drawer2D_BlackTextShadows ? black : BitmapCol_Scale(col, 0.25f);
Platform_TextDraw(args, bmp, x + DRAWER2D_OFFSET, y + DRAWER2D_OFFSET, backCol); Platform_TextDraw(args, bmp, x + DRAWER2D_OFFSET, y + DRAWER2D_OFFSET, backCol);
} }

View File

@ -2,6 +2,7 @@
#define CC_DRAWER2D_H #define CC_DRAWER2D_H
#include "PackedCol.h" #include "PackedCol.h"
#include "Constants.h" #include "Constants.h"
#include "Bitmap.h"
/* Responsible for performing drawing operations on bitmaps, and for converting bitmaps into textures. /* Responsible for performing drawing operations on bitmaps, and for converting bitmaps into textures.
Copyright 2017 ClassicalSharp | Licensed under BSD-3 Copyright 2017 ClassicalSharp | Licensed under BSD-3
*/ */
@ -18,7 +19,7 @@ CC_NOINLINE void Drawer2D_MakeFont(FontDesc* desc, int size, int style);
bool Drawer2D_BitmappedText; bool Drawer2D_BitmappedText;
/* Whether the shadows behind text (that uses shadows) is fully black. */ /* Whether the shadows behind text (that uses shadows) is fully black. */
bool Drawer2D_BlackTextShadows; bool Drawer2D_BlackTextShadows;
PackedCol Drawer2D_Cols[DRAWER2D_MAX_COLS]; BitmapCol Drawer2D_Cols[DRAWER2D_MAX_COLS];
#define DRAWER2D_OFFSET 1 #define DRAWER2D_OFFSET 1
#define Drawer2D_GetCol(c) Drawer2D_Cols[(uint8_t)c] #define Drawer2D_GetCol(c) Drawer2D_Cols[(uint8_t)c]
@ -26,11 +27,11 @@ void Drawer2D_Init(void);
void Drawer2D_Free(void); void Drawer2D_Free(void);
/* Draws a 2D flat rectangle. */ /* Draws a 2D flat rectangle. */
void Drawer2D_Rect(Bitmap* bmp, PackedCol col, int x, int y, int width, int height); void Drawer2D_Rect(Bitmap* bmp, BitmapCol col, int x, int y, int width, int height);
/* Clears the entire given area to the specified colour. */ /* Clears the entire given area to the specified colour. */
void Drawer2D_Clear(Bitmap* bmp, PackedCol col, int x, int y, int width, int height); void Drawer2D_Clear(Bitmap* bmp, BitmapCol col, int x, int y, int width, int height);
void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, PackedCol col); void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, BitmapCol col);
void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y); void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y);
Size2D Drawer2D_MeasureText(struct DrawTextArgs* args); Size2D Drawer2D_MeasureText(struct DrawTextArgs* args);
int Drawer2D_FontHeight(const FontDesc* font, bool useShadow); int Drawer2D_FontHeight(const FontDesc* font, bool useShadow);

View File

@ -477,6 +477,9 @@ void TabList_MakeComponent(struct IGameComponent* comp) {
static void Player_MakeNameTexture(struct Player* player) { static void Player_MakeNameTexture(struct Player* player) {
String colorlessName; char colorlessBuffer[STRING_SIZE]; String colorlessName; char colorlessBuffer[STRING_SIZE];
BitmapCol shadowCol = BITMAPCOL_CONST(80, 80, 80, 255);
BitmapCol origWhiteCol;
struct DrawTextArgs args; struct DrawTextArgs args;
bool bitmapped; bool bitmapped;
String name; String name;
@ -501,9 +504,9 @@ static void Player_MakeNameTexture(struct Player* player) {
Bitmap_AllocateClearedPow2(&bmp, size.Width, size.Height); Bitmap_AllocateClearedPow2(&bmp, size.Width, size.Height);
{ {
PackedCol origWhiteCol = Drawer2D_Cols['f']; origWhiteCol = Drawer2D_Cols['f'];
Drawer2D_Cols['f'] = PackedCol_Create3(80, 80, 80); Drawer2D_Cols['f'] = shadowCol;
String_AppendColorless(&colorlessName, &name); String_AppendColorless(&colorlessName, &name);
args.Text = colorlessName; args.Text = colorlessName;
Drawer2D_DrawText(&bmp, &args, NAME_OFFSET, NAME_OFFSET); Drawer2D_DrawText(&bmp, &args, NAME_OFFSET, NAME_OFFSET);
@ -653,11 +656,9 @@ static void Player_ClearHat(Bitmap* bmp, uint8_t skinType) {
/* determine if we actually need filtering */ /* determine if we actually need filtering */
for (y = 0; y < sizeY; y++) { for (y = 0; y < sizeY; y++) {
uint32_t* row = Bitmap_GetRow(bmp, y); BitmapCol* row = Bitmap_GetRow(bmp, y) + sizeX;
row += sizeX;
for (x = 0; x < sizeX; x++) { for (x = 0; x < sizeX; x++) {
uint8_t alpha = PackedCol_ARGB_A(row[x]); if (row[x].A != 255) return;
if (alpha != 255) return;
} }
} }
@ -665,8 +666,7 @@ static void Player_ClearHat(Bitmap* bmp, uint8_t skinType) {
uint32_t fullWhite = PackedCol_ARGB(255, 255, 255, 255); uint32_t fullWhite = PackedCol_ARGB(255, 255, 255, 255);
uint32_t fullBlack = PackedCol_ARGB(0, 0, 0, 255); uint32_t fullBlack = PackedCol_ARGB(0, 0, 0, 255);
for (y = 0; y < sizeY; y++) { for (y = 0; y < sizeY; y++) {
uint32_t* row = Bitmap_GetRow(bmp, y); uint32_t* row = Bitmap_RawRow(bmp, y) + sizeX;
row += sizeX;
for (x = 0; x < sizeX; x++) { for (x = 0; x < sizeX; x++) {
uint32_t pixel = row[x]; uint32_t pixel = row[x];
if (pixel == fullWhite || pixel == fullBlack) row[x] = 0; if (pixel == fullWhite || pixel == fullBlack) row[x] = 0;
@ -690,8 +690,8 @@ static void Player_EnsurePow2(struct Player* p, Bitmap* bmp) {
stride = bmp->Width * BITMAP_SIZEOF_PIXEL; stride = bmp->Width * BITMAP_SIZEOF_PIXEL;
for (y = 0; y < bmp->Height; y++) { for (y = 0; y < bmp->Height; y++) {
uint32_t* src = Bitmap_GetRow(bmp, y); BitmapCol* src = Bitmap_GetRow(bmp, y);
uint32_t* dst = Bitmap_GetRow(&scaled, y); BitmapCol* dst = Bitmap_GetRow(&scaled, y);
Mem_Copy(dst, src, stride); Mem_Copy(dst, src, stride);
} }

View File

@ -602,14 +602,14 @@ static bool ShadowComponent_GetBlocks(struct Entity* e, int x, int y, int z, str
#define sh_half (sh_size / 2) #define sh_half (sh_size / 2)
static void ShadowComponent_MakeTex(void) { static void ShadowComponent_MakeTex(void) {
uint8_t pixels[Bitmap_DataSize(sh_size, sh_size)]; uint8_t pixels[Bitmap_DataSize(sh_size, sh_size)];
Bitmap bmp; Bitmap_Create(&bmp, sh_size, sh_size, pixels); BitmapCol inPix = BITMAPCOL_CONST(0, 0, 0, 200);
BitmapCol outPix = BITMAPCOL_CONST(0, 0, 0, 0);
uint32_t inPix = PackedCol_ARGB(0, 0, 0, 200); Bitmap bmp;
uint32_t outPix = PackedCol_ARGB(0, 0, 0, 0);
uint32_t x, y; uint32_t x, y;
Bitmap_Create(&bmp, sh_size, sh_size, pixels);
for (y = 0; y < sh_size; y++) { for (y = 0; y < sh_size; y++) {
uint32_t* row = Bitmap_GetRow(&bmp, y); BitmapCol* row = Bitmap_GetRow(&bmp, y);
for (x = 0; x < sh_size; x++) { for (x = 0; x < sh_size; x++) {
double dist = double dist =
(sh_half - (x + 0.5)) * (sh_half - (x + 0.5)) + (sh_half - (x + 0.5)) * (sh_half - (x + 0.5)) +

View File

@ -215,18 +215,21 @@ static GfxResourceID sky_vb;
static int sky_vertices; static int sky_vertices;
void EnvRenderer_RenderSky(double deltaTime) { void EnvRenderer_RenderSky(double deltaTime) {
struct Matrix m;
float skyY, normY, dy;
if (!sky_vb || EnvRenderer_ShouldRenderSkybox()) return; if (!sky_vb || EnvRenderer_ShouldRenderSkybox()) return;
Vector3 pos = Camera_CurrentPos;
float normalY = (float)World_Height + 8.0f; normY = (float)World_Height + 8.0f;
float skyY = max(pos.Y + 8.0f, normalY); skyY = max(Camera_CurrentPos.Y + 8.0f, normY);
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FC4B); Gfx_SetBatchFormat(VERTEX_FORMAT_P3FC4B);
Gfx_BindVb(sky_vb); Gfx_BindVb(sky_vb);
if (skyY == normalY) { if (skyY == normY) {
Gfx_DrawVb_IndexedTris(sky_vertices); Gfx_DrawVb_IndexedTris(sky_vertices);
} else { } else {
struct Matrix m = Gfx_View; m = Gfx_View;
float dy = skyY - normalY; /* inlined Y translation matrix multiply */ dy = skyY - normY;
/* inlined Y translation matrix multiply */
m.Row3.X += dy * m.Row1.X; m.Row3.Y += dy * m.Row1.Y; m.Row3.X += dy * m.Row1.X; m.Row3.Y += dy * m.Row1.Y;
m.Row3.Z += dy * m.Row1.Z; m.Row3.W += dy * m.Row1.W; m.Row3.Z += dy * m.Row1.Z; m.Row3.W += dy * m.Row1.W;
@ -445,12 +448,19 @@ static float EnvRenderer_RainAlphaAt(float x) {
} }
void EnvRenderer_RenderWeather(double deltaTime) { void EnvRenderer_RenderWeather(double deltaTime) {
int weather = Env_Weather; VertexP3fT2fC4b vertices[WEATHER_VERTS_COUNT];
VertexP3fT2fC4b* ptr, v;
int weather, vCount;
Vector3I pos; Vector3I pos;
bool moved, particles; bool moved, particles;
float speed, vOffset; float speed, vOffset;
float dist, alpha;
int dist, dx, dz, x, z;
float alpha, y, height;
float worldV, v1, v2;
float x1,y1,z1, x2,y2,z2;
weather = Env_Weather;
if (weather == WEATHER_SUNNY) return; if (weather == WEATHER_SUNNY) return;
if (!Weather_Heightmap) EnvRenderer_InitWeatherHeightmap(); if (!Weather_Heightmap) EnvRenderer_InitWeatherHeightmap();
Gfx_BindTexture(weather == WEATHER_RAINY ? rain_tex : snow_tex); Gfx_BindTexture(weather == WEATHER_RAINY ? rain_tex : snow_tex);
@ -468,16 +478,15 @@ void EnvRenderer_RenderWeather(double deltaTime) {
particles = weather == WEATHER_RAINY; particles = weather == WEATHER_RAINY;
weather_accumulator += deltaTime; weather_accumulator += deltaTime;
VertexP3fT2fC4b v; v.Col = Env_SunCol; ptr = vertices;
VertexP3fT2fC4b vertices[WEATHER_VERTS_COUNT]; v.Col = Env_SunCol;
VertexP3fT2fC4b* ptr = vertices;
int dx, dz;
for (dx = -WEATHER_EXTENT; dx <= WEATHER_EXTENT; dx++) { for (dx = -WEATHER_EXTENT; dx <= WEATHER_EXTENT; dx++) {
for (dz = -WEATHER_EXTENT; dz <= WEATHER_EXTENT; dz++) { for (dz = -WEATHER_EXTENT; dz <= WEATHER_EXTENT; dz++) {
int x = pos.X + dx, z = pos.Z + dz; x = pos.X + dx; z = pos.Z + dz;
float y = EnvRenderer_RainHeight(x, z);
float height = pos.Y - y; y = EnvRenderer_RainHeight(x, z);
height = pos.Y - y;
if (height <= 0) continue; if (height <= 0) continue;
if (particles && (weather_accumulator >= 0.25 || moved)) { if (particles && (weather_accumulator >= 0.25 || moved)) {
@ -485,16 +494,17 @@ void EnvRenderer_RenderWeather(double deltaTime) {
Particles_RainSnowEffect(particlePos); Particles_RainSnowEffect(particlePos);
} }
dist = (float)dx * (float)dx + (float)dz * (float)dz; dist = dx * dx + dz * dz;
alpha = EnvRenderer_RainAlphaAt(dist); alpha = EnvRenderer_RainAlphaAt((float)dist);
Math_Clamp(alpha, 0.0f, 255.0f); Math_Clamp(alpha, 0.0f, 255.0f);
v.Col.A = (uint8_t)alpha; v.Col.A = (uint8_t)alpha;
/* NOTE: Making vertex is inlined since this is called millions of times. */ /* NOTE: Making vertex is inlined since this is called millions of times. */
float worldV = vOffset + (z & 1) / 2.0f - (x & 0x0F) / 16.0f; worldV = vOffset + (z & 1) / 2.0f - (x & 0x0F) / 16.0f;
float v1 = y / 6.0f + worldV, v2 = (y + height) / 6.0f + worldV; v1 = y / 6.0f + worldV;
float x1 = (float)x, y1 = (float)y, z1 = (float)z; v2 = (y + height) / 6.0f + worldV;
float x2 = (float)(x + 1), y2 = (float)(y + height), z2 = (float)(z + 1); x1 = (float)x; y1 = (float)y; z1 = (float)z;
x2 = (float)(x + 1); y2 = (float)(y + height); z2 = (float)(z + 1);
v.X = x1; v.Y = y1; v.Z = z1; v.U = 0.0f; v.V = v1; *ptr++ = v; v.X = x1; v.Y = y1; v.Z = z1; v.U = 0.0f; v.V = v1; *ptr++ = v;
v.Y = y2; v.V = v2; *ptr++ = v; v.Y = y2; v.V = v2; *ptr++ = v;
@ -518,7 +528,7 @@ void EnvRenderer_RenderWeather(double deltaTime) {
Gfx_SetAlphaArgBlend(true); Gfx_SetAlphaArgBlend(true);
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B); Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B);
int vCount = (int)(ptr - vertices); vCount = (int)(ptr - vertices);
GfxCommon_UpdateDynamicVb_IndexedTris(weather_vb, vertices, vCount); GfxCommon_UpdateDynamicVb_IndexedTris(weather_vb, vertices, vCount);
Gfx_SetAlphaArgBlend(false); Gfx_SetAlphaArgBlend(false);

View File

@ -445,13 +445,16 @@ typedef struct {
} X11Button; } X11Button;
static void X11Button_Draw(X11Button* b, X11Window* w) { static void X11Button_Draw(X11Button* b, X11Window* w) {
X11Textbox* t;
int begX, endX, begY, endY;
XSetForeground(dpy, w->gc, w->btnBorder); XSetForeground(dpy, w->gc, w->btnBorder);
XDrawRectangle(dpy, w->win, w->gc, b->X, b->Y, XDrawRectangle(dpy, w->win, w->gc, b->X, b->Y,
b->Width, b->Height); b->Width, b->Height);
X11Textbox* t = &b->Text; t = &b->Text;
int begX = b->X + 1, endX = b->X + b->Width - 1; begX = b->X + 1; endX = b->X + b->Width - 1;
int begY = b->Y + 1, endY = b->Y + b->Height - 1; begY = b->Y + 1; endY = b->Y + b->Height - 1;
if (b->Clicked) { if (b->Clicked) {
XSetForeground(dpy, w->gc, w->highlight); XSetForeground(dpy, w->gc, w->highlight);

View File

@ -2,6 +2,7 @@
#define CC_GAME_H #define CC_GAME_H
#include "Picking.h" #include "Picking.h"
#include "Options.h" #include "Options.h"
#include "Bitmap.h"
/* Represents the game. /* Represents the game.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/ */

View File

@ -3,6 +3,7 @@
#include "PackedCol.h" #include "PackedCol.h"
#include "Vectors.h" #include "Vectors.h"
#include "GameStructs.h" #include "GameStructs.h"
#include "Bitmap.h"
/* Abstracts a 3D graphics rendering API. /* Abstracts a 3D graphics rendering API.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3

View File

@ -167,52 +167,54 @@ void GfxCommon_RestoreAlphaState(uint8_t draw) {
} }
#define alphaMask ((uint32_t)0xFF000000UL)
/* Quoted from http://www.realtimerendering.com/blog/gpus-prefer-premultiplication/ /* Quoted from http://www.realtimerendering.com/blog/gpus-prefer-premultiplication/
The short version: if you want your renderer to properly handle textures with alphas when using The short version: if you want your renderer to properly handle textures with alphas when using
bilinear interpolation or mipmapping, you need to premultiply your PNG color data by their (unassociated) alphas. */ bilinear interpolation or mipmapping, you need to premultiply your PNG color data by their (unassociated) alphas. */
static uint32_t GfxCommon_Average(uint32_t p1, uint32_t p2) { static BitmapCol GfxCommon_Average(BitmapCol p1, BitmapCol p2) {
uint32_t a1 = ((p1 & alphaMask) >> 24) & 0xFF; uint32_t a1, a2, aSum;
uint32_t a2 = ((p2 & alphaMask) >> 24) & 0xFF; uint32_t b1, g1, r1;
uint32_t aSum = (a1 + a2); uint32_t b2, g2, r2;
BitmapCol ave;
a1 = p1.A; a2 = p2.A;
aSum = (a1 + a2);
aSum = aSum > 0 ? aSum : 1; /* avoid divide by 0 below */ aSum = aSum > 0 ? aSum : 1; /* avoid divide by 0 below */
/* Convert RGB to pre-multiplied form */ /* Convert RGB to pre-multiplied form */
uint32_t r1 = ((p1 >> 16) & 0xFF) * a1, g1 = ((p1 >> 8) & 0xFF) * a1, b1 = (p1 & 0xFF) * a1; b1 = p1.B * a1; g1 = p1.G * a1; r1 = p1.R * a1;
uint32_t r2 = ((p2 >> 16) & 0xFF) * a2, g2 = ((p2 >> 8) & 0xFF) * a2, b2 = (p2 & 0xFF) * a2; b2 = p1.B * a2; g2 = p2.G * a2; r2 = p2.R * a2;
/* https://stackoverflow.com/a/347376 /* https://stackoverflow.com/a/347376
We need to convert RGB back from the pre-multiplied average into normal form We need to convert RGB back from the pre-multiplied average into normal form
((r1 + r2) / 2) / ((a1 + a2) / 2) ((r1 + r2) / 2) / ((a1 + a2) / 2)
but we just cancel out the / 2*/ but we just cancel out the / 2*/
uint32_t aAve = aSum >> 1; ave.B = (b1 + b2) / aSum;
uint32_t rAve = (r1 + r2) / aSum; ave.G = (g1 + g2) / aSum;
uint32_t gAve = (g1 + g2) / aSum; ave.R = (r1 + r2) / aSum;
uint32_t bAve = (b1 + b2) / aSum; ave.A = aSum >> 1;
return ave;
return (aAve << 24) | (rAve << 16) | (gAve << 8) | bAve;
} }
void GfxCommon_GenMipmaps(int width, int height, uint8_t* lvlScan0, uint8_t* scan0) { void GfxCommon_GenMipmaps(int width, int height, uint8_t* lvlScan0, uint8_t* scan0) {
uint32_t* baseSrc = (uint32_t*)scan0; BitmapCol* baseSrc = (BitmapCol*)scan0;
uint32_t* baseDst = (uint32_t*)lvlScan0; BitmapCol* baseDst = (BitmapCol*)lvlScan0;
int srcWidth = width << 1; int srcWidth = width << 1;
int x, y; int x, y;
for (y = 0; y < height; y++) { for (y = 0; y < height; y++) {
int srcY = (y << 1); int srcY = (y << 1);
uint32_t* src0 = baseSrc + srcY * srcWidth; BitmapCol* src0 = baseSrc + srcY * srcWidth;
uint32_t* src1 = src0 + srcWidth; BitmapCol* src1 = src0 + srcWidth;
uint32_t* dst = baseDst + y * width; BitmapCol* dst = baseDst + y * width;
for (x = 0; x < width; x++) { for (x = 0; x < width; x++) {
int srcX = (x << 1); int srcX = (x << 1);
uint32_t src00 = src0[srcX], src01 = src0[srcX + 1]; BitmapCol src00 = src0[srcX], src01 = src0[srcX + 1];
uint32_t src10 = src1[srcX], src11 = src1[srcX + 1]; BitmapCol src10 = src1[srcX], src11 = src1[srcX + 1];
/* bilinear filter this mipmap */ /* bilinear filter this mipmap */
uint32_t ave0 = GfxCommon_Average(src00, src01); BitmapCol ave0 = GfxCommon_Average(src00, src01);
uint32_t ave1 = GfxCommon_Average(src10, src11); BitmapCol ave1 = GfxCommon_Average(src10, src11);
dst[x] = GfxCommon_Average(ave0, ave1); dst[x] = GfxCommon_Average(ave0, ave1);
} }
} }

View File

@ -13,10 +13,6 @@ bool PackedCol_Equals(PackedCol a, PackedCol b) {
return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A; return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
} }
uint32_t PackedCol_ToARGB(PackedCol col) {
return PackedCol_ARGB(col.R, col.G, col.B, col.A);
}
PackedCol PackedCol_Scale(PackedCol value, float t) { PackedCol PackedCol_Scale(PackedCol value, float t) {
value.R = (uint8_t)(value.R * t); value.R = (uint8_t)(value.R * t);
value.G = (uint8_t)(value.G * t); value.G = (uint8_t)(value.G * t);

View File

@ -1,11 +1,11 @@
#ifndef CC_PACKEDCOL_H #ifndef CC_PACKEDCOL_H
#define CC_PACKEDCOL_H #define CC_PACKEDCOL_H
#include "String.h" #include "String.h"
/* Manipulates an ARGB colour, in a format suitable for the native 3d graphics api. /* Manipulates an ARGB colour, in a format suitable for the native 3D graphics API.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/ */
/* Represents an ARGB colour, in a format suitable for the native graphics api. */ /* Represents an ARGB colour, suitable for native graphics API colours. */
typedef CC_ALIGN_HINT(4) struct PackedCol_ { typedef CC_ALIGN_HINT(4) struct PackedCol_ {
#ifdef CC_BUILD_D3D9 #ifdef CC_BUILD_D3D9
uint8_t B, G, R, A; uint8_t B, G, R, A;
@ -14,25 +14,22 @@
#endif #endif
} PackedCol; } PackedCol;
/* Represents an ARGB colour, in a format suitable for the native graphics api. */ /* Represents an ARGB colour, suitable for native graphics API colours. */
/* Unioned with Packed member for efficient equality comparison */ /* Unioned with Packed member for efficient equality comparison */
typedef union PackedColUnion_ { PackedCol C; uint32_t Raw; } PackedColUnion; typedef union PackedColUnion_ { PackedCol C; uint32_t Raw; } PackedColUnion;
/* NOTE: can't just use "struct { uint8_t B, G, R, A; };" here,
because unnamed members aren't supported on all compilers) */
#ifdef CC_BUILD_D3D9 #ifdef CC_BUILD_D3D9
#define PACKEDCOL_CONST(r, g, b, a) { b, g, r, a } #define PACKEDCOL_CONST(r, g, b, a) { b, g, r, a }
#else #else
#define PACKEDCOL_CONST(r, g, b, a) { r, g, b, a } #define PACKEDCOL_CONST(r, g, b, a) { r, g, b, a }
#endif #endif
#define PACKEDCOL_WHITE PACKEDCOL_CONST(255, 255, 255, 255)
PackedCol PackedCol_Create4(uint8_t r, uint8_t g, uint8_t b, uint8_t a); PackedCol PackedCol_Create4(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
PackedCol PackedCol_Create3(uint8_t r, uint8_t g, uint8_t b); PackedCol PackedCol_Create3(uint8_t r, uint8_t g, uint8_t b);
bool PackedCol_Equals(PackedCol a, PackedCol b); bool PackedCol_Equals(PackedCol a, PackedCol b);
#define PackedCol_ARGB(r, g, b, a) (((uint32_t)(r) << 16) | ((uint32_t)(g) << 8) | ((uint32_t)(b)) | ((uint32_t)(a) << 24)) #define PackedCol_ARGB(r, g, b, a) (((uint32_t)(r) << 16) | ((uint32_t)(g) << 8) | ((uint32_t)(b)) | ((uint32_t)(a) << 24))
#define PackedCol_ARGB_A(col) ((uint8_t)((col) >> 24))
uint32_t PackedCol_ToARGB(PackedCol col);
PackedCol PackedCol_Scale(PackedCol value, float t); PackedCol PackedCol_Scale(PackedCol value, float t);
PackedCol PackedCol_Lerp(PackedCol a, PackedCol b, float t); PackedCol PackedCol_Lerp(PackedCol a, PackedCol b, float t);
CC_NOINLINE bool PackedCol_Unhex(char hex, int* value); CC_NOINLINE bool PackedCol_Unhex(char hex, int* value);
@ -44,13 +41,4 @@ CC_NOINLINE bool PackedCol_TryParseHex(const String* str, PackedCol* value);
#define PACKEDCOL_SHADE_YMIN 0.5f #define PACKEDCOL_SHADE_YMIN 0.5f
/* Retrieves shaded colours for ambient block face lighting */ /* Retrieves shaded colours for ambient block face lighting */
void PackedCol_GetShaded(PackedCol normal, PackedCol* xSide, PackedCol* zSide, PackedCol* yMin); void PackedCol_GetShaded(PackedCol normal, PackedCol* xSide, PackedCol* zSide, PackedCol* yMin);
#define PACKEDCOL_WHITE PACKEDCOL_CONST(255, 255, 255, 255)
#define PACKEDCOL_BLACK PACKEDCOL_CONST( 0, 0, 0, 255)
#define PACKEDCOL_RED PACKEDCOL_CONST(255, 0, 0, 255)
#define PACKEDCOL_GREEN PACKEDCOL_CONST( 0, 255, 0, 255)
#define PACKEDCOL_BLUE PACKEDCOL_CONST( 0, 0, 255, 255)
#define PACKEDCOL_YELLOW PACKEDCOL_CONST(255, 255, 0, 255)
#define PACKEDCOL_MAGENTA PACKEDCOL_CONST(255, 0, 255, 255)
#define PACKEDCOL_CYAN PACKEDCOL_CONST( 0, 255, 255, 255)
#endif #endif

View File

@ -1212,7 +1212,7 @@ static void CPE_BulkBlockUpdate(uint8_t* data) {
} }
static void CPE_SetTextColor(uint8_t* data) { static void CPE_SetTextColor(uint8_t* data) {
PackedCol c; BitmapCol c;
uint8_t code; uint8_t code;
c.R = *data++; c.G = *data++; c.B = *data++; c.A = *data++; c.R = *data++; c.G = *data++; c.B = *data++; c.A = *data++;

View File

@ -1007,7 +1007,7 @@ Size2D Platform_TextMeasure(struct DrawTextArgs* args) {
return s; return s;
} }
Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, PackedCol col) { Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, BitmapCol col) {
FT_Face face = args->Font.Handle; FT_Face face = args->Font.Handle;
String text = args->Text; String text = args->Text;
Size2D s = { x, TEXT_CEIL(face->size->metrics.height) }; Size2D s = { x, TEXT_CEIL(face->size->metrics.height) };
@ -1023,19 +1023,19 @@ Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, P
for (yy = 0; yy < img->rows; yy++) { for (yy = 0; yy < img->rows; yy++) {
if ((y + yy) < 0 || (y + yy) >= bmp->Height) continue; if ((y + yy) < 0 || (y + yy) >= bmp->Height) continue;
uint8_t* src = img->buffer + (yy * img->width); uint8_t* src = img->buffer + (yy * img->width);
uint8_t* dst = (uint8_t*)Bitmap_GetRow(bmp, y + yy) + (x * BITMAP_SIZEOF_PIXEL); BitmapCol* dst = Bitmap_GetRow(bmp, y + yy) + x;
for (xx = 0; xx < img->width; xx++) { for (xx = 0; xx < img->width; xx++) {
if ((x + xx) < 0 || (x + xx) >= bmp->Width) continue; if ((x + xx) < 0 || (x + xx) >= bmp->Width) continue;
uint8_t intensity = *src, invIntensity = UInt8_MaxValue - intensity; uint8_t intensity = *src, invIntensity = UInt8_MaxValue - intensity;
dst[0] = ((col.B * intensity) >> 8) + ((dst[0] * invIntensity) >> 8); dst->B = ((col.B * intensity) >> 8) + ((dst->B * invIntensity) >> 8);
dst[1] = ((col.G * intensity) >> 8) + ((dst[1] * invIntensity) >> 8); dst->G = ((col.G * intensity) >> 8) + ((dst->G * invIntensity) >> 8);
dst[2] = ((col.R * intensity) >> 8) + ((dst[2] * invIntensity) >> 8); dst->R = ((col.R * intensity) >> 8) + ((dst->R * invIntensity) >> 8);
//dst[3] = ((col.A * intensity) >> 8) + ((dst[3] * invIntensity) >> 8); //dst[3] = ((col.A * intensity) >> 8) + ((dst->A * invIntensity) >> 8);
dst[3] = intensity + ((dst[3] * invIntensity) >> 8); dst->A = intensity + ((dst->A * invIntensity) >> 8);
src++; dst += BITMAP_SIZEOF_PIXEL; src++; dst++;
} }
} }

View File

@ -2,6 +2,7 @@
#define CC_PLATFORM_H #define CC_PLATFORM_H
#include "Utils.h" #include "Utils.h"
#include "PackedCol.h" #include "PackedCol.h"
#include "Bitmap.h"
/* Abstracts platform specific memory management, I/O, etc. /* Abstracts platform specific memory management, I/O, etc.
Copyright 2017 ClassicalSharp | Licensed under BSD-3 Copyright 2017 ClassicalSharp | Licensed under BSD-3
*/ */
@ -176,7 +177,7 @@ CC_EXPORT void Font_Free(FontDesc* desc);
/* Measures dimensions of the given text, if it was drawn with the given font. */ /* Measures dimensions of the given text, if it was drawn with the given font. */
CC_EXPORT Size2D Platform_TextMeasure(struct DrawTextArgs* args); CC_EXPORT Size2D Platform_TextMeasure(struct DrawTextArgs* args);
/* Draws the given text with the given font onto the given bitmap. */ /* Draws the given text with the given font onto the given bitmap. */
CC_EXPORT Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, PackedCol col); CC_EXPORT Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, BitmapCol col);
/* Allocates a new socket. */ /* Allocates a new socket. */
void Socket_Create(SocketPtr* socket); void Socket_Create(SocketPtr* socket);

View File

@ -1,5 +1,4 @@
#include "TerrainAtlas.h" #include "TerrainAtlas.h"
#include "Bitmap.h"
#include "Block.h" #include "Block.h"
#include "ExtMath.h" #include "ExtMath.h"
#include "Funcs.h" #include "Funcs.h"

View File

@ -1,6 +1,6 @@
#ifndef CC_TERRAINATLAS_H #ifndef CC_TERRAINATLAS_H
#define CC_TERRAINATLAS_H #define CC_TERRAINATLAS_H
#include "Core.h" #include "Bitmap.h"
/* Represents the 2D texture atlas of terrain.png, and converted into an array of 1D textures. /* Represents the 2D texture atlas of terrain.png, and converted into an array of 1D textures.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/ */

View File

@ -154,14 +154,13 @@ int Utils_AccumulateWheelDelta(float* accumulator, float delta) {
} }
uint8_t Utils_GetSkinType(const Bitmap* bmp) { uint8_t Utils_GetSkinType(const Bitmap* bmp) {
int scale;
if (bmp->Width == bmp->Height * 2) return SKIN_64x32; if (bmp->Width == bmp->Height * 2) return SKIN_64x32;
if (bmp->Width != bmp->Height) return SKIN_INVALID; if (bmp->Width != bmp->Height) return SKIN_INVALID;
/* Minecraft alex skins have this particular pixel with alpha of 0 */ /* Minecraft alex skins have this particular pixel with alpha of 0 */
int scale = bmp->Width / 64; scale = bmp->Width / 64;
uint32_t pixel = Bitmap_GetPixel(bmp, 54 * scale, 20 * scale); return Bitmap_GetPixel(bmp, 54 * scale, 20 * scale).A >= 127 ? SKIN_64x64 : SKIN_64x64_SLIM;
uint8_t alpha = PackedCol_ARGB_A(pixel);
return alpha >= 127 ? SKIN_64x64 : SKIN_64x64_SLIM;
} }
uint32_t Utils_CRC32(const uint8_t* data, uint32_t length) { uint32_t Utils_CRC32(const uint8_t* data, uint32_t length) {

View File

@ -1,6 +1,7 @@
#ifndef CC_UTILS_H #ifndef CC_UTILS_H
#define CC_UTILS_H #define CC_UTILS_H
#include "String.h" #include "String.h"
#include "Bitmap.h"
/* Implements various utility functions. /* Implements various utility functions.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/ */

View File

@ -925,6 +925,7 @@ static char InputWidget_GetLastCol(struct InputWidget* w, int x, int y) {
} }
static void InputWidget_UpdateCaret(struct InputWidget* w) { static void InputWidget_UpdateCaret(struct InputWidget* w) {
BitmapCol col;
String line; char lineBuffer[STRING_SIZE]; String line; char lineBuffer[STRING_SIZE];
struct DrawTextArgs args; struct DrawTextArgs args;
int maxChars, lineWidth; int maxChars, lineWidth;
@ -961,7 +962,9 @@ static void InputWidget_UpdateCaret(struct InputWidget* w) {
colCode = InputWidget_GetLastCol(w, w->CaretX, w->CaretY); colCode = InputWidget_GetLastCol(w, w->CaretX, w->CaretY);
if (colCode) { if (colCode) {
w->CaretCol = Drawer2D_GetCol(colCode); col = Drawer2D_GetCol(colCode);
w->CaretCol.B = col.B; w->CaretCol.G = col.G;
w->CaretCol.R = col.R; w->CaretCol.A = col.A;
} else { } else {
PackedCol white = PACKEDCOL_WHITE; PackedCol white = PACKEDCOL_WHITE;
w->CaretCol = PackedCol_Scale(white, 0.8f); w->CaretCol = PackedCol_Scale(white, 0.8f);
@ -2725,9 +2728,9 @@ static Size2D SpecialInputWidget_MeasureTitles(struct SpecialInputWidget* w) {
} }
static void SpecialInputWidget_DrawTitles(struct SpecialInputWidget* w, Bitmap* bmp) { static void SpecialInputWidget_DrawTitles(struct SpecialInputWidget* w, Bitmap* bmp) {
PackedCol col_selected = PACKEDCOL_CONST(30, 30, 30, 200); BitmapCol col_selected = BITMAPCOL_CONST(30, 30, 30, 200);
PackedCol col_inactive = PACKEDCOL_CONST( 0, 0, 0, 127); BitmapCol col_inactive = BITMAPCOL_CONST( 0, 0, 0, 127);
PackedCol col; BitmapCol col;
struct DrawTextArgs args; struct DrawTextArgs args;
Size2D size; Size2D size;
@ -2788,7 +2791,7 @@ static void SpecialInputWidget_DrawContent(struct SpecialInputWidget* w, struct
} }
static void SpecialInputWidget_Make(struct SpecialInputWidget* w, struct SpecialInputTab* tab) { static void SpecialInputWidget_Make(struct SpecialInputWidget* w, struct SpecialInputTab* tab) {
PackedCol col = PACKEDCOL_CONST(30, 30, 30, 200); BitmapCol col = PACKEDCOL_CONST(30, 30, 30, 200);
Size2D size, titles, content; Size2D size, titles, content;
Bitmap bmp; Bitmap bmp;