diff --git a/src/Core.h b/src/Core.h index a6ccb447d..c7a79447e 100644 --- a/src/Core.h +++ b/src/Core.h @@ -43,7 +43,6 @@ typedef signed __int64 int64_t; typedef uint16_t Codepoint; typedef uint8_t bool; -typedef uint8_t bool; #define true 1 #define false 0 #ifndef NULL diff --git a/src/HeldBlockRenderer.c b/src/HeldBlockRenderer.c index f24b77ee1..d66a52f03 100644 --- a/src/HeldBlockRenderer.c +++ b/src/HeldBlockRenderer.c @@ -85,10 +85,10 @@ static void HeldBlockRenderer_SetBaseOffset(void) { Vector3 normalOffset = { 0.56f, -0.72f, -0.72f }; Vector3 spriteOffset = { 0.46f, -0.52f, -0.72f }; Vector3 offset = sprite ? spriteOffset : normalOffset; - - Vector3_Add(&held_entity.Position, &held_entity.Position, &offset); + + Vector3_AddBy(&held_entity.Position, &offset); if (!sprite && Blocks.Draw[held_block] != DRAW_GAS) { - float height = Blocks.MaxBB[held_block].Y - Blocks.MinBB[held_block].Y; + float height = Blocks.MaxBB[held_block].Y - Blocks.MinBB[held_block].Y; held_entity.Position.Y += 0.2f * (1.0f - height); } } diff --git a/src/Http.c b/src/Http.c index 882b5cd55..8f42d9621 100644 --- a/src/Http.c +++ b/src/Http.c @@ -124,7 +124,7 @@ static void Http_SysInit(void) { } /* Adds custom HTTP headers for a req */ -static void Http_SysMakeHeaders(String* headers, struct HttpRequest* req) { +static void Http_MakeHeaders(String* headers, struct HttpRequest* req) { if (!req->Etag[0] && !req->LastModified && !req->Data) { headers->buffer = NULL; return; } @@ -150,8 +150,8 @@ static void Http_SysMakeHeaders(String* headers, struct HttpRequest* req) { headers->buffer[headers->length] = '\0'; } -/* Creates and sends a http req */ -static ReturnCode Http_SysMakeRequest(struct HttpRequest* req, HINTERNET* handle) { +/* Creates and sends a HTTP requst */ +static ReturnCode Http_StartRequest(struct HttpRequest* req, HINTERNET* handle) { const static char* verbs[3] = { "GET", "HEAD", "POST" }; struct HttpCacheEntry entry; DWORD flags; @@ -167,7 +167,7 @@ static ReturnCode Http_SysMakeRequest(struct HttpRequest* req, HINTERNET* handle HttpCache_Lookup(&entry); /* https://stackoverflow.com/questions/25308488/c-wininet-custom-http-headers */ String_InitArray(headers, headersBuffer); - Http_SysMakeHeaders(&headers, req); + Http_MakeHeaders(&headers, req); flags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD; if (entry.Https) flags |= INTERNET_FLAG_SECURE; @@ -179,8 +179,8 @@ static ReturnCode Http_SysMakeRequest(struct HttpRequest* req, HINTERNET* handle req->Data, req->Size) ? 0 : GetLastError(); } -/* Gets headers from a http response */ -static ReturnCode Http_SysGetHeaders(struct HttpRequest* req, HINTERNET handle) { +/* Gets headers from a HTTP response */ +static ReturnCode Http_ProcessHeaders(struct HttpRequest* req, HINTERNET handle) { DWORD len; len = sizeof(DWORD); @@ -207,8 +207,8 @@ static ReturnCode Http_SysGetHeaders(struct HttpRequest* req, HINTERNET handle) return 0; } -/* Gets the data/contents of a http response */ -static ReturnCode Http_SysGetData(struct HttpRequest* req, HINTERNET handle, volatile int* progress) { +/* Downloads the data/contents of a HTTP response */ +static ReturnCode Http_DownloadData(struct HttpRequest* req, HINTERNET handle, volatile int* progress) { uint8_t* buffer; uint32_t size, totalRead; uint32_t read, avail; @@ -246,19 +246,18 @@ static ReturnCode Http_SysGetData(struct HttpRequest* req, HINTERNET handle, vol return 0; } -/* Performs a http req and inspecting the response */ static ReturnCode Http_SysDo(struct HttpRequest* req, volatile int* progress) { HINTERNET handle; - ReturnCode res = Http_SysMakeRequest(req, &handle); + ReturnCode res = Http_StartRequest(req, &handle); HttpRequest_Free(req); if (res) return res; *progress = ASYNC_PROGRESS_FETCHING_DATA; - res = Http_SysGetHeaders(req, handle); + res = Http_ProcessHeaders(req, handle); if (res) { InternetCloseHandle(handle); return res; } if (req->RequestType != REQUEST_TYPE_HEAD) { - res = Http_SysGetData(req, handle, progress); + res = Http_DownloadData(req, handle, progress); if (res) { InternetCloseHandle(handle); return res; } } @@ -285,13 +284,15 @@ static void Http_SysInit(void) { if (!curl) Logger_Abort("Failed to init easy curl"); } -static int Http_SysProgress(int* progress, double total, double received, double a, double b) { +/* Updates progress of current download */ +static int Http_UpdateProgress(int* progress, double total, double received, double a, double b) { if (total == 0) return 0; *progress = (int)(100 * received / total); return 0; } -static struct curl_slist* Http_SysMake(struct HttpRequest* req) { +/* Makes custom request HTTP headers, usually none. */ +static struct curl_slist* Http_MakeHeaders(struct HttpRequest* req) { String tmp; char buffer[STRING_SIZE + 1]; struct curl_slist* list = NULL; String etag; @@ -317,19 +318,8 @@ static struct curl_slist* Http_SysMake(struct HttpRequest* req) { return list; } -static void Http_SysSetType(struct HttpRequest* req) { - if (req->RequestType == REQUEST_TYPE_HEAD) { - curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); - } else if (req->RequestType == REQUEST_TYPE_POST) { - curl_easy_setopt(curl, CURLOPT_POST, 1L); - /* TODO: Just use POSTFIELDS ?? */ - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, req->Size); - curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, req->Data); - HttpRequest_Free(req); - } -} - -static size_t Http_SysGetHeaders(char *buffer, size_t size, size_t nitems, struct HttpRequest* req) { +/* Processes a HTTP header downloaded from the server */ +static size_t Http_ProcessHeader(char *buffer, size_t size, size_t nitems, struct HttpRequest* req) { String tmp; char tmpBuffer[STRING_SIZE + 1]; String line, name, value; time_t time; @@ -361,7 +351,8 @@ static size_t Http_SysGetHeaders(char *buffer, size_t size, size_t nitems, struc } static int curlBufferSize; -static size_t Http_SysGetData(char *buffer, size_t size, size_t nitems, struct HttpRequest* req) { +/* Processes a chunk of data downloaded from the web server */ +static size_t Http_ProcessData(char *buffer, size_t size, size_t nitems, struct HttpRequest* req) { uint8_t* dst; if (!curlBufferSize) { @@ -385,32 +376,49 @@ static size_t Http_SysGetData(char *buffer, size_t size, size_t nitems, struct H return nitems; } -static ReturnCode Http_SysDo(struct HttpRequest* req, volatile int* progress) { - struct curl_slist* list; - String url = String_FromRawArray(req->URL); - char urlStr[600]; - long status = 0; - CURLcode res; - - Platform_ConvertString(urlStr, &url); - curl_easy_reset(curl); - list = Http_SysMake(req); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); - curl_easy_setopt(curl, CURLOPT_COOKIEJAR, ""); - Http_SysSetType(req); - - curl_easy_setopt(curl, CURLOPT_URL, urlStr); +/* Sets general curl options for a request */ +static void Http_SetCurlOpts(struct HttpRequest* req, volatile int* progress) { + curl_easy_setopt(curl, CURLOPT_COOKIEJAR, ""); curl_easy_setopt(curl, CURLOPT_USERAGENT, GAME_APP_NAME); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, Http_SysProgress); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, Http_UpdateProgress); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, progress); - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, Http_SysGetHeaders); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, Http_ProcessHeader); curl_easy_setopt(curl, CURLOPT_HEADERDATA, req); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Http_SysGetData); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Http_ProcessData); curl_easy_setopt(curl, CURLOPT_WRITEDATA, req); +} + +static ReturnCode Http_SysDo(struct HttpRequest* req, volatile int* progress) { + String url = String_FromRawArray(req->URL); + char urlStr[600]; + void* post_data = req->Data; + struct curl_slist* list; + long status = 0; + CURLcode res; + + curl_easy_reset(curl); + list = Http_MakeHeaders(req); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); + + Http_SetCurlOpts(req, progress); + Platform_ConvertString(urlStr, &url); + curl_easy_setopt(curl, CURLOPT_URL, urlStr); + + if (req->RequestType == REQUEST_TYPE_HEAD) { + curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); + } else if (req->RequestType == REQUEST_TYPE_POST) { + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, req->Size); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req->Data); + + /* per curl docs, we must persist POST data until request finishes */ + req->Data = NULL; + HttpRequest_Free(req); + } curlBufferSize = 0; *progress = ASYNC_PROGRESS_FETCHING_DATA; @@ -421,6 +429,8 @@ static ReturnCode Http_SysDo(struct HttpRequest* req, volatile int* progress) { req->StatusCode = status; curl_slist_free_all(list); + /* can free now that request has finished */ + Mem_Free(post_data); return res; } diff --git a/src/LWidgets.c b/src/LWidgets.c index 783a699c4..31d7e5b1e 100644 --- a/src/LWidgets.c +++ b/src/LWidgets.c @@ -714,7 +714,7 @@ static int LTable_GetSelectedIndex(struct LTable* w) { return -1; } -/* Sets selected row to given row, scrolling table if needed. */ +/* Sets selected row to given row, scrolling table if needed */ static void LTable_SetSelectedTo(struct LTable* w, int index) { if (!w->RowsCount) return; if (index >= w->RowsCount) index = w->RowsCount - 1; @@ -834,7 +834,6 @@ static void LTable_DrawHeaders(struct LTable* w) { /* Draws contents of the currently visible rows in the table */ static void LTable_DrawRows(struct LTable* w) { - BitmapCol gridCol = BITMAPCOL_CONST(20, 20, 10, 255); String str; char strBuffer[STRING_SIZE]; struct ServerInfo* entry; struct DrawTextArgs args; diff --git a/src/Platform.c b/src/Platform.c index a349f9192..001ecfab8 100644 --- a/src/Platform.c +++ b/src/Platform.c @@ -878,7 +878,7 @@ static bool FontData_Init(const String* path, struct FontData* data, FT_Open_Arg /* For OSX font suitcase files */ #ifdef CC_BUILD_OSX String filename = String_NT_Array(data->filename); - String_Copy(&filename, &path); + String_Copy(&filename, path); data->filename[filename.length] = '\0'; args->pathname = data->filename; #endif diff --git a/src/Window.c b/src/Window.c index 7acd063fe..bbe91d401 100644 --- a/src/Window.c +++ b/src/Window.c @@ -1985,6 +1985,10 @@ OSStatus Window_ProcessMouseEvent(EventHandlerCallRef inCaller, EventRef inEvent if (win_state != WINDOW_STATE_FULLSCREEN) { mousePos.Y -= title_height; } + + /* mousePos.Y will be < 0 if user clicks or moves on titlebar */ + /* don't intercept this, prevents clicking close/minimise/maximise from working */ + if (mousePos.Y < 0) return eventNotHandledErr; kind = GetEventKind(inEvent); switch (kind) { @@ -2078,10 +2082,7 @@ static void Window_ConnectEvents(void) { EventTargetRef target; OSStatus res; - target = GetApplicationEventTarget(); - /* TODO: Use EventTargetRef target = GetWindowEventTarget(windowRef); instead?? */ - /* need WindowEventTargetRef, otherwise message boxes don't work */ - /* but if use WindowEventTargetRef, can't click quit/move buttons anymore */ + target = GetWindowEventTarget(win_handle); res = InstallEventHandler(target, NewEventHandlerUPP(Window_EventHandler), Array_Elems(eventTypes), eventTypes, NULL, NULL); if (res) Logger_Abort2(res, "Connecting events"); @@ -2345,6 +2346,8 @@ void Window_ShowDialog(const char* title, const char* msg) { RunStandardAlert(dialog, NULL, &itemHit); } + +/* TODO: WORK OUT WHY THIS IS BROKEN!!!! static CGrafPtr win_winPort; static CGImageRef win_image; @@ -2375,7 +2378,7 @@ void Window_DrawRaw(Rect2D r) { err = QDBeginCGContext(win_winPort, &context); if (err) Logger_Abort2(err, "Begin draw"); - /* TODO: Only update changed bit.. */ + // TODO: Only update changed bit.. rect.origin.x = 0; rect.origin.y = 0; rect.size.width = Window_ClientSize.Width; rect.size.height = Window_ClientSize.Height; @@ -2385,6 +2388,52 @@ void Window_DrawRaw(Rect2D r) { err = QDEndCGContext(win_winPort, &context); if (err) Logger_Abort2(err, "End draw"); } +*/ + +static CGrafPtr win_winPort; +static CGImageRef win_image; +static Bitmap* bmp_; +static CGColorSpaceRef colorSpace; +static CGDataProviderRef provider; + +void Window_InitRaw(Bitmap* bmp) { + if (!win_winPort) win_winPort = GetWindowPort(win_handle); + Mem_Free(bmp->Scan0); + bmp->Scan0 = Mem_Alloc(bmp->Width * bmp->Height, 4, "window pixels"); + + colorSpace = CGColorSpaceCreateDeviceRGB(); + + bmp_ = bmp; + //CGColorSpaceRelease(colorSpace); +} + +void Window_DrawRaw(Rect2D r) { + CGContextRef context = NULL; + CGRect rect; + OSStatus err; + + err = QDBeginCGContext(win_winPort, &context); + if (err) Logger_Abort2(err, "Begin draw"); + /* TODO: REPLACE THIS AWFUL HACK */ + + /* TODO: Only update changed bit.. */ + rect.origin.x = 0; rect.origin.y = 0; + rect.size.width = Window_ClientSize.Width; + rect.size.height = Window_ClientSize.Height; + + provider = CGDataProviderCreateWithData(NULL, bmp_->Scan0, + Bitmap_DataSize(bmp_->Width, bmp_->Height), NULL); + win_image = CGImageCreate(bmp_->Width, bmp_->Height, 8, 32, bmp_->Width * 4, colorSpace, + kCGBitmapByteOrder32Little | kCGImageAlphaFirst, provider, NULL, 0, 0); + + CGContextDrawImage(context, rect, win_image); + CGContextSynchronize(context); + err = QDEndCGContext(win_winPort, &context); + if (err) Logger_Abort2(err, "End draw"); + + CGImageRelease(win_image); + CGDataProviderRelease(provider); +} /*########################################################################################################################* diff --git a/src/freetype/ftbase.h b/src/freetype/ftbase.h index e7ad1fd68..78ffe7d8e 100644 --- a/src/freetype/ftbase.h +++ b/src/freetype/ftbase.h @@ -30,6 +30,33 @@ FT_BEGIN_HEADER /* see https://support.microsoft.com/en-us/kb/130437 */ #define FT_MAC_RFORK_MAX_LEN 0x00FFFFFFUL +#ifdef FT_MACINTOSH + + +/* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */ +/* font, and try to load a face specified by the face_index. */ +FT_LOCAL(FT_Error) +open_face_PS_from_sfnt_stream(FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Int num_params, + FT_Parameter *params, + FT_Face *aface); + + +/* Create a new FT_Face given a buffer and a driver name. */ +/* From ftmac.c. */ +FT_LOCAL(FT_Error) +open_face_from_buffer(FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Long face_index, + const char* driver_name, + FT_Face *aface); + + +#endif + FT_END_HEADER #endif /* FTBASE_H_ */ diff --git a/src/freetype/ftobjs.c b/src/freetype/ftobjs.c index e23f426a6..2b7bd6bf6 100644 --- a/src/freetype/ftobjs.c +++ b/src/freetype/ftobjs.c @@ -1382,6 +1382,301 @@ } +#ifdef FT_MACINTOSH + + /* The behavior here is very similar to that in base/ftmac.c, but it */ + /* is designed to work on non-mac systems, so no mac specific calls. */ + /* */ + /* We look at the file and determine if it is a mac dfont file or a mac */ + /* resource file, or a macbinary file containing a mac resource file. */ + /* */ + /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */ + /* the point, especially since there may be multiple `FOND' resources. */ + /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */ + /* they occur in the file. */ + /* */ + /* Note that multiple `POST' resources do not mean multiple postscript */ + /* fonts; they all get jammed together to make what is essentially a */ + /* pfb file. */ + /* */ + /* We aren't interested in `NFNT' or `FONT' bitmap resources. */ + /* */ + /* As soon as we get an `sfnt' load it into memory and pass it off to */ + /* FT_Open_Face. */ + /* */ + /* If we have a (set of) `POST' resources, massage them into a (memory) */ + /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */ + /* going to try to save the kerning info. After all that lives in the */ + /* `FOND' which isn't in the file containing the `POST' resources so */ + /* we don't really have access to it. */ + + + /* Finalizer for a memory stream; gets called by FT_Done_Face(). */ + /* It frees the memory it uses. */ + /* From `ftmac.c'. */ + static void + memory_stream_close( FT_Stream stream ) + { + FT_Memory memory = stream->memory; + + + FT_FREE( stream->base ); + + stream->size = 0; + stream->base = NULL; + stream->close = NULL; + } + + + /* Create a new memory stream from a buffer and a size. */ + /* From `ftmac.c'. */ + static FT_Error + new_memory_stream( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Stream_CloseFunc close, + FT_Stream *astream ) + { + FT_Error error; + FT_Memory memory; + FT_Stream stream = NULL; + + + if ( !library ) + return FT_THROW( Invalid_Library_Handle ); + + if ( !base ) + return FT_THROW( Invalid_Argument ); + + *astream = NULL; + memory = library->memory; + if ( FT_NEW( stream ) ) + goto Exit; + + FT_Stream_OpenMemory( stream, base, size ); + + stream->close = close; + + *astream = stream; + + Exit: + return error; + } + + + /* Create a new FT_Face given a buffer and a driver name. */ + /* From `ftmac.c'. */ + FT_LOCAL_DEF( FT_Error ) + open_face_from_buffer( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Long face_index, + const char* driver_name, + FT_Face *aface ) + { + FT_Open_Args args; + FT_Error error; + FT_Stream stream = NULL; + FT_Memory memory = library->memory; + + + error = new_memory_stream( library, + base, + size, + memory_stream_close, + &stream ); + if ( error ) + { + FT_FREE( base ); + return error; + } + + args.flags = FT_OPEN_STREAM; + args.stream = stream; + if ( driver_name ) + { + args.flags = args.flags | FT_OPEN_DRIVER; + args.driver = FT_Get_Module( library, driver_name ); + } + + /* At this point, the face index has served its purpose; */ + /* whoever calls this function has already used it to */ + /* locate the correct font data. We should not propagate */ + /* this index to FT_Open_Face() (unless it is negative). */ + + if ( face_index > 0 ) + face_index &= 0x7FFF0000L; /* retain GX data */ + + error = ft_open_face_internal( library, &args, face_index, aface, 0 ); + + if ( !error ) + (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; + else + FT_Stream_Free( stream, 0 ); + + return error; + } + + + /* Look up `TYP1' or `CID ' table from sfnt table directory. */ + /* `offset' and `length' must exclude the binary header in tables. */ + + /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */ + /* format too. Here, since we can't expect that the TrueType font */ + /* driver is loaded unconditionally, we must parse the font by */ + /* ourselves. We are only interested in the name of the table and */ + /* the offset. */ + + static FT_Error + ft_lookup_PS_in_sfnt_stream( FT_Stream stream, + FT_Long face_index, + FT_ULong* offset, + FT_ULong* length, + FT_Bool* is_sfnt_cid ) + { + FT_Error error; + FT_UShort numTables; + FT_Long pstable_index; + FT_ULong tag; + int i; + + + *offset = 0; + *length = 0; + *is_sfnt_cid = FALSE; + + /* TODO: support for sfnt-wrapped PS/CID in TTC format */ + + /* version check for 'typ1' (should be ignored?) */ + if ( FT_READ_ULONG( tag ) ) + return error; + if ( tag != TTAG_typ1 ) + return FT_THROW( Unknown_File_Format ); + + if ( FT_READ_USHORT( numTables ) ) + return error; + if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */ + return error; + + pstable_index = -1; + *is_sfnt_cid = FALSE; + + for ( i = 0; i < numTables; i++ ) + { + if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) || + FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) ) + return error; + + if ( tag == TTAG_CID ) + { + pstable_index++; + *offset += 22; + *length -= 22; + *is_sfnt_cid = TRUE; + if ( face_index < 0 ) + return FT_Err_Ok; + } + else if ( tag == TTAG_TYP1 ) + { + pstable_index++; + *offset += 24; + *length -= 24; + *is_sfnt_cid = FALSE; + if ( face_index < 0 ) + return FT_Err_Ok; + } + if ( face_index >= 0 && pstable_index == face_index ) + return FT_Err_Ok; + } + + return FT_THROW( Table_Missing ); + } + + + FT_LOCAL_DEF( FT_Error ) + open_face_PS_from_sfnt_stream( FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Int num_params, + FT_Parameter *params, + FT_Face *aface ) + { + FT_Error error; + FT_Memory memory = library->memory; + FT_ULong offset, length; + FT_ULong pos; + FT_Bool is_sfnt_cid; + FT_Byte* sfnt_ps = NULL; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + /* ignore GX stuff */ + if ( face_index > 0 ) + face_index &= 0xFFFFL; + + pos = FT_STREAM_POS(); + + error = ft_lookup_PS_in_sfnt_stream( stream, + face_index, + &offset, + &length, + &is_sfnt_cid ); + if ( error ) + goto Exit; + + if ( offset > stream->size ) + { + FT_TRACE2(( "open_face_PS_from_sfnt_stream: invalid table offset\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + else if ( length > stream->size - offset ) + { + FT_TRACE2(( "open_face_PS_from_sfnt_stream: invalid table length\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + + error = FT_Stream_Seek( stream, pos + offset ); + if ( error ) + goto Exit; + + if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) ) + goto Exit; + + error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length ); + if ( error ) + { + FT_FREE( sfnt_ps ); + goto Exit; + } + + error = open_face_from_buffer( library, + sfnt_ps, + length, + FT_MIN( face_index, 0 ), + is_sfnt_cid ? "cid" : "type1", + aface ); + Exit: + { + FT_Error error1; + + + if ( FT_ERR_EQ( error, Unknown_File_Format ) ) + { + error1 = FT_Stream_Seek( stream, pos ); + if ( error1 ) + return error1; + } + + return error; + } + } +#endif /* FT_MACINTOSH */ + + /* documentation is in freetype.h */ #ifndef FT_MACINTOSH