T168_111\appl\Text\Agfa:第12~16文件

cffdict.txt   

/* 
 * Copyright (C) 2004 Agfa Monotype Corporation. All rights reserved.
 */
/*
* cffDict.c   Reads and processes top and private DICT for a CFF font   
* called from cffsetup and recursively calls self to read private DICT 
*/
/* $Header:   I:/BULL/URIP/RTS/PSI/CFFDICT.C_V   1.50   Jan 07 2005 13:43:38   DugganJ  $ */
/* $Log:   I:/BULL/URIP/RTS/PSI/CFFDICT.C_V  $
 * 
 *    Rev 1.50   Jan 07 2005 13:43:38   DugganJ
 * In cff_readDICT(), when processing BlueScale number opcode ("12,9"),
 * pop data from correct stack ("fpstack" or "argsptr") to resolve Alpha
 * "floating exception" crash.
 * 
 * 
 *    Rev 1.49   Nov 18 2004 08:17:58   dugganj
 * In cff_readDICT(), save "CIDCount" when processing opcode 12:34.
 * In same function, added support for format "0" for opcode 12:37.
 * In dump_FDSelect(), added support for format "0".
 * 
 * 
 *    Rev 1.48   Oct 19 2004 12:15:44   galejss
 * add processing for all CID opcodes (actual processing for 12:30, 12:36, 12:37;
 * stub processing for the remaining opcodes)
 * 
 *    Rev 1.47   Apr 26 2004 18:33:46   GalejsS
 * NEW_PS_HINTS test not needed now (old code removed)
 * 
 *    Rev 1.46   Sep 26 2003 16:13:02   Galejs
 * use new FPOP, FPUSH macros (with optional stackchecking if PS_ERRORCHECK is enabled)
 * 
 *    Rev 1.45   Aug 22 2003 09:19:24   LynchR
 * Updated copyright notice.
 * 
 *    Rev 1.44   Jul 21 2003 18:54:46   Galejs
 * reentrancy / debug fix
 * 
 *    Rev 1.43   Jun 20 2003 14:15:48   Galejs
 * get rid of asserts
 * 
 *    Rev 1.42   Dec 02 2002 18:06:54   Galejs
 * cast all calls to MEMptr()
 * 
 *    Rev 1.41   Jul 10 2001 14:30:48   Galejs
 * get rid of // comments
 * 
 *    Rev 1.40   Jun 20 2001 16:55:50   Paul
 * bluevalues, otherblues, snapstems were
 * not in the units the T1 code expected.
 * 
 *    Rev 1.38   Jun 18 2001 10:33:48   Paul
 * changes for NEW_PS_HINTS
 * 
 *    Rev 1.36   04 Jun 2001 10:16:24   JOE
 * 
 * OpenType changes.
 * 
 *    Rev 1.35   May 04 2001 15:51:40   Galejs
 * data-type cleanup
 * 
 *    Rev 1.34   10 Feb 2000 15:32:44   AL
 * Removed PST1_ROM
 * 
 *    Rev 1.33   Aug 13 1999 16:11:56   galejs
 * include-file changes
 * 
 *    Rev 1.32   29 Jul 1999 17:31:06   JOE
 * Changed DEBUG directive to AGFADEBUG (by ks).
 * 
 *    Rev 1.31   23 Mar 1999 09:00:02   JOE
 * In cff_readDICT(), when processing 'BCD' operator, convert integer
 * stack item to floating point before copying to the floating point stack
 * to resolve compiler error when INT_FP = 1.
 * 
 *    Rev 1.30   23 Mar 1999 08:35:00   JOE
 * In cff_readDICT(), copy any existing items from the integer stack to the
 * floating point stack at the start of the 'BCD' processing code (opcode 30).
 * This resolves the fontmatrix integer / floating point operand bug.
 * 
 *    Rev 1.29   26 Feb 1999 11:09:36   DAVID
 * In cff_readDICT(), initialized args[] and BCDBuffer[] to 0s.
 * 
 *    Rev 1.28   19 Feb 1999 09:30:12   JOE
 * In cff_readDICT(), push any value which is stored on the floating
 * point stack 'fpstack' onto the standard argument stack (using the
 * fpush() call at the end of opcode 30 processing). This will alleviate
 * the problem of determining on which stack a given operand is located
 * since any operand of type 'number' (including 'delta' and 'array')
 * can be either a floating point number or an integer. As a result,
 * all operands will be located on the standard argument stack.
 * 
 *    Rev 1.26   10 Feb 1999 16:37:14   JOE
 * In cff_readDICT(), made the following changes:
 * 1.) Disabled storing of FamilyBlues and FamilyOtherBlues values for
 * consistency with Type 1 processing.
 * 2.) Converted the horizointal and vertical stem width values to 16ths
 * for consistency with Type 1 processing.
 * 
 *    Rev 1.25   09 Feb 1999 13:39:04   GALEJS
 * remove unused includes
 * 
 *    Rev 1.24   03 Feb 1999 08:28:04   JOE
 * CFF changes made in cff_readDICT() when processing Blues, FamilyBlues,
 * OtherBlues, FamilyOtherBlues, StdHW, StdVW and BCD operators for handling
 * mixture of integer and floating points operands.
 * Changed the way the 'blues[]' array is loaded by autoincrementing the
 * offset on a separate line.
 * Increased the size of the 'fpstack[]' array from 6 to 8.
 * Added partial support for the operators BaseFontName and BaseFontBlend.
 * 
 *    Rev 1.23   21 Jan 1999 18:04:04   GALEJS
 * standardize #include files
 * 
 *    Rev 1.22   20 Jan 1999 13:37:58   DAVID
 * Added code to pickup file position for charset (opcode 15).
 * 
 *    Rev 1.21   05 Oct 1998 15:08:26   DAVID
 * Changed assert in case 30 (for floating point) from "<=6" to "<=8".
 * 
 *    Rev 1.20   01 Oct 1998 17:32:56   DAVID
 * Replaced code added 30-Sep-98 with newer code to fix UDV boundary
 * conditions for CFF.
 * 
 *    Rev 1.19   30 Sep 1998 11:16:40   DAVID
 * Added new code segment to set UDV to default when requested values are
 * out-of-range.
 * 
 *    Rev 1.18   16 Sep 1998 20:08:50   GALEJS
 * get rid of obsolete MIPS case
 * 
 *    Rev 1.17   16 Sep 1998 17:02:48   DAVID
 * Set 3rd element of 'thischar' to 1 at initialization.
 * 
 *    Rev 1.16   15 Sep 1998 14:02:02   JOE
 * Changed include reference from cffProto.h to cffproto.h
 * for SUN - SPARC usage (by jwd).
 * 
 *    Rev 1.15   10 Sep 1998 18:59:38   GALEJS
 * compiler fixes (add 3 casts)
 * 
 *    Rev 1.14   31 Aug 1998 19:02:02   GALEJS
 * add reentrancy arg to getStringData() calls
 * 
 *    Rev 1.13   26 Aug 1998 16:15:40   DAVID
 * Deleted erroneous 'FSA' in call to MEMptr().
 * 
 *    Rev 1.12   26 Aug 1998 00:26:40   DAVID
 * Updates for reentrancy.
 * 
 *    Rev 1.11   24 Aug 1998 18:51:10   DAVID
 * Added reentrancy param & arg to 'processSID()'.
 * 
 *    Rev 1.10   24 Aug 1998 13:47:30   AL
 * Fixed defualt mm instance problems
 * 
 *    Rev 1.9   10 Aug 1998 11:43:18   AL
 * Check error returns and clean up // comments
 * 
 *    Rev 1.8   06 Aug 1998 16:25:26   AL
 * 
 * CFF rom, multiple master and bug fixes
 * 
 *    Rev 1.7   27 Jul 1998 15:26:52   AL
 * 
 * Internal floating point support
 * 
 *    Rev 1.6   27 Jul 1998 08:54:46   AL
 * Added internal memeory management support
 * 
 *    Rev 1.5   23 Jul 1998 15:38:44   AL
 * Added ALBUG for cff testing
 * 
 *    Rev 1.4   21 Jul 1998 16:06:44   AL
 * Store MM UDV in bucket for BUCKfind()
 * 
 *    Rev 1.3   20 Jul 1998 15:18:02   AL
 * Multiple master instance support
 * 
 *    Rev 1.2   10 Jul 1998 10:40:54   AL
 * Conditional compile entire file on CFF_RDR
 * 
 *    Rev 1.1   08 Jul 1998 11:27:10   DAVID
 * 
 * Added PVCS Change History tracking for original source.
 * 
 */

/*
REVISION HISTORY
------------------------------------------------------------------------------
08-Jul-98 dlk Original version placed under PVCS control.  Added this REVISION
              HISTORY
24-Aug-98 dlk Added reentrancy param & arg to 'processSID()'.
26-Aug-98 dlk Deleted 'FSA' from within argument list of call to MEMptr().
31-Aug-98 slg Add 'FSA' to getStringData() calls
15-Sep-98 jwd Changed reference from cffProto.h to cffproto.h for Sun/SPARC
              usage.
16-Sep-98 dlk Set 3rd element of 'thischar' to 1 (on initialization).
30-Sep-98 dlk Added code segment to test for out or range values in requested
              User Design Vector, and set to default values when true.
01-Oct-98 dlk Deleted change made 30-Sep-98, and added new code in its place
              in 'cff_read_MM()'.
05-Oct-98 dlk In case 30 for floating point, changed assert from "... <= 6" to
              "... <= 8".
20-Jan-99 dlk Added code to pick up file position for charset (opcode 15).
01-Feb-99 jfd In cff_readDICT(), made the following changes:
              1.) Increased size of fpstack[] from 6 to 8
              2.) When processing operators BlueValues (6), OtherBlues (7),
                  FamilyBlues (8), FamilyOtherBlues (9), StdHW (10),
                  StdVW (11), operands could come from either the int stack
                  or the fp stack (or both). If 'fp_arg' > 0, assume that
                  the operands will be found on the fp stack. (The BCD
                  operator (30) now checks if anything has been pushed onto
                  the int stack, and if it has, pops it off the int stack
                  and pushes it onto the fp stack (in the next available 
                  position). That way, all operands should be found in only
                  one stack.)
              3.) Added partial support for operators BaseFontName (22) and 
                  BaseFontBlend (23) - popping operands off stack.
10-Feb-99 jfd In cff_readDICT(), made the following changes:
              1.) Disabled storing of FamilyBlues and FamilyOtherBlues
                  values for consistency with Type 1 processing.
              2.) Convert the horizontal and vertical stem widths to
                  16ths for consistency with Type 1 processing.
18-Feb-99 jfd In cff_readDICT(), push every value which is stored in the
              floating point stack 'fpstack' onto the standard argument 
              stack (fpush() call at end of opcode 30 processing).
              This will alleviate the problem of determining on which stack
              a given operand is located since any operand of type 'number'
              (including 'delta' and 'array') can be either a floating point
              number or an integer.
26-Feb-99 dlk In cff_readDICT(), initialized args[] and BCDBuffer[] array
              elements to 0.
19-Mar-99 jfd In cff_readDICT(), copy any existing items from the integer
              stack to the floating point stack at the start of the 'BCD'
              processing code (opcode 30). This resolves the fontmatrix
              integer / floating point operand bug.
19-Mar-99 jfd In cff_readDICT(), when processing 'BCD' operator, convert
              integer stack item to floating point before copying to the
              floating point stack.
28-Jul-99 ks  Changed DEBUG compiler directive to AGFADEBUG. 
10-Feb-00 awr Removed PST1_ROM
23-May-01 jfd OpenType changes:
              In cff_readDICT(), increased fpstack[] from 8 to 12.
              In same function, for opcodes 15-19, adjusted offsets accordingly for
              OpenType CFF fonts.
              In same function, save offset to private DICT in new cft field.
------------------------------------------------------------------------------
*/

#include "cgconfig.h"

#if CFF_RDR    /* conditionally compile entire file */

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

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

#include "ufstport.h" 

#if MAYBE_FCNTL_H
#include <fcntl.h>
#endif

#if MAYBE_FCNTL_HIF_H
#include <fcntl.h>
#include <hif.h>  /* 2-7-94 jfd */
#endif

#if MAYBE_IO_H
#include <io.h>         /* close() */
#endif

#if MAYBE_UNISTD_H
#include <unistd.h>
#endif

#if MAYBE_MALLOC_H
#include    <malloc.h>
#endif

#include <stdlib.h> /* need for 'abort()' i.e. ASSERT */

#include "dbg_ufst.h"

#include "shareinc.h"
#include "mixmodel.h"

#include "t1itype1.h"
#include "t1isyntx.h"
#include "t1iproto.h"
#include "cffproto.h"
#if PST1_SFNTI
#include "t1isfnt.h"
#endif

#if PS_ERRORCHECK
/* optional stackchecking (only necessary for corrupt fonts, in our opinion) */

#define FPOP(dest)    \
{    \
if (argsptr > args)  { dest = (*--argsptr); }    \
else {return ERR_psi_stack_underflow;}    \
}

#define FPUSH(src)    \
{    \
if (argsptr < stacklimit) { *argsptr++ = src; }    \
else {return ERR_psi_stack_overflow;}    \
}

#else
#define FPOP(x)    x = (*--argsptr)
#define FPUSH(x)  (*argsptr++ = (x))
#endif


#define GETECHAR()   ((UW16)(*edata++))

MLOCAL SW16 cff_read_MM (FSP struct char_info* thischar);
MLOCAL SW16 processSID(FSP cft* cf, SL32 SID, struct char_info *thischar);

#ifdef AGFADEBUG
MLOCAL VOID dump_FDSelect(FSP0);
#endif


/* ------------------------------------------------------------------------ 
 * cff_readDICT(FSA cft* cf, LPUB8 edata, UL32 dictstt, UL32 dictlen)
 * 
 * reads and processes the CFF data string for the top and private DICT 
 * 
 * ------------------------------------------------------------------------ */
UW16 cff_readDICT(FSP  cft* cf, LPUB8 edata, UL32 dictstt, UL32 dictlen)
{
    SL32 args[T2ARGSTACKSIZE];
    SL32 *stacklimit = args + T2ARGSTACKSIZE;

    SW16 stems[12];
    
    LPSL32  argsptr;       /* pointer to next arg in above stack     */
    /* 02-01-99 JFD - increased stack size from 6 to 8 */
    /* 05-23-01 JFD - increased stack size from 8 to 12 */
    FPNUM fpstack[12];      /* small stack for real numbers           */
    SW16 fp_arg = 0;       /* floating point stack argument[index]   */ 
    LPUB8 lastdata = edata + dictlen;
    UW16  opcode;       
    SW16 tmp, status;      /* multi-purpose temp variables           */
    SL32  x1, x2, x3, y1;  
    SW16  blues[MAXBLUES];
    SW16 stackcnt, cnt;
    UB8 BCDbuffer[50];
    UB8 SyntheticBaseFont = 0;
    SW16 args_offset = 0;
    SL32 CIDCount = 0L;

    /* data transfered between Dict and t2Char  */
    struct char_info thischar = {0, 0, 1, 0, 0, 0, 0};  /* 3rd element should init to 1 */

    MEMSET (BCDbuffer, '\0', sizeof (BCDbuffer));
    MEMSET (args, '\0', sizeof (args));

    thischar.args = args;
    argsptr = args;        /* start with clean stack              */

    
    DBG2("stt - read CFF DICT w/ args %d len %d\n", argsptr-args, dictlen);
    while (edata < lastdata)  /* process a decrypted post-script language string */
    {
        opcode = nextopcode(FSA &edata, args, &argsptr); /* puts operands on arg stack */

        DBG1("<opcode=%d>\n",opcode);
        switch (opcode)
        {
        case 0: /*----- version SID    */ 
            FPOP(x1);   
            DBG1(" version SID %d\n", x1);
#ifdef AGFADEBUG
            if(x1 > 390)
            {
                SL32 buflen; 
                MEM_HANDLE m;
                LPUB8 localbuf;

                status = getStringData(FSA NULL, &buflen, &cf->strings, x1-390);
                if(status)
                    return ERR_cff_get_string_data;
                m = BUFalloc(FSA buflen);
                if(!m)
                    return ERR_cff_no_dict_mem;
                localbuf = (UB8*)MEMptr(m);

                status = getStringData(FSA localbuf, &buflen, &cf->strings, x1-390);
                if(status)
                    return ERR_cff_get_string_data;
                DBG2("SID version %d: [%s]\n", x1, localbuf);
                BUFfree(FSA m);
            }
            else if (x1 == 379) 
                DBG1("SID version %d: [001.000]\n", x1);
            else if (x1 == 380) 
                DBG1("SID version %d: [001.001]\n", x1);
            else if (x1 == 381) 
                DBG1("SID version %d: [001.002]\n", x1);
#endif
            break;
            
        case 1: /*----- copyright notice SID     */
            FPOP(x1);
            DBG1(" notice SID %d\n", x1); 
#ifdef AGFADEBUG
            if(x1 > 390)
            {
                SL32 buflen; 
                MEM_HANDLE m;
                LPUB8 localbuf;

                status = getStringData(FSA NULL, &buflen, &cf->strings, x1-390);
                if(status)
                    return ERR_cff_get_string_data;
                m = BUFalloc(FSA buflen);
                if(!m)
                    return ERR_cff_no_dict_mem;
                localbuf = (UB8*)MEMptr(m);

                status = getStringData(FSA localbuf, &buflen, &cf->strings, x1-390);
                if(status)
                    return ERR_cff_get_string_data;
                DBG2("SID copyright notice %d : [%s]\n", x1, localbuf);
                BUFfree(FSA m);
            }
#endif
            break;
            
        case 2: /*----- FullName SID   */ 
            FPOP(x1);
            DBG1(" FullName SID %d\n", x1); 
#ifdef AGFADEBUG
            if(x1 > 390)
            {
                SL32 buflen; 
                MEM_HANDLE m;
                LPUB8 localbuf;

                status = getStringData(FSA NULL, &buflen, &cf->strings, x1-390);
                if(status)
                    return ERR_cff_get_string_data;
                m = BUFalloc(FSA buflen);
                if(!m)
                    return ERR_cff_no_dict_mem;
                localbuf = (UB8*)MEMptr(m);

                status = getStringData(FSA localbuf, &buflen, &cf->strings, x1-390);
                if(status)
                    return ERR_cff_get_string_data;
                DBG2("SID FullName %d: [%s]\n", x1, localbuf);
                BUFfree(FSA m);
            }
#endif
            break;
            
        case 3: /*----- FamilyName SID */ 
            FPOP(x1); 
            DBG1(" FamilyName SID %d\n", x1); 
#ifdef AGFADEBUG
            if(x1 > 390)
            {
                SL32 buflen; 
                MEM_HANDLE m;
                LPUB8 localbuf;
                
                status = getStringData(FSA NULL, &buflen, &cf->strings, x1-390);
                m = BUFalloc(FSA buflen);
                if(!m)
                    return ERR_cff_no_dict_mem;
                localbuf = (UB8*)MEMptr(m);
                
                status = getStringData(FSA localbuf, &buflen, &cf->strings, x1-390);
                DBG2("SID FamilyName %d: [%s]\n", x1, localbuf);
                BUFfree(FSA m);
            }
#endif
            break;
            
        case 4: /* Weight SID */ 
            FPOP(x1);
            DBG1(" weight SID %d\n", x1); 
            if (x1 == 384)      /* Adobe standard string SID "Bold"         */
                if_state.gpxb->bucket_num |= B_BOLD;  
            break;
            
        case 5: /* FontBBox  array 1 2 3 4 (always four)                    */ 
            if_state.gpps->FontBBox[0] = args[0];
            if_state.gpps->FontBBox[1] = args[1];
            if_state.gpps->FontBBox[2] = args[2];
            if_state.gpps->FontBBox[3] = args[3];
            DBG4("FontBBox %d %d %d %d\n", 
                args[0], args[1], args[2], args[3]); 
            argsptr = args;             /* clear the stack                  */
            break;
            
        case 6: /* BlueValues (private) delta                               */                             
            cnt = argsptr - args; /* number of args on stack                */
#if 1 /* blue values are coming in as deltas  ... SWP 6/20/01 */
            if (cnt)
                {
                blues[0] = args[0];
                for (tmp=1; tmp<cnt; tmp++)
                    blues[tmp] = blues[tmp-1] + args[tmp];
                }
#else
            tmp = 0;
            while(tmp < cnt) 
            {
                blues[tmp] = args[tmp];
                tmp++;
            }
#endif

            blue_values (FSA blues, tmp);   /* 1st 2=bot blues, rest top blues  */
            argsptr = args;             /* clear the stack                  */
            fp_arg = 0;        /* reset the floating point stack */
            break;
            
        case 7: /* OtherBlues (private) delta                               */         
            cnt = argsptr - args; /* number of args on stack                */
#if 1 /* other blues are coming in as deltas ... SWP 6/20/01 */
            if (cnt)
                {
                blues[0] = args[0];
                for (tmp=1; tmp<cnt; tmp++)
                    blues[tmp] = blues[tmp-1] + args[tmp];
                }
#else
            tmp = 0;
            while(tmp < cnt) 
            {
                blues[tmp] = args[tmp];
                tmp++;
            }
#endif

            other_blues(FSA blues,cnt);
            argsptr = args;             /* clear the stack                  */
            fp_arg = 0;        /* reset the floating point stack */
            break;
            
        case 8: /* FamilyBlues (private) delta                              */  
            cnt = argsptr - args; /* number of args on stack                */
            tmp = 0;
            while(tmp < cnt) 
            {
                blues[tmp] = args[tmp];
                tmp++;
            }
#if 0
            /* Do not store the FamilyBlues values since we are
             * not storing them when processing Type 1 fonts
             * (02-10-99 jfd )
             */

            top_blues(FSA blues, cnt);  
#endif
            argsptr = args;             /* clear the stack                  */
            fp_arg = 0;        /* reset the floating point stack */
            break;
            
        case 9: /* FamilyOtherBlues (private) delta                         */         
            cnt = argsptr - args; /* number of args on stack                */
            tmp = 0;
            while(tmp < cnt) 
            {
                blues[tmp] = args[tmp];
                tmp++;
            }
#if 0
            /* Do not store the FamilyOtherBlues values since we are
             * not storing them when processing Type 1 fonts
             * (02-10-99 jfd )
             */

            bot_blues(FSA blues, cnt);  
#endif
            argsptr = args;             /* clear the stack                  */
            fp_arg = 0;        /* reset the floating point stack */
            break;
            
        case 10:  /* StdHW (private) number                                 */        
            FPOP(x1);

            /* Convert the horizontal stem width to 16ths since it
             * is stored in 16ths when processing Type 1 fonts
             * (02-10-99 jfd )
             */

            x1 <<= 4;

            stdhwx(FSA (SW16)x1);
            DBG1("stdHW: %d\n", x1);
            argsptr = args;             /* clear the stack                  */
            fp_arg = 0;    /* reset the floating point stack */
            break;  
            
        case 11:  /* StdVW (private) number                                 */        
            FPOP(x1);

            /* Convert the vertical stem width to 16ths since it
             * is stored in 16ths when processing Type 1 fonts
             * (02-10-99 jfd )
             */

            x1 <<= 4;

            stdvwx(FSA (SW16)x1);
            DBG1("stdVW: %d\n", x1);
            argsptr = args;             /* clear the stack                  */
            fp_arg = 0;    /* reset the floating point stack */
            break;
            
        case 12:  /* escape ----- start of 2-byte opcodes  --------- */
            tmp = GETECHAR ();
            DBG1("    <opcode2=%d>\n",tmp);
            switch  (tmp)
            {
            case 1:     /* isFixed Pitch bool                         */
                FPOP(x1);            /* NOTE: NOT USED, discarded  */
                break;
                
            case 2:     /* ItalicAngle number */
                if (fp_arg && (fplt(fpint2fp(1),fpabs(fpstack[0]))))
                {
                    if_state.gpxb->bucket_num |= B_ITALIC;
                }
                else 
                    if (argsptr > args)
                    {
                        FPOP(x1);
                        if (x1 > 0)
                            if_state.gpxb->bucket_num |= B_ITALIC;
                    }
                    
                fp_arg = 0;
                argsptr = args;
                break;
                
            case 3:     /* UnderlinePosition number */
                FPOP(x1);            /* NOTE: NOT USED, discarded  */
                fp_arg = 0;    /* reset the floating point stack */
                break;
                
            case 4:     /* UnderlineThickness number */
                FPOP(x1);            /* NOTE: NOT USED, discarded  */
                fp_arg = 0;    /* reset the floating point stack */
                break;
                
            case 5:     /* PaintType number */
                FPOP(x1);            /* NOTE: NOT USED, discarded  */
                fp_arg = 0;    /* reset the floating point stack */
                break;
                
            case 6:     /* CharstringType number */
                FPOP(x1);            /* must use. NEW item */
                if_state.gpps->CharstringType = (SW16) x1;
                fp_arg = 0;    /* reset the floating point stack */
                break;
                
            case 7:     /* FontMatrix array 6 */
                DBG1("fontmatrix array with %d fp args\n", fp_arg);
#if 1    /* 02-18-99 jfd */
                while(fp_arg < 6) 
                {
                    fpstack[fp_arg++] = fpint2fp(0);
                }
#else
                while(fp_arg < 6 && argsptr > args && *(argsptr-1) == 0) 
                {
                    fpstack[fp_arg++] = fpint2fp(0);
                    argsptr--;
                }
#endif
                                /* leave fp_arg at zero for next use */
                for(tmp = 0; fp_arg > 0; fp_arg--, tmp++)
                {
                    if_state.gpps->fontmatrix[tmp] = fpstack[tmp];
                }
                argsptr = args;
#if 1    /* 03-19-99 jfd */
                args_offset = 0;
#endif    /* 03-19-99 jfd */
                break;
                
            case 8:     /* StrokeWidth number */
                FPOP(x1);            /* NOTE: NOT USED, discarded  */
                fp_arg = 0;    /* reset the floating point stack */
                break;
                
            case 9:     /* BlueScale number (private) */
                if (fp_arg == 0)
                {
                    FPOP(x1);
                    bluescale(FSA x1 >> 1L);
                }
                else
                    bluescale(FSA fp2long((fpmul (fpstack[--fp_arg], fpint2fp(32768L)))));

                DBG1("BlueScale: %f\n", fpstack[fp_arg]);
                fp_arg = 0;
#if 1    /* 02-18-99 jfd */
                argsptr = args;
#endif
                break;
                
            case 10:    /* BlueShift number (private) */
                FPOP(x1);
                if_state.gpps->iBlueShift = (SW16)x1;
                DBG1("BlueShift: %d\n", x1);
                fp_arg = 0;    /* reset the floating point stack */
                break;
                
            case 11:    /* BlueFuzz number (private) */
                FPOP(x1);
                if_state.gpps->BlueFuzz = x1;
                DBG1("BlueFuzz: %d\n", x1);
                fp_arg = 0;    /* reset the floating point stack */
                break;
                
            case 12:    /* StemSnapH number (private) */
                cnt = argsptr - args;   /* number of args on stack */
                if (cnt)
                    {
                    /*** they're coming in as integers ... need 16-ths
                    *** they're coming in as deltas too! ***/
                    stems[0] = args[0] << 4;
                    for (tmp=1; tmp<cnt; tmp++)
                        stems[tmp] = stems[tmp-1] + (args[tmp]<< 4);
                    stemsnaph(FSA stems,cnt);
                    }
                argsptr = args;         /* clear the stack */
                fp_arg = 0;    /* reset the floating point stack */
                break;
                
            case 13:    /* StemSnapV number (private) */
                cnt = argsptr - args;   /* number of args on stack */
                if (cnt)
                    {
                    /*** they're coming in as integers ... need 16-ths
                    *** they're coming in as deltas too! ***/
                    stems[0] = args[0]<< 4;
                    for (tmp=1; tmp<cnt; tmp++)
                        stems[tmp] = stems[tmp-1] + (args[tmp]<< 4);
                    stemsnapv(FSA stems,cnt);
                    }
                argsptr = args;         /* clear the stack */
                fp_arg = 0;    /* reset the floating point stack */
                break;
                
            case 14:    /* ForceBold bool (private) */
                FPOP(x1);
                DBG1("ForceBold %d\n", x1);
                if(x1)
                    if_state.gpxb->bucket_num |= B_BOLD; 
                break;
                
            case 15:    /* ForceBoldThreshold number (private) */
                if(argsptr > args)
                {
                    FPOP(x1);
                    fp_arg = 0;    /* reset the floating point stack */
                    DBG1("ForceBoldThreshold %d \n", x1);
                    break;
                }
                break;
                
            case 16:    /* LenIV number (private) -1 = unencrypted charstrings */
                if(argsptr > args)
                {
                    FPOP(x1);
                    fp_arg = 0;    /* reset the floating point stack */
                }
                if(x1 == 4) if_state.gpps->lenIV = 4;
                else if_state.gpps->lenIV = 0;  /* not encrypted */
                DBG1("LenIV number %d\n", x1);
                break;
                
            case 17:    /* LanguageGroup number (private) */
                if(argsptr > args)
                {
                    FPOP(x1);
                    fp_arg = 0;    /* reset the floating point stack */
                }
                DBG1("LanguageGroup %d\n", x1);
                break;
                
            case 18:    /* ExpansionFactor number (private) */
                if(argsptr > args)
                {
                    FPOP(x1);
                    fp_arg = 0;    /* reset the floating point stack */
                }
                DBG1("ExpansionFactor %d\n", x1);
                break;
                
            case 19:    /* InitialRandomSeed number (private) */
                if(argsptr > args)
                {
                    FPOP(x1);
                    fp_arg = 0;    /* reset the floating point stack */
                }
                DBG1("InitialRandomSeed %d\n", x1);
                break;
                
            case 20:    /* Top Dict (# 20) 0x14 SyntheticBase font        */
                FPOP(x1);
                fp_arg = 0;    /* reset the floating point stack */
                DBG2("Synthetic Base Font. Face %d Index %d \n", cf->name, x1);
                if(x1 < 0 || x1 > (SL32)cf->fonts.items)
                    return ERR_cff_bad_synth;
                SyntheticBaseFont = 1;      /* flag for 0 matrix values    */
                status = GetTopDICT(FSA cf, x1+1); /* load up info from base font   */
                if(status)
                    return status;
                break;                  /* then continure with overrides   */
                
            case 21:    /* Top Dict (# 21) 0x15 Embedded Postscript`        */
                DBG("Embedded Postscript \007 not supported!\n");
                    /* return ERR_cff_no_support;   */
                break;
                
            case 22: /* BaseFontName SID */
                FPOP(x1);
                DBG1("BaseFontName %d\n", x1);
                break;

            case 23:    /* BaseFontBlend delta */
               cnt = argsptr - args; /* # args on stack */
               tmp = 0;
               while(tmp < cnt)
               {
                  /* Ignore BaseFontBlend data for now */
                  tmp++;
               }
               tmp = 0;
               argsptr = args;   /* clear the stack */
               fp_arg = 0;    /* reset the floating point stack */
               break;
                
            case 24:    /* Top Dict (# 24) 0x18 Multiple Master font        */
                stackcnt = argsptr - args; /* number of args on stack       */
                thischar.argcnt = stackcnt;
                status = cff_read_MM(FSA &thischar); 
                if(status)
                    return status;
                argsptr = args; /* clear the stack */
                fp_arg = 0;    /* reset the floating point stack */
                break;

            case 26:    /* Blend Axis types (# 26) 0x1A Multi Master font   */
                /* stack contains SID's of types i.e., "Weight", "Width"    */
                /* used by apps to set custom vals, not needed for output   */
                argsptr = args;                         /* clear the stack  */
                DBG("Blend Axis types (SID's) not used. Stack cleared.\n");
                break;
                
            case 30:    /* ROS */
                          /* UFST does not do anything with the operands:    it just
                               uses the ROS operator to identify a CIDCFF font */
              
                /* sample processing of ROS operands */
                /**************************************
                struct { SL32 r; SL32 o; FPNUM s;} ROS;
                FPNUM fptemp;

                  ROS.r = args[0];
                  ROS.o = args[1];
                  if (fp_arg == 0)
                    ROS.s = args[3];
                  else
                    ROS.s = fpstack[0];
                **************************************/

                DBG("ROS (CID) font\n");
                  if_state.gpps->isCID = TRUE;
                if_state.gpps->FDidx_cur = -1;

                  argsptr = args;
                  fp_arg = 0;
                break;

            case 31:    /* CIDFontVersion */
                          /* UFST does not do anything with this value */
              
                /* sample processing of CIDFontVersion operand */
                /* the value for this opcode can be either int or real:
                     determine which and convert int to real, if needed */
                /**************************************
                FPNUM fptemp;
              
                  if (fp_arg == 0)
                  {
                    FPOP(x1);
                    fptemp = x1;
                  }
                  else
                    fptemp = fpstack[0];
                **************************************/
                
                DBG("CIDFontVersion\n");
                  argsptr = args;
                  fp_arg = 0;
                break;

            case 32:    /* CIDFontRevision */
                          /* UFST does not do anything with this value */
              
                /* sample processing of CIDFontRevision operand */
                /* the value for this opcode can be either int or real:
                     determine which and convert int to real, if needed */
                /**************************************
                FPNUM fptemp;
              
                  if (fp_arg == 0)
                  {
                    FPOP(x1);
                    fptemp = x1;
                  }
                  else
                    fptemp = fpstack[0];
                **************************************/

                DBG("CIDFontRevision\n");
                  argsptr = args;
                  fp_arg = 0;
                break;

            case 33:    /* CIDFontType */
                          /* UFST does not do anything with this value */
              
                  FPOP(x1);
                DBG1("CIDFontType=%d\n", x1);
                  argsptr = args;
                  fp_arg = 0;
                break;

            case 34:    /* CIDCount */
                          /* UFST does not do anything with this value */
              
                  FPOP(x1);
                CIDCount = (SL32)x1;
                DBG1("CIDCount=%d\n",x1);
                  argsptr = args;
                  fp_arg = 0;
                break;

            case 35:    /* UIDBase */
                          /* UFST does not do anything with this value */
              
                FPOP(x1);
                DBG1("UIDBase=%d\n", x1);
                  argsptr = args;
                  fp_arg = 0;
                break;

            case 36:    /* FDArray Offset */
              
                 FPOP(x1);
                DBG1("FDArray Offset=%d\n",x1);
                cf->fontdict.stt = x1 + if_state.gpps->cft.CFFTableOffset;

                  argsptr = args;
                  fp_arg = 0;
                break;
            
            case 37:    /* FDSelect Offset */
            {  
            UL32 FDSelect_off, fpos; 
            UW16 nRanges, tblSize;
            UB8 tmpbuf[4], *pFDSelect;     

                  FPOP(x1);
                DBG1("FDSelect Offset=%d\n",x1);

                FDSelect_off = x1 + if_state.gpps->cft.CFFTableOffset;
                fpos = seekandread(FSA tmpbuf, FDSelect_off, 1);

                switch (tmpbuf[0])
                {
                case 0:
                    DBG1("Format=%d encountered\n", tmpbuf[0]);
                    tblSize = 1 + CIDCount;
                    DBG1("size=%d\n", tblSize);
                    if_state.gpps->hFDSelect = BUFalloc(FSA tblSize);
                    if (!if_state.gpps->hFDSelect)
                    {
                         DBG("ERROR allocating FDSelect\n");
                          return (ERR_cff_FDSelect_mem);
                    }
                    pFDSelect = MEMptr(if_state.gpps->hFDSelect);
                    fpos = seekandread(FSA pFDSelect,  FDSelect_off, tblSize);
                    break;

                case 3:
                    DBG1("Format=%d encountered\n", tmpbuf[0]);
                    fpos = seekandread(FSA tmpbuf, FDSelect_off, 3);
                    nRanges = *(tmpbuf+1);
                    nRanges = ((nRanges << 8) | *(tmpbuf+2));
                       tblSize = 3 + (3 * nRanges) + 2;
                    DBG2("number of ranges=%d size=%d\n", nRanges, tblSize);

                    if_state.gpps->hFDSelect = BUFalloc(FSA tblSize);
                    if (!if_state.gpps->hFDSelect)
                    {
                         DBG("ERROR allocating FDSelect\n");
                          return (ERR_cff_FDSelect_mem);
                    }
                    pFDSelect = MEMptr(if_state.gpps->hFDSelect);
                    fpos = seekandread(FSA pFDSelect,  FDSelect_off, tblSize);
                    break;

                default:
                    DBG1("Unknown format=%d\n", pFDSelect[0]);
                    return (ERR_cff_FDSelect_fmt);
                }

#ifdef AGFADEBUG
                dump_FDSelect(FSA0);
#endif
            }
                argsptr = args;
                  fp_arg = 0;
                break;

            case 38:    /* FontName */
                          /* UFST does not do anything with this value */
              
                  FPOP(x1);
                  DBG1("FontName SID=%d\n",x1);

                  argsptr = args;
                  fp_arg = 0;
              
                break;
                            
            case 39:        /* Top Dict (# 39) 0x27 Chameleon font          */
                DBG("Chameleon font \007\n");
                return ERR_cff_Chamel_notsupp;  
                
            default:
                  DBG2("ERROR: Reserved \007 opcode 12-%d arg cnt %d\n", tmp, argsptr-args);
                break;
            } /* ----- end  of 2-byte opcodes  --------- */
            break;
            
        case 13:   /* Unique ID */
            FPOP(x1);
            DBG1("Adobe unique ID # \n", x1);
            fp_arg = 0;    /* reset the floating point stack */
            break;
            
        case 14:  /* XUID array */ 
            stackcnt = argsptr - args;
            DBG1("XUID with %d args. Vals equal weights in MM fonts \n", stackcnt);
            argsptr = args;             /* clear the stack */
            fp_arg = 0;    /* reset the floating point stack */
            break;
            
        case 15:  /* charset file Position */ 
            if(argsptr > args)
            {
                FPOP(x1);
                fp_arg = 0;    /* reset the floating point stack */
            }
            if(x1 <= 0)
               return ERR_cff_bad_charset;

            cf->charset.stt = x1 + if_state.gpps->cft.CFFTableOffset;    /* added 'CFFTableOffset'  05-23-01 jfd */
            DBG1("Charset file position %d\n", x1);
            break;
            
        case 16:  /* Encoding file position */ 
            FPOP(x1);
            fp_arg = 0;    /* reset the floating point stack */
            if(x1 <= 0)
                return ERR_cff_bad_encode;
            cf->encoding.stt = x1 + if_state.gpps->cft.CFFTableOffset;    /* added 'CFFTableOffset'  05-23-01 jfd */
            DBG1("Encoding file position %d\n", x1);
            break;
            
        case 17:  /* CharStrings file position */
            FPOP(x1);
            DBG1("CharStrings file position %d\n", x1);
            fp_arg = 0;    /* reset the floating point stack */
            if(x1 <= 0)
                return ERR_cff_bad_str_pos;
            cf->charstrings.stt = x1 + if_state.gpps->cft.CFFTableOffset;    /* 05-23-01 jfd */
            break;
            
        case 18:  /* Private DICT size and file position */
        {
            MEM_HANDLE m;
            LPUB8 buffer;     /* pointer for private DICT data buffer   */
            SL32 nread;
            FPOP(x1);
            x1 += if_state.gpps->cft.CFFTableOffset;    /* 05-23-01 jfd */
            FPOP(x2);
            fp_arg = 0;    /* reset the floating point stack */
            
            /*----- make recursive call to topdict for private.      */
            m = BUFalloc(FSA x2);
            if(!m)
                return ERR_cff_no_dict_mem;
            buffer = (LPUB8) MEMptr(m);
            
            nread = seekandread(FSA buffer, x1, x2);
            if(nread != x2)
                return ERR_cff_bad_read;
#if 1    /* 05-23-01 jfd */
            cf->private_DICT_offset = x1;
#endif    /* 05-23-01 jfd */
            DBG2("Private DICT read %d bytes from %d\n", x2, x1-1);
            status = cff_readDICT(FSA cf, (LPUB8)buffer, 0, (UL32)(x2));
            BUFfree(FSA m);
            if (status)
                return status;
            break;
        }            
        case 19:  /* localsubrs file position */
            FPOP(x1);
            cf->localsubrs.stt = x1 + cf->private_DICT_offset;    /* added 'cf->private_DICT_offset'  05-23-01 jfd */
            DBG1("localsubrs file position %d\n", x1);
            fp_arg = 0;    /* reset the floating point stack */
            break;
            
        case 20:  /* defaultWidthX (private) number */
            FPOP(x1);
            if_state.gpps->defaultWidthX = (SW16)x1;  
            DBG1("defaultWidthX %d\n", x1);
            fp_arg = 0;    /* reset the floating point stack */
            break;
            
        case 21:  /* normalWidthX (private) number */
            FPOP(x1);
            if_state.gpps->normalWidthX = (SW16)x1;  
            DBG1("normalWidthX %d\n", x1);
            fp_arg = 0;    /* reset the floating point stack */
            break;
            
        case 28:  /* shortint number */
            x1 = tmp = GETECHAR ();
            x2 = tmp = GETECHAR ();
            x3 = (x1 << 8) + x2;
            DBG1("push: %d (shortint)\n", x3);
            FPUSH(x3);
            break;
            
        case 29:  /* longint number always followed by 4 bytes.*/  
            
            x1 =  GETECHAR();  x1 <<= 8;
            x1 += GETECHAR();  x1 <<= 8;
            x1 += GETECHAR();  x1 <<= 8;
            x1 += GETECHAR();
            DBG1("push: %d (longint)\n", x1);
            FPUSH(x1);
            break;
            
        case 30:  /* BCD (real) number from Tech Note #5176 pg 4-5.*/ 

#if 0    /* 03-19-99 jfd DISABLE FOR NOW */
            /* 02-18-99 jfd
             * The SyntheticBaseFont code that follows may require some
             * changing in order to work!!!
             * 02-18-99 jfd
             */
            if(SyntheticBaseFont && (argsptr-args > 0) && (*(argsptr-1) == 0) )
            {   /*  duplicate any zeros for synthetic font matrix */
                while((*(argsptr-1) == 0) && fp_arg < 6)
                {
                    fpstack[fp_arg++] = fpint2fp(0);
                    DBG1("push FP stack: %f\n", fpstack[fp_arg-1]);
                    argsptr--;
                    if(argsptr <= args)
                        break;
                }
            }
#endif    /* 03-19-99 jfd */

#if 1    /* 03-19-99 jfd */

            /* The 'FontMatrix' operands can be a combination of both
             * integer and floating point values, and can appear in any
             * order. Since the integer stack is populated both by us (via the
             * 'fpush()' call at the end of this section of code) and by 
             * normal postscript processing, we need a way of identifying
             * what elements postscript has put on the stack since this must be 
             * copied to the floating point stack. The value 'args_offset'
             * points to the next element of the integer stack which is to be
             * copied to the floating point stack. Therefore, if the integer 
             * stack has something on it, copy everything starting at position
             * 'args_offset' to the floating point stack.
             */

             stackcnt = argsptr - args;
             if (stackcnt > 0)
             {
                tmp = args_offset;
                while (tmp < stackcnt)
                {
                   fpstack[fp_arg++] = fpint2fp(args[tmp]);
                   tmp++;
                }
             }

#endif /* 03-19-99 jfd */

             /* Initialize the string buffer every time an opcode 30 is processed
              * 06-14-01 jfd
              */
            MEMSET (BCDbuffer, '\0', sizeof (BCDbuffer));
            tmp = y1 = x1 = 0;      /* x1 = nibble, y1 = count */
            do
            {
                if(y1++ & 1)        /* part two */
                    x2 = tmp & 0xf;
                else                /* part one */
                {
                    tmp = GETECHAR();
                    x2 = tmp >> 4;
                }
                if(x2 == 0x0F)
                    break;
                
                    /*  first, we make a string from variable length of     */
                    /*  packed bytes, each holding 2 digits or chars        */
                BCDbuffer[y1] = "0123456789.EE?-?"[x2];
                if (x2 == 0xc)
                    BCDbuffer[y1] = '-';  /* 'E-' is exception */
                
            } while(y1 < 64);    /* swag at max length to avoid runaways    */
            
            /* now, convert the sring to a real value                       */
            /* we skipped the first byte when loading, so add 1 to start    */
            fpstack[fp_arg++] = fpatof((LPSB8)(BCDbuffer + 1)); /* result stored on fpstack. */

            /* 05-23-01 jfd Increased from 8 to 12 */

            FPUSH( fp2word(fpstack[fp_arg-1]) );
#if 1    /* 03-19-99 jfd */
            args_offset = fp_arg;
#endif    /* 03-19-99 jfd */
            DBG1("push FP stack: %f\n", fpstack[fp_arg-1]);
            
            break;
        case 31:  /* special 'T2' operator. Changes states. The following   */
            /* data will be interpreted as Type2 Charstring (not DICT)      */
            /* until the next 0x0E (endchar) is reached. The state will     */
            /* then revert to reading DICT operators and operands. During   */
            /* this state, there is a whole host of charstring operators    */
            /* that are invalid. Tech note #5176, (15 Oct 97)  pg 24        */
            /* this state can leave data of the stack for the next Dict     */
            /* operator.   Used in Mult Master fonts.                       */
            {
                SL32 len = lastdata - edata;
                struct char_info dummy = { 1, 1, 1, 0, 0, 0, 0, };
                
                dummy.args = args;              /* pass the arg stack       */
                dummy.argcnt = argsptr-args;    /* and pointer count        */
                
                status = readT2charstring(FSA &edata, len, &dummy);
                if(status)
                    return status;
                argsptr = args + dummy.argcnt;  /* retrieve new arg cnt     */
            }
            break;
        default:
            DBG3("ERROR: \007 DICT opcode %d arg cnt %d pos %d\n", 
                opcode, argsptr-args, lastdata - edata);
            argsptr = args;             /* this function clears stack       */
            /*    return ERR_cff_no_support; */
            break;
        }
    } 
    return 0;
} /* ---------------------------------------------------------------------*/
 
   
/* ------------------------------------------------------------------------ 
 * cff_read_MM (FSP SL32* args, SW16 stackcnt)
 * 
 * do initial CFF Multi Master setup. Start with 5 args on stack and 
 * use to create the gpps->weights[] used later by  blend routine.
 * ------------------------------------------------------------------------ */
MLOCAL SW16 cff_read_MM (FSP struct char_info* thischar)
{
    SL32  cnt, SID_NDV, SID_CDV,  status = 0;
    LPSL32 args; 
    LPSL32 argsptr;
    LPSL32 dest;
    BOOLEAN default_instance;
    SL32 one;
    MEM_HANDLE m;
    
    args = thischar->args;
    argsptr = args + thischar->argcnt;
    
    /* length of transient build char array (BCA) */
    thischar->BCAsize = args[thischar->argcnt-3];  

    m = BUFalloc(FSA (SL32)(thischar->BCAsize * sizeof(SL32)));
    if(!m)
        return ERR_cff_no_readmm_mem;
    thischar->BCA = (LPSL32)MEMptr(m);

    if_state.gpps->Weightvals = args[0];         /* first arg is # masters  */
    if_state.gpps->MMnaxes = (thischar->argcnt - 4); /* 2 to (tot-3) is UDV */

    default_instance = (if_state.fcCur.userDesignVector[0] == -1);
getweights:
    for(dest = if_state.gpps->UserDV, cnt = 0; cnt < if_state.gpps->MMnaxes; cnt++)
    {
        if(default_instance)
            *dest++ = args[cnt+1]; /* move default User Design Vector values to UDV */
        else
            *dest++ = if_state.fcCur.userDesignVector[cnt];
    }
    
    SID_NDV = args[thischar->argcnt-2];      /* StringID for NDV string */
    SID_CDV = args[thischar->argcnt-1];      /* StringID for CDV string */
    
    DBG1("\nSubroutine Normalized Design Vector SID %d\n", SID_NDV);
    
    DBG4("UDV values, %d %d %d %d\n", if_state.gpps->UserDV[0], if_state.gpps->UserDV[1],
        if_state.gpps->UserDV[2], if_state.gpps->UserDV[3]);

    /*----- locate, get and execute type2 charstring (disgused subroutine) */
    status = processSID(FSA &if_state.gpps->cft, SID_NDV, thischar);
    if(status)
        goto done;


                                          /* test NDV for two out of range values */
    for(one = cnt = 0; cnt < if_state.gpps->MMnaxes; cnt++)
    {
        if(if_state.gpps->NormDV[cnt] > 0x20000       /* this is one in 16.16 format */
            || if_state.gpps->NormDV[cnt] < 0)
        {
            DBG1("\007NDV val out of range, %d", if_state.gpps->NormDV[cnt]);
            default_instance = TRUE;
            goto getweights;
        }
    }
    
 

    DBG4("NVD values, %d %d %d %d\n", if_state.gpps->NormDV[0], if_state.gpps->NormDV[1],
        if_state.gpps->NormDV[2], if_state.gpps->NormDV[3]);
    DBG1("\nSubroutine Convert Design Vector SID %d\n", SID_NDV);
    
    /*----- locate, get and execute type2 charstring (disgused subroutine)  */
    status = processSID(FSA &if_state.gpps->cft, SID_CDV, thischar);
    if(status)
        goto done;

    DBG4(" with weight values %d %d %d %d\n", if_state.gpps->weights[0],
        if_state.gpps->weights[1], if_state.gpps->weights[2], if_state.gpps->weights[3]);
    DBG("========================================================\n");

    /* This is to protect against out of range user design vector.
     * The weight vector vals should all be between 0 and 1 and
     * sum to 1.
     */
    for(cnt = 0; cnt < if_state.gpps->Weightvals; cnt++)
        if(if_state.gpps->weights[cnt] < 0  ||
           if_state.gpps->weights[cnt] > (SL32)0x10000)
        {
            default_instance = TRUE;
            DBG1("\007Weight vector val out of range, %d", if_state.gpps->weights[cnt]);
            goto getweights;
        }
    for(one = cnt = 0; cnt < if_state.gpps->Weightvals; cnt++)
        one += if_state.gpps->weights[cnt];
    if(one<65535 || one > 65537)
    {
        default_instance = TRUE;
        DBG1("\007Total of Weight vectors out of range, %d", one);
        goto getweights;
    }
    /* Remember input DV */
    for(cnt = 0; cnt < if_state.gpps->MMnaxes; cnt++)
        if_state.gpps->inputDV[cnt] = if_state.fcCur.userDesignVector[cnt];

done:
    BUFfree(FSA m);                /* free temp area     */

    return status;
} /* ---------------------------------------------------------------------- */
   
   
/* ------------------------------------------------------------------------ 
 * processSID(FSP cft* cf, SW32 SID)
 *
 * called by cff_read_MM to process charstrings stored in the string index
 * 
 * Similar to subroutines, but only called from the topDICT.
 * Makes recursive call to topDICT
 *
 * 1. Locate the String ID containing the MM type2 charstring 
 * 2. allocate a buffer on the heap and read it into the buffer
 * 3. call the cff_readDict to process the charstring
 * 4. free the buffer
 * ------------------------------------------------------------------------ */
MLOCAL SW16 processSID(FSP cft* cf, SL32 SID, struct char_info* thischar)
{
    SL32 status;
    LPUB8 dictbuf;
    LPUB8 copyptr;
    SL32 buflen = 0; 
    MEM_HANDLE m;
    
    
    SID -= 390;         /* 1-390 = Adobe standard strings */
    if(SID < 1) 
        return ERR_cff_bad_SID_val;
    
    /*----- find selected SID */
    status = getStringData(FSA NULL, &buflen, &cf->strings, SID);
    if(status)
        return ERR_cff_get_string_data;
    m = BUFalloc(FSA buflen);
    if(!m)
        return ERR_cff_no_dict_mem;
    copyptr = dictbuf = (LPUB8) MEMptr(m);

    status = getStringData(FSA dictbuf, &buflen, &cf->strings, SID);
    if(status)
        goto done;
    
    status = readT2charstring(FSA &dictbuf, buflen, thischar);
    
done:
    BUFfree(FSA m);  /* use copyptr to free as dictbuf modified by read    */
    
    return status;
} /* ---------------------------------------------------------------------- */
    

#ifdef AGFADEBUG
MLOCAL VOID dump_FDSelect(FSP0)
{
    UB8 *pFDSelect, *pcur, fdIdx;
    UW16 nRanges, idx, first, sentinel, tblSize; 
    UW16 status;
    cft* cf = &if_state.gpps->cft;    

    pFDSelect = MEMptr(if_state.gpps->hFDSelect);
    switch (pFDSelect[0])
    {
    case 0:
        DBG1("Format=%d encountered\n", pFDSelect[0]);

        /* Extract glyph count from the count field in the
         * charstrings INDEX
         */

        status = gethead(FSA &cf->charstrings, cf->charstrings.stt);
        if(status)
        {
            DBG1("Format=%d not processed yet\n", pFDSelect[0]);
            break;
        }

           tblSize = 1 + cf->charstrings.items;
        DBG2("number of glyphs=%d size=%d\n", cf->charstrings.items, tblSize);
        pcur = pFDSelect + 1;

        for (idx=0; idx<cf->charstrings.items; idx++)
        {
            fdIdx = *pcur++;
            DBG2("...glyph %d: FD index=%d\n", idx, fdIdx);
        }
        break;

    case 3:
        DBG1("Format=%d encountered\n", pFDSelect[0]);
        nRanges = *(pFDSelect+1);
        nRanges = ((nRanges << 8) | *(pFDSelect+2));
           tblSize = 3 + (3 * nRanges) + 2;
        DBG2("number of ranges=%d size=%d\n", nRanges, tblSize);
        pcur = pFDSelect + 3;

        for (idx=0; idx<nRanges; idx++)
        {
            first = *pcur++;
            first = ((first << 8) | (*pcur++));
            fdIdx = *pcur++;
            DBG3("...entry %d: 1st idx=%d FD index=%d\n", idx, first, fdIdx);
        }
        sentinel = *pcur++;
        sentinel = ((sentinel << 8) | (*pcur++));
        DBG1("sentinel GID=%d\n\n",sentinel);
          break;

    default:
        DBG1("Unknown format=%d\n", pFDSelect[0]);
        break;
    }
}
#endif    /* AGFADEBUG */

#endif /* CFF_RDR */   
 

cffproto.h   /

/* 
 * Copyright (C) 2004 Agfa Monotype Corporation. All rights reserved.
 */
/*
* cffproto.h       
*   Requires 'ufstport.h' 
*/
/* $Header:   I:/BULL/URIP/RTS/PSI/CFFPROTO.H_V   1.19   Oct 19 2004 11:33:50   galejss  $ */
/* $Log:   I:/BULL/URIP/RTS/PSI/CFFPROTO.H_V  $
 * 
 *    Rev 1.19   Oct 19 2004 11:33:50   galejss
 * make "gethead" a global function
 * 
 *    Rev 1.18   Sep 27 2004 16:21:16   dugganj
 * Added multithread support.
 * 
 *    Rev 1.17   Aug 22 2003 09:19:24   LynchR
 * Updated copyright notice.
 * 
 *    Rev 1.16   Jul 28 2003 17:53:54   Galejs
 * get rid of psf_open(), psf_close()
 * 
 *    Rev 1.15   Jul 23 2003 17:34:08   Galejs
 * move "hexasc" enum to if_type.h
 * 
 *    Rev 1.14   Jul 21 2003 18:47:32   Galejs
 * reentrancy / debug change
 * 
 *    Rev 1.13   Jun 20 2003 14:17:14   Galejs
 * get rid of asserts
 * 
 *    Rev 1.12   Sep 23 2002 13:57:36   Galejs
 * test for multiple includes (part of bug # 76)
 * 
 *    Rev 1.11   18 Feb 1999 18:07:36   DAVID
 * Uncoupled CFF processing from USE_UFST_MAPPING.
 * 
 *    Rev 1.10   28 Sep 1998 13:32:24   DAVID
 * Added new prototype for 'set_escapement()'.
 * 
 *    Rev 1.9   31 Aug 1998 18:55:28   GALEJS
 * getStringData() needs FSP, while getSubBias() doesn't
 * 
 *    Rev 1.8   26 Aug 1998 00:39:52   DAVID
 * Updates for reentrancy.
 * 
 *    Rev 1.7   24 Aug 1998 22:51:52   DAVID
 * Updated params in 'getSubBias()' for reentrancy.
 * 
 *    Rev 1.6   10 Aug 1998 11:43:58   AL
 * Check error returns and clean up // comments
 * 
 *    Rev 1.5   06 Aug 1998 16:25:00   AL
 * 
 * CFF rom, multiple master and bug fixes
 * 
 *    Rev 1.4   27 Jul 1998 15:35:32   AL
 * Moved structures to ix.h
 * 
 *    Rev 1.3   24 Jul 1998 15:10:48   GALEJS
 * remove incorrect EXTERN declarations
 * 
 *    Rev 1.2   20 Jul 1998 16:43:04   AL
 * Added nameInSet to cft structure
 * 
 *    Rev 1.1   08 Jul 1998 14:10:00   DAVID
 * Added PVCS Change History tracking for original source.
 * 
 */


/*
REVISION HISTORY
------------------------------------------------------------------------------
08-Jul-98  dlk    Original version placed under PVCS control.  Added this REVISION
                HISTORY
24-Jul-98  slg    Remove incorrect/unnecessary EXTERN dcls for type1/2char(),
                BUFalloc/free()    
27-Jul-98  awr  Moved structure definitions to ix.h
24-Aug-98  dlk  Updated params of 'getSubBias()' for reentrancy.
31-Aug-98  slg    getStringData() needs FSP, getSubBias() doesn't
28-Sep-98  dlk Added prototype for new function 'set_escapement()'.
18-Feb-99  dlk Removed prototype for 'free_encoding', and coupling to USE_UFST
               _MAPPING.
------------------------------------------------------------------------------
*/

#ifndef __CFFPROTO__
#define __CFFPROTO__

GLOBAL VOID estart (FSP LPUB8, SL32); 
GLOBAL VOID free_charstrings (FSP PPS_BUCK);
GLOBAL VOID free_subrs (FSP PPS_BUCK);

#define MOVETO(x,y)  (t1moveto (FSA x, y))
#define LINETO(x,y)  (t1lineto (FSA x, y))
#define CURVETO(x1,y1,x2,y2,x3,y3) (t1curveto (FSA x1, y1, x2, y2, x3, y3))
#define CLOSEPATH() (savex = if_state.gpps->psiw.curx, savey = if_state.gpps->psiw.cury, t1closepath(FSA0), t1moveto (FSA savex, savey))    /* 08-27-04 jfd */
#define ENDCHAR()  t1endchar (FSA0)

struct char_info
{
    SL32 curx;        /* current X    */
    SL32 cury;        /* current Y    */
    SL32 path;        /* flag when t1closepath() called            */
    LPSL32 args;    /* argument stack NULL if not allocated        */
    SL32 argcnt;    /* number of args on passing / returning    */
    SL32 BCAsize;    /* build character array length    needed        */
    LPSL32 BCA;        /* bca storage pointer, NULL if not used    */
} ;


GLOBAL VOID set_escapement(FSP SL32 escapement);
GLOBAL SL32 cff_get_charstrings(FSP SL32 nchars, SL32 pos);
GLOBAL UW16 cff_readDICT(FSP cft* cf, LPUB8 edata, UL32 dictstt, UL32 dictlen);
GLOBAL UW16 cffsetup(FSP  SL32 headsize, SL32 aos );
GLOBAL UW16 Cff_Set_Char(FSP UW16 chId);
GLOBAL SL32 type2char(FSP PCDATASTR cptr, SL32 wflag);
GLOBAL SL32 readT2charstring(FSP LPUB8* data, SL32 len, struct char_info *thischar);
GLOBAL SL32 GetTopDICT(FSP cft* cf, SL32 face);
GLOBAL VOID top_blues (FSP LPSW16 vals, SL32 n);
GLOBAL VOID bot_blues (FSP LPSW16 vals, SL32 n);
GLOBAL UW16 nextopcode(FSP LPUB8* PPdata, SL32* args, LPSL32* aptr);   
GLOBAL SL32 variablevalue(LPUB8 data, SL32 step);
GLOBAL SL32 seekandread(FSP LPUB8 buf, SL32 stt, SL32 len);
GLOBAL SL32 gethints(FSP LPUB8* edata);
GLOBAL SL32 exitloop(FSP struct char_info *thischar);
GLOBAL VOID unload_cff_font(FSP PPS_BUCK);
GLOBAL SL32 roundFixPt2int(SL32 val);
GLOBAL SL32 wholeFixPt2int(SL32 val);
GLOBAL SL32 int2fixpt(SL32 val);
GLOBAL SL32 getStringData(FSP LPUB8 buf, LPSL32 len, cfix* obj, UL32 index);
GLOBAL SL32 getSubBias(SL32 globalitems);

GLOBAL SL32 psf_read(FSP  LPUB8 buf, SL32 cnt);
GLOBAL SL32 psf_seek(FSP  SL32 pos, SL32 seektype);
GLOBAL SL32 gethead(FSP cfix* fill, SL32 stt);

#endif    /* __CFFPROTO__ */
 

cffsetup.txt  //

/* 
 * Copyright (C) 2004 Agfa Monotype Corporation. All rights reserved.
 */
/*
* cff_setup.c   Reads the CFF font headers, locating key elements of font
* then calls cff_readDICT() to get global font information to bucket.
* called from t1_setup when cff font detected. Replaces t1_setup actions.
*/
/* $Header:   I:/BULL/URIP/RTS/PSI/CFFSETUP.C_V   1.44   Dec 03 2004 17:10:38   galejss  $ */
/* $Log:   I:/BULL/URIP/RTS/PSI/CFFSETUP.C_V  $
 * 
 *    Rev 1.44   Dec 03 2004 17:10:38   galejss
 * changes to dump_FDIndex() for INT_MEM_MGT
 * 
 *    Rev 1.43   Nov 18 2004 08:23:54   dugganj
 * In dump_FDIndex(), replaced static arrays "buf" and "buffy"
 * with dynamic ones.
 * 
 * 
 *    Rev 1.42   Oct 19 2004 12:05:38   galejss
 * if processing a CID-in-CFF font, read in its fontdict index
 * 
 *    Rev 1.41   Jul 16 2004 13:53:18   galejss
 * modify seekandread(0 so that it works for mixed disk/rom builds
 * 
 *    Rev 1.40   Oct 17 2003 15:17:42   Galejs
 * fix 2 STRNCPY compiler warnings
 * 
 *    Rev 1.39   Sep 25 2003 16:13:32   Galejs
 * replace memset() by MEMSET(), for portability
 * 
 *    Rev 1.38   Aug 22 2003 09:19:24   LynchR
 * Updated copyright notice.
 * 
 *    Rev 1.37   Aug 08 2003 12:32:32   Galejs
 * move #if / #endif to column 1 (fix Sun compile error)
 * 
 *    Rev 1.36   Jul 23 2003 16:30:50   Galejs
 * if NameInCFF field is NULL, just use 1st font in CFF (bug # 113)
 * 
 *    Rev 1.35   Jun 23 2003 15:23:04   Galejs
 * ufstport.h; VOID
 * 
 *    Rev 1.34   04 Jun 2001 10:23:20   JOE
 * OpenType changes.
 * 
 *    Rev 1.33   May 21 2001 19:55:32   Galejs
 * cleaner implementation of CFF_ROM
 * 
 *    Rev 1.32   May 04 2001 14:11:12   Galejs
 * data-type cleanup
 * 
 *    Rev 1.31   15 Feb 2000 09:38:08   JOE
 * Removed CTRL characters at end of file (by aof).
 * 
 *    Rev 1.30   10 Feb 2000 15:38:20   AL
 * Removed PST1_ROM
 * 
 *    Rev 1.29   08 Oct 1999 15:32:06   AL
 * Fixed array overrun when building custom character sets formats 1 & 2
 * 
 *    Rev 1.28   Aug 13 1999 16:11:58   galejs
 * include-file changes
 * 
 *    Rev 1.27   13 Apr 1999 22:57:06   DAVID
 * Minor changes to size of local buffers for reading in
 * Encoding and Charset arays.
 * 
 *    Rev 1.26   26 Feb 1999 11:32:28   DAVID
 * In GetTopDICT(), fixed call to cff_readDICT() by subtracting
 * 1 from buflen as it is passed in (as the len argument).
 * 
 *    Rev 1.25   22 Feb 1999 10:02:52   JOE
 * In cffsetup(), moved the initialization of "if_state.gpps->hcffencodearray"
 * and "if_state.gpps->hcharsetarray" to NIL_MH to the beginning of the
 * function. (GetTopDICT() will be testing for NIL_MH).
 * 
 *    Rev 1.24   18 Feb 1999 18:24:24   DAVID
 * Initialized CFF hcffencodearray and hcharsetarray to NIL_MH.
 * 
 *    Rev 1.23   18 Feb 1999 08:32:44   DAVID
 * Eliminated both 'if check' conditions involving Casts made
 * yesterday (17-Feb).
 * 
 *    Rev 1.22   17 Feb 1999 15:53:36   DAVID
 * Added 2 cases of SL32 Casts, to eliminate degenerate comparisons
 * of UL32 with 0.
 * 
 *    Rev 1.21   16 Feb 1999 21:51:10   DAVID
 * Repaired Custom Encoding Array building logic for format 1.
 * 
 *    Rev 1.20   09 Feb 1999 14:05:16   GALEJS
 * remove unused includes
 * 
 *    Rev 1.19   02 Feb 1999 23:12:26   DAVID
 * General cleanup of comments.
 * 
 *    Rev 1.18   02 Feb 1999 16:19:16   DAVID
 * Fixed typo in calculation of Custom Encoding Array size.
 * 
 *    Rev 1.17   29 Jan 1999 10:45:58   DAVID
 * Made CFF Encoding Arrays 2 Bytes wide.
 * 
 *    Rev 1.16   21 Jan 1999 17:51:16   GALEJS
 * standardize #include tests
 * 
 *    Rev 1.15   20 Jan 1999 14:27:10   DAVID
 * Correcting last PVCS comment - In cffsetup(), added
 * code to build charset array and updated code to handle
 * encoding array building.  In preparation for glyph
 * access via SIDs and PS character name strings.
 * 
 *    Rev 1.14   20 Jan 1999 14:11:34   DAVID
 * Changed Cff_Set_Char() to handle NO_SYMSET_MAPPING and
 * CFFENCODING options.
 * 
 *    Rev 1.13   16 Sep 1998 20:07:14   GALEJS
 * get rid of obsolete MIPS case
 * 
 *    Rev 1.12   15 Sep 1998 14:01:04   JOE
 * Changed include reference from cffProto.h to cffproto.h
 * for SUN - SPARC usage (by jwd).
 * 
 *    Rev 1.11   10 Sep 1998 19:02:00   GALEJS
 * compiler fixes (2 casts, 1 typechange)
 * 
 *    Rev 1.10   31 Aug 1998 19:05:46   GALEJS
 * add reentrancy arg to getStringData() calls
 * 
 *    Rev 1.9   26 Aug 1998 00:43:50   DAVID
 * Updates for reentrancy.
 * 
 *    Rev 1.8   24 Aug 1998 21:54:14   DAVID
 * Fixed compiler warning, changed BUFalloc calls for reentrancy.
 * 
 *    Rev 1.7   10 Aug 1998 11:44:04   AL
 * Check error returns and clean up // comments
 * 
 *    Rev 1.6   06 Aug 1998 16:24:54   AL
 * CFF rom, multiple master and bug fixes
 * 
 *    Rev 1.5   27 Jul 1998 15:26:34   AL
 * Internal floating point support
 * 
 *    Rev 1.4   27 Jul 1998 10:31:08   AL
 * Added internal memory management suppport
 * 
 *    Rev 1.3   20 Jul 1998 15:21:24   AL
 * removed extern fontcontext and saved CFF nameInSet
 * 
 *    Rev 1.2   10 Jul 1998 10:41:12   AL
 * Conditional compile entire file on CFF_RDR
 * 
 *    Rev 1.1   08 Jul 1998 14:14:14   DAVID
 * Added PVCS Change History tracking for original source.
 * 
 */


/*
REVISION HISTORY
------------------------------------------------------------------------------
08-Jul-98 dlk Original version placed under PVCS control.  Added this REVISION
              HISTORY
24-Aug-98 dlk In 'cffsetup()' changed SL32 fpos, to UL32 fpos to eliminate
              compile time warning.
24-Aug-98 dlk Changed BUFalloc calls for reentrancy.
31-Aug-98 slg Add 'FSA' to getStringData() calls
15-Sep-98 jwd Changed reference from cffProto.h to cffproto.h for Sun/SPARC
              usage.
20-Jan-99 dlk In cffsetup(), added code to build charset array, and changed
              code to handle encoding array building in preparation for
              access to glyphs via SIDs and PS character name strings.
29-Jan-99 dlk Made CFF Encoding Arrays 2 Bytes wide (UW16).
02-Feb-99 dlk Fixed typo in calculation of Custom Encoding Array size.
02-Feb-99 dlk General comment cleanup.
16-Feb-99 dlk Replaced Custom Encoding Array setup (case 1), and adjusted loop
              terminatin conditins for Custom Encoding and Custom Charset.
17-Feb-99 dlk Added SL32 Cast for UL32 comparisons to 0 (eliminate degenerate
              cases).
18-Feb-99 dlk Deleted 'if checks' for both cases Cast yesterday (17-Feb).
18-Feb-99 dlk Initialize hcffencodearray and hcharsetarray to NIL_MH.
22-Feb-99 jfd/dlk
              In cffsetup(), moved the statements which initialize
              "if_state.gpps->hcffencodearray" and "if_state.gpps->hcharsetarray"
              to NIL_MH to the beginning of the function. (GetTopDICT() will
              test them for NIL_MH.)
26-Feb-99 dlk In GetTopDICT(), call to cff_readDICT() - decremented the length
              argument by 1 because getStringData() returns length assuming a
              NULL terminated string rather than a buffer of numeric data values.
13-Feb-99 dlk Minor changes to the size of local buffers for custom arrays.
08-Oct-99 awr Fixed array over runs in custom character sets formats 1 and 2
10-Feb-00 awr Removed PST1_ROM
21-May-01 slg Cleaner implementation of CFF_ROM - seekandread()    now has
                separate cases for CFF_ROM and CFF_DISK
23-May-01 jfd OpenType changes:
              In cffsetup(), adjusted offset to font index by offset to CFF table.
              In same function, store first fontname found in 'nameInSet' field
              for OpenType CFF fonts.
              In same function, load INDEX data for localsubrs.
              In same function, disabled call to cff_get_charstrings() - moved to
              Cff_Set_Char().
------------------------------------------------------------------------------
*/

#include "cgconfig.h"

#if CFF_RDR    /* conditionally compile entire file */
#ifdef VXWORKS
#include "vxWorks.h"
#endif

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

#include "ufstport.h" 

#if MAYBE_FCNTL_H
#include <fcntl.h>
#endif

#if MAYBE_FCNTL_HIF_H
#include <fcntl.h>
#include <hif.h>  /* 2-7-94 jfd */
#endif

#if MAYBE_IO_H
#include <io.h>         /* close() */
#endif

#if MAYBE_UNISTD_H
#include <unistd.h>
#endif

#if MAYBE_MALLOC_H
#include    <malloc.h>
#endif

#include <stdlib.h> /* need for 'abort()' i.e. ASSERT */

#include "dbg_ufst.h"

#include "shareinc.h"
#include "mixmodel.h"

#include "t1itype1.h"
#include "t1isyntx.h"
#include "t1iproto.h"
#if PST1_SFNTI
#include "t1isfnt.h"
#endif

#include "cffproto.h"


/* Adobe Predefined Encoding Arrays */

struct cffencodings /* used to build the Adobe Standard Predefined Encoding arrays */
{
    UW16  code;
    UW16  SID; 
    UW16  end;
} CFF_Standard_Encoding[] = {
     32,   1, 126,
    161,  96, 175,
    177, 111, 180,
    182, 115, 189,
    191, 123, 191,
    193, 124, 200,
    202, 132, 203,
    205, 134, 208,
    225, 138, 225,
    227, 139, 227,
    232, 140, 235,
    241, 144, 241,
    245, 145, 245,
    248, 146, 251,
      0,   0,   0        /* end of array flag */
};


struct cffencodings CFF_Expert_Encoding[] = {
     32,    1,  32,
     33,  229,  34,
     36,  231,  43,
     44,   13,  46,
     47,   99,  47,
     48,  239,  57,
     58,   27,  58,
     59,   28,  59,
     60,  249,  63,
     65,  253,  69,
     73,  258,  73,
     76,  259,  79,
     82,  263,  84,
     86,  266,  86,
     87,  109,  88,
     89,  267,  91,
     93,  270, 126,
     161, 304, 163,
     166, 307, 170,
     172, 312, 172,
     175, 313, 175,
     178, 314, 179,
     182, 316, 184,
     188, 158, 188,
     189, 155, 189,
     190, 163, 190,
     191, 319, 197,
     200, 326, 200,
     201, 150, 201,
     202, 164, 202,
     203, 169, 203,
     204, 327, 255,
       0,   0,   0    
};

/* Adobe Predefined Charset Arrays */

struct cffcharsets  /* Used for Adobe Predefined Standard Charset Arrays */
{
  UW16  csSID;
} CFF_ISOAdobe_Charset[] = {
    1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
   11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
   21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
   31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
   41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
   51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
   61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
   71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
   81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
   91, 92, 93, 94, 95, 96, 97, 98, 99,100,
  101,102,103,104,105,106,107,108,109,110,
  111,112,113,114,115,116,117,118,119,120,
  121,122,123,124,125,126,127,128,129,130,
  131,132,133,134,135,136,137,138,139,140,
  141,142,143,144,145,146,147,148,149,150,
  151,152,153,154,155,156,157,158,159,160,
  161,162,163,164,165,166,167,168,169,170,
  171,172,173,174,175,176,177,178,179,180,
  181,182,183,184,185,186,187,188,189,190,
  191,192,193,194,195,196,197,198,199,200,
  201,202,203,204,205,206,207,208,209,210,
  211,212,213,214,215,216,217,218,219,220,
  221,222,223,224,225,226,227,228,  0            /* 0 signals end - value not uesd */
};

struct cffcharsets CFF_Expert_Charset[] = {
    1,229,230,231,232,233,234,235,236,237,
  238, 13, 14, 15, 99,239,240,241,242,243,
  244,245,246,247,248, 27, 28,249,250,251,
  252,253,254,255,256,257,258,259,260,261,
  262,263,264,265,266,109,110,267,268,269,
  270,271,272,273,274,275,276,277,278,279,
  280,281,282,283,284,285,286,287,288,289,
  290,291,292,293,294,295,296,297,298,299,
  300,301,302,303,304,305,306,307,308,309,
  310,311,312,313,314,315,316,317,318,158,
  155,163,319,320,321,322,323,324,325,326,
  150,164,169,327,328,329,330,331,332,333,
  334,335,336,337,338,339,340,341,342,343,
  344,345,346,347,348,349,350,351,352,353,
  354,355,356,357,358,359,360,361,362,363,
  364,365,366,367,368,369,370,371,372,373,
  374,375,376,377,378,  0                         /* 0 signals end - value not uesd */
};

struct cffcharsets CFF_ExpertSubset_Charset[] = {
    1,231,232,235,236,237,238, 13, 14, 15,
   99,239,240,241,242,243,244,245,246,247,
  248, 27, 28,249,250,251,253,254,255,256,
  257,258,259,260,261,262,263,264,265,266,
  109,110,267,268,269,270,272,300,301,302,
  305,314,315,158,155,163,320,321,322,323,
  324,325,326,150,164,169,327,328,329,330,
  331,332,333,334,335,336,337,338,339,340,
  341,342,343,344,345,346,  0                     /* 0 signals end - value not uesd */
};


MLOCAL VOID cff_default_matrix(FSP0);
#ifdef AGFADEBUG
MLOCAL VOID dump_FDIndex(FSP cft* cf);
#endif

/* ------------------------------------------------------------------------ 
*    cffsetup(FSP)
*
*    fills in the CF structure with information on major areas of CFF font
*   selects the face from the fontset
*   then builds the encoding array
*   then builds the charset array
* ------------------------------------------------------------------------ */
GLOBAL UW16 cffsetup(FSP SL32 headsize, SL32 aos)
{
    SL32    status = SUCCESS;
    UL32    fpos;  
    UB8     buf[1065];   /* long enough for a font name  */
    UL32    fontnumber, cnt, loop1, loop2;
    UW16*    pcffencodearray;
    UW16*   pcffcharsetarray;
    UW16     ix;
    UW16    csSID;
    UW16    first;
    UW16     nLeft;
    UW16    nLeft2;
    cft*    cf;
    SL32    nread;
    
    if_state.gpps->hcffencodearray = NIL_MH;  /* initialize, to be sure */
    if_state.gpps->hcharsetarray = NIL_MH;  /* initialize, to be sure */

    /* allocate charstring array here to hold cft structure */
    cf = &if_state.gpps->cft;
    
    cf->headsize = headsize;
    cf->aos = aos;
    
    /*----- load up cff font info and set file pointer to topdict.  */
    if_state.gpps->lenIV = 0; /* default=no encryption. Top DICT can change */
    
    DBG2("cff setup for %s, id=%d\n", if_state.fcCur.nameInSet,
                                                 if_state.fcCur.font_id);
    
    cff_default_matrix(FSA0);  /* set up default 1-1000 matrix  */
    
    /*----- do font index                                              */
    DBG("READING fonts index\n"); 
    status = gethead(FSA &cf->fonts, cf->headsize + cf->CFFTableOffset);    /* add 'CFFTableOffset' 05-23-01 jfd */
    if(status)
        return status;

    /*----- do top dict index                                           */
    nread = seekandread(FSA buf, cf->fonts.zbase - cf->fonts.step, 8);
    if(nread != 8)
        return ERR_cff_bad_read;

    cnt = variablevalue(buf, cf->fonts.step) - 1;
    DBG("READING dict index\n");  
    status = gethead(FSA &cf->dict, cf->fonts.zbase + cnt);
    if(status)
        return status;

    /*----- do strings index                                            */
    nread = seekandread(FSA buf, cf->dict.zbase - cf->dict.step, 8);
    if(nread != 8)
        return ERR_cff_bad_read;
    cnt = variablevalue(buf, cf->dict.step) - 1;
    DBG("READING strings index\n");          
    status = gethead(FSA &cf->strings, cf->dict.zbase + cnt);
    if(status)
        return status;
    
    /*----- do globalsubrs index                                              */
    nread = seekandread(FSA buf, cf->strings.zbase - cf->strings.step, 8);
    if(nread != 8)
        return ERR_cff_bad_read;


    cnt = variablevalue(buf, cf->strings.step) - 1;
    DBG("READING globalsubrs index\n");             
    status = gethead(FSA &cf->globalsubrs, cf->strings.zbase + cnt);
    if(status)
        return status;
        

    /*----- find the correct font from if_state.fcCur.name     */
    /* NOTE: parse input line in if_state.fcCur for UDV values */
    /* here to add user design vectors on MultiMaster       */
    /* fonts when interface format is finalized. Then       */      
    /* name string for match with internal face name and    */
    /* save values to gpps->UDV[0..3].                      */

    /* if no name specified, use 1st font in CFF */
    if (if_state.fcCur.nameInSet[0] == 0)
    {
    SL32 buflen = 64;

        fontnumber = 1;
        getStringData(FSA buf, &buflen, &cf->fonts, fontnumber);
        STRNCPY(if_state.fcCur.nameInSet, (FILECHAR *)buf, CFFNAMELEN);
        DBG1("null CFF name: using 1st font in CFF=%s\n", if_state.fcCur.nameInSet);
    }
    else
    {
        for(fontnumber = 1; fontnumber <= cf->fonts.items ; fontnumber++)
        {
            SL32 buflen = 64;
            status = getStringData(FSA buf, &buflen, &cf->fonts, fontnumber);
            if(status)
                return status;
        /* OpenType CFF fonts will always use 1st (and only) font in CFF */  
#if TT_RDR
            if (B_ISOTCFF(if_state.gpxb))
                STRNCPY(if_state.fcCur.nameInSet, (FILECHAR *)buf, CFFNAMELEN);
#endif    /* TT_RDR */
            DBG3("Looking for %s. Font# %d = %s\n", if_state.fcCur.nameInSet, fontnumber, buf);
            if(STRNCMP((FILECHAR *)buf, if_state.fcCur.nameInSet, CFFNAMELEN) == 0)
                break;
        }
    }

    if(fontnumber > cf->fonts.items)        /* non-null face name not in fontset    */
    {
        return ERR_cff_bad_face_name;
    }

    cf->name = fontnumber;
    STRNCPY(cf->nameInSet, if_state.fcCur.nameInSet, CFFNAMELEN);

    /*----- find selected font DICT                                     */

    status = GetTopDICT(FSA cf, fontnumber);
    if(status)
        return status;


    if(cf->charstrings.stt == 0)  
        return ERR_cff_bad_str_mem;
    

    DBG("READING charstrings index\n");          
    status = gethead(FSA &cf->charstrings, cf->charstrings.stt);
    if(status)
        return status;

    if (if_state.gpps->isCID)
    {
        /* if this is a CID CFF font, read in the fontdict index now */
        /* the appropriate fontdict (and its PrivateDICT) will be read in on a per-glyphID basis */
     
         DBG("READING fontdict index (for CIDFonts)\n");
         status = gethead(FSA &cf->fontdict, cf->fontdict.stt);

#ifdef AGFADEBUG
        dump_FDIndex(FSA cf);
#endif
    }
    else
    {
        /* if this is a regular (non-CID) CFF font, read in the localsubrs index now */

        DBG("READING localsubrs index\n");      
        status = gethead(FSA &cf->localsubrs, cf->localsubrs.stt);
        if(status)
            return status;
    }
    


/* NOTE:  */
/*       For non-standard fonts, and fonts with encoding supplements, */
/*       the number of entries needed in the Charset array is determined by the value */
/*       in the cf->charstrings.items field */


    /*----- build an array for encoding data */

    /* Predefined Encoding ids:     pg. 15, Adobe Tech Note #5176  */
    /*       0   Standard Encoding - also default  */
    /*       1   Expert Encoding                   */
    /*                                             */
    /* Otherwise Encoding Array will be Custom,    */
    /* that is, from the font.                     */

    

    switch (cf->encoding.stt)
      {

      case 0:     /* use Adobe CFF Standard Encoding array - also default */
        {
        struct cffencodings* code = CFF_Standard_Encoding;

        if_state.gpps->hcffencodearray = BUFalloc(FSA (SL32)(256 * sizeof (UW16)));
        if (!if_state.gpps->hcffencodearray)
          {
          DBG ("ERROR: allocate encoding array ");
          return (ERR_cff_enc_arr_mem);
          }
        pcffencodearray = (UW16*)MEMptr(if_state.gpps->hcffencodearray);
        MEMSET(pcffencodearray, 0, 256 * sizeof(UW16)); /* must blank */
        pcffencodearray[0] = (UW16)0;             /* always "notdef"                  */ 
 
        cnt = 1;        
        while((code->SID + code->code + code->end) != 0) /* 3 nulls at end */
          {
          for(cnt = code->code, ix = code->SID; cnt <= code->end; )
              pcffencodearray[cnt++] = ix++;
          code++;
          }
        }
        break;      /* end case 0: */

      case 1:     /* use Adobe Expert Encoding array */
        {
        struct cffencodings* code = CFF_Expert_Encoding;

        if_state.gpps->hcffencodearray = BUFalloc(FSA (SL32)(256 * sizeof (UW16)));
        if (!if_state.gpps->hcffencodearray)
          {
          DBG ("ERROR: allocate encoding array ");
          return (ERR_cff_enc_arr_mem);
          }
        pcffencodearray = (UW16*)MEMptr(if_state.gpps->hcffencodearray);
        MEMSET(pcffencodearray, 0, 256 * sizeof(UW16)); /* must blank */
        pcffencodearray[0] = 0;             /* always "notdef"                  */ 
 
        cnt = 1;        
        while((code->SID + code->code + code->end) != 0) /* 3 nulls at end */
          {
          for(cnt = code->code, ix = code->SID; cnt <= code->end; )
              pcffencodearray[cnt++] = ix++;
          code++;
          }
        }
        break;    /* end case 1; */

      } /* end  switch (cf->encoding.stt) */

    /* ----- build a Custom Encoding array using font supplied data */
    /* NOTE: Should also check here for supplement encodings... see p.14 & 15 CFF Spec. */
    if (cf->encoding.stt > 1)
      {   
      MEM_HANDLE m;
      LPUB8 tempbuf;

        if_state.gpps->hcffencodearray = BUFalloc(FSA (SL32)(256 * sizeof (UW16)));
        if (!if_state.gpps->hcffencodearray)
          {
          DBG ("ERROR: allocate encoding array ");
          return (ERR_cff_enc_arr_mem);
          }
        pcffencodearray = (UW16*)MEMptr(if_state.gpps->hcffencodearray);
        MEMSET(pcffencodearray, 0, 256 * sizeof(UW16)); /* must blank */
        pcffencodearray[0] = (UW16)0;             /* always ".notdef"                  */ 

      fpos = seekandread(FSA buf, cf->encoding.stt, 2); /* set when Top DICT is read */
      if(fpos != 2)
         return ERR_cff_bad_read;

                                      /* buf[1] holds:                               */
                                      /*  - number of encoded glyphs -- format 0.    */
                                      /*  OR                                         */
                                      /*  - number of ranges of glyphs -- format 1.  */
                                      /*  cf->charstrings.items holds the number of glyphs in the font */
                                      /* NOTE:  There may be more glyphs          */
                                      /*        in the font than this ...!        */

      m = BUFalloc(FSA (256 * 2) + 2);  /* encoding items have 2 values     */
      if(!m)
         return ERR_cff_enc_arr_mem;
      tempbuf = (LPUB8)MEMptr(m);

      fpos = seekandread(FSA tempbuf, cf->encoding.stt, (256 * 2) + 2);
      if(fpos != ((256 * 2) + 2))
         return ERR_cff_bad_read;


      tempbuf++;  /* skip over format byte */
      tempbuf++;    /* skip over nCodes, or nRanges byte */

      switch (buf[0])         /* format identifier                        */
        {
        case 0:               /* one of two currently defined formats     */
          for(cnt = 1; cnt <= buf[1]; cnt++)
            {
            pcffencodearray[*tempbuf++] = (UW16)cnt;
            }
          cf->encoding.items = buf[1];
          break; /* end of case 0: */

        case 1:
          ix = 1;
          for (cnt=0; cnt<buf[1]; cnt++)
              {
              first = *tempbuf++;
              nLeft = *tempbuf++;
                  loop2 = (UL32)(first + nLeft);
                  for (loop1=first; loop1<=loop2; loop1++)
                   {
                   pcffencodearray[loop1] = ix++; 
                   if(ix > 255)
                      break;
                   }
               if(ix > 255)
                      break;
               }
          cf->encoding.items = ix;
          break; /* end of case 1: */

        } /* end switch */    
        BUFfree(FSA m);
    } /* end (cf->encoding.stt > 1) */
    /*----- end of building encoding array */

    /*----- build an array for Charset data */

    /* Predefined charset ids:     pg. 17, Adobe Tech Note #5176  */
    /*       0   ISOAdobe Charset - also default  */
    /*       1   Expert Charset                   */
    /*       2   ExpertSubset Charset             */
    /*                                            */
    /* Otherwise, Charset Array will be Custom,   */
    /* that is, from the font.                    */


    switch (cf->charset.stt)
      {
      case 0:   /* Set up for ISOAdobe Standard Charset */
        {
        struct cffcharsets* code = CFF_ISOAdobe_Charset;

        if_state.gpps->hcharsetarray = BUFalloc(FSA (SL32)(256 * sizeof (UW16)));
        if (!if_state.gpps->hcharsetarray)
          {
          DBG ("ERROR: allocate charset array ");
          return (ERR_cff_charset_arr_mem);
          }
    
        pcffcharsetarray = (UW16*)MEMptr(if_state.gpps->hcharsetarray);
        MEMSET(pcffcharsetarray, 0, 256 * sizeof(UW16)); /* must blank */
        pcffcharsetarray[0] = 0;             /* always "notdef"                  */ 
 
        cnt = 1;        
        while(code->csSID != 0)   /* 1 null at end */
          {
              pcffcharsetarray[cnt++] = code->csSID;
          code++;
          }
        cf->charset.items = cf->charstrings.items;
        }
        break; /* end of case 0: */

      case 1:   /* Set up for Expert Charset */
        {
        struct cffcharsets* code = CFF_Expert_Charset;

        if_state.gpps->hcharsetarray = BUFalloc(FSA (SL32)(256 * sizeof (UW16)));
        if (!if_state.gpps->hcharsetarray)
          {
          DBG ("ERROR: allocate charset array ");
          return (ERR_cff_charset_arr_mem);
          }
    
        pcffcharsetarray = (UW16*)MEMptr(if_state.gpps->hcharsetarray);
        MEMSET(pcffcharsetarray, 0, 256 * sizeof(UW16)); /* must blank */
        pcffcharsetarray[0] = 0;             /* always "notdef"                  */ 

        cnt = 1;        
        while(code->csSID != 0)   /* 1 null at end */
          {
              pcffcharsetarray[cnt++] = code->csSID;
          code++;
          }
        cf->charset.items = cf->charstrings.items;
        }
        break; /* end of case 1: */

      case 2:   /* Set up for ExpertSubset Charset */
        {
        struct cffcharsets* code = CFF_ExpertSubset_Charset;

        if_state.gpps->hcharsetarray = BUFalloc(FSA (SL32)(256 * sizeof (UW16)));
        if (!if_state.gpps->hcharsetarray)
          {
          DBG ("ERROR: allocate charset array ");
          return (ERR_cff_charset_arr_mem);
          }
    
        pcffcharsetarray = (UW16*)MEMptr(if_state.gpps->hcharsetarray);
        MEMSET(pcffcharsetarray, 0, 256 * sizeof(UW16)); /* must blank */
        pcffcharsetarray[0] = 0;             /* always "notdef"                  */ 
 
        cnt = 1;        
        while(code->csSID != 0)   /* 1 null at end */
          {
              pcffcharsetarray[cnt++] = code->csSID;
          code++;
          }
        cf->charset.items = cf->charstrings.items;
        }
        break; /* end of case 2: */

      } /* end  switch (cf->charset.stt) */

     /*----- build a Custom Charset array using font supplied data */
     if(cf->charset.stt > 2)  /* offset to start of charset in font */
       {    
       MEM_HANDLE m;
       LPUB8 tempbuf;

       cf->charset.items = cf->charstrings.items;    /* number of glyphs in the font */

       if_state.gpps->hcharsetarray = BUFalloc(FSA (SL32)(cf->charset.items * sizeof (UW16)));
       if (!if_state.gpps->hcharsetarray)
         {
         DBG ("ERROR: allocate charset array ");
         return (ERR_cff_charset_arr_mem);
         }
    
       pcffcharsetarray = (UW16*)MEMptr(if_state.gpps->hcharsetarray);
       MEMSET(pcffcharsetarray, 0, cf->charset.items * sizeof(UW16)); /* must blank */
       pcffcharsetarray[0] = 0;             /* always "notdef"                  */ 
 
       fpos = seekandread(FSA buf, cf->charset.stt, 2); /* set when Top DICT is read */
       if(fpos != 2)
          return ERR_cff_bad_read;

    
       switch (buf[0])            /* format identifier - one of three defined formats  */
         {
         case 0:                    /* Format 0     */
           m = BUFalloc(FSA (cf->charset.items * 2) + 2);  /* these charset items have 1 2-Byte SID value */
           if(!m)
              return ERR_cff_charset_arr_mem;
           tempbuf = (LPUB8)MEMptr(m);

           fpos = seekandread(FSA tempbuf, cf->charset.stt, (cf->charset.items * 2) + 2);
           if(fpos != (cf->charset.items * 2) + 2)
              return ERR_cff_bad_read;

           pcffcharsetarray[0] = (UW16)0;

           tempbuf++;  /* skip over format byte */
           for(cnt = 1; cnt < cf->charset.items; cnt++)
             {
             pcffcharsetarray[cnt] = *tempbuf++;
             pcffcharsetarray[cnt] = ((pcffcharsetarray[cnt] << 8) | (*tempbuf++));
             }
           break; /* end of case 0: */

            
         case 1:                 /* Format 1    */
           m = BUFalloc(FSA (cf->charset.items * 3) + 3);  /* these charset items have 2 values  */
                                                      /* 2-Byte first SID, 1-Byte nleft count    */
           if(!m)
              return ERR_cff_charset_arr_mem;
           tempbuf = (LPUB8)MEMptr(m);
           fpos = seekandread(FSA tempbuf, cf->charset.stt, (cf->charset.items * 3) + 3);

           if(fpos != (cf->charset.items * 3) + 3)
              return ERR_cff_bad_read;

              pcffcharsetarray[0] = (UW16)0;

           cnt = 1;
           tempbuf++;  /* skip first format byte */

           while(cnt < cf->charset.items)
          {
          first = *tempbuf++;
          first = (first << 8 | *tempbuf++);
          nLeft = *tempbuf++;

          for(csSID = first; csSID <= (first + nLeft); )
             {
              pcffcharsetarray[cnt++] = csSID++;
                  if (cnt >= cf->charset.items)
                break;
             }
          }
           break; /* end of case 1: */


         case 2:   /* Format 2 - 32 bit value for items left in range */
           m = BUFalloc(FSA (cf->charset.items * 4) + 2);  /* these charset items have 2 values */
                                                      /* 2-Byte SID, 2-Byte nleft count    */
           if(!m)
              return ERR_cff_charset_arr_mem;
           tempbuf = (LPUB8)MEMptr(m);


           fpos = seekandread(FSA tempbuf, cf->charset.stt, ((cf->charset.items * 4) + 2));
           if(fpos != ((cf->charset.items * 4) + 2))
              return ERR_cff_bad_read;

           pcffcharsetarray[0] = (UW16)0;

           cnt = 1;

           tempbuf++;  /* skip first format byte */
        while(cnt < cf->charset.items)
          {
          first = *tempbuf++;
          first = (first << 8 | *tempbuf++);
          nLeft2 = *tempbuf++;
          nLeft2 = ((nLeft2 << 8) | (*tempbuf++));
          for(csSID = first; csSID <= (first + nLeft2); )
             {
              pcffcharsetarray[cnt++] = csSID++;
                  if (cnt >= cf->charset.items)
                break;
             }
          }
           break; /* end of case 2: */

         } /* end switch */    
        BUFfree(FSA m);
 
       } /* end if(cf->charset.stt > 2) */

    /*----- end of building charset array */


    return status;
} /* ---------------------------------------------------------------------- */


/* ------------------------------------------------------------------------ 
*    seekandread(FSP UB8* buf, SL32 stt, SL32 len)
*
* ------------------------------------------------------------------------ */
GLOBAL SL32 seekandread(FSP LPUB8 buf, SL32 stt, SL32 len)
{
    SL32 fpos;
#if CFF_ROM
    SL32 i;

    if (if_state.font_access == ROM_ACCESS)
    {
        if_state.psptr = if_state.gpxb->cur_font_hdr + stt;
        for (i=0; i<len; i++)
            buf[i] = *(if_state.psptr++);
        fpos = len;
    }
#endif
#if CFF_DISK
    if (if_state.font_access == DISK_ACCESS)
    {
        fpos = psf_seek(FSA stt, SEEK_SET);
        if(fpos == -1L)
            return fpos;
        fpos = psf_read(FSA buf, len);
    }
#endif

    return fpos;
} /* ---------------------------------------------------------------------- */
  
  
/* ------------------------------------------------------------------------ 
*    GetTopDICT(FSP SL32 face)
*
*    Locates the data for a DICT.
*  allocates a buffer to hold, and reads data to buffer.
*  calls cff_readDICT to process data
*  frees the data buffer
*  This function is called recursively in synthetic fonts 
* ------------------------------------------------------------------------ */
GLOBAL SL32 GetTopDICT(FSP cft* cf, SL32 face)
{
    SL32 status;
    SL32 buflen = 0; 
    LPUB8 dictbuf;
    LPUB8 copyptr;
    MEM_HANDLE m;
    
    DBG1("GetTopDICT for face %d\n", face);
    /*----- find selected font DICT */
    status = getStringData(FSA NULL, &buflen, &cf->dict, face);
    if(status)
        return ERR_cff_get_string_data;
    m = BUFalloc(FSA buflen);
    if(!m )
        return ERR_cff_no_dict_mem;
    copyptr = dictbuf = (LPUB8)MEMptr(m);

    status = getStringData(FSA dictbuf, &buflen, &cf->dict, face);
    if(status)
        goto done;

    status = cff_readDICT(FSA cf, dictbuf, 0, buflen - 1);    /* dict data loaded and read */

done:
    BUFfree(FSA m);
    dictbuf = NULL;
    
    return SUCCESS;
} /* ---------------------------------------------------------------------- */


/* ------------------------------------------------------------------------ 
*    variablevalue(UB8* data, SL32 step)
*
*    make a value from 1,2,3 or 4 bytes of data. 
* ------------------------------------------------------------------------ */
GLOBAL SL32 variablevalue(LPUB8 data, SL32 step)
{
    SL32 val = 0, cnt=0;
    
    while(cnt < step)
    {    
        val *= 256;
        val += data[cnt++];
    }
    return val;
} /* ---------------------------------------------------------------------- */


/* ------------------------------------------------------------------------ 
*    gethead(cfix* fill, SL32 stt)
*
*    locate and save in cf struct, items, step and stt pos for CFF heads 
* ------------------------------------------------------------------------ */
SL32 gethead(FSP cfix* fill, SL32 stt)
{
    UB8 buf[8];
    SL32 nread;
    
    nread = seekandread(FSA buf, stt, 4);
    if(nread != 4)
        return ERR_cff_bad_read;

    
    fill->items = variablevalue(buf, 2);
    DBG1("...gethead: # items = %d\n", fill->items);

    if(fill->items == 0)                    /* empty index (it's legal)    */
        return SUCCESS;
    
    fill->step = buf[2];
    if(fill->step < 1 || fill->step > 4)    /* must be 1..4                 */
        return ERR_cff_bad_offset_size;    
                      /* stt (or start) follows the 3 byte head information */
    fill->stt = stt + 3;
                             /* zbase is first byte of first item (item[1]) */
    fill->zbase = fill->stt + ((fill->items + 1) * fill->step);
    return SUCCESS;
} /* ---------------------------------------------------------------------- */

/* ------------------------------------------------------------------------ 
* cff_default_matrix()

* ------------------------------------------------------------------------ */
MLOCAL VOID cff_default_matrix(FSP0)
{
    FPNUM n, z;
    /* /FontMatrix [0.001 0 0 0.001 0 0] readonly def */
    
    n = fpdiv(fpint2fp(1),fpint2fp(1000));  /* 0.001 */
    z = fpint2fp(0);
    if_state.gpps->fontmatrix[0] = n;
    if_state.gpps->fontmatrix[1] = z;
    if_state.gpps->fontmatrix[2] = z;
    if_state.gpps->fontmatrix[3] = n;
    if_state.gpps->fontmatrix[4] = z;
    if_state.gpps->fontmatrix[5] = z;
} /* ---------------------------------------------------------------------- */


#ifdef AGFADEBUG
MLOCAL VOID dump_FDIndex(FSP cft* cf)
{
    UW16 idx, jdx, val, nextval, len;
    MEM_HANDLE hbuf, hbuffy;
    LPUB8 buf, buffy;

    /* cf->fontdict.zbase should point to a FontDICT */

    DBG4("zbase=0x%x, stt=0x%x, step=%d, items=%d\n", cf->fontdict.zbase, cf->fontdict.stt, cf->fontdict.step, cf->fontdict.items);

    for (idx=0; idx<cf->fontdict.items; idx++)
    {
        /* read two entries of the offset table for the FontDict INDEX */
        hbuf = BUFalloc(FSA cf->fontdict.step * 2);
        if (!hbuf)
        {
            DBG("BUFalloc() error in dump_FDIndex()\n");
            break;
        }
        buf = MEMptr(hbuf);

        seekandread(FSA buf,  cf->fontdict.stt + (idx * cf->fontdict.step), cf->fontdict.step*2);
        val = variablevalue(buf, cf->fontdict.step);
        nextval = variablevalue(buf + cf->fontdict.step, cf->fontdict.step);
        len = nextval - val;
        DBG4("idx=%d val=%d nextval=%d len=%d\n", idx, val, nextval, len);

        BUFfree(FSA hbuf);
        hbuffy = BUFalloc(FSA len);
        if (!hbuffy)
        {
            DBG("BUFalloc() error in dump_FDIndex()\n");
            break;
        }
        buffy = MEMptr(hbuffy);

        seekandread(FSA buffy, cf->fontdict.zbase - 1 + val, len);
         DBG1("bytes at 0x%x:\n    ", cf->fontdict.zbase - 1 + val);
        for (jdx=0; jdx<len; jdx++)
            DBG1(" %d ", buffy[jdx]);
        DBG("\n");
        BUFfree(FSA hbuffy);
    }
    DBG("\n");
}
#endif    /* AGFADEBUG */

#endif /* CFF_RDR */
 

cffsupp.txt   

/* 
 * Copyright (C) 2004 Agfa Monotype Corporation. All rights reserved.
 */
/*
* CffSupp.c   (previous name was Cffsupport.c)
* contains:
*    Cff_Set_Char()
*
*/
/* $Header:   I:/BULL/URIP/RTS/PSI/CFFSUPP.C_V   1.51   Nov 18 2004 08:20:52   dugganj  $ */
/* $Log:   I:/BULL/URIP/RTS/PSI/CFFSUPP.C_V  $
 * 
 *    Rev 1.51   Nov 18 2004 08:20:52   dugganj
 * In Cff_Set_Char(), added support for format "0".
 * 
 * 
 *    Rev 1.50   Oct 26 2004 13:27:04   dugganj
 * Multithreading changes.
 * 
 *    Rev 1.49   Oct 19 2004 13:36:58   galejss
 * read in appropriate FontDICT / PrivateDICT on a per-char basis  for CID-in-CFF fonts
 * 
 *    Rev 1.48   Aug 10 2004 13:56:50   galejss
 * changes for runtime no-symset-mapping option
 * 
 *    Rev 1.47   Aug 22 2003 09:19:24   LynchR
 * Updated copyright notice.
 * 
 *    Rev 1.46   Jul 21 2003 18:52:32   Galejs
 * reentrancy / debug fix (plus remove some #if-0 code)
 * 
 *    Rev 1.45   Jun 23 2003 15:19:06   Galejs
 * ufstport.h
 * 
 *    Rev 1.44   Sep 06 2002 17:28:16   Galejs
 * centralize #if-TT includes
 * 
 *    Rev 1.43   Jul 02 2001 20:51:56   Galejs
 * Joe's fix for CFF char mapping (now consistent whether or not TT is enabled)
 * 
 *    Rev 1.42   05 Jun 2001 13:06:02   JOE
 * In Cff_Set_Char(), look up the SID in the font charset array
 * if processing a native CFF font using symbolset mapping.
 * 
 *    Rev 1.41   04 Jun 2001 10:20:18   JOE
 * OpenType changes.
 * 
 *    Rev 1.40   May 21 2001 20:48:00   Galejs
 * remove unneeded calls to psf_open(), psf_close()
 * 
 *    Rev 1.39   May 04 2001 15:42:14   Galejs
 * data-type cleanup
 * 
 *    Rev 1.38   Jan 10 2001 14:31:44   Song
 * Removed ctrl-z from EOF
 * 
 *    Rev 1.37   10 Feb 2000 15:39:16   AL
 * Removed PST1_ROM
 * 
 *    Rev 1.36   Aug 13 1999 16:11:58   galejs
 * include-file changes
 * 
 *    Rev 1.35   16 Apr 1999 14:42:16   JOE
 * In Cff_Set_Char(), changed 'for' loop terminating condition when
 * looping through 'charset' items.
 * In same function, eliminated second pass of character search for
 * custom encoded fonts (by dlk).
 * 
 *    Rev 1.34   13 Apr 1999 23:00:34   DAVID
 * In Cff_Set_Char(), added more support for handling Custom
 * encoded fonts.
 * 
 *    Rev 1.33   24 Feb 1999 22:37:18   DAVID
 * In Cff_Set_Char(), added check for SID of '9999', then return
 * 'ERR_find_cgnum' to match PS Type 1 processing.
 * 
 *    Rev 1.32   18 Feb 1999 21:49:54   DAVID
 * Changed CFFSID to CFFCHARSET.
 * 
 *    Rev 1.31   16 Feb 1999 21:37:30   DAVID
 * Added ERR_cff_chId2cgnum for case when cgnum isn't found
 * in the current SymbolSet for the input chId.
 * 
 *    Rev 1.30   15 Feb 1999 11:01:28   DAVID
 * In Cff_Set_Char(), added ERR_cff_idx2SID.
 * 
 *    Rev 1.29   10 Feb 1999 13:10:46   DAVID
 * In unload_cff_font(), added code to free cffencodearray and
 * charsetarray.
 * 
 *    Rev 1.28   09 Feb 1999 13:35:36   GALEJS
 * remove unused includes
 * 
 *    Rev 1.27   05 Feb 1999 11:39:26   DAVID
 * Added access to Adobe Standard Strings array and Adobe Standard
 * SIDs for CFF processing of character requests by name string.
 * 
 *    Rev 1.26   02 Feb 1999 22:47:58   DAVID
 * Updated Cff_Set_Char() for composite accented character support,
 * and custom encoded fonts.
 * 
 *    Rev 1.25   01 Feb 1999 22:05:06   DAVID
 * Clean up chId assignment when NO_SYMSET_MAPPING == 0.
 * 
 *    Rev 1.24   01 Feb 1999 11:18:12   DAVID
 * Added access to glyph data via SID (ssnum == CFFSID).
 * 
 *    Rev 1.23   29 Jan 1999 10:50:50   DAVID
 * Made CFF Encoding Arrays 2 Bytes wide.
 * 
 *    Rev 1.22   27 Jan 1999 17:49:56   GALEJS
 * EXTERN PS_SIDdata[] needed only #if-CFF_RDR
 * 
 *    Rev 1.21   21 Jan 1999 18:20:10   GALEJS
 * standardize #include files
 * 
 *    Rev 1.20   20 Jan 1999 16:21:10   DAVID
 * Fixed typo 'CF_RDR' to 'CFF_RDR'.
 * 
 *    Rev 1.19   20 Jan 1999 14:20:32   DAVID
 * In Cff_Set_Char(), added support for NO_SYMSET_MAPPING and
 * CFFENCODING options.
 * 
 *    Rev 1.18   29 Sep 1998 15:22:14   GALEJS
 * set_escapement() needed even if CFF off
 * 
 *    Rev 1.17   29 Sep 1998 10:13:32   DAVID
 * In 'set_escapement()' moved local variables to '#else' part of conditional.
 * 
 *    Rev 1.16   28 Sep 1998 14:18:06   DAVID
 * Updated 'set_escapement()' with local variables to calculate 'matrix_val'.
 * 
 *    Rev 1.15   28 Sep 1998 13:33:14   DAVID
 * Added new function definition for 'set_escapement()'.
 * 
 *    Rev 1.14   16 Sep 1998 20:05:42   GALEJS
 * get rid of obsolete MIPS case
 * 
 *    Rev 1.13   16 Sep 1998 15:35:04   DAVID
 * In Cff_Set_Char(), changed '==' to '=' in assignment statement.
 * 
 *    Rev 1.12   15 Sep 1998 14:00:02   JOE
 * Changed include reference from cffProto.h to cffproto.h
 * for SUN - SPARC usage (by jwd).
 * 
 *    Rev 1.11   31 Aug 1998 19:10:40   GALEJS
 * fix reentrancy parms, delete bogus "extern if_state" dcl
 * 
 *    Rev 1.10   26 Aug 1998 00:45:32   DAVID
 * Updates for reentrancy.
 * 
 *    Rev 1.9   25 Aug 1998 13:07:50   AL
 * Was only processing new characters; could not go back and rasterize a chara
 * 
 *    Rev 1.8   24 Aug 1998 22:41:26   DAVID
 * Preparation for reentrancy.
 * 
 *    Rev 1.7   13 Aug 1998 09:38:30   DAVID
 * Moved PostScript file function definition block ('psf_xxx', and
 * 'psrom_xxx' functions) to t1idecod.c so that PST1_DISK without CFF_RDR
 * will compile.
 * 
 *    Rev 1.6   10 Aug 1998 11:44:10   AL
 * Check error returns and clean up // comments
 * 
 *    Rev 1.5   06 Aug 1998 16:24:44   AL
 * 
 * CFF rom, multiple master and bug fixes
 * 
 *    Rev 1.4   27 Jul 1998 15:27:06   AL
 * 
 * Internal floating point support
 * 
 *    Rev 1.3   27 Jul 1998 11:00:02   AL
 * Added internal memory management support
 * 
 *    Rev 1.2   10 Jul 1998 10:41:20   AL
 * Conditional compile entire file on CFF_RDR
 * 
 *    Rev 1.1   08 Jul 1998 10:59:38   DAVID
 * 
 * Added PVCS Change History tracking, and UFST REVISION HISTORY.
*
*/


/*
REVISION HISTORY
------------------------------------------------------------------------------
08-Jul-98 dlk Original version placed under PVCS control.  File name changed
              from 'CffSupport.c' to 'cffsupp.c' to maintain '8.3' file name
              convention.  This REVISION HISTORY added.  Fix made to
              'roundFixPt2int()' code for positioning of the inner loops in 
              SWCaps.
13-Aug-98 dlk Moved PostScript file function definition block ('psf_xxx' and
              'psrom_xxx' functions) to t1idecod.c so that PST1_DISK without
              CFF_RDR will compile.
24-Aug-98 dlk Preparation for reentrancy.
31-Aug-98 slg Reentrancy fixes: getSubBias() doesn't need FSP parameter, but
              getStringData() does need FSP. Also delete spurious
              "extern IF_STATE if_state" declaration, which was the reason that
              this file built successfully despite getStringData() problem.
15-Sep-98 jwd Changed reference from cffProto.h to cffproto.h for Sun/SPARC usage.
16-Sep-98 dlk In Cff_Set_Char(), changed '==' to '=' in assignment statement.
28-Sep-98 dlk Added definition for 'set_escapement()'.
28-Sep-98 dlk Updated definition for 'set_escapement()' with local variables
              to calculate 'matrix_val'.
29-Sep-98 dlk In 'set_escapement()' moved local variables to '#else' part of
              conditional.
20-Jan-99 dlk In Cff_Set_Char(), added support for NO_SYMSET_MAPPING and
              CFFENCODING options.
20-Jan-99 dlk Fixed typo 'CF_RDR' to "CFF_RDR'.
29-Jan-99 dlk Changed 'hencodearray' references to 'hcffencodearray'.
              And made CFF Encoding Arrays 2 Bytes wide.
01-Feb-99 dlk Added access to glyph data via SID (ssnum field == CFFSID).
01-Feb-99 dlk Clean up chId assignment when NO_SYMSET_MAPPING == 0.
02-Feb-99 dlk Updated logic in Cff_Set_Char() for support of composite
              accented characters, custom encoded fonts.
05-Feb-99 dlk If NO_SYMSET_MAPPING == 1, and char_name specifies the requested
              character, use the Adobe Standard Strings array (not PSdata[]),
              then use the return 'mapidx' as index to CFFStdSIDs[] array to
              get the SID.
10-Feb-99 dlk In unload_cff_font(), added code to free cffencodearray and
              charsetarray.
15-Feb-99 dlk In Cff_Set_Char(), added ERR_cff_idx2SID in case SID value from
              PS_SIDdata[] is 999.
16-Feb-99 dlk In Cff_Set_Char(), added ERR_cff_chId2cgnum for case when chId
              can NOT be found in SymbolSet.
18-Feb-99 dlk Changed CFFSID to CFFCHARSET.
24-Feb-99 dlk In Cff_Set_Char(), added check for SID of '9999', then return
              'ERR_find_cgnum' to match PS Type 1 action.
12-Feb-99 dlk In Cff_Set_Char(), added more support for processing Custom
              encoded fonts with unique (non-standard) SIDs.
16-Apr-99 dlk In Cff_Set_Char(), changed 'for' loop terminating condition
              when looping through 'charset' items. In same function,
              elimintated second pass of character search for custom 
              encoded fonts.
10-Feb-00 awr Removed PST1_ROM
21-May-01 slg Remove unneeded psf_open() and psf_close() calls
23-May-01 jfd OpenType changes:
              Including "fscdefs.h" and "fontscal.h".
              In set_escapement(), point to correct bucket.
              In CFF_Set_Char(), for OpenType CFF fonts, use TT CMAP table
              to map character ID to glyph index.
              In same function, call cff_get_charstrings() to build an empty
              charstrings item.
              In cff_get_charstrings(), allocate only 1 item instead of an array.
05-Jun-01 jfd In Cff_Set_Char(), look up the SID in the font charset array 
              if processing a native CFF font using symbolset mapping.

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


#include "cgconfig.h"

#if PST1_RDR    /* conditional compile entire module */

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

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

#include "ufstport.h" 

#if MAYBE_FCNTL_H
#include <fcntl.h>
#endif

#if MAYBE_FCNTL_HIF_H
#include <fcntl.h>
#include <hif.h>  /* 2-7-94 jfd */
#endif

#if MAYBE_IO_H
#include <io.h>         /* close() */
#endif

#if MAYBE_UNISTD_H
#include <unistd.h>
#endif

#if MAYBE_MALLOC_H
#include    <malloc.h>
#endif

#include <stdlib.h> /* need for 'abort()' i.e. ASSERT */

#include "dbg_ufst.h"

#include "shareinc.h"
#include "mixmodel.h"

#include "t1itype1.h"
#include "t1isyntx.h"
#include "t1iproto.h"
#if PST1_SFNTI
#include "t1isfnt.h"
#endif

#include "cffproto.h"

#if CFF_RDR
EXTERN UW16 PS_SIDdata[];
EXTERN UW16 CFFStdSIDs[];
#endif


/* ------------------------------------------------------------------------ 
 * set_escapement(FSP SW32 esc)
 *
 * set the character width escapement from the decoded data
 * ------------------------------------------------------------------------ */
GLOBAL VOID set_escapement(FSP SL32 escapement)
{

#if DU_ESCAPEMENT
    if_state.gpcs->escapement = (SW16)escapement;
#else
    FPNUM tmp_fp_esc;
    UW16  matrix_val;
    PBUCKET pb;    /* 05-23-01 jfd */

    pb = GET_pBUCKET(if_state.pbucket);                                /* 05-23-01 jfd */

    tmp_fp_esc = fpdiv( fplongexp(1L, 0), pb->p.ps.fontmatrix[0]);    /* changed 'if_state.pbucket' to 'pb'  05-23-01 jfd */
    matrix_val = fp2word( tmp_fp_esc );

    if_state.gpcs->escapement = (SW16)(((escapement * 8782) + (matrix_val / 2)) / matrix_val);
#endif
} /* ---------------------------------------------------------------------- */

#if CFF_RDR  /* conditionally compile rest of module */

/* ------------------------------------------------------------------------ 
 * SL32 getSubBias(SL32 globalitems)
 * 
 * Determins and returns "bias" depending on the number of global subrs.
 * bias is added to both global and local subroutine numbers to determine
 * the actual call index. Optional in type1, mandatory in type2.
 * ------------------------------------------------------------------------ */
GLOBAL SL32 getSubBias(SL32 gsubrs)
{
    if(gsubrs < 1240)
        return 107;
    if(gsubrs < 33900)
        return 1131;
    return 32768;
} /* ---------------------------------------------------------------------- */


/* ------------------------------------------------------------------------ 
 * Cff_Set_Char (FSP UW16 chId)
 * 
 * NOTE: This scheme depends upon memory not moving between this call to
 * 'set_char()' and the followup call to 'make_gaso...()'.
 * return a cptr pointer to the charstring data .
 * ------------------------------------------------------------------------ */
UW16 Cff_Set_Char(FSP UW16 chId)
{
    LPSB8   char_name;
    UW16    charstringIx;
    PCDATASTR pcharstrings, pcs;
    cft* cf;
    SL32 status;
    SL32 buflen = 0; 
    LPUB8 p;

    UW16  SID;
    UW16* pcffcharsetarray;
    BOOLEAN found;
    UL32 idx;

    DBG ("Cff_Set_Char()\n");

    cf = &if_state.gpps->cft;    
    charstringIx = if_state.gpps->curr_char = chId;
    SID = 0;         /* default to 'notdef' */
    char_name = "";  /* default */


  if (FC_NO_SSMAP(&if_state.fcCur))
  {
    /* Since (NO_SYMSET_MAPPING == 1), DON'T go through the     */
    /* conversion to cgnum, and Agfa symbolset mapping.         */
    /* Note:                                                    */
    /* chIdptr and PSchar_name MUST be set previously by        */
    /* an application call to CGIFchIdptr().                    */

    chId = *(LPUW16)if_state.chIdptr;
    char_name = if_state.PSchar_name;
    if_state.gpps->curr_char = chId;


    if (if_state.fcCur.ssnum == CFFENCODING)
       /* so use the Font Encoding Array and chId code */
       /* to get the index to the glyph data.          */
       {
       if(if_state.gpps->hcffencodearray)    /* should always have something... */
         {
         UW16*    pcffencodearray;
         pcffencodearray = (UW16*)MEMptr(if_state.gpps->hcffencodearray);
         SID = (UW16)pcffencodearray[chId];
         }
       else
         {
         SID = chId;
         }
       }  /* End (ssnum == CFFENCODING) */

    if (if_state.fcCur.ssnum == CFFCHARSET)
       /* use the number (chId) passed in directly as the SID */
       /* and the font charset array to get the index to the glyph data.          */
       {
       SID = chId;
       }  /* End (ssnum == CFFCHARSET) */

    if ((if_state.fcCur.ssnum != CFFENCODING) &&
        (if_state.fcCur.ssnum != CFFCHARSET) )
#if TT_RDR    /* 05-23-01 jfd */
       /* If processing an OpenType CFF font, use the CMAP table to map the
        * 'chId' to a glyph index. From there, use the glyph index to access
        * glyph data through the CharStrings INDEX of the CFF table.
        */
       if ( B_ISOTCFF(if_state.pbucket) )
       {
          UW16 status;
          fs_GlyphInfoType  *ttOutput;
#if (USE_JUMP_TABLES)
          status = ((*((PIF_FUNC_TBL)if_state.pbucket->pft)->set_char) (FSA if_state.pbucket, chId));
#else
          status = ttset_char (FSA if_state.pbucket, chId);
#endif
          if (status)
              return status;

          ttOutput = (fs_GlyphInfoType *) MEMptr(if_state.pbucket->p.tt.buffInfo);
          charstringIx = ttOutput->glyphIndex;
       }
       else
#endif    /* TT_RDR */        /* 05-23-01 jfd */
       /* access by character name string... */
       /* use char_name to get SID */
       /* then, use the font charset array and SID */
       /* to get the index to the glyph data */
       {    
       UW16  mapidx;

       mapidx = 0;
       mapidx = StdStrToIndex((LPSB8)char_name);
       if (mapidx)
          {
          SID = (UW16)CFFStdSIDs[mapidx];
          } /* End - if(mapidx) */
       else
          {
          UL32  i;
          DBG1 ("Unable to get index for char_name %s\n", char_name);

          for(i = 1; i <= cf->strings.items; i++)
             {
             SL32 buflen = 127;
             UB8 localbuf[255];

             status = getStringData(FSA localbuf, &buflen, &cf->strings, i);
             if (status)
                {
                return (ERR_cff_chname2SID);
                     }

             if (STRNCMP((FILECHAR *)localbuf, (FILECHAR *)char_name, 127) == 0)
                {
                SID = (UW16)i + 390;
                break;
                }
                } /* End for() */

          return(ERR_find_cgnum);

          } /* End else - if(mapidx) */
       }  /* End ((ssnum != CFFENCODING) && (ssnum != CFFCHARSET)) */

  }
  else
  { 
      /* Since (NO_SYMBOLSET_MAPPING == 0),          */
      /* Use Agfa SymbolSet Mapping for case         */
      /* when ssnum field has a SymbolSet designator */
      /* Note:                                       */
      /* Application passes character code to UFST.  */

    if (if_state.fcCur.ssnum == CFFENCODING)
       /* so use the Font Encoding Array and chId code */
       /* to get the index to the glyph data.          */
       {
       if(if_state.gpps->hcffencodearray)    /* should always have something... */
         {
         UW16*    pcffencodearray;
         pcffencodearray = (UW16*)MEMptr(if_state.gpps->hcffencodearray);

         SID = (UW16)pcffencodearray[chId];
            }
       else
         {
           SID = (UW16)chId;
         }
       }  /* End (ssnum == CFFENCODING) */


    if (if_state.fcCur.ssnum == CFFCHARSET)
       /* use the number (chId) passed in directly as the SID */
       /* and the font charset array to get the index to the glyph data.          */
       {
       SID = (UW16)chId;
       }  /* End (ssnum == CFFCHARSET) */

    if ((if_state.fcCur.ssnum != CFFENCODING) &&
        (if_state.fcCur.ssnum != CFFCHARSET))
       {    
#if TT_RDR    /* 05-23-01 jfd */
       /* If processing an OpenType CFF font, use the CMAP table to map the
        * 'chId' to a glyph index. From there, use the glyph index to access
        * glyph data through the CharStrings INDEX of the CFF table.
        */
       if ( B_ISOTCFF(if_state.pbucket) )
       {
          UW16 status;
          fs_GlyphInfoType  *ttOutput;
#if (USE_JUMP_TABLES)
          status = ((*((PIF_FUNC_TBL)if_state.pbucket->pft)->set_char) (FSA if_state.pbucket, chId));
#else
          status = ttset_char (FSA if_state.pbucket, chId);
#endif
          if (status)
              return status;

          ttOutput = (fs_GlyphInfoType *) MEMptr(if_state.pbucket->p.tt.buffInfo);
          charstringIx = ttOutput->glyphIndex;
       }
       else
#endif    /* TT_RDR */        /* 05-23-01 jfd */
       /* use Agfa UFST symbolset mapping of chId to a cgnum */
       /* then, map the cgnum to an index into the PS SID array */
       /* then look up the SID in the font charset array to get */
       /* to the glyph data */ 
       {    
       UW16  cgnum;
       UW16  mapidx;

       cgnum = SYMmap (FSA chId, FC_PST1_TYPE);
       if (!cgnum)
          {
          DBG1 ("Unable to get cgnum for chId %d\n", chId);
          return (ERR_cff_chId2cgnum);
          }

       mapidx = 0;
       mapidx = cm_cgidToIndex (cgnum);
       if (!mapidx)
          {
          DBG1 ("Unable to get map index for cgnum %d\n", cgnum);
          return (ERR_cff_cg2idx);
          }

       SID = (UW16)PS_SIDdata[mapidx];
       if (SID == (UW16)999)
          {
          DBG1 ("Unable to get SID from PS_SIDdata[] for mapidx %d\n", mapidx);
          return (ERR_cff_idx2SID);
          }
       if (SID == (UW16)9999)
          {
          DBG1 ("No valid SID from PS_SIDdata[] for mapidx %d\n", mapidx);
          return (ERR_find_cgnum);
          }
        } /* End (B_ISOTCFF() )  05-23-01 jfd */
        } /* End ((ssnum != CFFENCODING) && (ssnum != CFFCHARSET))  */

  }

    /* 07-01-01 jfd
     * Reduce the following test to 'if !B_ISOTCFF(...) '
     * to resolve mapping problem.
     */


#if TT_RDR    /* 07-01-01 jfd */
    if (!B_ISOTCFF(if_state.pbucket))
    {
#endif    /* 07-01-01 jfd */

    if ( (cf->charset.stt > 2) && 
         (if_state.fcCur.ssnum == CFFENCODING) )
       /* test for Custom Encoded Font, with CFFENCODING selected,  */
       /* and set charstringIx to currrent SID value                */
       {
        charstringIx = SID;
       }
    else /* else, NOT (Custom Encoded with CFFENCODING selected) */
       {
        pcffcharsetarray = (UW16*)MEMptr(if_state.gpps->hcharsetarray);
        found = FALSE;
        for(idx = 0; idx < cf->charset.items; idx++)
          {
          if ((UW16)pcffcharsetarray[idx] == SID)
             {
              charstringIx = (UW16)idx;
             found = TRUE;
             break;
             }
          if (found)
             break;
          } /* end of for() */

       if (!found)
             return (ERR_find_cgnum);

       } /* End (test for custom encoding...) */

#if TT_RDR    /* 07-01-01 jfd */
    }    /* End if (!B_ISOTCFF(if_state.pbucket)) */
#endif    /* 07-01-01 jfd */

     /* Now, we finally have the index to the charstring data */
    if_state.gpps->curr_char = charstringIx;

    DBG3("CFF_Set_Char: chId %d csIx %d name %s\n", chId, charstringIx, char_name);

/* If we are processing a CFF-encoded CID font, we need to go back to the data and read in the
   appropriate font dictionary and Private dictionary for the current glyph ID. */
        
    if ((if_state.gpps->hexascii == CFF) && if_state.gpps->isCID)
    {
    UB8 *pFDSelect, *pcur, fdIdx;
    UW16 nRanges, idx, first;
    UL32 whichRange; 
    UW16 val, nextval, len;

    pFDSelect = MEMptr(if_state.gpps->hFDSelect);
    switch (pFDSelect[0])
    {
    case 0:
        DBG1("CID-in-CFF: Format=%d encountered\n", pFDSelect[0]);
        pcur = pFDSelect + 1;
        fdIdx = *(pcur + charstringIx);
        DBG2("glyph=%d: FD index=%d\n", charstringIx, fdIdx);
        break;
    case 3:
        DBG1("CID-in-CFF: Format=%d encountered\n", pFDSelect[0]);
        pcur = pFDSelect + 1;
        nRanges = *pcur++;
        nRanges = ((nRanges << 8) | (*pcur++));
        DBG1("number of ranges=%d\n", nRanges);

        whichRange = nRanges - 1;    /* fall through to last entry */
        for (idx=0; idx<nRanges; idx++)
        {
            first = *pcur++;
              first = ((first << 8) | (*pcur++));
              fdIdx = *pcur++;
              if (charstringIx < first)
              {
                whichRange = idx - 1;
                break;
              }
        }

          pcur = pFDSelect + 3 + (3 * whichRange);
        first = *pcur++;
        first = ((first << 8) | (*pcur++));
        fdIdx = *pcur++;
        DBG3("entry to use=%d: 1st idx=%d, FD index=%d\n", whichRange, first, fdIdx);
          break;

    default:
        /* shouldn't reach this stmt - case should be detected in cffdict.c, during readin */
        DBG1("CID-in-CFF: Unknown format=%d\n", pFDSelect[0]);
        break;
    }

    if (fdIdx == (UB8)if_state.gpps->FDidx_cur)
    {
        DBG1("    NOT loading FontDICT at %d (already loaded)\n", fdIdx);
    }
    else
    {
        UB8 tmpbuf[10], *fd;
        MEM_HANDLE h_fd;

        cf = &if_state.gpps->cft;

        /* read two entries of the offset table for the FontDict INDEX */
        seekandread(FSA tmpbuf,  cf->fontdict.stt + (fdIdx * cf->fontdict.step), cf->fontdict.step*2);
        val = variablevalue(tmpbuf, cf->fontdict.step);
        nextval = variablevalue(tmpbuf + cf->fontdict.step, cf->fontdict.step);
        len = nextval - val;
        DBG2("    LOADING FontDICT at fdIdx=%d (len=%d)\n", fdIdx, len);

        h_fd = BUFalloc(FSA len);
        if(!h_fd)
            return ERR_cff_no_dict_mem;
        fd = (LPUB8)MEMptr(h_fd);

        seekandread(FSA fd, cf->fontdict.zbase - 1 + val, len);

        status = cff_readDICT(FSA cf, (LPUB8)fd, 0, len);
        BUFfree(FSA h_fd);

        if(status)
            return status;
        else
            if_state.gpps->FDidx_cur = fdIdx; 


        if (cf->localsubrs.stt)
        {
            DBG("READING localsubrs index\n"); 
            status = gethead(FSA &cf->localsubrs, cf->localsubrs.stt);
            if(status)
                return status; 
        }
        else
             DBG("No localsubrs to read in\n");
    }

}

    /* ---- build an empty array to hold charstrings  */
    /* *** cff_get_charstrings() call was moved from cffsetup() *** jfd */
    status = cff_get_charstrings(FSA cf->charstrings.items, cf->charstrings.zbase);
    if(status)
        return status;
    pcharstrings = (PCDATASTR)MEMptr (if_state.gpps->hcharstrings);
    pcs = pcharstrings; /* current character */

    /*----- add this char's charstring data to empty array element   */
                                    /*----- put away the charstring       */
    status = getStringData(FSA NULL, &buflen, &cf->charstrings, (UL32)(charstringIx + 1));
    if(status)
    {
        status = ERR_cff_get_string_data;
        goto done;
    }
    
    /*----- make a place to put the data, use buflen to alloc mem */
    pcs->hdata = BUFalloc(FSA buflen);
    if (!pcs->hdata)
    {
        status = ERR_psi_Chardat_mem;
        goto done;
    }


    p = (LPUB8)MEMptr(pcs->hdata);
    /*----- find this charstring's data, and copy to buffer                */
    status = getStringData(FSA p, &buflen, &cf->charstrings, (UL32)(charstringIx + 1));
    if(status)
      {
        status = ERR_cff_get_string_data;
        goto done;
      }
    
    /*----- keep a copy of this charstring pointer and it's length         */
    if_state.gpps->pthis_charstring = pcs;
    
    pcs->len = buflen; 
    if(if_state.gpps->lenIV != 4)
        pcs->decrypted = 'y';

done:
    return status;
} /* ---------------------------------------------------------------------- */


/* ------------------------------------------------------------------------ 
* nextopcode(LPUB8* PPdata, SL32* args, LPSL32* aptr) 
*
*  reads data finding and decoding operands and operators.
*  puts operands on arg stack until it finds an operator
*  returns operator.
* ------------------------------------------------------------------------ */
GLOBAL UW16 nextopcode(FSP LPUB8* PPdata, SL32* args, LPSL32* aptr)   
{
    UL32  c = 0;
    SL32  arg = 0;            
    UW16  inchar = 0, inchar2 = 0;
    LPUB8 pdata = *PPdata;   
    LPSL32 argsptr = *aptr;
    
    do 
    {
        if ((inchar = *pdata++) <= 0xf6)
            c = inchar;
        else
        {
            inchar2 = *pdata++;
            c = ((UL32)(inchar << 8) | (UL32)inchar2);
        }
        /* -------------- values -------------------*/
        if ((c >= 0x20))
        {                            /* see if we should flush them out */
            if (c >= 0x20 && c < 0xf7)
            {
                arg = (SL32)c - 0x20L - 107L;         /*  -107 to  +107 */
            }
            else if (c >= 0xf700 && c < 0xfb00)
            {
                arg = (SL32)c - 0xf700L + 108L;       /*  +108 to +1137 */
            }
            else if (c >= 0xfb00 && c < 0xff00)
            {
                arg = (-((SL32)c - 0xfb00L + 108L));    /*  -108 to -1131 */
            }
            else
            {              /* next four bytes contain a fixed point 16.16 */
                c =  c << 24;
                c |= (UL32)*pdata++ << 16; 
                c |= (UL32)*pdata++ << 8;
                c |= (UL32)*pdata++;
                arg = (SL32)(c);
            }
            *argsptr++ = (arg);              /* put values on stack  */
            DBG1 ("Push: %ld\n", arg);
        }
    }
    while(c >= 0x20);   /* loop getting/storing args while not an opcode    */
    *PPdata = pdata; /* update orignal pointer                           */
    *aptr = argsptr;
    return (SW16)(c & 0xffff);   /* return opcode, data is on arg stack      */
} /* ---------------------------------------------------------------------- */   


/* ------------------------------------------------------------------------ 
 * cff_get_charstrings(FSP SL32 nchars, SL32 pos)
 *
 * aquires memory and initializes entire charstring array to zeros 
 * stores handle in gpps
 * ------------------------------------------------------------------------ */
SL32 cff_get_charstrings(FSP SL32 nchars, SL32 pos)
{
    PCDATASTR pcharstrings;

    free_charstrings(FSA if_state.gpps);

    if_state.gpps->n_chars = nchars;
    
                /* ----- allocate charstrings dictionary  - for one entry */
    if_state.gpps->hcharstrings = BUFalloc (FSA (SL32)(sizeof (CDATASTR)));    /* only allocate 1 05-23-01 jfd */
    if(!if_state.gpps->hcharstrings)
    {
        DBG2 ("%s%s", "cff_get_charstrings", "mem problem"); 
        return ERR_cff_no_str_mem; 
    }
    pcharstrings = (PCDATASTR)MEMptr (if_state.gpps->hcharstrings);
    
                /* ----- Init charstrings array so we can free it later    */
    pcharstrings->hname = NIL_MH;
    pcharstrings->hdata = NIL_MH;
    if_state.gpps->curr_char = 0;
    if_state.gpps->last_seek = pos;
    if_state.gpps->last_key = 0;
    return SUCCESS;
} /* ---------------------------------------------------------------------- */

/* ------------------------------------------------------------------------ 
 * unload_cff_font(FSP PBUCKET pxb)
 *
 * frees additional memory associated with CFF fonts
 * conditionally called from psunload_font() in t1scan.c
 * ------------------------------------------------------------------------ */
GLOBAL VOID unload_cff_font(FSP PPS_BUCK lpps)
{

    DBG3("unload cff font mem pools available 1=%d  2=%d 3=%d\n", 
       if_state.pserver->mem_avail[0], if_state.pserver->mem_avail[1],
       if_state.pserver->mem_avail[2]);


   /* free CFF Encoding Array */
   if (lpps->hcffencodearray)
   {
      BUFfree (FSA lpps->hcffencodearray);
      lpps->hcffencodearray = NIL_MH;
   }
    
   /* free CFF Charset Array */
   if (lpps->hcharsetarray)
   {
      BUFfree (FSA lpps->hcharsetarray);
      lpps->hcharsetarray = NIL_MH;
   }
   /* free CID CFF FontDict Select Array */
   if (lpps->hFDSelect)
   {
      BUFfree (FSA lpps->hFDSelect);
      lpps->hFDSelect = NIL_MH;

   }

} /* ---------------------------------------------------------------------- */


/* ------------------------------------------------------------------------ 
*  int2fixpt(SL32)    convert val to 16.16 fixed point format xxxx.xxxx 
*
*  If val is not already a fixed floating point value, * val by 65536.
*  The tests assume that all non fixpt vals are ints in the range of 
*  --32767L to +32768. 
* ------------------------------------------------------------------------ */
GLOBAL SL32 int2fixpt(SL32 val)
{
/*    if(val < 32768 || -32767 < val) */
    if(val < 2048 || -2048 > val)    /* for maximum efficency, let the   */
        return(val * 65536);            /* compiler determine the shifts to */
    return(val);                        /*  insure proper sign extention    */
} /* ---------------------------------------------------------------------- */   

/* ------------------------------------------------------------------------ 
*  wholeFixPt2int(SL32)    convert val from fixed point to int
*
*  But, only if it is a whole number. 
*  Leave as is, if it contains a fraction
* ------------------------------------------------------------------------ */
GLOBAL SL32 wholeFixPt2int(SL32 val)
{                    
    if((val & 0xffff0000) && (val & 0x0000ffff) == 0)
        return(val / 65536);    /* let the compiler determine the shifts    */
    return(val);                /* for the various platforms                */
} /* ---------------------------------------------------------------------- */   


/* ------------------------------------------------------------------------ 
*  roundFixPt2int(SL32)    convert val from fixed point to int
*
*  Truncate any fractions
* ------------------------------------------------------------------------ */
GLOBAL SL32 roundFixPt2int(SL32 val)
{                    
    if(val < 65535 && -65535 < val)   /* positive and negative numbers */
        return(val);
    return(val / 65536);
} /* ---------------------------------------------------------------------- */   


/* ------------------------------------------------------------------------ 
*  getStringData(LPUB8 buf, LPSL32 len, cfix* obj, SL32 index)
*
*  This function resolves a string of text or data and returns it in buf.
*  If called with a NULL *buf, it returns only the len of the string.
*  The caller is responsible for allocating and freeing the buf memory.
*  The second call with a valid *buf will put the string data into buf. 
*
* ------------------------------------------------------------------------ */
GLOBAL SL32 getStringData(FSP
    LPUB8 buf,   /* if NULL, returns the len of the string, else fill data */
    LPSL32 len,  /* output the size of the string (to be or) returned      */
    cfix* obj,   /* cff index struct for string, global or local subr      */
    UL32 index)  /* the SID or item count used to determine the offset     */
{
    UB8 tempbuf[10];
    SL32 newlen, seek, fpos = 0, stt, end;

    if(index < 1 || index > obj->items)
        return ERR_cff_T2_Index_err;


    /*----- find selected string */
    fpos = seekandread(FSA tempbuf, obj->stt + ((index-1) * obj->step), 8);
    if(fpos != 8) 
        return ERR_cff_bad_read;
    
    stt = variablevalue(tempbuf, obj->step);        
    end = variablevalue(tempbuf + obj->step, obj->step);
    newlen = end-stt;
    if(newlen < 1) 
        return ERR_cff_bad_read_len;
    else
        *len = newlen + 1;      /* add zero termination */
    if(!buf)
        return SUCCESS;
    if(newlen <= *len)
    {
        /*----- read and process top and private DICT  */
        seek = obj->zbase + stt -1; 
    
        fpos = seekandread(FSA buf, seek, newlen);
        buf[newlen] = 0;
    }
    if(fpos < newlen) 
        return ERR_cff_bad_read;
    return SUCCESS;
} /* ---------------------------------------------------------------------- */   


#endif /* CFF_RDR */
#endif /* PST1_RDR */
 

cg_multi.c   ///

/* 
 * Copyright (C) 2003 Agfa Monotype Corporation. All rights reserved.
 */
/* $Header:   I:/BULL/URIP/RTS/DEP/cg_multi.c_v   1.6   Dec 14 2004 16:16:42   dugganj  $ */
/* $Log:   I:/BULL/URIP/RTS/DEP/cg_multi.c_v  $
 * 
 *    Rev 1.6   Dec 14 2004 16:16:42   dugganj
 * Added multithread version of CGIFchar_map().
 * 
 * 
 *    Rev 1.5   Nov 15 2004 10:25:48   azimaf
 * removed all references to WTLE_API
 * 
 *    Rev 1.4   Oct 26 2004 11:29:36   dugganj
 * Multithreading changes.
 * 
 *    Rev 1.3   Oct 25 2004 17:24:34   galejss
 * remove duplicate global data (for FONTBBOX); fix some compile errors; add CGIFget_kern_value
 * 
 *    Rev 1.2   Oct 13 2004 08:16:28   dugganj
 * Added missing fucntion CGIFtt_query().
 * 
 *    Rev 1.1   Oct 01 2004 14:44:32   azimaf
 * added CGIFFmem_purge to handle mutlti-
 * threading for purging CACHE and BUFFER pool
 * 
 *    Rev 1.0   Sep 28 2004 09:02:22   dugganj
 * Initial revision.
 */

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

#include <stdio.h>
#include <string.h>
#include "cgconfig.h"

#include "ufstport.h"

#if MAYBE_FCNTL_H
#include <fcntl.h>
#endif

#if MAYBE_IO_H
#include <io.h>
#endif

#if MAYBE_UNISTD_H
#include <unistd.h>
#endif

#include "dbg_ufst.h"

#include "shareinc.h"

#include "fontmath.h"

#if TT_RDR
#include "sfntenum.h"
#endif

#include "mixmodel.h"
#include "dll.h"
#include "cgmacros.h"

#include <stdlib.h>

#if MAYBE_MALLOC_H
#include <malloc.h>
#endif


#if TT_ROM_ACT
#include "config.h"
#include "ra_mem.h"
#include "bitio.h"
#include "radecomp.h"
#endif


/*-----------------*/
/*  MTinit         */
/*-----------------*/
/*
This function initializes the multi-thread manager.
*/

#if defined (ANSI_DEFS)
GLOBAL UW16 MTinit(FSP0)
#else
GLOBAL UW16 MTinit()
#endif /* ANSI_DEFS */
{
    if_state.pserver = (CG_SERVER *)&if_state.server;

    /* Initialize the rest of the shared server data */

#if 1
    /* Initialize the copy of the current system fontcontext */
    MEMSET(&if_state.pserver->cur_loc_fc, 0, sizeof(FONTCONTEXT));
#endif

    if_state.pserver->hBUCKlru = (MEM_HANDLE)NIL_MH;
#if CACHE
    if_state.pserver->hFNTlru = (MEM_HANDLE)NIL_MH;
    if_state.pserver->hBMlru = (MEM_HANDLE)NIL_MH;
#endif
#if UFST_MULTITHREAD
    if_state.pserver->client_count = 1;    /* 10-25-04 jfd - was 0 */
#endif

#if FCO_RDR
    if_state.pserver->FCO_List = 0;
#if PLUGINS
    if_state.pserver->FCO_pTrees = 0;
    if_state.pserver->fco_StickyPlugin = 0;
#endif  /* PLUGINS */
#endif    /* FCO_RDR */

    if_state.pserver->MTinitstate  = not_BUCKlru | not_FNTlru | not_BMlru;    /* set not initialized bits */
    return SUCCESS;
}

#if UFST_MULTITHREAD

#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFinit(FSP0)
#else
UW16 CGENTRY
CGIFinit()
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    status = CGIFFinit(FSA0);
    if (status)
        return status;

    if_state.error = CGIFcreate_mutex(FSA0);
    if (if_state.error)
        return (UW16)if_state.error;

    if_state.error = CGIFcreate_app_mutex(FSA0);
    return (UW16)if_state.error;
}


/*----------------------*/
/*    CGIFenter         */
/*----------------------*/
/*  This function is called once after the memory pools have been funded
 *  to initialize the cache and the font management subsystem.

 * Read PostScript mapping table into memory if PS is enabled. - 5/21/92 - rs
 */

#if defined (ANSI_DEFS)
UW16  CGENTRY CGIFenter (FSP0)
#else
UW16  CGENTRY
CGIFenter()
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFenter(FSA0);

    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}


/*----------------------*/
/*    CGIFexit          */
/*----------------------*/

#if defined (ANSI_DEFS)
UW16  CGENTRY CGIFexit (FSP0)
#else
UW16  CGENTRY
CGIFexit()
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

#if UFST_MULTITHREAD
    /* one fewer active client */
    if_state.pserver->client_count--;
#endif
    status = CGIFFexit(FSA0);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

     if_state.error = CGIFrelease_mutex(FSA0);
    if (if_state.error)
        return if_state.error;

    if_state.error = CGIFdelete_mutex(FSA0);
    if (if_state.error)
        return if_state.error;

    if_state.error = CGIFdelete_app_mutex(FSA0);
    return if_state.error;
} /* CGIFexit() */


/* ------------------------------- CGIFfont -------------------------------
 *
 * Description: The application calls this function when the current font-
 *              context changes.
 * Parameters:  fc - pointer to FONTCONTEXT structure.
 * Returns:     UW16 status code ( 0 = SUCCESS, nonzero = error )
 *
 */
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFfont (FSP PFONTCONTEXT fc)
#else
UW16 CGENTRY CGIFfont (fc)
    PFONTCONTEXT  fc;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFfont(FSA fc);

    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}       /* CGIFfont() */


/*--------------------------------------------------------------------*/
/*  All entries below are conditionally compiled depending on which
 *  options have been set in cgconfig.h
 */


#if CHAR_HANDLE

/*----------------------*/
/*    CGIFchar_handle   */
/*----------------------*/
/*  Return a handle  to the requested character IFBITMAP.  */
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFchar_handle (FSP UL32 chId, PHIFBITMAP phbm, SW16 alt_width)
#else
UW16 CGENTRY CGIFchar_handle(chId, phbm, alt_width)
    UL32       chId;
    PHIFBITMAP phbm;
    SW16       alt_width;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFchar_handle(FSA chId, phbm, alt_width);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif  /*  CHAR_HANDLE  */

/* -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- */


#if CACHE
/*----------------------*/
/*    CGIFchar          */
/*----------------------*/
/*  Character generation used with AGFA supplied character cache.
 *  May be used with internal or external memory manager.
 *  Return a pointer to the requested character IFBITMAP.
 *  Return nil if the character is not in the cache and cannot be
 *  made or if bad input data.
 *  If caller ID has changed since the last call to this function, then the 
 *  saved state (from CGIFconfig, CGIFfont) of the caller must be restored.
 */

#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFchar (FSP UL32 chId, PPIFBITMAP ppbm, SW16 alt_width)
#else
UW16 CGENTRY
CGIFchar(chId, ppbm, alt_width)
    UL32      chId;
    PPIFBITMAP ppbm;
    SW16       alt_width;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFchar(FSA chId, ppbm, alt_width);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}

#if CACHE_BY_REF
/* New "cache-by-reference" caching method */
/*----------------------*/
/*    CGIFchar_by_ref   */
/*----------------------*/
/*  Character generation used with AGFA supplied character cache
 *  and "cache-by-reference" method.
 *  May be used with internal or external memory manager.
 *  Return pointers to the requested character IFBITMAP.
 *  Increments the cache-by-reference counter.
 *  Return nil if the character is not in the cache and cannot be
 *  made or if bad input data.
 *  If caller ID has changed since the last call to this function, then the 
 *  saved state (from CGIFconfig, CGIFfont) of the caller must be restored.
 */
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFchar_by_ref (FSP UL32 chId, PPIFBITMAP ppbm, SW16 alt_width)
#else
UW16 CGENTRY
CGIFchar_by_ref(chId, ppbm, alt_width)
    UL32      chId;
    PPIFBITMAP ppbm;
    SW16       alt_width;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
{
        return (UW16)if_state.error;
}

    status = CGIFFchar_by_ref(FSA chId, ppbm, alt_width);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}

#endif    /* CACHE_BY_REF */

#endif  /* CACHE */

/* -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- */


#if CHAR_SIZE
/*----------------------*/
/*    CGIFchar_size     */
/*----------------------*/
/* Character generator for application managed bitmap buffers */

#if defined (ANSI_DEFS)
#if (MAX_BM_BITS > 16)
UW16  CGENTRY CGIFchar_size (FSP UL32 chId, LPSL32 size, SW16 alt_width)
#else
UW16  CGENTRY CGIFchar_size (UL32 chId, LPUW16 size, SW16 alt_width)
#endif /* MAX_BM_BITS */
#else /* !ANSI_DEFS */
UW16  CGENTRY CGIFchar_size (chId, size, alt_width)
    UL32    chId;
#if (MAX_BM_BITS > 16)
    LPSL32    size;
#else
    LPUW16   size;
#endif
    SW16     alt_width;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFchar_size(FSA chId, size, alt_width);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif  /* CHAR_SIZE */

/* -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- */


#if (TILE && CGBITMAP)
/*----------------------*/
/*    CGIFbmheader      */
/*----------------------*/
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFbmheader (FSP UL32 chId, PIFBITMAP pbm, SW16 alt_width)
#else
UW16 CGENTRY CGIFbmheader (chId, pbm, alt_width)
    UL32     chId;
    PIFBITMAP pbm;
    SW16      alt_width;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFbmheader(FSA chId, pbm, alt_width);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}


#if CHAR_HANDLE
/*----------------------*/
/*    CGIFtile_handle   */
/*----------------------*/

#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFtile_handle (FSP PIFTILE piftile, PHIFBITMAP phbm)
#else
UW16 CGENTRY CGIFtile_handle (piftile, phbm)
    PIFTILE piftile;
    PHIFBITMAP phbm;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFtile_handle(FSA piftile, phbm);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif /* CHAR_HANDLE */

#if CACHE
/*----------------------*/
/*    CGIFtile          */
/*----------------------*/
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFtile (FSP PIFTILE piftile, PPIFBITMAP ppbm)
#else
UW16 CGENTRY CGIFtile (piftile, ppbm)
    PIFTILE piftile;
    PPIFBITMAP ppbm;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFtile(FSA piftile, ppbm);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}

#endif /* CACHE */
#endif  /* TILE && CGBITMAP */

#if WIDTHS
#if defined (ANSI_DEFS)
#if /* NO_SYMSET_MAPPING */ WIDTH_NOSYMMAP
UW16 CGENTRY CGIFwidth (FSP PWIDTH_LIST_INPUT_ENTRY PointerToList, UW16 NumEntriesInList,
                        UW16 buffer_size, LPUW16 buffer)
#else
UW16 CGENTRY CGIFwidth (FSP UL32 first_chId, UW16 num_chId,
                        UW16 buffer_size, LPUW16 buffer)
#endif    /* NO_SYMSET_MAPPING */
#else
#if NO_SYMSET_MAPPING
UW16 CGENTRY CGIFwidth (PointerToList, NumEntriesInList, buffer_size, buffer)
   PWIDTH_LIST_INPUT_ENTRY PointerToList;
   UW16   NumEntriesInList;
   UW16   buffer_size;
   LPUW16 buffer;
#else
UW16 CGENTRY CGIFwidth (first_chId, num_chId, buffer_size, buffer)
    UL32  first_chId;
    UW16  num_chId;
    UW16  buffer_size;
    LPUW16 buffer;
#endif /* WIDTH_NOSYMMAP */
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

#if /* NO_SYMSET_MAPPING */ WIDTH_NOSYMMAP
    status = CGIFFwidth(FSA PointerToList, NumEntriesInList, buffer_size, buffer);
#else
    status = CGIFFwidth(FSA first_chId, num_chId, buffer_size, buffer);
#endif    /* WIDTH_NOSYMMAP */
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif  /* WIDTHS */


#if IF_RDR
#if SEGACCESS
/*------------------*/
/*   CGIFsegments   */
/*------------------*/
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFsegments (FSP SL32 tfnum, UW16 key, LPUW16 psize, LPSB8 pbuffer)
#else
UW16 CGENTRY CGIFsegments (tfnum, key, psize, pbuffer)
    SL32        tfnum;
    UW16       key;
    LPUW16      psize;
    LPSB8       pbuffer;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFsegments(FSA tfnum, key, psize, pbuffer);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}

#endif  /* SEGACCESS */
#endif  /* IF_RDR */

/*------------------*/
/*  CGIFfont_purge  */
/*-----------------------------*/
/*  CGIFcache_purge (obsolete) */
/*-----------------------------*/
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFfont_purge (FSP PFONTCONTEXT fc)
#else
UW16 CGENTRY CGIFfont_purge (fc)
   PFONTCONTEXT fc;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFfont_purge(FSA fc);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
/*--------------------*/
/*  CGIFmem_purge  */
/*--------------------*/

#if defined (ANSI_DEFS)
UL32 CGENTRY CGIFmem_purge (FSP UL32 ActionFlag)
#else
UL32 CGENTRY CGIFmem_purge (ActionFlag)
   UL32 ActionFlag;
#endif /* ANSI_DEFS */
{
    SL32 ActualMemoryFreed = 0; 
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return ActualMemoryFreed;
    ActualMemoryFreed = CGIFFmem_purge(FSA ActionFlag);
    if_state.error = CGIFrelease_mutex(FSA0);
    return ActualMemoryFreed;
}

/*--------------------*/
/*  CGIFbucket_purge  */
/*--------------------*/

#if defined (ANSI_DEFS)
UL32 CGENTRY CGIFbucket_purge (FSP UL32 ActionFlag)
#else
UL32 CGENTRY CGIFbucket_purge (ActionFlag)
   UL32 ActionFlag;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFbucket_purge(FSA ActionFlag);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}

/*--------------------------*/
/*  CGIFhdr_font_purge      */
/*--------------------------*/
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFhdr_font_purge (FSP PFONTCONTEXT fc)
#else
UW16 CGENTRY CGIFhdr_font_purge (fc)
   PFONTCONTEXT fc;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFhdr_font_purge(FSA fc);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}


//extern char cTempBuffer[];
//void Send_String(char *);

#if FCO_RDR
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFfco_Open( FSP LPUB8 fcName, LPSW16 FChandle )
#else
UW16 CGENTRY CGIFfco_Open( fcName, FChandle )
    LPUB8 fcName;
    LPSW16 FChandle;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFfco_Open(FSA fcName, FChandle);

    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    
    return if_state.error;
}

#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFfco_Close( FSP SW16 FChandle )
#else
UW16 CGENTRY CGIFfco_Close( FChandle )
    SW16 FChandle;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFfco_Close(FSA FChandle);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}

#endif  /* FCO_RDR */

#if FNT_METRICS

#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFfont_metrics( FSP FONT_METRICS* mtx )
#else
UW16 CGENTRY CGIFfont_metrics( mtx )
    FONT_METRICS* mtx;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFfont_metrics(FSA mtx);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
} /*** CGIFfont_metrics ***/
#endif  /* FNT_METRICS */

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

#if FONTBBOX

#if defined (ANSI_DEFS)
#if VLCOUTPUT
UW16 CGENTRY CGIFbound_box( FSP SL32 FontBBox[4], LPSW16 pVLCpower )
#else
UW16 CGENTRY CGIFbound_box( FSP SL32 FontBBox[4] )
#endif /* VLCOUTPUT */
#else /* !ANSI_DEFS */
#if VLCOUTPUT
UW16 CGENTRY CGIFbound_box( FontBBox, pVLCpower )
    SL32         *FontBBox;
    LPSW16        pVLCpower;
#else
UW16 CGENTRY CGIFbound_box( FontBBox )
    SL32         *FontBBox;
#endif /* VLCOUTPUT */
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFbound_box(FSA FontBBox, pVLCpower);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
/* CGIFbound_box */
#endif  /* FONTBBOX */

#if (TT_ROM || TT_DISK || TT_ROM_ACT)
/**************************************************************************/
/* Function:    CGIFtt_query - API to retrieve the buffer containing the  */
/*              whole TrueType table entry, based on a tag id and TTC     */
/*              index (if applicable).  This routine assumes that the     */
/*              caller knows the structure of the table being returned.   */
/*                                                                        */
/*              1st call - pBuffer should be NULL; will get the size      */
/*              of the requested table                                    */
/*              2nd call - fills pBuffer with the table                   */
/*                                                                        */
/* Parameters:  pFont(I) - ptr to pathname (disk) or truetype font in rom */
/*              uTagKey(I) - 4-byte identifier for the TT table           */
/*              uTTCindex(I) - index into TTC array of table directories  */
/*              uSize(O/I) - size of the tag's table                      */
/*              pBuffer(O) - buffer of size uSize to hold the table entry */
/*                                                                        */
/* Return:  UW16 - Did the function successfully retrieve the TT tag      */
/*          information from the font tables; SUCCESS or FAILURE.         */
/* Created: ks - December 27, 1999                                        */
/**************************************************************************/

#if defined (ANSI_DEFS)
UW16  CGENTRY CGIFtt_query (FSP LPUB8 pFont, UL32 uTagKey, UW16 uTTCIndex,
                            LPUL32 uSize, LPUB8 pBuffer )
#else
UW16  CGENTRY CGIFtt_query (pFont, uTagKey, uTTCIndex, uSize, pBuffer )
LPUB8 pFont;
UL32 uTagKey;
UW16 uTTCIndex;
LPUL32 uSize;
LPUB8 pBuffer;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFtt_query(FSA pFont, uTagKey, uTTCIndex, uSize, pBuffer);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif

#if (TT_ROM || TT_DISK || TT_ROM_ACT)
#if (CACHE || CHAR_HANDLE) && DIRECT_TT_TABLE_ACCESS
#if defined (ANSI_DEFS)
UW16  CGENTRY CGIFtt_query_direct (FSP LPUB8 pFont, UL32 uTagKey, UW16 uTTCIndex,
                            LPUL32 uSize, LPLPUB8 pBuffer )
#else
UW16  CGENTRY CGIFtt_query_direct (pFont, uTagKey, uTTCIndex, uSize, pBuffer )
LPUB8 pFont;
UL32 uTagKey;
UW16 uTTCIndex;
LPUL32 uSize;
LPLPUB8 pBuffer;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFtt_query_direct(FSA pFont, uTagKey, uTTCIndex, uSize, pBuffer);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}

#if defined (ANSI_DEFS)
UW16  CGENTRY CGIFtt_query_direct_free (FSP LPUB8 pTable)
#else
UW16  CGENTRY CGIFtt_query_direct_free ( pTable )
LPUB8 pTable;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFtt_query_direct_free(FSA pTable);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif

#if defined (ANSI_DEFS)
UW16  CGENTRY CGIFtt_cmap_query (FSP UB8 *pFont, UW16 uTTCIndex, CMAP_QUERY *ret)
#else
UW16  CGENTRY CGIFtt_cmap_query (pFont, uTTCIndex, ret)
UB8 *pFont;
UW16 uTTCIndex;
CMAP_QUERY *ret;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFtt_cmap_query(FSA pFont, uTTCIndex, ret);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}    /* CGIFtt_cmap_query() */

#if defined (ANSI_DEFS)
UW16  CGENTRY CGIFtt_name_query (FSP UB8 *pFont, UW16 uTTCIndex, NAME_QUERY *ret)
#else
UW16  CGENTRY CGIFtt_name_query (pFont, uTTCIndex, ret)
UB8 *pFont;
UW16 uTTCIndex;
NAME_QUERY *ret;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFtt_name_query(FSA pFont, uTTCIndex, ret);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}    /* CGIFtt_name_query() */

#endif  /* TT_ROM || TT_DISK || TT_ROM_ACT */

#if 1    /* 06-23-04 jfd ADDED THE FUNCTIONS BELOW */

#if INT_MEM_MGT && DEFUND  /*  internal memory manager  */
#if defined (ANSI_DEFS)
GLOBAL UW16 CGENTRY CGIFdefund (FSP UW16 page)
#else
GLOBAL UW16 CGENTRY CGIFdefund (page)
    UW16  page;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFdefund(FSA page);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* INT_MEM_MGT && DEFUND */

#if TILE && CHAR_SIZE
#if defined (ANSI_DEFS)
GLOBAL UW16 CGENTRY CGIFtilebitMap(FSP PIFTILE piftile, PIFBITMAP tile_bm,
    LPUB8 nzw_buf)
#else
GLOBAL UW16 CGENTRY
CGIFtilebitMap(piftile, tile_bm, nzw_buf)
    PIFTILE    piftile;
    PIFBITMAP  tile_bm;            /* Final result goes here */
    LPUB8      nzw_buf;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFtilebitMap(FSA piftile, tile_bm, nzw_buf);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* TILE && CHAR_SIZE */

#if CHAR_SIZE
#if defined (ANSI_DEFS)
GLOBAL UW16 CGENTRY CGIFmakechar(FSP PIFBITMAP bm, LPUB8 nzw_buf)
#else
GLOBAL UW16 CGENTRY
CGIFmakechar(bm, nzw_buf)
    PIFBITMAP bm;             /* Final result goes here */
    LPUB8    nzw_buf;         /* non zero winding buffer */
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFmakechar(FSA bm, nzw_buf);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* CHAR_SIZE */

#if CACHE && CACHE_BY_REF
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFfree_by_ref (FSP PIFBITMAP pifb)
#else
UW16 CGENTRY
CGIFfree_by_ref(pifb)
    PIFBITMAP pifb;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFfree_by_ref(FSA pifb);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* CACHE && CACHE_BY_REF */

#if FCO_RDR && FCOACCESS
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFfco_Access( FSP LPUB8 fcPathName, UW16 fco_Index, UW16 Info_Key, LPUW16 pSize, LPSB8 pBuffer )
#else
UW16 CGENTRY CGIFfco_Access( fcPathName, fco_Index, Info_Key, pSize, pBuffer )
   LPUB8  fcPathName;
   UW16   fco_Index;
   UW16   Info_Key;
   LPUW16 pSize;
   LPSB8  pBuffer;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFfco_Access(FSA fcPathName, fco_Index, Info_Key, pSize, pBuffer);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* FCO_RDR && FCOACCESS */

#if UNICODE_IN
#if JIS_ENCODING
#if defined (ANSI_DEFS)
GLOBAL UW16 CGIFinitUnicodeToJisTbl(FSP LPSB8 tblPtr, UL32 tblSize)
#else
GLOBAL UW16 CGIFinitUnicodeToJisTbl(tblPtr, tblSize)
  LPSB8 tblPtr;
  UL32 tblSize;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFinitUnicodeToJisTbl(FSA tblPtr, tblSize);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif  /* JIS_ENCODING */

#if K_ENCODING
#if defined (ANSI_DEFS)
GLOBAL UW16 CGIFinitUnicodeToKscTbl(FSP LPSB8 tblPtr, UL32 tblSize)
#else
GLOBAL UW16 CGIFinitUnicodeToKscTbl(tblPtr, tblSize)
  LPSB8 tblPtr;
  UL32 tblSize;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFinitUnicodeToKscTbl(FSA tblPtr, tblSize);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif   /*  K_ENCODING  */

#if BIG5_ENCODING
#if defined (ANSI_DEFS)
GLOBAL UW16 CGIFinitUnicodeToBig5Tbl(FSP LPSB8 tblPtr, UL32 tblSize)
#else
GLOBAL UW16 CGIFinitUnicodeToBig5Tbl(tblPtr, tblSize)
  LPSB8 tblPtr;
  UL32 tblSize;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFinitUnicodeToBig5Tbl(FSA tblPtr, tblSize);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif   /*  BIG5_ENCODING  */

#if GB_ENCODING
#if defined (ANSI_DEFS)
GLOBAL UW16 CGIFinitUnicodeToGbTbl(FSP LPSB8 tblPtr, UL32 tblSize)
#else
GLOBAL UW16 CGIFinitUnicodeToGbTbl(tblPtr, tblSize)
  LPSB8 tblPtr;
  UL32 tblSize;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFinitUnicodeToGbTbl(FSA tblPtr, tblSize);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif   /*  GB_ENCODING  */
#endif /* UNICODE_IN */

#if (UNICODE_MAPPING & JIS2UNI_MAP)
#if defined (ANSI_DEFS)
GLOBAL UW16 CGIFinitJisToUnicodeTbl(FSP LPSB8 tblPtr, UL32 tblSize)
#else
GLOBAL UW16 CGIFinitJisToUnicodeTbl(tblPtr, tblSize)
  LPSB8 tblPtr;
  UL32 tblSize;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFinitJisToUnicodeTbl(FSA tblPtr, tblSize);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* UNICODE_MAPPING & JIS2UNI_MAP */

#if (UNICODE_MAPPING & KSC2UNI_MAP)
#if defined (ANSI_DEFS)
GLOBAL UW16 CGIFinitKscToUnicodeTbl(FSP LPSB8 tblPtr, UL32 tblSize)
#else
GLOBAL UW16 CGIFinitKscToUnicodeTbl(tblPtr, tblSize)
  LPSB8 tblPtr;
  UL32 tblSize;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFinitKscToUnicodeTbl(FSA tblPtr, tblSize);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* UNICODE_MAPPING & KSC2UNI_MAP */

#if (UNICODE_MAPPING & BIG52UNI_MAP)
#if defined (ANSI_DEFS)
GLOBAL UW16 CGIFinitBig5ToUnicodeTbl(FSP LPSB8 tblPtr, UL32 tblSize)
#else
GLOBAL UW16 CGIFinitBig5ToUnicodeTbl(tblPtr, tblSize)
  LPSB8 tblPtr;
  UL32 tblSize;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFinitBig5ToUnicodeTbl(FSA tblPtr, tblSize);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* UNICODE_MAPPING & KSC2UNI_MAP */

#if (UNICODE_MAPPING & GB2UNI_MAP)
#if defined (ANSI_DEFS)
GLOBAL UW16 CGIFinitGbToUnicodeTbl(FSP LPSB8 tblPtr, UL32 tblSize)
#else
GLOBAL UW16 CGIFinitGbToUnicodeTbl(tblPtr, tblSize)
  LPSB8 tblPtr;
  UL32 tblSize;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFinitGbToUnicodeTbl(FSA tblPtr, tblSize);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* UNICODE_MAPPING & KSC2UNI_MAP */

#if defined (ANSI_DEFS)
MEM_HANDLE CGENTRY CGIFnew_client(FSP0)
#else
MEM_HANDLE CGENTRY CGIFnew_client()
/* PIFCONFIG pcfg; */
#endif
{
    MEM_HANDLE hstate;
    PIF_STATE state;
    
    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (MEM_HANDLE)NIL_MH;

    /* clone a STATE */
    hstate = BUFalloc(FSA sizeof(IF_STATE));
    if (hstate != (MEM_HANDLE)NIL_MH)
    {
        state = (PIF_STATE)MEMptr(hstate);

        /* initialize new STATE */
        /* NOTE: We can't call CGIFFinit() because the */
        /* shared server data has already been set up. */
        init_former_globals(state);

        /* use same mutex */
        state->mutex_ptr = if_state.mutex_ptr;

        /* use same application mutex */
        state->app_mutex_ptr = if_state.app_mutex_ptr;

        /* use same server */
        state->pserver = if_state.pserver;

        /* one more active client */
        state->pserver->client_count++;
    }
    else
        if_state.error = ERRmem;

    if_state.error = CGIFrelease_mutex(FSA0);
    return hstate;
}

#if defined (ANSI_DEFS)
SL32 CGENTRY CGIFend_client(FSP MEM_HANDLE mh)
#else
SL32 CGENTRY CGIFend_client(mh)
MEM_HANDLE mh;
#endif
{
    SL32 status = SUCCESS;

    PIF_STATE pclient;

    pclient = (PIF_STATE)MEMptr(mh);

    if_state.error = CGIFobtain_mutex(pclient);
    if (if_state.error != SUCCESS)
        return if_state.error;

#if UFST_MULTITHREAD
    /* one fewer active client */
    if_state.pserver->client_count--;
#endif

    status = CGIFFexit(pclient);
    if (status)
    {
        CGIFrelease_mutex(pclient);
        return status;
    }

    if_state.error = CGIFrelease_mutex(pclient);
    if (if_state.error != SUCCESS)
        return if_state.error;

    BUFfree(pclient, mh);
    return SUCCESS;
}
#endif    /* 06-23-04 jfd */

#if FCO_RDR
/*------------------*/
/*  CGIFfco_Plugin  */
/*------------------*/
/*  This function permanently selects an FCO where the plugins are located.
 *  The handle of the FCO is 'FChandle'.
 */

#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFfco_Plugin( FSP SW16 FChandle )
#else
UW16 CGENTRY CGIFfco_Plugin( FChandle )
    SW16 FChandle;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFfco_Plugin(FSA FChandle);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* FCO_RDR */

#if defined (ANSI_DEFS)
VOID CGENTRY CGIFCHARfree( FSP MEM_HANDLE h )
#else
VOID CGENTRY CGIFCHARfree( h )
    MEM_HANDLE h;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return;

    CHARfree(FSA h);

     if_state.error = CGIFrelease_mutex(FSA0);
    return;
}

#if CHAR_SIZE && TILE && NON_Z_WIND
/*----------------------*/
/*   CGIFtile_nzw_buf   */
/*----------------------*/
#if defined (ANSI_DEFS)
GLOBAL UW16 CGENTRY CGIFtile_nzw_buf(FSP PIFTILE piftile, LPSL32 psize)
#else
GLOBAL UW16 CGENTRY
CGIFtile_nzw_buf(piftile, psize)
    PIFTILE    piftile;
    LPSL32      psize;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFtile_nzw_buf(FSA piftile, psize);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* CHAR_SIZE && TILE && NON_Z_WIND */

#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFchar_get_gpos_pts(FSP UW16 index, UW16 num, UW16 *pts, SL32 *x, SL32 *y)
#else 
UW16 CGENTRY CGIFchar_get_gpos_pts(index, num, pts, x, y)
UW16 index;
UW16 num;
UW16 *pts;
SL32 *x;
SL32 *y
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFchar_get_gpos_pts(FSA index, num, pts, x, y);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}


#if TT_RDR
#if defined (ANSI_DEFS)
SW16 CGENTRY CGIFget_kern_value(FSP UB8 *tableBuffer, UL32 id1, UL32 id2)
#else
SW16 CGENTRY CGIFget_kern_value(tableBuffer, id1, id2 )
UB8 *tableBuffer;
UL32 id1, id2;
#endif
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFget_kern_value(FSA tableBuffer, id1, id2);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#endif    /* TT_RDR */

#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFchar_map(FSP UL32 chId, UW16 *glyph_index)
#else
UW16 CGENTRY CGIFchar_map(chId, glyph_index)
    UL32 chId;
    UW16 *glyph_index;
#endif /* ANSI_DEFS */
{
    UW16 status = SUCCESS;

    if_state.error = CGIFobtain_mutex(FSA0);
    if (if_state.error != SUCCESS)
        return (UW16)if_state.error;

    status = CGIFFchar_map(FSA chId, glyph_index);
    if (status)
    {
        CGIFrelease_mutex(FSA0);
        return status;
    }

    if_state.error = CGIFrelease_mutex(FSA0);
    return if_state.error;
}
#if THREAD_DUMP
#if defined (ANSI_DEFS)
GLOBAL VOID print_current_thread(FSP0)
#else 
GLOBAL VOID print_current_thread()
#endif
{
    printf("\n thread %8x", get_thread_id(FSA0));
}
#endif    /* THREAD_DUMP */

#endif    /* UFST_MULTITHREAD */


 

  • 23
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值