summaryrefslogtreecommitdiff
path: root/Build/source/libs/freetype/lib/ttfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/freetype/lib/ttfile.c')
-rw-r--r--Build/source/libs/freetype/lib/ttfile.c1176
1 files changed, 1176 insertions, 0 deletions
diff --git a/Build/source/libs/freetype/lib/ttfile.c b/Build/source/libs/freetype/lib/ttfile.c
new file mode 100644
index 00000000000..256082dad55
--- /dev/null
+++ b/Build/source/libs/freetype/lib/ttfile.c
@@ -0,0 +1,1176 @@
+/*******************************************************************
+ *
+ * ttfile.c (extended version) 2.1
+ *
+ * File I/O Component (body).
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ * NOTES:
+ *
+ * This implementation relies on the ANSI libc. You may wish to
+ * modify it to get rid of libc and go straight to the your
+ * platform's stream routines.
+ *
+ * The same source code can be used for thread-safe and re-entrant
+ * builds of the library.
+ *
+ * Changes between 2.0 and 2.1 :
+ *
+ * - it is now possible to close a stream's file handle explicitely
+ * through the new API "TT_Flush_Stream". This will simply close
+ * a stream's file handle (useful to save system resources when
+ * dealing with lots of opened fonts). Of course, the function
+ * "TT_Use_Stream" will automatically re-open a stream's handle if
+ * necessary.
+ *
+ * - added "TT_Stream_Size" to replace "TT_File_Size" which wasn't
+ * used anyway. This one returns the size of any stream, even
+ * flushed one (when the previous TT_File_Size could only return
+ * the size of the current working stream). This is used by the
+ * new "Load_TrueType_Any" function in the tables loader.
+ *
+ ******************************************************************/
+
+#include "ttconfig.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "freetype.h"
+#include "tttypes.h"
+#include "ttdebug.h"
+#include "ttengine.h"
+#include "ttmutex.h"
+#include "ttmemory.h"
+#include "ttfile.h" /* our prototypes */
+
+/* required by the tracing mode */
+#undef TT_COMPONENT
+#define TT_COMPONENT trace_file
+
+
+/* For now, we don't define additional error messages in the core library */
+/* to report open-on demand errors. Define these error as standard ones */
+
+#define TT_Err_Could_Not_ReOpen_File TT_Err_Could_Not_Open_File
+#define TT_Err_Could_Not_ReSeek_File TT_Err_Could_Not_Open_File
+
+ /* This definition is mandatory for each file component! */
+ FT_EXPORT_FUNC( const )
+ TFileFrame TT_Null_FileFrame = { NULL, 0, 0 };
+
+/* It has proven useful to do some bounds checks during development phase. */
+/* They should probably be undefined for speed reasons in a later release. */
+
+#if DEBUG_FILE
+#define CHECK_FRAME( frame, n ) \
+ do { \
+ if ( frame.cursor + n > frame.address + frame.size ) \
+ Panic( "Frame boundary error!\n" ); \
+ } while ( 0 )
+#else
+#define CHECK_FRAME( frame, n ) /* nothing */
+#endif
+
+ /* Because a stream can be flushed, i.e. its file handle can be */
+ /* closed to save system resources, we must keep the stream's file */
+ /* pathname to be able to re-open it on demand when it is flushed */
+
+ struct TStream_Rec_;
+ typedef struct TStream_Rec_ TStream_Rec;
+ typedef TStream_Rec* PStream_Rec;
+
+ struct TStream_Rec_
+ {
+ Bool opened; /* is the stream handle opened ? */
+ TT_Text* name; /* the file's pathname */
+ Long position; /* current position within the file */
+
+ FILE* file; /* file handle */
+ Long base; /* stream base in file */
+ Long size; /* stream size in file */
+ };
+
+ /* We support embedded TrueType files by allowing them to be */
+ /* inside any file, at any location, hence the 'base' argument. */
+ /* Note however that the current implementation does not allow you */
+ /* to specify a 'base' index when opening a file. */
+ /* (will come later) */
+ /* I still don't know if this will turn out useful ?? - DavidT */
+
+#define STREAM2REC( x ) ( (TStream_Rec*)HANDLE_Val( x ) )
+
+ static TT_Error Stream_Activate ( PStream_Rec stream );
+ static TT_Error Stream_Deactivate( PStream_Rec stream );
+
+
+#ifndef TT_CONFIG_OPTION_THREAD_SAFE
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /*******************************************************************/
+ /**** ****/
+ /**** N O N R E E N T R A N T I M P L E M E N T A T I O N ****/
+ /**** ****/
+ /*******************************************************************/
+ /*******************************************************************/
+ /*******************************************************************/
+
+ /* in non-rentrant builds, we allocate a single block where we'll */
+ /* place all the frames smaller than FRAME_CACHE_SIZE, rather than */
+ /* allocating a new block on each access. Bigger frames will be */
+ /* malloced normally in the heap. */
+ /* */
+ /* See TT_Access_Frame() and TT_Forget_Frame() for details. */
+
+#define FRAME_CACHE_SIZE 2048
+
+ /* The TFile_Component structure holds all the data that was */
+ /* previously declared static or global in this component. */
+ /* */
+ /* It is accessible through the 'engine.file_component' */
+ /* variable in re-entrant builds, or directly through the */
+ /* static 'files' variable in other builds. */
+
+ struct TFile_Component_
+ {
+ TMutex lock; /* used by the thread-safe build only */
+ Byte* frame_cache; /* frame cache */
+ PStream_Rec stream; /* current stream */
+ TFileFrame frame; /* current frame */
+ };
+
+ typedef struct TFile_Component_ TFile_Component;
+
+ static TFile_Component files;
+
+#define CUR_Stream files.stream
+#define CUR_Frame files.frame
+
+#define STREAM_VARS /* void */
+#define STREAM_VAR /* void */
+
+/* The macro CUR_Stream denotes the current input stream. */
+/* Note that for the re-entrant version, the 'stream' name has been */
+/* chosen according to the macro STREAM_ARGS. */
+
+/* The macro CUR_Frame denotes the current file frame. */
+/* Note that for the re-entrant version, the 'frame' name has been */
+/* chosen according to the macro FRAME_ARGS. */
+
+/* The macro STREAM_VAR is used when calling public functions */
+/* that need an 'optional' stream argument. */
+
+
+/*******************************************************************
+ *
+ * Function : TTFile_Init
+ *
+ * Description : Initializes the File component.
+ *
+ ******************************************************************/
+
+ FT_INTERNAL_FUNC( TT_Error )
+ TTFile_Init( PEngine_Instance engine )
+ {
+ TT_Error error;
+
+
+ MUTEX_Create( files.lock );
+ files.stream = NULL;
+ ZERO_Frame( files.frame );
+
+ if ( ALLOC( files.frame_cache, FRAME_CACHE_SIZE ) )
+ return error;
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TTFile_Done
+ *
+ * Description : Finalizes the File component.
+ *
+ ******************************************************************/
+
+ FT_INTERNAL_FUNC( TT_Error )
+ TTFile_Done( PEngine_Instance engine )
+ {
+ FREE( files.frame_cache );
+ MUTEX_Destroy( files.lock );
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Use_Stream
+ *
+ * Description : Copies or duplicates a given stream.
+ *
+ * Input : org_stream original stream
+ * stream target stream (copy or duplicate)
+ *
+ * Output : Error code.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Use_Stream( TT_Stream org_stream,
+ TT_Stream* stream )
+ {
+ MUTEX_Lock( files.lock ); /* lock file mutex */
+
+ *stream = org_stream; /* copy the stream */
+ files.stream = STREAM2REC(org_stream); /* set current stream */
+
+ Stream_Activate( files.stream );
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Done_Stream
+ *
+ * Description : Releases a given stream.
+ *
+ * Input : stream target stream
+ *
+ * Output : Error code.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Done_Stream( TT_Stream* stream )
+ {
+ HANDLE_Set( *stream, NULL );
+ MUTEX_Release( files.lock );
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Access_Frame
+ *
+ * Description : Notifies the component that we're going to read
+ * 'size' bytes from the current file position.
+ * This function should load/cache/map these bytes
+ * so that they will be addressed by the GET_xxx
+ * functions easily.
+ *
+ * Input : size number of bytes to access.
+ *
+ * Output : SUCCESS on success. FAILURE on error.
+ *
+ * Notes: The function fails if the byte range is not within the
+ * the file, or if there is not enough memory to cache
+ * the bytes properly (which usually means that `size' is
+ * too big in both cases).
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long size )
+ {
+ TT_Error error;
+
+
+ if ( CUR_Frame.address != NULL )
+ return TT_Err_Nested_Frame_Access;
+
+ if ( size <= FRAME_CACHE_SIZE )
+ {
+ /* use the cache */
+ CUR_Frame.address = files.frame_cache;
+ CUR_Frame.size = FRAME_CACHE_SIZE;
+ }
+ else
+ {
+ if ( ALLOC( CUR_Frame.address, size ) )
+ return error;
+ CUR_Frame.size = size;
+ }
+
+ error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size );
+ if (error)
+ {
+ if ( size > FRAME_CACHE_SIZE )
+ FREE( CUR_Frame.address );
+ CUR_Frame.address = NULL;
+ CUR_Frame.size = 0;
+ }
+
+ CUR_Frame.cursor = CUR_Frame.address;
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Check_And_Access_Frame
+ *
+ * Description : Notifies the component that we're going to read
+ * `size' bytes from the current file position.
+ * This function should load/cache/map these bytes
+ * so that they will be addressed by the GET_xxx
+ * functions easily.
+ *
+ * Input : size number of bytes to access.
+ *
+ * Output : SUCCESS on success. FAILURE on error.
+ *
+ * Notes: The function truncates `size' if the byte range is not
+ * within the file.
+ *
+ * It will fail if there is not enough memory to cache
+ * the bytes properly (which usually means that `size' is
+ * too big).
+ *
+ * It will fail if you make two consecutive calls
+ * to TT_Access_Frame(), without a TT_Forget_Frame() between
+ * them.
+ *
+ * The only difference with TT_Access_Frame() is that we
+ * check that the frame is within the current file. We
+ * otherwise truncate it.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long size )
+ {
+ TT_Error error;
+ Long readBytes, requested;
+
+
+ if ( CUR_Frame.address != NULL )
+ return TT_Err_Nested_Frame_Access;
+
+ if ( size <= FRAME_CACHE_SIZE )
+ {
+ /* use the cache */
+ CUR_Frame.address = files.frame_cache;
+ CUR_Frame.size = FRAME_CACHE_SIZE;
+ }
+ else
+ {
+ if ( ALLOC( CUR_Frame.address, size ) )
+ return error;
+ CUR_Frame.size = size;
+ }
+
+ requested = size;
+ readBytes = CUR_Stream->size - TT_File_Pos( STREAM_VAR );
+ if ( size > readBytes )
+ size = readBytes;
+
+ error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size );
+ if (error)
+ {
+ if ( requested > FRAME_CACHE_SIZE )
+ FREE( CUR_Frame.address );
+ CUR_Frame.address = NULL;
+ CUR_Frame.size = 0;
+ }
+
+ CUR_Frame.cursor = CUR_Frame.address;
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Forget_Frame
+ *
+ * Description : Releases a cached frame after reading.
+ *
+ * Input : None
+ *
+ * Output : SUCCESS on success. FAILURE on error.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Forget_Frame( FRAME_ARG )
+ {
+ if ( CUR_Frame.address == NULL )
+ return TT_Err_Nested_Frame_Access;
+
+ if ( CUR_Frame.size > FRAME_CACHE_SIZE )
+ FREE( CUR_Frame.address );
+
+ ZERO_Frame( CUR_Frame );
+
+ return TT_Err_Ok;
+ }
+
+
+#else /* TT_CONFIG_OPTION_THREAD_SAFE */
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /*******************************************************************/
+ /******** ********/
+ /******** R E E N T R A N T I M P L E M E N T A T I O N ********/
+ /******** ********/
+ /*******************************************************************/
+ /*******************************************************************/
+ /*******************************************************************/
+
+/* a simple macro to access the file component's data */
+#define files ( *((TFile_Component*)engine.file_component) )
+
+#define CUR_Stream STREAM2REC( stream ) /* re-entrant macros */
+#define CUR_Frame (*frame)
+
+#define STREAM_VARS stream,
+#define STREAM_VAR stream
+
+
+/*******************************************************************
+ *
+ * Function : TTFile_Init
+ *
+ * Description : Initializes the File component.
+ *
+ ******************************************************************/
+
+ FT_INTERNAL_FUNC( TT_Error )
+ TTFile_Init( PEngine_Instance engine )
+ {
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TTFile_Done
+ *
+ * Description : Finalizes the File component.
+ *
+ ******************************************************************/
+
+ FT_INTERNAL_FUNC( TT_Error )
+ TTFile_Done( PEngine_Instance engine )
+ {
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Use_Stream
+ *
+ * Description : Duplicates a stream for a new usage.
+ *
+ * Input : input_stream source stream to duplicate
+ * copy address of target duplicate stream
+ *
+ * Output : error code.
+ * The target stream is set to NULL in case of failure.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Use_Stream( TT_Stream input_stream,
+ TT_Stream* copy )
+ {
+ PStream_Rec rec = STREAM2REC( input_stream );
+
+ return TT_Open_Stream( rec->name, copy );
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Done_Stream
+ *
+ * Description : Releases a given stream.
+ *
+ * Input : stream target stream
+ *
+ * Output :
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Done_Stream( TT_Stream* stream )
+ {
+ return TT_Close_Stream( stream );
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Access_Frame
+ *
+ * Description : Notifies the component that we're going to read
+ * 'size' bytes from the current file position.
+ * This function should load/cache/map these bytes
+ * so that they will be addressed by the GET_xxx
+ * functions easily.
+ *
+ * Input : size number of bytes to access.
+ *
+ * Output : SUCCESS on success. FAILURE on error.
+ *
+ * Notes: The function fails if the byte range is not within the
+ * the file, or if there is not enough memory to cache
+ * the bytes properly (which usually means that `size' is
+ * too big in both cases).
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long size )
+ {
+ TT_Error error;
+
+
+ if ( CUR_Frame.address != NULL )
+ return TT_Err_Nested_Frame_Access;
+
+ if ( ALLOC( CUR_Frame.address, size ) )
+ return error;
+ CUR_Frame.size = size;
+
+ error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size );
+ if ( error )
+ {
+ FREE( CUR_Frame.address );
+ CUR_Frame.size = 0;
+ }
+
+ CUR_Frame.cursor = CUR_Frame.address;
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Check_And_Access_Frame
+ *
+ * Description : Notifies the component that we're going to read
+ * `size' bytes from the current file position.
+ * This function should load/cache/map these bytes
+ * so that they will be addressed by the GET_xxx
+ * functions easily.
+ *
+ * Input : size number of bytes to access.
+ *
+ * Output : SUCCESS on success. FAILURE on error.
+ *
+ * Notes: The function truncates `size' if the byte range is not
+ * within the file.
+ *
+ * It will fail if there is not enough memory to cache
+ * the bytes properly (which usually means that `size' is
+ * too big).
+ *
+ * It will fail if you make two consecutive calls
+ * to TT_Access_Frame(), without a TT_Forget_Frame() between
+ * them.
+ *
+ * The only difference with TT_Access_Frame() is that we
+ * check that the frame is within the current file. We
+ * otherwise truncate it.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long size )
+ {
+ TT_Error error;
+ Long readBytes;
+
+
+ if ( CUR_Frame.address != NULL )
+ return TT_Err_Nested_Frame_Access;
+
+ if ( ALLOC( CUR_Frame.address, size ) )
+ return error;
+ CUR_Frame.size = size;
+
+ readBytes = CUR_Stream->size - TT_File_Pos( STREAM_VAR );
+ if ( size > readBytes )
+ size = readBytes;
+
+ error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size );
+ if ( error )
+ {
+ FREE( CUR_Frame.address );
+ CUR_Frame.size = 0;
+ }
+
+ CUR_Frame.cursor = CUR_Frame.address;
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Forget_Frame
+ *
+ * Description : Releases a cached frame after reading.
+ *
+ * Input : None
+ *
+ * Output : SUCCESS on success. FAILURE on error.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Forget_Frame( STREAM_ARGS FRAME_ARG )
+ {
+ if ( CUR_Frame.address == NULL )
+ return TT_Err_Nested_Frame_Access;
+
+ FREE( CUR_Frame.address );
+ ZERO_Frame( CUR_Frame );
+
+ return TT_Err_Ok;
+ }
+
+#endif /* TT_CONFIG_OPTION_THREAD_SAFE */
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /*******************************************************************/
+ /*********** ***********/
+ /*********** C O M M O N I M P L E M E N T A T I O N ***********/
+ /*********** ***********/
+ /*******************************************************************/
+ /*******************************************************************/
+ /*******************************************************************/
+
+/*******************************************************************
+ *
+ * Function : Stream_Activate
+ *
+ * Description : activates a stream, this will either:
+ * - open a new file handle if the stream is closed
+ * - move the stream to the head of the linked list
+ *
+ * Input : stream the stream to activate
+ *
+ * Output : error condition.
+ *
+ * Note : This function is also called with fresh new streams
+ * created by TT_Open_Stream(). They have their 'size'
+ * field set to -1.
+ *
+ ******************************************************************/
+
+ static TT_Error Stream_Activate( PStream_Rec stream )
+ {
+ if ( !stream->opened )
+ {
+ if ( (stream->file = fopen( (TT_Text*)stream->name, "rb" )) == 0 )
+ return TT_Err_Could_Not_ReOpen_File;
+
+ stream->opened = TRUE;
+
+ /* A newly created stream has a size field of -1 */
+ if ( stream->size < 0 )
+ {
+ fseek( stream->file, 0, SEEK_END );
+ stream->size = ftell( stream->file );
+ fseek( stream->file, 0, SEEK_SET );
+ }
+
+ /* Reset cursor in file */
+ if ( stream->position )
+ {
+ if ( fseek( stream->file, stream->position, SEEK_SET ) != 0 )
+ {
+ /* error during seek */
+ fclose( stream->file );
+ stream->opened = FALSE;
+ return TT_Err_Could_Not_ReSeek_File;
+ }
+ }
+ }
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Stream_DeActivate
+ *
+ * Description : deactivates a stream, this will :
+ * - close its file handle if it was opened
+ * - remove it from the opened list if necessary
+ *
+ * Input : stream the stream to deactivate
+ *
+ * Output : Error condition
+ *
+ * Note : the function is called whenever a stream is deleted
+ * (_not_ when a stream handle's is closed due to an
+ * activation). However, the stream record isn't
+ * destroyed by it..
+ *
+ ******************************************************************/
+
+ static TT_Error Stream_Deactivate( PStream_Rec stream )
+ {
+ if ( stream->opened )
+ {
+ /* Save its current position within the file */
+ stream->position = ftell( stream->file );
+ fclose( stream->file );
+ stream->file = 0;
+ stream->opened = FALSE;
+ }
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Stream_Size
+ *
+ * Description : Returns the length of a given stream, even if it
+ * is flushed.
+ *
+ * Input : stream the stream
+ *
+ * Output : Length of stream in bytes.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( Long )
+ TT_Stream_Size( TT_Stream stream )
+ {
+ PStream_Rec rec = STREAM2REC( stream );
+
+
+ if ( rec )
+ return rec->size;
+ else
+ return 0; /* invalid stream - return 0 */
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Open_Stream
+ *
+ * Description : Opens the font file and saves the total file size.
+ *
+ * Input : error address of stream's error variable
+ * (re-entrant build only)
+ * filepathname pathname of the file to open
+ * stream address of target TT_Stream structure
+ *
+ * Output : SUCCESS on sucess, FAILURE on error.
+ * The target stream is set to -1 in case of failure.
+ *
+ ******************************************************************/
+
+ FT_INTERNAL_FUNC( TT_Error )
+ TT_Open_Stream( const TT_Text* filepathname,
+ TT_Stream* stream )
+ {
+ Int len;
+ TT_Error error;
+ PStream_Rec stream_rec;
+
+ if ( ALLOC( *stream, sizeof ( TStream_Rec ) ) )
+ return error;
+
+ stream_rec = STREAM2REC( *stream );
+
+ stream_rec->file = NULL;
+ stream_rec->size = -1L;
+ stream_rec->base = 0;
+ stream_rec->opened = FALSE;
+ stream_rec->position = 0;
+
+ len = strlen( filepathname ) + 1;
+ if ( ALLOC( stream_rec->name, len ) )
+ goto Fail;
+
+ strncpy( stream_rec->name, filepathname, len );
+
+ error = Stream_Activate( stream_rec );
+ if ( error )
+ goto Fail_Activate;
+
+#ifndef TT_CONFIG_OPTION_THREAD_SAFE
+ CUR_Stream = stream_rec;
+#endif
+
+ return TT_Err_Ok;
+
+ Fail_Activate:
+ FREE( stream_rec->name );
+ Fail:
+ FREE( stream_rec );
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Close_Stream
+ *
+ * Description : Closes a stream.
+ *
+ * Input : stream address of target TT_Stream structure
+ *
+ * Output : SUCCESS (always).
+ *
+ ******************************************************************/
+
+ FT_INTERNAL_FUNC( TT_Error )
+ TT_Close_Stream( TT_Stream* stream )
+ {
+ PStream_Rec rec = STREAM2REC( *stream );
+
+
+ Stream_Deactivate( rec );
+ FREE( rec->name );
+ FREE( rec );
+
+ HANDLE_Set( *stream, NULL );
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Flush_Stream
+ *
+ * Description : Flushes a stream, i.e., closes its file handle.
+ *
+ * Input : stream address of target TT_Stream structure
+ *
+ * Output : Error code
+ *
+ * NOTE : Never flush the current opened stream. This means that
+ * you should _never_ call this function between a
+ * TT_Use_Stream() and a TT_Done_Stream()!
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Flush_Stream( TT_Stream* stream )
+ {
+ PStream_Rec rec = STREAM2REC( *stream );
+
+
+ if ( rec )
+ {
+ Stream_Deactivate( rec );
+ return TT_Err_Ok;
+ }
+ else
+ return TT_Err_Invalid_Argument;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Seek_File
+ *
+ * Description : Seeks the file cursor to a different position.
+ *
+ * Input : position new position in file
+ *
+ * Output : SUCCESS on success. FAILURE if out of range.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Seek_File( STREAM_ARGS Long position )
+ {
+ position += CUR_Stream->base;
+
+ if ( fseek( CUR_Stream->file, position, SEEK_SET ) )
+ return TT_Err_Invalid_File_Offset;
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Skip_File
+ *
+ * Description : Skips forward the file cursor.
+ *
+ * Input : distance number of bytes to skip
+ *
+ * Output : see TT_Seek_File()
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Skip_File( STREAM_ARGS Long distance )
+ {
+ return TT_Seek_File( STREAM_VARS ftell( CUR_Stream->file ) -
+ CUR_Stream->base + distance );
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Read_File
+ *
+ * Description : Reads a chunk of the file and copies it to memory.
+ *
+ * Input : buffer target buffer
+ * count length in bytes to read
+ *
+ * Output : SUCCESS on success. FAILURE if out of range.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Read_File( STREAM_ARGS void* buffer, Long count )
+ {
+ if ( fread( buffer, 1, count, CUR_Stream->file ) != (ULong)count )
+ return TT_Err_Invalid_File_Read;
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_Read_At_File
+ *
+ * Description : Reads file at a specified position.
+ *
+ * Input : position position to seek to before read
+ * buffer target buffer
+ * count number of bytes to read
+ *
+ * Output : SUCCESS on success. FAILURE if error.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( TT_Error )
+ TT_Read_At_File( STREAM_ARGS Long position,
+ void* buffer,
+ Long count )
+ {
+ TT_Error error;
+
+
+ if ( (error = TT_Seek_File( STREAM_VARS position )) != TT_Err_Ok ||
+ (error = TT_Read_File( STREAM_VARS buffer, count )) != TT_Err_Ok )
+ return error;
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TT_File_Pos
+ *
+ * Description : Returns current file seek pointer.
+ *
+ * Input : none
+ *
+ * Output : Current file position.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( Long )
+ TT_File_Pos( STREAM_ARG )
+ {
+ return ftell( CUR_Stream->file ) - CUR_Stream->base;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : GET_Byte
+ *
+ * Description : Extracts a byte from the current file frame.
+ *
+ * Input : None or current frame
+ *
+ * Output : Extracted Byte.
+ *
+ ******************************************************************/
+#if 0
+ FT_EXPORT_FUNC( Byte )
+ TT_Get_Byte( FRAME_ARG )
+ {
+ CHECK_FRAME( CUR_Frame, 1 );
+
+ return (Byte)(*CUR_Frame.cursor++);
+ }
+#endif
+
+
+/*******************************************************************
+ *
+ * Function : GET_Char
+ *
+ * Description : Extracts a signed byte from the current file frame.
+ *
+ * Input : None or current frame
+ *
+ * Output : Extracted char.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( Char )
+ TT_Get_Char( FRAME_ARG )
+ {
+ CHECK_FRAME( CUR_Frame, 1 );
+
+ return (Char)(*CUR_Frame.cursor++);
+ }
+
+
+/*******************************************************************
+ *
+ * Function : GET_Short
+ *
+ * Description : Extracts a short from the current file frame.
+ *
+ * Input : None or current frame
+ *
+ * Output : Extracted short.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( Short )
+ TT_Get_Short( FRAME_ARG )
+ {
+ Short getshort;
+
+
+ CHECK_FRAME( CUR_Frame, 2 );
+
+ getshort = (Short)((CUR_Frame.cursor[0] << 8) |
+ CUR_Frame.cursor[1]);
+
+ CUR_Frame.cursor += 2;
+
+ return getshort;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : GET_UShort
+ *
+ * Description : Extracts an unsigned short from the frame.
+ *
+ * Input : None or current frame
+ *
+ * Output : Extracted ushort.
+ *
+ ******************************************************************/
+#if 0
+ FT_EXPORT_FUNC( UShort )
+ TT_Get_UShort( FRAME_ARG )
+ {
+ UShort getshort;
+
+
+ CHECK_FRAME( CUR_Frame, 2 );
+
+ getshort = (UShort)((CUR_Frame.cursor[0] << 8) |
+ CUR_Frame.cursor[1]);
+
+ CUR_Frame.cursor += 2;
+
+ return getshort;
+ }
+#endif
+
+
+/*******************************************************************
+ *
+ * Function : GET_Long
+ *
+ * Description : Extracts a long from the frame.
+ *
+ * Input : None or current frame
+ *
+ * Output : Extracted long.
+ *
+ ******************************************************************/
+
+ FT_EXPORT_FUNC( Long )
+ TT_Get_Long( FRAME_ARG )
+ {
+ Long getlong;
+
+
+ CHECK_FRAME( CUR_Frame, 4 );
+
+ getlong = ((Long)CUR_Frame.cursor[0] << 24) |
+ ((Long)CUR_Frame.cursor[1] << 16) |
+ ((Long)CUR_Frame.cursor[2] << 8 ) |
+ (Long)CUR_Frame.cursor[3];
+
+ CUR_Frame.cursor += 4;
+
+ return getlong;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : GET_ULong
+ *
+ * Description : Extracts an unsigned long from the frame.
+ *
+ * Input : None or current frame
+ *
+ * Output : Extracted ulong.
+ *
+ ******************************************************************/
+#if 0
+ FT_EXPORT_FUNC( ULong )
+ TT_Get_ULong( FRAME_ARG )
+ {
+ ULong getlong;
+
+
+ CHECK_FRAME( CUR_Frame, 4 );
+
+ getlong = ( ((ULong)CUR_Frame.cursor[0] << 24) |
+ ((ULong)CUR_Frame.cursor[1] << 16) |
+ ((ULong)CUR_Frame.cursor[2] << 8 ) |
+ (ULong)CUR_Frame.cursor[3] );
+
+ CUR_Frame.cursor += 4;
+
+ return getlong;
+ }
+#endif
+
+
+/* END */