Back to index

tetex-bin  3.0
t1finfo.c
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------------
00002   ----- File:        t1finfo.c 
00003   ----- Author:      Rainer Menzner (Rainer.Menzner@web.de)
00004   ----- Date:        2003-01-04
00005   ----- Description: This file is part of the t1-library. It contains
00006                      functions for accessing afm-data and some other
00007                    fontinformation data.
00008   ----- Copyright:   t1lib is copyrighted (c) Rainer Menzner, 1996-2003. 
00009                      As of version 0.5, t1lib is distributed under the
00010                    GNU General Public Library Lincense. The
00011                    conditions can be found in the files LICENSE and
00012                    LGPL, which should reside in the toplevel
00013                    directory of the distribution.  Please note that 
00014                    there are parts of t1lib that are subject to
00015                    other licenses:
00016                    The parseAFM-package is copyrighted by Adobe Systems
00017                    Inc.
00018                    The type1 rasterizer is copyrighted by IBM and the
00019                    X11-consortium.
00020   ----- Warranties:  Of course, there's NO WARRANTY OF ANY KIND :-)
00021   ----- Credits:     I want to thank IBM and the X11-consortium for making
00022                      their rasterizer freely available.
00023                    Also thanks to Piet Tutelaers for his ps2pk, from
00024                    which I took the rasterizer sources in a format
00025                    independent from X11.
00026                      Thanks to all people who make free software living!
00027 --------------------------------------------------------------------------*/
00028   
00029 #define T1FINFO_C
00030 
00031 
00032 #include <stdio.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <fcntl.h>
00036 #if defined(_MSC_VER)
00037 # include <io.h>
00038 # include <sys/types.h>
00039 # include <sys/stat.h>
00040 #else
00041 # include <unistd.h>
00042 #endif
00043 #include <stdlib.h>
00044 #include <math.h>
00045 #include <string.h>
00046 
00047 #include "../type1/ffilest.h" 
00048 #include "../type1/types.h"
00049 #include "parseAFM.h" 
00050 #include "../type1/objects.h"
00051 #include "../type1/spaces.h"
00052 #include "../type1/util.h"
00053 #include "../type1/fontfcn.h"
00054 #include "../type1/regions.h"
00055 
00056 
00057 #include "t1types.h"
00058 #include "t1extern.h"
00059 #include "t1finfo.h"
00060 #include "t1base.h"
00061 #include "t1misc.h"
00062 #include "t1set.h"
00063 #include "t1load.h"
00064 
00065 
00066 /* The following variable controls the computation of the bbox internal
00067    to T1_GetMetricsInfo(). Its influence may be overridden by the
00068    global variable ForceAFMBBox: */
00069 static int ForceAFMBBoxInternal=0;
00070 
00071 
00072 extern int ForceAFMBBox;
00073 extern char *t1_get_abort_message( int number);
00074   
00075 
00076 /* int T1_GetKerning(): This function returns the amount of kerning that
00077    is specified in the afm-file for the supplied character-pair. If an
00078    an extension has been applied to the font in question, this is taken
00079    into account.
00080    If for whatever reason there's no afm information available (that's not
00081    deadly), simply 0 is returned, indicating that no kerning should be used.
00082    The value returned is meant to be in character space coordinates. Thus,
00083    it must be transformed to be applicable in device space.
00084    */
00085 int T1_GetKerning( int FontID, char char1, char char2)
00086 {
00087   METRICS_ENTRY entry;
00088   METRICS_ENTRY *target_pair=NULL;
00089   
00090 
00091   /* Check whether font is loaded: */
00092   if (T1_CheckForFontID(FontID)!=1){
00093     T1_errno=T1ERR_INVALID_FONTID;
00094     return(0);
00095   }
00096 
00097   /* If no AFM info is present, we return an error */
00098   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
00099     T1_errno=T1ERR_NO_AFM_DATA;
00100     return( 0);
00101   }
00102 
00103   /* if there's no kerning info, return immediately */
00104   if (pFontBase->pFontArray[FontID].KernMapSize==0)
00105     return( 0);
00106   
00107   entry.chars=(char1<<8) | char2;
00108   if ((target_pair=(METRICS_ENTRY *)
00109        bsearch( &entry, pFontBase->pFontArray[FontID].pKernMap,
00110               (size_t) pFontBase->pFontArray[FontID].KernMapSize,
00111               sizeof(METRICS_ENTRY),
00112               &cmp_METRICS_ENTRY))==NULL)
00113     return(0);
00114   else
00115     return( target_pair->hkern * pFontBase->pFontArray[FontID].extend);
00116   
00117 }
00118 
00119 
00120 
00121 /* int T1_GetCharWidth(): This function returns the characterwidth
00122    specified in the .afm-file. If no .afm-file is loaded for that font,
00123    0 is returned. Note that if one tries to raster strings, afm data
00124    must always be available. The returned character width is corrected
00125    using  a possibly applied font extension!
00126    */
00127 int T1_GetCharWidth( int FontID, char char1)
00128 {
00129   unsigned char uchar1;
00130 
00131   uchar1=(unsigned char) char1;
00132   
00133   /* Check whether font is loaded: */
00134   if (T1_CheckForFontID(FontID)!=1){
00135     T1_errno=T1ERR_INVALID_FONTID;
00136     return(0);
00137   }
00138   
00139   /* If no AFM info is present, we return an error */
00140   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
00141     T1_errno=T1ERR_NO_AFM_DATA;
00142     return( 0);
00143   }
00144   
00145   /* return appriate value */
00146   if (pFontBase->pFontArray[FontID].pEncMap[(int) uchar1]>0) { /* ordinary character */
00147     return((int) ((pFontBase->pFontArray[FontID].pAFMData->cmi[pFontBase->pFontArray[FontID].pEncMap[(int) uchar1]-1].wx) * pFontBase->pFontArray[FontID].extend));
00148   }
00149   else if (pFontBase->pFontArray[FontID].pEncMap[(int) uchar1]<0) { /* composite character */
00150     return((int) ((pFontBase->pFontArray[FontID].pAFMData->ccd[-(pFontBase->pFontArray[FontID].pEncMap[(int) uchar1]+1)].wx) * pFontBase->pFontArray[FontID].extend));
00151   }
00152   else { /* undefined or .notdef */
00153     return(0);
00154   }
00155   
00156 }
00157 
00158 
00159 
00160 /* T1_GetCharBBox(): Get the BoundingBox of specified character. If an
00161    extension factor has been applied to the font in question, this
00162    is taken into account. However, a slant factor which has been applied
00163    to the font, also affects the bounding box of a character. The
00164    only way to determine its influence on the character bounding box
00165    is to compute the exact shape of that slanted character. There's no
00166    simple way to extract the new bounding box from the former bounding
00167    box. Thus, if a font has been slanted, the characters outline itself
00168    is examined. Since this must be done at 1000 bp it takes considerably
00169    longer than reading afm data. */
00170 BBox T1_GetCharBBox( int FontID, char char1)
00171 {
00172 
00173   struct region *area;
00174   struct XYspace *S;    
00175   int mode=0;
00176   int i;
00177   
00178   BBox NullBBox= { 0, 0, 0, 0}; /* A bounding box containing all 0's. */
00179   BBox ResultBox= { 0, 0, 0, 0}; /* The Box returned if char is found */
00180   
00181   unsigned char uchar1;
00182 
00183 
00184   /* We return to this if something goes wrong deep in the rasterizer */
00185   if ((i=setjmp( stck_state))!=0) {
00186     T1_errno=T1ERR_TYPE1_ABORT;
00187     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
00188             t1_get_abort_message( i));
00189     T1_PrintLog( "T1_GetCharBBox()", err_warn_msg_buf,
00190               T1LOG_ERROR);
00191     return( NullBBox);
00192   }
00193 
00194   
00195   uchar1=(unsigned char) char1;
00196   
00197   /* Check whether font is loaded: */
00198   if (T1_CheckForFontID(FontID)!=1){
00199     T1_errno=T1ERR_INVALID_FONTID;
00200     return(NullBBox);
00201   }
00202 
00203   /* If no AFM info is present, we return an error */
00204   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
00205     T1_errno=T1ERR_NO_AFM_DATA;
00206     return( NullBBox);
00207   }
00208   
00209   
00210   /* Check for a font slant */
00211   if ((pFontBase->pFontArray[FontID].slant!=0.0)
00212       &&(ForceAFMBBox==0)
00213       &&(ForceAFMBBoxInternal==0)){
00214     /* We have a font slant -> character outline must be examined in order
00215        to determine bounding box */
00216     /* Set up an identity charspace matrix 
00217        and take a slant and an extension into account */
00218     /* And make it permanent, to plug a memory leak */
00219     S=(struct XYspace *)IDENTITY;
00220     S=(struct XYspace *)Permanent
00221       (Transform(S, pFontBase->pFontArray[FontID].FontTransform[0],
00222                pFontBase->pFontArray[FontID].FontTransform[1],
00223                pFontBase->pFontArray[FontID].FontTransform[2],
00224                pFontBase->pFontArray[FontID].FontTransform[3]));
00225     /* Genrate an edgelist for the current character at size 1000bp
00226        using current transformation and encoding: */
00227     area=fontfcnB( FontID, 0, S,
00228                  pFontBase->pFontArray[FontID].pFontEnc,
00229                  (int) uchar1, &mode,
00230                  pFontBase->pFontArray[FontID].pType1Data,
00231                  DO_RASTER,0.0f);
00232     /* Read out bounding box */
00233     ResultBox.llx =area->xmin;
00234     ResultBox.urx =area->xmax;
00235     ResultBox.lly =area->ymin;
00236     ResultBox.ury =area->ymax;
00237     
00238     /* Reset AFM-switch and return BBox */
00239     ForceAFMBBoxInternal=0;
00240     /* make sure to destroy 'area' before leaving! */
00241     KillRegion (area);
00242     /* make sure to free S */
00243     if (S) {
00244       KillSpace (S);
00245     }
00246     return(ResultBox);
00247   }
00248   else{
00249     /* Assign bounding box for the different cases: */
00250     /* Check if character is  */
00251     if (pFontBase->pFontArray[FontID].pEncMap[(int) uchar1]>0) { /* ordinary char */
00252       ResultBox=(pFontBase->pFontArray[FontID].pAFMData->cmi[pFontBase->pFontArray[FontID].pEncMap[(int) uchar1]-1].charBBox);
00253     }
00254     else if (pFontBase->pFontArray[FontID].pEncMap[(int) uchar1]<0) { /* composite char */
00255       ResultBox=(pFontBase->pFontArray[FontID].pAFMData->ccd[-(pFontBase->pFontArray[FontID].pEncMap[(int) uchar1]+1)].charBBox);
00256     }
00257     else { /* undefined char */
00258       return(NullBBox);
00259     }
00260     
00261     /* .. and apply transformations: */
00262     ResultBox.llx *=pFontBase->pFontArray[FontID].extend;
00263     ResultBox.urx *=pFontBase->pFontArray[FontID].extend;
00264     
00265     return(ResultBox);
00266   }
00267 }
00268 
00269 
00270 
00271 /* int T1_GetUnderlinePosition(): Return underline position of specified
00272    font in charspace units. If 0 is returned, it indicated that the font
00273    is not yet loaded into memory. or an invalid ID has been specified. */
00274 float T1_GetUnderlinePosition( int FontID)
00275 {
00276   if (T1_CheckForFontID(FontID)!=1){
00277     T1_errno=T1ERR_INVALID_FONTID;
00278     return(0.0);
00279   }
00280   
00281   return((float)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[UNDERLINEPOSITION].value.data.real));
00282 }
00283 
00284 
00285 
00286 /* int T1_GetUnderlineThickness(): Return underline thickness of specified
00287    font in charspace units. If 0 is returned, it indicated that the font
00288    is not yet loaded into memory. or an invalid ID has been specified. */
00289 float T1_GetUnderlineThickness( int FontID)
00290 {
00291   if (T1_CheckForFontID(FontID)!=1){
00292     T1_errno=T1ERR_INVALID_FONTID;
00293     return(0.0);
00294   }
00295   
00296   return((float)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[UNDERLINETHICKNESS].value.data.real));
00297 }
00298 
00299 
00300 /* int T1_ItalicAngle(): Return underline position of specified
00301    font in charspace units. If 0.0 is returned, it indicated that the font
00302    is not yet loaded into memory. or an invalid ID has been specified. */
00303 float T1_GetItalicAngle( int FontID)
00304 {
00305   if (T1_CheckForFontID(FontID)!=1){
00306     T1_errno=T1ERR_INVALID_FONTID;
00307     return(0.0);
00308   }
00309   
00310   return((float)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ITALICANGLE].value.data.real));
00311 }
00312 
00313 
00314 
00315 /* int T1_GetUnderlinePosition(): Return underline position of specified
00316    font in charspace units. If 0 is returned, it indicated that the font
00317    is not yet loaded into memory. or an invalid ID has been specified. */
00318 int T1_GetIsFixedPitch( int FontID)
00319 {
00320   if (T1_CheckForFontID(FontID)!=1){
00321     T1_errno=T1ERR_INVALID_FONTID;
00322     return(0.0);
00323   }
00324   
00325   return((int)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ISFIXEDPITCH].value.data.boolean));
00326 }
00327 
00328 
00329 
00330 /* char *T1_GetFontName( FontID): Get the PostScript FontName of
00331    the  font dictionary associated with the specified font, or NULL if
00332    an error occurs. */
00333 char *T1_GetFontName( int FontID)
00334 {
00335   static char fontname[MAXPSNAMELEN];
00336   
00337   if (T1_CheckForFontID(FontID)!=1){
00338     T1_errno=T1ERR_INVALID_FONTID;
00339     return(NULL);
00340   }
00341   
00342   strncpy(fontname,
00343          (char *)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTNAME].value.data.nameP),
00344          pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTNAME].value.len);
00345   fontname[pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTNAME].value.len]=0;
00346     
00347   return(fontname);
00348   
00349 }
00350 
00351 
00352 /* char *T1_GetFullName( FontID): Get the Full Name from
00353    the  font dictionary associated with the specified font, or NULL if
00354    an error occurs. */
00355 char *T1_GetFullName( int FontID)
00356 {
00357   static char fullname[MAXPSNAMELEN];
00358   
00359   if (T1_CheckForFontID(FontID)!=1){
00360     T1_errno=T1ERR_INVALID_FONTID;
00361     return(NULL);
00362   }
00363   
00364   strncpy(fullname,
00365          (char *)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FULLNAME].value.data.nameP),
00366          pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FULLNAME].value.len);
00367   fullname[pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FULLNAME].value.len]=0;
00368     
00369   return(fullname);
00370   
00371 }
00372 
00373 
00374 /* char *T1_GetFamilyName( FontID): Get the Family Name of
00375    the  font dictionary associated with the specified font, or NULL if
00376    an error occurs. */
00377 char *T1_GetFamilyName( int FontID)
00378 {
00379   static char familyname[MAXPSNAMELEN];
00380   
00381   if (T1_CheckForFontID(FontID)!=1){
00382     T1_errno=T1ERR_INVALID_FONTID;
00383     return(NULL);
00384   }
00385   
00386   strncpy(familyname,
00387          (char *)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FAMILYNAME].value.data.nameP),
00388          pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FAMILYNAME].value.len);
00389   familyname[pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FAMILYNAME].value.len]=0;
00390     
00391   return(familyname);
00392   
00393 }
00394 
00395 
00396 /* char *T1_GetWeight( FontID): Get the Weight entry from
00397    the  font dictionary associated with the specified font, or NULL if
00398    an error occurs. */
00399 char *T1_GetWeight( int FontID)
00400 {
00401   static char weight[128];
00402   
00403   if (T1_CheckForFontID(FontID)!=1){
00404     T1_errno=T1ERR_INVALID_FONTID;
00405     return(NULL);
00406   }
00407   
00408   strncpy(weight,
00409          (char *)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[WEIGHT].value.data.nameP),
00410          pFontBase->pFontArray[FontID].pType1Data->fontInfoP[WEIGHT].value.len);
00411   weight[pFontBase->pFontArray[FontID].pType1Data->fontInfoP[WEIGHT].value.len]=0;
00412     
00413   return(weight);
00414   
00415 }
00416 
00417 
00418 /* char *T1_GetFontName( FontID): Get the Version entry from 
00419    the  font dictionary associated with the specified font, or NULL if
00420    an error occurs. */
00421 char *T1_GetVersion( int FontID)
00422 {
00423   static char version[2048];
00424   
00425   if (T1_CheckForFontID(FontID)!=1){
00426     T1_errno=T1ERR_INVALID_FONTID;
00427     return(NULL);
00428   }
00429   
00430   strncpy(version,
00431          (char *)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[VERSION].value.data.nameP),
00432          pFontBase->pFontArray[FontID].pType1Data->fontInfoP[VERSION].value.len);
00433   version[pFontBase->pFontArray[FontID].pType1Data->fontInfoP[VERSION].value.len]=0;
00434     
00435   return(version);
00436   
00437 }
00438 
00439 
00440 /* char *T1_GetNotice( FontID): Get the Notice entry from
00441    the  font dictionary associated with the specified font, or NULL if
00442    an error occurs. */
00443 char *T1_GetNotice( int FontID)
00444 {
00445   static char notice[2048];
00446   
00447   if (T1_CheckForFontID(FontID)!=1){
00448     T1_errno=T1ERR_INVALID_FONTID;
00449     return(NULL);
00450   }
00451   
00452   strncpy(notice,
00453          (char *)(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[NOTICE].value.data.nameP),
00454          pFontBase->pFontArray[FontID].pType1Data->fontInfoP[NOTICE].value.len);
00455   notice[pFontBase->pFontArray[FontID].pType1Data->fontInfoP[NOTICE].value.len]=0;
00456     
00457   return(notice);
00458   
00459 }
00460 
00461 
00462 
00463 
00464 /* char *T1_GetCharName(): Get the PostScript character name of
00465    the  character indexed by char1. */
00466 char *T1_GetCharName( int FontID, char char1)
00467 {
00468   static char cc_name1[256];
00469   char *c1;
00470   
00471 
00472   if (T1_CheckForFontID(FontID)!=1){
00473     T1_errno=T1ERR_INVALID_FONTID;
00474     return(NULL);
00475   }
00476 
00477   if (pFontBase->pFontArray[FontID].pFontEnc==NULL){
00478     /* We have to get the names from the fonts internal encoding */
00479     c1= (char *)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[(unsigned char)char1].data.arrayP;
00480     strncpy(cc_name1,
00481            (char *)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[(unsigned char)char1].data.arrayP,
00482            pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[(unsigned char)char1].len);
00483     cc_name1[pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[(unsigned char)char1].len]=0;
00484   }
00485   else{
00486     /* Take names from explicitly loaded and assigned encoding */
00487     c1=pFontBase->pFontArray[FontID].pFontEnc[(unsigned char)char1];
00488     strcpy(cc_name1,c1);
00489   }
00490 
00491   /* Return address of charname */
00492   return(cc_name1);
00493   
00494 }
00495 
00496 
00497 
00498 /* T1_QueryLigs(): Get the number of ligatures defined in the font FontID for
00499    the character which is located at position char1 in the current encoding
00500    vector!
00501    Function returns the number of defined ligs (including 0) or -1 if an
00502    error occured.
00503    */
00504 int T1_QueryLigs( int FontID,  char char1, char **successors,
00505                 char **ligatures)
00506 {
00507 
00508   FontInfo *afm_ptr;
00509   CharMetricInfo *m_ptr;
00510   char *c_name;
00511   char cc_name[128];
00512   static char succ[MAX_LIGS];
00513   int succ_index;
00514   static char lig[MAX_LIGS];
00515   int lig_index;
00516   
00517   Ligature *ligs;
00518   int i,j;
00519   
00520   /* Check whether font is loaded: */
00521   if (T1_CheckForFontID(FontID)!=1){
00522     T1_errno=T1ERR_INVALID_FONTID;
00523     return(-1);
00524   }
00525   
00526   /* If no AFM info is present, we return an error */
00527   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
00528     T1_errno=T1ERR_NO_AFM_DATA;
00529     return( -1);
00530   }
00531 
00532   /* All OK, ... */
00533   afm_ptr=pFontBase->pFontArray[FontID].pAFMData;
00534   m_ptr=afm_ptr->cmi;
00535 
00536   /* Get the name of the character: */
00537   if (pFontBase->pFontArray[FontID].pFontEnc==NULL){
00538     /* We have to get the name from the fonts internal encoding */
00539     c_name=(char *)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[(unsigned char)char1].data.arrayP;
00540     strncpy(cc_name,
00541            (char *)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[(unsigned char)char1].data.arrayP,
00542            pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[(unsigned char)char1].len);
00543     cc_name[pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[(unsigned char)char1].len]=0;
00544   }
00545   else{
00546     /* Take name from explicitly loaded and assigned encoding */
00547     c_name=pFontBase->pFontArray[FontID].pFontEnc[(unsigned char)char1];
00548     strcpy(cc_name,c_name);
00549   }
00550 
00551   for (i=0; i<afm_ptr->numOfChars; i++){
00552     if (strcmp(m_ptr[i].name,cc_name)==0)
00553       break;
00554   }
00555   
00556 
00557   if (i==afm_ptr->numOfChars) /* we didn't find the characters name */
00558     return(-1);
00559   
00560   ligs=m_ptr[i].ligs;
00561 
00562   j=0;
00563   if (ligs==NULL)
00564     return(0);
00565   
00566   while (ligs!=NULL) {
00567     /* Get indices of the two characters: */
00568     if ((succ_index=T1_GetEncodingIndex( FontID, (char*) ligs->succ))==-1) {
00569       /* successor is not current encoding */
00570       ligs=ligs->next;
00571       continue;
00572     }
00573     if ((lig_index=T1_GetEncodingIndex( FontID, (char*) ligs->lig))==-1) {
00574       /* Specified ligature is not in current encoding */
00575       ligs=ligs->next;
00576       continue;
00577     }
00578     succ[j]=(char)succ_index;
00579     lig[j]=(char)lig_index;
00580     j++;
00581     ligs=ligs->next;
00582   }
00583     
00584   *successors=succ;
00585   *ligatures=lig;
00586   
00587   return(j);
00588 }
00589 
00590       
00591 
00592 /* T1_GetEncodingIndex(): Return the Index of char1 in the current
00593    encoding vector of font FontID */
00594 int T1_GetEncodingIndex( int FontID, char *char1)
00595 {
00596   int i;
00597   int len1;
00598   int result_index;
00599   char **extern_enc;
00600   psobj *objptr;
00601   
00602   
00603   if (T1_CheckForFontID(FontID)!=1){
00604     T1_errno=T1ERR_INVALID_FONTID;
00605     return(-1);
00606   }
00607 
00608   extern_enc=pFontBase->pFontArray[FontID].pFontEnc;
00609 
00610   len1=strlen( char1);
00611   
00612   /* The default return-value if character is not found: */
00613   result_index=-1;
00614 
00615   if (extern_enc==NULL) {
00616     objptr=&(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[0]);
00617     /* We have to search the fonts internal encoding */
00618     for (i=0;i<256;i++){
00619       if (len1==objptr[i].len){
00620        if (strncmp((char *)objptr[i].data.arrayP,
00621                   char1, objptr[i].len)==0){ 
00622          result_index=i; 
00623          break; 
00624        }
00625       }
00626     }
00627     
00628   }
00629   else {
00630     /* Take name from explicitly loaded and assigned encoding */
00631     for (i=0;i<256;i++){
00632       if (strcmp(extern_enc[i], char1)==0){
00633        result_index=i;
00634        break;
00635       }
00636     }
00637   }
00638 
00639   return(result_index);
00640 }
00641 
00642 
00643 /* T1_GetEncodingIndices(): Return all indices of char1 in the current
00644    encoding vector of font FontID. */
00645 int *T1_GetEncodingIndices( int FontID, char *char1)
00646 {
00647   int i;
00648   int endmark=0;
00649   int len1;
00650   char **extern_enc;
00651   psobj *objptr;
00652   /* the following array suffices for the extreme unlikely case of a font
00653      where one single fillsthe whole encoding vector */
00654   static int indices[257];
00655 
00656   
00657   if (T1_CheckForFontID(FontID)!=1) {
00658     T1_errno=T1ERR_INVALID_FONTID;
00659     return(NULL);
00660   }
00661 
00662   extern_enc=pFontBase->pFontArray[FontID].pFontEnc;
00663 
00664   len1=strlen( char1);
00665   
00666   if (extern_enc==NULL) {
00667     objptr=&(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[0]);
00668     /* We have to search the fonts internal encoding */
00669     for (i=0;i<256;i++){
00670       if (len1==objptr[i].len){
00671        if (strncmp((char *)objptr[i].data.arrayP,
00672                   char1, objptr[i].len)==0){ 
00673          indices[endmark++]=i; 
00674        }
00675       }
00676     }
00677   }
00678   else {
00679     /* Take name from explicitly loaded and assigned encoding */
00680     for (i=0;i<256;i++){
00681       if (strcmp(extern_enc[i], char1)==0){
00682        indices[endmark++]=i; 
00683       }
00684     }
00685   }
00686 
00687   indices[endmark]=-1;
00688   return((int *)indices);
00689 }
00690 
00691 
00692 /* int T1_GetStringWidth(): This function returns the width of string
00693    in .afm-file units. If no .afm-file is loaded for font FontID,
00694    0 is returned. Note that if one tries to raster strings, afm data
00695    should always be available. The returned character width is corrected
00696    using  a possibly applied font extension!
00697    */
00698 int T1_GetStringWidth( int FontID, char *string,
00699                      int len,  long spaceoff, int kerning)
00700 {
00701 
00702   int no_chars;      /* Number of chars in string */
00703   int i;
00704   int *kern_pairs;
00705   int *charwidths;
00706   int spacewidth; 
00707   int stringwidth;
00708 
00709   unsigned char *ustring;
00710 
00711   ustring=(unsigned char *) string;
00712   
00713   /* First, check for a correct ID */
00714   i=T1_CheckForFontID(FontID);
00715   if (i!=1){
00716     T1_errno=T1ERR_INVALID_FONTID;
00717     return(0);
00718   }
00719   
00720   /* If no AFM info is present, we return an error */
00721   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
00722     T1_errno=T1ERR_NO_AFM_DATA;
00723     return( 0);
00724   }
00725 
00726   /* Get length of string: */
00727   if (len<0 || ustring == NULL){  /* invalid length or NULL-pointer */
00728     T1_errno=T1ERR_INVALID_PARAMETER;
00729     return(0);
00730   }
00731   if (len==0) /* should be computed assuming "normal" 0-terminated string */
00732     no_chars=strlen(string);
00733   else        /* use value given on command line */
00734     no_chars=len;
00735 
00736   switch (no_chars) {
00737     case 0:
00738       /* Empty string has width 0 */
00739       stringwidth=0;
00740       break;
00741 
00742     case 1:
00743       /* Width of string with 1 character is the width of that character.
00744          If the character is a space, adjust by the value of spaceoff.
00745          */
00746       stringwidth=T1_GetCharWidth(FontID,ustring[0]);
00747       if (ustring[0]==pFontBase->pFontArray[FontID].space_position)
00748         stringwidth+=spaceoff;
00749       break;
00750 
00751     default:
00752       /* Two or more characters.  Add widths of characters and adjust by
00753          the adjustment widths for any kerning pairs.  For spaces, use the
00754          width of the space character in the font adjusted by the value of
00755          spaceoff.
00756          */
00757     
00758       /* Allocate room for temporary arrays of kerning and width arrays: */
00759       kern_pairs=(int *)calloc(no_chars -1, sizeof(int));
00760       if (kern_pairs==NULL){
00761         T1_errno=T1ERR_ALLOC_MEM;
00762         return(0);
00763       }
00764       charwidths=(int *)calloc(no_chars, sizeof(int));
00765       if (charwidths==NULL){
00766         T1_errno=T1ERR_ALLOC_MEM;
00767         return(0);
00768       }
00769   
00770       /* If kerning is requested, get kerning amounts and fill the array: */
00771       if (kerning){
00772         for (i=0; i<no_chars -1; i++){
00773           kern_pairs[i]=T1_GetKerning( FontID, ustring[i], ustring[i+1]);
00774         }
00775       }
00776   
00777       /* Compute the correct spacewidth value (in charspace units): */
00778       spacewidth=T1_GetCharWidth(FontID,pFontBase->pFontArray[FontID].space_position)+spaceoff;
00779   
00780       /* Fill the width-array:  */
00781       for (i=0; i<no_chars; i++){
00782         if (ustring[i]==pFontBase->pFontArray[FontID].space_position)
00783           charwidths[i]=(int)spacewidth;
00784         else
00785           charwidths[i]=T1_GetCharWidth(FontID,ustring[i]);
00786       }
00787   
00788       /* Accumulate width: */
00789       stringwidth=0;
00790       for (i=0; i<no_chars-1; i++){
00791         stringwidth += kern_pairs[i];
00792       }
00793       for (i=0; i<no_chars; i++){
00794         stringwidth += charwidths[i];
00795       }
00796   
00797       /* free memory: */
00798       free( charwidths);
00799       free( kern_pairs);
00800 
00801       break;
00802   }
00803 
00804   /* .. and return result: */
00805   return( stringwidth);
00806 }
00807 
00808     
00809 
00810 /* int T1_GetStringBBox(): This function returns the bounding box of string
00811    in .afm-file units. If no .afm-file is loaded for font FontID,
00812    0 is returned. Note that if one tries to raster strings, afm data
00813    should always be available. The returned character width is corrected
00814    using  a possibly applied font extension!
00815    */
00816 BBox T1_GetStringBBox( int FontID, char *string,
00817                      int len,  long spaceoff, int kerning)
00818 {
00819 
00820   BBox NullBBox= { 0, 0, 0, 0}; /* A bounding box containing all 0's. */
00821   BBox tmp_BBox= { 0, 0, 0, 0}; 
00822   BBox ResultBBox= { 0, 0, 0, 0}; /* The resulting BBox */
00823   int i;
00824   int no_chars;
00825   int curr_width=0;
00826   int spacewidth=0;
00827   
00828   int rsb_max=-30000;
00829   int lsb_min= 30000;
00830   int overallascent=-30000;
00831   int overalldescent=30000;
00832 
00833   
00834   /* First, check for a correct ID */
00835   i=T1_CheckForFontID(FontID);
00836   if (i!=1){
00837     T1_errno=T1ERR_INVALID_FONTID;
00838     return(NullBBox);
00839   }
00840   
00841   /* If no AFM info is present, we return an error */
00842   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
00843     T1_errno=T1ERR_NO_AFM_DATA;
00844     return( NullBBox);
00845   }
00846 
00847   /* Get length of string: */
00848   if (len<0 || string==NULL) {  /* invalid length or NULL-pointer */
00849     T1_errno=T1ERR_INVALID_PARAMETER;
00850     return(NullBBox);
00851   }
00852   if (len==0) /* should be computed assuming "normal" 0-terminated string */
00853     no_chars=strlen(string);
00854   else        /* use value given on command line */
00855     no_chars=len;
00856   
00857   spacewidth=
00858     T1_GetCharWidth(FontID,pFontBase->pFontArray[FontID].space_position)+spaceoff;
00859   
00860   /* Accumulate metrics: */
00861   for (i=0; i<no_chars; i++){
00862     if (string[i]==pFontBase->pFontArray[FontID].space_position)
00863       curr_width +=spacewidth;
00864     else{
00865       tmp_BBox=T1_GetCharBBox( FontID, string[i]);
00866       if (curr_width+tmp_BBox.llx < lsb_min)
00867        lsb_min=curr_width+tmp_BBox.llx;
00868       if (curr_width+tmp_BBox.urx > rsb_max)
00869        rsb_max=curr_width+tmp_BBox.urx;
00870       if (tmp_BBox.lly < overalldescent)
00871        overalldescent=tmp_BBox.lly;
00872       if (tmp_BBox.ury > overallascent)
00873        overallascent=tmp_BBox.ury;
00874       curr_width +=T1_GetCharWidth( FontID, string[i]);
00875       if ((i<no_chars-1) && (kerning != 0))
00876        curr_width += T1_GetKerning( FontID, string[i], string[i+1]);
00877     }
00878   }
00879 
00880   ResultBBox.llx=lsb_min;
00881   ResultBBox.lly=overalldescent;
00882   ResultBBox.urx=rsb_max;
00883   ResultBBox.ury=overallascent;
00884   
00885   return( ResultBBox);
00886   
00887 }
00888 
00889 
00890 /* T1_GetMetricsInfo(): Return a structure containing metrics information
00891    about the string to the user. */
00892 METRICSINFO T1_GetMetricsInfo( int FontID, char *string,
00893                             int len, long spaceoff, int kerning)
00894 {
00895 
00896   BBox NullBBox= { 0, 0, 0, 0}; /* A bounding box containing all 0's. */
00897   BBox tmp_BBox= { 0, 0, 0, 0}; 
00898 
00899 
00900   int i;
00901   int no_chars;
00902   
00903   int curr_width=0;
00904   int spacewidth=0;
00905   
00906   int rsb_max=-30000;
00907   int lsb_min= 30000;
00908   int overallascent=-30000;
00909   int overalldescent=30000;
00910 
00911   static METRICSINFO metrics={ 0, {0, 0, 0, 0}, 0, NULL};
00912 
00913   unsigned char *ustring;
00914 
00915   
00916   ustring=(unsigned char *) string;
00917   
00918   /* Reset struct: */
00919   metrics.width=0;
00920   metrics.bbox=NullBBox;
00921   metrics.numchars=0;
00922   if (metrics.charpos != NULL){
00923     free( metrics.charpos);
00924     metrics.charpos=NULL;
00925   }
00926 
00927 
00928   /* First, check for a correct ID */
00929   i=T1_CheckForFontID(FontID);
00930   if (i!=1){
00931     T1_errno=T1ERR_INVALID_FONTID;
00932     return(metrics);
00933   }
00934   
00935   /* If no AFM info is present, we return an error */
00936   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
00937     T1_errno=T1ERR_NO_AFM_DATA;
00938     return( metrics);
00939   }
00940 
00941   /* Get length of string: */
00942   if (len<0 || ustring==NULL ) {  /* invalid length or NULL_pointer */
00943     T1_errno=T1ERR_INVALID_PARAMETER;
00944     return(metrics);
00945   }
00946   
00947   if (len==0) /* should be computed assuming "normal" 0-terminated string */
00948     no_chars=strlen(string);
00949   else        /* use value given on command line */
00950     no_chars=len;
00951 
00952   /* Compute the correct spacewidth value (in charspace units): */
00953   spacewidth=T1_GetCharWidth(FontID,pFontBase->pFontArray[FontID].space_position)+spaceoff;
00954 
00955   /* Allocate memory for character positions array: */
00956   metrics.charpos=(int *)calloc(no_chars, sizeof(int));
00957 
00958   metrics.numchars=no_chars;
00959   
00960   /* Accumulate metrics: */
00961   for (i=0; i<no_chars; i++){
00962     /* Save current offst to array */
00963     metrics.charpos[i]=curr_width;
00964     if (string[i]==pFontBase->pFontArray[FontID].space_position)
00965       curr_width +=spacewidth;
00966     else{
00967       tmp_BBox=T1_GetCharBBox( FontID, string[i]);
00968       if (curr_width+tmp_BBox.llx < lsb_min)
00969        lsb_min=curr_width+tmp_BBox.llx;
00970       if (curr_width+tmp_BBox.urx > rsb_max)
00971        rsb_max=curr_width+tmp_BBox.urx;
00972       if (tmp_BBox.lly < overalldescent)
00973        overalldescent=tmp_BBox.lly;
00974       if (tmp_BBox.ury > overallascent)
00975        overallascent=tmp_BBox.ury;
00976       curr_width +=T1_GetCharWidth( FontID, string[i]);
00977       if ((i<no_chars-1) && (kerning != 0))
00978        curr_width += T1_GetKerning( FontID, string[i], string[i+1]);
00979     }
00980   }
00981 
00982   metrics.width   =curr_width;
00983   metrics.bbox.llx=lsb_min;
00984   metrics.bbox.lly=overalldescent;
00985   metrics.bbox.urx=rsb_max;
00986   metrics.bbox.ury=overallascent;
00987 
00988   return( metrics);
00989   
00990 }
00991 
00992 
00993 
00994 /* T1_GetFontBBox(): Return the font's bounding box. Note: The font
00995    BBox is taken is taken from the font file rather than from afm
00996    file since I have seen some afm with rather inaccurate BBoxes.: */
00997 BBox T1_GetFontBBox( int FontID)
00998 {
00999   
01000   BBox outbox= { 0, 0, 0, 0}; 
01001   struct ps_obj *obj;
01002 
01003   /* return Null-box if font not loaded */
01004   if (T1_CheckForFontID(FontID)!=1){
01005     T1_errno=T1ERR_INVALID_FONTID;
01006     return(outbox);
01007   }
01008 
01009   /* As suggested by Derek B. Noonburg (xpdf-Author), we allow the
01010      FontBBox also to be specified by real numbers. */
01011   obj = &(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTBBOX].value.data.arrayP[0]);
01012   outbox.llx =
01013     objPIsInteger(obj) ? obj->data.integer : obj->data.real > 0 ?
01014     (int) ceil(obj->data.real) : (int) floor(obj->data.real);
01015   obj = &(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTBBOX].value.data.arrayP[1]);
01016   outbox.lly =
01017     objPIsInteger(obj) ? obj->data.integer : obj->data.real > 0 ?
01018     (int) ceil(obj->data.real) : (int) floor(obj->data.real);
01019   obj = &(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTBBOX].value.data.arrayP[2]);
01020   outbox.urx =
01021     objPIsInteger(obj) ? obj->data.integer : obj->data.real > 0 ?
01022     (int) ceil(obj->data.real) : (int) floor(obj->data.real);
01023   obj = &(pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTBBOX].value.data.arrayP[3]);
01024   outbox.ury =
01025     objPIsInteger(obj) ? obj->data.integer : obj->data.real > 0 ?
01026     (int) ceil(obj->data.real) : (int) floor(obj->data.real);
01027   
01028   return( outbox);
01029 }
01030 
01031        
01032 
01033 /* T1_GetAllCharNames(): Get a list of all defined character names in
01034    in the font FontID: */
01035 char **T1_GetAllCharNames( int FontID)
01036 {
01037   static char **bufmem=NULL;
01038   register char *namedest;
01039   psdict *pCharStrings;
01040   int len, i, j;
01041   long nameoffset;
01042   
01043   int bufmemsize=0;
01044   
01045   /* return NULL if font not loaded */
01046   if (T1_CheckForFontID(FontID)!=1){
01047     T1_errno=T1ERR_INVALID_FONTID;
01048     return( NULL);
01049   }
01050   
01051   pCharStrings=pFontBase->pFontArray[FontID].pType1Data->CharStringsP;
01052 
01053   /* First, get number of charstrings: */
01054   len=pCharStrings[0].key.len;
01055 
01056   /* We must be careful here: size of the charstrings dict might be larger
01057      than the actual number of charstrings. We correct for this by reducing
01058      the value of len appropriately */
01059   for ( i=1; i<=len; i++){
01060     /* calculate room for each characters name plus the prepending \0 */ 
01061     if ((j=pCharStrings[i].key.len)){
01062       bufmemsize += j + 1;
01063     }
01064     else{ /* we skip this (the remaining) entries */
01065       len--;
01066       i--;
01067     }
01068   }
01069   /* Now we reserve memory for the pointers (including final NULL) */
01070   nameoffset=(len+1)*sizeof( char *);
01071   bufmemsize += nameoffset;
01072 
01073   /* Now allocate memory, copy strings and initialize pointers */
01074   if (bufmem!=NULL)
01075     free(bufmem);
01076   if ((bufmem=(char **)malloc( bufmemsize))==NULL){
01077     T1_errno=T1ERR_ALLOC_MEM;
01078     return(NULL);
01079   }
01080   
01081   namedest=(char *)((long)bufmem + nameoffset);
01082   j=0;
01083   for ( i=0; i<len; i++){
01084     bufmem[i]=&(namedest[j]);
01085     strncpy( &(namedest[j]), pCharStrings[i+1].key.data.nameP,
01086             pCharStrings[i+1].key.len);
01087     j += pCharStrings[i+1].key.len;
01088     namedest[j++]='\0';
01089   }
01090   bufmem[i++]=NULL;
01091   
01092   return( bufmem);
01093   
01094 }
01095 
01096 
01097 
01098 /* T1_GetNoKernPairs(): Return the number of kerning pairs defined
01099    for font FontID */
01100 int T1_GetNoKernPairs( int FontID)
01101 {
01102   
01103   /* Check whether font is loaded: */
01104   if (T1_CheckForFontID(FontID)!=1){
01105     T1_errno=T1ERR_INVALID_FONTID;
01106     return( -1);
01107   }
01108 
01109   /* If no AFM info is present, we return an error */
01110   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
01111     T1_errno=T1ERR_NO_AFM_DATA;
01112     return( -1);
01113   }
01114 
01115   return( pFontBase->pFontArray[FontID].pAFMData->numOfPairs);
01116   
01117 }
01118 
01119 
01120 
01121 /* A function for comparing METRICS_ENTRY structs */
01122 static int cmp_METRICS_ENTRY( const void *entry1, const void *entry2)
01123 {
01124   if (((METRICS_ENTRY *)entry1)->chars <
01125       ((METRICS_ENTRY *)entry2)->chars)
01126     return(-1);
01127   if (((METRICS_ENTRY *)entry1)->chars >
01128       ((METRICS_ENTRY *)entry2)->chars)
01129     return(1);
01130   return(0); /* This should not happen */
01131 }
01132 
01133 
01134 
01135 /* A few functions for accessing composite character data: */
01136 /* T1_GetNoCompositeChars(): Return the number of characters for
01137    for which composite character information is available
01138    for font FontID */
01139 int T1_GetNoCompositeChars( int FontID)
01140 {
01141   
01142   /* Check whether font is loaded: */
01143   if (T1_CheckForFontID(FontID)!=1){
01144     T1_errno=T1ERR_INVALID_FONTID;
01145     return( -1);
01146   }
01147 
01148   /* If no AFM info is present, we return an error */
01149   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
01150     T1_errno=T1ERR_NO_AFM_DATA;
01151     return( -1);
01152   }
01153 
01154   return( pFontBase->pFontArray[FontID].pAFMData->numOfComps);
01155   
01156 }
01157 
01158 
01159 
01160 /* T1_QueryCompositeChar(): Query whether char1 from font FontID
01161    is a composite character. If so, the index of the composite
01162    character data within the afm array is returned. The index can
01163    be used to retrieve the retrieve the composite character data.
01164 
01165    retval>=0:    index into AFM-array where the corresponding
01166                  composite char data is located
01167    retval=-1:    No composite character, but result is valid,
01168    retval=-2:    No composite character, but result is invalid.
01169                  T1_errno indicated the reason.
01170 */
01171 int T1_QueryCompositeChar( int FontID, char char1) 
01172 {
01173   unsigned char uchar1;
01174 
01175   uchar1=char1;
01176   
01177   /* Check whether font is loaded: */
01178   if (T1_CheckForFontID(FontID)!=1){
01179     T1_errno=T1ERR_INVALID_FONTID;
01180     return( -2);
01181   }
01182 
01183   /* If no AFM info is present, we return -2 */
01184   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
01185     T1_errno=T1ERR_NO_AFM_DATA;
01186     return( -2);
01187   }
01188 
01189   if (pFontBase->pFontArray[FontID].pEncMap[ uchar1]<0) { /* composite char */
01190     return( -(pFontBase->pFontArray[FontID].pEncMap[(int) uchar1]+1));
01191   }
01192 
01193   return(-1);
01194   
01195 }
01196 
01197 
01198 
01199 /* T1_GetCompCharData(): Retrieve data to construct composite
01200    character char1 from font FontID. In case of an error NULL is returned
01201    and T1_errno is set appropriately. */
01202 T1_COMP_CHAR_INFO *T1_GetCompCharData( int FontID, char char1)
01203 {
01204   T1_COMP_CHAR_INFO *cci=NULL;
01205   CompCharData *ccd=NULL;
01206   int afmind=-1;
01207   int i;
01208   unsigned char uchar1;
01209   
01210   /* Check whether font is loaded: */
01211   if (T1_CheckForFontID(FontID)!=1){
01212     T1_errno=T1ERR_INVALID_FONTID;
01213     return( cci);
01214   }
01215 
01216   /* If no AFM info is present, we return -2 */
01217   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
01218     T1_errno=T1ERR_NO_AFM_DATA;
01219     return( cci);
01220   }
01221 
01222   if ((cci=(T1_COMP_CHAR_INFO*)malloc( sizeof(T1_COMP_CHAR_INFO)))==NULL) {
01223     T1_errno=T1ERR_ALLOC_MEM;
01224     return( cci);
01225   }
01226   
01227   uchar1=(unsigned char)char1;
01228   
01229   /* set default values */
01230   cci->compchar=uchar1;
01231   cci->numPieces=1;
01232   cci->pieces=NULL;
01233 
01234   /* check char1 */
01235   if ((afmind=pFontBase->pFontArray[FontID].pEncMap[uchar1]) >= 0) {
01236     /* char is no composite char */
01237     return(cci);
01238   }
01239   
01240   /* character is a composite char-> retrieve index and pointer into
01241      AFM data */
01242   afmind=-(afmind+1);
01243   ccd=&(pFontBase->pFontArray[FontID].pAFMData->ccd[afmind]);
01244 
01245   /* cci->compchar is already setup correctly because char1 is a
01246      composite character */
01247   cci->numPieces=ccd->numOfPieces;
01248   /* we expect numPieces to be >1 */
01249   if ((cci->pieces=(T1_COMP_PIECE *)malloc( sizeof(T1_COMP_PIECE)*
01250                                        cci->numPieces))==NULL) {
01251     T1_errno=T1ERR_ALLOC_MEM;
01252     free( cci);
01253     return( NULL);
01254   }
01255   /* Copy information */
01256   for (i=0; i<cci->numPieces; i++) {
01257     cci->pieces[i].piece=T1_GetEncodingIndex( FontID, ccd->pieces[i].pccName);
01258     cci->pieces[i].deltax=ccd->pieces[i].deltax;
01259     cci->pieces[i].deltay=ccd->pieces[i].deltay;
01260   }
01261   return( cci);
01262   
01263 }
01264 
01265 
01266 
01267 /* T1_GetCompCharDataByIndex(): Retrieve data to construct composite
01268    characters form font FontID. The data is addressed by index which
01269    may, for example, have been obtained by a call to
01270    T1_QueryCompositeChar().
01271    In case of error NULL is returned and T1_errno is set appropriately.
01272 */
01273 T1_COMP_CHAR_INFO *T1_GetCompCharDataByIndex( int FontID, int index)
01274 {
01275   T1_COMP_CHAR_INFO *cci=NULL;
01276   CompCharData *ccd=NULL;
01277   int i;
01278   
01279   /* Check whether font is loaded: */
01280   if (T1_CheckForFontID(FontID)!=1){
01281     T1_errno=T1ERR_INVALID_FONTID;
01282     return( cci);
01283   }
01284 
01285   /* If no AFM info is present, we return -2 */
01286   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
01287     T1_errno=T1ERR_NO_AFM_DATA;
01288     return( cci);
01289   }
01290 
01291   /* range check for index */
01292   if ((index < 0) ||
01293       (index >= pFontBase->pFontArray[FontID].pAFMData->numOfComps)) {
01294     T1_errno=T1ERR_INVALID_PARAMETER;
01295     return( cci);
01296   }
01297 
01298   /* Alloc mem */
01299   if ((cci=(T1_COMP_CHAR_INFO*)malloc( sizeof(T1_COMP_CHAR_INFO)))==NULL) {
01300     T1_errno=T1ERR_ALLOC_MEM;
01301     return( cci);
01302   }
01303   
01304   /* set source pointer */
01305   ccd=&(pFontBase->pFontArray[FontID].pAFMData->ccd[index]);
01306   /* and copy information */
01307   cci->compchar=T1_GetEncodingIndex( FontID, ccd->ccName);
01308   cci->numPieces=ccd->numOfPieces;
01309   /* we expect numPieces to be >1 */
01310   if ((cci->pieces=(T1_COMP_PIECE *)malloc( sizeof(T1_COMP_PIECE)*
01311                                        cci->numPieces))==NULL) {
01312     T1_errno=T1ERR_ALLOC_MEM;
01313     free( cci);
01314     return( NULL);
01315   }
01316   /* Copy information */
01317   for (i=0; i<cci->numPieces; i++) {
01318     cci->pieces[i].piece=T1_GetEncodingIndex( FontID, ccd->pieces[i].pccName);
01319     cci->pieces[i].deltax=ccd->pieces[i].deltax;
01320     cci->pieces[i].deltay=ccd->pieces[i].deltay;
01321   }
01322   return( cci);
01323   
01324 }
01325 
01326 
01327 
01328 /* T1_IsInternalChar(): Query whether the character in encoding slot
01329    char1 of font FontID has an internal definition (CharString) or
01330    whether it is constructed by t1lib from elementary units */
01331 int T1_IsInternalChar( int FontID, char char1)
01332 {
01333   unsigned char uchar1;
01334   char *charname;
01335   psdict *pCharStrings;
01336   int len, i, j;
01337   
01338   /* return NULL if font not loaded */
01339   if (T1_CheckForFontID(FontID)!=1){
01340     T1_errno=T1ERR_INVALID_FONTID;
01341     return( -1);
01342   }
01343   
01344   pCharStrings=pFontBase->pFontArray[FontID].pType1Data->CharStringsP;
01345   uchar1=(unsigned char)char1;
01346 
01347   charname=T1_GetCharName( FontID, uchar1);
01348   
01349   /* First, get the maximum number of charstrings: */
01350   len=pCharStrings[0].key.len;
01351 
01352   /* Check all CharString definitions */
01353   for ( i=1; i<=len; i++) {
01354     /* if len=0, then the CharStrings dict is larger that required which
01355        is valid and allowed by the spec.*/ 
01356     if ((j=pCharStrings[i].key.len)!=0) {
01357       if ( (j==strlen(charname)) &&
01358           (strncmp( charname, pCharStrings[i].key.data.nameP, j)==0) ) {
01359        /* we have found an internal definition */
01360        return( 1);
01361       }
01362     }
01363   }
01364   return( 0);
01365 }