T168_111\appl\Text\Agfa:第68~74

gmfile.h、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* 
 * Copyright (C) 2003 Agfa Monotype Corporation. All rights reserved.
 */

/*----------------*/
/* gmfile.h       */
/*----------------*/
/*------------------------------------------------------------------------*/

#define GRAYMAPFONT_FILE  1


/*--------------------- Graymap file imaging -----------------*/
/*
   Object oriented design and conventions.  Object structure is
   GMFONT.  Member fuctions open and close a graymap disk based font
   and return graymap characters suitable for imaging.
*/

#define ERRgmout_fileopen   5500
#define ERRgmout_too_many   5501
#define ERRgraymap_size     5502
#define ERRgmfile_open      5503
#define ERRchIdnotfound     5504
#define ERRmaxdatasize      5505

#define MAXNUMGRAYMAPS  256
#define MAXDATASIZE 10000

typedef struct
{
    FILE *file;
    SW16 point_size;
    SW16 set_size;
    SL32 xres;
    SL32 yres;
    SW16 gmapcount;
    SW16 numXsubpixels;
    SW16 numYsubpixels;
    SW16 numXphases;
    SW16 numYphases;
    SW16 tablewidth;
    long offset[MAXNUMGRAYMAPS+1];
    SW16  chId[MAXNUMGRAYMAPS];
    UB8 data[MAXDATASIZE];     /* for read in character data */
} GMFONT;

#ifdef LINT_ARGS
EXTERN UW16 open_gm_font(GMFONT*, SB8*);
EXTERN UW16 close_gm_font(GMFONT*);
EXTERN UW16 char_gm_font(GMFONT*, SW16, PPIFBITMAP);
#else
EXTERN UW16 open_gm_font();
EXTERN UW16 close_gm_font();
EXTERN UW16 char_gm_font();
#endif 

 

gray_mgt.h   、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* 
 * Copyright (C) 2003 Agfa Monotype Corporation. All rights reserved.
 */
/* $Header:   I:/BULL/URIP/RTS/GRAY/GRAY_MGT.H_V   1.11   Aug 22 2003 09:07:20   LynchR  $ */
/* $Log:   I:/BULL/URIP/RTS/GRAY/GRAY_MGT.H_V  $
 * 
 *    Rev 1.11   Aug 22 2003 09:07:20   LynchR
 * Updated copyright notice.
 * 
 *    Rev 1.10   23 Feb 1999 17:38:00   GALEJS
 * add reentrancy parms to GRAYPIX/BLACKPIX
 * 
 *    Rev 1.9   18 Dec 1997 17:14:50   GALEJS
 * delete if-0 code
 * 
 *    Rev 1.8   01 May 1997 18:14:00   MIKE
 * Fixed nested comments
 * 
 *    Rev 1.7   16 Apr 1996 18:32:22   MIKE
 * Replace C++ comment syntax
 * 
 *    Rev 1.5   05 Apr 1996 13:28:06   MERRILL
 * add a def
 * 
 *    Rev 1.4   21 Feb 1996 13:09:38   MERRILL
 * remove use of macros
 * 
 *    Rev 1.3   12 Jan 1996 13:12:56   JOE
 * Placed "v>=16" check in non-BorlandC GRAYPIX macro (by jwd).
 * Lined up continuation marks (by jwd).
 * 
 *    Rev 1.2   09 Jan 1996 13:00:44   RICK
 * move gr_image and app_functions/demogr to CGCONFIG.H
 *
 *  RICK: spelling change "gray"
 *  AL:  Separate graymap file and UFST inputs
 *  MIKE: Contains BLACKPIX and GRAYPIX macros.
 *
*/
/* $Date:   Aug 22 2003 09:07:20  $ */

/*
DESCRIPTION
----------------------------------------------------------------------------
  Contains BLACKPIX and GRAYPIX macros [ or function declarations ]
*/

/*------------------------------------------------------------------------*/
/*  History
 *
 *  12-Jan-96  jwd  Placed v>=16 check in non-BorlandC GRAYPIX
 *                  Macro; lined up continuation marks.
 *  06-Dec-95  mby  Original program created.
 */

/* These defines are specific to demogr.c.  */

#if GRAYSCALING

#define BLACKPIXEL   15         /* 15 is all on */
#define PIXELDEPTH   4
#define MAXPIXVAL    0x0F
#define MAXPIXVAL_4  0xF0

#ifdef LINT_ARGS
EXTERN VOID BLACKPIX( FSP SW16 x, SW16 y );
EXTERN VOID GRAYPIX( FSP SW16 x, SW16 y, SW16 v );
#else
EXTERN VOID BLACKPIX();
EXTERN VOID GRAYPIX();
#endif

#endif    /* GRAYSCALING */

graymap.h   、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* 
 * Copyright (C) 2003 Agfa Monotype Corporation. All rights reserved.
 */
/* $Header:   I:/BULL/URIP/RTS/GRAY/GRAYMAP.H_V   1.16   Aug 22 2003 09:07:22   LynchR  $ */
/* $Log:   I:/BULL/URIP/RTS/GRAY/GRAYMAP.H_V  $ 
 * 
 *    Rev 1.16   Aug 22 2003 09:07:22   LynchR
 * Updated copyright notice.
 * 
 *    Rev 1.15   Jun 19 2003 19:14:36   Galejs
 * move GRAYSTATS debug defines into cgconfig.h
 * 
 *    Rev 1.14   Sep 20 2002 19:59:00   Galejs
 * test for multiple includes (part of bug # 76)
 * 
 *    Rev 1.13   12 Jun 1998 13:28:22   GALEJS
 * move fn prototypes to shareinc.h
 * 
 *    Rev 1.12   20 Mar 1998 16:30:56   AL
 * Changed GRAYFILTER.phaseval from SB8 to SW16 to support 128 and 256 gray va
 * 
 *    Rev 1.11   26 Nov 1997 14:03:10   AL
 * Added GRAYFILTER.bsct for smaller, faster code.
 * 
 *    Rev 1.10   01 Aug 1997 10:47:30   MIKE
 * Moved grayscale alignment defs to cgif.h
 * 
 *    Rev 1.9   23 Jun 1997 13:39:54   MIKE
 * Changed #if PTV_OS to #if defined (PTV_OS)
 * 
 *    Rev 1.8   18 Jun 1997 18:46:36   GALEJS
 * pad structure for PTV_OS port (for 32-bit aligned parameters)
 * 
 *    Rev 1.7   14 May 1997 13:24:06   MIKE
 * Removed GS_DIRECT_OUTPUT changes
 * 
 *    Rev 1.5   02 May 1997 13:51:44   MIKE
 * Changes to GRAYFILTER for GS_DIRECT_OUTPUT
 * 
 *    Rev 1.4   02 Apr 1997 10:43:26   AL
 * gs_close() can be called on error returns for cleanup.
 * 
 *    Rev 1.3   25 Mar 1997 09:37:06   AL
 * Gray alignment is independent in x and y
 * 
 *    Rev 1.2   24 Mar 1997 19:14:26   MIKE
 * Added function prototype for grayexit(). GRAYSTATS_1.
 * 
 *    Rev 1.1   22 Jan 1996 10:32:16   AL
 * fixed GA and GH options
 * 
 *    Rev 1.0   21 Dec 1995 15:12:18   MERRILL
 * spelling change gray
 * 
 *    Rev 1.6   14 Dec 1995 13:16:58   MIKE
 * Removed GS1 code; NUMCOLORS to be defined in application layer
 * 
 *    Rev 1.5   14 Nov 1995 11:32:10   MERRILL
 * Portability Issue: ANSI_DEFS for function calls
 * 
 *    Rev 1.4   18 Oct 1995 13:17:22   LISA
 * Fixed header info for PVCS.
 * 
 *    Rev 1.2   10 Oct 1995 11:10:14   LISA
 * Added header information for use with PVCS.
 * 
*/
/* $Date:   Aug 22 2003 09:07:22  $ */

/*----------------*/
/* graymap.h      */
/*----------------*/
/*  History
 *  14-Dec-95  mby  Removed GS1 code; removed definition of NUMCOLORS
 *  20-Mar-97  mby  Added function prototype grayexit().
 *                  Added GRAYSTATS_1 definition (is normally 0).
 *  25-Mar-97  awr  grayfilter.phaseval[] is dynamically allocated
 *  01-May-97  mby  Removed tran_buffer and totphases from GRAYFILTER.
 *                  Added conditional code with GS_DIRECT_OUTPUT.
 *  14-May-97  mby  Removed GS_DIRECT_OUTPUT changes.
 *  18-Jun-97  slg  Structure-padding for PTV_OS port
 *  01-Aug-97  mby  Moved grayscale alignment definitions to cgif.h
 *  20-Mar-98  awr  Changed GRAYFILTER.phaseval from SB8 to SW16 to support
 *                  128 and 256 gray values
 *    12-Jun-98  slg    Moved fn protos to shareinc.h
 */
/*------------------------------------------------------------------------*/


#if GRAYSCALING

#ifndef __GRAYMAP__
#define __GRAYMAP__


/*
    The structure GRAYFILTER and the functions gs_init(), gs_*() represent
    c++ object oriented programming in an ANSI c environment.  GRAYFILTER
    represents a class with the gs_*() functions representing member
    functions of the class.
*/


/* define exactly one:
       GS1     grayscaling version 1
       GS2     grayscaling version 2
*/
#define GS1  0    /* This is _always_ 0  */
#define GS2  1    /* This is _always_ 1  */

#define MAXGRAYWIDTH  256  /* max width of gray map in gray pixels */

#define MAXTRANS 100       /* maximum transitions in a raster */
#define MAXPHPERPIX  8     /* max 8 xphase or yphase */
#define MAXPHPERRAST MAXPHPERPIX*MAXGRAYWIDTH

/* Grayscale alignment constants: for reference only.
 * The actual definitions are in cgif.h
 *  #define GASUB   9
 *  #define GASUPER 10
 *  #define GAHALF  11
 *  #define GAGG    0
 *  #define GAGH    1
 *  #define GAGP    2
 *  #define GAHG    3
 *  #define GAHH    4
 *  #define GAHP    5
 *  #define GAPG    6
 *  #define GAPH    7
 *  #define GAPP    8
*/

typedef struct
{
    /* Input parameters from the FONTCONTEXT */
    SW16 numXsubpixels;  /* Sub-pixel definition */
    SW16 numYsubpixels;
    SW16 alignment;
    SW16 numXphases;     /* Grayscale phasing */ 
    SW16 numYphases;
    /* These elements are set per font in graymap() */
    SW16 maxpixval;    /* max gray value a pixel can have */
    SW16 maxphval;     /* max gray value a phase can have -- drawgrayrow() */
    SW16 bsct;         /* log2(maxphval) */
    SW16 numXbitsperphase;
    SW16 numYbitsperphase;
    SW16 lognumXpix;   /* log2(numsubpixels) */
    SW16 lognumYpix;
    SW16 phasemask;    /* masks in lower bits of transition = bits into x phase -- gs_endsubrast() */
    SW16 phaseshift;   /* shift right to get phase number -- gs_endsubrast() */

    /* initialized in gs_open() */
    LPSW16 phaseval;   /* two dimensional array containing graymap raster */
    SW16 phrow;        /* current subrow in gray row -- gs_endsubrast() */
    SW16 phrastct;     /* y rasters processed in current y phase -- gs_endsubrast() */
    SW16 graywidth;    /* graymap width in gray pixels */
    SW16 graydepth;    /* graymap depth in gray pixels */
    SW16 black_depth;  /* in sub-pixels */

    /* True if gs_open changed xpix etc via setScanConvert()
     * so gs_close() must restore.
     */
    SW16 restoreXpix;
    SW16 restoreYpix;

    /* specific to the graymap; set in gs_open(), used in gs_close() */
    SL32 xorigin;
    SL32 yorigin;

    /* lower left corner of black box within graypixel (0,0)
     * in subpixel bitmap units
     */
    SW16VECTOR startoffset;
  
#if defined (PTV_OS)
    SW16  PTV_OS_AligmentTo32;
#endif
    SW16VECTOR bmdim;  /* to pass into raster() */

    /* Used in graymap generation to feed raster() */
    MEM_HANDLE hnzw;   /* non zero winding buffer handle */
    LPUB8      nzw;
    /*** LPUB8 tran_buffer; ****/

    /* updated by writetran() macro in from nz_set_trans() */
    SW16 transition[MAXTRANS];  /* transition list array */
    SW16 numtrans;     /* number of trans in array */

    SW16 curgrayrow;   /* row number of current gray row being constructed */
    SW16 cursubrow;    /* row number of current gray subpixel row */

    UW16 error;
} GRAYFILTER;


#if GRAYSTATS_1  /* debugging function, called from application */
EXTERN VOID gs_memstats(SL32*, SL32*);
#endif

#endif /* __GRAYMAP__ */
#endif /* GRAYSCALING */

graymap.txt   、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* 
 * Copyright (C) 2005 Monotype Imaging Inc. All rights reserved.
 */

/* $Header:   I:/BULL/URIP/RTS/GRAY/GRAYMAP.C_V   1.49   Jan 03 2005 15:52:52   doolittlej  $ */
/* $Log:   I:/BULL/URIP/RTS/GRAY/GRAYMAP.C_V  $ 
 * 
 *    Rev 1.49   Jan 03 2005 15:52:52   doolittlej
 * TT_SCREENRES-specific changes; bubble up the advancewidth members of IFBITMAP.
 * 
 *    Rev 1.48   Dec 15 2004 14:12:32   galejss
 * make all DBG calls 16-bit-compatible
 * 
 *    Rev 1.47   Nov 02 2004 08:31:24   DugganJ
 * In gs_open() and gs_close(), adjusted the way the nzw buffer
 * size is calculated for consistency.
 * 
 * 
 *    Rev 1.46   Sep 09 2004 17:09:18   galejss
 * allocate temporary storage from new 3rd memory pool
 * 
 *    Rev 1.45   Jun 04 2004 16:08:26   GalejsS
 * remove experimental TT_SCREENRES code 
 * 
 *    Rev 1.44   Apr 27 2004 11:14:48   GalejsS
 * changes to support IFBITSPLIT option; initialization of IFBITMAP structures
 * 
 *    Rev 1.43   Aug 22 2003 09:07:20   LynchR
 * Updated copyright notice.
 * 
 *    Rev 1.42   Aug 13 2003 15:37:58   LynchR
 * Added memory allocation error checking.
 * 
 *    Rev 1.41   Jul 21 2003 18:21:54   Galejs
 * reentrancy / debug fixes
 * 
 *    Rev 1.40   Jun 19 2003 19:13:04   Galejs
 * clean up debug flahs; get rid of asserts; size_t becomes UL32
 * 
 *    Rev 1.39   04 Jun 2001 10:09:46   JOE
 * OpenType changes.
 * 
 *    Rev 1.38   May 03 2001 20:26:42   Galejs
 * data-type cleanup
 * 
 *    Rev 1.37   Oct 05 2000 13:51:12   Al
 * Corrected non ANSI function declaration
 * 
 *    Rev 1.36   Feb 14 2000 18:11:06   galejs
 * in gs_close(), validate non-linear width (TT_SCREENRES)
 * 
 *    Rev 1.35   03 Feb 2000 15:31:20   AL
 * Changed SWP799 to WINDCOMP
 * 
 *    Rev 1.34   Dec 10 1999 15:37:42   galejs
 * DBG stmt needs to be conditional on !SWP799
 * 
 *    Rev 1.33   08 Oct 1999 13:13:42   AL
 * Corrected graymap size calculation when number of subpixels per 
 * 
 *    Rev 1.32   17 Sep 1999 08:33:56   JOE
 * Various changes to nzw buffers and allocations, compatible with
 * new rasterizer (by swp).
 * 
 *    Rev 1.31   Aug 09 1999 18:46:32   galejs
 * include-file changes
 * 
 *    Rev 1.30   29 Jul 1999 17:15:32   JOE
 * Changed DEBUG directive to AGFADEBUG (by ks).
 * 
 *    Rev 1.29   Jun 29 1999 14:50:46   galejs
 * add missing-pixel recovery code (experimental)
 * 
 *    Rev 1.28   17 Jun 1998 16:38:06   GALEJS
 * add arg to render...() calls (for reentrancy)
 * 
 *    Rev 1.27   15 Jun 1998 11:32:48   GALEJS
 * reentrancy parm-passing changes
 * 
 *    Rev 1.26   02 Apr 1998 19:29:46   GALEJS
 * move GLOBAL grayfilter to IF_STATE
 * 
 *    Rev 1.25   31 Mar 1998 18:39:12   GALEJS
 * move MLOCALs into IF_STATE
 * 
 *    Rev 1.24   24 Mar 1998 15:58:36   GALEJS
 * include-file changes
 * 
 *    Rev 1.23   23 Mar 1998 08:58:40   AL
 * Fixed oversight
 * 
 *    Rev 1.22   20 Mar 1998 16:30:20   AL
 * Changed GRAYFILTER.phaseval from SB8 to SW16 to support 128 and 256 gray va
 * 
 *    Rev 1.21   12 Mar 1998 10:10:18   AL
 * Fixed large point size crashing bug (intermitent)
 * 
 *    Rev 1.20   09 Dec 1997 14:39:16   GALEJS
 * remove obsolete references to GASUB mode
 * 
 *    Rev 1.19   26 Nov 1997 14:03:46   AL
 * Added GRAYFILTER.bsct for smaller, faster code and support for 128 &y level
 * 
 *    Rev 1.18   11 Sep 1997 15:56:44   MIKE
 * Fix scrambled graymap bug -- gs_close()
 * 
 *    Rev 1.15   15 Jul 1997 12:33:00   AL
 * Pseudo bold via outlines
 * 
 *    Rev 1.14   23 Jun 1997 13:40:40   MIKE
 * Added #include "nzwind.h"
 * 
 *    Rev 1.13   16 Jun 1997 14:23:18   AL
 * Can have GRAYSCALING without CGBITMAP
 * 
 *    Rev 1.12   14 May 1997 16:59:50   MIKE
 * Removed GRAY_DIRECT_OUTPUT code; roll back approx to rev 1.10
 * 
 *    Rev 1.11   02 May 1997 14:47:56   MIKE
 * gs_endsubrast_lite(); conditional code with GS_DIRECT_OUTPUT
 * 
 *    Rev 1.9   16 Apr 1997 18:41:46   MIKE
 * Patched out "notenoughprecision" errors bec. they croak MT at big sizes
 * 
 *    Rev 1.8   02 Apr 1997 10:47:22   AL
 * Corrected typo in conditional compile
 * 
 *    Rev 1.7   02 Apr 1997 10:42:48   AL
 * gs_close() can be called on error returns for cleanup.
 * 
 *    Rev 1.6   25 Mar 1997 13:10:10   MIKE
 * Allocate graymap work buffer (BITSERVER) dynamically.
 * 
 *    Rev 1.5   25 Mar 1997 09:36:44   AL
 * Gray alignment is independent in x and y
 * 
 *    Rev 1.4   29 Jan 1996 14:07:14   MIKE
 * Removed #define DEBUG from file.
 * 
 *    Rev 1.3   26 Jan 1996 16:31:50   AL
 * GH gray half pix align only in x
 * 
 *    Rev 1.2   22 Jan 1996 10:31:50   AL
 * fixed GA and GH options
 * 
 *    Rev 1.1   17 Jan 1996 11:40:08   MERRILL
 * Try to fix clipping problem...
 * 
 *    Rev 1.0   21 Dec 1995 15:11:22   MERRILL
 * spelling change gray
 * 
 *    Rev 1.10   05 Dec 1995 13:03:54   MERRILL
 * localize size and yphase variables
 * 
 *    Rev 1.9   01 Dec 1995 16:41:14   AL
 * Fixed streaks again
 * 
 *    Rev 1.8   17 Nov 1995 16:00:28   AL
 * Fixed streaks in gramaps
 * 
 *    Rev 1.7   14 Nov 1995 12:16:08   MERRILL
 * Portibility Issue: ANSI_DEF for function calls
 * 
 *    Rev 1.6   18 Oct 1995 15:16:02   AL
 * corrected error recovery
 * 
*/
/* $Date:   Jan 03 2005 15:52:52  $ */

/*--------------*/
/* graymap.c    */
/*--------------*/
/*  History
 *
 *  25-Mar-97  awr  Gray alignment is independent in x and y.
 *  25-Mar-97  mby  Made changes to allocate dynamically memory used in
 *                  constructing the graymaps. Initially we alloc a default amount,
 *                  but if memory runs out, use gs_realloc() to get more.
 *                  Changed BITSERVER struc. Added grayexit().
 *  16-Apr-97  mby  Patched out all occurrences of ERRnotenoughprecision
 *                  (see "MBY" comments). These errors prevent rasterizing
 *                  MicroType data at large sizes, and there is apparently no
 *                  harm done by removing them ?!
 *  01-May-97  mby  Added conditional GS_DIRECT_OUTPUT (set in graymap.h)
 *                  See gs_endsubrast_lite(), gs_direct_output, gs_Xphase.
 *  14-May-97  mby  Removed GS_DIRECT_OUTPUT code.
 *  16-Jun-97  awr  Moved render() call here from raster.c
 *  23-Jun-97  mby  Added #include "nzwind.h".
 *  15-Jul-97  awr  Pseudo bold via outlines.
 *  11-Sep-97  mby  Fix problem of scrambled graymaps: in gs_close() code to
 *                  reduce size of bs.bytestream buffer was in wrong place.
 *  09-Dec-97  slg  Remove references to obsolete alignment mode GASUB
 *  12-Mar-98  awr  Changed name of BITERVER bs to bbbb to get around bug in
 *                  Microsoft Visual c++. Fixed crashing problem in
 *                  gs_realloc().
 *  20-Mar-98  awr  Changed GRAYFILTER.phaseval from SB8 to SW16 to support
 *                  128 and 256 gray values
 *    31-Mar-98  slg    "BITSERVE bbbb" becomes "BITSERVE_GM if_state.bs_gm";
 *                    move a few other MLOCALs into IF_STATE.
 *    02-Apr-98  slg    Move GLOBAL grayfilter into IF_STATE.
 *    29-Jun-99  slg    Put Steven's missing-pixel-recovery code into gs_endsubrast():
 *                    experimental, so only enabled if TT_SCREENRES set in cgconfig.h.
 *                    Also - passback of nonlinear pixelwidth if TT_SCREENRES set;
 *                    fix some compiler warnings (signed/unsigned compares).
 *  28-July-99 ks    Changed DEBUG compiler directive to AGFADEBUG. 
 *    July-99  swp  various changes to nzw buffers and allocations, compatible
 *                    with new rasterizer. enabled if SWP799 defined
 *  08-Oct-99  awr  Corrected graymap size calculation when number of subpixels
 *                  per phase is > 1.
 *  03-Feb-00  awr  Changed SWP799 to WINDCOMP
 *    14-Feb-00  slg    Move TT_SCREENRES validation lower-down in code: check here
 *                    rather than in application for Phased grayscale alignment
 *                    (which invalidates "non-linear width" value).  
 *  05-Oct-00  awr  Corrected non ANSI function declaration
 *  23-May-01  jfd  OpenType changes:
 *                  In graymap(), point to correct bucket.
*/


#include "cgconfig.h"

#if GRAYSCALING         /* Conditionally compile entire module */

#include <stdio.h>
#include <string.h>
#include <limits.h>

#include "ufstport.h"
#include "dbg_ufst.h"

#include "shareinc.h"

#include "mixmodel.h"

#if GRAYSTATS
    extern UL32 black_ct, white_ct, gray_ct;
    extern UL32 char_ct, depth_ct;
#endif


#ifdef LINT_ARGS
MLOCAL UW16 gs_open(FSP GRAYFILTER *gf, PIFBITMAP bm);
MLOCAL UW16 gs_close(FSP GRAYFILTER *gf, PIFBITMAP bm, PHIFBITMAP phbm);
MLOCAL VOID drawgrayrow( FSP GRAYFILTER* );
MLOCAL SL32 checkparam ( SW16 v );
#else
MLOCAL UW16 gs_open();
MLOCAL UW16 gs_close();
MLOCAL VOID drawgrayrow();
MLOCAL SL32 checkparam ();
#endif

/*=====================================================================*/
/*                     B I T S E R V E R                               */
/*  Bitserver.  This object represents a stream of bits used in the variable
 *  length messages that make up a GS2 graymap data structure.  Calls are
 *  made to the bitserver to send the messages [these calls are by UFST]
 *  as well as to receive the messages; calls made by the imaging
 *  subsystem.
 *  
 */

#define MAXBYTESTREAM   1000

CONST static UINTG AllocMax = (UINT_MAX & ~0xFF);  /* don't try to alloc bigger than this,
                                              * possible integer overflow on 16-bit CPU */
#ifdef LINT_ARGS
MLOCAL VOID initbits  (FSP0);
MLOCAL VOID flushbits (FSP0);
MLOCAL VOID flushbyte (FSP0);
#else
MLOCAL VOID initbits  ();
MLOCAL VOID flushbits ();
MLOCAL VOID flushbyte ();
#endif


/* static void putbits    (UB8 v, SL32 n); */

/* put the low n bits from UB8 v at the end of our bit stream */
#define putbits(v, n)                  \
{                                      \
    if_state.bs_gm.bitbuf |= (v) << if_state.bs_gm.bitct;      \
    if_state.bs_gm.bitct += (n);                   \
    if(if_state.bs_gm.bitct>= 8)                   \
        flushbyte(FSA0);                   \
}

/*=====================================================================*/
/*                     B I T S E R V E R                               */
/*=====================================================================*/
/*                     Internal Functions                              */
/*=====================================================================*/

#define GS_REALLOC_NOCOPY    0
#define GS_REALLOC_COPYBUF   1

#ifdef LINT_ARGS
MLOCAL VOID clearphvals(FSP GRAYFILTER *gf);
MLOCAL SW16 floorlog2(SW16 v);
MLOCAL VOID setSCpixval( PCOORD_DATA pcoord, SW16 lx );
MLOCAL VOID gs_realloc( FSP GRAYFILTER*, UINTG, INTG );

#else
MLOCAL VOID clearphvals();
MLOCAL SW16 floorlog2();
MLOCAL VOID setSCpixval();
MLOCAL VOID gs_realloc();
#endif 


#ifdef LINT_ARGS
MLOCAL SW16 floor(SW16 v, SW16 div);
MLOCAL SW16 ceiling(SW16 v, SW16 div);
MLOCAL SL32 round_div(SL32 v, SL32 div);
#else
MLOCAL SW16 floor();
MLOCAL SW16 ceiling();
MLOCAL SL32 round_div();
#endif

/*-----------------------*/
/*    clearphvals()      */
/*-----------------------*/
/* Clear the phase value array in preparation for creating a new gray
 * raster row.
 */

#if defined (ANSI_DEFS)
MLOCAL VOID clearphvals(FSP GRAYFILTER *gf)
#else
MLOCAL VOID clearphvals(gf)
GRAYFILTER *gf;
#endif
{
    SW16 ct, i;
    DBG("clearphvals()\n");

    ct = gf->numYphases * gf->numXphases * (gf->graywidth+1);
    for ( i=0; i<ct; i++ )
        gf->phaseval [ i ] = 0;
}

/*  Return the log base 2 of v which must be positive power of two */
/*-----------------------*/
/*      floorlog2()      */
/*-----------------------*/
#if defined (ANSI_DEFS)
MLOCAL SW16 floorlog2(SW16 v)
#else
MLOCAL SW16 floorlog2(v)
SW16 v;
#endif
{
    SW16 c;
    c = 0;
    while(v>1)
    {
        c++;
        v>>=1;
    }
    return c;
}

/*-----------------------*/
/*      setSCpixval()    */
/*-----------------------*/
/*  Computes and sets the pixel size related variables that raster
    uses to scan convert the character outline.  The function argument lx
    is the log base 2 of the pixel size.  Eg. lx = 6 if pixel_size = 64
*/
#if defined (ANSI_DEFS)
MLOCAL VOID setSCpixval( PCOORD_DATA pcoord, SW16 lx )
#else
MLOCAL VOID setSCpixval( pcoord, lx )
PCOORD_DATA pcoord;
SW16 lx;
#endif
{
    pcoord->grid_shift = lx;
    pcoord->pixel_size = 1<<pcoord->grid_shift;
    pcoord->half_pixel = pcoord->pixel_size >> 1;
    pcoord->grid_align =  ~((INTR)pcoord->pixel_size -(INTR)1);
}

/*----------------------------------------------------------------------*/
/* The following are three division functions that round the returned   */
/* quotient in three different ways: to the left, to the right, and     */
/* round to closest.                                                    */

/*-----------------------*/
/*       floor()         */
/*-----------------------*/
/* Rounds to left */
#if defined (ANSI_DEFS)
MLOCAL SW16 floor(SW16 v, SW16 div)
#else
MLOCAL SW16 floor(v, div)
SW16 v;
SW16 div;
#endif
{
    if(v<0)
        return -((-v-1)/div + 1);
    else
        return v/div;
}

/*-----------------------*/
/*       ceiling()       */
/*-----------------------*/
/* Rounds to right */
#if defined (ANSI_DEFS)
MLOCAL SW16 ceiling(SW16 v, SW16 div)
#else
MLOCAL SW16 ceiling(v, div)
SW16 v;
SW16 div;
#endif
{
    if(v<0)
        return -((-v)/div);
    else
        return (v-1)/div + 1;   /* Ceiling */
}

/*-----------------------*/
/*      round_div        */
/*-----------------------*/
/* Rounds to closest */
#if defined (ANSI_DEFS)
MLOCAL SL32 round_div(SL32 v, SL32 div)
#else
MLOCAL SL32 round_div(v, div)
SL32 v;
SL32 div;
#endif
{
    if(v<0L)
        return -((-v+(div>>1))/div);
    else
        return (v+(div>>1))/div;
}


/*=====================================================================*/
/*                     Internal Functions                              */
/*=====================================================================*/


/* ------------------------------ gs_realloc ------------------------------
 *
 * Description: Reallocates new memory buffer; deallocs old one.
 *              Optionally copies old buf to new.
 * Parameters:  size - size of new buffer
 *              makeCopy - GS_REALLOC_COPYBUF: copy old buffer before deleting.
 *                         GS_REALLOC_NOCOPY: do not copy old buffer.
 * Errors:      ERRgray_BytestreamNoMem if cannot allocate new buffer or
 *              if makeCopy == COPYBUF and new buffer is too small.
 * Called By:   gs_close(), flushbits(), flushbyte()/putbits().
 */
#if defined (ANSI_DEFS)
MLOCAL VOID gs_realloc( FSP GRAYFILTER *gf, UINTG size, INTG makeCopy )
#else
MLOCAL VOID gs_realloc( gf, size, makeCopy )
  GRAYFILTER *gf;
  UINTG size;
  INTG  makeCopy;
#endif
{
    MEM_HANDLE saveh = if_state.bs_gm.bytestream;

    /* Don't bother if an error has occured. This function could have
       failed earlier but we keep going. if_state.bs_gm.bytestream is 0 then
       causing problems with the MEMCPY() below if the CHARalloc()
       succeeds this time. 12-Mar98 awr */

    if (gf->error)
        return;
    if (!makeCopy)
        TEMPCHARfree(FSA saveh);
    else if (size < if_state.bs_gm.maxbytestream)
    {
        gf->error = ERRgray_BytestreamNoMem;
        return;
    }

    if ((if_state.bs_gm.bytestream = TEMPCHARalloc(FSA (SL32)size)) == NIL_MH)
    {
        if_state.bs_gm.maxbytestream = 0;
        if_state.bs_gm.numused = 0;
        gf->error = ERRgray_BytestreamNoMem;
        return;
    }

    if (makeCopy)
    {
        LPUB8 psrcbs = (LPUB8)MEMptr(saveh);
        if_state.bs_gm.p_bytestream = (LPUB8)MEMptr(if_state.bs_gm.bytestream);
        MEMCPY(if_state.bs_gm.p_bytestream, psrcbs, (UL32)if_state.bs_gm.maxbytestream);
        TEMPCHARfree(FSA saveh);
    }
    if_state.bs_gm.maxbytestream = size;
}


/*-----------------------*/
/*     gs_close()        */
/*-----------------------*/
/* This function is designed to be called not only at the normal termination
 * of the build gray character process, but also to clean up during
 * abnormal terminations (like out of memory, or math limits).  This
 * places restrictions on the code: it must ALL be executed, no early returns
 * in the function; otherwise the code following the return doesn't get
 * its shot at cleaning up.
 */
#if defined (ANSI_DEFS)
MLOCAL UW16 gs_close(FSP GRAYFILTER *gf, PIFBITMAP bm0, PHIFBITMAP phbm)
#else
MLOCAL UW16 gs_close(gf, bm0, phbm)
GRAYFILTER *gf;
PIFBITMAP bm0;
PHIFBITMAP phbm;
#endif
{
    HIFBITMAP  hbm;    /* handle of constructed graymap is returned here */
    PIFBITMAP  pbm;
#if IFBITSPLIT
    MEM_HANDLE bmdatahandle=0;
    UL32 *bmdataptr=0;
#endif

    DBG("gs_close()\n");

    /* Step: Free the memory for transition arrays and the gray raster
     *       line buffer phval[].  Check for over run of phval[] if
     *       the debugging define CHECK_MEMORY_GRAY is true
     */
    if ( gf->hnzw != NIL_MH )
    {
#if CHECK_MEMORY_GRAY
#ifdef WINDCOMP
        SL32 nzw_size = 0;
#else
        SL32 nzw_size = (SL32)if_state.ras.tran_run_ct * (
                           (SL32)((sizeof(NZ_NODE) + MEM_ALIGN) & ~MEM_ALIGN)
                         + (SL32)(gf->black_depth + 1) * (SL32)(sizeof(NZCOUNTER))
                                                         );
#endif /* WINDCOMP */
        
        SL32 phv_count = gf->numXphases * gf->numYphases
                                                      * (gf->graywidth+1);
        gf->nzw = (LPUB8)MEMptr(gf->hnzw);
        gf-> phaseval = (LPSW16) ( gf->nzw + (UL32)nzw_size );
        if (*(gf->phaseval+phv_count ) != 'a'     ||
            *(gf->phaseval+phv_count + 1 ) != 'b' ||
            *(gf->phaseval+phv_count + 2 ) != 'c' ||
            *(gf->phaseval+phv_count + 3 ) != 'd')
            printf("graymap.c gs_close() phval[] over run\n");
#endif  /* CHECK_MEMORY_GRAY */

        TEMPCHARfree(FSA gf->hnzw);
        gf->hnzw = NIL_MH;
    }

    /* Step: Restore the number of fractional subpixels to their original
     *       value before gs_open() reduced them
     */
    if ( gf->restoreXpix )
        setSCpixval ( &if_state.x, (SW16)(log_xpix + gf->lognumXpix) );
    if ( gf->restoreYpix )
        setSCpixval ( &if_state.y, (SW16)(log_ypix + gf->lognumYpix) );

    if_state.bs_gm.p_bytestream = (LPUB8)MEMptr(if_state.bs_gm.bytestream);  /* setup for this function */

    /* All clean up code must be above this point. The final step is to
     * build the final graymap structure. From here forward, error returns
     * can again take place.
     */

    if(gf->error)
        return gf->error;

    flushbits(FSA0);  /* flush any remaining data */

    if(if_state.grayfilter.error)    /* Added error handling */ /* rjl 8/4/2003 - */
        return if_state.grayfilter.error;

    /* Step: allocate build the final graymap in an IFBITMAP
     *       like structure.
     */

    /* Compute size of final graymap. Allocate memory in UFST cache as part
     * of an IFBITMAP structure. Copy the compressed graymap data from local
     * buffer into the IFBITMAP->bm buffer.
     */

    DBG2("final graymap size: header=%d, data=%ld\n", BMHEADERSIZE, (SL32)if_state.bs_gm.numused);

#if IFBITSPLIT
    /* allocate the space for the actual graymap data (bits) */
    bmdatahandle = CHARalloc(FSA if_state.bs_gm.numused);
    if (bmdatahandle == NIL_MH)
        return ERR_bm_buff;

    /* allocate the IFBITMAP structure */
    hbm = (HIFBITMAP)CHARalloc(FSA (SL32)BMHEADERSIZE);
    if (hbm == NIL_MH)
    {
        CHARfree(FSA bmdatahandle);
        return ERR_bm_buff;
    }

    pbm = (PIFBITMAP)MEMptr(hbm);
    MEMSET(pbm, 0, BMHEADERSIZE);
    bmdataptr = (UL32 *)MEMptr(bmdatahandle);
    pbm->bm = bmdataptr;        /* set pointer/handle to data in IFBITMAP structure */
    pbm->datahandle = bmdatahandle;
#else
    hbm = CHARalloc(FSA (SL32)(BMHEADERSIZE + if_state.bs_gm.numused));  /* allocate memory */
    if(hbm == NIL_MH)
        return ERR_bm_buff;
    pbm = (PIFBITMAP)MEMptr(hbm);
    MEMSET(pbm, 0, BMHEADERSIZE);
#endif

    if_state.graysize[if_state.gs_count++] = if_state.bs_gm.numused;
    pbm->width = (SW16)if_state.bs_gm.numused;  /* construct partial header */
    pbm->depth = 1;
    pbm->size = if_state.bs_gm.numused;

    /*  Copy the compressed graymap data */
    {
        UB8 *p, *q;
        p = (UB8*)&pbm->bm[0];
        q = if_state.bs_gm.p_bytestream;
        while(if_state.bs_gm.numused--)
            *p++ = *q++;
    }

    pbm->left_indent = 0;
    pbm->top_indent = 0;
    pbm->black_width = gf->graywidth;
    pbm->black_depth = gf->graydepth;
    pbm->xorigin = gf->xorigin;       /*  (1/16th pixel)  */
    pbm->yorigin = gf->yorigin;       /*  (1/16th pixel)  */
    pbm->escapement = bm0->escapement;
    pbm->du_emx = bm0->du_emx;
    pbm->du_emy = bm0->du_emy;
#if TT_SCREENRES
    /* don't pass the "non-linear width" value up if using Phased alignment 
     (as this width was based on the fictitious larger bitmap used to create
     the Phased-mode graymap.) */
    pbm->pixelWidth = bm0->pixelWidth; 
    if (pbm->pixelWidth)
    {
        SW16 align = gf->alignment;
        if (align == GAPP || 
            align == GAPG || align == GAPH || 
            align == GAGP || align == GAHP)
            pbm->pixelWidth = 0;
    }

    pbm->advanceWidth.x = bm0->advanceWidth.x;
    pbm->advanceWidth.y = bm0->advanceWidth.y;

#endif

   /* Code to realloc if_state.bs_gm.bytestream buffer if the old buffer is too big.
    * This is so we don't permanently tie up a big chunk of cache pool
    * memory. The method is to store the sizes of the last several graymap
    * characters. If the max size is less than half the value of
    * maxbytestream, then reduce the buffer size, call gs_realloc().
    */
    if (if_state.gs_count == MAXGSCOUNT) {
        UL32 maxsz;
        INTG ii;
        if_state.gs_count = 0;
        for (maxsz=0, ii=0; ii<MAXGSCOUNT; ii++) {
            if (if_state.graysize[ii] > maxsz)
                maxsz = if_state.graysize[ii];
        }
        maxsz <<= 1;
        if (maxsz < if_state.bs_gm.maxbytestream  &&  maxsz > MAXBYTESTREAM)
        {
            /* _reduce_ buffer size */
            gs_realloc(FSA gf, (UINTG)maxsz, GS_REALLOC_NOCOPY);
            if(gf->error)
                return gf->error;
        }
    }

    DBG1("notmru  %d\n", pbm->notmru);        /* set to 0 if recently made most recently used */
    DBG1("hiffont  %lx\n", pbm->hiffont);       /* Font handle of the owner of this IFBITMAP    */
    DBG1("index  %ld\n", pbm->index);         /* index to IFBITMAP in above FONT's table      */

    DBG1("width  %d\n", pbm->width);         /* bit map width (bytes)                 */
    DBG1("depth  %d\n", pbm->depth);         /*  "   "  depth (pixels)                */
    DBG1("left_indent  %d\n", pbm->left_indent);
    DBG1("top_indent  %d\n", pbm->top_indent);
    DBG1("black_width  %d\n", pbm->black_width);
    DBG1("black_depth  %d\n", pbm->black_depth);
    DBG1("xorigin  %ld\n", pbm->xorigin);       /*  (1/16th pixel)  */
    DBG1("yorigin  %ld\n", pbm->yorigin);       /*  (1/16th pixel)  */
    DBG1("escapement  %d\n", pbm->escapement);
    DBG1("du_emx  %d\n", pbm->du_emx);
    DBG1("du_emy  %d\n", pbm->du_emy);
    DBG1("size  %ld\n", pbm->size);          /* Size in bytes of entire structure */

    /* return the graymap handle */
    *phbm = hbm;
    return SUCCESS;
}  /* gs_close() */

/*-----------------------*/
/*       gs_open()       */
/*-----------------------*/
/* Called By: graymap()  */

#if defined (ANSI_DEFS)
MLOCAL UW16 gs_open(FSP GRAYFILTER *gf, PIFBITMAP bm)
#else
MLOCAL UW16 gs_open(gf, bm)
   GRAYFILTER *gf;
   PIFBITMAP bm;
#endif
{
    DBG("\n_______________________\n");
    DBG("gs_open()\n");

    gf->restoreXpix = gf->restoreYpix = 0;

    {
    /* First set x alignement, then set y alignment ----------------------*/

        if ( gf->alignment == GAPG ||           /* Are we PHASED in x ? */
               gf->alignment == GAPH ||
                 gf->alignment == GAPP )
        { /* x alignment is PHASED */
            SW16 orgx;
            SL32 xorigin;
            SW16 black_width;
            SW16 leftsub, rightsub;
            SW16 leftgray, rightgray;
            SW16 numXsubpixels;

            /* Copy input parameters */
            black_width   = bm->black_width;
            xorigin       = bm->xorigin;
            numXsubpixels = gf->numXsubpixels;

            DBG2("black_width = %d  xorigin = %ld\n", bm->black_width, bm->xorigin);

            /* compute the subpixel containing the origin
             * orgx and orgy are in subpixel bitmap coordinates.
             */
            orgx = (SW16)(( (SL32)(-xorigin)) >> 4);

            /* Translate the subpixel boundaries so origin pixel is at (0,0) */
            leftsub   = -orgx;    /* 0 - orgx */
            rightsub  = black_width - orgx;

            /* Compute graypixel boundaries.  Subpixel origin is at lower left
             *  of graypixel origin.  Allow extra space on top and to right
             *  for phasing.
             */
            leftgray   = floor(leftsub, numXsubpixels);
            rightgray  = ceiling((SW16)(rightsub + (gf->numXphases-1)*gf->numXbitsperphase),
                                                          numXsubpixels);

            /*  Compute graymap width */
            gf->graywidth = rightgray - leftgray;
            gf->startoffset.x = leftsub   - leftgray   * numXsubpixels;

            /*  Compute xorigin for the final graymap,
             *  first in 16th subpixels
             */
            gf->xorigin = 16*(leftgray*numXsubpixels - leftsub) + xorigin;
            /* convert 1/16th subpixels into 1/16 graypixels */
            gf->xorigin = round_div(gf->xorigin, (SL32)numXsubpixels);

            gf->bmdim.x = bm->width;    /* ... use the byte width */
        }
        else /* assume x alignment is GRID or HALF-GRID */
        {
            SW16 lx;   /* logs of small pix */
            
            {
              SW16 xpix_small, half_xpix_small;

              INTRVECTOR xlate;

              /* compute pixel sizes for subpixels    */
              /* log_xpix = if_state.x.grid_shift     */
              /* lognumXpix = log2(fc->numXsubpixels) */
              lx = log_xpix - gf->lognumXpix;
#if 0                                           /* MBY */
              if ( lx<1 )
                  return ERRnotenoughprecision;
#endif

              xpix_small = 1<<lx;
              half_xpix_small = xpix_small>>1;

              DBG1 ( "xpix       %d    \n", xpix);
              DBG1 ( "xpix_small %d    \n", xpix_small );
              DBG1 ( "xmin       %ld   \n", if_state.cs.xmin );
              DBG1 ( "xmax       %ld   \n", if_state.cs.xmax );
              if(gf->alignment == GAGG || gf->alignment == GAGH ||
                                                 gf->alignment == GAGP )
                  xlate.x = -((INTR)(if_state.cs.xmin + half_xpix_small)
                               & if_state.x.grid_align);
              else if(gf->alignment == GAHG || gf->alignment == GAHH ||
                                                 gf->alignment == GAHP )
                  xlate.x = half_xpix
                             - ((INTR)(if_state.cs.xmin
                                        + half_xpix + half_xpix_small)
                                & if_state.x.grid_align);
              else
                  return ERRgray_parm_not_supported;

              /* Compute width of graymap in gray pixels */
              gf->graywidth = (SW16)XCEILING(if_state.cs.xmax + xlate.x);
              /* Compute new x origin.
                     old baseline = 16*(black_depth-yorigin)
                     new baseline = old baseline + translate diff
                     translate diff = XFLOOR(16*(new xlate - old xlate))
                     new yorigin = 16*graydepth - new baseline

                     old comp x = -xorigin
                     new comp x = old comp x + translate diff
                     translate diff = YFLOOR(16*(new xlate - old xlate))
                     new xorigin = - new comp x
               */  

              gf->xorigin = bm->xorigin - XFLOOR(16*(xlate.x - if_state.xlate.x));
              if_state.xlate.x = xlate.x;
            }

            /* reduce the number of fractional subpixels so that the scan
               converter will generate subpixel transitions.
             */
            setSCpixval ( &if_state.x, lx );
            gf->restoreXpix = 1;  /* flag for gs_close() */

            gf->startoffset.x = 0;   /* it is all in xlate.x */
            /* Raster does not use bmdim.x for grayscaling, only for bitmaps. */
            gf->bmdim.x = 0;   /* just to give it a value */
        }
        /* End of X setup -------------------------------------*/

        /* Next do y setup ------------------------------------*/
        if(gf->alignment == GAGP ||    /* are we PHASED in y ? */
             gf->alignment == GAHP ||
               gf->alignment == GAPP )
        { /* y alignment is PHASED */
            SW16 orgy;
            SL32 yorigin;
            SW16 black_depth;
            SW16 topsub, bottomsub;
            SW16 topgray, bottomgray;
            SW16 numYsubpixels;

            /* This is currently a limitation when we have y-phasing. There
             * are two fixed length arrays in imagegr.c.
             */
            if(gf->graywidth >= MAXGRAYWIDTH)
                return ERRgraymaptoobig;

            /* Copy input parameters */
            black_depth   = bm->black_depth;
            yorigin       = bm->yorigin;
            numYsubpixels = gf->numYsubpixels;

            DBG2("black_depth = %d  yorigin = %ld\n", bm->black_depth, bm->yorigin);

            gf->black_depth = black_depth;

            /* compute the subpixel containing the origin
             * orgx and orgy are in subpixel bitmap coordinates.
             */
            orgy = (SW16)(((((SL32)black_depth)<<4) - yorigin) >> 4);

            /* Translate the subpixel boundaries so origin pixel is at (0,0) */
            bottomsub = -orgy;    /* 0 - orgy */
            topsub    = black_depth - orgy;

            /* Compute graypixel boundaries.  Subpixel origin is at lower left
             *  of graypixel origin.  Allow extra space on top and to right
             *  for phasing.
             */
            bottomgray = floor(bottomsub, numYsubpixels);
            topgray    = ceiling((SW16)(topsub + (gf->numYphases-1)*gf->numYbitsperphase),
                                                          numYsubpixels);

            /*  Compute graymap width and depth */
            gf->graydepth = topgray - bottomgray;
            gf->startoffset.y = bottomsub - bottomgray * numYsubpixels;

            /*  Compute yorigin for the final graymap,
             *  first in 16th subpixels
             */
            gf->yorigin = 16*(topgray*numYsubpixels - topsub) + yorigin;
            /* convert 1/16th subpixels into 1/16 graypixels */
            gf->yorigin = round_div(gf->yorigin, (SL32)numYsubpixels);

            gf->bmdim.y = bm->depth;    /* depth from the bitmap header...   */
        }
        else /* assume y alignment is GRID or HALF-GRID */
        {
            SW16 ly;   /* log of small pix */
            {
              SW16 ypix_small, half_ypix_small;

              INTRVECTOR xlate;

              xlate.x = xlate.y = 0;

              /* compute pixel sizes for subpixels    */
              /* log_ypix = if_state.y.grid_shift     */
              /* lognumYpix = log2(fc->numYsubpixels) */
              ly = log_ypix - gf->lognumYpix;
#if 0                                           /* MBY */
              if ( ly < 1 )
                  return ERRnotenoughprecision;
#endif

              ypix_small = 1<<ly;
              half_ypix_small = ypix_small>>1;

              DBG1 ("ypix       %d \n", ypix);
              DBG1 ("ypix_small %d \n", ypix_small);
              DBG1 ("ymin       %ld\n", if_state.cs.ymin);
              DBG1 ("ymax       %ld\n", if_state.cs.ymax);
              if(gf->alignment == GAGG || gf->alignment == GAHG ||
                                                 gf->alignment == GAPG )
                  xlate.y = -((INTR)(if_state.cs.ymin + half_ypix_small-1)
                               & if_state.y.grid_align);
              else if(gf->alignment == GAGH || gf->alignment == GAHH ||
                                                 gf->alignment == GAPH )
                  xlate.y = half_ypix
                             - ((INTR)(if_state.cs.ymin
                                        + half_ypix + half_ypix_small - 1)
                                & if_state.y.grid_align);

/**               xlate.y = -((INTR)(if_state.cs.ymin + half_ypix_small-1)
 **                                            & if_state.y.grid_align);
 **/
              else
                  return ERRgray_parm_not_supported;

              /* Compute width and depth of graymap in gray pixels */
              gf->graydepth = (SW16)YCEILING(if_state.cs.ymax
                                   + xlate.y + half_ypix_small);
              /* Compute new x and y origin.
                     old baseline = 16*(black_depth-yorigin)
                     new baseline = old baseline + translate diff
                     translate diff = XFLOOR(16*(new xlate - old xlate))
                     new yorigin = 16*graydepth - new baseline

                     old comp x = -xorigin
                     new comp x = old comp x + translate diff
                     translate diff = YFLOOR(16*(new xlate - old xlate))
                     new xorigin = - new comp x
               */

              gf->yorigin = 16*gf->graydepth -
                              ((16 * bm->black_depth - bm->yorigin) +  /* old baseline */
                                 YFLOOR(16*(xlate.y - if_state.xlate.y)));
              if_state.xlate.y = xlate.y;

#if INTR_SIZE == 16
              DBG2("  xlate.x,xlate.y = (%d, %d)\n", xlate.x, xlate.y);
              DBG2("  if_state.xlate  = (%d, %d)\n", if_state.xlate.x, if_state.xlate.y);
#else
              DBG2("  xlate.x,xlate.y = (%ld, %ld)\n", xlate.x, xlate.y);
              DBG2("  if_state.xlate  = (%ld, %ld)\n", if_state.xlate.x, if_state.xlate.y);
#endif
              DBG1("   if_state.right_shift  %ld\n", if_state.right_shift);
            } /* end of data block */

            /* reduce the number of fractional subpixels so that the scan
               converter will generate subpixel transitions.
             */
            setSCpixval ( &if_state.y, ly );
            gf->restoreYpix = 1;  /* flag for gs_close() */

            gf->startoffset.y = (SW16)YCEILING(if_state.cs.ymin +
                                         if_state.xlate.y + half_ypix) - 1;

            /* Compute bmdim to be passed into raster().  Raster uses this to
             * move pointers from one end of an nz tran run to the other.
             * It does not use bmdim.x for grayscaling, only for bitmaps.
             * bmdim.y should be the number of subpixel rows we will process.
             * There could be blank rows at the bottom so this may be larger
             * the black depth.
             */
            gf->bmdim.y = (SW16)YFLOOR(if_state.cs.ymax
                                        + if_state.xlate.y + half_ypix)
                                 - gf->startoffset.y + 1;
            gf->black_depth = gf->bmdim.y;  /* remove black_depth */

            DBG2("  bmdim.x,y = (%d, %d)\n", gf->bmdim.x, gf->bmdim.y);
        } /* else assume GRID or HALF */
          /* End of y processing, new alignment code */
    } /* end new code */
    /* End of set up for gs_endsubrast()  */
/* --------------------New code above -----------------------------*/


    DBG2("graywidth graydepth    %d %d\n", gf->graywidth, gf->graydepth);
    DBG2("xorigin = %ld  yorigin = %ld\n", gf->xorigin, gf->yorigin );
    DBG2("startoffset %d %d\n", gf->startoffset.x, gf->startoffset.y);


    gf->curgrayrow = 0;
    gf->cursubrow  = 0;

    /* Allocate Non zero winding buffer and phase value array */
    gf->hnzw = NIL_MH;   /* for error clean up */

    /* if_state.non_z_wind is ALWAYS on for grayscale (see comp_pix.c) */
    {
        SL32 nzw_size, phv_size, phv_count;
#ifdef WINDCOMP
        nzw_size = 0;
#else
        nzw_size = (SL32)if_state.ras.tran_run_ct * (
                           (SL32)((sizeof(NZ_NODE) + MEM_ALIGN) & ~MEM_ALIGN)
                         + (SL32)(gf->black_depth + 1) * (SL32)(sizeof(NZCOUNTER))
                                                         );
#endif /* WINDCOMP */
        phv_count = gf->numXphases * gf->numYphases * (gf->graywidth+1);
        phv_size  =  sizeof(SW16) * phv_count;

#if !defined (WINDCOMP)
        DBG4("tran_run_ct %d  nzw_size %ld  phv_count %ld phv_size %ld\n",
                      if_state.ras.tran_run_ct, nzw_size, phv_count, phv_size);
#endif

#if CHECK_MEMORY_GRAY
        gf->hnzw = TEMPCHARalloc ( FSA nzw_size + phv_size + 4*sizeof(SW16) );
#else
        gf->hnzw = TEMPCHARalloc ( FSA nzw_size + phv_size );
#endif
        if ( gf->hnzw == NIL_MH )
            return ERR_bm_buff;
        gf->nzw = (LPUB8)MEMptr(gf->hnzw);
        gf-> phaseval = (LPSW16) ( gf->nzw + (UL32)nzw_size );
#if CHECK_MEMORY_GRAY
        *(gf->phaseval+phv_count ) = 'a';
        *(gf->phaseval+phv_count + 1 ) = 'b';
        *(gf->phaseval+phv_count + 2 ) = 'c';
        *(gf->phaseval+phv_count + 3 ) = 'd';
#endif
    }

    gf->error = 0;
    initbits(FSA0);
    clearphvals(FSA gf);

    gf->phrow = gf->startoffset.y / gf->numYbitsperphase;
    gf->phrastct = gf->startoffset.y - (gf->phrow * gf->numYbitsperphase);
    DBG2("phrow = %d   phrastct = %d\n", gf->phrow, gf->phrastct);
    return gf->error;

} /* gs_open */


/*-----------------------*/
/*      initbits()       */
/*-----------------------*/
#if defined (ANSI_DEFS)
MLOCAL VOID initbits  (FSP0)
#else
MLOCAL VOID initbits  ()
#endif
{
    if (!if_state.bs_gm.maxbytestream) {
        if ((if_state.bs_gm.bytestream = TEMPCHARalloc(FSA MAXBYTESTREAM)) != NIL_MH)
            if_state.bs_gm.maxbytestream = MAXBYTESTREAM;
        else
            if_state.grayfilter.error = ERRgray_BytestreamNoMem;
    }
    if_state.bs_gm.bitbuf = 0;
    if_state.bs_gm.bitct = 0;
    if_state.bs_gm.numused = 0;
}


/*-----------------------*/
/*      flushbits()      */
/*-----------------------*/
#if defined (ANSI_DEFS)
MLOCAL VOID flushbits(FSP0)
#else
MLOCAL VOID flushbits()
#endif
{
    if(if_state.bs_gm.bitct)
    {
        if(if_state.bs_gm.numused == if_state.bs_gm.maxbytestream)
        {
            UL32 size;
            if (if_state.bs_gm.maxbytestream == AllocMax) {
                if_state.grayfilter.error = ERRgray_BytestreamNoMem;
                return;
            }
            size = if_state.bs_gm.maxbytestream + 256;
            if (size > AllocMax)  size = AllocMax;
            gs_realloc(FSA &if_state.grayfilter, (UINTG)size, GS_REALLOC_COPYBUF);
            if (if_state.grayfilter.error)
                return;
        }
        if_state.bs_gm.p_bytestream[if_state.bs_gm.numused++] = (UB8)(if_state.bs_gm.bitbuf & 0xff);
    }
}


/*-----------------------*/
/*     flushbyte()       */
/*-----------------------*/
#if defined (ANSI_DEFS)
MLOCAL VOID flushbyte(FSP0)
#else
MLOCAL VOID flushbyte()
#endif
{
    if_state.bs_gm.bitct -= 8;
    if(if_state.bs_gm.numused == if_state.bs_gm.maxbytestream)
    {
        UL32 size;
        if (if_state.bs_gm.maxbytestream == AllocMax)  {
            if_state.grayfilter.error = ERRgray_BytestreamNoMem;
            return;
        }
        /* bump size by 50% */
        size = if_state.bs_gm.maxbytestream + (if_state.bs_gm.maxbytestream >> 1);
        if (size > AllocMax)  size = AllocMax;
        gs_realloc(FSA &if_state.grayfilter, (UINTG)size, GS_REALLOC_COPYBUF);
        if (if_state.grayfilter.error)
            return;
    }
    if_state.bs_gm.p_bytestream[if_state.bs_gm.numused++] = (UB8)(if_state.bs_gm.bitbuf & 0xff);
    if_state.bs_gm.bitbuf >>= 8;
}


/* ------------------------------ drawgrayrow ------------------------------
 *
 * Description: Writes out 1 raster row
 * Parameter:   gf - GRAYFILTER object
 * Errors:      None    
 * Called By:   gs_endsubrast()
 */

#if defined (ANSI_DEFS)
MLOCAL VOID drawgrayrow ( FSP GRAYFILTER *gf )
#else
MLOCAL VOID drawgrayrow ( gf )
GRAYFILTER *gf;
#endif
{
    SW16 ct;
    SW16 *phaseval;

    phaseval = &gf->phaseval[0];

    if(gf->numXsubpixels == 1 && gf->numYsubpixels == 1 )  /* are we a bitmap ?   */
    {
        /* write out a bitmap */
        ct=0;
        while( ct<gf->graywidth ) /* for each gray pixel in raster */
        {
            putbits(phaseval[ct++], 1);
        }
    } 
    else if( gf->numXphases == 1 && gf->numYphases == 1)
    {
        /* special case no-phasing, plain graymaps */
        for(ct=0; ct<gf->graywidth; ct++) /* for each gray pixel in raster */
        {
            SW16 v;

            /* Get gray pixel value */
            v = phaseval[ct];

            /* Output graypixel value */
            if(v==0)                  /* Are we white? ...          */
            {
                putbits(0, 1);
            }
            else if(v==gf->maxpixval) /* ... or are we black? ...   */
            {
                putbits(3, 2);
            }
            else                      /* ... or we are gray.        */
            {
                putbits(1, 2);   /* signals gray pixel value follows */
                /* case maxphval == 2:  we don't need to write anything else.
                 * The gray values can be 0, 1, 2.  We've already
                 * distinguished those 3 messages.
                 */
                if ( gf->maxphval > 2 )
                    putbits(v, gf->bsct);
            }
        }  /* for each gray pixel in raster */
    }
    else  /* we have some sort of phasing */
    {
        SW16 col0;
        SW16 nxph, nyph;

        nxph  = gf->numXphases;
        nyph  = gf->numYphases;

        col0 = 0;
        for(ct=0; ct<gf->graywidth; ct++) /* for each gray pixel in raster */
        {
            SW16 v, row, col;

            /* Compute gray pixel value */
            v = 0;
            for(row=0; row<nyph; row++)
                for(col=col0; col<col0+nxph; col++)
                    v += phaseval[ row * nxph
                                       * gf->graywidth + col ];

            /* Output graypixel value */
            if(v==0)                  /* Are we white? ...          */
            {
                putbits(0, 1);
            }
            else if(v==gf->maxpixval) /* ... or are we black? ...   */
            {
                putbits(3, 2);
            }
            else                      /* ... or we are gray.        */
            {
                putbits(1, 2);   /* signals gray phase values follow */
                for(row=0; row<nyph; row++)
                    for(col=col0; col<col0+nxph; col++)
                    {
                        v = phaseval[row * nxph
                                         * gf->graywidth + col ];
                        if(v==gf->maxphval)
                        {
                            putbits(1, 1);
                        }
                        else
                        {
                            putbits(0, 1);
                            putbits(v, gf->bsct);
                        }
                    }

            }
            col0 += nxph;   /* for next gray pixel */
        }  /* for each gray pixel in raster */
    }  /*  else output gray pixel row if phasing */
} /* drawgrayrow ( ) */

/* ----------------------------- gs_endsubrast -----------------------------
 *
 * Description: Write out 1 raster row with call to drawgrayrow().
 * Parameter:   gf - GRAYFILTER object
 * Errors:      None    
 * Called By:   nz_set_trans()
 */

#if defined (ANSI_DEFS)
GLOBAL UW16 gs_endsubrast(FSP GRAYFILTER *gf)
#else
GLOBAL UW16 gs_endsubrast(gf)
GRAYFILTER *gf;
#endif
{

    SW16 i;
    SW16 phrow;
    SW16 *phaseval;
    BOOLEAN islastsubrow;

    DBG1("gs_endsubrast()    cursubrow %d  ", gf->cursubrow);

    if_state.bs_gm.p_bytestream = (LPUB8)MEMptr(if_state.bs_gm.bytestream);


    phrow = gf->phrow;   /* because we use it a lot */
    phaseval = &gf->phaseval [ phrow * gf->numXphases * gf->graywidth ];
#ifdef AGFADEBUG
    DBG1("numtrans %d   transitions:  ", gf->numtrans);
    for(i=0; i<gf->numtrans; i++)
        DBG1("%3d", gf->transition[i]);
    DBG("\n");
#endif

    /* NOTE: we should have an EVEN number of transitions here */

    /* Add each transition into the current y phase list of phase values */
    i=0;  /* number of transitions processed */
    while(i<gf->numtrans)
    {
        SW16 val0, col0, phval0;
        SW16 val1, col1, phval1;

        /* get the next on/off pair of transitions */
        val0 = gf->transition[i  ] + gf->startoffset.x; 
        val1 = gf->transition[i+1] + gf->startoffset.x;
        i+=2;


#if TT_SCREENRES
#if 0    /*** not a good idea after all - delete before 4.7 release ***/

        /*** swp - missing-pixel recovery (experimental) ***/
        /*** part 1 of change is in nzwind.c ***/
        if (val0 == val1)
        {
            if (val0 > 0)
                val0 --;
            else
            /* is this GUARANTEED safe? seems likely, but... */
                val1 ++;
        }
#endif
#endif    /* TT_SCREENRES */

        if(gf->numXbitsperphase == 1)
        {
            phaseval[val0] += 1;
            phaseval[val1] -= 1;
        }
        else
        {
            /* separate the phase column number from the phase sub-bit value */
            phval0 = val0 & gf->phasemask;  col0 = val0 >> gf->phaseshift;
            phval1 = val1 & gf->phasemask;  col1 = val1 >> gf->phaseshift;

            /* process the tran on / off pair */
            phaseval[col0  ] += gf->numXbitsperphase - phval0;
            phaseval[col0+1] += phval0;
            phaseval[col1  ] -= gf->numXbitsperphase - phval1;
            phaseval[col1+1] -= phval1;
        }
    }
    gf->numtrans = 0;   /* initialize for next sub raster row */

    /*  Bump everything one subraster */
    /*  If we have completed all of the subrasters in a y-phase, then
     *  process the y phase row.
     */
    gf->cursubrow++;
    islastsubrow = gf->cursubrow >= gf->black_depth;

    gf->phrastct++;
    if(gf->phrastct == gf->numYbitsperphase || islastsubrow)
    {
        SW16 ct,v;
        SW16 *p;

        gf->phrastct = 0;

        /* Convert phase's gray transitions to gray values */
        /* We use one more than graywidth for the last off transition */
        ct = gf->numXphases * (gf->graywidth+1);
        p = phaseval;
        v = 0;
        while(ct--)
        {
            v += *p;
            *p++ = v;
        }

        /* Bump to next y phase for next call to gs_endsubrast() */
        /* If we have just completed the last y phase row in the gray
         * pix row, then process the completed gray pixel row.  This
         * consists of sending the bit encoding for the gray pixel row
         * to the output recorder via calls to putbits()
         */

        gf->phrow++;                         /*    move to next phase         */
        if(gf->phrow == gf->numYphases       /* if we've finished all ph
                                                     in gray row ... */
           || islastsubrow)
        {                                /*     Output pixel row etc.     */
            gf->phrow = 0;
            gf->curgrayrow++;

            drawgrayrow ( FSA gf );
            clearphvals(FSA gf);
            /* There may be one more blank gray row at the top if we are
             * doing y-phasing.  It would be better to detect this at
             * run time rather than write out a larger graymap.
             */
            if(islastsubrow && gf->curgrayrow < gf->graydepth)
            {
                SW16 ct;
                ct = gf->graywidth;
                while(ct--)
                    putbits(0, 1);
            }
        }  /* write out a gray row */
    }
    return gf->error;

} /* gs_endsubrast */


/*  Return TRUE if parameter fails and FALSE if parameter is good */
/*-----------------------*/
/*      checkparam()     */
/*-----------------------*/
#if defined (ANSI_DEFS)
MLOCAL SL32 checkparam ( SW16 v )
#else
MLOCAL SL32 checkparam ( v )
SW16 v;
#endif
{
    return !(v==1 || v==2 || v == 4 || v == 8 || v == 16);
}
/* ------------------------------- grayfont -------------------------------
 *
 * Description: Validates grayscaling parameters of the FONTCONTEXT, copies
 *              them into our GRAYFILTER, and initializes things fontwide.
 * Parameter:   fc - UFST fontcontext
 * Errors:      ERRgray_if_not_supported if fsttype == IF
 *              ERRgray_parm_not_supported if FONTCONTEXT parameters are
 *                 incorrect
 *
 * Called By:   CGIFfont(), even if fc is set for binary bitmaps.
 */

#if defined (ANSI_DEFS)
UW16 grayfont( FSP PFONTCONTEXT fc )
#else
UW16 grayfont( fc )
PFONTCONTEXT fc;
#endif
{
    SW16 nxph, nyph, nxsub, nysub;

    DBG("grayfont()\n");

    if (!FC_ISGRAY(fc))
    {       /* If NOT making graymaps, if the bytestream memory buffer is
             * greater than the nominal size MAXBYTESTREAM, then release
             * this memory and allocate a fresh buffer of MAXBYTESTREAM bytes.
             * This is so a big grayscale buffer won't hog CACHE memory.
             */
        if (if_state.bs_gm.maxbytestream > MAXBYTESTREAM)
        {
            TEMPCHARfree(FSA if_state.bs_gm.bytestream);
            if_state.bs_gm.maxbytestream = 0;
        }
        return SUCCESS;
    }

    nxsub = fc->numXsubpixels;
    nysub = fc->numYsubpixels;
    nxph  = fc->numXphases;
    nyph  = fc->numYphases;

    /* Verify valid input parameters */

    if(FC_ISIF(fc))
        return ERRgray_if_not_supported;
    if(nxsub<=0 || nysub<=0 || nxph<=0 || nyph<=0)  /* only positive values */
        return ERRgray_parm_not_supported;
    if(nxph>nxsub || nyph>nysub)   /* can't have more phases than sub-pix */
        return ERRgray_parm_not_supported;
   /* params must be powers of 2 and be <= 8 */
    if ( checkparam ( nxsub ) ) return ERRgray_parm_not_supported;
    if ( checkparam ( nysub ) ) return ERRgray_parm_not_supported;
    if ( checkparam ( nxph  ) ) return ERRgray_parm_not_supported;
    if ( checkparam ( nyph  ) ) return ERRgray_parm_not_supported;

    if_state.grayfilter.numXsubpixels = nxsub;
    if_state.grayfilter.numYsubpixels = nysub;
    if_state.grayfilter.alignment     = fc->alignment;
    if_state.grayfilter.numXphases    = nxph;
    if_state.grayfilter.numYphases    = nyph;

    /* If number of x or y phases is > 1 then make sure gf->alignement
     * has phasing turned on in that direction.
     */
    if ( fc->alignment != GAPG && fc->alignment != GAPH &&
         fc->alignment != GAPP && nxph > 1 )
        return ERRgray_parm_not_supported;
    if ( fc->alignment != GAGP && fc->alignment != GAHP &&
         fc->alignment != GAPP && nyph > 1)
        return ERRgray_parm_not_supported;

    if_state.grayfilter.error = 0;   /* so far, so good */
    if_state.grayfilter.numtrans = 0;

    /* The following division must be exact.  This is checked for up front */
    if_state.grayfilter.maxpixval = if_state.grayfilter.numXsubpixels*if_state.grayfilter.numYsubpixels;
    if_state.grayfilter.maxphval = if_state.grayfilter.maxpixval / (if_state.grayfilter.numXphases * if_state.grayfilter.numYphases);
    if_state.grayfilter.bsct = floorlog2(if_state.grayfilter.maxphval);
    if_state.grayfilter.numXbitsperphase = if_state.grayfilter.numXsubpixels / if_state.grayfilter.numXphases;
    if_state.grayfilter.numYbitsperphase = if_state.grayfilter.numYsubpixels / if_state.grayfilter.numYphases;
    if_state.grayfilter.phaseshift = floorlog2(if_state.grayfilter.numXbitsperphase);
    if_state.grayfilter.phasemask  = if_state.grayfilter.numXbitsperphase - 1;
    if_state.grayfilter.lognumXpix = floorlog2(nxsub);
    if_state.grayfilter.lognumYpix = floorlog2(nysub);

    DBG1("alignment = %d\n", if_state.grayfilter.alignment);
    DBG2("numXsubpixels = %d   numYsubpixels = %d\n",
                  if_state.grayfilter.numXsubpixels, if_state.grayfilter.numYsubpixels);
    DBG2("numXphases    = %d   numYphases    = %d\n",
                if_state.grayfilter.numXphases, if_state.grayfilter.numYphases );
    DBG2("maxpixval = %d   maxphval = %d\n", if_state.grayfilter.maxpixval,
                                             if_state.grayfilter.maxphval);
    DBG2("numXbitsperphase = %d   numYbitsperphase = %d\n",
                                        if_state.grayfilter.numXbitsperphase,
                                        if_state.grayfilter.numYbitsperphase);

    DBG2("phaseshift = %d    phasemask = %d\n", if_state.grayfilter.phaseshift,
                                                if_state.grayfilter.phasemask );
    DBG2("lognumXpix = %d    lognumYpix = %d\n", if_state.grayfilter.lognumXpix,
                                                 if_state.grayfilter.lognumYpix );
    return SUCCESS;

} /* grayfont */

/* -------------------------------- graymap --------------------------------
 *
 * Description: Calls gs_open(), raster(), gs_close()
 * Parameters:  bm0 - pointer to IFBITMAP header created by MAKifbmheader()
 *              phbm - returned pointer to completed graymap
 * Errors:      ERR_bm_buff - error building empty bitmap
 *              ERR_fixed_space, errors from gs_open(), gs_close() or raster()
 *
 * Called By:   makechar()
 */

#if defined (ANSI_DEFS)
UW16 graymap(FSP PIFBITMAP bm0, PHIFBITMAP phbm)
#else
UW16 graymap(bm0, phbm)
PIFBITMAP bm0;
PHIFBITMAP phbm;
#endif
{
    PBUCKET pb;    /* 05-23-01 jfd */

    DBG("graymap()\n");

#if GRAYSTATS
    char_ct++;
#endif

    if (!if_state.num_loops)  /* fixed space */
    {
        /* Allocate empty bitmap and return fixed space error */
        *phbm = (HIFBITMAP)CHARalloc(FSA (SL32)BMHEADERSIZE);
        if(!*phbm)
            return ERR_bm_buff;
        else
        {
#if IFBITSPLIT
            PIFBITMAP pbm = (PIFBITMAP)MEMptr(*phbm);
            pbm->datahandle = NIL_MH;
#endif
            return ERR_fixed_space;
        }
    }

    if_state.grayfilter.error = gs_open(FSA &if_state.grayfilter, bm0);
    if ( if_state.grayfilter.error )
        goto close;

    /* generate graymap data through call to render() */
{
#ifndef WINDCOMP
    nz_init ( FSA &if_state.ras.nz_instance, if_state.grayfilter.nzw, if_state.ras.tran_run_ct,
                                    if_state.grayfilter.bmdim.y );
#endif /* WINDCOMP */
    
    pb = GET_pBUCKET(if_state.pbucket);    /* 05-23-01 jfd */

#if USE_JUMP_TABLES
    if_state.grayfilter.error =  (*((PIF_FUNC_TBL)pb->pft)->render)        /* changed 'if_state.pbucket' to 'pb'  05-23-01 jfd */
                 (FSA if_state.out_instance, pb,                        /* changed 'if_state.pbucket' to 'pb'  05-23-01 jfd */
                                  if_state.xlate.x, if_state.xlate.y
                                      + (half_ypix<<if_state.right_shift));
#else
   switch (pb->fst_type)    /* changed 'if_state.pbucket' to 'pb'  05-23-01 jfd */
   {
#if IF_RDR
      case FC_IF_TYPE:
         if_state.grayfilter.error =  (ifrender (FSA if_state.out_instance,
                                     pb, if_state.xlate.x,                /* changed 'if_state.pbucket' to 'pb'  05-23-01 jfd */
                                            if_state.xlate.y
                                      + (half_ypix<<if_state.right_shift)));
#endif
#if PST1_RDR
      case FC_PST1_TYPE:
         if_state.grayfilter.error =  (psrender (FSA if_state.out_instance,
                                           pb, if_state.xlate.x,        /* changed 'if_state.pbucket' to 'pb'  05-23-01 jfd */
                                            if_state.xlate.y
                                      + (half_ypix<<if_state.right_shift)));
#endif
#if TT_RDR
      case FC_TT_TYPE:
          if_state.grayfilter.error =  (ttrender (FSA if_state.out_instance,
                                              pb, if_state.xlate.x,        /* changed 'if_state.pbucket' to 'pb'  05-23-01 jfd */
                                            if_state.xlate.y
                                      + (half_ypix<<if_state.right_shift)));
#endif
#if FCO_RDR
      case FC_FCO_TYPE:
          if_state.grayfilter.error =  (fco_render (FSA if_state.out_instance,
                                        pb, if_state.xlate.x,            /* changed 'if_state.pbucket' to 'pb'  05-23-01 jfd */
                                            if_state.xlate.y
                                      + (half_ypix<<if_state.right_shift)));
#endif
      default:
           if_state.grayfilter.error =  (ERR_fst_type);
        break;
     }
#endif /* not USE_JUMP_TABLES */
}

    if ( if_state.grayfilter.error )
        goto close;

#ifndef WINDCOMP
    if_state.grayfilter.error = nz_set_trans ( FSA &if_state.ras.nz_instance );
    if(if_state.grayfilter.error)
        goto close;
#else
    {
    /* send ON/OFF transitions off to grayscale machinery */
    void grab_trans(FSP0);
    grab_trans(FSA0);
    }
#endif /* WINDCOMP */
close:
    /*  Build final graymap and free up all of the memory buffers */
    gs_close(FSA &if_state.grayfilter, bm0, phbm);
    return if_state.grayfilter.error;
}

/* ------------------------------- grayexit -------------------------------
 *
 * Description: Frees CHARalloc'ed memory in if_state.bs_gm.bytestream.
 * Parameters:  None
 * Called By:   CGIFexit()
 */
#if defined (ANSI_DEFS)
GLOBAL VOID  grayexit( FSP0 )
#else
GLOBAL VOID  grayexit()
#endif /* ANSI_DEFS */
{
    if (if_state.bs_gm.maxbytestream)
        TEMPCHARfree(FSA if_state.bs_gm.bytestream);
    if_state.bs_gm.maxbytestream = 0;
}

#if GRAYSTATS_1
/* ------------------------------ gs_memstats ------------------------------
 *
 * Description: Returns memory size statistics.
 * Parameters:  allocsize - BITSERVER memory buffer size
 *              mem_used  - actual size of graychar
 * Called By:   application code
 * Notes:       In "graymap.h":  #define GRAYSTATS_1 1
 */
GLOBAL VOID  gs_memstats( SL32* allocsize, SL32* mem_used )
{
    INTG x = if_state.gs_count - 1;
    if (!if_state.gs_count) x = MAXGSCOUNT - 1;
    *allocsize = if_state.bs_gm.maxbytestream;
    *mem_used = if_state.graysize[x];
}
#endif  /* GRAYSTATS_1 */

#endif /* GRAYSCALING */  /* conditionally compile this module */

/*** EOF ***/
 

hif.h  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

空文件

if.txt  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* Copyright (C) 2003 Agfa Monotype Corporation. All rights reserved. */

/* $Header:   I:/BULL/URIP/RTS/COR/IF.C_V   1.19   Aug 21 2003 17:03:34   Galejs  $ */
/* $Log:   I:/BULL/URIP/RTS/COR/IF.C_V  $ 
 * 
 *    Rev 1.19   Aug 21 2003 17:03:34   Galejs
 * update copyright notice
 * 
 *    Rev 1.18   Jun 23 2003 14:13:02   Galejs
 * ufstport.h
 * 
 *    Rev 1.17   Aug 13 1999 15:07:02   galejs
 * include-file changes
 * 
 *    Rev 1.16   22 Jun 1998 18:59:52   GALEJS
 * make Intellifont reentrant too
 * 
 *    Rev 1.15   30 Mar 1998 12:28:28   GALEJS
 * MLOCAL x/y_skel[] become if_state.x/y_skel_if[]
 * 
 *    Rev 1.14   24 Mar 1998 15:16:36   GALEJS
 * include-file changes
 * 
 *    Rev 1.13   21 Oct 1997 10:30:32   PVCSADMN
 * Removed control-z character from bottom of file.
 * 
 *    Rev 1.12   15 Sep 1997 15:54:20   JOE
 * Added check for global italic angle as well as local in process
 * italic evaluation. A local italic angle is not valid without a
 * global italic angle as well (by jwd).
 * 
 *    Rev 1.11   24 Jul 1997 15:48:10   JOE
 * Added one header file to resolve memset() (by Jimmy).
 * 
 *    Rev 1.10   13 Jan 1997 10:21:14   DAVID
 * Correct edit error in last delivery.
 * 
 *    Rev 1.9   13 Jan 1997 09:40:48   DAVID
 * Removed ELASTIC_X, and ELASTIC_Y, and ELASTEST, and bounds-compute(),
 * and testElasticInput variable as part of project to trim ufst.
 * 
 *    Rev 1.8   06 Apr 1995 15:10:50   LISA
 * Changed copyright from Miles Inc. to Bayer Corp.
 * 
 *    Rev 1.7   08 Jun 1994 13:47:56   JOE
 * In intel_char(), if character is unhinted, reset skeletal arrays
 * x_skel[] and y_skel[]. This fixes a bug which was occurring when
 * switching between hinted and unhinted characters.
 * Including "mixmodel.h".
 * 
 *    Rev 1.6   22 Apr 1994 09:28:24   LISA
 * 
 * Modified copyright/disclaimer notice for 1994.
 * 
 *    Rev 1.5   09 Jul 1993 10:58:16   MAIB
 * examine making_bold to determine embolding, not non_z_wind
 * 
 *    Rev 1.4   01 Jul 1993 14:26:30   MAIB
 * changed making_bold to non_z_wind
 * 
 *    Rev 1.3   12 Feb 1993 11:36:06   JOE
 * VXWorks support.
 * 
 *    Rev 1.2   07 Jan 1993 10:23:08   JOE
 * ANSI C function declaration changes.
 * 
 *    Rev 1.1   14 Dec 1992 09:36:38   LISA
 * Made change to Log keyword
 * 
 *    Rev 1.0   10 Dec 1992 08:37:18   LISA
 * Initial revision.
*/
/* $Date:   Aug 21 2003 17:03:34  $ */
/* if.c */


/*  07-Jul-90  awr  switch pixel size data for quadrant rotation
    25-Sep-90  jfd  Uncommented call to bold() at end of routine
    05-Oct-90  awr  added root adjust parameter to skel_proc() for
                    connecting characters
    14-Jan-91  jfd  Replaced "//" comments.
    29-Jan-91  jfd  Added cgconfig.h.
    30-Jan-91  dET  added function prototyping for MSC
    31-Jan-91  dET  Modify for MSC multi-model compilation.
     5-Feb-91  awr  Conditionally compiled out call to bold()
                    Moved manipulate() here.
     8-Feb-91 awr  Moved skel_init(), y_skel[] and x_skel[] from yclass.c
                   to if.c.
                   Renamed yclass_proc() to yclass().
                   Made x_skel[] and y_skel[] MLOCAL and passed as params
                   to yclass(), ital(), skel_proc(), bold(),
                   and manipulate().
                   Moved GLOBAL WORD work_buffer[WORK_BUFFER_SIZE]
                   from manilua.c and passed as parameter to manpulate().
    10-Feb-91 awr  Made global flag char_is_if part of IF_CHAR structure.
                   Moved making_bold to SCALE structure.
    08-Mar-91 jfd  For MULTI-MODEL, change references to LOOP* to PLOOP.
    01-Jun-91 awr  HQ4 changes
    17-Jun-91 jfd  Moved "debug.h" after "port.h".
                   Moved "profile.h" after "port.h".
                   Moved "cgconfig.h" before "port.h".
    24 Jun 91 ss   Changed prototypes for manipulate() to match the actual
                   definition in manipula.c.
     4-Jul-91 awr  Removed SCALE fields "px" and "py".
     8-Jul-91 tbh  Added elasticity.
     1-Aug-91 tbh  Changed COUNTER to UCOUNTER
                   Made declaration of result conditional with ELASTICITY.
                   Cleaned up line lengths.
     6-Aug-91 jfd  In intel_char(), "root_adjust" is never initialized if
                   (!ELASTIC_Y) so am setting it to "0" at top.
    24-Aug-91 awr  Moved function decls to include file
    23-Aug-91 jfd  In skleletal_init(), if ELASTICITY is enabled but no
                   elastic data exists (pex, pey == 0), check for pex and
                   pey == NULL before trying to read *pex and *pey in order
                   to get rid of a WINDOWS general protection fault error.
    11-Dec-91 tbh  Corrected placement of italic() call relative to
                   skeletal_init().
    04-Mar-92  tbh  Added .baseproj to support standard STANDARD dimensions
    03-Apr-92 rs   Portability cleanup (see port.h).
    15-Sep-92 jfd  Conditionally compiling entire module based on IF_RDR.
    17-Sep-92 jfd  Changed "if_state" from GLOBAL to EXTERN. It is declared
                   GLOBAL in COMP_PIX.C
    05-Oct-92 jfd  In intel_char(), added extra set of parentheses to two
                   "while" statements to get rid of compiler warnings.
    15-Nov-92 rs   Port to Mac - italic() -> cgitalic(), bold() -> cgbold().
    07-Jan-93 jfd  ANSI C function declaration changes.
    08-Feb-93 jfd  VXWorks support.
    01-Jul-93 maib  Changed making_bold to non_z_wind
    09-Jul-93 maib  Checked for using bold code by examining making_bold
                    field not non_z_wind
    08-Jun-94 jfd  In intel_char(), if character is unhinted, reset
                   skeletal arrays x_skel[] and y_skel[]. This fixes
                   a problem which was occurring when switching
                   between hinted and unhinted characters.
                   Including "mixmodel.h".
    13-Jan-97 dlk  Removed ELASTIC_X and ELASTIC_Y option as part of project
                   to trim ufst.  This caused removal of bounds_compute().
                   Also removed ELASTEST and testElasticInput.
    14-Sep-97 jwd  Added check for global italic angle as well as local in
                   in process italic evaluation. A local italic angle is not
                   valid without a global italic angle as well.
     27-Mar-98 slg  Move MLOCALs x_skel[], y_skel[] into if_state, renaming
                    to x_skel_if[], y_skel_if[]
*/

#include "cgconfig.h"

#if IF_RDR

#ifdef VXWORKS
#include "vxWorks.h"
#endif

#include <stdio.h>
#include "ufstport.h"
#include "dbg_ufst.h"

#include "shareinc.h"

#include "mixmodel.h"
#include "adj_skel.h"

#include <string.h> /* add this line to resolve memset(). OffWarningMsg by jqz */


#ifdef LINT_ARGS
MLOCAL BOOLEAN    skeletal_init (FSP UW16);
#endif


/**********************************************************************/
/*                                                                    */
/*      skeletal_init ()                                              */
/*              sets the adjusted skeletal data arrays to their       */
/*              initial values                                        */
/*                                                                    */
/**********************************************************************/


#if defined (ANSI_DEFS)
MLOCAL BOOLEAN skeletal_init (FSP UW16 process)
#else
MLOCAL BOOLEAN
skeletal_init (process)
UW16 process;
#endif

{

    UCOUNTER i, j, ky, kx, total_y, total_x;
    LOOP  loop;       /* pointer to current loop structure */
    PSW16VECTOR cv;   /* pointer to coordinate vectors */
    PADJUSTED_SKEL xs, ys;
    SW16  index;
    SW16  val;


    ky=0;
    kx=0;
    xs = if_state.x_skel_if;
    ys = if_state.y_skel_if;
    total_y = 0;
    total_x = 0;

   DBG ("skeletal_init()  orig  new\n");


   /* for each contour loop */

    first_loop(FSA0);

    for (i=0; i<if_state.num_loops; i++)
        {
        DBG1("    loop %d\n", i);
        DBG2("    if_state.yskel.num_skel_loop[%d] = %d\n",
                                        i, if_state.yskel.num_skel_loop[i]);
        DBG2("    if_state.xskel.num_skel_loop[%d] = %d\n",
                                        i, if_state.xskel.num_skel_loop[i]);

        next_loop(FSA &loop);
        cv = loop.cv;

        /* if skel array exceeded, return error */
        total_y += if_state.yskel.num_skel_loop[i];
        total_x += if_state.xskel.num_skel_loop[i];
        if ((total_y > MAX_SKEL) || (total_x > MAX_SKEL))
            return FALSE;
        if (process == YPROC)
          {
          for (j=0; j < if_state.yskel.num_skel_loop[i]; j++)
            {
            index = if_state.yskel.skel_to_contr[ky];
            val   = (cv+index)->y;

            ys->original          = val;
            ys->intermed          = val;
            ys->adjusted          = val;
            ys->baseproj          = val;


            DBG2("    yskel[%d]   %d\n", index, val);

            ys++;
            ky++;
            }
          }

        else
          {
          for (j=0; j < if_state.xskel.num_skel_loop[i]; j++)
            {
            index = if_state.xskel.skel_to_contr[kx];
            val    = (cv+index)->x;

            xs->original          = val;
            xs->intermed          = val;
            xs->adjusted          = val;
            xs->baseproj          = val;


            DBG2("    xskel[%d]   %d\n", index, val);

            xs++;
            kx++;
            }
          }
        }


  /* check data integrity */
/***
    if ((ky != if_state.yskel.num_skel) || (kx != if_state.xskel.num_skel))
    {
        DBG("BAD SKELETAL DATA\n");
        DBG2("    total number of y,x skels = %d, %d\n",
                                     if_state.yskel.num_skel, if_state.xskel.num_skel);
        DBG2("    number processed = %d, %d\n", ky, kx);
        return FALSE;
    }
***/

    return TRUE;
}


/**********************************************************************/
/*                                                                    */
/*      intel_char ()                                                 */
/*              drives the Intellifont process                        */
/*                                                                    */
/**********************************************************************/

#if defined (ANSI_DEFS)
GLOBAL UW16  intel_char(FSP0)
#else
GLOBAL UW16
intel_char()
#endif

    {

    PADJUSTED_SKEL xskel, yskel;
    SW16           root_adjust;


    DBG("\n\nintel_char()\n");

    if(if_state.char_is_if)
        {
        xskel = (PADJUSTED_SKEL) & if_state.x_skel_if[0];
        yskel = (PADJUSTED_SKEL) & if_state.y_skel_if[0];
        root_adjust = 0;

          if(!skeletal_init (FSA YPROC)) return ERR_skeletal_init;

          yclass (FSA yskel);
    
          if(!skel_proc (FSA &if_state.yskel, &if_state.glob_y_dim,
                         &if_state.y, yskel, root_adjust))
            return ERR_y_skel_proc;
   

        pixel_align (FSAvoid if_state.escape_box.ll.x, &if_state.x, R_TWO_I);
    
        root_adjust = if_state.value - if_state.escape_box.ll.x;
    

          if(!skeletal_init (FSA XPROC)) return ERR_skeletal_init;

          DBG1("    if_state.loc_ital_ang = %d\n", if_state.loc_ital_ang);

          /* The routine cgitalic should not be entered unless both a local */
          /* and  global italic angle exists for the character.  This add'l */
          /* check is installed to resolve fnctnl issues occurring w/ early */
          /* decoratives, such as Brush and ParkAve.                        */

          /* process italic, based on both glob and loc italic angles;  loc */
          /* angle is not valid without global angle as well.               */
          
          if ((if_state.glob_ital_ang) && (if_state.loc_ital_ang))
             cgitalic(FSA xskel, yskel); 

          if(!skel_proc (FSA &if_state.xskel, &if_state.glob_x_dim,
                         &if_state.x, xskel, root_adjust))
            return ERR_x_skel_proc;

#if BOLD
        if(if_state.making_bold)   cgbold(FSA if_state.x_skel_if, if_state.y_skel_if);
#endif
        }

        /* If character is unhinted, reset skeletal arrays (6-8-94 jfd) */

        else
        {
           MEMSET (if_state.x_skel_if, '\0', sizeof (if_state.x_skel_if));
           MEMSET (if_state.y_skel_if, '\0', sizeof (if_state.y_skel_if));
        }
         

/*  Manipulate and scale outline into work buffer */

    return manipulate (FSA if_state.x_skel_if, if_state.y_skel_if);
    }
#endif  /* IF_RDR */


 

if_init.txt  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* Copyright (C) 2004 Agfa Monotype Corporation. All rights reserved. */

/* $Header:   I:/BULL/URIP/RTS/COR/IF_INIT.C_V   1.29   Jun 04 2004 16:00:18   GalejsS  $ */
/* $Log:   I:/BULL/URIP/RTS/COR/IF_INIT.C_V  $ 
 * 
 *    Rev 1.29   Jun 04 2004 16:00:18   GalejsS
 * save IF orThreshold value at end of if_init_glob()
 * 
 *    Rev 1.28   Aug 21 2003 17:03:34   Galejs
 * update copyright notice
 * 
 *    Rev 1.27   Aug 21 2003 13:58:00   IndrelR
 * Added feature for processing XL bitmaps.
 * 
 *    Rev 1.26   Jul 21 2003 17:28:36   Galejs
 * reentrancy / debug fixes
 * 
 *    Rev 1.25   Jun 19 2003 18:31:54   Galejs
 * get rid of STATS option; fix a compiler warning
 * 
 *    Rev 1.24   Oct 21 2002 18:15:50   Galejs
 *  
 *    Rev 1.23   Sep 26 2002 19:26:02   Galejs
 * remove obsolete PAD_BYTE code
 * 
 *    Rev 1.22   07 Sep 2001 17:04:08   Zhang
 * Put back MAKEWORD macro.
 * 
 *    Rev 1.21   31 Aug 2001 16:12:22   Zhang
 * Modified macro MAKEWORD_NS.
 * 
 *    Rev 1.0   31 Aug 2001 16:12:22   Zhang
 * Initial revision.
 * 
 *    Rev 1.20   May 03 2001 19:24:54   Galejs
 * data-type cleanup
 * 
 *    Rev 1.19   Jan 24 2000 12:47:54   galejs
 * compile fixes (if REENTRANT and AGFADEBUG)
 * 
 *    Rev 1.18   Aug 13 1999 15:07:02   galejs
 * include-file changes
 * 
 *    Rev 1.17   29 Jul 1999 17:14:06   JOE
 * Changed DEBUG directive to AGFADEBUG (by ks).
 * 
 *    Rev 1.16   17 Aug 1998 11:04:24   AL
 * Made debug print statements reentrant
 * 
 *    Rev 1.15   22 Jun 1998 19:14:16   GALEJS
 * make Intellifont reentrant too
 * 
 *    Rev 1.14   15 Apr 1998 17:59:46   GALEJS
 * move GLOBAL dup_points[] into IF_STATE
 * 
 *    Rev 1.13   13 Apr 1998 13:05:32   AL
 * Corrected DBG2() to DBG1() when unused variable was removed
 * 
 *    Rev 1.12   26 Mar 1998 16:43:12   GALEJS
 * include-file changes; delete unused if_state elements
 * 
 *    Rev 1.11   16 Jul 1997 16:44:50   JOE
 * Got rid of 3 warning messages about type mismatches (by Jimmy).
 * 
 *    Rev 1.10   13 Jan 1997 08:55:46   DAVID
 * Removed ELASTIC_X and ELASTIC_Y as part of project to trim ufst.
 * Also resulted in removal of GLOBAL variable isElastic.
 * 
 *    Rev 1.9   20 Mar 1996 09:40:12   MERRILL
 * save unused lenth
 * 
 *    Rev 1.8   06 Apr 1995 15:11:04   LISA
 * Changed copyright from Miles Inc. to Bayer Corp.
 * 
 *    Rev 1.7   22 Apr 1994 09:28:18   LISA
 * Modified copyright/disclaimer notice for 1994.
 * 
 *    Rev 1.6   18 Oct 1993 15:57:28   JOE
 * In slimrecon(), additional support for processing early MOTOROLA fonts
 * which contain a pad byte in various places.
 * 
 *    Rev 1.5   23 Sep 1993 10:49:00   JOE
 * In slimrecon(), added support for processing early MOTOROLA fonts
 * which contain a pad byte in various places.
 * 
 *    Rev 1.4   12 Feb 1993 11:58:48   JOE
 * VXWorks support.
 * 
 *    Rev 1.3   07 Jan 1993 15:27:12   JOE
 * Corrected ANSI function declaration for slimsetup_intell().
 * 
 *    Rev 1.2   07 Jan 1993 14:03:42   JOE
 * ANSI C function declaration changes.
 * 
 *    Rev 1.1   14 Dec 1992 09:34:42   LISA
 * Made change to Log keyword
 * 
 *    Rev 1.0   10 Dec 1992 08:37:36   LISA
 * Initial revision.
*/
/* $Date:   Jun 04 2004 16:00:18  $ */
/* if_init.c */
/*
 *
 *
 * HISTORY
 *
 * 03-Jan-91  jfd  IFB on a Printer changes:
 *                 1.) Including file "cgconfig.h".
 *                 2.) Adding ROM support.
 *
 * 15-Jan-91  jfd  Due to change in if_type.h ("baseline_offset" is now a
 *                 WORD), in routine if_data(), cast value stored in
 *                 "c.baseline_offset" as  *(WORD*) instead of *(UWORD*). 
 * 30-Jan-91  dET added function prototyping for MSC
 * 31-Jan-91  dET Modify for MSC multi-model compilation.
 * 31-Jan-91  dET Initalize structure SCALE d = {0,0};  This forces "d" 
 *                to be in the DATA segment rather than BSS segment.  This 
 *                modification enhances performance on 80x86 processors and
 *                can be removed if modifications to "imath.asm" are made.
 *  5-Feb-91  awr Conditionally compiled BOLD.
 * 10-Feb-91  awr Made global flag char_is_if part of IF_CHAR structure.
 * 23-Feb-91  awr Changed bucket sub-segment handles to offsets.

 *  31-Jan-91 bjg Added slimsetup_intell and slimrecon for slim format
 *  01-May-91 bjg Removed pad byte in HQ4 format.
 *  01-May-91 bjg Initialize intel data for contourless char in slimrecon
 *  24-Apr-91 bjg Reset ptr after reading expand buffer in setup_face().
 *  15-Apr-91 bjg Treat HQ4 data as Intell ordered bytes regardless of platform.
 *  01-Apr-91 tbh Added STANDARD standard dimension setup to setup_intell and setup_face
 *  02-Jun-91 awr HQ4 changes
 *  17-Jun-91 jfd Moved "debug.h" after "port.h".
 *  21 Jun 91 ss  Moved prototype for fgseg() from ix.h.
 *  25 Jun 91 ss  Cleaned up warnings by adding casts.
 *   8 Jul 91 bjg Added elasticity.
 *   1-Aug-91 tbh Removed unreferenced variables.
                  Redeclared loop counters as COUNTER or UWORD where appropriate.
                  Coerced (pub - c.expand_buf) to UWORD.
 *  22-Aug-91 jfd Conditionally compiled slimrecon() and slimsetup_intell()
 *                based on SLIM_FONTS.
 *                In if_init_char(), conditionally compiling call to
 *                slimrecon() based on SLIM_FONTS.
 *  02-Oct-91 jfd In if_init_char(), always resetting isElastic at start
 *                in case we're processing a SLIM FONT which returns
 *                without setting these variables properly.
 *  04-Oct-91 jfd In slimrecon(), initialize xmin, xmax, ymin and ymax
 *                to values of first point because first point was not
 *                being considered as an extreme, causing an incorrect
 *                x-bounding box value.
 *   4 Oct 91 ss  Fixed casts in expand_hq3().
 *   9 Oct 91 jfd In if_init_char(), conditionally compiling statement
 *                which resets isElastic to get rid of compiler error.
 *   9 Oct 91 ss  Changed set of "done" in slimrecon() to get better results.
 *  11 Oct 91 jfd Added code to produce skeletal statistics.
 *  23-Oct-91 rs  Modify 'next_loop()' for PS type 1 bezier data.
 *  28-Oct-91 jfd In slimrecon(), made changes to get rid of compiler
 *                warnings caused when building medium model as follows:
 *                   (UBYTE *)         --> (PUBYTE)
 *                   (slimfont_type *) --> (Pslimfont_type)
 *                Made similar change to MAKEWORD macro
 *                   (UBYTE *)         --> (PUBYTE)
 *  04-Nov-91 jfd In if_init_char(), removed call to print_xy() if processing
 *                slim fonts.
 *  05-Nov-91 jfd Moved declaration for "isElastic" to outside LINT_ARGS
 *                conditional compile block.
 *  16-Jan-92 rs  Fix 'next_loop()' for PS type 1 bezier data.
 *  22-Jan-92 bjg Fixed slimrecon for proofer fonts.
 *                also fixed escapement on 68000.
 *  27-Jan-92 jfd In slimrecon(), corrected misspelling for "xescapement".
 *   5-Feb-92 bg  The dup_points array is now conditionally declared based
 *                on BOLD.
 *  25 Feb 92 ss  Fixed problems in if_init_char() caused when running on
 *                SPARC.  Also changed use of pointer in slimrecon() to
 *                slimfont_type struc to allocated struc to eliminate
 *                alignment problems.
 *  04-Mar-92 jfd In if_init_char(), changed reference to "c.char_buf" to
 *                "if_state.char_buf".
 *   7-Mar-92 awr Changed next_loop() PS to not need extern_font flag
 *  19 Mar 92 ss  Fix for swapped local_italic_angle bytes in slimrecon().
 *  30-Mar-92 rs  Changed "#if DEBUG" to "#ifdef DEBUG".
 *  02-Apr-92 jfd Added STAN_STAN_MASK parameter.
 *                In glob_dims(), added code for standard standards.
 *                In if_init_glob(), added code for standard standards.
 *  03-Apr-92 rs  Portability cleanup (see port.h).
 *  08-Jul-92 rs  Code cleanup.
 *  21-Jul-92 rs  Removed unused PS code in next_loop().
 *  13 Aug 92 ss  In slimrecon(), don't swap bytes of sf.size.
 *  10-Aug-92 jfd In if_init_char(), if contour tree is missing, do not
 *                return with ERR_no_contour. Proceed with processing the
 *                character. This is being done for the case of a compound
 *                character with one of its parts being the space character.
 *  15-Sep-92 jfd Conditionally compile entire module based on IF_RDR.
 *  03-Oct-92 rs  Changes toward ANSI C - declaration of slimsetup_intell().
 *  09-Oct-92 rs  Make prototypes of slimsetup_intell() and slimrecon
 *                conditional on SLIM_FONTS.
 *  20-Oct-92 awr In build_skel_tables(), removed local variable ncoords.
 *  27-Oct-92 jfd In slimrecon(), if processing a contour-less character,
 *                instead of returning immediately with ERR_no_contour,
 *                continue processing. (This will resolve the bolle compound
 *                character problem (2 parts, 1st is space character).
 *  15-Nov-92 rs  Port to Mac -> casts in calls to build_skel_tables().
 *  07-Jan-93 jfd ANSI C function declaration changes.
 *                Corrected ANSI function declaration for slimsetup_intell().
 *  08-Feb-93 jfd VXWorks support.
 *  23-Sep-93 jfd In slimrecon(), added support for processing early MOTOROLA
 *                fonts which contain a pad byte in various places.
 *  18-Oct-93 jfd In slimrecon(), additional support for processing early 
 *                MOTOROLA fonts which contain a pad byte in various places.
 *  13-Jan-97 dlk Removed ELASTIC_X and ELASTIC_Y as part of project to trim
 *                ufst.  Also, this caused removal of variable isElastic.
 *    26-Mar-98 slg Remove unused if_state elts "contour_data","subst_wdth_fac",
 *                  "contour_flag","PreBrokenContrs". Also make entire module
 *                  conditional on IF_RDR, since load_char_stats() at end is
 *                  used to dump IF_RDR-only data.
 *    15-Apr-98 slg Move GLOBAL dup_points[] into IF_STATE.
 *  17-Apr-98 awr Added reentrant calling sequence to debug print statements
 *                print_metrics(), etc.
 *  28-Jul-99 ks  Changed DEBUG compiler directive to AGFADEBUG. 
 *  30-Aug-01 dz  Merged macro MAKEWORD_NS and MAKEWORD and deleted macro MAKEWORD 
 *  07-Sep-01 dz  Put back MAKEWORD macro.
 * 
 */

#include "cgconfig.h"

#if IF_RDR

#ifdef VXWORKS
#include "vxWorks.h"
#endif

#include <stdio.h>
#include "ufstport.h"
#include "dbg_ufst.h"

#include "shareinc.h"

#include "segments.h"

#define STAN_STAN_MASK 0x04

#ifdef LINT_ARGS
MLOCAL UW16   expand_hq3(FSP LPLPSB8);
MLOCAL LPSB8   glob_dims(FSP PDIMENSION, LPSB8);
MLOCAL LPSB8   skel_data(LPSB8, PSKEL);
MLOCAL UW16   build_skel_tables(FSP LPSB8);
MLOCAL UW16   if_data(FSP UW16, LPSB8);
#if SLIM_FONTS
MLOCAL UW16  slimrecon (FSP0);
MLOCAL LPUB8 slimsetup_intell (PSKEL, LPUB8, UB8, UB8, UB8);
#endif /* SLIM_FONTS */
#ifdef AGFADEBUG
MLOCAL BOOLEAN print_contour(FSP0);
MLOCAL VOID print_metric(FSP0);
MLOCAL VOID print_xy(FSP0);
MLOCAL VOID print_points(FSP0);
MLOCAL VOID print_skel(FSP PSKEL);
MLOCAL VOID print_if(FSP0);
#endif

#else
#if SLIM_FONTS
MLOCAL UW16  slimrecon ();
MLOCAL LPUB8 slimsetup_intell ();
#endif /* SLIM_FONTS */

#endif /* LINT_ARGS */

/*-----------------------------*/

/*---------------*/
/*  next_loop    */
/*---------------*/
#if defined (ANSI_DEFS)
GLOBAL VOID  next_loop(FSP PLOOP lp)
#else
GLOBAL VOID
next_loop(lp)
    PLOOP lp;
#endif
{
    LPSB8 p;
    UW16 npnt, ncontact;

    p = if_state.next_coord_data;
    npnt     = *(LPSW16)p;  p +=2;
    ncontact = *(LPSW16)p;  p +=2;

    lp->npnt = npnt;
    lp->ncontact = ncontact & 0x7fff;
    lp->polarity = (SB8)((ncontact&0x8000) ? 1:0);
    lp->v = p;    p += (npnt+1)&0xfffe;
    lp->cv = (PSW16VECTOR)p;
    if(if_state.quality > 1) npnt += lp->ncontact;
    lp->ncoords = npnt;

    if_state.next_coord_data = p + sizeof(SW16VECTOR)*(npnt + 1);
}

/*---------------*/
/*  first_loop   */
/*---------------*/
#if defined (ANSI_DEFS)
GLOBAL VOID  first_loop(FSP0)
#else
GLOBAL VOID
first_loop()
#endif
{
    if_state.next_coord_data = if_state.expand_buf;
}


/*---------------*/
/*  glob_dims    */
/*---------------*/
#if defined (ANSI_DEFS)
MLOCAL LPSB8 glob_dims(FSP PDIMENSION d, LPSB8 p)
#else
MLOCAL LPSB8
glob_dims(d,p)
    PDIMENSION d;
    LPSB8 p;
#endif
{
    UW16 uw;
    LPSB8 pubSTAN;

    uw = *(LPUW16)p;
    d->num_dim = (UB8)uw;
        p += 2;         /* step to array of global dimension values */
    d->value = (LPUW16)p;
        p += uw<<1;     /* step to array of global dimension flags  */
    d->attrib = (LPUB8)p;
    pubSTAN   = (LPSB8)p; /* cast correctly to prevent warnings -ss 3/19/92 */
        p += uw;        /* step to Global dimension data            */
    if(((UL32)p&1) != 0) p++;

#ifdef AGFADEBUG
    DBG("\n\nGlobal Dimensions\n");
    DBG1("    number of dimensions  %u\n",d->num_dim);
    for(uw = 0; uw < d->num_dim; uw++)
        DBG2("    %u    %x\n", d->value[uw], d->attrib[uw]);
#endif

    /*
    setup index to standard STANDARD dimension ! */
    d->stan_STAN_i = 0xff;
    for (uw=0; uw<d->num_dim; uw++)
      {
      if (*pubSTAN & STAN_STAN_MASK)  /* 0x04 */
        {
        d->stan_STAN_i = (UB8)uw;
        break;
        }
      pubSTAN++;
      }

    return p;
}


/*---------------*/
/*  if_init_glob */
/*---------------*/
#if defined (ANSI_DEFS)
GLOBAL BOOLEAN if_init_glob(FSP PBUCKET bucket)
#else
GLOBAL BOOLEAN
if_init_glob(bucket)
    PBUCKET  bucket;
#endif
{
  SW16   temp_glob_ital_ang;
  UW16  uw;
  LPSB8  p;
#ifdef AGFADEBUG
  UCOUNTER   i;
  PDISPLAY  display;
  PFACE_ATT attribute;
#endif

    /* Don't think we'll need to do anything in here for PCL DL bitmap data. Let's */
    /* return for now. jwd, 07/21/03.                                              */

    if (
#if PCLEO_RDR
       (if_state.DLBmpInProcess) ||
#endif
       (if_state.if_init_face == bucket->tfnum))
          return TRUE;

    if_state.if_init_face = 0; /* set current init'd face to invalid incase failure */

  /* raster parameter */

    if (bucket->p.in.orast != MAX_UWORD)  /* jfd */
    {
        p = fgseg(FSA bucket) + bucket->p.in.orast;  /* jfd */
        if_state.orThreshold = *(LPUW16)(p);
        temp_glob_ital_ang = *(LPSW16)(p+2);
        DBG("Raster parameter\n");
        DBG1("  orThreshhold        %u\n",if_state.orThreshold);
        DBG1("  temp_glob_ital_ang  %d\n",temp_glob_ital_ang);
    }
    else
    {
        if_state.orThreshold = 0;
        temp_glob_ital_ang = 0;
    }


  /* display header */

    if (bucket->p.in.odisplay != MAX_UWORD)  /* jfd */
    {
#ifdef AGFADEBUG
        display = (PDISPLAY)(fgseg(FSA bucket) + bucket->p.in.odisplay);  /* jfd */
        DBG("Display header segment\n");
        DBG1("  NCHAR             %u\n",display->NCHAR);
        DBG1("  leftReference     %u\n",display->leftReference);
        DBG1("  baselinePosition  %u\n",display->baselinePosition);
        DBG1("  minimumPointSize  %u\n",display->minimumPointSize);
        DBG1("  maximumPointSize  %u\n",display->maximumPointSize);
        DBG1("  minimumSetSize    %u\n",display->minimumSetSize);
        DBG1("  maximumSetSize    %u\n",display->maximumSetSize);
        DBG1("  masterPointSize   %u\n",display->masterPointSize);
        DBG1("  scanDirection     %u\n",display->scanDirection);
        DBG1("  italicAngle       %d\n",display->italicAngle);
        DBG1("  xHeight           %d\n",display->xHeight);
        DBG1("  scanResolutionY   %u\n",display->scanResolutionY);
        DBG1("  scanResolutionX   %u\n",display->scanResolutionX);
        DBG1("  outputEnable      %u\n",display->outputEnable);
#endif        
    }
    else
        return FALSE;

  /* attribute header */

    if (bucket->p.in.oattribute != MAX_UWORD)  /* jfd */
    {
#ifdef AGFADEBUG
        attribute = (PFACE_ATT)(fgseg(FSA bucket) + bucket->p.in.oattribute); /* jfd */
        DBG("Face attribute segment\n");
        DBG1("  languageType     %u\n", attribute->languageType);
        DBG1("  fontUsage        %u\n", attribute->fontUsage);
        DBG1("  isFixedPitch     %u\n", attribute->isFixedPitch);
        DBG1("  escapeUnit       %u\n", attribute->escapeUnit);
        DBG1("  scaleFactor      %u\n", attribute->scaleFactor);
        DBG1("  leftReference    %u\n", attribute->leftReference);
        DBG1("  baselinePosition %u\n", attribute->baselinePosition);
        DBG1("  windowTop        %d\n", attribute->windowTop);
        DBG1("  windowBottom     %d\n", attribute->windowBottom);
        DBG1("  ascender         %d\n", attribute->ascender);
        DBG1("  descender        %d\n", attribute->descender);
        DBG1("  capHeight        %d\n", attribute->capHeight);
        DBG1("  xHeight          %d\n", attribute->xHeight);
        DBG1("  lcAccenHeight    %d\n", attribute->lcAccenHeight);
        DBG1("  ucAccentHeight   %d\n", attribute->ucAccentHeight);
        DBG1("  charPica         %u\n", attribute->charPica);
        DBG1("  leftAlign        %d\n", attribute->leftAlign);
        DBG1("  rightAlign       %d\n", attribute->rightAlign);
        DBG1("  uscoreDepth      %d\n", attribute->uscoreDepth);
        DBG1("  uscoreThickness  %u\n", attribute->uscoreThickness);
        DBG1("  windowLeft       %d\n", attribute->windowLeft);
        DBG1("  windowRight      %d\n", attribute->windowRight);
        DBG1("  spaceBand        %u\n", attribute->spaceBand);
#endif
    }
   else
      return FALSE;


/*
 *  Locate Global Intellifont Data
 */
  if ((bucket->p.in.ogif != MAX_UWORD) && bucket->p.in.gifct)  /* jfd */
  {
    if_state.if_flag = TRUE;
  }
  else
  {
    if_state.if_flag = FALSE;
    if ( if_state.orThreshold == 0 ) if_state.orThreshold = 210;
  }


    if ((bucket->p.in.ogif != MAX_UWORD) && bucket->p.in.gifct)  /* jfd */
    {
       DBG("Global Intellifont Data\n");
       p = fgseg(FSA bucket) + bucket->p.in.ogif;  /* jfd */

      /*  Y Class Data  */

        uw = if_state.num_gylines = *(LPUW16)p;
            p += 2;
        if_state.gylines = (LPUW16)p;
            p += uw<<1;      /* step to global Y-class defin data */
        uw = *(LPUW16)p;
        if_state.glob_yclass.num_yclass_def = (UB8)uw;
            p += 2;          /* step to high Y-line index array   */
        if_state.glob_yclass.yline_high_i = (LPUB8)p;
            p += uw;         /* step to low Y-line index array    */
        if_state.glob_yclass.yline_low_i = (LPUB8)p;
            p += uw;         /* step to Global Dimension Data     */

#ifdef AGFADEBUG
        DBG1("  number of gylines %u\n", if_state.num_gylines);
        for (i = 0; i < if_state.num_gylines; i++)
            DBG1("    %u\n", if_state.gylines[i]);

        DBG1("    number of yclass definitions  %u\n",
                                           if_state.glob_yclass.num_yclass_def);
        for (i = 0; i < if_state.glob_yclass.num_yclass_def; i++)
            DBG2("    %u  %u\n", if_state.glob_yclass.yline_high_i[i],
                                if_state.glob_yclass.yline_low_i[i]);
#endif


      /*  Global Y Dimension Data  */

        p = glob_dims(FSA &if_state.glob_y_dim, p);

      /*  Global X Dimension Data  */

        p = glob_dims(FSA &if_state.glob_x_dim, p);

      /*  orThreshold value  */

        if ( if_state.orThreshold == 0 )
        {
            if ( *(LPUW16)p == 0 )
                if_state.orThreshold = 210;
            else
                if_state.orThreshold = *(LPUW16)p;
        }
            p += 2;         /* step to std dim cut-in limit               */
        if_state.stan_dim_lim = *(LPUW16)p;
            p += 2;         /* step to screen face substitution width fact*/

          /* "subst_wdth_fac" never referenced - removed 24 Mar 1998 (sandra) */
        /*** if_state.subst_wdth_fac = *(LPUW16)p;    ***/

            p += 2;         /* step to screen face substitution cut-in    */
        if_state.subst_cutin = *(LPUW16)p;
            p += 10;         /* step past detail face descriptor to possible STANDARD standard dim cutin */
        if_state.stan_STAN_dim_lim = *(LPUW16)p;

        if_state.glob_ital_ang = temp_glob_ital_ang;
        if ( (if_state.stan_dim_lim == 0) || (if_state.subst_cutin == 0) )
        {
           if_state.stan_dim_lim = MAX_WORD;
           if_state.subst_cutin  = MAX_WORD;
        }
    }

    if_state.if_init_face = bucket->tfnum;  /* current init'd face */
    if_state.orThresholdIF = if_state.orThreshold;    /* save IF threshold (reload in matrix_to_scale) */  
    return TRUE;
}

/*===============================================================*/
/*            I n i t i a l i z e    C h a r a c t e r           */


#ifdef AGFADEBUG
/*----------------*/
/* print_contour  */
/*----------------*/
#if defined (ANSI_DEFS)
MLOCAL BOOLEAN  print_contour(FSP0)
#else
MLOCAL BOOLEAN
print_contour()
#endif
{
    PCTREE tnode;
    UCOUNTER i;

    DBG("Contour Tree\n");
    DBG1("    num loops  %d\n",if_state.num_loops);

    tnode = if_state.ctree;
    for(i=0; i< if_state.num_loops; i++, tnode++)
    {
        DBG4("    offset/pol/child/sib   %d  %d  %d  %d\n",
                  tnode->xyoff, tnode->polarity,
                  tnode->child, tnode->sibling);
    }
    return TRUE;
}


/*----------------*/
/* print_metric   */
/*----------------*/
#if defined (ANSI_DEFS)
MLOCAL VOID  print_metric(FSP0)
#else
MLOCAL VOID
print_metric()
#endif
{
    DBG("    metric data\n");
    DBG4("    bounding box %d,%d   %d,%d\n", if_state.bound_box.ll.x,
                                             if_state.bound_box.ll.y,
                                             if_state.bound_box.ur.x,
                                             if_state.bound_box.ur.y);
    DBG4("    escape box   %d,%d   %d,%d\n", if_state.escape_box.ll.x,
                                             if_state.escape_box.ll.y,
                                             if_state.escape_box.ur.x,
                                             if_state.escape_box.ur.y);
}


/*----------------*/
/* print_xy       */
/*----------------*/
#if defined (ANSI_DEFS)
MLOCAL VOID print_xy(FSP0)
#else
MLOCAL VOID
print_xy()
#endif
{
    PCTREE ctree;
    LPSW16 xptr, yptr;
    LPSB8 xauxptr, yauxptr;
    UCOUNTER  i;
    COUNTER   j;
    LPSB8 p;
    SW16 npnt, nauxpt;

    ctree = if_state.ctree;

    for (i=0; i< if_state.num_loops; i++)
    {
        DBG("    --------next loop-------\n");

        p = if_state.char_buf + ctree->xyoff;
        ctree++;

        npnt    = *(LPSW16)p;   p += 2;
        nauxpt  = *(LPSW16)p;   p += 2;
        xptr    = (LPSW16)p;    p += 2*npnt;
        yptr    = (LPSW16)p;    p += 2*npnt;
        xauxptr = p;           p += nauxpt;
        yauxptr = p;           p += nauxpt;


        DBG2("    npt = %d   nauxpt = %d\n", npnt, nauxpt);
        for(j=0; j < npnt; j++)
        {
            DBG4("        %x  %d      %x  %d\n",
                 ((UW16)*xptr) >> 14, *xptr&0x3fff,
                 ((UW16)*yptr) >> 14, *yptr&0x3fff);

            xptr++;
            yptr++;
        }
        DBG("\n    auxilary points\n");
        for(j=0; j < nauxpt; j++)
            DBG2("        %d  %d\n",*xauxptr++, *yauxptr++);


    }
}


/*----------------*/
/* print_points   */
/*----------------*/
#if defined (ANSI_DEFS)
MLOCAL VOID print_points(FSP0)
#else
MLOCAL VOID
print_points()
#endif
{
    PSW16VECTOR cv;
    LPSB8 v;
    UCOUNTER  i,j;
    LOOP loop;

    DBG("\n\nCoordinate and contact points\n");
    first_loop(FSA0);
    for (i=0; i< if_state.num_loops; i++)
    {
        DBG("    --------next loop-------\n");
        next_loop(FSA &loop);

        DBG3("    npnt = %d   ncontact = %d     polarity = %d\n",
                   loop.npnt, loop.ncontact, loop.polarity);
        cv = loop.cv;
        v  = loop.v;

        for(j=0; j < loop.npnt; j++)
        {
            if(V_XSKEL(*v)) {DBG("  x ");}
                       else {DBG("    ");}
            if(V_YSKEL(*v)) {DBG("y ");}
                       else {DBG("  ");}
            if(V_CONTACT(*v)) {DBG("c ");}
                         else {DBG("  ");}

            DBG3("    %d      %d    %x\n", cv->x, cv->y, *v);
            cv++;
            if(V_CONTACT(*v) && if_state.quality > 1)
            {
                DBG2("            %d      %d\n", cv->x, cv->y);
                cv++;
            }
            v++;
        }
        DBG2("            %d      %d\n", cv->x, cv->y);
    }
}

/*----------------*/
/* print_skel     */
/*----------------*/
#if defined (ANSI_DEFS)
MLOCAL VOID  print_skel(FSP PSKEL sp)
#else
MLOCAL VOID
print_skel(sp)
    PSKEL sp;
#endif
{
    UCOUNTER i,j;
    LPUB8 skloop;
    LPUW16 skcntr;

    /* tree_attrib bits */
    SW16   attrib;
    SW16   num_assoc;
    SW16   constr_dim;
    SW16   grid_align;
    SW16   rtz;
    SW16   rtype;


    DBG3("    num_skel / num_trees / num_nodes %d  %d  %d\n",
                         sp->num_skel, sp->num_trees, sp->num_nodes);


  /* build loop order list of skeletal points */

    skloop = sp->num_skel_loop;
    skcntr = sp->skel_to_contr;

    for ( i=0; i<if_state.num_loops; i++, skloop++)
    {
        DBG2("        loop %d has %u skel points\n\n\n",i,*skloop);
        DBG("                      skel_to_contr\n");
        for ( j=0; j<*skloop; j++)
            DBG2("            %d            %u\n", j, *skcntr++);
    }

    DBG("\n        tree_attrib        tree_skel_i\n");
    DBG("        N C G Z R\n");
    for(i=0; i < sp->num_nodes ; i++)
    {
        attrib = *(sp->tree_attrib+i);
        num_assoc = attrib >> 5;
        constr_dim = (attrib>>4) & 1;
        grid_align = (attrib>>3) & 1;
        rtz        = (attrib>>2) & 1;
        rtype      = attrib & 3;

        DBG6("        %d %d %d %d %d            %d\n",
           num_assoc,constr_dim,grid_align,rtz,rtype,*(sp->tree_skel_i+i));
    }

    DBG1("    num_intrp %d\n", sp->num_intrp);
    for(i=0; i < sp->num_intrp ; i++)
        DBG3("        %d %d %d\n", *(sp->intrp1_skel_i+i),
                                   *(sp->intrp2_skel_i+i),
                                   *(sp->num_intrp_assoc+i));
    DBG1("    tot_num_intrp_assoc %d\n", sp->tot_num_intrp_assoc);
    for(i=0; i < sp->tot_num_intrp_assoc ; i++)
        DBG1("        %d\n",*(sp->intrp_assoc_skel_i+i));
}

/*----------------*/
/* print_if       */
/*----------------*/
#if defined (ANSI_DEFS)
MLOCAL VOID print_if(FSP0)
#else
MLOCAL VOID
print_if()
#endif
{
    UCOUNTER i;

  /* y skel data */

    DBG("y skeletal data\n");
    print_skel(FSA &if_state.yskel);

  /* baseline */

    DBG1("baseline_offset %d\n",if_state.baseline_offset);

  /* y classes */

    DBG("y classes\n");
    DBG1("    num_yclass_ass %d\n",if_state.num_yclass_ass);
    DBG("        num_root_p_ass\n");
    for(i=0; i< if_state.num_yclass_ass; i++)
        DBG1("        %d\n", *(if_state.num_root_p_ass+i));
    DBG("        root_skel_i\n");
    for(i=0; i< if_state.yskel.num_trees; i++)
        DBG1("        %d\n", *(if_state.root_skel_i+i));
    DBG("        yclass_i\n");
    for(i=0; i< if_state.num_yclass_ass; i++)
        DBG1("        %d\n", *(if_state.yclass_i+i));

    DBG1("    num_yclass_def  (high/low) %d\n",if_state.num_yclass_def);
    for(i=0; i<if_state.num_yclass_def; i++)
        DBG2("        %d %d\n",*(if_state.yline_high_i+i), *(if_state.yline_low_i+i));

    DBG1("    num_ylines %d\n",if_state.num_ylines);
    for(i=0; i< if_state.num_ylines; i++)
        DBG1("        %d\n",*(if_state.ylines + i));

  /* x data */

    DBG("x skeletal data\n");
    print_skel(FSA &if_state.xskel);

  /* local italic angle */

    DBG2("italic angle/flag  %d %d\n",if_state.loc_ital_ang, if_state.italic_flag);

  /* standard dimension data */

    DBG2("standard dims %d %d\n",if_state.xskel.stan_dim_i,if_state.yskel.stan_dim_i);
}
#endif

/*----------------*/
/*   expand_hq3   */
/*----------------*/
#if defined (ANSI_DEFS)
MLOCAL UW16 expand_hq3(FSP LPLPSB8 ppub)
#else
MLOCAL UW16
expand_hq3(ppub)
    LPLPSB8  ppub;       /* pointer to unused bytes of expansion buffer */
#endif
{
    LPSB8 pub;
    PCTREE ctree;
    LPSB8 p;
    UW16 i, j;
    UW16 npnt, ncontact, nvertex;
    LPSW16 x, y;
    LPSB8 xa, ya;
    LPSB8 v;          /* vertex codes */
    PSW16VECTOR cv;   /* coordinates and contact points */
    SW16 xs, ys;      /* first coordinate (needed to build last contact) */
    SW16 xc, yc;      /* current coordinate */
    SB8 vc;          /* current vertex code */


    pub = *ppub;

    ctree = if_state.ctree;
    for(i=0; i<if_state.num_loops; i++)
    {
      /*  Setup input pointers  */

        p = if_state.char_buf + ctree->xyoff;
          /* deleted (incorrect) cast of int to npnt,ncontact -ss 10/3/91 */
        npnt     = (*(LPSW16)p);       p += 2;         /* num coordinates  */
        ncontact = (*(LPSW16)p);       p += 2;         /* num aux pts      */
        x        = (LPSW16)p;          p += 2*npnt;    /* coordinates      */
        y        = (LPSW16)p;          p += 2*npnt;
        xa       = p;                 p += ncontact;  /* auxillary points */
        ya       = p;

      /*  setup output pointers in expansion buffer. Layout for each loop
       *  is:
       *        UW16      npnt
       *        UW16      ncontact  bit 15 is set to polarity
       *        SB8       v[npnt]   vertex codes
       *        SB8       pad if needed to align to SW16 boundary
       *        SW16VECTOR cv[nvertex] 
       */
        nvertex = npnt + 1;                    /* the loop is closed */
        if(if_state.quality > 1) nvertex += ncontact; /* interleave contact points */
        if(ctree->polarity == 1) ncontact |= 0x8000;

        /*  Leave room for 2 UW16S plus npnt bytes of vertex codes
         *  plus pad byte if needed.
         */
        v  = pub; pub += ((5 + npnt) & 0xfffe);
        cv = (PSW16VECTOR)pub; pub += 4*(nvertex);      /* coordinates */

        if((UW16)(pub - if_state.expand_buf) > if_state.expand_size)
            return ERR_ov_char_buf;


        *(LPSW16)v = npnt;     v += 2;
        *(LPSW16)v = ncontact; v += 2;

        xs = (*x & (SW16)0x3fff);    /* remember first coordinate */
        ys = (*y & (SW16)0x3fff);

      /*  Unpack input data into output arrays */

        for(j=0; j<npnt-1; j++)
        {
          /* vertex code        */

            *v++ = vc = (UB8) (((UW16)*x >> 14 )
                                | (((UW16)*y >> 12)&(UW16)0xfffc));

            xc = cv->x = *x++ & (SW16)0x3fff;
            yc = cv->y = *y++ & (SW16)0x3fff;
            cv++;
            if(if_state.quality > 1)
            {
                if(V_CONTACT(vc))
                {
                    cv->x = ((xc+(*x & (SW16)0x3fff)) >> 1) + (SW16)(*xa++);
                    cv->y = ((yc+(*y & (SW16)0x3fff)) >> 1) + (SW16)(*ya++);
                    cv++;
                }
            }
        }
        *v++ = vc = (UB8) (((UW16)*x >> 14 )
                            | (((UW16)*y >> 12)&(UW16)0xfffc));

        xc = cv->x = *x & (SW16)0x3fff;
        yc = cv->y = *y & (SW16)0x3fff;
        cv++;
        if(if_state.quality > 1)
        {
            if (V_CONTACT(vc))
            {
                cv->x = ((xc + xs) >> 1 ) + (SW16)(*xa);
                cv->y = ((yc + ys) >> 1 ) + (SW16)(*ya);
                cv++;
            }
        }
        cv->x = xs;    /* close the loop */
        cv->y = ys;

        ctree++;
    }

    *ppub = pub;
    return SUCCESS;
}


/*----------------*/
/* skel_data      */
/*----------------*/
#if defined (ANSI_DEFS)
MLOCAL LPSB8 skel_data(LPSB8 pp, PSKEL sp)
#else
MLOCAL LPSB8
skel_data(pp, sp)
    LPSB8 pp;
    PSKEL sp;
#endif
{
    LPSB8 p;

    p = pp;

    sp->num_skel    = *(p++);
    sp->num_trees   = *(p++);
    sp->num_nodes   = *(p++);
    sp->tree_skel_i = (LPUB8)p;     /*  added cast -ss 6/25/91  */
       p += sp->num_nodes;
    sp->tree_attrib = (LPUB8)p;     /*  added cast -ss 6/25/91  */
       p += sp->num_nodes;


  /* Interpolated association data */

    sp->num_intrp           = *(p++);
    sp->intrp1_skel_i       = (LPUB8)p;     /*  added cast -ss 6/25/91  */
        p += sp->num_intrp;
    sp->intrp2_skel_i       = (LPUB8)p;     /*  added cast -ss 6/25/91  */
        p += sp->num_intrp;
    sp->num_intrp_assoc     = (LPUB8)p;     /*  added cast -ss 6/25/91  */
        p += sp->num_intrp;
    sp->tot_num_intrp_assoc = *(p++);
    sp->intrp_assoc_skel_i  = (LPUB8)p;     /*  added cast -ss 6/25/91  */
        p += sp->tot_num_intrp_assoc;

    if((p - pp) & 1) p++;
    return p;
}

/*---------------------*/
/*  build_skel_tables  */
/*---------------------*/
#if defined (ANSI_DEFS)
MLOCAL UW16 build_skel_tables(FSP LPSB8 pub)
#else
MLOCAL UW16
build_skel_tables(pub)
    LPSB8 pub;
#endif
{
    UCOUNTER     i;
    COUNTER      j;

    LPUB8   xskloop, yskloop;
    LPUW16   xskcntr, yskcntr;
    LOOP     loop;
    SB8     vertex_code;

#if BOLD
    UCOUNTER    k;
    PSW16VECTOR cv;
    PDUP_POINTS dp     = if_state.dup_points;
    UW16       dup_ct = 0;
    SW16VECTOR  last_coord;
#endif

  /*  Build loop order list of skeletal points. If pseudo bold is in
   *  enabled, find duplicate points.
   */

    if_state.yskel.num_skel_loop = yskloop = (LPUB8)pub; pub += if_state.num_loops;
    if_state.xskel.num_skel_loop = xskloop = (LPUB8)pub; pub += if_state.num_loops;
    if_state.yskel.skel_to_contr = yskcntr = (LPUW16)pub; pub += 2*if_state.yskel.num_skel;
    if_state.xskel.skel_to_contr = xskcntr = (LPUW16)pub; pub += 2*if_state.xskel.num_skel;

    if((UW16)(pub - if_state.expand_buf) > if_state.expand_size)
       return ERR_ov_char_buf;


    first_loop(FSA0);
    for ( i=0; i<if_state.num_loops; i++, yskloop++, xskloop++)
    {
        next_loop(FSA &loop);

        *yskloop = 0;
        *xskloop = 0;

        j = 0;

        while(j<loop.ncoords)
        {
            vertex_code = *loop.v++;

            if (V_XSKEL(vertex_code))  /* test for x skel pt */
            {
                (*xskloop)++;
                *xskcntr++ = j;
            }
            if(V_YSKEL(vertex_code))  /* test for y skel pt */
            {
                (*yskloop)++;
                *yskcntr++ = j;
            }
            if(if_state.quality>1 && V_CONTACT(vertex_code))
                j++;     /* skip contact point  */
            j++;
        }      

    }
#ifdef AGFADEBUG
    print_if(FSA0);
#endif

#if BOLD
    first_loop(FSA0);
    for (i=0; i<if_state.num_loops; i++)
    {
        next_loop(FSA &loop);

        cv = loop.cv;

        last_coord = *(cv + loop.ncoords - 1);
        k=0;
        while(k < loop.ncoords)
        {
            if(last_coord.x == cv->x && last_coord.y == cv->y)
            {
                DBG4("    dup pt: (%d, %d)  loop = %u   index = %u\n",
                               last_coord.x, last_coord.y, i, k);
                dp->loop  = i;
                dp->coord_index = k;
                dup_ct++;
                if(dup_ct == MAX_DUP_POINTS) return ERRtoo_many_dup_skel;
                dp++;
            }
            last_coord = *cv++;
            k++;
        }      
    }
    /* dp->loop = -1; OffWarningMsg by jqz & dp->loop is UW16, why assign -1 ? */
    dp->loop = (UW16)-1 ;
#endif /* BOLD */

    return SUCCESS;
}

/*----------------*/
/* if_data        */
/*----------------*/
#if defined (ANSI_DEFS)
MLOCAL UW16  if_data(FSP UW16 ifoff, LPSB8 pub)
#else
MLOCAL UW16
if_data(ifoff, pub)
    UW16  ifoff;
    LPSB8  pub;
#endif
{
    LPSB8    ifp;
    LPSB8    p;

    if(ifoff == MAX_UWORD)
    {
        if_state.char_is_if     = FALSE;
        if_state.yskel.num_skel = 0;
        if_state.xskel.num_skel = 0;
        if_state.loc_ital_ang   = 0;
    }
    else
    {
        if_state.char_is_if = TRUE;

        ifp = p = if_state.char_buf + ifoff;

      /* y skel data */

        p = skel_data(p, &if_state.yskel);

      /* baseline */

        if_state.baseline_offset = *(LPSW16)p;  p += 2;

      /* y classes */

        if_state.num_yclass_ass = *(p++);
        if_state.num_root_p_ass = (LPUB8)p;     /*  added cast -ss 6/25/91  */
                      p += if_state.num_yclass_ass;
        if_state.root_skel_i    = (LPUB8)p;     /*  added cast -ss 6/25/91  */
                      p += if_state.yskel.num_trees;
        if_state.yclass_i       = (LPUB8)p;     /*  added cast -ss 6/25/91  */
                      p += if_state.num_yclass_ass;

        /* local y class definitions */

        if_state.num_yclass_def = *(p++);
        if_state.yline_high_i   = (LPUB8)p;     /*  added cast -ss 6/25/91  */
                      p += if_state.num_yclass_def;
        if_state.yline_low_i    = (LPUB8)p;     /*  added cast -ss 6/25/91  */
                      p += if_state.num_yclass_def;

        if((p - ifp) & 1) p++;      /* pad to even byte */


        if_state.num_ylines = *(LPUW16)p;    p += 2;
        if_state.ylines     =  (LPUW16)p;    p += 2*if_state.num_ylines;

      /* x data */

        p = skel_data(p, &if_state.xskel);

      /* local italic angle */

        if_state.loc_ital_ang = *(LPSW16)p;   p += 2;
        if_state.italic_flag  = *(LPUW16)p;  p += 2;;

      /* standard dimension data */

        if_state.xskel.stan_dim_i = *(LPUB8)p++;
        if_state.yskel.stan_dim_i = *(LPUB8)p++;
    }


    return build_skel_tables(FSA (LPSB8)pub);
}

/*  build words from Intel ordered bytes in slim char recon */
/*  What do we do about non-Intel ?????? */

                                                       /* 10-28 91 jfd */
#define MAKEWORD(p)  ( (UW16)(*(LPUB8)(p)) + ((UW16)*((LPUB8)(p)+1)<<8) )

/* no swap, needed for words not aligned on word boundry  -ss 2/25/92 */
#if BYTEORDER == LOHI
#define MAKEWORD_NS(p) ( (UW16)(*(LPUB8)(p)) + ((UW16)*((LPUB8)(p)+1)<<8) ) /* 08-30-01 dz */
#else
#define MAKEWORD_NS(p) ( ((UW16)*(LPUB8)(p) << 8) + (UW16)(*((LPUB8)(p)+1)))
#endif

/*---------------*/
/*  if_init_char */
/*---------------*/
#if defined (ANSI_DEFS)
GLOBAL UW16 if_init_char(FSP0)
#else
GLOBAL UW16
if_init_char()
#endif
{
    UW16 /*len,*/ metoff, ifoff, conoff, xyoff;
    LPUW16 wp;
    LPSB8  p;
    SW16   i;
    UW16  status;
    LPSB8 pub;
    PBOX  pbox;

   /* Reset elasticitity flag here in case slim fonts returns prematurely */


#if SLIM_FONTS
    status = MAKEWORD_NS( if_state.char_buf ); /* use status cuz its there -ss 2/21/92 */
    if(status & 0x8000) 
       return slimrecon(FSA0);
#endif  /* SLIM_FONTS */

  /*  Offsets to sections of character */

    wp     = (LPUW16)if_state.char_buf;
  /*  len    = MAKEWORD_NS( wp ); */  wp++;   /* total length     */
    metoff = MAKEWORD_NS( wp );   wp++;   /* metric data      */
    ifoff  = MAKEWORD_NS( wp );   wp++;   /* Intellifont data */
    conoff = MAKEWORD_NS( wp );   wp++;   /* Contour tree     */
    xyoff  = MAKEWORD_NS( wp );   wp++;   /* XY data          */

    pub = if_state.expand_buf;

  /*-------------Contour Data---------------------------------*/

    if ( conoff == MAX_UWORD )  /* !!!!!!!!!!!!!!!!!! */
    {
        if_state.num_loops = 0;
        /* 2 elts never referenced - removed 26 Mar 1998 (sandra) */
        /*** if_state.contour_flag = 0;
        if_state.PreBrokenContrs = 0; ***/
        if_state.HqFormat = 0;
        if_state.ConnectingChar = 0;
/***
        DBG("No contour tree\n");
        return ERR_no_contour;
***/
    }
    else
    {

    p = (LPSB8)(if_state.char_buf+conoff);
    if_state.num_loops        = MAKEWORD_NS( p );   p += 2;
    i = MAKEWORD_NS( p );   p += 2;
        /* 2 elts never referenced - removed 26 Mar 1998 (sandra) */
        /*** i = if_state.contour_flag = MAKEWORD_NS( p );   p += 2;
        if_state.PreBrokenContrs = i & 0x0001;    ***/
        if_state.HqFormat = ((i & 0x0006) >> 1) + 1;
        if_state.ConnectingChar = (i & 0x0100) >> 8;
    if (if_state.HqFormat != 3)
    {
        DBG("----------not HQ3\n");
        return ERR_not_hq3;
    }
    if_state.ctree        = (PCTREE)p;

    }  /* !!!!!!!!!!!!!!!!!!!!!!!! */


#ifdef AGFADEBUG
    print_contour(FSA0);
    print_xy(FSA0);
#endif

    status = expand_hq3(FSA &pub);
    if (status)
        return status;
#ifdef AGFADEBUG
    print_points(FSA0);
#endif

  /*-------------Metric Data----------------------------------*/

    pbox = (PBOX)(if_state.char_buf+metoff);
    if_state.bound_box  = *pbox++;
    if_state.escape_box = *pbox;
#ifdef AGFADEBUG
    print_metric(FSA0);
#endif

  /*-------------XY Data--------------------------------------*/

  /* "contour_data" never referenced - removed 24 Mar 1998 (sandra) */
  /*** if_state.contour_data = (LPSB8)(if_state.char_buf + xyoff); ***/


  /*-------------Intellifont Data-----------------------------*/

     return if_data(FSA ifoff, pub);
}

#if SLIM_FONTS

typedef struct {
      UW16  size;
      UW16  xescapement;
      UB8  NYTR;
      UB8  NYND;
      UB8  NXYPR;
      UB8  NYCA;
      UB8  NXND;
      UB8  baseline_offset;
      SW16   local_italic_angle;
      LPUB8 data;
} slimfont_type;

typedef slimfont_type FARPTR * Pslimfont_type;

/**********************************************************************/

/*
**  Sets up X or Y Intellifont Data for slim fonts
*/

/**********************************************************************/
#if defined (ANSI_DEFS)
MLOCAL LPUB8 slimsetup_intell (PSKEL sp, LPUB8 p, UB8 NTR, UB8 NND, UB8 NPR)
#else
MLOCAL LPUB8
slimsetup_intell (sp, p, NTR, NND, NPR)
    PSKEL   sp;
    LPUB8  p;
    UB8   NTR;
    UB8   NND;
    UB8   NPR;
#endif
{
    UCOUNTER i;
    SW16     tot;
    LPUB8   ni;

/*... Skeletal Array  I6.2.{1|2}.1 */
/*  num_skel will be counted from xy data */

  sp->num_skel = 0;

/*... Tree Data       I6.2.{1|2}.2 */

  sp->num_trees   = NTR;
  sp->num_nodes   = NND;
  sp->tree_skel_i = p;           p += sp->num_nodes;
  sp->tree_attrib = p;           p += sp->num_nodes;

/*... Interpolated Association Data  I6.2.{1|2}.3 */

  sp->num_intrp   = NPR;
  sp->intrp1_skel_i = p;         p += sp->num_intrp;
  sp->intrp2_skel_i = p;         p += sp->num_intrp;
  sp->num_intrp_assoc = p;       p += sp->num_intrp;

  ni = sp->num_intrp_assoc;
  tot = 0;
  for(i=0; i<sp->num_intrp; i++) 
    tot += (SL32)(*ni++);
  sp->tot_num_intrp_assoc = (UB8)tot;

  sp->intrp_assoc_skel_i = p;    p += sp->tot_num_intrp_assoc;

  return(p);
}


/**********************************************************************/
/*  uncompresses data for slim fonts                                  */
/**********************************************************************/

#if defined (ANSI_DEFS)
MLOCAL UW16 slimrecon (FSP0)
#else
MLOCAL UW16
slimrecon ()
#endif
{
  LPSB8  dxptr, dyptr;
  LPUB8 CharBuffPntr, ptr, pub, vptr, startvptr;
  UW16  j;
  SW16  xmin,xmax,ymin,ymax;
  UW16  expand_size,done;
  slimfont_type sf;
  UB8 vcmask,f1mask,f2mask,vcshift,f2shift,flag;
  SL32  ord;
  UW16  temp,temp2;

  UW16 npnt, ncontact;
  UW16 polarity;
  PSW16VECTOR cv, startcv;
  SW16VECTOR vec={0,0}, prev_vec;

/*
** Set Input Character Data Pointer
*/
  CharBuffPntr = (LPUB8)if_state.char_buf;   /* 10-28-91 jfd */

  /* Changed following to use allocated struct vs. pointer.             */
  /* Makes life easier when worrying about alignment of elements within */
  /* the structure.                                       -ss 2/21/92   */

  /*  read char data as sequence of bytes */
                          /* don't swap -ss 8/13/92 */
  sf.size               = MAKEWORD_NS(CharBuffPntr);
     CharBuffPntr += sizeof( SW16 );
  sf.xescapement        = MAKEWORD(CharBuffPntr);  /* change back to MAKEWORD */
                                                      /* 08-30-01 dz */
     CharBuffPntr += sizeof( SW16 );

  sf.NYTR               = *CharBuffPntr++;
  sf.NYND               = *CharBuffPntr++;
  sf.NXYPR              = *CharBuffPntr++;
  sf.NYCA               = *CharBuffPntr++;
  sf.NXND               = *CharBuffPntr++;
  sf.baseline_offset    = *CharBuffPntr++;
                 /* loc_ital_ang swapped later, don't swap now -ss 3/19/92 */
  sf.local_italic_angle = MAKEWORD_NS( CharBuffPntr );   
     CharBuffPntr += sizeof( SW16 );
  sf.data               = CharBuffPntr;
  
/*
** Setup Character Contour Data  I6.1
*/
  /*  contourless character */
  if ( sf.NYTR == 0 &&
       sf.NYND == 0 &&
       sf.NXYPR == 0 &&
       sf.NYCA == 0x80  )
  {
     DBG("No contour tree\n");
#if 0
     return ERR_no_contour;
#endif  /* 10-27-92 */
  }
  else
  {
     if_state.HqFormat = 3;
     if_state.ConnectingChar = (sf.size&0x2000) ? 1 : 0;
  }
   /*
** Setup Intellifont Portion of character
*/
  if ( sf.NYTR == 0 && sf.NYND == 0 )
  {
    if_state.char_is_if     = FALSE;
    if_state.yskel.num_skel = 0;
    if_state.xskel.num_skel = 0;
    if_state.loc_ital_ang   = 0;
    ptr = sf.data;

/*??????????????*/

    if(sf.NXYPR == 0 &&
       sf.NYCA == 0x80  ) 
    {
        DBG("No contour tree\n");
#if 0
        return ERR_no_contour;
#endif  /* 10-27-92 */
    }

  } else {
    if_state.char_is_if     = TRUE;

  /*
  ** Setup y_intell  I6.2.1.1 thru I6.2.1.4
  */
  /*
  ** Setup Relative Baseline Offset  I6.2.1.5
  */
    if_state.baseline_offset = if_state.gylines[sf.baseline_offset];
  /*
  ** Setup Local Italic Angle Data  I6.2.3
  */

    if_state.loc_ital_ang = MAKEWORD(&sf.local_italic_angle); /* change back to MAKEWORD */
                                                                 /* 08-30-01 dz */
    if_state.italic_flag = (sf.size & 0x4000) ? 1 : 0;

  /*
  ** Setup Y Preset (Vertical Channelization)  I6.2.1.6 
  */

  /* ptr = slimsetup_intell(&if_state.yskel, sf.data, sf.NYTR,
                           sf.NYND, (sf.NXYPR&0xf)); OffWarningMsg by jqz */

    ptr = slimsetup_intell(&if_state.yskel, sf.data, sf.NYTR,
                                          sf.NYND, (UB8)(sf.NXYPR&0xf));

  /*
  **  Setup Y-class Character (local) Data  I6.2.1.7
  */
    if_state.num_yclass_ass = sf.NYCA;
    if_state.num_root_p_ass = ptr;              ptr += if_state.num_yclass_ass;
    if_state.root_skel_i    = ptr;              ptr += if_state.yskel.num_trees;
    if_state.yclass_i       = ptr;              ptr += if_state.num_yclass_ass;

  /*  local intellifont data - not used in slim fonts */

    if_state.num_yclass_def = 0;
    if_state.yline_high_i   = ptr;
    if_state.yline_low_i    = ptr;
   
    if_state.num_ylines = 0;
    if_state.ylines = (LPUW16)ptr;  /* 10-28-91 jfd */

  /*
  ** Setup x_intell  I6.2.2.1 thru I6.2.2.4
  */
/*ptr = slimsetup_intell(&if_state.xskel, ptr, 1, sf.NXND, (UB8)(sf.NXYPR>>4));*/
                                                    /* OffWarningMsg by jqz */

  ptr = slimsetup_intell(&if_state.xskel, ptr, 1, sf.NXND, (UB8)(sf.NXYPR>>4));
  /*
  **  Setup Character Standard Dimension Data  I6.2.4
  */
    if_state.xskel.stan_dim_i = *ptr++;
    if_state.yskel.stan_dim_i = *ptr++;
  }

  /*  Expand coordinate data */

    pub = (LPUB8)if_state.expand_buf; /* Expanded data goes here. Added cast -ss  */
    done = 0;
    if_state.num_loops = 0;
    expand_size = 0;

  /* Trying to process a space character - 10/27/92 jfd*/
    if ( sf.NYTR == 0 &&
       sf.NYND == 0 &&
       sf.NXYPR == 0 &&
       sf.NYCA == 0x80  )
    {
       xmin = 0;
       ymin = 0;
       xmax = 0;
       ymax = 0;
    }
    else
    {

    xmax = ymax = 0;         /* character bounding box in design units */
    xmin = ymin = 0x4000;    /* gets calculated on the fly             */

  while(!done)
  {
     temp = MAKEWORD(ptr);    /* set temp first and use it  -ss 10/9/91 */
                                  /* change back to MAKEWORD */
                                   /* 08-30-01 dz */
     done = temp & 0x8000;    /* last loop if bit 15 is set */
     npnt = temp&0x3ff;

    /*  Update expand_size for npnt vertex code bytes plus pad plus
     *  npnt+1 vectors (loop is closed). In our overflow check, make sure
     *  there's room for the worst case of npnt contact points. We won't
     *  know how many contact points there are until after we expand
     *  the coordinates. Then we'll update expand_size.
     */

     expand_size += ((npnt+1)*4 + npnt + 1)&0xfffe;
     if(expand_size + npnt > if_state.expand_size)
         return ERR_ov_char_buf;

     polarity = (temp&0x4000)<<1;    /* sit bit 15 to polarity */
     ptr+=2;

     *(LPUW16)pub = npnt;                     pub += 4;
     vptr = startvptr = pub;                  pub += (npnt+1) & 0xfffe;
     cv   = startcv   = (PSW16VECTOR)pub;     pub += 4*(npnt+1);
                                              /* add contact points later */
     ncontact = 0;

     ord = 0;
     vcmask = 0xe0;
     f1mask = 0x10;
     f2mask = 0xc;
     vcshift = 4;
     f2shift = 2;
 
  /*  process 1st coordinate separately */

    {
    temp = MAKEWORD(ptr);
    temp2 = MAKEWORD(ptr+2);        ptr += 4;   /* change back to MAKEWORD */
                                                   /* 08-30-01 dz */
    }

    *vptr = (UB8)(( temp>>14) | (( temp2>>12)&(UW16)0xfffc) );

    if(!(*vptr & 0x2))
        ncontact++;
    if(*vptr & 0x8)
        if_state.yskel.num_skel++;
    if(*vptr & 0x4)
        if_state.xskel.num_skel++;
    vptr++;

    prev_vec.x = temp&0x3fff;
    prev_vec.y = temp2&0x3fff;

    /* Initialize xmin, xmax, ymin and ymax here because
       first point was not being considered as an extreme
     */

    if(prev_vec.x < xmin) xmin = prev_vec.x;
    if(prev_vec.x > xmax) xmax = prev_vec.x;
    if(prev_vec.y < ymin) ymin = prev_vec.y;
    if(prev_vec.y > ymax) ymax = prev_vec.y;

    *cv++ = prev_vec;


    for(j=1; j<npnt; j++, vptr++)
    {
        *vptr = (*ptr&vcmask)>>vcshift;

        if(!(*vptr & 0x2)) 
        {   /* previous point was start of bi-arc */
            ncontact++;
            if(if_state.quality>1) cv++;        /* leave room for contact point */
        }
        else
            *(vptr-1) |= 0x1;
        if(*vptr & 0x8)
            if_state.yskel.num_skel++;
        if(*vptr & 0x4)
            if_state.xskel.num_skel++;

        flag = *ptr&f1mask;
        if(ord) 
            ptr++;
        if(flag) 
            flag = (SB8)1 + ((*ptr&f2mask)>>f2shift);

        switch (flag) {

            case 0:  /*  bits 4-13 deltax, bits 14-23 deltay */
                if(ord) {
                    vec.x  = ((SW16)*ptr)<<2;             ptr++;
                    vec.x |= ((SW16)(*ptr&0xc0))>>6;
                    vec.y  = ((SW16)(*ptr&0x3f))<<4;      ptr++;
                    vec.y |= ((SW16)(*ptr&0xf0))>>4;
                }
                else {
                    vec.x  = ((SW16)(*ptr&0xf))<<6;       ptr++;
                    vec.x |= ((SW16)(*ptr&0xfc))>>2;
                    vec.y  = ((SW16)(*ptr&0x3))<<8;       ptr++;
                    vec.y |= (SW16)*ptr;                  ptr++;
                }
                /*  set high bits for negative numbers */
                if(vec.x & 0x200) vec.x |= 0xfc00;
                if(vec.y & 0x200) vec.y |= 0xfc00;
                vec.x += prev_vec.x;
                vec.y += prev_vec.y;
                break;

            case 1:  /*  deltay = 0, bits 6-19 x value (14bits) */
                if(ord) {
                    vec.x  = ((SW16)(*ptr&0x3f))<<8;      ptr++;
                    vec.x |= (SW16)*ptr;                  ptr++;
                }
                else {
                    vec.x  = ((SW16)(*ptr&0x3))<<12;      ptr++;
                    vec.x |= ((SW16)*ptr)<<4;             ptr++;
                    vec.x |= ((SW16)(*ptr&0xf0))>>4;
                }
                vec.y = prev_vec.y;
                break;

            case 2:  /*  deltax = 0, bits 6-19 y value (14bits) */
                if(ord) {
                    vec.y = ((SW16)(*ptr&0x3f))<<8;       ptr++;
                    vec.y |= (SW16)*ptr;                  ptr++;
                }
                else {
                    vec.y = ((SW16)(*ptr&0x3))<<12;       ptr++;
                    vec.y |= ((SW16)*ptr)<<4;             ptr++;
                    vec.y |= ((SW16)(*ptr&0xf0))>>4;
                }
                vec.x  = prev_vec.x;
                break;

            case 3:  /*  bits 6-16 deltax, bits 17-27 deltay */
                if(ord) {
                    vec.x = ((SW16)(*ptr&0x3f))<<5;       ptr++;
                    vec.x |= ((SW16)(*ptr&0xf8))>>3;
                    vec.y = ((SW16)(*ptr&0x7))<<8;        ptr++;
                    vec.y |= (SW16)*ptr;                  ptr++;
                }
                else {
                    vec.x = ((SW16)(*ptr&0x3))<<9;        ptr++;
                    vec.x |= ((SW16)*ptr)<<1;             ptr++;
                    vec.x |= ((SW16)(*ptr&0x80))>>7;
                    vec.y = ((SW16)(*ptr&0x7f))<<4;       ptr++;
                    vec.y |= ((SW16)(*ptr&0xf0))>>4;
                }
                if(vec.x & 0x400) vec.x |= 0xf800;
                if(vec.y & 0x400) vec.y |= 0xf800;
                vec.x += prev_vec.x;
                vec.y += prev_vec.y;
                break;

            case 4:  /*  bits 6-19 x value, bits 22-35 y value */
                if(ord) {
                    vec.x = ((SW16)(*ptr&0x3f))<<8;       ptr++;
                    vec.x |= ((SW16)*ptr);                ptr++;
                    vec.y = ((SW16)(*ptr&0x3f))<<8;       ptr++;
                    vec.y |= (SW16)*ptr;                  ptr++;
                }
                else {
                    vec.x = ((SW16)(*ptr&3))<<12;         ptr++;
                    vec.x |= ((SW16)(*ptr&0xff))<<4;      ptr++;
                    vec.x |= ((SW16)(*ptr&0xf0))>>4;
                    vec.y = ((SW16)(*ptr&0x3))<<12;       ptr++;
                    vec.y |= ((SW16)*ptr)<<4;             ptr++;
                    vec.y |= ((SW16)(*ptr&0xf0))>>4;
                }
                break;
        }

      /* Update character bounding box */

        if(vec.x < xmin) xmin = vec.x;
        if(vec.x > xmax) xmax = vec.x;
        if(vec.y < ymin) ymin = vec.y;
        if(vec.y > ymax) ymax = vec.y;

        *cv++ = prev_vec = vec;

      /* Set shifts and mask for next coordinate to be expanded */

        if(flag) {
            if(ord) {
                ord = 0;
                vcmask = 0xe0;
                f1mask = 0x10;
                f2mask = 0xc;
                vcshift = 4;
                f2shift = 2;
            }
            else {
                ord = 4;
                vcmask = 0xe;
                f1mask = 0x1;
                f2mask = 0xc0;
                vcshift = 0;
                f2shift = 6;
            }
        }

    }
    if(ord)
        ptr++;

    if(*startvptr & 0x2)
    {
        *(vptr-1) |= 0x1;
    }
    else
        if(if_state.quality>1) cv++;        /* leave room for contact point */

    *cv = *startcv;     /* close the loop */

    *(LPUW16)(startvptr-2) = ncontact | polarity;

    dxptr = (LPSB8)ptr;                /*  added cast -ss 6/25/91  */
    dyptr = (LPSB8)ptr + ncontact;     /*  added cast -ss 6/25/91  */
    ptr += 2*ncontact;          /* set for next loop */

  /* expand contact points if there are any and quality > 1  */

    if(ncontact && (if_state.quality>1))
    {
        pub += 4*ncontact;         /* Update expansion buffer pointer      */
        expand_size += 4*ncontact; /* and total size to relect contact pts */

        vptr = startvptr;
        cv   = startcv;
        for(j=0; j<npnt; j++, cv++)
            if(V_CONTACT(*vptr++))
            {
                vec = *cv++;
                cv->x = ((vec.x + (cv+1)->x) >> 1 ) + (SW16)(*dxptr++);
                cv->y = ((vec.y + (cv+1)->y) >> 1 ) + (SW16)(*dyptr++);
            }
    }

    if_state.num_loops++;
    if(if_state.num_loops > MAX_LOOPS)
        return ERRtoo_many_loops;

  }
#ifdef AGFADEBUG
    print_points(FSA0);
#endif

  }  /* end of test for space character 10/27/82 jfd */


  /*  Character bounding box and escapement box */

    if_state.bound_box.ll.x  = xmin;
    if_state.bound_box.ll.y  = ymin;
    if_state.bound_box.ur.x  = xmax;
    if_state.bound_box.ur.y  = ymax;

    if_state.escape_box.ll.x = 2980;
    if_state.escape_box.ll.y = 5380;
    if_state.escape_box.ur.x = 2980 + sf.xescapement;
    if_state.escape_box.ur.y = 5380;

#ifdef AGFADEBUG
    print_metric(FSA0);
#endif
/*
**  Expand Skeletal Data arrays I6.2.2.1
*/
  return build_skel_tables(FSA (LPSB8)pub);
}
#endif  /* SLIM_FONTS */

#endif  /* IF_RDR */
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值