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 e

⟦de1946d09⟧ TextFile

    Length: 20299 (0x4f4b)
    Types: TextFile
    Names: »emitc.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/emitc.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.  */


/*
 * The following switches are defined:
 * DEBUG_GF: show any gf file reading.
 * DEBUG_PK: show any pk file reading.
 * SAFE: indices checking for PIX. Should be consistent with
 * the same switch in shipc.c.
 */

#define SAFE

#include <stdio.h>
#include "defs.h"
#include "units.h"
#include "dvitps.h"
#include "extfil.h"
#include "fontd.h"
#include "gf-com.h"
#include "pdr.h"
#include "emit.h"

/* Declarations for the painting business in gf and pk files. BLACK (1)
 * and WHITE (0) are defined in gf-com.h */
#define INVERT_PAINT paint_switch = 1 - paint_switch;

extern char *Malloc();
extern char *StrcpyAlloc();
extern void Blacken();
extern void ShipPixelsToPrinter();
extern void DuplicateRows();
extern void OpenFontFileCached();

extern int CharactersDownloadedThisPage;
extern int CurFontNumber;
extern FE_P CurFontPointer;
extern EX_FILES Ex_PsOutput;
extern int HConv;
extern int HConvUnMag;
extern int SmallPsVectors;

CE_P DownLoadCharXX();
void PdrHandleChar();
void GfDownLoadCharBitMap();
void PkDownLoadCharBitMap();
void PxlDownLoadCharBitMap();

int CurFontSelected; /* Has the current font already been selected, i.e.
			switched to? */
/*
 * This will be our standard array to load with pixels from pixel files.
 * This array is to be interpreted as follows:
 * The first index is the row index, the second is the column index.
 * The row index is on a bit basis, the column index on a 8-bit basis.
 * The array is loaded as follows: in case a character has n-rows,
 * then the rows are loaded into indices n-1..0 (top row has index n-1).
 * The columns are loaded left to right.
 *
 * The way the font transformation matrix is set up, we have to load
 * from this array top to down: this matrix is a unity matrix and
 * therefore we proceed in the positive y direction.
 *
 * You have to read the postscript code, which the driver downloads, with
 * the code in this program. Initially this pointer is NULL indicating
 * that no array at all is allocated.
 */
char *PIX;

/* Current number of rows and columns of the dynamically allocated PIX[][]. */
int PixelsMaxRow;
int PixelsMaxCol;

int RepeatCount; /* For pk files. */

void HandleCharacterPass0();
void DownLoadCharBitMap();
void MaintainPixelsArray();
void CheckPixelArrayIndices();

/*
 * HandleCharacterPass0
 * ********************
 * This routine is called for every character during Pass0 which
 * must be downloaded (tested in Pass0), and also once for each
 * PostScript characters (although, unless a PS procedure is
 * behind them, they do not have to be downloaded.)
 *
 * c:   character code, font is the current font.
 */
void
HandleCharacterPass0(char_code)
     int char_code;
{
  CE_P ce;
  CharactersDownloadedThisPage ++;

  switch (CurFontPointer->f_type) {
    case CF_PXL:
      ce = DownLoadCharXX(char_code);
      PxlDownLoadCharBitMap (char_code, ce);
      break;
    case CF_GF:
      ce = DownLoadCharXX(char_code);
      GfDownLoadCharBitMap (char_code, ce);
      break;
    case CF_PK:
      ce = DownLoadCharXX(char_code);
      PkDownLoadCharBitMap (char_code, ce);
      break;
    case CF_PDR:
      PdrHandleChar (char_code);
      break;
    default:
      Fatal("HandleCharacterPass0(): default.");
    }
}

/*
 * PdrHandleChar
 * *************
 * Handle character, pdr file.
 *
 * c: character code.
 */
void
PdrHandleChar (c)
     int c;
{
  CE_P ce;
  char * p;
  char buffer[256];
  double move_x;

  /* Check whether character code is ok, if -S option was used. */
  if (SmallPsVectors && c>= 128)
    Fatal2 ("PdrHandleChar(): -S option can not be used in this dvi file [font \"%s\"]",
	    CurFontPointer->f_n);
  ce = &(CurFontPointer->f_ch[c]);
  switch (ce->c_type) {
    case CT_AFM:
    case CT_ASS:
      ce->c_dl = TRUE;
      break;
    case CT_EXECPS:
      ce->c_dl = TRUE;
      /* Start defining a PS procedure for this character */
      fprintf (EX_FP(Ex_PsOutput), "/%s {\n", ce->c_n);
      /* Include width in Pixels */
      move_x = (double)ce->c_rw / (double)HConv;
      fprintf (EX_FP(Ex_PsOutput), "\t/Move-X %6.3lf def\n", move_x);
      /* Procedure which converts afm units into pixels */
      fprintf (EX_FP(Ex_PsOutput), "\t/Convert-Afm-To-Pixels { %6.3lf mul } def\n",
	       (double)CurFontPointer->f_s/(double)HConvUnMag/1000.0);
      /* Now send the PS code of this procedure. */
      p = ce->c_prog;
      while (*p != '\0')
	putc (*p++, EX_FP(Ex_PsOutput));
      /* Procedure is now defined */
      fprintf (EX_FP(Ex_PsOutput), "}\ndef\n");
      break;
    case CT_WIDTH_ONLY:
      /* Here we come only when a PS font is used for font
	 emulation and the PS font has no character defined there
	 but the font being emulated does. Because if the font
	 being emulated did not have a character defined at
	 this position than TeX in the first place would not have
	 written this information to the dvi file. */
      ce->c_type = CT_EXECPS;
      ce->c_execps_type = EXECPS_DRIVER;
      ce->c_dl = TRUE;
      /* Here we form the procedure to be executed for this character.
	 We draw a black square in place of the character. */
      sprintf (buffer, "@F%d==%o", CurFontNumber, c);
      ce->c_n = StrcpyAlloc(buffer);
      /* Include width in Pixels */
      move_x = (double)ce->c_rw / (double)HConv;
      sprintf (buffer, "/%s {\n\
		currentpoint		1 0 rmoveto\n\
		currentpoint newpath moveto\n\
		0 %6.3lf rlineto %6.3lf 0 rlineto 0 %6.3lf rlineto\n\
		closepath fill\n\
		moveto\n\
		%6.3lf 0 rmoveto\n} def\n", ce->c_n,
		   -move_x, move_x, move_x, move_x);
      ce->c_prog = StrcpyAlloc(buffer);
      fprintf (EX_FP(Ex_PsOutput), ce->c_prog);
      break;
    case CT_NONE:
      Fatal3 ("PdrHandleChar(): CT_NONE,\n\t\tfont %s, char: '%o",
	      CurFontPointer->f_ex_file.ef_fn, c);
    default:
      Fatal3 ("PdrHandleChar(): CT_def,\n\t\tfont, char: '%o",
	      CurFontPointer->f_ex_file.ef_fn, c);
    }
}

/*
 * GfDownLoadCharBitMap
 * ********************
 * This routine is only called, if a character's bitmap in a gf file
 * has not yet been downloaded.
 *
 * c:   character code, font is the current font.
 * ce:  character encoding entry.
 */
void
GfDownLoadCharBitMap(c, ce)
     int c;
     CE_P ce;
{
  int i;
  int command; /* Command read in from gf file. */
  int paint_switch; /* paint switch in the .gf file: 1 is black, 0 is white */
  int n; /* gf row */
  int m; /* gf column */
  int del_m;
  int min_m, max_m; /* Minimum and maximum of m of current character. */
  int del_n;
  int min_n, max_n; /* gf file */
  int m_start, n_start; /* Starting values. */
  int gf_done; /* To control reading from gf file. */
  int tmp;
  int p;

  if (c < 0 || c > MAX_CHAR_CODE_PIXEL_FONTS)
    Fatal2 ("GfDownLoadCharBitMap(): exceeded character code ('%o)", c);

  gf_done = FALSE;
  while (! gf_done) {
    command = NoSignExtend(CurFontPointer->f_ex_file.ef_filep, 1);
#ifdef DEBUG_GF
    fprintf (stderr, "%% GF Command: %d\n", command);
#endif
    switch (command) {
      case GF_PAINT1:
      case GF_PAINT2:
      case GF_PAINT3:
        tmp = NoSignExtend(CurFontPointer->f_ex_file.ef_filep,
			   command - GF_PAINT1 + 1);
	if (paint_switch == BLACK)
	  Blacken (n, m, tmp);
	INVERT_PAINT;
	m += tmp;
	break;

      case GF_BOC:
	/* read c[4] */
	while ((i = NoSignExtend(CurFontPointer->f_ex_file.ef_filep, 4)) != c) {
	  if ((p = NoSignExtend(CurFontPointer->f_ex_file.ef_filep, 4)) == -1)
	    Fatal2 ("GfDownLoadCharBotmap(): GF_BOC: no character '%o found", c);
	  FExSeek (&(CurFontPointer->f_ex_file), p, FSEEK_ABS);
	} /* while */
	NoSignExtend (CurFontPointer->f_ex_file.ef_filep, 4); /* skip p */
	min_m = SignExtend(CurFontPointer->f_ex_file.ef_filep, 4);
	max_m = SignExtend(CurFontPointer->f_ex_file.ef_filep, 4);
	min_n = SignExtend(CurFontPointer->f_ex_file.ef_filep, 4);
	max_n = SignExtend(CurFontPointer->f_ex_file.ef_filep, 4);

	del_m = max_m - min_m;
	del_n = max_n - min_n;

	m_start = 0;
	n_start = max_n - min_n;
	m = m_start;
	n = n_start;
	paint_switch = WHITE;

	MaintainPixelsArray (del_n, del_m);
	break;

      case GF_BOC1:
	if (NoSignExtend(CurFontPointer->f_ex_file.ef_filep, 1) != c)
	  Fatal ("GfDownLoadCharBitMap(): GF inconsistent character code");
	del_m = NoSignExtend (CurFontPointer->f_ex_file.ef_filep, 1);
	max_m = NoSignExtend (CurFontPointer->f_ex_file.ef_filep, 1);
	del_n = NoSignExtend (CurFontPointer->f_ex_file.ef_filep, 1);
	max_n = NoSignExtend (CurFontPointer->f_ex_file.ef_filep, 1);

	min_m = max_m - del_m;
	min_n = max_n - del_n;

	m_start = 0;
	n_start = max_n - min_n;
	m = m_start;
	n = n_start;
	paint_switch = WHITE;
#ifdef DEBUG_GF
	fprintf (stderr,
		 "%% GfDownLoadCharBitMap (CF_GF): m: column, n: row\n");
	fprintf (stderr,
		 "%% GF_BOC1 (%d): m:[%d..%d], n:[%d..%d] m_start: %d, n_start: %d\n",
		 c, min_m, max_m, min_n, max_n, m_start, n_start);
#endif
	MaintainPixelsArray (del_n, del_m);
	break;
      case GF_EOC:
	gf_done = TRUE;
#ifdef DEBUG_GF
	fprintf (stderr, "%% GF_EOC: (m,n) = (%d,%d)\n", m, n);
#endif
	break;
      case GF_SKIP0:
	n--;
	m = m_start;
	paint_switch = WHITE;
	break;
      case GF_SKIP1: case GF_SKIP2: case GF_SKIP3:
	tmp = NoSignExtend (CurFontPointer->f_ex_file.ef_filep,
			    command - GF_SKIP1 + 1);
	n -= (tmp+1);
	m = m_start;
	paint_switch = WHITE;
	break;
	/* GF_XXX*, GF_YYY: just drop it */
      case GF_XXX1: case GF_XXX2: case GF_XXX3: case GF_XXX4:
	NoSignExtend (CurFontPointer->f_ex_file.ef_filep, command - GF_XXX1 + 1);
	break;
      case GF_YYY:
	NoSignExtend (CurFontPointer->f_ex_file.ef_filep, 4);
	break;
      case GF_NO_OP:
	break;
      case GF_CHAR_LOC:
      case GF_CHAR_LOC0:
      case GF_PRE:
      case GF_POST:
      case GF_POST_POST:
	Fatal ("GfDownLoadCharBitMap(): illegal Op code gf file.");
      default:
	if ((GF_PAINT_00 <= command) && (command <= GF_PAINT_63)) {
	  if (paint_switch == BLACK)
	    Blacken (n, m, command - GF_PAINT_00);
	  INVERT_PAINT;
	  m += command - GF_PAINT_00;
	}
	else if ((GF_NEW_ROW_000 <= command)&&(command <= GF_NEW_ROW_164)) {
	  n--;
	  m = m_start + (command-GF_NEW_ROW_000);
	  paint_switch = BLACK;
	}
	else
	  Fatal ("GfDownLoadCharBitMap(): illegal Op code GF file.");
      } /* switch */
  } /* while */
  ShipPixelsToPrinter (c, del_m, del_n+1, -min_m, max_n, PixRound(ce->c_rw, HConv));
}

/*
 * PkDownLoadCharBitMap
 * ********************
 * Download pixel information from a pk file.
 *
 * c: character code, font is the current font.
 * ce: character entry
 */
void
PkDownLoadCharBitMap(c, ce)
     int c;
     CE_P ce;
{
  int n_rows; /* pxl: number of rows in pixels */
  int n_cols; /* pxl: number of columns in pixels */
  int paint_switch; /* Paint switch in the .gf file: 1 is black, 0 is white.*/
  int n; /* gf row */
  int m; /* gf column */
  int m_start, n_start; /* Starting values. */
  int max_m;
  int dyn_f;
  int p;
  int tmp;
  int rep; /* Repeat count. */

  if (c < 0 || c > MAX_CHAR_CODE_PIXEL_FONTS)
    Fatal2 ("PkDownLoadCharBitMap(): exceeded character code ('%o)", c);

  InitNybbling (CurFontPointer->f_ex_file.ef_filep);
  rep = 0;
  RepeatCount = 0;
  n_rows = ce->c_ph; /* Number of rows (pixels) */
  n_cols = ce->c_pw; /* Number of columns (pixels) */
  n_start = ce->c_ph - 1; /* starting row */
  m_start = 0; /* starting column */
  n = n_start;
  m = m_start;
  max_m = ce->c_pw - 1; /* maximum column index */

  MaintainPixelsArray (n_rows, n_cols);

  paint_switch = (ce->c_flag & 0x8) != 0 ? BLACK : WHITE;
  dyn_f = (ce->c_flag & 0xf0) >> 4;
  if (dyn_f >= 15)
    Fatal ("PkDownLoadCharBitMap(): CF_PK: illegal dyn_f.");

  /* Character which is NOT runlength encoded !! */
  if (dyn_f == 14) {
    InitBitling (CurFontPointer->f_ex_file.ef_filep);
    for (n=n_start; n>=0; n--) {
      for (m=0; m<=max_m; m++) {
	if (GetBit())
	  Blacken (n, m, 1);
      }
    }
    ShipPixelsToPrinter (c, n_cols, n_rows, ce->c_xoff, ce->c_yoff,
			 PixRound(ce->c_rw, HConv));
    return;
  } /* dyn_f == 14 */

#ifdef DEBUG_PK
  fprintf (stderr, "%% CF_PK: char: '%o\n", c);
#endif

  while (n >= 0) {
    p = PkPackedNum(dyn_f); /* Get a new run count, may set RepeatCount. */
    if (RepeatCount > 0) { /* RepeatCount set as side effect of Pk. */
      rep = RepeatCount;
      RepeatCount = 0;
    }

#ifdef DEBUG_PK
    fprintf(stderr,"%% row[n]: %2d, col [m]: %2d, p= %3d, rep: %2d\n",
	    n, m, p, rep);
#endif
    if (p==0)
      Fatal ("PkDownLoadCharBitmap(): p==0");
    while (p > 0) {
      tmp = MIN_MACRO(p, max_m - m + 1); /* Positions affected in cur row. */
#ifdef DEBUG_PK
      fprintf(stderr, "%%\ttmp = %d, p = %d, n = %d, m = %d\n",
	      tmp, p, n, m);
#endif
      if (paint_switch == BLACK)
	Blacken (n, m, tmp);
      p -= tmp;
      m += tmp;
      if (m == (max_m+1)) { /* At the end of a row. */
	m = m_start; /* Go to the beginning of the current row. */
	if (rep != 0) {
#ifdef DEBUG_PK
	  fprintf (stderr, "%% n: %d, rep: %d\n", n, rep);
#endif	      
	  DuplicateRows (n, n_cols, rep);
	  n -= rep;
	  rep = 0;
	} /* rep != 0 */
	n--; /* Go one row down. */
      } /* At the end of a row. */
    } /* p > 0 */

    INVERT_PAINT;
  } /* while n >= 0 */

  ShipPixelsToPrinter (c, n_cols, n_rows, ce->c_xoff, ce->c_yoff,
		       PixRound(ce->c_rw, HConv));
}

/*
 * PxlDownLoadCharBitMap
 * ********************
 * This routine is only called, if the font is a bitmap based font
 * and the character's bitmap has not yet been downloaded.
 * It is only called during Pass0. We may have to open the font file!
 * This routine is not called for PS fonts.
 *
 * c:   character code, font is the current font.
 * ce: character entry
 */
void
PxlDownLoadCharBitMap(c, ce)
     int c;
     CE_P ce;
{
  int n_rows; /* pxl: number of rows in pixels */
  int n_cols; /* pxl: number of columns in pixels */
  int n_skip_col_byte;
  int i, j;
  int p;

  if (c < 0 || c > MAX_CHAR_CODE_PIXEL_FONTS)
    Fatal2 ("PxlDownLoadCharBitMap(): exceeded character code ('%o)", c);

#ifdef DEBUG
    fprintf (stderr,
	     "%% DownLoadCharBitMap (CF_PXL): Char: '%o, w: %d, h: %d, x-off: %d, y-off: %d\n",
	     c, ce->c_pw, ce->c_ph, ce->c_xoff, ce->c_yoff);
#endif

  /*
   * Preparation for reading stuff from pxl file. The computations
   * here have to do with the fact, that from the pxl file we
   * read on a word (32 bit) basis, whereas our array is based
   * on bytes.
   */
  n_rows = ce->c_ph; /* number of rows */
  n_cols = ce->c_pw; /* number of columns (pixels) */
  n_skip_col_byte =(ce->c_pw + 31)/32;/* how many words per row */
  n_skip_col_byte *= 4; /* number of bytes */
  n_skip_col_byte -= (ce->c_pw + 7)/8;

  MaintainPixelsArray (n_rows, n_cols);

  /* Read the stuff from the pxl file. */
  for (i=n_rows-1; i>=0; i--) { /* Row index. */
    for (j=0; j<(ce->c_pw + 7)/8; j++) { /* Column index. */
#ifdef SAFE
      CheckPixelArrayIndices(i,j);
#endif
      PIX_LOAD(i,j) = NoSignExtend (CurFontPointer->f_ex_file.ef_filep, 1);
    }
    FExSeek (&(CurFontPointer->f_ex_file), n_skip_col_byte, FSEEK_REL);
  }

  /* Ship the pixels and all the other information out. */
  ShipPixelsToPrinter (c, n_cols, n_rows, ce->c_xoff, ce->c_yoff,
		       PixRound(ce->c_rw, HConv));
}

/*
 * PkPackedNum
 * ***********
 * Return a packed number from a pk file.
 *
 * dny_f: see the description of packed numbers.
 * RET: the packed number.
 */
int
PkPackedNum (dyn_f)
     int dyn_f;
{
  int i;
  int j;

  i = GetNybble();
  if (i == 0) { /* Large run counts */
    do { /* Count number of zeros */
      j = GetNybble();
      i++;
    }
    while (j == 0);

    /* j now contains the first digit of a large run count */
    while (i-- > 0)
      j = 16*j + GetNybble();
    return (j - 15 + (13-dyn_f)*16 + dyn_f); /* normalization */
  } else
    if (i <= dyn_f) { /* single nybble run count */
      return (i);
    } else
      if (i < 14) { /* double nybble run count */
	return ((i-dyn_f-1)*16 + GetNybble() + dyn_f + 1);
      } else {
	if (RepeatCount != 0)
	  Fatal ("PkPackedNum(): extra repeat count");
	if (i == 14)
	  RepeatCount = PkPackedNum(dyn_f);
	else
	  RepeatCount = 1;
	return(PkPackedNum(dyn_f));
      }
}

/*
 * MaintainPixelsArray
 * *******************
 * Call this routine to maintain the PIX array. If the array as currently
 * allocated is too small, it is reallocated / enlarged.
 *
 * n_rows:    number of rows needed    ('bits')
 * n_cols:    number of columns needed ('bits')
 */
void
MaintainPixelsArray (n_rows, n_cols)
     int n_rows;
     int n_cols;
{
  int all_rows; /* How many rows and columns do you need will be stored here. */
  int all_cols;

  int i, j;

  if (PIX == NULL) {
    PixelsMaxRow = 0;
    PixelsMaxCol = 0;
  }

  /* Compute how much space PIX should have. */
  all_rows = MAX_MACRO(ROW_PXL_INIT, n_rows);
  all_cols = MAX_MACRO(COL_PXL_INIT, n_cols);
  all_rows += 24;
  all_cols += 24;
  /* Increase all_cols to the next multiple of 8. */
  all_cols = ((all_cols/8) + 1) * 8;

  /* Do nothing, if currently big enough. PixelMaxRow and PixelMaxColumn are
     initially zero so that the very first call to MaintainPixelsArray()
     will actually allocate the array. */
  if (all_rows <= PixelsMaxRow && all_cols <= PixelsMaxCol)
    return;

  /* The old array has not enough space, we have to allocated some
   * more space. We free the old space in case this is not
   * the very first allocation. */
  if (PIX != NULL)
    free (PIX);

  /* Allocate the array now. */
  PixelsMaxRow = MAX_MACRO(all_rows, PixelsMaxRow);
  PixelsMaxCol = MAX_MACRO(all_cols, PixelsMaxCol);
#ifdef DEBUG
  fprintf (stderr, "%% MaintainPixelsArray(): all_rows/cols = %d %d\n",
	   PixelsMaxRow, PixelsMaxCol);
#endif
  PIX = Malloc(PixelsMaxRow * (PixelsMaxCol/8));

  /* Initialize array */
  for (i=0; i<PixelsMaxRow; i++) {
    for (j=0; j<PixelsMaxCol/8; j++) {
      PIX_LOAD(i,j) = 0;
    }
  }
}

/*
 * CheckPixelArrayIndices
 * **********************
 * Trying to trace down an error: call this procedure
 * with (i, j), the two indices of Pixels[][] and this
 * procedure will check, whether things are ok or not.
 * Time consuming. Only done if SAVE is defined.
 *
 * i: row (bits)
 * j: col (bytes)
 */
void
CheckPixelArrayIndices(i, j)
     int i;
     int j;
{
  if (i < 0)
    Fatal ("CheckPixelArrayIndices: i < 0");
  if (j < 0)
    Fatal ("CheckPixelArrayIndices: j < 0");
  if (i >= PixelsMaxRow)
    Fatal ("CheckPixelArrayIndices: i >= PixelsMaxRow");
  if (j >= PixelsMaxCol/8)
    Fatal ("CheckPixelArrayIndices: j >= PixelsMaxCol/8");
}

/*
 * DownLoadCharXX
 * **************
 * For the character with character code c:
 * 1. Open the font file (pixel file), if necessary.
 * 2. Issue a font change instruction, if necessary.
 *
 * c: character code.
 * RET: pointer to the character structure.
 */
CE_P
DownLoadCharXX(c)
     int c;
{
  CE_P ce;

  ce = &(CurFontPointer->f_ch[c]);

  /* Here is a short cut to avoiding calling FExOpen(): if file is already
     in cache, nothing needs to be done. */
  if (! CurFontPointer->f_ex_file.ef_in_cache)
    OpenFontFileCached ();
  /* Position within the pixel file. */
  FExSeek (&(CurFontPointer->f_ex_file), ce->c_offset, FSEEK_ABS);
  ce->c_dl = TRUE; /* Mark as downloaded now. */

  /* Issue font change instruction. */
  if (! CurFontSelected) {
    fprintf (EX_FP(Ex_PsOutput), "%s\n", CurFontPointer->f_sf);
    CurFontSelected = TRUE;
  }
  return (ce);
}