]> git.sesse.net Git - rdpsrv/blobdiff - Xserver/lib/font/Type1/type1.c
Removed Xserver/ directory, it does nothing useful ATM.
[rdpsrv] / Xserver / lib / font / Type1 / type1.c
diff --git a/Xserver/lib/font/Type1/type1.c b/Xserver/lib/font/Type1/type1.c
deleted file mode 100644 (file)
index 92d6d8c..0000000
+++ /dev/null
@@ -1,1776 +0,0 @@
-/* $XConsortium: type1.c,v 1.7 94/02/07 15:30:22 gildea Exp $ */
-/* Copyright International Business Machines, Corp. 1991
- * All Rights Reserved
- * Copyright Lexmark International, Inc. 1991
- * All Rights Reserved
- * Portions Copyright (c) 1990 Adobe Systems Incorporated.
- * All Rights Reserved
- *
- * License to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of IBM or Lexmark or Adobe
- * not be used in advertising or publicity pertaining to distribution of
- * the software without specific, written prior permission.
- *
- * IBM, LEXMARK, AND ADOBE PROVIDE THIS SOFTWARE "AS IS", WITHOUT ANY
- * WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
- * LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  THE
- * ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE, INCLUDING
- * ANY DUTY TO SUPPORT OR MAINTAIN, BELONGS TO THE LICENSEE.  SHOULD ANY
- * PORTION OF THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM,
- * LEXMARK, OR ADOBE) ASSUMES THE ENTIRE COST OF ALL SERVICING, REPAIR AND
- * CORRECTION.  IN NO EVENT SHALL IBM, LEXMARK, OR ADOBE BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-/*********************************************************************/
-/*                                                                   */
-/* Type 1 module - Converting fonts in Adobe Type 1 Font Format      */
-/*                 to scaled and hinted paths for rasterization.     */
-/*                 Files: type1.c, type1.h, and blues.h.             */
-/*                                                                   */
-/* Authors:   Sten F. Andler, IBM Almaden Research Center            */
-/*                 (Type 1 interpreter, stem & flex hints)           */
-/*                                                                   */
-/*            Patrick A. Casey, Lexmark International, Inc.          */
-/*                 (Font level hints & stem hints)                   */
-/*                                                                   */
-/*********************************************************************/
-/******************/
-/* Include Files: */
-/******************/
-#include  <stdio.h>          /* a system-dependent include, usually */
-#include  "objects.h"
-#include  "spaces.h"
-#include  "paths.h"
-#include  "fonts.h"        /* understands about TEXTTYPEs */
-#include  "pictures.h"     /* understands about handles */
-typedef struct xobject xobject;
-#include  "util.h"       /* PostScript objects */
-#include  "blues.h"          /* Blues structure for font-level hints */
-/**********************************/
-/* Type1 Constants and Structures */
-/**********************************/
-#define MAXSTACK 24        /* Adobe Type1 limit */
-#define MAXCALLSTACK 10    /* Adobe Type1 limit */
-#define MAXPSFAKESTACK 32  /* Max depth of fake PostScript stack (local) */
-#define MAXSTRLEN 512      /* Max length of a Type 1 string (local) */
-#define MAXLABEL 256       /* Maximum number of new hints */
-#define MAXSTEMS 128       /* Maximum number of VSTEM and HSTEM hints */
-#define EPS 0.001          /* Small number for comparisons */
-/************************************/
-/* Adobe Type 1 CharString commands */
-/************************************/
-#define HSTEM        1
-#define VSTEM        3
-#define VMOVETO      4
-#define RLINETO      5
-#define HLINETO      6
-#define VLINETO      7
-#define RRCURVETO    8
-#define CLOSEPATH    9
-#define CALLSUBR    10
-#define RETURN      11
-#define ESCAPE      12
-#define HSBW        13
-#define ENDCHAR     14
-#define RMOVETO     21
-#define HMOVETO     22
-#define VHCURVETO   30
-#define HVCURVETO   31
-/*******************************************/
-/* Adobe Type 1 CharString Escape commands */
-/*******************************************/
-#define DOTSECTION       0
-#define VSTEM3           1
-#define HSTEM3           2
-#define SEAC             6
-#define SBW              7
-#define DIV             12
-#define CALLOTHERSUBR   16
-#define POP             17
-#define SETCURRENTPOINT 33
-/*****************/
-/* Useful macros */
-/*****************/
-static double tmpx;  /* Store macro argument in tmpx to avoid re-evaluation */
-static long tmpi;    /* Store converted value in tmpi to avoid re-evaluation */
-#define FABS(x) (((tmpx = (x)) < 0.0) ? -tmpx : tmpx)
-#define CEIL(x) (((tmpi = (long) (tmpx = (x))) < tmpx) ? ++tmpi : tmpi)
-#define FLOOR(x) (((tmpi = (long) (tmpx = (x))) > tmpx) ? --tmpi : tmpi)
-#define ROUND(x) FLOOR((x) + 0.5)
-#define ODD(x) (((int)(x)) & 01)
-#define Error {errflag = TRUE; return;}
-#define ErrorRet(ret) {errflag = TRUE; return (ret);}
-#define Error0(errmsg) {IfTrace0(TRUE, errmsg); Error;}
-#define Error0Ret(errmsg, ret) {IfTrace0(TRUE, errmsg); ErrorRet(ret);}
-#define Error1(errmsg,arg) {IfTrace1(TRUE, errmsg, arg); Error;}
-/********************/
-/* global variables */
-/********************/
-struct stem {                     /* representation of a STEM hint */
-    int vertical;                 /* TRUE if vertical, FALSE otherwise */
-    double x, dx;                 /* interval of vertical stem */
-    double y, dy;                 /* interval of horizontal stem */
-    struct segment *lbhint, *lbrevhint;   /* left  or bottom hint adjustment */
-    struct segment *rthint, *rtrevhint;   /* right or top    hint adjustment */
-};
-extern struct XYspace *IDENTITY;
-static double escapementX, escapementY;
-static double sidebearingX, sidebearingY;
-static double accentoffsetX, accentoffsetY;
-static struct segment *path;
-static int errflag;
-/*************************************************/
-/* Global variables to hold Type1Char parameters */
-/*************************************************/
-static char *Environment;
-static struct XYspace *CharSpace;
-static psobj *CharStringP, *SubrsP, *OtherSubrsP;
-static int *ModeP;
-/************************/
-/* Forward declarations */
-/************************/
-static double Div();
-static double PSFakePop();
-static DoCommand();
-static Escape();
-static HStem();
-static VStem();
-static RLineTo();
-static RRCurveTo();
-static DoClosePath();
-static CallSubr();
-static Return();
-static EndChar();
-static RMoveTo();
-static DotSection();
-static Seac();
-static Sbw();
-static CallOtherSubr();
-static SetCurrentPoint();
-
-/*****************************************/
-/* statics for Flex procedures (FlxProc) */
-/*****************************************/
-static struct segment *FlxOldPath; /* save path before Flex feature */
-/******************************************************/
-/* statics for Font level hints (Blues) (see blues.h) */
-/******************************************************/
-static struct blues_struct *blues; /* the blues structure */
-static struct alignmentzone alignmentzones[MAXALIGNMENTZONES];
-static int numalignmentzones;     /* total number of alignment zones */
-/****************************************************************/
-/* Subroutines for the Font level hints (Alignment zones, etc.) */
-/****************************************************************/
-/******************************************/
-/* Fill in the alignment zone structures. */
-/******************************************/
-static ComputeAlignmentZones()
-{
-  int i;
-  double dummy, bluezonepixels, familyzonepixels;
-  struct segment *p;
-  numalignmentzones = 0;     /* initialize total # of zones */
-  /* do the BlueValues zones */
-  for (i = 0; i < blues->numBlueValues; i +=2, ++numalignmentzones) {
-    /* the 0th & 1st numbers in BlueValues are for a bottom zone */
-    /* the rest are topzones */
-    if (i == 0)           /* bottom zone */
-      alignmentzones[numalignmentzones].topzone = FALSE;
-    else                  /* top zone */
-      alignmentzones[numalignmentzones].topzone = TRUE;
-    if (i < blues->numFamilyBlues) {    /* we must consider FamilyBlues */
-      p = ILoc(CharSpace,0,blues->BlueValues[i] - blues->BlueValues[i+1]);
-      QueryLoc(p, IDENTITY, &dummy, &bluezonepixels);
-      Destroy(p);
-      p = ILoc(CharSpace,0,blues->FamilyBlues[i]-blues->FamilyBlues[i+1]);
-      QueryLoc(p, IDENTITY, &dummy, &familyzonepixels);
-      Destroy(p);
-      /* is the difference in size of the zones less than 1 pixel? */
-      if (FABS(bluezonepixels - familyzonepixels) < 1.0) {
-        /* use the Family zones */
-        alignmentzones[numalignmentzones].bottomy =
-          blues->FamilyBlues[i];
-        alignmentzones[numalignmentzones].topy =
-          blues->FamilyBlues[i+1];
-        continue;
-      }
-    }
-    /* use this font's Blue zones */
-    alignmentzones[numalignmentzones].bottomy = blues->BlueValues[i];
-    alignmentzones[numalignmentzones].topy = blues->BlueValues[i+1];
-  }
-  /* do the OtherBlues zones */
-  for (i = 0; i < blues->numOtherBlues; i +=2, ++numalignmentzones) {
-    /* all of the OtherBlues zones are bottom zones */
-    alignmentzones[numalignmentzones].topzone = FALSE;
-    if (i < blues->numFamilyOtherBlues) {/* consider FamilyOtherBlues  */
-      p = ILoc(CharSpace,0,blues->OtherBlues[i] - blues->OtherBlues[i+1]);
-      QueryLoc(p, IDENTITY, &dummy, &bluezonepixels);
-      Destroy(p);
-      p = ILoc(CharSpace,0,blues->FamilyOtherBlues[i] -
-        blues->FamilyOtherBlues[i+1]);
-      QueryLoc(p, IDENTITY, &dummy, &familyzonepixels);
-      Destroy(p);
-      /* is the difference in size of the zones less than 1 pixel? */
-      if (FABS(bluezonepixels - familyzonepixels) < 1.0) {
-        /* use the Family zones */
-        alignmentzones[numalignmentzones].bottomy =
-          blues->FamilyOtherBlues[i];
-        alignmentzones[numalignmentzones].topy =
-          blues->FamilyOtherBlues[i+1];
-        continue;
-      }
-    }
-    /* use this font's Blue zones (as opposed to the Family Blues */
-    alignmentzones[numalignmentzones].bottomy = blues->OtherBlues[i];
-    alignmentzones[numalignmentzones].topy = blues->OtherBlues[i+1];
-  }
-}
-/**********************************************************************/
-/* Subroutines and statics for handling of the VSTEM and HSTEM hints. */
-/**********************************************************************/
-static int InDotSection;             /* DotSection flag */
-static struct stem stems[MAXSTEMS];  /* All STEM hints */
-static int numstems;                 /* Number of STEM hints */
-static int currstartstem;            /* The current starting stem. */
-static int oldvert, oldhor;          /* Remember hint in effect */
-static int oldhorhalf, oldverthalf;  /* Remember which half of the stem */
-static double wsoffsetX, wsoffsetY;  /* White space offset - for VSTEM3,HSTEM3 */
-static int wsset;                    /* Flag for whether we've set wsoffsetX,Y */
-static InitStems()  /* Initialize the STEM hint data structures */
-{
-  InDotSection = FALSE;
-  currstartstem = numstems = 0;
-  oldvert = oldhor = -1;
-}
-static FinitStems()  /* Terminate the STEM hint data structures */
-{
-  int i;
-  for (i = 0; i < numstems; i++) {
-    Destroy(stems[i].lbhint);
-    Destroy(stems[i].lbrevhint);
-    Destroy(stems[i].rthint);
-    Destroy(stems[i].rtrevhint);
-  }
-}
-/*******************************************************************/
-/* Compute the dislocation that a stemhint should cause for points */
-/* inside the stem.                                                */
-/*******************************************************************/
-static ComputeStem(stemno)
-int stemno;
-{
-  int verticalondevice, idealwidth;
-  double stemstart, stemwidth;
-  struct segment *p;
-  int i;
-  double stembottom, stemtop, flatposition;
-  double Xpixels, Ypixels;
-  double unitpixels, onepixel;
-  int suppressovershoot, enforceovershoot;
-  double stemshift, flatpospixels, overshoot;
-  double widthdiff; /* Number of character space units to adjust width */
-  double lbhintvalue, rthintvalue;
-  double cxx, cyx, cxy, cyy; /* Transformation matrix */
-  int rotated; /* TRUE if character is on the side, FALSE if upright */
-  /************************************************/
-  /* DETERMINE ORIENTATION OF CHARACTER ON DEVICE */
-  /************************************************/
-  QuerySpace(CharSpace, &cxx, &cyx, &cxy, &cyy); /* Transformation matrix */
-  if (FABS(cxx) < 0.00001 || FABS(cyy) < 0.00001)
-    rotated = TRUE; /* Char is on side (90 or 270 degrees), possibly oblique. */
-  else if (FABS(cyx) < 0.00001 || FABS(cxy) < 0.00001)
-    rotated = FALSE; /* Char is upright (0 or 180 degrees), possibly oblique. */
-  else {
-    stems[stemno].lbhint = NULL; /* Char is at non-axial angle, ignore hints. */
-    stems[stemno].lbrevhint = NULL;
-    stems[stemno].rthint = NULL;
-    stems[stemno].rtrevhint = NULL;
-    return;
-  }
-  /* Determine orientation of stem */
-  if (stems[stemno].vertical) {
-    verticalondevice = !rotated;
-    stemstart = stems[stemno].x;
-    stemwidth = stems[stemno].dx;
-  } else {
-    verticalondevice = rotated;
-    stemstart = stems[stemno].y;
-    stemwidth = stems[stemno].dy;
-  }
-  /* Determine how many pixels (non-negative) correspond to 1 character space
-     unit (unitpixels), and how many character space units (non-negative)
-     correspond to one pixel (onepixel). */
-  if (stems[stemno].vertical)
-    p = ILoc(CharSpace, 1, 0);
-  else
-    p = ILoc(CharSpace, 0, 1);
-  QueryLoc(p, IDENTITY, &Xpixels, &Ypixels);
-  Destroy(p);
-  if (verticalondevice)
-    unitpixels = FABS(Xpixels);
-  else
-    unitpixels = FABS(Ypixels);
-  onepixel = 1.0 / unitpixels;
-  /**********************/
-  /* ADJUST STEM WIDTHS */
-  /**********************/
-  widthdiff = 0.0;
-  /* Find standard stem with smallest width difference from this stem */
-  if (stems[stemno].vertical) { /* vertical stem */
-    if (blues->StdVW != 0)      /* there is an entry for StdVW */
-      widthdiff = blues->StdVW - stemwidth;
-    for (i = 0; i < blues->numStemSnapV; ++i) { /* now look at StemSnapV */
-      if (blues->StemSnapV[i] - stemwidth < widthdiff)
-        /* this standard width is the best match so far for this stem */
-        widthdiff = blues->StemSnapV[i] - stemwidth;
-    }
-  } else {                      /* horizontal stem */
-    if (blues->StdHW != 0)      /* there is an entry for StdHW */
-      widthdiff = blues->StdHW - stemwidth;
-    for (i = 0; i < blues->numStemSnapH; ++i) { /* now look at StemSnapH */
-      if (blues->StemSnapH[i] - stemwidth < widthdiff)
-        /* this standard width is the best match so far for this stem */
-        widthdiff = blues->StemSnapH[i] - stemwidth;
-    }
-  }
-  /* Only expand or contract stems if they differ by less than 1 pixel from
-     the closest standard width, otherwise make the width difference = 0. */
-  if (FABS(widthdiff) > onepixel)
-    widthdiff = 0.0;
-  /* Expand or contract stem to the nearest integral number of pixels. */
-  idealwidth = ROUND((stemwidth + widthdiff) * unitpixels);
-  /* Ensure that all stems are at least one pixel wide. */
-  if (idealwidth == 0)
-    idealwidth = 1;
-  /* Apply ForceBold to vertical stems. */
-  if (blues->ForceBold && stems[stemno].vertical)
-    /* Force this vertical stem to be at least DEFAULTBOLDSTEMWIDTH wide. */
-    if (idealwidth < DEFAULTBOLDSTEMWIDTH)
-      idealwidth = DEFAULTBOLDSTEMWIDTH;
-  /* Now compute the number of character space units necessary */
-  widthdiff = idealwidth * onepixel - stemwidth;
-  /*********************************************************************/
-  /* ALIGNMENT ZONES AND OVERSHOOT SUPPRESSION - HORIZONTAL STEMS ONLY */
-  /*********************************************************************/
-  stemshift = 0.0;
-  if (!stems[stemno].vertical) {
-    /* Get bottom and top boundaries of the stem. */
-    stembottom = stemstart;
-    stemtop = stemstart + stemwidth;
-    /* Find out if this stem intersects an alignment zone (the BlueFuzz  */
-    /* entry in the Private dictionary specifies the number of character */
-    /* units to extend (in both directions) the effect of an alignment   */
-    /* zone on a horizontal stem.  The default value of BlueFuzz is 1.   */
-    for (i = 0; i < numalignmentzones; ++i) {
-      if (alignmentzones[i].topzone) {
-        if (stemtop >= alignmentzones[i].bottomy &&
-            stemtop <= alignmentzones[i].topy + blues->BlueFuzz) {
-          break; /* We found a top-zone */
-        }
-      } else {
-        if (stembottom <= alignmentzones[i].topy &&
-            stembottom >= alignmentzones[i].bottomy - blues->BlueFuzz) {
-          break; /* We found a bottom-zone */
-        }
-      }
-    }
-    if (i < numalignmentzones) { /* We found an intersecting zone (number i). */
-      suppressovershoot = FALSE;
-      enforceovershoot = FALSE;
-      /* When 1 character space unit is rendered smaller than BlueScale
-         device units (pixels), we must SUPPRESS overshoots.  Otherwise,
-         if the top (or bottom) of this stem is more than BlueShift character
-         space units away from the flat position, we must ENFORCE overshoot. */
-      if (unitpixels < blues->BlueScale)
-        suppressovershoot = TRUE;
-      else
-        if (alignmentzones[i].topzone)
-          if (stemtop >= alignmentzones[i].bottomy + blues->BlueShift)
-            enforceovershoot = TRUE;
-        else
-          if (stembottom <= alignmentzones[i].topy - blues->BlueShift)
-            enforceovershoot = TRUE;
-      /*************************************************/
-      /* ALIGN THE FLAT POSITION OF THE ALIGNMENT ZONE */
-      /*************************************************/
-      /* Compute the position of the alignment zone's flat position in
-         device space and the amount of shift needed to align it on a
-         pixel boundary. Move all stems this amount. */
-      if (alignmentzones[i].topzone)
-        flatposition = alignmentzones[i].bottomy;
-      else
-        flatposition = alignmentzones[i].topy;
-      /* Find the flat position in pixels */
-      flatpospixels = flatposition * unitpixels;
-      /* Find the stem shift necessary to align the flat
-         position on a pixel boundary, and use this shift for all stems */
-      stemshift = (ROUND(flatpospixels) - flatpospixels) * onepixel;
-      /************************************************/
-      /* HANDLE OVERSHOOT ENFORCEMENT AND SUPPRESSION */
-      /************************************************/
-      /* Compute overshoot amount (non-negative) */
-      if (alignmentzones[i].topzone)
-        overshoot = stemtop - flatposition;
-      else
-        overshoot = flatposition - stembottom;
-      if (overshoot > 0.0) {
-        /* ENFORCE overshoot by shifting the entire stem (if necessary) so that
-           it falls at least one pixel beyond the flat position. */
-        if (enforceovershoot)
-          if (overshoot < onepixel)
-            if (alignmentzones[i].topzone)
-              stemshift += onepixel - overshoot;
-            else
-              stemshift -= onepixel - overshoot;
-        /* SUPPRESS overshoot by aligning the stem to the alignment zone's
-           flat position. */
-        if (suppressovershoot)
-          if (alignmentzones[i].topzone)
-            stemshift -= overshoot;
-          else
-            stemshift += overshoot;
-      }
-      /************************************************************/
-      /* COMPUTE HINT VALUES FOR EACH SIDE OF THE HORIZONTAL STEM */
-      /************************************************************/
-      /* If the stem was aligned by a topzone, we expand or contract the stem
-         only at the bottom - since the stem top was aligned by the zone.
-         If the stem was aligned by a bottomzone, we expand or contract the stem
-         only at the top - since the stem bottom was aligned by the zone. */
-      if (alignmentzones[i].topzone) {
-        lbhintvalue = stemshift - widthdiff; /* bottom */
-        rthintvalue = stemshift;             /* top    */
-      } else {
-        lbhintvalue = stemshift;             /* bottom */
-        rthintvalue = stemshift + widthdiff; /* top    */
-      }
-      stems[stemno].lbhint    = (struct segment *)Permanent(Loc(CharSpace, 0.0,  lbhintvalue));
-      stems[stemno].lbrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -lbhintvalue));
-      stems[stemno].rthint    = (struct segment *)Permanent(Loc(CharSpace, 0.0,  rthintvalue));
-      stems[stemno].rtrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -rthintvalue));
-      return;
-    } /* endif (i < numalignmentzones) */
-    /* We didn't find any alignment zones intersecting this stem, so
-       proceed with normal stem alignment below. */
-  } /* endif (!stems[stemno].vertical) */
-  /* Align stem with pixel boundaries on device */
-  stemstart = stemstart - widthdiff / 2;
-  stemshift = ROUND(stemstart * unitpixels) * onepixel - stemstart;
-  /* Adjust the boundaries of the stem */
-  lbhintvalue = stemshift - widthdiff / 2; /* left  or bottom */
-  rthintvalue = stemshift + widthdiff / 2; /* right or top    */
-  if (stems[stemno].vertical) {
-    stems[stemno].lbhint    = (struct segment *)Permanent(Loc(CharSpace,  lbhintvalue, 0.0));
-    stems[stemno].lbrevhint = (struct segment *)Permanent(Loc(CharSpace, -lbhintvalue, 0.0));
-    stems[stemno].rthint    = (struct segment *)Permanent(Loc(CharSpace,  rthintvalue, 0.0));
-    stems[stemno].rtrevhint = (struct segment *)Permanent(Loc(CharSpace, -rthintvalue, 0.0));
-  } else {
-    stems[stemno].lbhint    = (struct segment *)Permanent(Loc(CharSpace, 0.0,  lbhintvalue));
-    stems[stemno].lbrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -lbhintvalue));
-    stems[stemno].rthint    = (struct segment *)Permanent(Loc(CharSpace, 0.0,  rthintvalue));
-    stems[stemno].rtrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -rthintvalue));
-  }
-}
-#define LEFT   1
-#define RIGHT  2
-#define BOTTOM 3
-#define TOP    4
-/*********************************************************************/
-/* Adjust a point using the given stem hint.  Use the left/bottom    */
-/* hint value or the right/top hint value depending on where the     */
-/* point lies in the stem.                                           */
-/*********************************************************************/
-static struct segment *Applyhint(p, stemnumber, half)
-struct segment *p;
-int stemnumber, half;
-{
-  if (half == LEFT || half == BOTTOM)
-    return Join(p, stems[stemnumber].lbhint); /* left  or bottom hint */
-  else
-    return Join(p, stems[stemnumber].rthint); /* right or top    hint */
-}
-/*********************************************************************/
-/* Adjust a point using the given reverse hint.  Use the left/bottom */
-/* hint value or the right/top hint value depending on where the     */
-/* point lies in the stem.                                           */
-/*********************************************************************/
-static struct segment *Applyrevhint(p, stemnumber, half)
-struct segment *p;
-int stemnumber, half;
-{
-  if (half == LEFT || half == BOTTOM)
-    return Join(p, stems[stemnumber].lbrevhint); /* left  or bottom hint */
-  else
-    return Join(p, stems[stemnumber].rtrevhint); /* right or top    hint */
-}
-/***********************************************************************/
-/* Find the vertical and horizontal stems that the current point       */
-/* (x, y) may be involved in.  At most one horizontal and one vertical */
-/* stem can apply to a single point, since there are no overlaps       */
-/* allowed.                                                            */
-/*   The actual hintvalue is returned as a location.                   */
-/* Hints are ignored inside a DotSection.                              */
-/***********************************************************************/
-static struct segment *FindStems(x, y, dx, dy)
-double x, y, dx, dy;
-{
-  int i;
-  int newvert, newhor;
-  struct segment *p;
-  int newhorhalf, newverthalf;
-  if (InDotSection) return(NULL);
-  newvert = newhor = -1;
-  newhorhalf = newverthalf = -1;
-  for (i = currstartstem; i < numstems; i++) {
-    if (stems[i].vertical) { /* VSTEM hint */
-      if ((x >= stems[i].x - EPS) &&
-          (x <= stems[i].x+stems[i].dx + EPS)) {
-        newvert = i;
-        if (dy != 0.0) {
-          if (dy < 0) newverthalf = LEFT;
-          else        newverthalf = RIGHT;
-        } else {
-          if (x < stems[i].x+stems[i].dx / 2) newverthalf = LEFT;
-          else                                newverthalf = RIGHT;
-        }
-      }
-    } else {                 /* HSTEM hint */
-      if ((y >= stems[i].y - EPS) &&
-          (y <= stems[i].y+stems[i].dy + EPS)) {
-        newhor = i;
-        if (dx != 0.0) {
-          if (dx < 0) newhorhalf = TOP;
-          else        newhorhalf = BOTTOM;
-        } else {
-          if (y < stems[i].y+stems[i].dy / 2) newhorhalf = BOTTOM;
-          else                                newhorhalf = TOP;
-        }
-      }
-    }
-  }
-  p = NULL;
-  if (newvert == -1 && oldvert == -1) ; /* Outside of any hints */
-  else if (newvert == oldvert &&
-    newverthalf == oldverthalf); /* No hint change */
-  else if (oldvert == -1) { /* New vertical hint in effect */
-    p = Applyhint(p, newvert, newverthalf);
-  } else if (newvert == -1) { /* Old vertical hint no longer in effect */
-    p = Applyrevhint(p, oldvert, oldverthalf);
-  } else { /* New vertical hint in effect, old hint no longer in effect */
-    p = Applyrevhint(p, oldvert, oldverthalf);
-    p = Applyhint(p, newvert, newverthalf);
-  }
-  if (newhor == -1 && oldhor == -1) ; /* Outside of any hints */
-  else if (newhor == oldhor &&
-    newhorhalf == oldhorhalf) ; /* No hint change */
-  else if (oldhor == -1) { /* New horizontal hint in effect */
-    p = Applyhint(p, newhor, newhorhalf);
-  } else if (newhor == -1) { /* Old horizontal hint no longer in effect */
-    p = Applyrevhint(p, oldhor, oldhorhalf);
-  }
-  else { /* New horizontal hint in effect, old hint no longer in effect */
-    p = Applyrevhint(p, oldhor, oldhorhalf);
-    p = Applyhint(p, newhor, newhorhalf);
-  }
-  oldvert = newvert; oldverthalf = newverthalf;
-  oldhor  = newhor;  oldhorhalf  = newhorhalf;
-  return p;
-}
-/******************************************************/
-/* Subroutines and statics for the Type1Char routines */
-/******************************************************/
-static int strindex; /* index into PostScript string being interpreted */
-static double currx, curry; /* accumulated x and y values for hints */
-struct callstackentry {
-  psobj *currstrP;        /* current CharStringP */
-  int currindex;          /* current strindex */
-  unsigned short currkey; /* current decryption key */
-  };
-static double Stack[MAXSTACK];
-static int Top;
-static struct callstackentry CallStack[MAXCALLSTACK];
-static int CallTop;
-static double PSFakeStack[MAXPSFAKESTACK];
-static int PSFakeTop;
-static ClearStack()
-{
-  Top = -1;
-}
-static Push(Num)
-        double Num;
-{
-  if (++Top < MAXSTACK) Stack[Top] = Num;
-  else Error0("Push: Stack full\n");
-}
-static ClearCallStack()
-{
-  CallTop = -1;
-}
-static PushCall(CurrStrP, CurrIndex, CurrKey)
-  psobj *CurrStrP;
-  int CurrIndex;
-  unsigned short CurrKey;
-{
-  if (++CallTop < MAXCALLSTACK) {
-    CallStack[CallTop].currstrP = CurrStrP;   /* save CharString pointer */
-    CallStack[CallTop].currindex = CurrIndex; /* save CharString index */
-    CallStack[CallTop].currkey = CurrKey;     /* save decryption key */
-  }
-  else Error0("PushCall: Stack full\n");
-}
-static PopCall(CurrStrPP, CurrIndexP, CurrKeyP)
-  psobj **CurrStrPP;
-  int *CurrIndexP;
-  unsigned short *CurrKeyP;
-{
-  if (CallTop >= 0) {
-    *CurrStrPP = CallStack[CallTop].currstrP; /* restore CharString pointer */
-    *CurrIndexP = CallStack[CallTop].currindex; /* restore CharString index */
-    *CurrKeyP = CallStack[CallTop--].currkey;   /* restore decryption key */
-  }
-  else Error0("PopCall: Stack empty\n");
-}
-static ClearPSFakeStack()
-{
-  PSFakeTop = -1;
-}
-/* PSFakePush: Pushes a number onto the fake PostScript stack */
-static PSFakePush(Num)
-  double Num;
-{
-  if (++PSFakeTop < MAXPSFAKESTACK) PSFakeStack[PSFakeTop] = Num;
-  else Error0("PSFakePush: Stack full\n");
-}
-/* PSFakePop: Removes a number from the top of the fake PostScript stack */
-static double PSFakePop ()
-{
-  if (PSFakeTop >= 0) return(PSFakeStack[PSFakeTop--]);
-  else Error0Ret("PSFakePop : Stack empty\n", 0.0);
-  /*NOTREACHED*/
-}
-/***********************************************************************/
-/* Center a stem on the pixel grid -- used by HStem3 and VStem3        */
-/***********************************************************************/
-static struct segment *CenterStem(edge1, edge2)
-    double edge1;
-    double edge2;
-{
-  int idealwidth, verticalondevice;
-  double leftx, lefty, rightx, righty, center, width;
-  double widthx, widthy;
-  double shift, shiftx, shifty;
-  double Xpixels, Ypixels;
-  struct segment *p;
-  p = Loc(CharSpace, edge1, 0.0);
-  QueryLoc(p, IDENTITY, &leftx, &lefty);
-  p = Join(p, Loc(CharSpace, edge2, 0.0));
-  QueryLoc(p, IDENTITY, &rightx, &righty);
-  Destroy(p);
-  widthx = FABS(rightx - leftx);
-  widthy = FABS(righty - lefty);
-  if (widthy <= EPS) { /* verticalondevice hint */
-    verticalondevice = TRUE;
-    center = (rightx + leftx) / 2.0;
-    width = widthx;
-  }
-  else if (widthx <= EPS) { /* horizontal hint */
-    verticalondevice = FALSE;
-    center = (righty + lefty) / 2.0;
-    width = widthy;
-  }
-  else { /* neither horizontal nor verticalondevice and not oblique */
-    return (NULL);
-  }
-  idealwidth = ROUND(width);
-  if (idealwidth == 0) idealwidth = 1;
-  if (ODD(idealwidth)) {       /* is ideal width odd? */
-    /* center stem over pixel */
-    shift = FLOOR(center) + 0.5 - center;
-  }
-  else {
-    /* align stem on pixel boundary */
-    shift = ROUND(center) - center;
-  }
-  if (verticalondevice) {
-    shiftx = shift;
-    shifty = 0.0;
-  } else {
-    shifty = shift;
-    shiftx = 0.0;
-  }
-  p = Loc(IDENTITY, shiftx, shifty);
-  QueryLoc(p, CharSpace, &Xpixels, &Ypixels);
-  wsoffsetX = Xpixels; wsoffsetY = Ypixels;
-  currx += wsoffsetX; curry += wsoffsetY;
-  return (p);
-}
-/*-----------------------------------------------------------------------
-  Decrypt - From Adobe Type 1 book page 63, with some modifications
------------------------------------------------------------------------*/
-#define KEY 4330 /* Initial key (seed) for CharStrings decryption */
-#define C1 52845 /* Multiplier for pseudo-random number generator */
-#define C2 22719 /* Constant for pseudo-random number generator */
-static unsigned short r; /* Pseudo-random sequence of keys */
-static unsigned char Decrypt(cipher)
-unsigned char cipher;
-{
-  unsigned char plain;
-  plain = cipher ^ (r >> 8);
-  r = (cipher + r) * C1 + C2;
-  return plain;
-}
-/* Get the next byte from the codestring being interpreted */
-static int DoRead(CodeP)
-  int *CodeP;
-{
-  if (strindex >= CharStringP->len) return(FALSE); /* end of string */
-  *CodeP = Decrypt((unsigned char) CharStringP->data.stringP[strindex++]);
-  return(TRUE);
-}
-/* Strip blues->lenIV bytes from CharString and update encryption key */
-/* (the lenIV entry in the Private dictionary specifies the number of */
-/* random bytes at the beginning of each CharString; default is 4)    */
-static void StartDecrypt()
-{
-  int Code;
-  r = KEY; /* Initial key (seed) for CharStrings decryption */
-  for (strindex = 0; strindex < blues->lenIV;)
-    if (!DoRead(&Code)) /* Read a byte and update decryption key */
-      Error0("StartDecrypt: Premature end of CharString\n");
-}
-static Decode(Code)
-  int Code;
-{
-  int Code1, Code2, Code3, Code4;
-  if (Code <= 31)                           /* Code is [0,31]    */
-    DoCommand(Code);
-  else if (Code <= 246)                     /* Code is [32,246]  */
-    Push((double)(Code - 139));
-  else if (Code <= 250) {                   /* Code is [247,250] */
-    if (!DoRead(&Code2)) goto ended;
-    Push((double)(((Code - 247) << 8) + Code2 + 108));
-  }
-  else if (Code <= 254) {                   /* Code is [251,254] */
-    if (!DoRead(&Code2)) goto ended;
-    Push((double)( -((Code - 251) << 8) - Code2 - 108));
-  }
-  else {                                    /* Code is 255 */
-    if (!DoRead(&Code1)) goto ended;
-    if (!DoRead(&Code2)) goto ended;
-    if (!DoRead(&Code3)) goto ended;
-    if (!DoRead(&Code4)) goto ended;
-    Push((double)((((((Code1<<8) + Code2)<<8) + Code3)<<8) + Code4));
-  }
-  return;
-ended: Error0("Decode: Premature end of Type 1 CharString");
-}
-/* Interpret a command code */
-static DoCommand(Code)
-  int Code;
-{
-  switch(Code) {
-    case HSTEM: /* |- y dy HSTEM |- */
-      /* Vertical range of a horizontal stem zone */
-      if (Top < 1) Error0("DoCommand: Stack low\n");
-      HStem(Stack[0], Stack[1]);
-      ClearStack();
-      break;
-    case VSTEM: /* |- x dx VSTEM |- */
-      /* Horizontal range of a vertical stem zone */
-      if (Top < 1) Error0("DoCommand: Stack low\n");
-      VStem(Stack[0], Stack[1]);
-      ClearStack();
-      break;
-    case VMOVETO: /* |- dy VMOVETO |- */
-      /* Vertical MOVETO, equivalent to 0 dy RMOVETO */
-      if (Top < 0) Error0("DoCommand: Stack low\n");
-      RMoveTo(0.0, Stack[0]);
-      ClearStack();
-      break;
-    case RLINETO: /* |- dx dy RLINETO |- */
-      /* Like RLINETO in PostScript */
-      if (Top < 1) Error0("DoCommand: Stack low\n");
-      RLineTo(Stack[0], Stack[1]);
-      ClearStack();
-      break;
-    case HLINETO: /* |- dx HLINETO |- */
-      /* Horizontal LINETO, equivalent to dx 0 RLINETO */
-      if (Top < 0) Error0("DoCommand: Stack low\n");
-      RLineTo(Stack[0], 0.0);
-      ClearStack();
-      break;
-    case VLINETO: /* |- dy VLINETO |- */
-      /* Vertical LINETO, equivalent to 0 dy RLINETO */
-      if (Top < 0) Error0("DoCommand: Stack low\n");
-      RLineTo(0.0, Stack[0]);
-      ClearStack();
-      break;
-    case RRCURVETO:
-      /* |- dx1 dy1 dx2 dy2 dx3 dy3 RRCURVETO |- */
-      /* Relative RCURVETO, equivalent to dx1 dy1 */
-      /* (dx1+dx2) (dy1+dy2) (dx1+dx2+dx3) */
-      /* (dy1+dy2+dy3) RCURVETO in PostScript */
-      if (Top < 5) Error0("DoCommand: Stack low\n");
-      RRCurveTo(Stack[0], Stack[1], Stack[2], Stack[3],
-        Stack[4], Stack[5]);
-      ClearStack();
-      break;
-    case CLOSEPATH: /* - CLOSEPATH |- */
-      /* Closes a subpath without repositioning the */
-      /* current point */
-      DoClosePath();
-      ClearStack();
-      break;
-    case CALLSUBR: /* subr# CALLSUBR - */
-      /* Calls a CharString subroutine with index */
-      /* subr# from the Subrs array */
-      if (Top < 0) Error0("DoCommand: Stack low\n");
-      CallSubr((int)Stack[Top--]);
-      break;
-    case RETURN: /* - RETURN - */
-      /* Returns from a Subrs array CharString */
-      /* subroutine called with CALLSUBR */
-      Return();
-      break;
-    case ESCAPE: /* ESCAPE to two-byte command code */
-      if (!DoRead(&Code)) Error0("DoCommand: ESCAPE is last byte\n");
-      Escape(Code);
-      break;
-    case HSBW: /* |- sbx wx HSBW |- */
-      /* Set the left sidebearing point to (sbx,0), */
-      /* set the character width vector to (wx,0). */
-      /* Equivalent to sbx 0 wx 0 SBW.  Space */
-      /* character should have sbx = 0 */
-      if (Top < 1) Error0("DoCommand: Stack low\n");
-      Sbw(Stack[0], 0.0, Stack[1], 0.0);
-      ClearStack();
-      break;
-    case ENDCHAR: /* - ENDCHAR |- */
-      /* Finishes a CharString outline */
-      EndChar();
-      ClearStack();
-      break;
-    case RMOVETO: /* |- dx dy RMOVETO |- */
-      /* Behaves like RMOVETO in PostScript */
-      if (Top < 1) Error0("DoCommand: Stack low\n");
-      RMoveTo(Stack[0], Stack[1]);
-      ClearStack();
-      break;
-    case HMOVETO: /* |- dx HMOVETO |- */
-      /* Horizontal MOVETO. Equivalent to dx 0 RMOVETO */
-      if (Top < 0) Error0("DoCommand: Stack low\n");
-      RMoveTo(Stack[0], 0.0);
-      ClearStack();
-      break;
-    case VHCURVETO: /* |- dy1 dx2 dy2 dx3 VHCURVETO |- */
-      /* Vertical-Horizontal CURVETO, equivalent to */
-      /* 0 dy1 dx2 dy2 dx3 0 RRCURVETO */
-      if (Top < 3) Error0("DoCommand: Stack low\n");
-      RRCurveTo(0.0, Stack[0], Stack[1], Stack[2],
-              Stack[3], 0.0);
-      ClearStack();
-      break;
-    case HVCURVETO: /* |- dx1 dx2 dy2 dy3 HVCURVETO |- */
-      /* Horizontal-Vertical CURVETO, equivalent to */
-      /* dx1 0 dx2 dy2 0 dy3 RRCURVETO */
-      if (Top < 3) Error0("DoCommand: Stack low\n");
-      RRCurveTo(Stack[0], 0.0, Stack[1], Stack[2], 0.0, Stack[3]);
-      ClearStack();
-      break;
-    default: /* Unassigned command code */
-      ClearStack();
-      Error1("DoCommand: Unassigned code %d\n", Code);
-  }
-}
-static Escape(Code)
-  int Code;
-{
-  int i, Num;
-  struct segment *p;
-  switch(Code) {
-    case DOTSECTION: /* - DOTSECTION |- */
-      /* Brackets an outline section for the dots in */
-      /* letters such as "i", "j", and "!". */
-      DotSection();
-      ClearStack();
-      break;
-    case VSTEM3: /* |- x0 dx0 x1 dx1 x2 dx2 VSTEM3 |- */
-      /* Declares the horizontal ranges of three */
-      /* vertical stem zones between x0 and x0+dx0, */
-      /* x1 and x1+dx1, and x2 and x2+dx2. */
-      if (Top < 5) Error0("DoCommand: Stack low\n");
-      if (!wsset && ProcessHints) {
-        /* Shift the whole character so that the middle stem is centered. */
-        p = CenterStem(Stack[2] + sidebearingX, Stack[3]);
-        path = Join(path, p);
-        wsset = 1;
-      }
-      VStem(Stack[0], Stack[1]);
-      VStem(Stack[2], Stack[3]);
-      VStem(Stack[4], Stack[5]);
-      ClearStack();
-      break;
-    case HSTEM3: /* |- y0 dy0 y1 dy1 y2 dy2 HSTEM3 |- */
-      /* Declares the vertical ranges of three hori- */
-      /* zontal stem zones between y0 and y0+dy0, */
-      /* y1 and y1+dy1, and y2 and y2+dy2. */
-      if (Top < 5) Error0("DoCommand: Stack low\n");
-      HStem(Stack[0], Stack[1]);
-      HStem(Stack[2], Stack[3]);
-      HStem(Stack[4], Stack[5]);
-      ClearStack();
-      break;
-    case SEAC: /* |- asb adx ady bchar achar SEAC |- */
-      /* Standard Encoding Accented Character. */
-      if (Top < 4) Error0("DoCommand: Stack low\n");
-      Seac(Stack[0], Stack[1], Stack[2],
-        (unsigned char) Stack[3],
-        (unsigned char) Stack[4]);
-      ClearStack();
-      break;
-    case SBW: /* |- sbx sby wx wy SBW |- */
-      /* Set the left sidebearing point to (sbx,sby), */
-      /* set the character width vector to (wx,wy). */
-      if (Top < 3) Error0("DoCommand: Stack low\n");
-      Sbw(Stack[0], Stack[1], Stack[2], Stack[3]);
-      ClearStack();
-      break;
-    case DIV: /* num1 num2 DIV quotient */
-      /* Behaves like DIV in the PostScript language */
-      if (Top < 1) Error0("DoCommand: Stack low\n");
-      Stack[Top-1] = Div(Stack[Top-1], Stack[Top]);
-      Top--;
-      break;
-    case CALLOTHERSUBR:
-      /* arg1 ... argn n othersubr# CALLOTHERSUBR - */
-      /* Make calls on the PostScript interpreter */
-      if (Top < 1) Error0("DoCommand: Stack low\n");
-      Num = Stack[Top-1];
-      if (Top < Num+1) Error0("DoCommand: Stack low\n");
-      for (i = 0; i < Num; i++) PSFakePush(Stack[Top - i - 2]);
-      Top -= Num + 2;
-      CallOtherSubr((int)Stack[Top + Num + 2]);
-      break;
-    case POP: /* - POP number */
-      /* Removes a number from the top of the */
-      /* PostScript interpreter stack and pushes it */
-      /* onto the Type 1 BuildChar operand stack */
-      Push(PSFakePop());
-      break;
-    case SETCURRENTPOINT: /* |- x y SETCURRENTPOINT |- */
-      /* Sets the current point to (x,y) in absolute */
-      /* character space coordinates without per- */
-      /* forming a CharString MOVETO command */
-      if (Top < 1) Error0("DoCommand: Stack low\n");
-      SetCurrentPoint(Stack[0], Stack[1]);
-      ClearStack();
-      break;
-    default: /* Unassigned escape code command */
-      ClearStack();
-      Error1("Escape: Unassigned code %d\n", Code);
-  }
-}
-/* |- y dy HSTEM |- */
-/* Declares the vertical range of a horizontal stem zone */
-/* between coordinates y and y + dy */
-/* y is relative to the left sidebearing point */
-static HStem(y, dy)
-  double y, dy;
-{
-  IfTrace2((FontDebug), "Hstem %f %f\n", &y, &dy);
-  if (ProcessHints) {
-    if (numstems >= MAXSTEMS) Error0("HStem: Too many hints\n");
-    if (dy < 0.0) {y += dy; dy = -dy;}
-    stems[numstems].vertical = FALSE;
-    stems[numstems].x = 0.0;
-    stems[numstems].y = sidebearingY + y + wsoffsetY;
-    stems[numstems].dx = 0.0;
-    stems[numstems].dy = dy;
-    ComputeStem(numstems);
-    numstems++;
-  }
-}
-/* |- x dx VSTEM |- */
-/* Declares the horizontal range of a vertical stem zone */
-/* between coordinates x and x + dx */
-/* x is relative to the left sidebearing point */
-static VStem(x, dx)
-  double x, dx;
-{
-  IfTrace2((FontDebug), "Vstem %f %f\n", &x, &dx);
-  if (ProcessHints) {
-    if (numstems >= MAXSTEMS) Error0("VStem: Too many hints\n");
-    if (dx < 0.0) {x += dx; dx = -dx;}
-    stems[numstems].vertical = TRUE;
-    stems[numstems].x = sidebearingX + x + wsoffsetX;
-    stems[numstems].y = 0.0;
-    stems[numstems].dx = dx;
-    stems[numstems].dy = 0.0;
-    ComputeStem(numstems);
-    numstems++;
-  }
-}
-/* |- dx dy RLINETO |- */
-/* Behaves like RLINETO in PostScript */
-static RLineTo(dx, dy)
-  double dx, dy;
-{
-  struct segment *B;
-  IfTrace2((FontDebug), "RLineTo %f %f\n", &dx, &dy);
-  B = Loc(CharSpace, dx, dy);
-  if (ProcessHints) {
-    currx += dx;
-    curry += dy;
-    /* B = Join(B, FindStems(currx, curry)); */
-    B = Join(B, FindStems(currx, curry, dx, dy));
-  }
-  path = Join(path, Line(B));
-}
-/* |- dx1 dy1 dx2 dy2 dx3 dy3 RRCURVETO |- */
-/* Relative RCURVETO, equivalent to dx1 dy1 */
-/* (dx1+dx2) (dy1+dy2) (dx1+dx2+dx3) */
-/* (dy1+dy2+dy3) RCURVETO in PostScript */
-static RRCurveTo(dx1, dy1, dx2, dy2, dx3, dy3)
-  double dx1, dy1, dx2, dy2, dx3, dy3;
-{
-  struct segment *B, *C, *D;
-  IfTrace4((FontDebug), "RRCurveTo %f %f %f %f ", &dx1, &dy1, &dx2, &dy2);
-  IfTrace2((FontDebug), "%f %f\n", &dx3, &dy3);
-  B = Loc(CharSpace, dx1, dy1);
-  C = Loc(CharSpace, dx2, dy2);
-  D = Loc(CharSpace, dx3, dy3);
-  if (ProcessHints) {
-    /* For a Bezier curve, we apply the full hint value to
-       the Bezier C point (and thereby D point). */
-    currx += dx1 + dx2 + dx3;
-    curry += dy1 + dy2 + dy3;
-    /* C = Join(C, FindStems(currx, curry)); */
-    C = Join(C, FindStems(currx, curry, dx3, dy3));
-  }
-  /* Since XIMAGER is not completely relative, */
-  /* we need to add up the delta values */
-  C = Join(C, Dup(B));
-  D = Join(D, Dup(C));
-  path = Join(path, Bezier(B, C, D));
-}
-/* - CLOSEPATH |- */
-/* Closes a subpath WITHOUT repositioning the */
-/* current point */
-static DoClosePath()
-{
-  struct segment *CurrentPoint;
-  IfTrace0((FontDebug), "DoClosePath\n");
-  CurrentPoint = Phantom(path);
-  path = ClosePath(path);
-  path = Join(Snap(path), CurrentPoint);
-}
-/* subr# CALLSUBR - */
-/* Calls a CharString subroutine with index */
-/* subr# from the Subrs array */
-static CallSubr(subrno)
-  int subrno;
-{
-  IfTrace1((FontDebug), "CallSubr %d\n", subrno);
-  if ((subrno < 0) || (subrno >= SubrsP->len))
-    Error0("CallSubr: subrno out of range\n");
-  PushCall(CharStringP, strindex, r);
-  CharStringP = &SubrsP->data.arrayP[subrno];
-  StartDecrypt();
-}
-/* - RETURN - */
-/* Returns from a Subrs array CharString */
-/* subroutine called with CALLSUBR */
-static Return()
-{
-  IfTrace0((FontDebug), "Return\n");
-  PopCall(&CharStringP, &strindex, &r);
-}
-/* - ENDCHAR |- */
-/* Finishes a CharString outline */
-/* Executes SETCHACHEDEVICE using a bounding box */
-/* it computes directly from the character outline */
-/* and using the width information acquired from a previous */
-/* HSBW or SBW.  It then calls a special version of FILL */
-/* or STROKE depending on the value of PaintType in the */
-/* font dictionary */
-static EndChar()
-{
-  IfTrace0((FontDebug), "EndChar\n");
-  /* There is no need to compute and set bounding box for
-     the cache, since XIMAGER does that on the fly. */
-  /* Perform a Closepath just in case the command was left out */
-  path = ClosePath(path);
-  /* Set character width */
-  path = Join(Snap(path), Loc(CharSpace, escapementX, escapementY));
-}
-/* |- dx dy RMOVETO |- */
-/* Behaves like RMOVETO in PostScript */
-static RMoveTo(dx,dy)
-  double dx,dy;
-{
-  struct segment *B;
-  IfTrace2((FontDebug), "RMoveTo %f %f\n", &dx, &dy);
-  B = Loc(CharSpace, dx, dy);
-  if (ProcessHints) {
-    currx += dx;
-    curry += dy;
-    /* B = Join(B, FindStems(currx, curry)); */
-    B = Join(B, FindStems(currx, curry, 0.0, 0.0));
-  }
-  path = Join(path, B);
-}
-/* - DOTSECTION |- */
-/* Brackets an outline section for the dots in */
-/* letters such as "i", "j", and "!". */
-static DotSection()
-{
-  IfTrace0((FontDebug), "DotSection\n");
-  InDotSection = !InDotSection;
-}
-/* |- asb adx ady bchar achar SEAC |- */
-/* Standard Encoding Accented Character. */
-static Seac(asb, adx, ady, bchar, achar)
-  double asb, adx, ady;
-  unsigned char bchar, achar;
-{
-  int Code;
-  struct segment *mypath;
-  IfTrace4((FontDebug), "SEAC %f %f %f %d ", &asb, &adx, &ady, bchar);
-  IfTrace1((FontDebug), "%d\n", achar);
-  /* Move adx - asb, ady over and up from base char's sbpoint. */
-  /* (We use adx - asb to counteract the accents sb shift.) */
-  /* The variables accentoffsetX/Y modify sidebearingX/Y in Sbw(). */
-  /* Note that these incorporate the base character's sidebearing shift by */
-  /* using the current sidebearingX, Y values. */
-  accentoffsetX = sidebearingX + adx - asb;
-  accentoffsetY = sidebearingY + ady;
-  /* Set path = NULL to avoid complaints from Sbw(). */
-  path = NULL;
-  /* Go find the CharString for the accent's code via an upcall */
-  CharStringP = GetType1CharString(Environment, achar);
-  StartDecrypt();
-  ClearStack();
-  ClearPSFakeStack();
-  ClearCallStack();
-  for (;;) {
-    if (!DoRead(&Code)) break;
-    Decode(Code);
-    if (errflag) return;
-  }
-  /* Copy snapped path to mypath and set path to NULL as above. */
-  mypath = Snap(path);
-  path = NULL;
-  /* We must reset these to null now. */
-  accentoffsetX = accentoffsetY = 0;
-  /* go find the CharString for the base char's code via an upcall */
-  CharStringP = GetType1CharString(Environment, bchar);
-  StartDecrypt();
-  ClearStack();
-  ClearPSFakeStack();
-  ClearCallStack();
-  FinitStems();
-  InitStems();
-  for (;;) {
-    if (!DoRead(&Code)) break;
-    Decode(Code);
-    if (errflag) return;
-  }
-  path = Join(mypath, path);
-}
-/* |- sbx sby wx wy SBW |- */
-/* Set the left sidebearing point to (sbx,sby), */
-/* set the character width vector to (wx,wy). */
-static Sbw(sbx, sby, wx, wy)
-  double sbx, sby, wx, wy;
-{
-  IfTrace4((FontDebug), "SBW %f %f %f %f\n", &sbx, &sby, &wx, &wy);
-  escapementX = wx; /* Character width vector */
-  escapementY = wy;
-  /* Sidebearing values are sbx, sby args, plus accent offset from Seac(). */
-  sidebearingX = sbx + accentoffsetX;
-  sidebearingY = sby + accentoffsetY;
-  path = Join(path, Loc(CharSpace, sidebearingX, sidebearingY));
-  if (ProcessHints) {currx = sidebearingX; curry = sidebearingY;}
-}
- /* num1 num2 DIV quotient */
-/* Behaves like DIV in the PostScript language */
-static double Div(num1, num2)
-  double num1, num2;
-{
-  IfTrace2((FontDebug), "Div %f %f\n", &num1, &num2);
-  return(num1 / num2);
-}
-/*
-  The following four subroutines (FlxProc, FlxProc1, FlxProc2, and
-  HintReplace) are C versions of the OtherSubrs Programs, which were
-  were published in the Adobe Type 1 Font Format book.
-  The Flex outline fragment is described by
-    c1: (x0, y0) = c3: (x0, yshrink(y0)) or (xshrink(x0), y0)
-     "  (x1, y1) =  "  (x1, yshrink(y1)) or (xshrink(x1), y1)
-     "  (x2, y2) - reference point
-    c2: (x0, y0) = c4: (x0, yshrink(y0)) or (xshrink(x0), y0)
-     "  (x1, y1) =  "  (x1, yshrink(y1)) or (xshrink(x1), y1)
-     "  (x2, y2) =  "  (x2, y2), rightmost endpoint
-    c3: (x0, y0) - control point, 1st Bezier curve
-     "  (x1, y1) - control point,      -"-
-     "  (x2, y2) - end point,          -"-
-    c4: (x0, y0) - control point, 2nd Bezier curve
-     "  (x1, y1) - control point,      -"-
-     "  (x2, y2) - end point,          -"-
-    ep: (epY, epX) - final endpoint (should be same as c4: (x2, y2))
-    idmin - minimum Flex height (1/100 pixel) at which to render curves
-*/
-#define dtransform(dxusr,dyusr,dxdev,dydev) { \
-  register struct segment *point = Loc(CharSpace, dxusr, dyusr); \
-  QueryLoc(point, IDENTITY, dxdev, dydev); \
-  Destroy(point); \
-}
-#define itransform(xdev,ydev,xusr,yusr) { \
-  register struct segment *point = Loc(IDENTITY, xdev, ydev); \
-  QueryLoc(point, CharSpace, xusr, yusr); \
-  Destroy(point); \
-}
-#define transform(xusr,yusr,xdev,ydev) dtransform(xusr,yusr,xdev,ydev)
-#define PaintType (0)
-#define lineto(x,y) { \
-  struct segment *CurrentPoint; \
-  double CurrentX, CurrentY; \
-  CurrentPoint = Phantom(path); \
-  QueryLoc(CurrentPoint, CharSpace, &CurrentX, &CurrentY); \
-  Destroy(CurrentPoint); \
-  RLineTo(x - CurrentX, y - CurrentY); \
-}
-#define curveto(x0,y0,x1,y1,x2,y2) { \
-  struct segment *CurrentPoint; \
-  double CurrentX, CurrentY; \
-  CurrentPoint = Phantom(path); \
-  QueryLoc(CurrentPoint, CharSpace, &CurrentX, &CurrentY); \
-  Destroy(CurrentPoint); \
-  RRCurveTo(x0 - CurrentX, y0 - CurrentY, x1 - x0, y1 - y0, x2 - x1, y2 - y1); \
-}
-#define xshrink(x) ((x - c4x2) * shrink +c4x2)
-#define yshrink(y) ((y - c4y2) * shrink +c4y2)
-#define PickCoords(flag) \
-  if (flag) { /* Pick "shrunk" coordinates */ \
-    x0 = c1x0; y0 = c1y0; \
-    x1 = c1x1; y1 = c1y1; \
-    x2 = c1x2; y2 = c1y2; \
-    x3 = c2x0; y3 = c2y0; \
-    x4 = c2x1; y4 = c2y1; \
-    x5 = c2x2; y5 = c2y2; \
-  } else { /* Pick original coordinates */ \
-    x0 = c3x0; y0 = c3y0; \
-    x1 = c3x1; y1 = c3y1; \
-    x2 = c3x2; y2 = c3y2; \
-    x3 = c4x0; y3 = c4y0; \
-    x4 = c4x1; y4 = c4y1; \
-    x5 = c4x2; y5 = c4y2; \
-  }
-/* FlxProc() = OtherSubrs[0]; Main part of Flex          */
-/*   Calling sequence: 'idmin epX epY 3 0 callothersubr' */
-/*   Computes Flex values, and renders the Flex path,    */
-/*   and returns (leaves) ending coordinates on stack    */
-static void FlxProc(c1x2, c1y2, c3x0, c3y0, c3x1, c3y1, c3x2, c3y2,
-             c4x0, c4y0, c4x1, c4y1, c4x2, c4y2, epY, epX, idmin)
-  double c1x2, c1y2;
-  double c3x0, c3y0, c3x1, c3y1, c3x2, c3y2;
-  double c4x0, c4y0, c4x1, c4y1, c4x2, c4y2;
-  double epX, epY;
-  int idmin;
-{
-  double dmin;
-  double c1x0, c1y0, c1x1, c1y1;
-  double c2x0, c2y0, c2x1, c2y1, c2x2, c2y2;
-  char yflag;
-  double x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5;
-  double cxx, cyx, cxy, cyy; /* Transformation matrix */
-  int flipXY;
-  double x, y;
-  double erosion = 1; /* Device parameter */
-    /* Erosion may have different value specified in 'internaldict' */
-  double shrink;
-  double dX, dY;
-  char erode;
-  double eShift;
-  double cx, cy;
-  double ex, ey;
-  Destroy(path);
-  path = FlxOldPath; /* Restore previous path (stored in FlxProc1) */
-  if (ProcessHints) {
-    dmin = ABS(idmin) / 100.0; /* Minimum Flex height in pixels */
-    c2x2 = c4x2; c2y2 = c4y2; /* Point c2 = c4 */
-    yflag = FABS(c1y2 - c3y2) > FABS(c1x2 - c3x2); /* Flex horizontal? */
-    QuerySpace(CharSpace, &cxx, &cyx, &cxy, &cyy); /* Transformation matrix */
-    if (FABS(cxx) < 0.00001 || FABS(cyy) < 0.00001)
-      flipXY = -1; /* Char on side */
-    else if (FABS(cyx) < 0.00001 || FABS(cxy) < 0.00001)
-      flipXY = 1; /* Char upright */
-    else
-      flipXY = 0; /* Char at angle */
-    if (yflag) { /* Flex horizontal */
-      if (flipXY == 0 || c3y2 == c4y2) { /* Char at angle or Flex height = 0 */
-        PickCoords(FALSE); /* Pick original control points */
-      } else {
-        shrink = FABS((c1y2 - c4y2) / (c3y2 - c4y2)); /* Slope */
-        c1x0 = c3x0; c1y0 = yshrink(c3y0);
-        c1x1 = c3x1; c1y1 = yshrink(c3y1);
-        c2x0 = c4x0; c2y0 = yshrink(c4y0);
-        c2x1 = c4x1; c2y1 = yshrink(c4y1);
-        dtransform(0.0, ROUND(c3y2-c1y2), &x, &y); /* Flex height in pixels */
-        dY = FABS((flipXY == 1) ? y : x);
-        PickCoords(dY < dmin); /* If Flex small, pick 'shrunk' control points */
-        if (FABS(y2 - c1y2) > 0.001) { /* Flex 'non-zero'? */
-          transform(c1x2, c1y2, &x, &y);
-          if (flipXY == 1) {
-            cx = x; cy = y;
-          } else {
-            cx = y; cy = x;
-          }
-          dtransform(0.0, ROUND(y2-c1y2), &x, &y);
-          dY = (flipXY == 1) ? y : x;
-          if (ROUND(dY) != 0)
-            dY = ROUND(dY);
-          else
-            dY = (dY < 0) ? -1 : 1;
-          erode = PaintType != 2 && erosion >= 0.5;
-          if (erode)
-            cy -= 0.5;
-          ey = cy + dY;
-          ey = CEIL(ey) - ey + FLOOR(ey);
-          if (erode)
-            ey += 0.5;
-          if (flipXY == 1) {
-            itransform(cx, ey, &x, &y);
-          } else {
-            itransform(ey, cx, &x, &y);
-          }
-          eShift = y - y2;
-          y1 += eShift;
-          y2 += eShift;
-          y3 += eShift;
-        }
-      }
-    } else { /* Flex vertical */
-      if (flipXY == 0 || c3x2 == c4x2) { /* Char at angle or Flex height = 0 */
-        PickCoords(FALSE); /* Pick original control points */
-      } else {
-        shrink = FABS((c1x2 - c4x2) / (c3x2 - c4x2)); /* Slope */
-        c1x0 = xshrink(c3x0); c1y0 = c3y0;
-        c1x1 = xshrink(c3x1); c1y1 = c3y1;
-        c2x0 = xshrink(c4x0); c2y0 = c4y0;
-        c2x1 = xshrink(c4x1); c2y1 = c4y1;
-        dtransform(ROUND(c3x2 - c1x2), 0.0, &x, &y); /* Flex height in pixels */
-        dX = FABS((flipXY == -1) ? y : x);
-        PickCoords(dX < dmin); /* If Flex small, pick 'shrunk' control points */
-        if (FABS(x2 - c1x2) > 0.001) {
-          transform(c1x2, c1y2, &x, &y);
-          if (flipXY == -1) {
-            cx = y; cy = x;
-          } else {
-            cx = x; cy = y;
-          }
-          dtransform(ROUND(x2-c1x2), 0.0, &x, &y);
-          dX = (flipXY == -1) ? y : x;
-          if (ROUND(dX) != 0)
-            dX = ROUND(dX);
-          else
-            dX = (dX < 0) ? -1 : 1;
-          erode = PaintType != 2 && erosion >= 0.5;
-          if (erode)
-            cx -= 0.5;
-          ex = cx + dX;
-          ex = CEIL(ex) - ex + FLOOR(ex);
-          if (erode)
-            ex += 0.5;
-          if (flipXY == -1) {
-            itransform(cy, ex, &x, &y);
-          } else {
-            itransform(ex, cy, &x, &y);
-          }
-          eShift = x - x2;
-          x1 += eShift;
-          x2 += eShift;
-          x3 += eShift;
-        }
-      }
-    }
-    if (x2 == x5 || y2 == y5) {
-      lineto(x5, y5);
-    } else {
-      curveto(x0, y0, x1, y1, x2, y2);
-      curveto(x3, y3, x4, y4, x5, y5);
-    }
-  } else { /* ProcessHints is off */
-    PickCoords(FALSE); /* Pick original control points */
-    curveto(x0, y0, x1, y1, x2, y2);
-    curveto(x3, y3, x4, y4, x5, y5);
-  }
-  PSFakePush(epY);
-  PSFakePush(epX);
-}
-/* FlxProc1() = OtherSubrs[1]; Part of Flex            */
-/*   Calling sequence: '0 1 callothersubr'             */
-/*   Saves and clears path, then restores currentpoint */
-static void FlxProc1()
-{
-  struct segment *CurrentPoint;
-  CurrentPoint = Phantom(path);
-  FlxOldPath = path;
-  path = CurrentPoint;
-}
-/* FlxProc2() = OtherSubrs[2]; Part of Flex */
-/*   Calling sequence: '0 2 callothersubr'  */
-/*   Returns currentpoint on stack          */
-static void FlxProc2()
-{
-  struct segment *CurrentPoint;
-  double CurrentX, CurrentY;
-  CurrentPoint = Phantom(path);
-  QueryLoc(CurrentPoint, CharSpace, &CurrentX, &CurrentY);
-  Destroy(CurrentPoint);
-  /* Push CurrentPoint on fake PostScript stack */
-  PSFakePush(CurrentX);
-  PSFakePush(CurrentY);
-}
-/* HintReplace() = OtherSubrs[3]; Hint Replacement            */
-/*   Calling sequence: 'subr# 1 3 callothersubr pop callsubr' */
-/*   Reinitializes stem hint structure                        */
-static void HintReplace()
-{
-  /* Effectively retire the current stems, but keep them around for */
-  /* revhint use in case we are in a stem when we replace hints. */
-  currstartstem = numstems;
-  /* 'subr#' is left on PostScript stack (for 'pop callsubr') */
-}
-/* arg1 ... argn n othersubr# CALLOTHERSUBR - */
-/* Make calls on the PostScript interpreter (or call equivalent C code) */
-/* NOTE: The n arguments have been pushed on the fake PostScript stack */
-static CallOtherSubr(othersubrno)
-  int othersubrno;
-{
-  IfTrace1((FontDebug), "CallOtherSubr %d\n", othersubrno);
-  switch(othersubrno) {
-    case 0: /* OtherSubrs[0]; Main part of Flex */
-      if (PSFakeTop < 16) Error0("CallOtherSubr: PSFakeStack low");
-      ClearPSFakeStack();
-      FlxProc(
-        PSFakeStack[0],  PSFakeStack[1],  PSFakeStack[2],  PSFakeStack[3],
-        PSFakeStack[4],  PSFakeStack[5],  PSFakeStack[6],  PSFakeStack[7],
-        PSFakeStack[8],  PSFakeStack[9],  PSFakeStack[10], PSFakeStack[11],
-        PSFakeStack[12], PSFakeStack[13], PSFakeStack[14], PSFakeStack[15],
-        (int) PSFakeStack[16]
-      );
-      break;
-    case 1: /* OtherSubrs[1]; Part of Flex */
-      FlxProc1();
-      break;
-    case 2: /* OtherSubrs[2]; Part of Flex */
-      FlxProc2();
-      break;
-    case 3: /* OtherSubrs[3]; Hint Replacement */
-      HintReplace();
-      break;
-    default: { /* call OtherSubrs[4] or higher if PostScript is present */
-    }
-  }
-}
-/* |- x y SETCURRENTPOINT |- */
-/* Sets the current point to (x,y) in absolute */
-/* character space coordinates without per- */
-/* forming a CharString MOVETO command */
-static SetCurrentPoint(x, y)
-  double x, y;
-{
-  IfTrace2((FontDebug), "SetCurrentPoint %f %f\n", &x, &y);
-  currx = x;
-  curry = y;
-}
-/* The Type1Char routine for use by PostScript. */
-/************************************************/
-struct xobject *Type1Char(env, S, charstrP, subrsP, osubrsP, bluesP, modeP)
-  char *env;
-  struct XYspace *S;
-  psobj *charstrP;
-  psobj *subrsP;
-  psobj *osubrsP;
-  struct blues_struct *bluesP;  /* FontID's ptr to the blues struct */
-  int *modeP;
-{
-  int Code;
-  path = NULL;
-  errflag = FALSE;
-  /* Make parameters available to all Type1 routines */
-  Environment = env;
-  CharSpace = S; /* used when creating path elements */
-  CharStringP = charstrP;
-  SubrsP = subrsP;
-  OtherSubrsP = osubrsP;
-  ModeP = modeP;
-    blues = bluesP;
-  /* compute the alignment zones */
-  ComputeAlignmentZones();
-  StartDecrypt();
-  ClearStack();
-  ClearPSFakeStack();
-  ClearCallStack();
-  InitStems();
-  currx = curry = 0;
-  escapementX = escapementY = 0;
-  sidebearingX = sidebearingY = 0;
-  accentoffsetX = accentoffsetY = 0;
-  wsoffsetX = wsoffsetY = 0;           /* No shift to preserve whitspace. */
-  wsset = 0;                           /* wsoffsetX,Y haven't been set yet. */
-  for (;;) {
-    if (!DoRead(&Code)) break;
-    Decode(Code);
-    if (errflag) break;
-  }
-  FinitStems();
-  /* Clean up if an error has occurred */
-  if (errflag) {
-    if (path != NULL) {
-      Destroy(path); /* Reclaim storage */
-      path = NULL;   /* Indicate that character could not be built */
-    }
-  }
-  return((struct xobject *) path);
-}