Permalink
Browse files

Fix crashing with some system fonts, minor code cleanup

  • Loading branch information...
UnknownShadow200 committed Jan 4, 2019
1 parent 0b3b200 commit 015b72b1eca7281ddc0adad1983798e492543904
Showing with 75 additions and 42 deletions.
  1. +3 −5 src/Bitmap.c
  2. +14 −2 src/Bitmap.h
  3. +6 −6 src/Block.c
  4. +3 −3 src/Block.h
  5. +3 −4 src/Deflate.h
  6. +2 −1 src/EntityComponents.c
  7. +2 −1 src/Game.h
  8. +4 −3 src/Graphics.c
  9. +5 −0 src/Gui.h
  10. +3 −0 src/IsometricDrawer.h
  11. +1 −1 src/LWeb.c
  12. +1 −1 src/Logger.c
  13. +5 −5 src/Model.h
  14. +19 −6 src/Platform.c
  15. +1 −1 src/Resources.c
  16. +3 −3 src/TexturePack.c
@@ -15,10 +15,6 @@ BitmapCol BitmapCol_Scale(BitmapCol value, float t) {
return value;
}

void Bitmap_Create(Bitmap* bmp, int width, int height, uint8_t* scan0) {
bmp->Width = width; bmp->Height = height; bmp->Scan0 = scan0;
}

void Bitmap_CopyBlock(int srcX, int srcY, int dstX, int dstY, Bitmap* src, Bitmap* dst, int size) {
int x, y;
for (y = 0; y < size; y++) {
@@ -350,7 +346,9 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
struct Stream compStream, datStream;
struct ZLibHeader zlibHeader;

Bitmap_Create(bmp, 0, 0, NULL);
bmp->Width = 0; bmp->Height = 0;
bmp->Scan0 = NULL;

res = Stream_Read(stream, tmp, PNG_SIG_SIZE);
if (res) return res;
if (!Png_Detect(tmp, PNG_SIG_SIZE)) return PNG_ERR_INVALID_SIG;
@@ -14,20 +14,32 @@ typedef CC_ALIGN_HINT(4) struct BitmapCol_ {
/* Unioned with Packed member for efficient equality comparison */
typedef union BitmapColUnion_ { BitmapCol C; uint32_t Raw; } BitmapColUnion;

/* Scales RGB of the given colour. */
BitmapCol BitmapCol_Scale(BitmapCol value, float t);

/* A 2D array of BitmapCol pixels */
typedef struct Bitmap_ { uint8_t* Scan0; int Width, Height; } Bitmap;

#define PNG_MAX_DIMS 0x8000
#define BITMAPCOL_CONST(r, g, b, a) { b, g, r, a }

/* Returns number of bytes a bitmap consumes. */
#define Bitmap_DataSize(width, height) ((uint32_t)(width) * (uint32_t)(height) * 4)
/* Gets the yth row of a bitmap as raw uint32_t* 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) ((uint32_t*)(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. */
/* NOTE: Does NOT check coordinates are inside the bitmap. */
#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);
/* Initialises a bitmap instance. */
#define Bitmap_Init(bmp, width, height, scan0) bmp.Width = width; bmp.Height = height; bmp.Scan0 = scan0;
/* Copies a rectangle of pixels from one bitmap to another. */
/* NOTE: If src and dst are the same, src and dst rectangles MUST NOT overlap. */
/* NOTE: Rectangles are NOT checked for whether they lie inside the bitmaps. */
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. */
/* NOTE: You are responsible for freeing its memory! */
@@ -129,17 +129,17 @@ static uint32_t Block_DefinedCustomBlocks[BLOCK_COUNT >> 5];
static char Block_NamesBuffer[STRING_SIZE * BLOCK_COUNT];
#define Block_NamePtr(i) &Block_NamesBuffer[STRING_SIZE * i]

static uint8_t Block_TopTex[BLOCK_CPE_COUNT] = { 0, 1, 0, 2, 16, 4, 15,
const static uint8_t topTex[BLOCK_CPE_COUNT] = { 0, 1, 0, 2, 16, 4, 15,
17, 14, 14, 30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 24, 23, 6, 6, 7, 9,
4, 36, 37, 16, 11, 25, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 26, 53, 52 };

static uint8_t Block_SideTex[BLOCK_CPE_COUNT] = { 0, 1, 3, 2, 16, 4, 15,
const static uint8_t sideTex[BLOCK_CPE_COUNT] = { 0, 1, 3, 2, 16, 4, 15,
17, 14, 14, 30, 30, 18, 19, 32, 33, 34, 20, 22, 48, 49, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 40, 39, 5, 5, 7, 8,
35, 36, 37, 16, 11, 41, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 42, 53, 52 };

static uint8_t Block_BottomTex[BLOCK_CPE_COUNT] = { 0, 1, 2, 2, 16, 4, 15,
const static uint8_t bottomTex[BLOCK_CPE_COUNT] = { 0, 1, 2, 2, 16, 4, 15,
17, 14, 14, 30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 56, 55, 6, 6, 7, 10,
4, 36, 37, 16, 11, 57, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 58, 53, 52 };
@@ -267,9 +267,9 @@ void Block_ResetProps(BlockID block) {
Block_SetTex(0, FACE_YMIN, block);
Block_SetSide(0, block);
} else {
Block_SetTex(Block_TopTex[block], FACE_YMAX, block);
Block_SetTex(Block_BottomTex[block], FACE_YMIN, block);
Block_SetSide(Block_SideTex[block], block);
Block_SetTex(topTex[block], FACE_YMAX, block);
Block_SetTex(bottomTex[block], FACE_YMIN, block);
Block_SetSide(sideTex[block], block);
}
}

@@ -64,11 +64,11 @@ extern struct _BlockLists {
/* e.g. a block with Min.X of 0.0 uses light colour at X-1,Y,Z for XMIN face. */
/* e.g. a block with Min.X of 0.1 uses light colour at X,Y,Z for XMIN face. */
uint8_t LightOffset[BLOCK_COUNT];
/* Draw method used when rendering this block. */
/* Draw method used when rendering this block. See DrawType enum. */
uint8_t Draw[BLOCK_COUNT];
/* Sound produced when the player manually destroys this block. */
/* Sound played when the player manually destroys this block. See SoundType enum. */
uint8_t DigSounds[BLOCK_COUNT];
/* Sound produced when the player walks on this block. */
/* Sound played when the player walks on this block. See SoundType enum. */
uint8_t StepSounds[BLOCK_COUNT];
/* Whether fog colour is used to apply a tint effect to this block. */
bool Tinted[BLOCK_COUNT];
@@ -41,8 +41,8 @@ struct HuffmanTable {
struct InflateState {
uint8_t State;
bool LastBlock; /* Whether the last DEFLATE block has been encounted in the stream */
uint32_t Bits; /* Holds bits across byte boundaries*/
uint32_t NumBits; /* Number of bits in Bits buffer*/
uint32_t Bits; /* Holds bits across byte boundaries */
uint32_t NumBits; /* Number of bits in Bits buffer */

uint8_t* NextIn; /* Pointer within Input buffer to next byte that can be read */
uint32_t AvailIn; /* Max number of bytes that can be read from Input buffer */
@@ -68,7 +68,7 @@ struct InflateState {
/* Initialises DEFLATE decompressor state to defaults. */
CC_API void Inflate_Init(struct InflateState* state, struct Stream* source);
/* Attempts to decompress as much of the currently pending data as possible. */
/* NOTE: This is a low level call - usually you should use Inflate_MakeStream. */
/* NOTE: This is a low level call - usually you treat as a stream via Inflate_MakeStream. */
void Inflate_Process(struct InflateState* state);
/* Deompresses input data read from another stream using DEFLATE. Read only stream. */
/* NOTE: This only uncompresses pure DEFLATE compressed data. */
@@ -119,7 +119,6 @@ struct ZipState {
/* Source of the .zip archive data. Must be seekable. */
struct Stream* Input;
/* Callback function to process the data in a .zip archive entry. */
/* obj is user specified in state.Obj variable */
/* Return non-zero to indicate an error and stop further processing. */
/* NOTE: data stream MAY NOT be seekable. (i.e. entry data might be compressed) */
ReturnCode (*ProcessEntry)(const String* path, struct Stream* data, struct ZipState* state);
@@ -608,10 +608,11 @@ static void ShadowComponent_MakeTex(void) {
BitmapCol outPix = BITMAPCOL_CONST(0, 0, 0, 0);
Bitmap bmp;
uint32_t x, y;
Bitmap_Create(&bmp, sh_size, sh_size, pixels);

Bitmap_Init(bmp, sh_size, sh_size, pixels);
for (y = 0; y < sh_size; y++) {
BitmapCol* row = Bitmap_GetRow(&bmp, y);

for (x = 0; x < sh_size; x++) {
double dist =
(sh_half - (x + 0.5)) * (sh_half - (x + 0.5)) +
@@ -79,7 +79,8 @@ bool Game_CanPick(BlockID block);
bool Game_UpdateTexture(GfxResourceID* texId, struct Stream* src, const String* file, uint8_t* skinType);
/* Checks that the given bitmap can be loaded into a native gfx texture. */
/* (must be power of two size and be <= Gfx_MaxTexWidth/Gfx_MaxHeight) */
bool Game_ValidateBitmap(const String* file, Bitmap* bmp);/* Calculates Game_Width and Game_Height. */
bool Game_ValidateBitmap(const String* file, Bitmap* bmp);
/* Updates Game_Width and Game_Height. */
void Game_UpdateClientSize(void);
/* Sets the strategy/method used to limit frames per second. */
void Game_SetFpsLimit(enum FpsLimit method);
@@ -460,7 +460,7 @@ static void D3D9_DoMipmaps(IDirect3DTexture9* texture, int x, int y, Bitmap* bmp
cur = Mem_Alloc(width * height, 4, "mipmaps");
Gfx_GenMipmaps(width, height, cur, prev);

Bitmap_Create(&mipmap, width, height, cur);
Bitmap_Init(mipmap, width, height, cur);
if (partial) {
D3D9_SetTexturePartData(texture, x, y, &mipmap, lvl);
} else {
@@ -863,6 +863,7 @@ void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar,
ReturnCode Gfx_TakeScreenshot(struct Stream* output, int width, int height) {
IDirect3DSurface9* backbuffer = NULL;
IDirect3DSurface9* temp = NULL;
Bitmap bmp;
ReturnCode res;

res = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
@@ -875,8 +876,8 @@ ReturnCode Gfx_TakeScreenshot(struct Stream* output, int width, int height) {
D3DLOCKED_RECT rect;
res = IDirect3DSurface9_LockRect(temp, &rect, NULL, D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE);
if (res) goto finished;
{
Bitmap bmp; Bitmap_Create(&bmp, width, height, rect.pBits);
{
Bitmap_Init(bmp, width, height, rect.pBits);
res = Png_Encode(&bmp, output, NULL, false);
if (res) { IDirect3DSurface9_UnlockRect(temp); goto finished; }
}
@@ -86,6 +86,7 @@ struct WidgetVTABLE {
struct Widget { Widget_Layout };
void Widget_SetLocation(void* widget, uint8_t horAnchor, uint8_t verAnchor, int xOffset, int yOffset);
void Widget_CalcPosition(void* widget);
/* Resets Widget struct fields to 0/NULL (except VTABLE) */
void Widget_Reset(void* widget);
/* Whether the given point is located within the bounds of the widget. */
bool Widget_Contains(void* widget, int x, int y);
@@ -99,6 +100,7 @@ extern struct Screen* Gui_Overlays[GUI_MAX_OVERLAYS];
extern int Gui_OverlaysCount;

int Gui_CalcPos(uint8_t anchor, int offset, int size, int axisLen);
/* Returns whether the given rectangle contains the given point. */
bool Gui_Contains(int recX, int recY, int width, int height, int x, int y);
/* Gets the screen that the user is currently interacting with. */
/* This means if an overlay is active, it will be over the top of other screens. */
@@ -107,7 +109,10 @@ struct Screen* Gui_GetActiveScreen(void);
/* This means if an overlay is active, the screen under it is returned. */
struct Screen* Gui_GetUnderlyingScreen(void);

/* Frees the active screen if it is not NULL. */
/* NOTE: You should usually use Gui_CloseActive instead. */
CC_NOINLINE void Gui_FreeActive(void);
/* Sets the active screen/menu that the user interacts with. */
/* NOTE: This doesn't free old active screen - must call Gui_FreeActive() first */
CC_NOINLINE void Gui_SetActive(struct Screen* screen);
/* NOTE: Same as Gui_FreeActive(); Gui_SetActive(NULL); */
@@ -7,7 +7,10 @@

/* Maximum number of vertices used to draw a block in isometric way. */
#define ISOMETRICDRAWER_MAXVERTICES 16
/* Sets up state to begin drawing blocks isometrically. */
void IsometricDrawer_BeginBatch(VertexP3fT2fC4b* vertices, GfxResourceID vb);
/* Buffers the vertices needed to draw the given block at the given position. */
void IsometricDrawer_DrawBatch(BlockID block, float size, float x, float y);
/* Flushes buffered vertices to the GPU, then restores state. */
void IsometricDrawer_EndBatch(void);
#endif
@@ -590,7 +590,7 @@ void FetchFlagsTask_Add(const String* name) {
}
FetchFlagsTask_Ensure();

Bitmap_Create(&flags[flagsCount].Bmp, 0, 0, NULL);
Bitmap_Init(flags[flagsCount].Bmp, 0, 0, NULL);
String_InitArray(flags[flagsCount].Name, flags[flagsCount]._nameBuffer);

/* classicube.net only works with lowercase flag urls */
@@ -198,7 +198,7 @@ static LONG WINAPI Logger_UnhandledFilter(struct _EXCEPTION_POINTERS* pInfo) {
}

void Logger_Hook(void) {
SetUnhandledExceptionFilter(Logger_UnhandledFilter);
//SetUnhandledExceptionFilter(Logger_UnhandledFilter);
}

/* Don't want compiler doing anything fancy with registers */
@@ -146,7 +146,7 @@ let SW = sides width, BW = body width, BH = body height
|H--------tex---------H|H--------tex---------H|H--------tex---------H|H--------tex---------H|
|----------SW----------|----------BW----------|----------SW----------|----------BW----------|
********************************************************************************************* */
void BoxDesc_BuildBox(struct ModelPart* part, const struct BoxDesc* desc);
CC_API void BoxDesc_BuildBox(struct ModelPart* part, const struct BoxDesc* desc);

/* Builds a box model assuming the follow texture layout:
let SW = sides width, BW = body width, BH = body height
@@ -161,9 +161,9 @@ let SW = sides width, BW = body width, BH = body height
|H--------tex---------H|H--------tex---------H|H--------tex---------H|H--------tex---------H|
|----------SW----------|----------BW----------|----------BW----------|----------------------|
********************************************************************************************* */
void BoxDesc_BuildRotatedBox(struct ModelPart* part, const struct BoxDesc* desc);
CC_API void BoxDesc_BuildRotatedBox(struct ModelPart* part, const struct BoxDesc* desc);

void BoxDesc_XQuad(struct Model* m, int texX, int texY, int texWidth, int texHeight, float z1, float z2, float y1, float y2, float x, bool swapU);
void BoxDesc_YQuad(struct Model* m, int texX, int texY, int texWidth, int texHeight, float x1, float x2, float z1, float z2, float y, bool swapU);
void BoxDesc_ZQuad(struct Model* m, int texX, int texY, int texWidth, int texHeight, float x1, float x2, float y1, float y2, float z, bool swapU);
CC_API void BoxDesc_XQuad(struct Model* m, int texX, int texY, int texWidth, int texHeight, float z1, float z2, float y1, float y2, float x, bool swapU);
CC_API void BoxDesc_YQuad(struct Model* m, int texX, int texY, int texWidth, int texHeight, float x1, float x2, float z1, float z2, float y, bool swapU);
CC_API void BoxDesc_ZQuad(struct Model* m, int texX, int texY, int texWidth, int texHeight, float x1, float x2, float y1, float y2, float z, bool swapU);
#endif
@@ -1063,16 +1063,23 @@ int Platform_TextWidth(struct DrawTextArgs* args) {
FT_Face face = data->face;
String text = args->Text;
int i, width = 0, charWidth;
FT_Error res;
Codepoint cp;

for (i = 0; i < text.length; i++) {
charWidth = data->widths[(uint8_t)text.buffer[i]];
/* need to calculate glyph width */
if (charWidth == UInt16_MaxValue) {
cp = Convert_CP437ToUnicode(text.buffer[i]);
FT_Load_Char(face, cp, 0); /* TODO: Check error */
cp = Convert_CP437ToUnicode(text.buffer[i]);
res = FT_Load_Char(face, cp, 0); /* TODO: Check error */

if (res) {
Platform_Log2("Error %i measuring width of %r", &res, &text.buffer[i]);
charWidth = 0;
} else {
charWidth = face->glyph->advance.x;
}

charWidth = face->glyph->advance.x;
data->widths[(uint8_t)text.buffer[i]] = charWidth;
}
width += charWidth;
@@ -1144,6 +1151,7 @@ int Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, Bitm
FT_BitmapGlyph glyph;
FT_Bitmap* img;
int i, offset;
FT_Error res;
Codepoint cp;

height = TEXT_CEIL(face->size->metrics.height);
@@ -1152,10 +1160,15 @@ int Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, Bitm
for (i = 0; i < text.length; i++) {
glyph = data->glyphs[(uint8_t)text.buffer[i]];
if (!glyph) {
cp = Convert_CP437ToUnicode(text.buffer[i]);
FT_Load_Char(face, cp, FT_LOAD_RENDER); /* TODO: Check error */
cp = Convert_CP437ToUnicode(text.buffer[i]);
res = FT_Load_Char(face, cp, FT_LOAD_RENDER);

if (res) {
Platform_Log2("Error %i drawing %r", &res, &text.buffer[i]);
continue;
}

FT_Get_Glyph(face->glyph, &glyph);
FT_Get_Glyph(face->glyph, &glyph); /* TODO: Check error */
data->glyphs[(uint8_t)text.buffer[i]] = glyph;
}

@@ -455,7 +455,7 @@ static ReturnCode ModernPatcher_MakeAnimations(struct Stream* s, struct Stream*
int i;

if ((res = Png_Decode(&bmp, data))) return res;
Bitmap_Create(&anim, 512, 16, anim_data);
Bitmap_Init(anim, 512, 16, anim_data);

for (i = 0; i < 512; i += 16) {
Bitmap_CopyBlock(0, i, i, 0, &bmp, &anim, 16);
@@ -234,7 +234,7 @@ static void Animations_Draw(struct AnimationData* data, TextureLoc texLoc, int s
if (size > ANIMS_FAST_SIZE) {
ptr = Mem_Alloc(size * size, 4, "anim frame");
}
Bitmap_Create(&frame, size, size, ptr);
Bitmap_Init(frame, size, size, ptr);

if (!data) {
if (texLoc == 30) {
@@ -425,7 +425,7 @@ static void Atlas_Convert2DTo1D(void) {
atlasY = Atlas2D_TileY(tile) * tileSize;

Bitmap_CopyBlock(atlasX, atlasY, 0, y * tileSize,
&Atlas_Bitmap, &atlas1D, tileSize);
&Atlas_Bitmap, &atlas1D, tileSize);
}
Atlas1D_TexIds[i] = Gfx_CreateTexture(&atlas1D, true, Gfx_Mipmaps);
}
@@ -479,7 +479,7 @@ GfxResourceID Atlas_LoadTile(TextureLoc texLoc) {
Mem_Free(tile.Scan0);
return texId;
} else {
Bitmap_Create(&tile, tileSize, tileSize, scan0);
Bitmap_Init(tile, tileSize, tileSize, scan0);
return Atlas_LoadTile_Raw(texLoc, &tile);
}
}

0 comments on commit 015b72b

Please sign in to comment.