Back to index

tetex-bin  3.0
fontmap.c
Go to the documentation of this file.
00001 /* fontmap.c */
00002 
00003 /************************************************************************
00004 
00005   Part of the dvipng distribution
00006 
00007   This program is free software; you can redistribute it and/or modify
00008   it under the terms of the GNU General Public License as published by
00009   the Free Software Foundation; either version 2 of the License, or
00010   (at your option) any later version.
00011 
00012   This program is distributed in the hope that it will be useful, but
00013   WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018   along with this program; if not, write to the Free Software
00019   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00020   02111-1307, USA.
00021 
00022   Copyright (C) 2002-2005 Jan-Åke Larsson
00023 
00024 ************************************************************************/
00025 
00026 #include "dvipng.h"
00027 
00028 static char* psfont_name=NULL;
00029 static struct filemmap psfont_mmap;
00030 static struct psfontmap *psfontmap=NULL;
00031 
00032 char* newword(char** buffer, char* end) 
00033 {
00034   char *word,*pos=*buffer;
00035 
00036   while(pos<end && *pos!=' ' && *pos!='\t' && *pos!='"') pos++;
00037   if ((word=malloc(pos-*buffer+1))==NULL)
00038     Fatal("cannot malloc space for string");
00039   strncpy(word,*buffer,pos-*buffer);
00040   word[pos-*buffer]='\0';
00041   if (*pos=='"') pos++;
00042   *buffer=pos;
00043   return(word);
00044 }
00045 
00046 char* find_format(char* name)
00047 {
00048   /* Cater for both new (first case) and old (second case) kpathsea */
00049   char* format =
00050     kpse_find_file(name,kpse_fontmap_format,false);
00051 
00052   if (format==NULL)
00053     format = kpse_find_file(name,kpse_dvips_config_format,false);
00054   return(format);
00055 }
00056 
00057 void InitPSFontMap(void)
00058 {
00059   char *pos,*end;
00060   struct psfontmap *entry;
00061 
00062   psfont_name=find_format("ps2pk.map");
00063   if (psfont_name==NULL)
00064     psfont_name=find_format("psfonts.map");
00065 
00066   if (psfont_name==NULL) {
00067     Warning("cannot find ps2pk.map, nor psfonts.map");
00068     return;
00069   }
00070   DEBUG_PRINT(DEBUG_FT,("\n  OPEN PSFONT MAP:\t'%s'", psfont_name));  
00071   if (MmapFile(psfont_name,&psfont_mmap)) {
00072     Warning("psfonts map %s could not be opened", psfont_name);
00073     return;
00074   }
00075   pos = psfont_mmap.mmap;
00076   end = psfont_mmap.mmap+psfont_mmap.size;
00077   while(pos<end) {
00078     while(pos < end && (*pos=='\n' || *pos==' ' || *pos=='\t' 
00079                      || *pos=='%' || *pos=='*' || *pos==';' || *pos=='#')) {
00080       while(pos < end && *pos!='\n') pos++; /* skip comments/empty rows */
00081       pos++;
00082     }
00083     if (pos < end) {
00084       if ((entry=malloc(sizeof(struct psfontmap)))==NULL)
00085        Fatal("cannot malloc psfontmap space");
00086       entry->line = pos;
00087       /* skip <something and quoted entries */
00088       while(pos < end && (*pos=='<' || *pos=='"')) {
00089        if (*pos=='<') 
00090          while(pos < end && *pos!=' ' && *pos!='\t') pos++;
00091        else 
00092          while(pos < end && *pos!='"') pos++;
00093        while(pos < end && (*pos==' ' || *pos=='\t')) pos++;
00094       }
00095       /* first word is font name */
00096       entry->tfmname = newword(&pos,end);
00097       entry->psfile = NULL;
00098       entry->encname = NULL;
00099       entry->encoding = NULL;
00100       while(pos < end && *pos!='\n') pos++;
00101       entry->end = pos;
00102       entry->next=psfontmap;
00103       psfontmap=entry;
00104     }
00105     pos++;
00106   }
00107 }
00108 
00109 void ClearPSFontMap(void)
00110 {
00111   struct psfontmap *entry;
00112 
00113   while(psfontmap!=NULL) {
00114     entry=psfontmap;
00115     psfontmap=psfontmap->next;
00116     free(entry->tfmname);
00117     if (entry->psfile!=NULL)
00118       free(entry->psfile);
00119     if (entry->encname!=NULL)
00120       free(entry->encname);
00121     free(entry);
00122   }
00123   UnMmapFile(&psfont_mmap);
00124   if (psfont_name != NULL)
00125     free(psfont_name);
00126   psfont_name=NULL;
00127 }
00128 
00129 struct psfontmap* FindPSFontMap(char* fontname)
00130 {
00131   char *pos,*tfmname,*psname;
00132   struct psfontmap *entry;
00133   double cxx=0.0,cxy=0.0;
00134        
00135   entry=psfontmap;
00136   while(entry!=NULL && strcmp(entry->tfmname,fontname)!=0)
00137     entry=entry->next;
00138   if (entry!=NULL && entry->psfile==NULL) {
00139     int nameno = 0;
00140     
00141     DEBUG_PRINT((DEBUG_FT|DEBUG_T1),("\n  PSFONTMAP: %s ",fontname));
00142     pos=entry->line;
00143 #if HAVE_LIBT1
00144     entry->t1_transformp=NULL;
00145 #endif
00146 #if HAVE_FT2
00147     entry->ft_transformp=NULL;
00148 #endif
00149     while(pos < entry->end) { 
00150       if (*pos=='<') {                               /* filename follows */
00151        pos++;
00152        if (pos<entry->end && *pos=='<') {           /* <<download.font */
00153          pos++;
00154          entry->psfile = newword((char**)&pos,entry->end);
00155          DEBUG_PRINT((DEBUG_FT|DEBUG_T1),("<%s ",entry->psfile));
00156        } else if (pos<entry->end && *pos=='[') {    /* <[encoding.file */
00157          pos++;
00158          entry->encname = newword((char**)&pos,entry->end);
00159          DEBUG_PRINT((DEBUG_FT|DEBUG_T1),("<[%s ",entry->encname));
00160        } else {                                     /* <some.file      */
00161          char* word =newword((char**)&pos,entry->end); 
00162          if (strncmp(word+strlen(word)-4,".enc",4)==0) {/* <some.enc */
00163            entry->encname=word;
00164            DEBUG_PRINT((DEBUG_FT|DEBUG_T1),("<[%s ",entry->encname));
00165          } else {                                   /* <font    */  
00166            entry->psfile=word;
00167            DEBUG_PRINT((DEBUG_FT|DEBUG_T1),("<%s ",entry->psfile));
00168          }
00169        }
00170       } else if (*pos=='"') { /* PS code: reencoding/tranformation exists */
00171        double val=0.0;
00172        pos++;
00173        DEBUG_PRINT((DEBUG_FT|DEBUG_T1),("\""));
00174        while(pos < entry->end && *pos!='"') {
00175          val=strtod(pos,(char**)&pos); 
00176          /* Small buffer overrun risk, but we're inside double quotes */
00177          while(pos < entry->end && (*pos==' ' || *pos=='\t')) pos++;
00178          if (pos<entry->end-10 && strncmp(pos,"ExtendFont",10)==0) {
00179            cxx=val;
00180            DEBUG_PRINT((DEBUG_FT|DEBUG_T1),
00181                      ("%f ExtendFont ",cxx));
00182          }
00183          if (pos<entry->end-9 && strncmp(pos,"SlantFont",9)==0) {
00184            cxy=val;
00185            DEBUG_PRINT((DEBUG_FT|DEBUG_T1),
00186                      ("%f SlantFont ",cxy));
00187          }
00188          while(pos<entry->end && *pos!=' ' && *pos!='\t' && *pos!='"') 
00189            pos++;
00190        }
00191 #if HAVE_FT2
00192        entry->ft_transformp=&(entry->ft_transform);
00193        if (cxx!=0.0)
00194          entry->ft_transform.xx=(FT_Fixed)(cxx*0x10000);
00195        else
00196          entry->ft_transform.xx=0x10000;
00197        entry->ft_transform.xy=(FT_Fixed)(cxy*0x10000);
00198        entry->ft_transform.yx=0;
00199        entry->ft_transform.yy=0x10000;
00200 #endif
00201 #if HAVE_LIBT1
00202        entry->t1_transformp=&(entry->t1_transform);
00203        if (cxx!=0)
00204          entry->t1_transform.cxx=cxx;
00205        else
00206          entry->t1_transform.cxx=1.0;
00207        entry->t1_transform.cxy=cxy;
00208        entry->t1_transform.cyx=0.0;
00209        entry->t1_transform.cyy=1.0;
00210 #endif
00211        DEBUG_PRINT((DEBUG_FT|DEBUG_T1),("\" "));
00212        pos++;
00213       } else {                                      /* bare word */
00214        switch (++nameno) {
00215        case 1:            /* first word is tfmname and perhaps psname */
00216          while(pos<entry->end && *pos!=' ' && *pos!='\t') pos++;
00217          psname=entry->tfmname;
00218          break;
00219        case 2:                              /* second word is psname */
00220          psname = newword((char**)&pos,entry->end);
00221          DEBUG_PRINT((DEBUG_FT|DEBUG_T1),("(%s) ",psname));
00222          free(psname);
00223          break;
00224        case 3:                             /* third word is encoding */
00225          entry->encname = newword((char**)&pos,entry->end);
00226          DEBUG_PRINT((DEBUG_FT|DEBUG_T1),("<[%s ",entry->encname));
00227          break;
00228        default:
00229          Warning("more than three bare words in font map entry");
00230        }
00231       }
00232       while(pos < entry->end && (*pos==' ' || *pos=='\t')) pos++;
00233     }
00234     if (entry->psfile==NULL) { 
00235       /* No psfile-name given, use (free-able copy of) tfmname */
00236       entry->psfile=newword(&tfmname,tfmname+strlen(tfmname));
00237       DEBUG_PRINT((DEBUG_FT|DEBUG_T1),(" <%s ",entry->psfile));
00238     }
00239     if (entry->encname!=NULL 
00240        && (entry->encoding=FindEncoding(entry->encname))==NULL) 
00241       Warning("unable to load font encoding '%s' for %s",
00242              entry->encname,entry->tfmname);
00243   }
00244   if (entry != NULL && entry->encname!=NULL && entry->encoding==NULL) 
00245     /* Encoding given but it cannot be found. Unusable font */
00246     return(NULL);
00247   
00248   return(entry);
00249 }
00250