📄 ttmmap.c
字号:
/******************************************************************* * * ttmmap.c 2.0 * * Memory-Mapped file component ( replaces ttfile.c ). * * Copyright 1996-2001 by David Williss, * 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. * * Changes between 2.0 and 1.3 : * * - adopted new design/separation introduced in ttfile.c 2.0 * ******************************************************************/#include "ttconfig.h"#include <stdio.h>#include <string.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#include <folders.h>#include <resources.h>#include "freetype.h"#include "tttypes.h"#include "ttdebug.h"#include "ttengine.h"#include "ttmutex.h"#include "ttmemory.h"#include "ttfile.h" /* our prototypes */ /* This definition is mandatory for each file component! */ FT_EXPORT_VAR( const TFileFrame ) TT_Null_FileFrame = { NULL, 0, 0 }; /* It has proven useful to do some bounds checks during */ /* development phase. Define DEBUG_FILE when compiling */ /* this component to enable them. */#ifdef 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 ) \ do { \ } while( 0 )#endif struct _TFileMap { String* base; /* base address of mapped file */ Int refcount; /* reference count for handle region */ Long size; /* stream size in file */ Long offset; /* offset in file */ Handle handle; /* Macintosh style handle to lock/unlock */ short resid; /* Id of resource file to close when done */ }; typedef struct _TFileMap TFileMap;#define MAP_Address( map ) (Byte*)( (map)->base + (map)->offset ) /* The stream record structure */ typedef struct _TStream_Rec { TFileMap* map; /* mapped file description */ Long pos ; /* cursor in mapped file */ } TStream_Rec; typedef TStream_Rec* PStream_Rec;#define STREAM2REC( x ) ( (TStream_Rec*)HANDLE_Val( x ) )#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 ****/ /**** ****/ /*******************************************************************/ /*******************************************************************/ /*******************************************************************/ /* 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 */ PStream_Rec stream; /* current stream */ TFileFrame frame; /* current frame */ }; typedef struct _TFile_Component TFile_Component;/* 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. */#define CUR_Stream files.stream /* thread-safe macros */#define CUR_Frame files.frame#define STREAM_VARS /* void */#define STREAM_VAR /* void */ /* the 'files' variable is only defined in non-reentrant builds */ static TFile_Component files;/******************************************************************* * * Function : TTFile_Init * * Description : Initializes the File component. * ******************************************************************/ FT_INTERNAL_FUNC( TT_Error ) TTFile_Init( PEngine_Instance engine ) { MUTEX_Create( files.lock ); files.stream = NULL; ZERO_Frame( files.frame ); return TT_Err_Ok; }/******************************************************************* * * Function : TTFile_Done * * Description : Finalizes the File component. * ******************************************************************/ FT_INTERNAL_FUNC( TT_Error ) TTFile_Done( PEngine_Instance engine ) { 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 ); *stream = org_stream; files.stream = STREAM2REC( org_stream ); /* set current stream */ return TT_Err_Ok; }/******************************************************************* * * Function : TT_Done_Stream * * Description : Releases a given stream. * * Input : 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; }#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 ********/ /******** ********/ /*******************************************************************/ /*******************************************************************/ /*******************************************************************/#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 ) { engine.file_component = NULL; 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 : Copies or duplicates a given stream. * * Input : org_stream original stream * stream target stream (copy or duplicate) * * Output : Error code. The output stream is set to NULL in * case of Failure. * ******************************************************************/ FT_EXPORT_FUNC( TT_Error ) TT_Use_Stream( TT_Stream input_stream, TT_Stream* copy ) { TT_Error error; PStream_Rec stream_rec; PStream_Rec copy_rec; stream_rec = STREAM2REC( input_stream ); if ( ALLOC( copy_rec, sizeof ( TStream_Rec ) ) ) goto Fail; HANDLE_Set( *copy, copy_rec ); copy_rec->map->refcount++; copy_rec->pos = 0; return TT_Err_Ok; Fail: HANDLE_Set( *copy, NULL ); return error; }/******************************************************************* * * Function : TT_Done_Stream * * Description : Releases a given stream. * * Input : stream * * Output : error code * ******************************************************************/ FT_EXPORT_FUNC( TT_Error ) TT_Done_Stream( TT_Stream* stream ) { return TT_Close_Stream( stream ); }#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 : AllocateMap * * Description : Allocates a new map from the table. * * Output : Pointer to new stream rec. NULL in case of failure. * ******************************************************************/ static TFileMap* Allocate_Map( void ) { TFileMap* result; if ( MEM_Alloc( result, sizeof ( TFileMap ) ) ) return NULL; result->refcount = 1; return result; }/******************************************************************* * * Function : ReleaseMap * * Description : Releases a used map to the table if reference i * counter reaches zero. * * Input : map * * Output : None. * * Note : Called by TT_Close_File() * ******************************************************************/ static void Release_Map ( TFileMap* map ) { map->refcount--; if ( map->refcount <= 0 ) { /* MacOS System calls */ HUnlock(map->handle); ReleaseResource(map->handle); CloseResFile(map->resid); FREE( map ); } }/* Whadda ya mean "strdup undefined"? Fine, I'll define my own! */ static char * mystrdup( const char *str ) { char *ret; if ( TT_Alloc(strlen(str) + 1, (void**)&ret) != 0 ) return(NULL); strcpy(ret, str); return(ret); }/******************************************************************* * * 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 success, FAILURE on error. * The target stream is set to -1 in case of failure. * ******************************************************************//*** This is not a totally generic implementation. It currently assumes the filename** starts with "fonts:" and uses slashes instead of colons like Mac code normally** would. Given a filename of the form "fonts:/filename/resname", Load the resource** and lock the handle**** The "fonts:" at the beginning is just a convention I came up with to ** indicate the Fonts folder inside the current System folder (find via FindFolder())*/ FT_INTERNAL_FUNC( TT_Error ) TT_Open_Stream( const String* filepathname, TT_Stream* stream ) { TT_Error error; Int file; PStream_Rec stream_rec; TFileMap* map; int size, err = 0; short vRefNum, res = -1; Str255 FontName; char *cp, *p, *fname, *sep; Str63 myName; long dirID; if ( ALLOC( *stream, sizeof ( TStream_Rec ) ) ) return error; map = Allocate_Map(); if ( !map ) { error = TT_Err_Out_Of_Memory; goto Memory_Fail; } stream_rec = STREAM2REC( *stream ); /* Find the dirID of the Fonts folder in the current System folder */ if (FindFolder(kOnSystemDisk, kFontsFolderType, kDontCreateFolder, &vRefNum, &dirID)) goto File_Fail; /* Break the name apart */ fname = mystrdup(filepathname); /* Make a copy so we can muck with it */ sep = ":/"; /* Things that can seperate file path componants */ strtok(fname, sep); /* Skip over "fonts:" */ if ((p = strtok(NULL, sep)) == NULL) /* Get filename */ goto File_Fail; strcpy(myName + 1, p); /* Make this a Pascal string (Yuck!) */ myName[0] = strlen(p); if ((p = strtok(NULL, sep)) == NULL) /* Get res name */ goto File_Fail; strcpy(FontName+1, p); /* Make this a Pascal string (Yuck!) */ FontName[0] = strlen(p); FREE( fname ); if ((cp = strchr(FontName, '.')) != NULL) /* Strip off ".ttf" , if any */ *cp = 0; /* Read the font into a buffer */ if ((map->resid = HOpenResFile(vRefNum, dirID, myName, fsRdPerm)) == -1) goto File_Fail; if ((map->handle = Get1NamedResource('sfnt', FontName)) == NULL) goto Map_Fail; HLock(map->handle); map->base = *map->handle; map->offset = 0; map->size = GetResourceSizeOnDisk(map->handle); if ( map->base == NULL ) goto Lock_Fail; stream_rec->map = map; stream_rec->pos = 0;#ifndef TT_CONFIG_OPTION_THREAD_SAFE CUR_Stream = stream_rec;#endif return TT_Err_Ok; Lock_Fail: ReleaseResource(map->handle); Map_Fail: CloseResFile(map->resid); File_Fail: error = TT_Err_Could_Not_Open_File; FREE( map ); Memory_Fail: FREE( *stream ); FREE( fname ); return error; }/*******************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -