C client: Fix immediately crashing in Release mode when compiled with MSVC

This commit is contained in:
UnknownShadow200 2018-10-12 20:28:59 +11:00
parent 3d511f7c89
commit b0380c5994
5 changed files with 74 additions and 187 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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> */

View file

@ -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 */