DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T f

⟦ccff6ca67⟧ TextFile

    Length: 23688 (0x5c88)
    Types: TextFile
    Names: »fonts.c«

Derivation

└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/laser-setters/dvi-to-ps/TeXPS/dvitps/src/fonts.c« 

TextFile

/* Copyright 1988 Stephan v. Bechtolsheim */

/* This file is part of the TeXPS Software Package.

The TeXPS Software Package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.  No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing.  Refer to the TeXPS Software Package
General Public License for full details.

Everyone is granted permission to copy, modify and redistribute
the TeXPS Software Package, but only under the conditions described in the
TeXPS Software Package General Public License.   A copy of this license is
supposed to have been given to you along with TeXPS Software Package so you
can know your rights and responsibilities.  It should be in a
file named CopyrightLong.  Among other things, the copyright notice
and this notice must be preserved on all copies.  */

/* Basic font handling */

#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include "defs.h"
#include "dvitps.h"
#include "units.h"
#include "extfil.h"
#include "fontd.h"
#include "emit.h"
#include "tfm.h"
#include "dvi-com.h"

/* Externals. */
extern char *SetUpHashTable();
extern char *LookUpKeyInHashTableE();
extern char *LocateFileWithPath();
extern char *Malloc();
extern void SetFontFileName();
extern void ReadGfFileInfo();
extern void ReadPkFileInfo();
extern void ReadPxlFileInfo();
extern void ReadPdrFileInfo();
extern void NewPsFont();

extern TFM_S_P ReadTfmFileUsePath();
extern EX_FILES ExDvi;
extern EX_FILES Ex_PsOutput;
extern char *texfonts_default;
extern char *StrcpyAlloc();
extern char *GetBytes();
extern char *getenv();
extern int CurFontNumber;
extern FFP FontFilePriorities[4];
extern char TryThisFontFileName[256];
extern int FontsFindError;
extern int Verbose;
extern int DriverMag;
extern int Resolution;
extern int ListFontSearch;
extern double ConvertPosPoints();
extern double ConvertPosPointsNoDriverMag();
extern FE_P Fonts[MAX_FONTS];
extern FE_P CurFontPointer;
/* Subdirectory for finding the font files. */
extern char TryThisFontFileDir[256];
extern char *FontsSearchPathCommandLine;

/* Data structure for FontFileSearchLoop() to report back the result
   of its search process. */
typedef struct ffs {
  int ffs_found; /* TRUE if a font file was found and therefore all the following
		    fields are loaded. FALSE otherwise. */
  int  ffs_type; /* Indicator what font type, CF_* */
  char *ffs_fn; /* Full and expanded file name of gf, pk, pxl or pdr file. */
}
FFS;

FFS FontFileSearchLoop();

/* Hash table to locate fonts. Hash key is the concatenation
   of font name, size font is used at, and the checksum. */
char *FontHashTable;

/* This is what is stored in the hash table: the normalized
   font number. */
typedef struct fh_struct {
  int fh_number;
}
FH, *FH_P;

int NextFontIndex; /* Next free font index. */
void FontNewDviFile();
void SubstituteAFont();

/*
 * This array maps the font number from the current dvi file
 * to the driver internal font number. -1 means that this
 * entry is free (which is an error, because it means that the
 * mapping is not possible). Otherwise the entry is the font number
 * to which the font number in the dvi file is translated to.
 */
int DviFileFontMap[MAX_FONTS];


/*
 * FontFileSearchLoop
 * ******************
 * This procedure searches for a font file.
 *
 * f_n: font name
 * f_a: area length
 * f_mag: font magnification.
 * RET: An FFS structure with ffs_found set as follows:
 *      TRUE: the font file was found (and also all the other fields are set).
 *      FALSE: the font file was not found.
 */
FFS
FontFileSearchLoop(f_n, f_a, f_mag)
     char *f_n;
     int f_a;
     double f_mag;
{
  int priority; /* Loop index */
  int try_type; /* Type of font file tried out */
  int found_a_type; /* TRUE, when there is a type of given priority. */
  int ty; /* Type */
  char buffer[256];
  FFS ret;

  /* Loop through all possibilities for font files (gf, pk, pxl and pdr).
     Priorities are set by the user. */
  for (priority = 0; priority <= 3; priority++){
    found_a_type = FALSE;

    /* Find which file type has that priority. */
    for (ty=0; ty<=3; ty++) {
      if (FontFilePriorities[ty].ffp_p == priority) {
	found_a_type = TRUE;
	try_type = ty;
	break;
      }
    }

    /* No font file type found with that priority. It's time to quit. */
    if (!found_a_type) {
      ret.ffs_found = FALSE;
      return(ret);
    }

    /*
     * Now set the font file name, and then look for the file.
     * If (area in dvi-file empty) then
     *   use FontPath to look for file;
     * else
     *   use name as it is in the dvi file;
     * fi;
     */
    SetFontFileName(try_type, f_mag, f_n);
    sprintf (buffer, "%s%s", TryThisFontFileDir, TryThisFontFileName);
#ifdef DEBUG
    fprintf (stderr, "%% FontFileSearchLoop(): looking for \"%s\"\n", buffer);
#endif
    if (f_a == 0) {
      if ((ret.ffs_fn = LocateFileWithPath(buffer, FontFilePriorities[try_type].ffp_s,
					   NULL, ListFontSearch)) != NULL) {
	ret.ffs_type = try_type;
	ret.ffs_found = TRUE;
	return(ret);
      }
    } else { /* "area" is defined for this font. */
      if (access (TryThisFontFileName, R_OK) == 0) {
	ret.ffs_type = try_type;
	ret.ffs_found = TRUE;
	ret.ffs_fn = StrcpyAlloc(TryThisFontFileName);
	return(ret);
      }
    }
  } /* for priority = ... */

  /* Here we come only if ALL four font file types are used in an installation
     and NO font file was found, which matches the specified magnifications, etc.
     This bug was discovered by anderson@sapir.cog.jhu.edu. It bombed out
     when the font substitution mechanism was tested processing the documentation. */
  ret.ffs_found = FALSE;
  return (ret);
}

/*
 * FontNewDviFile
 * **************
 * Call this routine if a new dvi file is started, and all the font business
 * which relates to one particular .dvi file, must be reset now.
 */
void
FontNewDviFile()
{
  int i;

  for (i=0; i<MAX_FONTS; i++)
    DviFileFontMap[i] = -1;
}

/*
 * InitFontHandling
 * ****************
 * Initalize font handling.
 * In particular sets up all the search paths etc. This procedure is only
 * called once in the beginning.
 */
void
InitFontHandling()
{
  int i, cf;
  char *fp;

  NextFontIndex = 0;
  FontHashTable = SetUpHashTable (50, sizeof(FH), "Font name hash table");
  FontNewDviFile();

  /* Clear the search path specications in the font priority array. */
  for (i=0; i<=3; i++)
    FontFilePriorities[i].ffp_s = NULL;

  /* Initialize font array. */
  for (i=0; i<MAX_FONTS; i++)
    Fonts[i] = NULL;

  /* CF_PXL, CF_GF, CF_PK and CF_PDR */
  for (cf=0; cf<=3; cf++) {
    switch (cf) {
      /* Consult font type specific environment variables first. */
      case CF_GF: 
        fp = getenv ("TEXFONTS_DVITPS_GF");
	break;
      case CF_PK:
	fp = getenv ("TEXFONTS_DVITPS_PK");
	break;
      case CF_PXL:
	fp = getenv ("TEXFONTS_DVITPS_PXL");
	break;
      case CF_PDR:
	fp = getenv ("TEXFONTS_DVITPS_PDR");
	break;
      default:
	Fatal ("InitFontHandling(): switch");
      } /* switch */

    /* -A option overrides everything. */
    if (FontsSearchPathCommandLine != NULL)
      fp = FontsSearchPathCommandLine;

    /* Still nothing! */
    if (fp == NULL) {
      if ((fp=getenv("TEXFONTS_DVITPS")) == NULL) {
	if ((fp=getenv("TEXFONTS")) == NULL)
	  fp = texfonts_default;
      }
    }
    if (fp == NULL)
      Fatal ("InitFontHandling(): X-1");
    FontFilePriorities[cf].ffp_s = StrcpyAlloc(fp);
  }
}

/* Font substitution information is stored in this table.
   This table has 7 entries, because there are (including
   \magstep 0 and \magstephalf) 7 \magsteps. */
struct fsub {
  double fs_basemag;   /* Base magnfication, 1.0, 1.099, 1.2 etc. */
  double fs_fontmag;   /* Font magnification to be used. */
  int    fs_gf_pk_ext; /* gf and pk file extension. */
  int    fs_pxl_ext;   /* pxl file extension. */
} Fsub_table[7];

/*
 * InitFontSubstitutionBusiness
 * ****************************
 * Initialize font substitution business.
 */
void
InitFontSubstitutionBusiness()
{
  int i;

  if (DriverMag == 0)
    Fatal ("InitFontSubstitutionBusiness(): DriverMag == 0");

  /* Load the base magnifications. */
  Fsub_table[0].fs_basemag = 1.0;
  Fsub_table[1].fs_basemag = 1.095;
  Fsub_table[2].fs_basemag = 1.2;
  for (i=3; i<=6; i++)
    Fsub_table[i].fs_basemag = 1.2 * Fsub_table[i-1].fs_basemag;

  /* Compute font magnifications which compensate for global magnifications. */
  for (i=0; i<=6; i++)
    Fsub_table[i].fs_fontmag = Fsub_table[i].fs_basemag / (DriverMag / 1000.0);

  /* Load the standard file extensions (gf,pk files and pxl files)
     which depend on the current resolution. */
  for (i=0; i<=6; i++) {
    Fsub_table[i].fs_gf_pk_ext = GfPkCluge(Resolution * Fsub_table[i].fs_basemag);
    Fsub_table[i].fs_pxl_ext   = PxlCluge (5.0 * Resolution * Fsub_table[i].fs_basemag);
  }

#ifdef DEBUG
  for (i=0; i<=6; i++)
    fprintf (stderr, "%2d: %7.4lf %7.4lf %5d %5d\n",
	     i, Fsub_table[i].fs_basemag, Fsub_table[i].fs_fontmag,
	     Fsub_table[i].fs_gf_pk_ext, Fsub_table[i].fs_pxl_ext);
#endif
}

/*
 * AdviseOnFontSubstitution
 * ************************
 * Help finding a font to be used for font substitution.
 *
 * f_mag: font magnification of the font for which no font could
 *        be found.
 * RET: largest index to be used in the Fsub_table[i] array for searching
 *      for a proper replacement font.
 */
int
AdviseOnFontSubstitution(f_mag)
     double f_mag;
{
  int i;

  if (f_mag <= Fsub_table[0].fs_fontmag)
    return (0);
  if (f_mag >= Fsub_table[6].fs_fontmag)
    return (6);
  for (i=0; i<=5; i++)
    if (Fsub_table[i].fs_fontmag <= f_mag &&
	f_mag < Fsub_table[i+1].fs_fontmag)
      return (i);
  Fatal ("AdviseOnFontSubstitution(): should never come here.");
  return(0); /* lint */
}

/*
 * NewFontFromDviFile
 * ******************
 * We have read in the basic information about a font from a dvi
 * file. We compute now the internal font number. We first look into
 * the hash table and see whether the font is there. If so we use the
 * old information. If not so we allocate a new driver internal font
 *
 * k: font number from dvi file
 * RET: TRUE, if this was a truely new font.
 *      FALSE if the font was already known and was already in the font table.
 */
int
NewFontFromDviFile (k)
     int k;
{
  char buffer [256];
  FH_P p;
  int check_sum;
  int s_factor;
  int design_size;
  int area_font_l;
  int length_font_name;
  char * font_name;

  if (DriverMag == 0)
    Fatal ("NewFontFromDviFile(): DriverMag not loaded.");

  check_sum = NoSignExtend(EX_FP(ExDvi), 4);
  s_factor  = NoSignExtend(EX_FP(ExDvi), 4);
  design_size = NoSignExtend(EX_FP(ExDvi), 4);
  area_font_l = NoSignExtend(EX_FP(ExDvi), 1);
  length_font_name = NoSignExtend(EX_FP(ExDvi), 1); /* length font name */
  font_name = GetBytes(EX_FP(ExDvi), area_font_l + length_font_name);

  /* Form key for hash table of fonts. Try to insert key. */
  sprintf (buffer, "%s-%d-%d", font_name, s_factor, check_sum);
  if ((p=(FH_P)InsertKeyIntoHashTableDup(FontHashTable, buffer)) == NULL) {
    /* This font is already in the hash table. */
    p = (FH_P)LookUpKeyInHashTableE (FontHashTable, buffer);
    CurFontNumber = p->fh_number;
    CurFontPointer = Fonts[CurFontNumber];
    DviFileFontMap[k] = CurFontNumber;
    return (FALSE);
  } else {
    /* Insertion was successful, i.e. it is a truely new font. */
    p->fh_number = NextFontIndex++;
    CurFontNumber = p->fh_number;
    DviFileFontMap[k] = CurFontNumber;

    /* Create room for this font. */
    Fonts[CurFontNumber] = (FE_P) Malloc(sizeof(FE));
    CurFontPointer = Fonts[CurFontNumber];

    /* Enter some stuff we already read in. */
    CurFontPointer->f_c = check_sum;
    CurFontPointer->f_s = s_factor;
    CurFontPointer->f_d = design_size;
    CurFontPointer->f_a = area_font_l;
    CurFontPointer->f_l = length_font_name;
    CurFontPointer->f_n = font_name;
    CurFontPointer->f_class = FOCLASS_UNDEFINED;

    /* More loading goes on in ReadFontDef(). */
    return (TRUE);
  }
}

/*
 * ReadFontDef
 * ***********
 * Read font definition for font k from the postamble of the dvi file.
 *
 * k: font number as found in the dvi file.
 */
void
ReadFontDef(k)
     int k;
{
  char buffer[256];
  FFS ffs_s; /* Result of FontFileSearchLoop(). */
#ifdef DEBUG
  char area[256];
  char name[256];
#endif
#ifdef DEBUG
  fprintf (stderr,  "%% ReadFontDef() [%d]:, ", k);
#endif
  if (k>= MAX_FONTS)
    Fatal ("ReadFontDef(): k>=MAX_FONTS");

  /* If we found that this font is already known because it already
   * occured in a preceding dvi file then we don't have to continue.
   * If it's a new font, also the whole stuff is read in. */
  if (! NewFontFromDviFile (k))
    return;

  /* A truely new font: we have to load in some info. */
  CurFontPointer->f_k = CurFontNumber;

#ifdef DEBUG
  strncpy (area, CurFontPointer->f_n, CurFontPointer->f_a);
  area[CurFontPointer->f_a] = '\0';
  strcpy  (name, CurFontPointer->f_n+CurFontPointer->f_a);
  fprintf (stderr, "\"%s\", (area: \"%s\", name: \"%s\") ",
	   CurFontPointer->f_n, area, name);
#endif

  CurFontPointer->f_fnt_def_length = 4 + 4 + 4 + 1 + 1 + 
    CurFontPointer->f_a + CurFontPointer->f_l;

  /* Compute the magnification of the font. This EXCLUDES the global
     magnification. */
  CurFontPointer->f_mag =
    (double)CurFontPointer->f_s / (double)CurFontPointer->f_d;

#ifdef DEBUG
  fprintf (stderr, "mag: %5.3lf, space: %d\n", 
	   CurFontPointer->f_mag, CurFontPointer->f_s);
#endif

  /* Get the font type and try to find what type of font it is.
   * This also sets the PostScript name of the font
   * and the change font instruction for this font. */

  CurFontPointer->f_ex_file.ef_fn = NULL;
  CurFontPointer->f_type = CF_NONE;
  CurFontPointer->f_new_font = FALSE;

  /* If the -F option is given some of the basic properties of this font will
     be printed. */
  if (ListFontSearch) {
    fprintf (stderr, "Font search: \"%s\", %4.2lfpt font, used at %5.2lfpt\n",
	     CurFontPointer->f_n,
	     ConvertPosPoints(CurFontPointer->f_d),
	     ConvertPosPoints(CurFontPointer->f_s));
    if (CurFontPointer->f_d != CurFontPointer->f_s) {
      fprintf (stderr, "\tmagnification: ");
      PrintMag ((int)(CurFontPointer->f_mag*1000.0), stderr);
      fprintf (stderr, ")\n");
    }
  }

  /* Here look for the font file now. */
  CurFontPointer->f_class = FOCLASS_UNDEFINED;
  ffs_s = FontFileSearchLoop(CurFontPointer->f_n, CurFontPointer->f_a, CurFontPointer->f_mag);
  if (ffs_s.ffs_found) {
    CurFontPointer->f_ex_file.ef_fn = ffs_s.ffs_fn;
    CurFontPointer->f_type = ffs_s.ffs_type;
    CurFontPointer->f_class = FOCLASS_AS_REQUESTED;
  } else {
    /* No font file was found. Try substituting a different font. If SubstituteAFont()
       returns then a substitution occured. The procedure will generate a fatal
       error in case no substitution was possible. */
    SubstituteAFont();
  }
#ifdef DEBUG
  fprintf (stderr, "%% ReadFontDef(): Font file name: \"%s\"\n",
	   CurFontPointer->f_ex_file.ef_fn);
#endif

  if (Verbose == V_A_LOT)
    fprintf (stderr, "%2d: [%s]\n", CurFontNumber, CurFontPointer->f_ex_file.ef_fn);

  /* Give the font name the name "@F" followed by the font number. */
  sprintf (buffer, "@F%d", CurFontNumber);
#ifdef DEBUG
    fprintf (stderr, "%% ReadFontDef(): Font[%d]: file name: \"%s\"\n",
	     CurFontNumber, CurFontPointer->f_ex_file.ef_fn);
#endif

  /*
   * Depending on where we get the font info from, load
   * some initial data for each font.
   */
  switch (CurFontPointer->f_type) {
    case CF_GF:
      ReadGfFileInfo();
      break;
    case CF_PK:
      ReadPkFileInfo();
      break;
    case CF_PXL:
      ReadPxlFileInfo();
      break;
    case CF_PDR:
      ReadPdrFileInfo();
      break;
    default:
      Fatal ("ReadFontDef(): illegal font type.");
  } /* switch */
}

/*
 * SendNewFontInstruction
 * **********************
 * Send new font instruction to the PostScript output file, it this
 * is necessary.
 */
void
SendNewFontInstruction()
{
  char buffer[256];

  if (CurFontPointer->f_new_font)
    return;

  /* Generate NewFont instructions. */
  switch (CurFontPointer->f_type) {
    case CF_PXL:
    case CF_PK:
    case CF_GF:
      fprintf (EX_FP(Ex_PsOutput), "/@F%d @newfont\n", CurFontNumber);
      CurFontPointer->f_new_font = TRUE;
      sprintf (buffer, "@F%d @sf", CurFontNumber);
      CurFontPointer->f_sf = StrcpyAlloc(buffer);
      break;
    case CF_PDR:
      NewPsFont(); /* This sets f_new_font if not yet. */
      sprintf (buffer, "@F%d-%d @sfps", CurFontNumber,
	       CurFontPointer->f_pdr->p_ser);
      CurFontPointer->f_sf = StrcpyAlloc(buffer);
      break;
    default:
      Fatal ("SendNewFontInstruction(): default.");
  } /* switch */
}

/*
 * SubstituteAFont
 * ***************
 * This is where the font substitution business is actually executed.
 */
void
SubstituteAFont()
{
  TFM_S_P tfm; /* tfm data structure if tfm file is loaded because
		  no gf, pk, pxl or pdr file for the font can be found. */
  FFS ffs_s; /* Result of FontFileSearchLoop(). */
  int i; /* Loop variable. */

  /* Generate elaborate error message because font was not found. */
  FontsFindError = FALSE;
  fprintf (stderr, "Cannot locate a font file for the following font:\n");
  fprintf (stderr, "=================================================\n");
  fprintf (stderr, "\tName: \"%s\"\n", CurFontPointer->f_n);
  fprintf (stderr, "\tGlobal magnification:      ");
  PrintMag (DriverMag, stderr);
  fprintf (stderr, "\n");
  
  fprintf (stderr, "\tThis font's magnification: ");
  PrintMag ((int)(CurFontPointer->f_mag*1000.0), stderr);
  fprintf (stderr, "\n\tIt is a %5.2lfpt font used at %5.2lfpt.\n",
	   ConvertPosPointsNoDriverMag(CurFontPointer->f_d),
	   ConvertPosPoints(CurFontPointer->f_s));
  /* Give an idea about what file extension (if it's a pixel based font)
     was used to locate the font. The computation is from "search2.c". */
  fprintf (stderr, "\tGF/PK file extension used for searching font file: %4d.\n",
	   GfPkCluge(CurFontPointer->f_mag * (DriverMag/1000.0) * Resolution));
  fprintf (stderr, "\tPXL   file extension used for searching font file: %4d.\n",
	   PxlCluge(CurFontPointer->f_mag * (DriverMag/1000.0) * Resolution * 5));
  
  /* Here is where we begin trying to fix things. Now a more or less intelligent
     font substitution will take place. */

  /* Load the tfm file for this font; generates a fatal error if the tfm file can't be found. */
  tfm = ReadTfmFileUsePath(CurFontPointer->f_n, getenv("TEXFONTS"), texfonts_default);
  
  /* Replacement font computation. The code which follows could be even more sophisticated.
     For instance, there could be a table which says that if the driver does not find
     font 'abc*' it should use 'def'. */

  /* 1st attempt: use the same font, in a loop downwards, using standard
     magsteps. */
  for (i=AdviseOnFontSubstitution(CurFontPointer->f_mag); i>=0; i--) {
    CurFontPointer->f_repl_mag = Fsub_table[i].fs_fontmag;
    CurFontPointer->f_repl_n = CurFontPointer->f_n;
    ffs_s = FontFileSearchLoop (CurFontPointer->f_repl_n, 0,
				CurFontPointer->f_repl_mag); /* Find it, if possible. */
    if (ffs_s.ffs_found)
      goto replacement_font_found;
  }

  /* In all likelyhood the following attemps (2nd to 4th) are never executed,
     because the first one just attempted succeeded. */

  /* 2nd attempt: use cmr10, at the magnification originally requested. */
  CurFontPointer->f_repl_mag = CurFontPointer->f_mag;
  CurFontPointer->f_repl_n = "cmr10";
  ffs_s = FontFileSearchLoop (CurFontPointer->f_repl_n, 0, CurFontPointer->f_repl_mag);
  if (ffs_s.ffs_found)
    goto replacement_font_found;
  
  /* 3rd attempt: use cmr10, compensate for some odd global magnification to arrive
     at a (hopefully) good pixel file extension. */
  CurFontPointer->f_repl_mag = CurFontPointer->f_mag / (DriverMag / 1000.0);
  CurFontPointer->f_repl_n = "cmr10";
  ffs_s = FontFileSearchLoop (CurFontPointer->f_repl_n, 0, CurFontPointer->f_repl_mag);
  if (ffs_s.ffs_found)
    goto replacement_font_found;
  
  /* 4th attempt: use cmr10, at magnification 1.0.  This is the last attempt, and a fatal
     error will be generated in case this substitution also fails. Again compensation
     for any odd global magnification factor is executed. */
  CurFontPointer->f_repl_mag = 1.0 / (DriverMag / 1000.0);
  CurFontPointer->f_repl_n = "cmr10";
  ffs_s = FontFileSearchLoop (CurFontPointer->f_repl_n, 0, CurFontPointer->f_repl_mag);
  if (ffs_s.ffs_found)
    goto replacement_font_found;

  /* None of the substitutions worked, it's time to give up. */
  fprintf (stderr, "Cannot locate a replacement font for this font.\n");
  if (! ListFontSearch)
    fprintf (stderr, "Run driver again using -F option!\n");
  Fatal ("SubstituteAFont(): that's it.");

  /* The replacement font was located. Perform the necessary substitutions so
     it will be loaded later. Report what substitution will be done. */
  replacement_font_found:

  fprintf (stderr, "\n");
  fprintf (stderr, "\tInformation about replacement font used:\n");
  fprintf (stderr, "\t----------------------------------------\n");
  fprintf (stderr, "\tFont file name, replacement font:  \"%s\"\n", ffs_s.ffs_fn);
  fprintf (stderr, "\tMagnification of replacement font: %6.3lf\n", CurFontPointer->f_repl_mag);
  fprintf (stderr, "\tMagnification * global mag:        %6.3lf\n",
	   CurFontPointer->f_repl_mag * (DriverMag/1000.0));
  fprintf (stderr, "\n");

  CurFontPointer->f_n = CurFontPointer->f_repl_n;
  CurFontPointer->f_ex_file.ef_fn = ffs_s.ffs_fn;
  CurFontPointer->f_type  = ffs_s.ffs_type;
  CurFontPointer->f_c     = tfm->tfm_cs;
  CurFontPointer->f_class = FOCLASS_REPLACEMENT_FONT;

  /* Now copy the tfm metric information over to the character info array. */
  for (i=0; i<128; i++)
    CurFontPointer->f_ch[i].c_w_tfm = tfm->tfm_c_width[i];

  return;
}

/*
 * SkipFontDef
 * ***********
 * Skip a font definition (the assumption is that that
 * font has already been read in as part of the PostAmble
 * read procedure. Side effect is to reposition the dvi file
 * accordingly.
 *
 * command: dvi command which must be one of DVI_FONT_DEF1..4
 *          That was the last command read in and that command
 *          caused a call to this function.
 */
void
SkipFontDef(command)
     int command;
{
  int k; /* Font number, first original from dvi file, then the
	    normalized number. */
  if (command < DVI_FNT_DEF1 || command > DVI_FNT_DEF4)
    Fatal2 ("SkipFontDef(): illegal dvi command %d", command);
  k = NoSignExtend(EX_FP(ExDvi), command - DVI_FNT_DEF1+1);
  k = DviFileFontMap[k];
  FExSeek (&ExDvi, Fonts[k]->f_fnt_def_length, FSEEK_REL);
}

/*
 * SkipPotentialFontDefinitions
 * ****************************
 * Read from the dvi file until you find no more any font definitions.
 * The assumption is that if there are any font definitions actually
 * found, that those are known fonts (that is a valid assumption because
 * this driver reads in all font definitions from the postamble).
 */
void
SkipPotentialFontDefinitions()
{
  int command; /* A command code from the dvi file which is begin read in. */

  for (;;) {
    switch(command = NoSignExtend (EX_FP(ExDvi), 1)) {
      case DVI_FNT_DEF1:
      case DVI_FNT_DEF2:
      case DVI_FNT_DEF3:
      case DVI_FNT_DEF4:
        SkipFontDef(command);
	break;
      default:
	/* Undo the effect of reading command, then return. */
	FExSeek (&ExDvi, -1, FSEEK_REL);
	return;
      }
  }
}