📄 os2file.c
字号:
/******************************************************************* * * os2file.c (OS2 version) 2.1 * * File I/O Component (body). * * Copyright 1996-2001 by Michal Necasek, * 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 OS/2 file API. It was provided * by the PM FreeType DLL author, Michal Necasek. * ******************************************************************/#include "ttconfig.h"#include <os2.h> /* !Mike! */#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 *//* For now, we don't define additional error messages in the core library *//* to report open-on demand errors. Define these errors 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 0#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 ) \ do { \ } while ( 0 )#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 { Bool opened; /* is the stream handle opened ? */ String* name; /* the file's pathname */ Long position; /* current pos. within the file */ HFILE file; /* file handle !Mike! */ Long base; /* stream base in file */ Long size; /* stream size in file */ }; typedef struct _TStream_Rec TStream_Rec; typedef TStream_Rec* PStream_Rec; /* 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-reentrant 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 */ /*******************************************************************/ /*******************************************************************/ /*******************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -