mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-24 18:13:15 -05:00
C client: Fix immediately crashing in Release mode when compiled with MSVC
This commit is contained in:
parent
3d511f7c89
commit
b0380c5994
5 changed files with 74 additions and 187 deletions
107
src/Platform.c
107
src/Platform.c
|
@ -710,6 +710,53 @@ static void Font_Init(void);
|
|||
#define DPI_PIXEL 72
|
||||
#define DPI_DEVICE 96 /* TODO: GetDeviceCaps(hdc, LOGPIXELSY) in Platform_InitDisplay ? */
|
||||
|
||||
|
||||
static unsigned long Font_ReadWrapper(FT_Stream s, unsigned long offset, unsigned char* buffer, unsigned long count) {
|
||||
if (!count && offset > s->size) return 1;
|
||||
struct Stream* stream = s->descriptor.pointer;
|
||||
if (s->pos != offset) stream->Seek(stream, offset);
|
||||
|
||||
ReturnCode res = Stream_Read(stream, buffer, count);
|
||||
return res ? 0 : count;
|
||||
}
|
||||
|
||||
static void Font_CloseWrapper(FT_Stream s) {
|
||||
struct Stream* stream = s->descriptor.pointer;
|
||||
struct Stream* source = stream->Meta.Buffered.Source;
|
||||
|
||||
/* Close the actual file stream */
|
||||
source->Close(source);
|
||||
Mem_Free(s->descriptor.pointer);
|
||||
}
|
||||
|
||||
static bool Font_MakeArgs(const String* path, FT_Stream stream, FT_Open_Args* args) {
|
||||
void* file;
|
||||
if (File_Open(&file, path)) return false;
|
||||
|
||||
uint32_t size;
|
||||
if (File_Length(file, &size)) { File_Close(file); return false; }
|
||||
stream->size = size;
|
||||
|
||||
struct Stream* data = Mem_Alloc(1, sizeof(struct Stream) * 2 + 8192, "Font_MakeArgs");
|
||||
struct Stream* wrapper = &data[0];
|
||||
struct Stream* fileSrm = &data[1];
|
||||
|
||||
/* TODO: Increase buffer size to 8192, better Seek impl (want 11,000 I/O reads) */
|
||||
uint8_t* buffer = (uint8_t*)&data[2];
|
||||
Stream_FromFile(fileSrm, file);
|
||||
Stream_ReadonlyBuffered(wrapper, fileSrm, buffer, 8192);
|
||||
|
||||
stream->descriptor.pointer = data;
|
||||
stream->memory = &ft_mem;
|
||||
stream->read = Font_ReadWrapper;
|
||||
stream->close = Font_CloseWrapper;
|
||||
|
||||
args->flags = FT_OPEN_STREAM;
|
||||
args->pathname = NULL;
|
||||
args->stream = stream;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int Font_Find(const String* name, StringsBuffer* entries) {
|
||||
int i;
|
||||
for (i = 1; i < entries->Count; i += 2) {
|
||||
|
@ -742,15 +789,16 @@ void Font_Make(FontDesc* desc, const String* fontName, int size, int style) {
|
|||
entries = &norm_fonts;
|
||||
idx = Font_Find(fontName, entries);
|
||||
}
|
||||
|
||||
if (idx == -1) ErrorHandler_Fail("Unknown font");
|
||||
|
||||
char pathBuffer[FILENAME_SIZE + 1];
|
||||
String path = String_NT_Array(pathBuffer);
|
||||
StringsBuffer_Get(entries, idx - 1, &path);
|
||||
path.buffer[path.length] = '\0';
|
||||
String path = StringsBuffer_UNSAFE_Get(entries, idx - 1, &path);
|
||||
|
||||
FT_Stream stream = Mem_AllocCleared(1, sizeof(FT_StreamRec), "leaky font"); /* TODO: LEAKS MEMORY!!! */
|
||||
FT_Open_Args args;
|
||||
if (!Font_MakeArgs(&path, stream, &args)) return;
|
||||
|
||||
FT_Face face;
|
||||
FT_Error err = FT_New_Face(ft_lib, path.buffer, 0, &face);
|
||||
FT_Error err = FT_Open_Face(ft_lib, &args, 0, &face);
|
||||
if (err) ErrorHandler_Fail2(err, "Creating font failed");
|
||||
desc->Handle = face;
|
||||
|
||||
|
@ -790,53 +838,6 @@ static void Font_Add(const String* path, FT_Face face, StringsBuffer* entries, c
|
|||
StringsBuffer_Add(entries, &name);
|
||||
}
|
||||
|
||||
static unsigned long Font_ReadWrapper(FT_Stream s, unsigned long offset, unsigned char* buffer, unsigned long count) {
|
||||
if (!count && offset > s->size) return 1;
|
||||
struct Stream* stream = s->descriptor.pointer;
|
||||
if (s->pos != offset) stream->Seek(stream, offset);
|
||||
|
||||
ReturnCode res = Stream_Read(stream, buffer, count);
|
||||
return res ? 0 : count;
|
||||
}
|
||||
|
||||
static void Font_CloseWrapper(FT_Stream s) {
|
||||
struct Stream* stream = s->descriptor.pointer;
|
||||
struct Stream* source = stream->Meta.Buffered.Source;
|
||||
|
||||
/* Close the actual file stream */
|
||||
source->Close(source);
|
||||
/* And free up everything */
|
||||
Mem_Free(s->descriptor.pointer);
|
||||
}
|
||||
|
||||
static bool Font_MakeArgs(const String* path, FT_Stream stream, FT_Open_Args* args) {
|
||||
void* file;
|
||||
if (File_Open(&file, path)) return false;
|
||||
|
||||
uint32_t size;
|
||||
if (File_Length(file, &size)) { stream->close(stream); return false; }
|
||||
stream->size = size;
|
||||
|
||||
struct Stream* data = Mem_Alloc(1, sizeof(struct Stream) * 2 + 4096, "Font_MakeArgs");
|
||||
struct Stream* wrapper = &data[0];
|
||||
struct Stream* fileSrm = &data[1];
|
||||
|
||||
/* TODO: Increase buffer size to 4096, better Seek impl (want 11,000 I/O reads) */
|
||||
uint8_t* buffer = (uint8_t*)&data[2];
|
||||
Stream_FromFile(fileSrm, file);
|
||||
Stream_ReadonlyBuffered(wrapper, fileSrm, buffer, 4096);
|
||||
|
||||
stream->descriptor.pointer = data;
|
||||
stream->memory = &ft_mem;
|
||||
stream->read = Font_ReadWrapper;
|
||||
stream->close = Font_CloseWrapper;
|
||||
|
||||
args->flags = FT_OPEN_STREAM;
|
||||
args->pathname = NULL;
|
||||
args->stream = stream;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Font_DirCallback(const String* path, void* obj) {
|
||||
FT_StreamRec stream = { 0 };
|
||||
FT_Open_Args args;
|
||||
|
|
24
src/Stream.c
24
src/Stream.c
|
@ -255,13 +255,14 @@ static ReturnCode Stream_BufferedRead(struct Stream* s, uint8_t* data, uint32_t
|
|||
|
||||
ReturnCode res = source->Read(source, s->Meta.Buffered.Cur, s->Meta.Buffered.Length, &read);
|
||||
if (res) return res;
|
||||
s->Meta.Mem.Left = read;
|
||||
s->Meta.Buffered.Left = read;
|
||||
s->Meta.Buffered.End += read;
|
||||
}
|
||||
|
||||
count = min(count, s->Meta.Buffered.Left);
|
||||
Mem_Copy(data, s->Meta.Buffered.Cur, count);
|
||||
|
||||
s->Meta.Buffered.Cur += count; s->Meta.Mem.Left -= count;
|
||||
s->Meta.Buffered.Cur += count; s->Meta.Buffered.Left -= count;
|
||||
*modified = count;
|
||||
return 0;
|
||||
}
|
||||
|
@ -276,11 +277,23 @@ static ReturnCode Stream_BufferedReadU8(struct Stream* s, uint8_t* data) {
|
|||
}
|
||||
|
||||
static ReturnCode Stream_BufferedSeek(struct Stream* s, uint32_t position) {
|
||||
/* Check if seek position is within cached buffer */
|
||||
uint32_t length = s->Meta.Buffered.Left + (uint32_t)(s->Meta.Buffered.Cur - s->Meta.Buffered.Base);
|
||||
uint32_t start = s->Meta.Buffered.End - length;
|
||||
|
||||
if (position >= start && position < start + length) {
|
||||
uint32_t offset = position - start;
|
||||
s->Meta.Buffered.Cur = s->Meta.Buffered.Base + offset;
|
||||
s->Meta.Buffered.Left = length - offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Stream* source = s->Meta.Buffered.Source;
|
||||
ReturnCode res = source->Seek(source, position);
|
||||
|
||||
if (res) return res;
|
||||
s->Meta.Buffered.Left = 0;
|
||||
s->Meta.Buffered.End = position;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -288,12 +301,13 @@ void Stream_ReadonlyBuffered(struct Stream* s, struct Stream* source, void* data
|
|||
Stream_Init(s);
|
||||
s->Read = Stream_BufferedRead;
|
||||
s->ReadU8 = Stream_BufferedReadU8;
|
||||
s->Seek = Stream_BufferedSeek; /* TODO: Try to reuse buffered cache */
|
||||
s->Seek = Stream_BufferedSeek;
|
||||
|
||||
s->Meta.Buffered.Cur = data;
|
||||
s->Meta.Buffered.Left = 0;
|
||||
s->Meta.Buffered.Length = size;
|
||||
s->Meta.Buffered.End = 0;
|
||||
s->Meta.Buffered.Cur = data;
|
||||
s->Meta.Buffered.Base = data;
|
||||
s->Meta.Buffered.Length = size;
|
||||
s->Meta.Buffered.Source = source;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ struct Stream {
|
|||
/* NOTE: These structs rely on overlapping Meta_Mem fields being the same! Don't change them */
|
||||
struct { uint8_t* Cur; uint32_t Left, Length; uint8_t* Base; } Mem;
|
||||
struct { struct Stream* Source; uint32_t Left, Length; } Portion;
|
||||
struct { uint8_t* Cur; uint32_t Left, Length; uint8_t* Base; struct Stream* Source; } Buffered;
|
||||
struct { uint8_t* Cur; uint32_t Left, Length; uint8_t* Base; struct Stream* Source; uint32_t End; } Buffered;
|
||||
struct { uint8_t* Cur; uint32_t Left, Last; uint8_t* Base; struct Stream* Source; } Ogg;
|
||||
struct { struct Stream* Source; uint32_t CRC32; } CRC32;
|
||||
} Meta;
|
||||
|
|
|
@ -2092,79 +2092,6 @@ FT_BEGIN_HEADER
|
|||
} FT_Open_Args;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FT_New_Face */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Call @FT_Open_Face to open a font by its pathname. */
|
||||
/* */
|
||||
/* <InOut> */
|
||||
/* library :: A handle to the library resource. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* pathname :: A path to the font file. */
|
||||
/* */
|
||||
/* face_index :: See @FT_Open_Face for a detailed description of this */
|
||||
/* parameter. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* aface :: A handle to a new face object. If `face_index' is */
|
||||
/* greater than or equal to zero, it must be non-NULL. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0~means success. */
|
||||
/* */
|
||||
/* <Note> */
|
||||
/* Use @FT_Done_Face to destroy the created @FT_Face object (along */
|
||||
/* with its slot and sizes). */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_New_Face( FT_Library library,
|
||||
const char* filepathname,
|
||||
FT_Long face_index,
|
||||
FT_Face *aface );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* FT_New_Memory_Face */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Call @FT_Open_Face to open a font that has been loaded into */
|
||||
/* memory. */
|
||||
/* */
|
||||
/* <InOut> */
|
||||
/* library :: A handle to the library resource. */
|
||||
/* */
|
||||
/* <Input> */
|
||||
/* file_base :: A pointer to the beginning of the font data. */
|
||||
/* */
|
||||
/* file_size :: The size of the memory chunk used by the font data. */
|
||||
/* */
|
||||
/* face_index :: See @FT_Open_Face for a detailed description of this */
|
||||
/* parameter. */
|
||||
/* */
|
||||
/* <Output> */
|
||||
/* aface :: A handle to a new face object. If `face_index' is */
|
||||
/* greater than or equal to zero, it must be non-NULL. */
|
||||
/* */
|
||||
/* <Return> */
|
||||
/* FreeType error code. 0~means success. */
|
||||
/* */
|
||||
/* <Note> */
|
||||
/* You must not deallocate the memory before calling @FT_Done_Face. */
|
||||
/* */
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_New_Memory_Face( FT_Library library,
|
||||
const FT_Byte* file_base,
|
||||
FT_Long file_size,
|
||||
FT_Long face_index,
|
||||
FT_Face *aface );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
|
|
|
@ -1395,61 +1395,6 @@
|
|||
}
|
||||
|
||||
|
||||
/* there's a Mac-specific extended implementation of FT_New_Face() */
|
||||
/* in src/base/ftmac.c */
|
||||
|
||||
#ifndef FT_MACINTOSH
|
||||
|
||||
/* documentation is in freetype.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_New_Face( FT_Library library,
|
||||
const char* pathname,
|
||||
FT_Long face_index,
|
||||
FT_Face *aface )
|
||||
{
|
||||
FT_Open_Args args;
|
||||
|
||||
|
||||
/* test for valid `library' and `aface' delayed to `FT_Open_Face' */
|
||||
if ( !pathname )
|
||||
return FT_THROW( Invalid_Argument );
|
||||
|
||||
args.flags = FT_OPEN_PATHNAME;
|
||||
args.pathname = (char*)pathname;
|
||||
args.stream = NULL;
|
||||
|
||||
return ft_open_face_internal( library, &args, face_index, aface, 1 );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* documentation is in freetype.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_New_Memory_Face( FT_Library library,
|
||||
const FT_Byte* file_base,
|
||||
FT_Long file_size,
|
||||
FT_Long face_index,
|
||||
FT_Face *aface )
|
||||
{
|
||||
FT_Open_Args args;
|
||||
|
||||
|
||||
/* test for valid `library' and `face' delayed to `FT_Open_Face' */
|
||||
if ( !file_base )
|
||||
return FT_THROW( Invalid_Argument );
|
||||
|
||||
args.flags = FT_OPEN_MEMORY;
|
||||
args.memory_base = file_base;
|
||||
args.memory_size = file_size;
|
||||
args.stream = NULL;
|
||||
|
||||
return ft_open_face_internal( library, &args, face_index, aface, 1 );
|
||||
}
|
||||
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_MAC_FONTS
|
||||
|
||||
/* The behavior here is very similar to that in base/ftmac.c, but it */
|
||||
|
|
Loading…
Add table
Reference in a new issue