Back to index

tetex-bin  3.0
font.c
Go to the documentation of this file.
00001 /* font.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 void CheckChecksum(uint32_t c1, uint32_t c2, const char* name)
00029 {
00030   /* Report a warning if both checksums are nonzero, they don't match,
00031      and the user hasn't turned it off.  */
00032   if (c1 && c2 && c1 != c2
00033 #ifdef HAVE_LIBKPATHSEA
00034       && !kpse_tex_hush ("checksum")
00035 #endif
00036       ) {
00037      Warning ("Checksum mismatch in %s", name) ;
00038    }
00039 }
00040 
00041 
00042 double ActualFactor(uint32_t unmodsize)
00043 /* compute the actual size factor given the approximation */
00044 /* actually factor * 1000 */
00045 {
00046   double  realsize;     /* the actual magnification factor */
00047   realsize = (double)unmodsize / 1000.0;
00048   if (abs((int)(unmodsize - 1095l))<2)
00049     realsize = 1.095445115; /*stephalf*/
00050   else if (abs((int)(unmodsize - 1315l))<2)
00051     realsize = 1.31453414; /*stepihalf*/
00052   else if (abs((int)(unmodsize - 1577l))<2)
00053     realsize = 1.57744097; /*stepiihalf*/
00054   else if (abs((int)(unmodsize - 1893l))<2)
00055     realsize = 1.89292916; /*stepiiihalf*/
00056   else if (abs((int)(unmodsize - 2074l))<2)
00057     realsize = 2.0736;   /*stepiv*/
00058   else if (abs((int)(unmodsize - 2488l))<2)
00059     realsize = 2.48832;  /*stepv*/
00060   else if (abs((int)(unmodsize - 2986l))<2)
00061     realsize = 2.985984; /*stepvi*/
00062   /* the remaining magnification steps are represented with sufficient
00063      accuracy already */
00064   return(realsize);
00065 }
00066 
00067 
00068 void FontDef(unsigned char* command, void* parent)
00069 {
00070   int32_t k;
00071   uint32_t   c, s, d;
00072   uint8_t    a, l;
00073   unsigned char* current;
00074   struct font_entry *tfontptr; /* temporary font_entry pointer   */
00075   struct font_num *tfontnump = NULL;  /* temporary font_num pointer   */
00076   unsigned short i;
00077 
00078   current = command + 1;
00079   k = UNumRead(current, (int)*command - FNT_DEF1 + 1);
00080   current += (int)*command - FNT_DEF1 + 1;
00081   c = UNumRead(current, 4); /* checksum */
00082   s = UNumRead(current+4, 4); /* space size */
00083   d = UNumRead(current+8, 4); /* design size */
00084   a = UNumRead(current+12, 1); /* length for font name */
00085   l = UNumRead(current+13, 1); /* device length */
00086   if (((struct font_entry*)parent)->type==FONT_TYPE_VF) {
00087     DEBUG_PRINT(DEBUG_VF,(" %d %d %d",k,c,s));
00088     /* Rescale. s is relative to the actual scale /(1<<20) */
00089     s = (uint32_t)((uint64_t) s * (((struct font_entry*) parent)->s) 
00090                  / (1<<20));
00091     DEBUG_PRINT(DEBUG_VF,(" (%d) %d",s,d));
00092     /* Oddly, d differs in the DVI and the VF that my system produces */
00093     d = (uint32_t)((uint64_t) d * ((struct font_entry*)parent)->d
00094                  / ((struct font_entry*)parent)->designsize);
00095     DEBUG_PRINT(DEBUG_VF,(" (%d)",d));
00096     DEBUG_PRINT(DEBUG_VF,(" %d %d '%.*s'",a,l,a+l,current+14));
00097 #ifdef DEBUG
00098   } else {
00099     DEBUG_PRINT(DEBUG_DVI,(" %d %d %d %d %d %d '%.*s'",k,c,s,d,a,l,
00100                a+l,current+14));
00101 #endif
00102   }
00103   if (a+l > STRSIZE-1)
00104     Fatal("too long font name for font %ld\n",k);
00105 
00106   /* Find entry with this font number in use */
00107   switch (((struct font_entry*)parent)->type) {
00108   case FONT_TYPE_VF:
00109     tfontnump = ((struct font_entry*)parent)->vffontnump;
00110     break;
00111   case DVI_TYPE:
00112     tfontnump = ((struct dvi_data*)parent)->fontnump;
00113   }
00114   while (tfontnump != NULL && tfontnump->k != k) {
00115     tfontnump = tfontnump->next;
00116   }
00117   /* If found, return if it is correct */
00118   if (tfontnump!=NULL 
00119       && tfontnump->fontp->s == s 
00120       && tfontnump->fontp->d == d 
00121       && strncmp(tfontnump->fontp->n,(char*)current+14,a+l) == 0) {
00122     DEBUG_PRINT((DEBUG_DVI|DEBUG_VF),("\n  FONT %d:\tMatch found",k));
00123     return;
00124   }
00125   /* If not found, create new */
00126   if (tfontnump==NULL) {
00127     if ((tfontnump=malloc(sizeof(struct font_num)))==NULL) 
00128       Fatal("cannot allocate memory for new font number");
00129     tfontnump->k=k;
00130     switch (((struct font_entry*)parent)->type) {
00131     case FONT_TYPE_VF:
00132       tfontnump->next=((struct font_entry*)parent)->vffontnump;
00133       ((struct font_entry*)parent)->vffontnump=tfontnump;
00134       break;
00135     case DVI_TYPE:
00136       tfontnump->next=((struct dvi_data*)parent)->fontnump;
00137       ((struct dvi_data*)parent)->fontnump=tfontnump;
00138     }
00139   }
00140 
00141   /* Search font list for possible match */
00142   tfontptr = hfontptr;
00143   while (tfontptr != NULL 
00144         && (tfontptr->s != s 
00145             || tfontptr->d != d 
00146             || strncmp(tfontptr->n,(char*)current+14,a+l) != 0 ) ) {
00147     tfontptr = tfontptr->next;
00148   }
00149   /* If found, set its number and return */
00150   if (tfontptr!=NULL) {
00151     DEBUG_PRINT((DEBUG_DVI|DEBUG_VF),("\n  FONT %d:\tMatch found, number set",k));
00152     tfontnump->fontp = tfontptr; 
00153     return;
00154   }
00155 
00156   DEBUG_PRINT((DEBUG_DVI|DEBUG_VF),("\n  FONT %d:\tNew entry created",k));
00157   /* No fitting font found, create new entry. */
00158   if ((tfontptr = calloc(1,sizeof(struct font_entry))) == NULL)
00159     Fatal("can't malloc space for font_entry");
00160   tfontptr->next = hfontptr;
00161   hfontptr = tfontptr;
00162   tfontnump->fontp = tfontptr;
00163 #ifndef MIKTEX
00164   tfontptr->fmmap.fd = 0;
00165 #else  /* MIKTEX */
00166   tfontptr->fmmap.hFile = INVALID_HANDLE_VALUE;
00167 #endif
00168   tfontptr->c = c; /* checksum */
00169   tfontptr->s = s; /* space size */
00170   tfontptr->d = d; /* design size */
00171   tfontptr->a = a; /* length for font name */
00172   tfontptr->l = l; /* device length */
00173   strncpy(tfontptr->n,(char*)current+14,a+l); /* full font name */
00174   tfontptr->n[a+l] = '\0';
00175   
00176   tfontptr->name[0] = '\0';
00177   for (i = FIRSTFNTCHAR; i <= LASTFNTCHAR; i++) {
00178     tfontptr->chr[i] = NULL;
00179   }
00180 
00181   tfontptr->dpi = 
00182     (uint32_t)((ActualFactor((uint32_t)(1000.0*tfontptr->s
00183                               /(double)tfontptr->d+0.5))
00184             * ActualFactor(dvi->mag) * dpi*shrinkfactor) + 0.5);
00185 #ifdef HAVE_FT2_OR_LIBT1
00186   tfontptr->psfontmap=NULL;
00187 #endif
00188 }
00189 
00190 #ifdef HAVE_FT2_OR_LIBT1
00191 char* kpse_find_t1_or_tt(char* filename) 
00192 {
00193     char* filepath = kpse_find_file(filename, kpse_type1_format, false);
00194 #ifdef HAVE_FT2
00195     if ((flags & USE_FREETYPE) && filepath==NULL) 
00196       filepath = kpse_find_file(filename, kpse_truetype_format, false);
00197 #endif
00198     return(filepath);
00199 }
00200 #endif
00201 
00202 void FontFind(struct font_entry * tfontptr)
00203 {
00204 #ifdef HAVE_LIBKPATHSEA
00205   kpse_glyph_file_type font_ret;
00206   char *name;
00207 
00208   /* tfontptr->dpi = kpse_magstep_fix (tfontptr->dpi, resolution, NULL); */
00209   DEBUG_PRINT(DEBUG_DVI,("\n  FIND FONT:\t%s %d",tfontptr->n,tfontptr->dpi));
00210 
00211   TEMPSTR(name,kpse_find_vf (tfontptr->n));
00212   if (name!=NULL) {
00213     strcpy (tfontptr->name, name);
00214     InitVF(tfontptr);
00215   }
00216 #ifdef HAVE_FT2_OR_LIBT1
00217   if ((flags & (USE_FREETYPE | USE_LIBT1)) && name==NULL) {
00218     tfontptr->psfontmap = FindPSFontMap(tfontptr->n);
00219     if (tfontptr->psfontmap!=NULL) {
00220       TEMPSTR(name,kpse_find_t1_or_tt(tfontptr->psfontmap->psfile));
00221     } else
00222       TEMPSTR(name,kpse_find_t1_or_tt(tfontptr->n));
00223     if (name!=NULL) {
00224       strcpy (tfontptr->name, name);
00225       TEMPSTR(name,kpse_find_file(tfontptr->n, kpse_tfm_format, false));
00226       if (name!=NULL) {
00227        if (!ReadTFM(tfontptr,name)) {
00228          Warning("unable to read tfm file %s", name);
00229          name=NULL;
00230        } else 
00231 #ifdef HAVE_FT2
00232          if ((flags & USE_FREETYPE)==0 || !InitFT(tfontptr)) {
00233 #endif
00234 #ifdef HAVE_LIBT1
00235            if ((flags & USE_LIBT1)==0 || !InitT1(tfontptr)) {
00236 #endif
00237              /* if Freetype or T1 loading fails for some reason, fall
00238                back to PK font */
00239              name=NULL; 
00240            }
00241 #ifdef HAVE_FT2
00242 #ifdef HAVE_LIBT1
00243          }
00244 #endif
00245 #endif
00246       }
00247     }
00248   }
00249 #endif /* HAVE_FT2_OR_LIBT1 */
00250   if (name==NULL) {
00251     TEMPSTR(name,kpse_find_pk (tfontptr->n, tfontptr->dpi, &font_ret));
00252     if (name!=NULL) {
00253       strcpy (tfontptr->name, name);
00254       if (!FILESTRCASEEQ (tfontptr->n, font_ret.name)) {
00255        flags |= PAGE_GAVE_WARN;
00256        Warning("font %s not found, using %s at %d dpi instead.\n",
00257               tfontptr->n, font_ret.name, font_ret.dpi);
00258        tfontptr->c = 0; /* no checksum warning */
00259       } else if (!kpse_bitmap_tolerance ((double)font_ret.dpi, (double) tfontptr->dpi)) {
00260        flags |= PAGE_GAVE_WARN;
00261        Warning("font %s at %d dpi not found, using %d dpi instead.\n",
00262               tfontptr->name, tfontptr->dpi, font_ret.dpi);
00263       }
00264       InitPK(tfontptr);
00265     } else {
00266       flags |= PAGE_GAVE_WARN;
00267       Warning("font %s at %d dpi not found, characters will be left blank.\n",
00268              tfontptr->n, tfontptr->dpi);
00269       strcpy (tfontptr->name, "None");
00270 #ifndef MIKTEX
00271       tfontptr->fmmap.fd = 0;
00272 #else  /* MIKTEX */
00273       tfontptr->fmmap.hFile = INVALID_HANDLE_VALUE;
00274 #endif
00275       tfontptr->magnification = 0;
00276       tfontptr->designsize = 0;
00277     }
00278   }
00279 #else /* not HAVE_LIBKPATHSEA */
00280       /* Ouch time! findfile not implemented (old cruft from dvilj) */
00281   /* Total argh, since none of this is adapted to vf and the like */
00282   if (!(findfile(PXLpath,
00283                tfontptr->n,
00284                tfontptr->dpi,
00285                tfontptr->name,
00286                false,
00287                0))) {
00288     Warning(tfontptr->name); /* contains error messsage */
00289 #ifndef MIKTEX
00290     tfontptr->fmmap.fd = 0;
00291 #else  /* MIKTEX */
00292     tfontptr->fmmap.hFile = INVALID_HANDLE_VALUE;
00293 #endif
00294 #ifdef __riscos
00295     MakeMetafontFile(PXLpath, tfontptr->n, tfontptr->dpi);
00296 #endif
00297   }
00298 #endif 
00299 }
00300 
00301 
00302 void DoneFont(struct font_entry *tfontp)
00303 {
00304   switch (tfontp->type) {
00305   case FONT_TYPE_PK:
00306     DonePK(tfontp);
00307     break;
00308   case FONT_TYPE_VF:
00309     DoneVF(tfontp);
00310     break;
00311 #ifdef HAVE_FT2
00312   case FONT_TYPE_FT:
00313     DoneFT(tfontp);
00314     break;
00315 #endif
00316 #ifdef HAVE_LIBT1
00317   case FONT_TYPE_T1:
00318     DoneT1(tfontp);
00319     break;
00320 #endif
00321   }
00322 }
00323 
00324 
00325 void FreeFontNumP(struct font_num *hfontnump)
00326 {
00327   struct font_num *tmp;
00328   while(hfontnump!=NULL) {
00329     tmp=hfontnump->next; 
00330     free(hfontnump);
00331     hfontnump=tmp;
00332   }
00333 }
00334 
00335 void ClearFonts(void)
00336 {
00337   struct font_entry *tmp;
00338 
00339   while(hfontptr!=NULL) {
00340     tmp=hfontptr->next;
00341     DoneFont(hfontptr);
00342     free(hfontptr);
00343     hfontptr=tmp;
00344   }
00345   if (dvi!=NULL)
00346     FreeFontNumP(dvi->fontnump);
00347 }
00348 
00349 /*-->SetFntNum*/
00350 /**********************************************************************/
00351 /****************************  SetFntNum  *****************************/
00352 /**********************************************************************/
00353 void SetFntNum(int32_t k, void* parent /* dvi/vf */)
00354 /*  this routine is used to specify the font to be used in printing future
00355     characters */
00356 {
00357   struct font_num *tfontnump=NULL;  /* temporary font_num pointer   */
00358 
00359   switch (((struct font_entry*)parent)->type) {
00360   case FONT_TYPE_VF:
00361     tfontnump = ((struct font_entry*)parent)->vffontnump;
00362     break;
00363   case DVI_TYPE:
00364     tfontnump = ((struct dvi_data*)parent)->fontnump;
00365   }
00366   while (tfontnump != NULL && tfontnump->k != k)
00367     tfontnump = tfontnump->next;
00368   if (tfontnump == NULL)
00369     Fatal("font %d undefined", k);
00370 
00371   currentfont = tfontnump->fontp;
00372   if (currentfont->name[0]=='\0')
00373     FontFind(currentfont);
00374 }
00375 
00376