diff options
Diffstat (limited to 'Build/source/libs/t1lib/t1load.c')
-rw-r--r-- | Build/source/libs/t1lib/t1load.c | 1013 |
1 files changed, 1013 insertions, 0 deletions
diff --git a/Build/source/libs/t1lib/t1load.c b/Build/source/libs/t1lib/t1load.c new file mode 100644 index 00000000000..cce22e72c7f --- /dev/null +++ b/Build/source/libs/t1lib/t1load.c @@ -0,0 +1,1013 @@ +/*-------------------------------------------------------------------------- + ----- File: t1load.c + ----- Author: Rainer Menzner (Rainer.Menzner@web.de) + ----- Date: 2002-11-27 + ----- Description: This file is part of the t1-library. It contains + functions for loading fonts and for managing size + dependent data. + ----- Copyright: t1lib is copyrighted (c) Rainer Menzner, 1996-2002. + 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 + independent from X11. + Thanks to all people who make free software living! +--------------------------------------------------------------------------*/ + +#define T1LOAD_C + +/* + SU: Enabling this causes a segfault on OSF1/V5.1 alpha. Since it + appears to be an optimization only, I've disabled it until Rainer + has a fix. + */ +/* #define ANSI_REALLOC_VM */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#if defined(_MSC_VER) +# include <io.h> +# include <sys/types.h> +# include <sys/stat.h> +#else +# include <unistd.h> +#endif +#include <stdlib.h> +#include <math.h> +#include <string.h> + +#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/blues.h" +#include "../type1/regions.h" + + +#include "t1types.h" +#include "t1extern.h" +#include "t1load.h" +#include "t1env.h" +#include "t1set.h" +#include "t1base.h" +#include "t1finfo.h" +#include "t1afmtool.h" + + + +extern psobj *StdEncArrayP; /* For checking of a fonts encoding */ +extern char not_def[]; /* for checking the ".notdef"-string */ + + + +/* T1_LoadFont(FontID): Loads a Type1 font into memory and allocates all + memory, necessary for this. */ + +int T1_LoadFont( int FontID) +{ + int i, j, k, l, m; + char *FileName, *FileNamePath; + int mode; /* This is used by the type1-library for error reporting */ + char *charname; + + /* The following vars are used for reallocation of VM */ + long tmp_size; + float ascender; +#ifdef ANSI_REALLOC_VM + unsigned long shift; + unsigned long ldummy; + char *tmp_ptr; +#endif + + struct region *area; + struct XYspace *S; + + /* These are for constructing the kerning lookup table: */ + PairKernData *pkd; + METRICS_ENTRY *kern_tbl; + int char1, char2; + + + if (T1_CheckForInit()){ + T1_errno=T1ERR_OP_NOT_PERMITTED; + return(-1); + } + + + i=T1_CheckForFontID(FontID); + if (i==1) + return(0); /* Font already loaded */ + if (i==-1){ + T1_errno=T1ERR_INVALID_FONTID; + return(-1); /* illegal FontID */ + } + + /* Allocate memory for ps_font structure: */ + if ((pFontBase->pFontArray[FontID].pType1Data=(psfont *)malloc(sizeof(psfont)))==NULL){ + T1_PrintLog( "T1_LoadFont()", "Failed to allocate memory for psfont-struct (FontID=%d)", + T1LOG_ERROR, FontID); + T1_errno=T1ERR_ALLOC_MEM; + return(-1); + } + + /* Check for valid filename */ + if ((FileName=T1_GetFontFileName(FontID))==NULL){ + T1_PrintLog( "T1_LoadFont()", "No font file name for font %d", T1LOG_ERROR, FontID); + return(-1); + } + + /* Fetch the full path of type1 font file */ + if ((FileNamePath=intT1_Env_GetCompletePath( FileName, + T1_PFAB_ptr))==NULL){ + T1_PrintLog( "T1_LoadFont()", "Couldn't locate font file for font %d in %s", + T1LOG_ERROR, FontID, T1_GetFileSearchPath(T1_PFAB_PATH)); + T1_errno=T1ERR_FILE_OPEN_ERR; + return(-1); + } + + /* And load all PostScript information into memory */ + if (fontfcnA( FileNamePath, &mode, + pFontBase->pFontArray[FontID].pType1Data) == FALSE){ + T1_PrintLog( "T1_LoadFont()", "Loading font with ID = %d failed! (mode = %d)", + T1LOG_ERROR, FontID, mode); + free(FileNamePath); + pFontBase->pFontArray[FontID].pType1Data=NULL; + T1_errno=mode; + return(-1); + } + free(FileNamePath); + + + /* Store the base address of virtual memory and realloc in order not + to waste too much memory: */ + pFontBase->pFontArray[FontID].vm_base=vm_base; +#ifdef ANSI_REALLOC_VM + /* We first get the size of pointers on the current system */ + /* Get size of VM, ... */ + tmp_size=((unsigned long)vm_used - (unsigned long)vm_base); + /* ... realloc to that size ... */ + tmp_ptr=(char *)realloc(vm_base, tmp_size); + /* ... and shift all pointers refering to that area */ + if (tmp_ptr > vm_base){ + shift= (unsigned long)tmp_ptr - (unsigned long)vm_base; + sprintf( err_warn_msg_buf, + "Old VM at 0x%lX, new VM at 0x%lX, shifting up by %lu", + (unsigned long)vm_base, (unsigned long)tmp_ptr, tmp_size); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + + /* We start by shifting the topmost pointers: */ + pFontBase->pFontArray[FontID].vm_base=tmp_ptr; + + ldummy=(long)(pFontBase->pFontArray[FontID].pType1Data->vm_start); + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->vm_start=(char *)ldummy; + + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->CharStringsP=(psdict *)ldummy; + + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->Private=(psdict *)ldummy; + + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP=(psdict *)ldummy; + + ldummy=(long)(pFontBase->pFontArray[FontID].pType1Data->BluesP); + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->BluesP=(struct blues_struct *)ldummy; + + /* We now have to care for correcting all pointers which are in the VM + and refer to some place in the VM! Note: Instead of selecting the + appropriate pointer-elements of the union we simply shift the + unspecified pointer "valueP". + Note: The filename entry does not need to be modified since it does not + need to be shifted since it points to memory managed by t1lib. + */ + /* FontInfo-dictionary: All name-pointers and the pointers to all array + types have to be shifted: */ + i=pFontBase->pFontArray[FontID].pType1Data->fontInfoP[0].key.len; + for (j=1; j<=i; j++){ + if ((pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_ARRAY) || + (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_STRING) || + (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_NAME) || + (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_FILE)){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP=(char *)ldummy; + } + /* The encoding needs special treatment: */ + if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_ENCODING){ + /* If a builtin encoding is used, it is sufficient to shift the pointer + to the Encoding since the character-namestrings of builtin encodings + are static and thus located on the heap. + For font-specific encoding, character-namestrings reside in VM and + thus each entry has to be shifted. + Caution: We still have to shift the builtin encoding-pointer, since + they also point to are located in VM: */ + ldummy=(long)StdEncArrayP; + ldummy +=shift; + StdEncArrayP=(psobj *)ldummy; + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP=(char *)ldummy; + if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP + == StdEncArrayP){ /* Font uses builtin standard encoding */ + ; + } + else{ /* Font-specific encoding */ + for (k=0; k<256; k++){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP[k].data.arrayP; + /* The ".notdef" is also static and may not be shifted (Thanks, Derek ;) */ + if (ldummy != (unsigned long)not_def) { + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP[k].data.arrayP=(struct ps_obj *)ldummy; + } + } + } + } /* end of encoding-handling */ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].key.data.valueP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].key.data.valueP=(char *)ldummy; + } /* fontinfo-dict done */ + + /* Private-dictionary: All name-pointers and the pointers to all array + types have to be shifted: */ + i=pFontBase->pFontArray[FontID].pType1Data->Private[0].key.len; + for (j=1; j<=i; j++){ + if ((pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_ARRAY) || + (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_STRING) || + (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_NAME) || + (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_FILE)){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private[j].value.data.valueP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->Private[j].value.data.valueP=(char *)ldummy; + } + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private[j].key.data.valueP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->Private[j].key.data.valueP=(char *)ldummy; + } + + /* BluesP: The entry "next" is the only pointer in blues_struct. Although it is + not used anywhere we should shift it for correctness reasons (in case its not + NULL)! */ + if (pFontBase->pFontArray[FontID].pType1Data->BluesP->next != NULL){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->BluesP->next; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->BluesP->next=(struct blues_struct *)ldummy; + } + + /* The CharStrings-dictionary: Every namepointer and its corresponding + charstring has to be shifted: */ + i=pFontBase->pFontArray[FontID].pType1Data->CharStringsP[0].key.len; + for (j=1; j<=i; j++){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].value.data.valueP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].value.data.valueP=(char *)ldummy; + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].key.data.valueP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].key.data.valueP=(char *)ldummy; + } + + /* The Subroutines have also to be reorganized: */ + i=pFontBase->pFontArray[FontID].pType1Data->Subrs.len; + /* First, shift pointer to array-start and after that the pointers to + each command string: */ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP=(struct ps_obj *)ldummy; + for (j=0; j<i; j++) { + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP[j].data.valueP; + ldummy +=shift; + pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP[j].data.valueP=(char *)ldummy; + } + } /* end of if( tmp_ptr > vm_base ) */ + else if ( vm_base > tmp_ptr){ + shift= (unsigned long)vm_base - (unsigned long)tmp_ptr; + sprintf( err_warn_msg_buf, + "Old VM at 0x%lX, new VM at 0x%lX, shifting down by %lu", + (unsigned long)vm_base, (unsigned long)tmp_ptr, tmp_size); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + + /* We start by shifting the topmost pointers: */ + pFontBase->pFontArray[FontID].vm_base=tmp_ptr; + + ldummy=(long)(pFontBase->pFontArray[FontID].pType1Data->vm_start); + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->vm_start=(char *)ldummy; + + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->CharStringsP=(psdict *)ldummy; + + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->Private=(psdict *)ldummy; + + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP=(psdict *)ldummy; + + ldummy=(long)(pFontBase->pFontArray[FontID].pType1Data->BluesP); + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->BluesP=(struct blues_struct *)ldummy; + + /* We now have to care for correcting all pointers which are in the VM + and refer to some place in the VM! Note: Instead of selecting the + appropriate pointer-elements of the union we simply shift the + unspecified pointer "valueP". + Note: The filename entry does not need to be modified since it does not + need to be shifted since it points to memory managed by t1lib. + */ + /* FontInfo-dictionary: All name-pointers and the pointers to all array + types have to be shifted: */ + i=pFontBase->pFontArray[FontID].pType1Data->fontInfoP[0].key.len; + for (j=1; j<=i; j++){ + if ((pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_ARRAY) || + (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_STRING) || + (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_NAME) || + (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_FILE)){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP=(char *)ldummy; + } + /* The encoding needs special treatment: */ + if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_ENCODING){ + /* If a builtin encoding is used, it is sufficient to shift the pointer + to the Encoding since the character-namestrings of builtin encodings + are static and thus located on the heap. + For font-specific encoding, character-namestrings reside in VM and + thus each entry has to be shifted. + Caution: We still have to shift the builtin encoding-pointer, since + they also point to are located in VM: */ + ldummy=(long)StdEncArrayP; + ldummy -=shift; + StdEncArrayP=(psobj *)ldummy; + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP=(char *)ldummy; + if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP + == StdEncArrayP){ /* Font uses builtin encoding */ + ; + } + else{ /* Font-specific encoding */ + for (k=0; k<256; k++){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP[k].data.arrayP; + /* The ".notdef" is also static and may not be shifted (Thanks, Derek ;) */ + if (ldummy != (unsigned long)not_def) { + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP[k].data.arrayP=(struct ps_obj *)ldummy; + } + } + } + } /* end of encoding-handling */ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].key.data.valueP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].key.data.valueP=(char *)ldummy; + } /* fontinfo-dict done */ + + /* Private-dictionary: All name-pointers and the pointers to all array + types have to be shifted: */ + i=pFontBase->pFontArray[FontID].pType1Data->Private[0].key.len; + for (j=1; j<=i; j++){ + if ((pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_ARRAY) || + (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_STRING) || + (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_NAME) || + (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_FILE)){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private[j].value.data.valueP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->Private[j].value.data.valueP=(char *)ldummy; + } + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private[j].key.data.valueP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->Private[j].key.data.valueP=(char *)ldummy; + } + + /* BluesP: The entry "next" is the only pointer in blues_struct. Although it is + not used anywhere we should shift it for correctness reasons (in case its not + NULL)! */ + if (pFontBase->pFontArray[FontID].pType1Data->BluesP->next != NULL){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->BluesP->next; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->BluesP->next=(struct blues_struct *)ldummy; + } + + /* The CharStrings-dictionary: Every namepointer and its corresponding + charstring has to be shifted: */ + i=pFontBase->pFontArray[FontID].pType1Data->CharStringsP[0].key.len; + for (j=1; j<=i; j++){ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].value.data.valueP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].value.data.valueP=(char *)ldummy; + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].key.data.valueP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].key.data.valueP=(char *)ldummy; + } + + /* The Subroutines have also to be reorganized: */ + i=pFontBase->pFontArray[FontID].pType1Data->Subrs.len; + /* First, shift pointer to array-start and after that the pointers to + each command string: */ + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP=(struct ps_obj *)ldummy; + for (j=0; j<i; j++) { + ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP[j].data.valueP; + ldummy -=shift; + pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP[j].data.valueP=(char *)ldummy; + } + } /* end of if( vm_base > tmp_ptr ) */ + else{ /* VM addess has not changed during reallocation */ + sprintf( err_warn_msg_buf, + "Old VM and new VM at 0x%lX, no pointer-shifting", + (unsigned long)vm_base); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + } +#endif + + /* Generate a message how much VM the current font consumes */ + sprintf( err_warn_msg_buf, + "VM for Font %d: %d bytes", FontID, (int) tmp_size); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_STATISTIC); + + + /* Set the matrix for common transformations to "no transformations" */ + pFontBase->pFontArray[FontID].FontTransform[0]=1.0; + pFontBase->pFontArray[FontID].FontTransform[1]=0.0; + pFontBase->pFontArray[FontID].FontTransform[2]=0.0; + pFontBase->pFontArray[FontID].FontTransform[3]=1.0; + + /* Now, that the font has been loaded into memory, try to find the + FontMatrix in the font info dictionary. If it exists, load it into + our local fontmatrix, otherwise use a default matrix which scales to + 1/1000 (since font outlines are defined in a 1000 point space) + and does no further transformations. */ + if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP == NULL){ + pFontBase->pFontArray[FontID].FontMatrix[0]=0.001; + pFontBase->pFontArray[FontID].FontMatrix[1]=0.0; + pFontBase->pFontArray[FontID].FontMatrix[2]=0.0; + pFontBase->pFontArray[FontID].FontMatrix[3]=0.001; + } + else{ + pFontBase->pFontArray[FontID].FontMatrix[0]= (double)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP[0].data.real; + pFontBase->pFontArray[FontID].FontMatrix[1]= (double)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP[1].data.real; + pFontBase->pFontArray[FontID].FontMatrix[2]= (double)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP[2].data.real; + pFontBase->pFontArray[FontID].FontMatrix[3]= (double)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP[3].data.real; + } + + /* Set the default values for transformation: */ + pFontBase->pFontArray[FontID].slant=0.0; + pFontBase->pFontArray[FontID].extend=1.0; + + + /* Now try to load afm-structures from corresponding .afm-file (if + not suppressed by the user). */ + if ((pFontBase->t1lib_flags & T1_NO_AFM)!=0) { + pFontBase->pFontArray[FontID].pAFMData = NULL; + T1_PrintLog( "T1_LoadFont()", + "Suppressing AFM data handling on user request", + T1LOG_STATISTIC); + } + else { + if ((i=openFontMetricsFile( FontID, 0))){ + /* Try a fallback, opening sloppy: */ + if ((i=openFontMetricsFile( FontID, 1))) { + sprintf( err_warn_msg_buf, + "Alert: Error (%d) sloppy-processing afm-file for Font %d!", + i ,FontID); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_STATISTIC); + if ((pFontBase->pFontArray[FontID].pAFMData= + T1_GenerateAFMFallbackInfo(FontID))==NULL){ + sprintf( err_warn_msg_buf, + "Ultimately failed to generate metrics information Font %d!", + FontID); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_WARNING); + } + else { + pFontBase->pFontArray[FontID].info_flags |=AFM_SELFGEN_SUCCESS; + T1_PrintLog( "T1_LoadFont()", + "Generating AFM-information from fontfile successful!", + T1LOG_STATISTIC); + } + } + else { + pFontBase->pFontArray[FontID].info_flags |=AFM_SLOPPY_SUCCESS; + sprintf( err_warn_msg_buf, + "Alert: Limited afm-information for Font %d",FontID); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_STATISTIC); + } + } + else { + pFontBase->pFontArray[FontID].info_flags |=AFM_SUCCESS; + } + } + + + /* Now, set Encodingvector entry to default if the font's + internal encoding is "StandardEncoding". + */ + if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP + == StdEncArrayP) { + pFontBase->pFontArray[FontID].info_flags |=USES_STANDARD_ENCODING; + pFontBase->pFontArray[FontID].pFontEnc=pFontBase->default_enc; + sprintf( err_warn_msg_buf, + "Font %d reencoded to default",FontID); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + } + else { + sprintf( err_warn_msg_buf, + "Font %d not reencoded to default",FontID); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + pFontBase->pFontArray[FontID].pFontEnc = NULL; + } + + + /* If AFM-Info available we try to speed up some things: */ + if (pFontBase->pFontArray[FontID].pAFMData != NULL) { + /* We have to fill the array that maps the current encodings' indices to the + indices used in afm file. The interpretation has been changed in + in t1lib-1.2. We now use positive values for indexing into the charmetrics + array and negative values for indexing into the composite character array. + an index of zero indicates that no metrics are defined for this character. + This may happen because (a) not all AFM-files define metrics for the .notdef + character, and (b) because font and AFM-file do not match. */ + if ((pFontBase->pFontArray[FontID].pEncMap= + (int *)calloc(256,sizeof(int)))==NULL) { + sprintf( err_warn_msg_buf, "Error allocating memory for encoding map (FontID=%d)", + FontID); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, + T1LOG_WARNING); + T1_errno=T1ERR_ALLOC_MEM; + return(-1); + } + for (i=0; i<256; i++) { + charname=T1_GetCharName( FontID, i); + /* in a first loop check for ordinary characters */ + for ( j=0; j<pFontBase->pFontArray[FontID].pAFMData->numOfChars; j++) { + if (strcmp( charname, + pFontBase->pFontArray[FontID].pAFMData->cmi[j].name)==0) { + pFontBase->pFontArray[FontID].pEncMap[i]=j+1; /* index 0 is reserved! */ + continue; + } + } + /* if nothing has been found, check for composite characters */ + for ( j=0; j<pFontBase->pFontArray[FontID].pAFMData->numOfComps; j++) { + if (strcmp( charname, + pFontBase->pFontArray[FontID].pAFMData->ccd[j].ccName)==0) { + pFontBase->pFontArray[FontID].pEncMap[i]=-(j+1); /* index 0 is reserved! */ + continue; + } + } + } + + /* For composite characters, we still have to compute the width and bbox */ + for ( j=0; j<pFontBase->pFontArray[FontID].pAFMData->numOfComps; j++) { + /*and bounding box by ourselves. First, set up an identity charspace + matrix and then generate an edgelist for the composite character at + size 1000bp using no transformation and current encoding. Note: This + action is only required when loading a font at first time, but not + when reencoding a font. */ + S=(struct XYspace *)IDENTITY; + S=(struct XYspace *)Permanent + (Transform(S, pFontBase->pFontArray[FontID].FontTransform[0], + pFontBase->pFontArray[FontID].FontTransform[1], + pFontBase->pFontArray[FontID].FontTransform[2], + pFontBase->pFontArray[FontID].FontTransform[3])); + + area=fontfcnB_ByName( FontID, 0, S, + pFontBase->pFontArray[FontID].pAFMData->ccd[j].ccName, + &mode, pFontBase->pFontArray[FontID].pType1Data, + DO_RASTER); + /* Store bounding box ... */ + pFontBase->pFontArray[FontID].pAFMData->ccd[j].charBBox.llx=area->xmin; + pFontBase->pFontArray[FontID].pAFMData->ccd[j].charBBox.urx=area->xmax; + pFontBase->pFontArray[FontID].pAFMData->ccd[j].charBBox.lly=area->ymin; + pFontBase->pFontArray[FontID].pAFMData->ccd[j].charBBox.ury=area->ymax; + /* ... and character width. This should be the width of the base character + of the composite! */ + pFontBase->pFontArray[FontID].pAFMData->ccd[j].wx=NEARESTPEL(area->ending.x); + /* clean up. */ + KillRegion (area); + if (S!=NULL) { + KillSpace (S); + S=NULL; + } + } + /* We now create an encoding-specific kerning table which will speed up + looking for kerning pairs! */ + pFontBase->pFontArray[FontID].KernMapSize=0; + /* First, get number of defined kerning pairs: */ + k=pFontBase->pFontArray[FontID].pAFMData->numOfPairs; + if (k>0){ /* i.e., there are any pairs */ + /* OK, it does not suffice to alloc numOfPairs METRICS_ENTRYs, because + a given character might be encoded at several locations and kerning + should still work. As a worst case estimation, we allocate 256^2 + and realloc later. */ + if ((pFontBase->pFontArray[FontID].pKernMap= + (METRICS_ENTRY *)malloc( (256*256) *sizeof( METRICS_ENTRY)))==NULL){ + sprintf( err_warn_msg_buf, "Error allocating memory for metrics map (FontID=%d)", + FontID); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, + T1LOG_WARNING); + T1_errno=T1ERR_ALLOC_MEM; + return(-1); + } + kern_tbl=pFontBase->pFontArray[FontID].pKernMap; + pkd=pFontBase->pFontArray[FontID].pAFMData->pkd; + j=0; + for ( i=0; i<k; i++) { + /* We do not check T1_GetEncodingIndices() against the return value + NULL because we just loading the font in question: */ + l=0; + while ((char1=(T1_GetEncodingIndices( FontID, pkd[i].name1))[l++])!=-1) { + /* pair could be relevant in current encoding */ + m=0; + while ((char2=(T1_GetEncodingIndices( FontID, pkd[i].name2))[m++])!=-1) { + /* Since we get here we have a relevant pair --> + Put char1 in higher byte and char2 in LSB: */ + kern_tbl[j].chars=(char1 << 8) | char2; + /* We only make use of horizontal kerning */ + kern_tbl[j].hkern=pkd[i].xamt; + j++; + } /* while (char2) */ + } /* while (char1) */ + } /* for */ + /* We are done, realloc memory: */ + kern_tbl=(METRICS_ENTRY*) realloc( kern_tbl, j*sizeof(METRICS_ENTRY)); + /* We now sort the kerning array with respect to char indices */ + qsort( kern_tbl, (size_t) j, sizeof(METRICS_ENTRY), + &cmp_METRICS_ENTRY ); + /* Finally write back pointer for the case that realloc changed the + pointer */ + pFontBase->pFontArray[FontID].pKernMap=kern_tbl; + pFontBase->pFontArray[FontID].KernMapSize=j; + } + else + pFontBase->pFontArray[FontID].pKernMap=NULL; + } + else { /* no AFM data */ + pFontBase->pFontArray[FontID].pKernMap=NULL; + pFontBase->pFontArray[FontID].pEncMap=NULL; + } + /* End of "if (AFM-info ..)" */ + + + /* We have just loaded a physical font into memory, thus .... */ + pFontBase->pFontArray[FontID].physical=1; + + /* Set reference-counter to 1: */ + pFontBase->pFontArray[FontID].refcount=1; + + /* Get the index into encoding vector where the space character is + found. If not encoded, set space_position to -1. */ + pFontBase->pFontArray[FontID].space_position=-1; + i=0; + if (pFontBase->pFontArray[FontID].pFontEnc) { /* external default encoding */ + while (i<256) { + if (strcmp( (char *)pFontBase->pFontArray[FontID].pFontEnc[i], + "space")==0){ + /* space found at position i: */ + pFontBase->pFontArray[FontID].space_position=i; + break; + } + i++; + } + } + else { /* internal encoding */ + while (i<256) { + if (strcmp( (char *)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[i].data.arrayP, + "space")==0){ + /* space found at position i: */ + pFontBase->pFontArray[FontID].space_position=i; + break; + } + i++; + } + } + + + /* Set the lining rule parameters to default values */ + pFontBase->pFontArray[FontID].UndrLnPos= + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[UNDERLINEPOSITION].value.data.real; + pFontBase->pFontArray[FontID].UndrLnThick= + pFontBase->pFontArray[FontID].pType1Data->fontInfoP[UNDERLINETHICKNESS].value.data.real; + + /* We have to set the value for the typographic ascender. If possible, + we get it from the afm-File. But be aware this value might be undefined! + This value should in any acse explicitly be set later by the user! */ + if (pFontBase->pFontArray[FontID].pAFMData!=NULL && + pFontBase->pFontArray[FontID].pAFMData->gfi!=NULL) { + ascender=(float) pFontBase->pFontArray[FontID].pAFMData->gfi->ascender; + } + else { + ascender=(float) T1_GetCharBBox( FontID, T1_GetEncodingIndex( FontID, "d")).ury; + } + + pFontBase->pFontArray[FontID].OvrLnPos=ascender + + (float) abs( (double)pFontBase->pFontArray[FontID].UndrLnPos); + pFontBase->pFontArray[FontID].OvrStrkPos=ascender / 2.0; + pFontBase->pFontArray[FontID].OvrLnThick=pFontBase->pFontArray[FontID].UndrLnThick; + pFontBase->pFontArray[FontID].OvrStrkThick=pFontBase->pFontArray[FontID].UndrLnThick; + + + /* Finally, set the font size dependencies pointer to NULL since we can + assume, that at load time of a font, no size specific data of this + font is available. + */ + + pFontBase->pFontArray[FontID].pFontSizeDeps=NULL; + + /* If wanted, some debugging information is put into logfile */ + sprintf( err_warn_msg_buf, "Pointer vm_base: 0x%lX", + (long)pFontBase->pFontArray[FontID].vm_base); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + sprintf( err_warn_msg_buf, "Pointer vm_start: 0x%lX", + (long)pFontBase->pFontArray[FontID].pType1Data->vm_start); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + sprintf( err_warn_msg_buf, "Pointer CharStringsP: 0x%lX", + (long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + sprintf( err_warn_msg_buf, "Pointer Private: 0x%lX", + (long)pFontBase->pFontArray[FontID].pType1Data->Private); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + sprintf( err_warn_msg_buf, "Pointer fontInfoP: 0x%lX", + (long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP); + T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG); + + return(0); +} + + +/* openFontMetricsFile( FontID, open_sloppy): Gets the fontfilename + corresponding to FontID, opens the corresponding afm-file and fills + the data structures. return-value is the value returned by the + T1lib_parseFile() function. If open_sloppy is set, the minimum + information needed is read from AFM file. This can be considered a + fallback for problematic AFM files. */ +static int openFontMetricsFile( int FontID, int open_sloppy) +{ + char *FontFileName; + char *AFMFileName; + char *afm_name; + char *AFMFileNamePath; + + int i, j; + FILE *metricsfile; + + + afm_name=T1_GetAfmFileName(FontID); + + if (afm_name!=NULL) { /* We have name explicitly specified */ + /* It needs to be freeable */ + if ((AFMFileName= + (char *)malloc( (strlen(afm_name)+1)*sizeof( char)))==NULL) { + T1_errno=T1ERR_ALLOC_MEM; + return( -6); + } + strcpy( AFMFileName, afm_name); + } + else { + FontFileName=T1_GetFontFileName( FontID); + i=strlen(FontFileName); + j=i; + AFMFileName=(char *)malloc( i+5); + strcpy( AFMFileName, FontFileName); + while ( AFMFileName[i] != '.'){ + if (i==0) break; + else i--; + } + if (i==0){ + /* We have a filename without extension -> append extension */ + AFMFileName[j]='.'; + AFMFileName[j+1]='a'; + AFMFileName[j+2]='f'; + AFMFileName[j+3]='m'; + AFMFileName[j+4]='\0'; + } + else{ + /* we found a '.' -> replace extension */ + AFMFileName[i+1]='a'; + AFMFileName[i+2]='f'; + AFMFileName[i+3]='m'; + AFMFileName[i+4]='\0'; + } + } + + /* Get full path of the afm file (The case of a full path name + name specification is valid */ + AFMFileNamePath=intT1_Env_GetCompletePath( AFMFileName, T1_AFM_ptr); + free( AFMFileName); + + /* open afm-file: */ + if (AFMFileNamePath!=NULL){ + if ((metricsfile=fopen(AFMFileNamePath,"rb"))==NULL){ + free(AFMFileNamePath); + return(-4); + } + else { + free(AFMFileNamePath); + } + } + else{ + return( -5); + } + + /* Call procedure to read afm-file and store the data formatted. + Flags used here: P_M All Metrics Information + P_P Pair Kerning Information + P_C Composite Character Data (since t1lib V.1.2) + The P_G flag to get global font information should not be used + if not absolutely needed. When parsing an unknown keyword, which + may be harmless, the T1lib_parseFile function returns the error code + -1 (parseError). On the other hand, all other really relevant + data may habe been parsed and stored correctly. In such a case, + There's no way to make a serious decision whether an error has + occured or not. + */ + if (open_sloppy!=0) + i=T1lib_parseFile( (FILE *) metricsfile, + (FontInfo **) &(FontBase.pFontArray[FontID].pAFMData), + P_M ); + else + i=T1lib_parseFile( (FILE *) metricsfile, + (FontInfo **) &(FontBase.pFontArray[FontID].pAFMData), + P_G | P_M | P_P | P_C ); + fclose(metricsfile); + return(i); +} + + + +/* T1int_CreateNewFontSize( FontID, size): Create a new size "size" of font + "FontID" and allocate all data necessary for this. The data + structure is connected to the linked list of FontSizeDeps for this + font. Returns a pointer to the newly created FontSizeDeps-struct + if all went correct and NULL otherwise. + Since of version 0.3 a member antialias has been added to the + FONTSIZEDEPS structure! This can be: + + 0: bitmaps are stored in this struct + 1: non-antialiased bytemaps are stored in this struct + 2: low-antialiased bytemaps are stored in this struct + 4: high-antialiased bytemaps are stored in this struct + */ +FONTSIZEDEPS *T1int_CreateNewFontSize( int FontID, float size, int aa) +{ + + FONTSIZEDEPS *pFontSizeDeps, *pPrev; + + + /* First, get to the last font size in the linked list for this font. + The following routine returns the address of the last struct in the + linked list of FONTSIZEDEPS or NULL if none exists. */ + pFontSizeDeps=T1int_GetLastFontSize( FontID); + pPrev=pFontSizeDeps; + + + if (pFontSizeDeps==NULL){ + /* Allocate memory for first FontSizeDeps-structure: */ + if ((pFontBase->pFontArray[FontID].pFontSizeDeps=(FONTSIZEDEPS *)malloc(sizeof(FONTSIZEDEPS)))==NULL){ + T1_errno=T1ERR_ALLOC_MEM; + return(NULL); + } + pFontSizeDeps=pFontBase->pFontArray[FontID].pFontSizeDeps; + } + else{ + /* A valid address of an existing structure was found */ + if ((pFontSizeDeps->pNextFontSizeDeps=(FONTSIZEDEPS *)malloc(sizeof(FONTSIZEDEPS)))==NULL){ + T1_errno=T1ERR_ALLOC_MEM; + return(NULL); + } + pFontSizeDeps=pFontSizeDeps->pNextFontSizeDeps; + } + + /* The pointer to the previous struct */ + pFontSizeDeps->pPrevFontSizeDeps=pPrev; + /* Put the size into this structure */ + pFontSizeDeps->size=size; + /* Set the antialias mark: */ + pFontSizeDeps->antialias=aa; + + /* Just the current becomes now the last item in the linked list: */ + pFontSizeDeps->pNextFontSizeDeps=NULL; + /* Setup CharSpaceMatrix for this font: */ + pFontSizeDeps->pCharSpaceLocal=(struct XYspace *) IDENTITY; + /* Apply transformation with font matrix: */ + pFontSizeDeps->pCharSpaceLocal=(struct XYspace *) + Transform(pFontSizeDeps->pCharSpaceLocal, + pFontBase->pFontArray[FontID].FontMatrix[0], + pFontBase->pFontArray[FontID].FontMatrix[1], + pFontBase->pFontArray[FontID].FontMatrix[2], + pFontBase->pFontArray[FontID].FontMatrix[3]); + /* Apply a further transformation (optionally): */ + pFontSizeDeps->pCharSpaceLocal=(struct XYspace *) + Transform(pFontSizeDeps->pCharSpaceLocal, + pFontBase->pFontArray[FontID].FontTransform[0], + pFontBase->pFontArray[FontID].FontTransform[1], + pFontBase->pFontArray[FontID].FontTransform[2], + pFontBase->pFontArray[FontID].FontTransform[3]); + /* Apply desired scaling factor, and make it Permanent */ + pFontSizeDeps->pCharSpaceLocal=(struct XYspace *) Permanent + (Scale(pFontSizeDeps->pCharSpaceLocal, size, size)); + + /* We should now allocate memory for the glyph area of the font + cache: */ + if ((pFontSizeDeps->pFontCache=(GLYPH *)calloc(256,sizeof(GLYPH))) + ==NULL) + return(NULL); + + sprintf( err_warn_msg_buf, "New Size %f created for FontID %d (antialias=%d)", + pFontSizeDeps->size, FontID, pFontSizeDeps->antialias); + T1_PrintLog( "CreateNewFontSize()", err_warn_msg_buf, T1LOG_STATISTIC); + /* We are done */ + return(pFontSizeDeps); + +} + + + + +/* T1_QueryFontSize( FontID, size, aa): Search if a requested size of font + FontID is already existing. If so, it returns a pointer to the + respective FontSizeDeps-structure, otherwise NULL is returned: */ +FONTSIZEDEPS *T1int_QueryFontSize( int FontID, float size, int aa) +{ + + FONTSIZEDEPS *link_ptr; + + + /* There's not yet one size: */ + if (pFontBase->pFontArray[FontID].pFontSizeDeps == NULL) + return(pFontBase->pFontArray[FontID].pFontSizeDeps); + + + /* There's already existing one or more size */ + link_ptr=pFontBase->pFontArray[FontID].pFontSizeDeps; + + while (((link_ptr->size != size)||(link_ptr->antialias != aa)) + &&(link_ptr->pNextFontSizeDeps != NULL)) + link_ptr=link_ptr->pNextFontSizeDeps; + + if ((link_ptr->size != size)||(link_ptr->antialias != aa)) + return( NULL); /* requested size/aa-combination was not found */ + else + return(link_ptr); /* return pointer to requested struct */ + +} + +/* FONTSIZEDEPS *T1int_GetLastFontSize( FontID): Get the address of the + last struct in the linked list of FontSizeDeps or NULL if there is + no existing size dependent data. */ +FONTSIZEDEPS *T1int_GetLastFontSize( int FontID) +{ + FONTSIZEDEPS *link_ptr, *result_ptr; + + + /* There's not yet one size: */ + if (pFontBase->pFontArray[FontID].pFontSizeDeps == NULL) + return((FONTSIZEDEPS *) (pFontBase->pFontArray[FontID].pFontSizeDeps)); + + + /* There's already existing one or more size */ + link_ptr=pFontBase->pFontArray[FontID].pFontSizeDeps; + + while (link_ptr != NULL){ + result_ptr=link_ptr; + link_ptr=link_ptr->pNextFontSizeDeps; + } + + return((FONTSIZEDEPS *)(result_ptr)); +} + + +/* A function for comparing METRICS_ENTRY structs */ +static int cmp_METRICS_ENTRY( const void *entry1, const void *entry2) +{ + if (((METRICS_ENTRY *)entry1)->chars < + ((METRICS_ENTRY *)entry2)->chars) + return(-1); + if (((METRICS_ENTRY *)entry1)->chars > + ((METRICS_ENTRY *)entry2)->chars) + return(1); + return(0); /* This should not happen */ +} + + |