/*-------------------------------------------------------------------------- ----- File: t1base.c ----- Author: Rainer Menzner (Rainer.Menzner@web.de) ----- Date: 2004-03-04 ----- Description: This file is part of the t1-library. It contains basic routines to initialize the data structures used by the t1-library. ----- Copyright: t1lib is copyrighted (c) Rainer Menzner, 1996-2004. As of version 0.5, t1lib is distributed under the GNU General Public Library Lincense. The conditions can be found in the files LICENSE and LGPL, which should reside in the toplevel directory of the distribution. Please note that there are parts of t1lib that are subject to other licenses: The parseAFM-package is copyrighted by Adobe Systems Inc. The type1 rasterizer is copyrighted by IBM and the X11-consortium. ----- Warranties: Of course, there's NO WARRANTY OF ANY KIND :-) ----- Credits: I want to thank IBM and the X11-consortium for making their rasterizer freely available. Also thanks to Piet Tutelaers for his ps2pk, from which I took the rasterizer sources in a format independ from X11. Thanks to all people who make free software living! --------------------------------------------------------------------------*/ #define T1BASE_C #include #include #include #include #if defined(_MSC_VER) # include # include # include #else # include #endif #include #include #include #include #include #include #include "../type1/ffilest.h" #include "../type1/types.h" #include "parseAFM.h" #include "../type1/objects.h" #include "../type1/spaces.h" #include "../type1/util.h" #include "../type1/fontfcn.h" #include "../type1/regions.h" #include "sysconf.h" #include "t1base.h" #include "t1types.h" #include "t1global.h" #include "t1env.h" #include "t1delete.h" static int test_for_t1_file( char *buffer ); static int T1_pad=0; /* A fix for Encoding Vector problem. Initialization / Deinitialization is now done in T1_InitLib() / T1-CloseLib. */ extern boolean Init_BuiltInEncoding( void); extern psobj *StdEncArrayP; static const char* T1errmsg[] = { "", /* -10 */ "", /* -9 */ "", /* -8 */ "", /* -7 */ "", /* -6 */ "Attempt to Load Multiple Master Font", /* T1ERR_SCAN_FONT_FORMAT -5 */ "Type 1 Font File Open Error", /* T1ERR_SCAN_FILE_OPEN_ERR -4 */ "Virtual Memory Exceeded", /* T1ERR_SCAN_OUT_OF_MEMORY -3 */ "Syntactical Error Scanning Font File", /* T1ERR_SCAN_ERROR -2 */ "Premature End of Font File Encountered", /* T1ERR_SCAN_FILE_EOF -1 */ "", /* 0 */ "Path Construction Error", /* T1ERR_PATH_ERROR 1 */ "Font is Corrupt", /* T1ERR_PARSE_ERROR 2 */ "Rasterization Aborted", /* T1ERR_TYPE1_ABORT 3 */ "", /* 4 */ "", /* 5 */ "", /* 6 */ "", /* 7 */ "", /* 8 */ "", /* 9 */ "Font ID Invalid in this Context", /* T1ERR_INVALID_FONTID 10 */ "Invalid Argument in Function Call", /* T1ERR_INVALID_PARAMETER 11 */ "Operation not Permitted", /* T1ERR_OP_NOT_PERMITTED 12 */ "Memory Allocation Error", /* T1ERR_ALLOC_MEM 13 */ "Error Opening File", /* T1ERR_FILE_OPEN_ERR 14 */ "Unspecified T1Lib Error", /* T1ERR_UNSPECIFIED 15 */ "Missing AFM Data", /* T1ERR_NO_AFM_DATA 16 */ "X11 Interface Error", /* T1ERR_X11 17 */ "Missing Component of Composite Character" /* T1ERR_COMPOSITE_CHAR 18 */ "Error Scanning Encoding File", /* T1ERR_SCAN_ENCODING 19 */ "", /* 20 */ }; /* T1_StrError(): Return an error message corresponding to the value of t1err. */ const char *T1_StrError( int t1err) { int errind; errind = t1err + 10; if ( errind < 0 ) errind = 0; if ( errind > 29 ) errind = 0; return T1errmsg[errind]; } /* This function is to be called by the user to initialize the font mechanism */ void *T1_InitLib( int log) { int result; int i; char *usershome=NULL; char *logfilepath=NULL; char *envlogreq=NULL; int usrforcelog=0; /* Reset T1_errno */ T1_errno=0; /* Assign pointer to global struct and set entry padding: */ pFontBase=&FontBase; if (T1_pad) pFontBase->bitmap_pad=T1_pad; else pFontBase->bitmap_pad=T1GLYPH_PAD; pFontBase->pFontArray = NULL; pFontBase->t1lib_flags=0; /* Check for AA-caching */ if ((log & T1_AA_CACHING)){ pFontBase->t1lib_flags |= T1_AA_CACHING; } /* Check for AFM disable */ if ((log & T1_NO_AFM)) { pFontBase->t1lib_flags |= T1_NO_AFM; } /* Check environment variable ENV_LOG_STRING. By this means, a user may generate a log file even if at compile time log file creation has been suppressed. Of course, if the loglevel is reduced after initialization by the programmer, this environment variable takes no effect! */ if ((envlogreq=getenv(ENV_LOG_STRING))!=NULL) { if (strcmp( envlogreq, "logDebug")==0) T1_SetLogLevel( T1LOG_DEBUG); else if (strcmp( envlogreq, "logStatistic")==0) T1_SetLogLevel( T1LOG_STATISTIC); else if (strcmp( envlogreq, "logWarning")==0) T1_SetLogLevel( T1LOG_WARNING); else if (strcmp( envlogreq, "logError")==0) T1_SetLogLevel( T1LOG_ERROR); usrforcelog=1; } /* Open log-file: */ t1lib_log_file=NULL; if ((log & LOGFILE) || (usrforcelog!=0)) { pFontBase->t1lib_flags |= LOGFILE; /* Try first opening in current directory: */ if ((t1lib_log_file=fopen( T1_LOG_FILE, "wb"))==NULL) { if ((usershome=getenv("HOME"))!=NULL) { logfilepath=(char *)malloc((strlen(usershome) + strlen(T1_LOG_FILE) + 2 ) * sizeof(char)); strcpy( logfilepath, usershome); strcat( logfilepath, DIRECTORY_SEP); strcat( logfilepath, T1_LOG_FILE); if ((t1lib_log_file=fopen( logfilepath, "wb"))==NULL){ t1lib_log_file=stderr; } free( logfilepath); } else { t1lib_log_file=stderr; } } if (t1lib_log_file==stderr) { T1_PrintLog( "T1_InitLib()", "Unable to open a logfile, using stderr", T1LOG_ERROR); } } T1_PrintLog( "T1_InitLib()", "Initialization started", T1LOG_STATISTIC); /* Check for representation of data in memory: */ if ((pFontBase->endian=T1_CheckEndian())){ T1_PrintLog( "T1_InitLib()", "Using Big Endian data presentation (MSBFirst)", T1LOG_DEBUG); pFontBase->endian=1; } else{ T1_PrintLog( "T1_InitLib()", "Using Little Endian data presentation (LSBFirst)", T1LOG_DEBUG); pFontBase->endian=0; } /* Save version identifier */ sprintf( err_warn_msg_buf, "Version Identifier: %s", T1LIB_IDENT); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); /* Save how t1lib is initialized */ sprintf( err_warn_msg_buf, "Initialization flags: 0x%X", log); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); /* Save padding value in log file */ sprintf( err_warn_msg_buf, "Glyphs are padded to %d bits", pFontBase->bitmap_pad); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); #ifdef __CHAR_UNSIGNED__ T1_PrintLog( "T1_InitLib()", "System-Info: char is unsigned", T1LOG_DEBUG); #else T1_PrintLog( "T1_InitLib()", "System-Info: char is signed", T1LOG_DEBUG); #endif sprintf( err_warn_msg_buf, "System-Info: sizeof(char): %d", SIZEOF_CHAR); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); sprintf( err_warn_msg_buf, "System-Info: sizeof(short): %d", SIZEOF_SHORT); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); sprintf( err_warn_msg_buf, "System-Info: sizeof(int): %d", SIZEOF_INT); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); sprintf( err_warn_msg_buf, "System-Info: sizeof(long): %d", SIZEOF_LONG); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); sprintf( err_warn_msg_buf, "System-Info: sizeof(long long): %d", SIZEOF_LONG_LONG); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); sprintf( err_warn_msg_buf, "System-Info: sizeof(float): %d", SIZEOF_FLOAT); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); sprintf( err_warn_msg_buf, "System-Info: sizeof(double): %d", SIZEOF_DOUBLE); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); sprintf( err_warn_msg_buf, "System-Info: sizeof(long double): %d", SIZEOF_LONG_DOUBLE); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); sprintf( err_warn_msg_buf, "System-Info: sizeof(void *): %d", SIZEOF_VOID_P); T1_PrintLog( "T1_InitLib()", err_warn_msg_buf, T1LOG_DEBUG); intT1_SetupDefaultSearchPaths(); if (log & IGNORE_CONFIGFILE) { pFontBase->t1lib_flags |= IGNORE_CONFIGFILE; T1_PrintLog( "T1_InitLib()", "Skipping configuration file search!", T1LOG_STATISTIC); } else { if ((result=intT1_ScanConfigFile())==0) T1_PrintLog( "T1_InitLib()", "Warning t1lib configuration file not found!", T1LOG_WARNING); } /* Initialize builtin Standard Encoding */ if ( !(Init_BuiltInEncoding()) ) { T1_PrintLog( "T1_InitLib()", "Unable initialize internal StandardEncoding!", T1LOG_ERROR); } /* Set the default encoding to the fonts' internal encoding */ pFontBase->default_enc=NULL; /* Initialize the no_fonts... values */ pFontBase->no_fonts=0; pFontBase->no_fonts_ini=pFontBase->no_fonts; pFontBase->no_fonts_limit=pFontBase->no_fonts; /* Check whether to read font database */ if ((log & IGNORE_FONTDATABASE)){ pFontBase->t1lib_flags |= IGNORE_FONTDATABASE; T1_Up=1; /* System has been initialized ! */ T1_PrintLog( "T1_InitLib()", "Initialization successfully finished (Database empty)", T1LOG_STATISTIC); return((void *) pFontBase); } result=0; /* Read fontdatabase(s) */ i=0; while (T1_FDB_ptr[i]!=NULL) { if ((result=intT1_scanFontDBase(T1_FDB_ptr[i]))==-1){ T1_PrintLog( "T1_InitLib()", "Fatal error scanning Font Database File %s", T1LOG_WARNING, T1_FDB_ptr[i]); } if (result>-1) pFontBase->no_fonts+=result; i++; } if (result == 0){ T1_PrintLog( "T1_InitLib()", "No fonts from Font Database File(s) found (T1_errno=%d)", T1LOG_ERROR, T1_errno); return(NULL); } /* Initialize the no_fonts... values */ pFontBase->no_fonts_ini=pFontBase->no_fonts; pFontBase->no_fonts_limit=pFontBase->no_fonts; T1_Up=1; /* System has been initialized ! */ T1_PrintLog( "T1_InitLib()", "Initialization successfully finished", T1LOG_STATISTIC); return((void *) pFontBase); } /* intT1_scanFontDBase(): - opens the file with the font definitions, - reads the number of fonts defined and saves this in FontBase, - allocates memory for all the filenames of the Type1 files - tests for .pfa und .pfb files and saves the name found - initializes an array that allows to acces these names by an index number, the font_ID - returns -1 on fatal error and the number of fonts located successfullly */ int intT1_scanFontDBase( char *filename) { int fd; int filesize, i, j, k, m; int found=0, located=0; char *filebuffer; int nofonts=0; FONTPRIVATE* fontarrayP=NULL; #ifndef O_BINARY # define O_BINARY 0x0 #endif if ((fd=open( filename, O_RDONLY | O_BINARY))<3){ T1_PrintLog( "intT1_scanFontDBase()", "Font Database File %s not found!", T1LOG_WARNING, filename); T1_errno=T1ERR_FILE_OPEN_ERR; return(-1); } /* Get the file size */ filesize=lseek( fd, 0, 2); /* Reset fileposition to start */ lseek (fd, 0, 0); if ((filebuffer=(char *)malloc(filesize*sizeof(char) )) == NULL){ T1_PrintLog( "intT1_scanFontDBase()", "Couldn't allocate memory for loading font database file %s", T1LOG_ERROR, filename); T1_errno=T1ERR_ALLOC_MEM; return(-1); } i=read( fd, filebuffer, filesize); close(fd); /* Close font database file */ i=j=m=0; while (inofonts) /* to ignore especially white space at end */ break; i++; /* Step further in file position */ } /* Return the memory for file reading */ free(filebuffer); return( found); } /* T1_CloseLib(): Close the library and free all associated memory */ int T1_CloseLib( void) { int i, j, error=0; if (T1_Up){ for (i=pFontBase->no_fonts; i; i--){ /* Free filename only if not NULL and if the font is physical! Do it before removing the font since the physical information is no more available afterwards. If necessary, an explicitly specified AFM filename is also freed. */ if ((pFontBase->pFontArray[i-1].pFontFileName!=NULL) && (pFontBase->pFontArray[i-1].physical==1)){ free( pFontBase->pFontArray[i-1].pFontFileName); pFontBase->pFontArray[i-1].pFontFileName=NULL; if (pFontBase->pFontArray[i-1].pAfmFileName!=NULL){ free( pFontBase->pFontArray[i-1].pAfmFileName); pFontBase->pFontArray[i-1].pAfmFileName=NULL; } } /* Now, remove font: */ if ((j=T1_DeleteFont( i-1))){ error=1; sprintf( err_warn_msg_buf, "T1_DeleteFont() returned %d for Font %d", j, i-1); T1_PrintLog( "T1_CloseLib()", err_warn_msg_buf, T1LOG_ERROR); } } /* Free the FONTPRIVATE area */ if (pFontBase->pFontArray) free( pFontBase->pFontArray); else error=1; /* Get rid of internal StandardEncoding vector */ if ( StdEncArrayP != NULL ) { free( StdEncArrayP); StdEncArrayP = NULL; } /* Free search paths */ intT1_FreeSearchPaths(); /* Reset the flags */ pFontBase->t1lib_flags=0; /* Indicate Library is no longer initialized */ pFontBase=NULL; T1_Up=0; T1_PrintLog( "T1_CloseLib()", "Library closed", T1LOG_STATISTIC); if ((t1lib_log_file!=NULL) && (t1lib_log_file!=stderr)) fclose(t1lib_log_file); t1lib_log_file=NULL; } return( error); } /* T1_AddFont(): Add a new fontfile to the fontdatabase. Return values: >0: Assigned FontID -1: Fontfile not found -2: Error allocating memory for FONTPRIVATE-area -3: No memory for saving font filename */ int T1_AddFont( char *fontfilename) { char *FullName; FONTPRIVATE *save_ptr; int i; int new_ID; if (fontfilename==NULL){ T1_errno=T1ERR_INVALID_PARAMETER; return(-1); } /* Check for existence of fontfile */ if ((FullName=intT1_Env_GetCompletePath(fontfilename,T1_PFAB_ptr))==NULL) { T1_errno=T1ERR_FILE_OPEN_ERR; return(-1); } free(FullName); /* Check if free space for a new FONTPRIVATE is available; if not, realloc memory some amount larger */ save_ptr=pFontBase->pFontArray; if (pFontBase->no_fonts==pFontBase->no_fonts_limit){ if (pFontBase->pFontArray == NULL) { /* In case this is the first font */ pFontBase->pFontArray=(FONTPRIVATE *)calloc(pFontBase->no_fonts_limit + ADVANCE_FONTPRIVATE, sizeof(FONTPRIVATE)); } else { /* We already have some fonts */ pFontBase->pFontArray=(FONTPRIVATE *)realloc(pFontBase->pFontArray, (pFontBase->no_fonts_limit + ADVANCE_FONTPRIVATE) * sizeof(FONTPRIVATE)); if (pFontBase->pFontArray==NULL){ /* Restore pointer */ pFontBase->pFontArray=save_ptr; T1_errno=T1ERR_ALLOC_MEM; return(-2); /* No memory available */ } } pFontBase->no_fonts_limit += ADVANCE_FONTPRIVATE; /* First, initialize newly allocated to be not used */ for ( i=pFontBase->no_fonts; ino_fonts+ADVANCE_FONTPRIVATE; i++){ pFontBase->pFontArray[i].pFontFileName=NULL; pFontBase->pFontArray[i].pAfmFileName=NULL; pFontBase->pFontArray[i].pAFMData=NULL; pFontBase->pFontArray[i].pType1Data=NULL; pFontBase->pFontArray[i].pEncMap=NULL; pFontBase->pFontArray[i].pKernMap=NULL; pFontBase->pFontArray[i].pFontEnc=NULL; pFontBase->pFontArray[i].pFontSizeDeps=NULL; pFontBase->pFontArray[i].vm_base=NULL; pFontBase->pFontArray[i].FontMatrix[0]=0.0; pFontBase->pFontArray[i].FontMatrix[1]=0.0; pFontBase->pFontArray[i].FontMatrix[2]=0.0; pFontBase->pFontArray[i].FontMatrix[3]=0.0; pFontBase->pFontArray[i].FontTransform[0]=0.0; pFontBase->pFontArray[i].FontTransform[1]=0.0; pFontBase->pFontArray[i].FontTransform[2]=0.0; pFontBase->pFontArray[i].FontTransform[3]=0.0; pFontBase->pFontArray[i].slant=0.0; pFontBase->pFontArray[i].extend=0.0; pFontBase->pFontArray[i].physical=0; pFontBase->pFontArray[i].refcount=0; pFontBase->pFontArray[i].space_position=0; pFontBase->pFontArray[i].info_flags=0; } } /* no_fonts-1 was the largest allowed font ID */ new_ID=pFontBase->no_fonts; pFontBase->no_fonts++; if ((FontBase.pFontArray[new_ID].pFontFileName=(char *) calloc( strlen( fontfilename)+1, sizeof(char))) == NULL){ T1_PrintLog( "T1_AddFont()", "Failed to allocate memory for Filename %s (FontID=%d)", T1LOG_ERROR, fontfilename, new_ID); T1_errno=T1ERR_ALLOC_MEM; return(-3); } strcpy( FontBase.pFontArray[new_ID].pFontFileName, fontfilename); /* Generate logfile entry */ sprintf( err_warn_msg_buf, "Assigned FontID %d to fontfile %s", new_ID, FontBase.pFontArray[new_ID].pFontFileName); T1_PrintLog( "T1_AddFont()", err_warn_msg_buf, T1LOG_STATISTIC); /* Return FontID of newly declared font */ return( new_ID); } /* T1_PrintLog() generates entries in the log file. msg_txt is subject to scan conversion and ... signifies a accordingly lrge variable list. */ void T1_PrintLog( char *func_ident, char *msg_txt, int level, ...) { va_list vararg; static char levelid[4]={ 'E', 'W', 'S', 'D'}; time_t s_clock, *tp; if (t1lib_log_file==NULL) return; if ((level>t1lib_log_level) || (level<1)){ return; } else{ /* initialize argument list */ va_start( vararg, level); tp=&s_clock; s_clock=time( tp); /* fprintf( t1lib_log_file, "(%c) (%.24s) %s: ", levelid[level-1], ctime(&s_clock), func_ident); */ /* Don't print the time stamp */ fprintf( t1lib_log_file, "(%c) %s: ", levelid[level-1], func_ident ); vfprintf( t1lib_log_file, msg_txt, vararg ); fprintf( t1lib_log_file, "\n"); fflush( t1lib_log_file); /* cleanup variable list */ va_end( vararg); return; } } /* T1_SetLogLevel(): Set the level which a message must have so that it is printed into the logfile. This function may be called before T1_InitLib(). */ void T1_SetLogLevel( int level) { if ((level>0) && (level<5)) t1lib_log_level=level; return; } /* T1_CheckForInit(): If no initialization of font mechanism has been done, return -1, indicating an error. */ int T1_CheckForInit(void) { if(T1_Up) return(0); else return(-1); } /* T1_CheckForFontID(): Checks the font mechanism concerning the specified ID. It returns: 0 if font belonging to FontID has not yet been loaded 1 if font belonging to FontID has already been loaded -1 if FontID is an invalid specification or t1lib not initialized */ int T1_CheckForFontID( int FontID) { /* FontID is invalid */ if ((FontID<0)||(FontID>(pFontBase->no_fonts - 1))||(T1_Up==0)) return(-1); if (pFontBase->pFontArray[FontID].pType1Data==NULL) return(0); /* has not yet been loaded */ else return(1); /* has already been loaded */ } /* test_for_t1_file returns 0 if a file "name.pfa" or "name.pfb" was found. Else, -1 is returned. If successful, buffer contains the found filename string */ static int test_for_t1_file( char *buffer ) { int i=0; char *FullName; /* First case: A PostScript Font ASCII File without extension (according to some UNIX-conventions) */ if ((FullName=intT1_Env_GetCompletePath(buffer,T1_PFAB_ptr))!=NULL) { free(FullName); return(0); } while (buffer[i]!=0){ i++; } buffer[i]='.'; buffer[i+1]='p'; buffer[i+2]='f'; buffer[i+4]=0; /* Second case: A PostScript Font ASCII File */ buffer[i+3]='a'; if ((FullName=intT1_Env_GetCompletePath(buffer,T1_PFAB_ptr))!=NULL) { free(FullName); return(0); } /* Third case: A PostScript Font Binary File */ buffer[i+3]='b'; if ((FullName=intT1_Env_GetCompletePath(buffer,T1_PFAB_ptr))!=NULL) { free(FullName); return(0); } /* If we get here no file was found => Set buffer to an empty string and return -1 */ buffer[0]=0; return(-1); } /* T1_GetFontFileName() returns a pointer to the filename of the font, associated with FontID. This filename does not contain a full path. */ char *T1_GetFontFileName( int FontID) { static char filename[MAXPATHLEN+1]; if (T1_CheckForInit())return(NULL); /* Check first for valid FontID */ if ((FontID<0) || (FontID>FontBase.no_fonts)){ T1_errno=T1ERR_INVALID_FONTID; return(NULL); } strcpy( filename, pFontBase->pFontArray[FontID].pFontFileName); return( filename); } /* As suggested by Nicolai Langfeldt, we make it possible to specify a completely independent path for the afm filename. This should make t1lib usable in context with using the kpathsearch-library. We allow setting those path´s after initialization, but before a font is loaded. returns 0: OK -1: Operation could not be performed */ int T1_SetAfmFileName( int FontID, char *afm_name) { if (T1_CheckForFontID(FontID)!=0){ /* Operation may not be applied because FontID is invalid or font is loaded */ T1_errno=T1ERR_INVALID_FONTID; return(-1); } if (afm_name==NULL) { T1_errno=T1ERR_INVALID_PARAMETER; return(-1); } if (pFontBase->pFontArray[FontID].pAfmFileName!=NULL){ /* we first free the current name */ free( pFontBase->pFontArray[FontID].pAfmFileName); pFontBase->pFontArray[FontID].pAfmFileName=NULL; } if ((pFontBase->pFontArray[FontID].pAfmFileName= (char *)malloc( (strlen(afm_name)+1)*sizeof( char)))==NULL) { T1_errno=T1ERR_ALLOC_MEM; return( -1); } strcpy( pFontBase->pFontArray[FontID].pAfmFileName, afm_name); return(0); } /* We have a function for querying the name. Returns a pointer to the string or NULL if name was not explicitly set .*/ char *T1_GetAfmFileName( int FontID) { static char filename[MAXPATHLEN+1]; if (T1_CheckForInit())return(NULL); /* Check first for valid FontID */ if ((FontID<0) || (FontID>FontBase.no_fonts)){ T1_errno=T1ERR_INVALID_FONTID; return(NULL); } if (pFontBase->pFontArray[FontID].pAfmFileName==NULL) { return( NULL); } strcpy( filename, pFontBase->pFontArray[FontID].pAfmFileName); return( filename); } /* T1_GetNoFonts(): Return the number of declared fonts */ int T1_GetNoFonts(void) { if (T1_CheckForInit()) return(-1); return(FontBase.no_fonts); } /* T1_SetDeviceResolutions( x_res, y_res): Set the device's physical resolution in horizontal and vertical direction, mesured in DPI (Dots Per Inch). This should be done before the first font is loaded! */ int T1_SetDeviceResolutions( float x_res, float y_res) { int i; if (T1_CheckForInit()) ; /* Not initialized -> no size dependent data -> OK */ else /* Check if size-dependent data is existent */ for ( i=T1_GetNoFonts(); i; i--) if (pFontBase->pFontArray[i-1].pFontSizeDeps!=NULL){ T1_errno=T1ERR_OP_NOT_PERMITTED; return(-1); /* There's is size dependent data for a font */ } /* Save resolutions and calculate horizontal and vertical scale factors to map desired bp to device pixel */ DeviceSpecifics.x_resolution=(float) x_res; DeviceSpecifics.y_resolution=(float) y_res; DeviceSpecifics.scale_x=(float)(((float)x_res)/BIGPOINTSPERINCH); DeviceSpecifics.scale_y=(float)(((float)y_res)/BIGPOINTSPERINCH); return(0); } /* T1_QueryX11Support(): Check at runtime to see if t1lib was compiled with X11 interface: */ int T1_QueryX11Support( void) { #ifndef T1LIB_NO_X11_SUPPORT return(1); #else return(0); #endif } /* int T1_CopyFont(): Copies the font associated with FontID to another location. The pointers to type1- , afm- and encoding data as well as the matrices remain completely untouched. However, size dependent data is not copied. The produced font is marked as a "logical" font. If no memory is available in the FONTPRIVATE-array, there's realloc'ed some more memory. The FontID which is assigned to the newly generated font is given as the return value, or < 0 if an error occurs. Also, the refcount entry of the source font is incremented by one. Return value -1: invalid FontID specified -2: source font is not a "physical" font -3: no memory for reallocation of FONTPRIVATEs -4: no memory for one of the mapping tables */ int T1_CopyFont( int FontID) { FONTPRIVATE *save_ptr; int k; int new_ID; /* Check for a valid source font */ if (T1_CheckForFontID(FontID)!=1){ T1_errno=T1ERR_INVALID_FONTID; return(-1); } /* Check if the font in question is a "physical" font, otherwise it may not be copied */ if (pFontBase->pFontArray[FontID].physical==0){ T1_errno=T1ERR_OP_NOT_PERMITTED; return(-2); } /* Check if free space for a new FONTPRIVATE is available; if not, realloc memory some amount larger */ save_ptr=pFontBase->pFontArray; if (pFontBase->no_fonts==pFontBase->no_fonts_limit){ pFontBase->pFontArray=(FONTPRIVATE *)realloc(pFontBase->pFontArray, (pFontBase->no_fonts_limit + ADVANCE_FONTPRIVATE) * sizeof(FONTPRIVATE)); if (pFontBase->pFontArray==NULL){ /* Restore pointer */ pFontBase->pFontArray=save_ptr; T1_errno=T1ERR_ALLOC_MEM; return(-3); } /* We zero the newly allocated memory */ if (pFontBase->pFontArray != NULL) { memset( pFontBase->pFontArray + pFontBase->no_fonts_limit, 0, ADVANCE_FONTPRIVATE * sizeof(FONTPRIVATE)); } pFontBase->no_fonts_limit += ADVANCE_FONTPRIVATE; } /* no_fonts-1 was the largest allowed font ID */ new_ID=pFontBase->no_fonts; /* Copy FONTPRIVATE-structure: */ pFontBase->pFontArray[new_ID]=pFontBase->pFontArray[FontID]; /* (Re)Set some values explicitly, others remain untouched: */ pFontBase->pFontArray[new_ID].pFontSizeDeps=NULL; pFontBase->pFontArray[new_ID].physical=0; /* AFM-mapping tables are to be setup for logical fonts separately (if AFM data is there) */ /* first, kerning map */ if (pFontBase->pFontArray[new_ID].pAFMData) { k=pFontBase->pFontArray[new_ID].pAFMData->numOfPairs; if (k>0){ /* kern map exists only if kerning pairs exist! */ if ((pFontBase->pFontArray[new_ID].pKernMap= (METRICS_ENTRY *)malloc( k*sizeof( METRICS_ENTRY)))==NULL){ sprintf( err_warn_msg_buf, "Error allocating memory for kerning map (new_ID=%d)", new_ID); T1_PrintLog( "T1_CopyFont()", err_warn_msg_buf, T1LOG_WARNING); T1_errno=T1ERR_ALLOC_MEM; return(-4); } memcpy( pFontBase->pFontArray[new_ID].pKernMap, pFontBase->pFontArray[FontID].pKernMap, k*sizeof( METRICS_ENTRY)); } else { /* no kerning pairs, bu AFM data present */ pFontBase->pFontArray[new_ID].pKernMap=NULL; } } else { /* AFM data not present at all */ pFontBase->pFontArray[new_ID].pKernMap=NULL; } /* second, encoding map */ if (pFontBase->pFontArray[FontID].pEncMap!=NULL) { if ((pFontBase->pFontArray[new_ID].pEncMap= (int *)calloc(256,sizeof(int)))==NULL){ sprintf( err_warn_msg_buf, "Error allocating memory for encoding map (new_ID=%d)", new_ID); T1_PrintLog( "T1_CopyFont()", err_warn_msg_buf, T1LOG_WARNING); T1_errno=T1ERR_ALLOC_MEM; return(-4); } memcpy( pFontBase->pFontArray[new_ID].pEncMap, pFontBase->pFontArray[FontID].pEncMap, 256*sizeof( int)); } /* New font is logical --> indicate to which physical font it refers by setting refcount: */ pFontBase->pFontArray[new_ID].refcount=FontID; /* Now the struct is setup; increment no_fonts by 1 because new_ID is a valid font specification from now on. */ pFontBase->no_fonts++; /* Increment refcount in source font */ pFontBase->pFontArray[FontID].refcount++; /* Generate logfile entry */ sprintf( err_warn_msg_buf, "Assigned FontID %d to fontfile %s", new_ID, FontBase.pFontArray[new_ID].pFontFileName); T1_PrintLog( "T1_CopyFont()", err_warn_msg_buf, T1LOG_STATISTIC); return(new_ID); } /* T1_SetBitmapPad(): Set the value to which bitmap-scanlines are padded. This has to be done before initialization because it is a very rudimentary operation. */ int T1_SetBitmapPad( int pad) { if (T1_Up){ /* Library is initialized --> return error */ T1_errno=T1ERR_OP_NOT_PERMITTED; return(-1); } else{ switch (pad){ case 8: T1_pad=8; return(0); case 16: T1_pad=16; return(0); #ifdef T1_AA_TYPE64 case 32: T1_pad=32; return(0); #endif default: T1_errno=T1ERR_INVALID_PARAMETER; return(-1); } } } /* T1_GetBitmapPad(): Read the value to which scanlines of bitmap are padded. This can be done before or after initialization. */ int T1_GetBitmapPad( void) { if (pFontBase) /* T1lib initialized --> return value from struct */ return( pFontBase->bitmap_pad); else{ if (T1_pad) return(T1_pad); /* pad is explicitly set --> return that value */ else return( T1GLYPH_PAD); /* not expl. set --> return compilation default */ } } /* CheckEndian(): Checks whether the current machine is of little or big endian architecture. This is important for concatenating bitmaps. Function returns 0 if LittleEndian and 1 if BigEndian representation is used on the current hardware. */ int T1_CheckEndian() { unsigned char *charptr; /* Generate test value */ unsigned short test=0x0001; /* Read out memory as unsigned char */ charptr=(unsigned char *)(&test)+1; /* Return value will be 1 if Big- and 0 if Little Endian */ return((int) *charptr); } /* T1_GetLibIdent(): Return the identifier string for the current version of t1lib */ char *T1_GetLibIdent( void) { static char buf[15]; sprintf( buf, "%s", T1LIB_IDENT); return( (char *)buf); } /* T1_SetRasterFlags(): Enable/Disable certain features in the rasterizer */ extern void T1_SetRasterFlags( int flags) { T1_Type1OperatorFlags=flags; return; } /* T1_GetFontFileName(): returns a pointer to the complete path filename of the font, associated with FontID as it is in use by t1lib. */ char *T1_GetFontFilePath( int FontID) { static char filepath[MAXPATHLEN+1]; char *FileNamePath=NULL; /* is initialzed? */ if (T1_CheckForInit()) { T1_errno=T1ERR_INVALID_FONTID; return(NULL); } /* Check first for valid FontID */ if ((FontID<0) || (FontID>FontBase.no_fonts)){ T1_errno=T1ERR_INVALID_FONTID; return(NULL); } /* lib is initialized and FontID is valid -> we can really expect a name */ if ((FileNamePath=intT1_Env_GetCompletePath( pFontBase->pFontArray[FontID].pFontFileName, T1_PFAB_ptr))==NULL) { T1_PrintLog( "T1_GetFontFilePath()", "Couldn't locate font file for font %d in %s", T1LOG_WARNING, FontID, T1_GetFileSearchPath(T1_PFAB_PATH)); T1_errno=T1ERR_FILE_OPEN_ERR; return(NULL); } strcpy( filepath, FileNamePath); free( FileNamePath); return( filepath); } /* We have a function for querying the name. Returns a pointer to the string or NULL if name was not explicitly set .*/ char *T1_GetAfmFilePath( int FontID) { static char filepath[MAXPATHLEN+1]; char *FontFileName; char *AFMFilePath; int i, j; /* is initialized? */ if ((T1_CheckForInit())) { T1_errno=T1ERR_INVALID_FONTID; return(NULL); } /* Check first for valid FontID */ if ((FontID<0) || (FontID>FontBase.no_fonts)){ T1_errno=T1ERR_INVALID_FONTID; return(NULL); } /* Check wether AFM-file loading was suppressed on user's request */ if ((pFontBase->t1lib_flags & T1_NO_AFM)!=0) { /* this is no error condition, we simply return (NULL) */ return( NULL); } /* Check for explicitly associated metrics filename (via "T1_SetAfmFileName()"). If it exists, we return it! */ if (pFontBase->pFontArray[FontID].pAfmFileName!=NULL) { strcpy( filepath, pFontBase->pFontArray[FontID].pAfmFileName); sprintf( err_warn_msg_buf, "Returning explicitly specified path %s for Font %d", filepath, FontID); T1_PrintLog( "T1_GetAfmFilePath()", err_warn_msg_buf, T1LOG_DEBUG); return( filepath); } /* we have the usual case that the name of the metrics file has to be deduced from the font file name */ FontFileName=T1_GetFontFileName( FontID); i=strlen(FontFileName); j=i; strcpy( filepath, FontFileName); while ( filepath[i] != '.'){ if (i==0) break; else i--; } if (i==0){ /* We have a filename without extension -> append extension */ filepath[j]='.'; filepath[j+1]='a'; filepath[j+2]='f'; filepath[j+3]='m'; filepath[j+4]='\0'; } else{ /* we found a '.' -> replace extension */ filepath[i+1]='a'; filepath[i+2]='f'; filepath[i+3]='m'; filepath[i+4]='\0'; } /* Get full path of the afm file (The case of a full path name name specification is valid) */ if ((AFMFilePath=intT1_Env_GetCompletePath( filepath, T1_AFM_ptr)) == NULL) { return NULL; } strcpy( filepath, AFMFilePath); free( AFMFilePath); return( filepath); }