T168_Debug222\appl\Barcode\Two\MPDF文件:独立的.c文件

MPDFENCDATA.C文件  /

/****************************************        B-N(伀)            *********************************/
/****************************************        B-N(仾)            *********************************/
/*********************************************************************
* Module Header
*
*  Identification:   encdata.c - Encoder Top Level
*  Copyright (c) 1993-1997 Symbol Technologies, Inc.
*
* Edit History:      
*  $Log: ENCDATA.C $
*  Revision 1.12  1997/12/31 18:52:50  Anne
*  Added cast to remove warning
*  Revision 1.11  1997/12/31 00:48:18  Anne
*  Correction for revision description previously entered.  The changes made
*  were for disabling macro character substitution and bug fixes related to
*  macro character substitution and code128 emulation.
*  Revision 1.10  1997/12/31 00:48:18  Anne
*  Added field  for disable Macro Character Substitution in app params 
*  data structure.
*  Revision 1.9  1997/12/03 17:23:06  Anne
*  Fixed bug related to encoding using  Macro Character Substitution for 
*  strange input data - last field is unprintable data, ending in rs eot.
*  Revision 1.8  1997/12/02 17:26:34  Anne
*  Removed check for numeric mode for certain AI's in Code128 Emulation
*  mode.  Allowed RS to be followed by no EOT if at eof when doing macro
*  character substitutuion. 
*  Revision 1.7  1997/12/01 16:34:32  Anne
*  Removed unnecessary call to optimize_mode when doing macro char 
*  substitution for MicroPDF.
*  Revision 1.6  1997/11/25 21:56:26  Anne
*  Changes for Code128 Emulation and Macro Character Substitution 
*  features of MicroPDF.  Structured Append is disabled for these features
*  in this revision.
*  Revision 1.5  1997/06/17 16:04:34  toml
*  Handle special case for switching into NUMeric compaction
*  for sequences less than 13 digits. This is efficient when the
*  sequence is at the end or preceeds a BINary sequence
*  Revision 1.4  1997/04/29 19:29:40  toml
*  Error during ECI encode of TC data with embedded ECI latch. Was
*  using PUNCT shift as pad which could not be used in the middle
*  of a TC seq. We now submode latch for a pad when ECI active
*  Revision 1.3  1997/04/24 18:34:30  toml
*  Parse ECI formatted source and enter ECI modes
*  Revision 1.2  1997/03/06 16:26:58  toml
*  Improved the optimize_mode function to latch into numeric using
*  different crossover points based on byte following the sequence.
*  Revision 1.1  1997/02/05 16:33:18  toml
*  Initial revision
*
*  Description:      Encode data stream into PDF codewords.
*
*  Call Tree:         
*
**********************************************************************/

/*********************************************************************
                                 Include Files
*********************************************************************/
#include "pdfapi.h"
#include "apienc.h"
#include "tcmap.h"
#include "memfunc.h"
#include "pdfobj.h"
/* #include "stdio.h"    */

/*********************************************************************
                                    Defines
*********************************************************************/
#define LATCH_TC     900
#define LATCH_NUM    902
#define LATCH_BIN    901      /* non-multiple of 6 data bytes */
#define LATCH_BIN6   924      /* mutiple of 6 data bytes */

#define SHIFT_BIN    913

#define  NUM_CWLEN            15    /* 15 codeword max for numeric */                          

/*  for MicroPDF code 128 emulation */

#define  PDF128_LATCH1_C0TC      910
#define  PDF128_LATCH1_C1TC      903   /* UCC/EAN-128 - not linked */
#define  PDF128_LATCH1_C2TC      908                           
#define  PDF128_LATCH1_LC1TC     906   /* Linked UCC/EAN-128 */

#define  PDF128_LATCH1_C0NUM     911
#define  PDF128_LATCH1_C1NUM     904   /* UCC/EAN-128 - not linked */
#define  PDF128_LATCH1_C2NUM     909
#define  PDF128_LATCH1_LC1NUM    907   /* Linked UCC/EAN-128 */ 

#define  PDF128_LATCH1_C1AI01    905   /* UCC/EAN-128 - not linked */
#define  PDF128_LATCH1_LC1AIMANY 912   /* Linked UCC/EAN-128 */
#define  PDF128_LATCH1_LC1AI10   914   /* Linked UCC/EAN-128 */
#define  PDF128_LATCH1_LC1AI21   915   /* Linked UCC/EAN-128 */

#define  PDF128_LATCHx_TC_ALPHA  903   /* Non-first codeword latches */
#define  PDF128_LATCHx_TC_MIXED  904 
#define  PDF128_LATCHx_NUM       905


typedef uint8 ENCODEMODE;
#define  MODE_EOF    0
#define  MODE_TC     1
#define  MODE_BIN    2
#define  MODE_NUM    3
#define  MODE_NA     4     /* For micro PDF */
#define  MODE_ECI    5     /* Enter ECI mode */   

#define RS_MACRO_CHAR   0x1e  /* for micro pdf macro char substitution */
#define GS_MACRO_CHAR   0x1d  /* for micro pdf macro char substitution  and code 128 emulation */
#define EOT_MACRO_CHAR  0x04  /* for micro pdf macro char substitution */


/*********************************************************************
                               Local Data Types
*********************************************************************/
/*
* Flags which characters are members of the TC/NUM mode
*/
#define  A  _PDFALPHA
#define  L  _PDFLOWER
#define  M  _PDFMIXED
#define  P  _PDFPUNCT
#define  N  _PDFNUM

const uchar g_pdftcset[ 256 ] = {
      0,/* NUL */       0,/* SOH */       0,/* STX */       0,/* ETX */
      0,/* EOT */       0,/* ENQ */       0,/* ACK */       0,/* BEL */
      0,/* BS  */     M|P,/* HT  */       P,/* LF  */       0,/* VT  */
      0,/* FF  */     M|P,/* CR  */       0,/* SO  */       0,/* SI  */
      0,/* DLE */       0,/* DC1 */       0,/* DC2 */       0,/* DC3 */
      0,/* DC4 */       0,/* NAK */       0,/* SYN */       0,/* ETB */
      0,/* CAN */       0,/* EM  */       0,/* SUB */       0,/* ESC */
      0,/* FS  */       0,/* GS  */       0,/* RS  */       0,/* US  */
  M|L|A,/*     */       P,/*  !  */       P,/*  "  */       M,/*  #  */
    M|P,/*  $  */       M,/*  %  */       M,/*  &  */       P,/*  '  */
      P,/*  (  */       P,/*  )  */     M|P,/*  *  */       M,/*  +  */
    M|P,/*  ,  */     M|P,/*  -  */     M|P,/*  .  */     M|P,/*  /  */
    M|N,/*  0  */     M|N,/*  1  */     M|N,/*  2  */     M|N,/*  3  */
    M|N,/*  4  */     M|N,/*  5  */     M|N,/*  6  */     M|N,/*  7  */
    M|N,/*  8  */     M|N,/*  9  */     M|P,/*  :  */       P,/*  ;  */
      P,/*  <  */       M,/*  =  */       P,/*  >  */       P,/*  ?  */
      P,/*  @  */       A,/*  A  */       A,/*  B  */       A,/*  C  */
      A,/*  D  */       A,/*  E  */       A,/*  F  */       A,/*  G  */
      A,/*  H  */       A,/*  I  */       A,/*  J  */       A,/*  K  */
      A,/*  L  */       A,/*  M  */       A,/*  N  */       A,/*  O  */
      A,/*  P  */       A,/*  Q  */       A,/*  R  */       A,/*  S  */
      A,/*  T  */       A,/*  U  */       A,/*  V  */       A,/*  W  */
      A,/*  X  */       A,/*  Y  */       A,/*  Z  */       P,/*  [  */
      P,/*  \  */       P,/*  ]  */       M,/*  ^  */       P,/*  _  */
      P,/*  `  */       L,/*  a  */       L,/*  b  */       L,/*  c  */
      L,/*  d  */       L,/*  e  */       L,/*  f  */       L,/*  g  */
      L,/*  h  */       L,/*  i  */       L,/*  j  */       L,/*  k  */
      L,/*  l  */       L,/*  m  */       L,/*  n  */       L,/*  o  */
      L,/*  p  */       L,/*  q  */       L,/*  r  */       L,/*  s  */
      L,/*  t  */       L,/*  u  */       L,/*  v  */       L,/*  w  */
      L,/*  x  */       L,/*  y  */       L,/*  z  */       P,/*  {  */
      P,/*  |  */       P,/*  }  */       P,/*  ~  */       0,/* DEL */
/*
   bytes 128-255 do not fall into TC or NUM
*/
   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,/*128-159*/
   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,/*160-191*/
   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,/*192-223*/
   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /*224-255*/
};

/* The following strings contain the set of characters in each of the submodes */
/*
static const char tc_alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
static const char tc_lower[] = "abcdefghijklmnopqrstuvwxyz ";
static const char tc_mixed[] = "0123456789&\x0D\t,:#-.$/+%*=^\x01 ";
static const char tc_punct[] = ";<>@[\\]_`~!\x0D\t,:\x0A-.$/\"|*()?{}'";
*/
static const char tc_alpha[] = "\101\102\103\104\105\106\107\110\111\112\113\
\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\040";

static const char tc_lower[] = "\141\142\143\144\145\146\147\150\151\152\153\
\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\040";

static const char tc_mixed[] = "\060\061\062\063\064\065\066\067\070\071\046\
\015\011\054\072\043\055\056\044\057\053\045\052\075\136\001\040";

static const char tc_punct[] = "\073\074\076\100\133\134\135\137\140\176\041\
\015\011\054\072\012\055\056\044\057\042\174\052\050\051\077\173\175\047";

/* Sequences to move from one latch mode to another */
static const uchar al_to_ll[] = {27,0};
static const uchar al_to_ml[] = {28,0};
static const uchar al_to_pl[] = {28,25,0};

static const uchar ll_to_al[] = {28,28,0};
static const uchar ll_to_ml[] = {28,0};
static const uchar ll_to_pl[] = {28,25,0};

static const uchar ml_to_al[] = {28,0};
static const uchar ml_to_ll[] = {27,0};
static const uchar ml_to_pl[] = {25,0};

static const uchar pl_to_al[] = {29,0};
static const uchar pl_to_ll[] = {29,27,0};
static const uchar pl_to_ml[] = {29,28,0};

/* Any submode to Punctuation shift */
static const uchar xl_to_ps[] = {29,0};

/* Lower latch to Alpha shift */
static const uchar ll_to_as[] = {27,0};

typedef struct {
   TCSUBMODE submode;      /* maintains active sub-mode */
   uint8 len;              /* sequence length */
   uchar data[ 3 ];        /* codeword halves (TC data bytes) */
} CWSequence;

   
#ifndef NO_MICROPDF  
static TCSUBMODE find_best_submode( LPPDFObject lpio );
#endif                        
/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      add_10to900
*
* Description:       Update the 15 digit, base 900 value with another
*                    base 10 digit.  Used to translate the 44 digit
*                    numeric sequence into its 15 digit, base 900 
*                    equivalent.
*
* Synopsis:          void add_10to900( uint16 cw[], uchar byte );
*
*  Parameters:       cw[] - current base 900 number
*                    byte - base 10 digit to update with
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Append another base 10 digit to the base 900 poly
* End Pseudocode *****************************************************
**********************************************************************/
static void add_10to900( uint16 FAR cw[], uchar byte )
{
   int16 i;
   uint16 FAR *cptr;
   /*
      adjust codeword poly to accept new base 10 value
   */
   for( cptr=cw, i=NUM_CWLEN; i; i--, cptr++ ) {
      if ( *cptr )
         *cptr *= 10;          /* poly *= 10 */
   }
   /*
      add in new base 10 value and then convert to base 900
   */
   cptr = &cw[ NUM_CWLEN-1 ];
   *cptr += byte;
   for( i=NUM_CWLEN-1; i; i--, cptr-- ) {
      if ( *cptr >= 900 ) {
         cptr[ -1 ] += (*cptr / 900);
         *cptr %= 900;
      }
   }
}
/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      ShouldPunctLatch
*
* Description:       Determine whether it is more efficient to shift (ps)
*                    or latch (pl) to punctuation submode.
*
* Synopsis:          Bool ShouldPunctLatch( LPPDFObject lpObj )
*
*  Return Value:     Returns a TRUE is pl is recommended; FALSE
*                    for ps.
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Determine if a latch or shift into PUNCT sub-mode should be used
* End Pseudocode *****************************************************
**********************************************************************/
static Bool ShouldPunctLatch( LPPDFObject lpObj )
{
   uint16 total_punct = 0;

   PDFObjLookReset( lpObj );

   while( !PDFObjIsLookEOF( lpObj ) && isTcPunct( PDFObjLook(lpObj) )) {
      if ( ++total_punct > 2 )
         break;
   }
   PDFObjLookReset( lpObj );

   return( total_punct > 2 );
}

/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      ShouldAlphaLatch
*
* Description:       Determine whether it is more efficient to shift (as)
*                    or latch (al) into ALPHA submode.
*
* Synopsis:          Bool ShouldAlphaLatch( LPPDFObject lpObj )
*
*  Return Value:     Returns a TRUE is al is recommended; FALSE
*                    for as.
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Determine if a latch or shift into ALPHA sub-mode should be used
* End Pseudocode *****************************************************
**********************************************************************/
static Bool ShouldAlphaLatch( LPPDFObject lpObj )
{
   uint16 total_alpha = 0;

   PDFObjLookReset( lpObj );

   while( !PDFObjIsLookEOF( lpObj ) && isTcAlpha( PDFObjLook(lpObj) ) ) {
      if ( ++total_alpha > 3 )
         break;
   }
   PDFObjLookReset( lpObj );

   return( total_alpha > 3 );
}

/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      map2tcseq
*
* Description:       This routine will build the necessary TC sequences
*                    required to encode the input byte. Any submode
*                    shifting/latching is determined thru this routine.
*
* Synopsis:          void map2tcseq( CWSequence *seq, uchar byte, 
*                       LPPDFObject lpObj )
*
*  Parameters:       seq - codeword sequence to setup with encoded byte
*                    byte - byte to encode
*                    lpObj - access to input stream
*
* Local Calls:       LastIntoAlpha(), LatchIntoPunct()
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Translate TC byte into sub-mode data
* End Pseudocode *****************************************************
**********************************************************************/
static void map2tcseq( CWSequence FAR *seq, uchar byte, LPPDFObject lpObj )
{
   const char *map;                    /* TC sub-mode character map */
   const uchar *sseq = (uchar *)0;     /* shift/latch sequence */
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */
    uchar    *seqdata;

    seqdata = &seq->data[0];
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */

   /*
   PDFASSERT( (TC_ALPHA <= seq->submode) && (seq->submode <= TC_PUNCT) );
   */
/****************************************        B-N(伀)            *********************************/
   map = 0;
/****************************************        B-N(仾)            *********************************/
   switch( seq->submode ) {
      case TC_LOWER:
         if ( isTcLower( byte ) )
               map = tc_lower;
         else if ( isTcAlpha( byte ) ) {
            map = tc_alpha;
            /* 
               Should we latch or shift to alpha mode ?
            */
            if( ShouldAlphaLatch( lpObj ) ) {
               seq->submode = TC_ALPHA;
               sseq = ll_to_al;
            }
            else
               sseq = ll_to_as;
         }
         else if ( isTcPunct( byte ) ) {
            map = tc_punct;
            /* 
               Should we latch or shift to punctuation mode ? 
            */
            if( ShouldPunctLatch( lpObj ) ) {
               seq->submode = TC_PUNCT;
               sseq = ll_to_pl;
            }
            else
               sseq = xl_to_ps;
         }
         else if ( isTcMixed( byte ) ) {
            map = tc_mixed;
            seq->submode = TC_MIXED;
            sseq = ll_to_ml;
         }
      break;

      case TC_MIXED:
         if ( isTcMixed( byte ) )
            map = tc_mixed;
         else if ( isTcAlpha( byte ) ) {
            map = tc_alpha;
            seq->submode = TC_ALPHA;
            sseq = ml_to_al;
         }
         else if ( isTcLower( byte ) ) {
            map = tc_lower;
            seq->submode = TC_LOWER;
            sseq = ml_to_ll;
         }
         else if ( isTcPunct( byte ) ) {
            map = tc_punct;
            /* 
               Should we latch or shift to punctuation mode ?
            */
            if( ShouldPunctLatch( lpObj ) ) {
               seq->submode = TC_PUNCT;
               sseq = ml_to_pl;
            }
            else
               sseq = xl_to_ps;
         }
      break;

      case TC_PUNCT:
         if ( isTcPunct( byte ) )
               map = tc_punct;

         else if ( isTcAlpha( byte ) ) {
            map = tc_alpha;
            seq->submode = TC_ALPHA;
            sseq = pl_to_al;
         }
         else if ( isTcMixed( byte ) ) {
            map = tc_mixed;
            seq->submode = TC_MIXED;
            sseq = pl_to_ml;
         }
         else if ( isTcLower( byte ) ) {
            map = tc_lower;
            seq->submode = TC_LOWER;
            sseq = pl_to_ll;
         }
      break;

      case TC_ALPHA:
         if ( isTcAlpha( byte ) ) {
               map = tc_alpha;
         }
         else if ( isTcLower( byte ) ) {
            map = tc_lower;
            seq->submode = TC_LOWER;
            sseq = al_to_ll;
         }
         else if ( isTcPunct( byte ) ) {
            map = tc_punct;
            /* 
               Should we latch or shift to punctuation mode ?
            */
            if( ShouldPunctLatch( lpObj ) ) {
               seq->submode = TC_PUNCT;
               sseq = al_to_pl;
            }
            else
               sseq = xl_to_ps;
         }
         else if ( isTcMixed( byte ) ) {
            map = tc_mixed;
            seq->submode = TC_MIXED;
            sseq = al_to_ml;
         }
      break;
   }
   seq->len = 0;
   /*
      check for shift/latch sequence prior to adding data
   */
   if ( sseq ) {
      while( *sseq ) 
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */
/* ///         seq->data[ seq->len++ ] = *sseq++;        */
         seqdata[ seq->len++ ] = *sseq++;
   }
   /*
   * We are guaranteed to have map set since one of the case entries
   * above will be satisfied -- disable lint warning
   */
   /*lint -e644 */
/* for TLCS C900 BUG  1998.03.24    T.GOTO                    */
/* ///   seq->data[ seq->len++ ] = (uchar)( STRCHR( map, byte ) - (LPCSTRING)map );    */
   seqdata[ seq->len++ ] = (uchar)( STRCHR( map, byte ) - (LPCSTRING)map );

   /*lint -restore */
}
/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      optimize_mode
*
* Description:       This routine will determine the "best" encoding mode
*                    by scanning ahead into the input stream. We begin
*                    with the most efficient mode (numeric), and then check
*                    for TC and default to binary.  The "best" mode is
*                    determined by finding sequences of defined lengths
*                    within a "look ahead window". We restrict our look
*                    ahead size based upon the number of available data
*                    codewords in the current barcode. This also has
*                    the desired effect of returning only enough data
*                    to fill a barcode, and never more.  The only exception
*                    to this is the TC mode, since we can never accurately
*                    predict the number of codewords produced.
*
* Synopsis:          ENCODEMODE optimize_mode( LPPDFObject lpObj, 
*                       LPCWRec lpCw, uint16 *pnBytes, Bool * fFoundMacroCharacter, ENCODEMODE FAR *ImpliedLatch,
                        Bool NeedExtraCodeword )
*
*  Parameters:       lpObj - access to input stream
*                    lpCw - active pdf codeword array
*                    pnBytes - returns the number of byte to encode 
*                    fFoundMacroCharacter - returns TRUE if eot follows rs or if gs is found while doing MicroPDF 
*                                           macro character substitution. 
*                    ImpliedLatch - input mode latch: 901 is implied in microPDF eci, output MODE_NA if 
*                                           binary mode latch is needed anyway (924); other implied latches apply
*                                           for microPDF macro character substitution feature. 
*                    NeedExtraCodeword - input true if there is a gs that needs to be encoded besides the data
*                                        during code128 emulation or macro character substitution             
*                    
*
*
*  Return Value:     Returns the mode to use to encode the next 'pnBytes'
*                    of data; MODE_EOF if no more data exists. Additional outputs for MicroPDF only - Implied Latch and
*                    fFoundMacroCharacter -see above.
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Determine best mode for encoding for next n-bytes
*  Return best mode and number of bytes to encode using mode
* End Pseudocode *****************************************************
**********************************************************************/
static ENCODEMODE optimize_mode( LPPDFObject lpObj, LPCWRec lpCw, 
      ENCODEMODE nCurrMode, uint16 FAR *pnBytes, Bool FAR *fFoundMacroCharacter, ENCODEMODE FAR *ImpliedLatch,
                                  Bool NeedExtraCodeword )
{
   int16 nCurrByte;
   int16 nTcMatches;  /* number of TC mode bytes */
   int16 nNumMatches;  /* number of NUMeric mode bytes */
   int16 nBinMatches;  /* number of BINary mode bytes */

   int16 nMaxSeq;
   int16 nMaxCws = lpCw->max_data - lpCw->n;  
                                           
                             
         
   
   
   /*
      Numeric mode map for:
         o given number of codewords [1-15], how many digits can be encoded
   */
   static const uchar cws2digits[15] = {
      0, 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41 /*, 44 */
   };  
   

   *pnBytes = 0;    
   *fFoundMacroCharacter = FALSE;
   if(NeedExtraCodeword && !PDFObjIsUsingMacroCharSub( lpObj))  /* doing 128 emulation doubles codeword for breaking transmission, */
      nMaxCws -=1;        /* macro char sub needs extra for gs only if it needs to encode in binary mode */


   /*
      check to see if there is room in barcode
   */                                 
   PDFObjLookReset( lpObj );  /* needed to remove unget char before looking */
   nCurrByte = PDFObjLook( lpObj ); 
                  
   /* If no codewords to use then we are done.
   ** If only 1 codeword left then there will only be room for a latch with no 
   ** data.  If doing macro char substitution, then there will never be a gs to encode (implied in the latch)
   ** at the end of the data.  There would have to be an rs eot in that case.
   */               
   if ( (nMaxCws <= 0) ||((nMaxCws == 1) && (*ImpliedLatch == MODE_NA) && (nCurrMode != MODE_TC))) 
   {                  
      if((nCurrByte == RS_MACRO_CHAR) && PDFObjIsUsingMacroCharSub( lpObj ))
      {
         if((nCurrByte = PDFObjLook( lpObj )) == EOT_MACRO_CHAR ) { /* its the eot char */ 
            *fFoundMacroCharacter = TRUE;                                  
            PDFObjLookReset( lpObj );
            return( MODE_BIN );
         }
      }   
      PDFObjLookReset( lpObj ); /* a.s. 10/8/97 added because of call above */
      return( MODE_EOF );
   }    
   if ( nCurrByte != -1 ) {   /* a.s. 10/8/97 moved pdfobjlook call above */

      if (   ( isNUM( nCurrByte ) ) && (
           (nMaxCws > 1)  || 
          ( (nMaxCws == 1) && (*ImpliedLatch == MODE_NUM) ) 
          ) ){
         int16 nNumCrossover;
         /*
            Determine max numeric sequence based upon remaining codewords
            in barcode: nMaxCws.
            (Note: allow room for numeric mode latch codeword)
         */                              
         if(*ImpliedLatch == MODE_NUM)                                         
            nMaxSeq = (((nMaxCws) / 15) * 44) + cws2digits[ (nMaxCws) % 15 ];
         else  
            nMaxSeq = (((nMaxCws-1) / 15) * 44) + cws2digits[ (nMaxCws-1) % 15 ];
         nNumMatches = 1;
         

         /*
            Tally up the length of a numeric sequence to see if we should
            use this mode for encoding.  Numeric mode is a sub-set of TC 
            therfore we must check it before TC.
         */
         while( (nCurrByte = PDFObjLook( lpObj )) != -1 ) { /* not EOF */

            if ( !isNUM( nCurrByte ) )
            {                                                              
               if(((nCurrByte == RS_MACRO_CHAR) || (nCurrByte == GS_MACRO_CHAR)) && PDFObjIsUsingMacroCharSub( lpObj ))
               {
                  *fFoundMacroCharacter = TRUE; /* error checking is done next time thru */
                  nCurrByte = -1;
               }  
               break;
            }   
            /*
            * If we hit the max numeric sequence the bar code can hold then
            * make it look like an EOF condition to change the crossover
            * point for numeric compaction efficiency
            */

            if ( ++nNumMatches >= nMaxSeq ){
               nCurrByte = -1;  /* a.s. added this to make it same as newencoder's pdfhienc.c */
               break;
            }   
         }
         /*
         * Numeric mode is most efficient for sequences of 13 digits or 
         * more if we need to follow the sequence with TC mode. However, if
         * the byte after the numeric sequence is BIN mode material, then
         * the sequence size is 7 or more -- also if there's nothing after
         * the sequence (we're at the end of file) then this applies too.
         */      
         if ( (nCurrByte == -1) || !isTC( nCurrByte ) )
            /*
            * If we're not in TC mode currently then we automatically choose
            * numeric packing mode since we would have to latch into TC which
            * reduces it's overall efficiency 
            */
            nNumCrossover = ((nCurrMode == MODE_TC) ) ? 7 : 0;
         else
            nNumCrossover = 13;

         if( nNumMatches > nNumCrossover ) {
            *pnBytes = nNumMatches;
              
            return( MODE_NUM );
         }
         /*
            numeric mode failed -- prime lookahead for next check
         */
         PDFObjLookReset( lpObj );
         nCurrByte = PDFObjLook( lpObj );
         *fFoundMacroCharacter = FALSE;
      }
      /*
         check for sequence of TC characters
      */
      if ( isTC( nCurrByte ) ) {
         nMaxSeq = nMaxCws * 2;      /* at best TC can pack 2 to 1 */
         nTcMatches = 1;
         nNumMatches = isNUM(nCurrByte) ? 1 : 0;

         while( ((nCurrByte = PDFObjLook(lpObj)) != -1) && isTC( nCurrByte ) ) {
            if ( ++nTcMatches >= nMaxSeq )
               break;
            /*
               check to see if a numeric sequence is embedded in here
            */
            if ( isNUM(nCurrByte) ) {
               if ( ++nNumMatches > 13 ) {
                  /*
                     found a numeric string within this TC block -- therefore 
                     we want to exclude it from TC encoding
                  */
                  nTcMatches -= 14;
                  break;
               }
            }
            else
               nNumMatches = 0;
         }   
         if(((nCurrByte == RS_MACRO_CHAR) || (nCurrByte == GS_MACRO_CHAR)) && PDFObjIsUsingMacroCharSub( lpObj ))
         {
            *fFoundMacroCharacter = TRUE; /* error checking is done next time thru */
            nCurrByte = -1;
         }  

         /*
            Allow TC mode if:
               o Found at least max sequence or sequence of 5
               o Or end of input stream (nCurrByte == EOF)
               o Or broke out due to embedded NUMeric sequence OR  gs char while doing Macro Char Substitution
         */
         if ( nTcMatches ) 
         {
            if ( (nTcMatches >= (nMaxSeq < 5 ? nMaxSeq : 5)) || 
                 PDFObjIsLookEOF(lpObj) || (nNumMatches > 13) || *fFoundMacroCharacter ) 
            {
               *pnBytes = nTcMatches;
               return( MODE_TC );
            }
         }
      }
      /*
         TC and NUMERIC both failed -- therefore the only encoding method
         left is BINARY.  Binary represents the least efficient method for
         encoding. It is also the superset for the data -- because of this
         we must look for embedded NUMERIC and TC sequences within the
         block and break these out.

         Note: we need at least 2 codewords -- latch/shift + data -- to handle
               any binary data  (unless there is an implied latch for MicroPDF )..
      */                       
      PDFObjLookReset( lpObj );                                   
      *fFoundMacroCharacter = FALSE;  
      if(NeedExtraCodeword && PDFObjIsUsingMacroCharSub( lpObj))
          nMaxCws -=1;
      if ( (nMaxCws < 1) || ((nMaxCws == 1 ) && (*ImpliedLatch != MODE_BIN)) ) 
      {
         nCurrByte = PDFObjLook( lpObj );
         if((nCurrByte == RS_MACRO_CHAR) && PDFObjIsUsingMacroCharSub( lpObj ))
         {
            if(((nCurrByte = PDFObjLook( lpObj )) == EOT_MACRO_CHAR ) ){ /* its the eot char */ 
               *fFoundMacroCharacter = TRUE;                  /* not eot is ok after rs */
               PDFObjLookReset( lpObj );
               return( MODE_BIN ); 
            }  
         }
            /* this will signal not enough room in barcode if we didn't find rs while doing macro sub  or if not doing
             ** macro char sub, we know the first char is not -1 so put it back unprocessed.
             */         
            PDFObjLookReset( lpObj ); 
         return( MODE_EOF );
      }
      
      nTcMatches = nNumMatches = nBinMatches = 0;
      /*
         binary can pack 6 bytes into 5 codewords -- with a 1:1 ratio for
         non multiples of 6 bytes
      */  
      
      /* A.S. 10/10/97 if this is the first data for a micropdf symbol that uses an eci, 
      ** then byte compaction latch 901 is implied.
      ** However, if the number of bytes is a multiple of 6 we must explicitly use
      ** the 924 latch for byte compaction mode.
      */                                           

      if(nMaxCws == 1) /* then we must have an implied latch to mode bin otherwise we returned above */
          nMaxSeq = 0;
      else    
          nMaxSeq = (((nMaxCws-1) / 5) * 6) + ((nMaxCws-1) % 5);
      if(*ImpliedLatch == MODE_BIN)
           nMaxSeq  += 1;      

      while( (nCurrByte = PDFObjLook( lpObj )) != -1 ) {
         /* a.s. added 10/6/97  
         ** if it's the rs char and we are using the macro characters in micropdf 
         ** see if the next char is the eot char  and if so, return 
         */                                                                                                                  
         if((nCurrByte == RS_MACRO_CHAR) && (PDFObjIsUsingMacroCharSub( lpObj )))
         {
            if((nCurrByte = PDFObjLook( lpObj )) == EOT_MACRO_CHAR ){ /* its the eot char */ 
               *fFoundMacroCharacter = TRUE;  
               break;
            }           
            else if((nCurrByte == -1) || (nCurrByte == GS_MACRO_CHAR) || (nCurrByte == RS_MACRO_CHAR)){
               *fFoundMacroCharacter = TRUE;   /*  a gs, rs or -1 following an rs will be processed as an error */
               break;
            }           
            else /* process the rs here then the next byte below as usual */                          
            {
               if(++nBinMatches >= nMaxSeq)
                  break;
               nTcMatches = 0;   /* rs is not Tc match */
            }     
         } 
         if((nCurrByte == GS_MACRO_CHAR) && (PDFObjIsUsingMacroCharSub( lpObj )) ) /* else if its the gs char */
         {                               
         
            *fFoundMacroCharacter = TRUE; 
            break;
         } 


         if ( ++nBinMatches >= nMaxSeq )
            break;
         /* 
            check for TC sequences within stream
         */
         if( isTC( nCurrByte ) ) {
            if ( ++nTcMatches >= 5 ) {
               nBinMatches -= nTcMatches;
               break;
            }
         }
         else
            nTcMatches = 0;
      }
      
      *pnBytes = nBinMatches;
      
      /* if the number of binary bytes to encode is a multiple of 6, we can't use the implied latch */ 
      if(nBinMatches > 0){
            if(((nBinMatches % 6) == 0) &&  (*ImpliedLatch == MODE_BIN) )
             *ImpliedLatch = MODE_NA;
      }       
      return( MODE_BIN );
   }
   /*
   * Look returned a -1; was it really an EOF or are we at an ECI transition
   */
   else if ( PDFObjAtECITrans( lpObj ) ) {
      return MODE_ECI;
   }
   return( MODE_EOF );
}
#ifndef NO_MICROPDF                                           
/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      PreambleExists
*
* Description:       Check the input data for the application preamble
*                    and if found, throw it away.  This was added for the macro characters processing in
*                    micropdf.
*
*
* Synopsis:          Bool PreambleExists( LPPDFObject lpObj)
*
*
*  Parameters:       lpObj - input stream
*
*  Returns:          Returns data identifier 5, 6 or 0 if none found
*                    
*
* External Calls:    PDFObjLook
*                    PDFObjLookReset
*                    PDFObjGet
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  see if the input begins with the preamble
*  reset the input look pointers
*  if preamble was found, remove it and return data identifier 5 or 6
*  else return 0
* End Pseudocode *****************************************************
**********************************************************************/
/****************************************        B-N(伀)            *********************************/
/* static int16 PreambleExists(LPPDFObject lpObj)                                */
int16 PreambleExists(LPPDFObject lpObj)
/****************************************        B-N(仾)            *********************************/
{
                                             
   const char *preamble = "[)>\0360";  /* preamble is "[)>rs0" */ 
   int16 ecinum;
   int16 nCurrByte;
   int16 i;
   
   ecinum = 0;                                                                                          
   i = 0;   
   while( (i < 5) && ( (nCurrByte = PDFObjLook( lpObj )) != -1 ) )  {
      if(nCurrByte != preamble[i])
         break;
      i++;  
   }  
   
   if(i == 5){
      if ((nCurrByte = PDFObjLook( lpObj )) == '5' )
         ecinum = 5;
      else if(nCurrByte == '6')
         ecinum = 6;
   }

    if(ecinum != 0){                                      
      if ((nCurrByte = PDFObjLook( lpObj )) != '\035' )   /* found the gs after the 5 or 6 */
            ecinum = 0;
   }
  
   
   PDFObjLookReset(lpObj);     
   if(ecinum != 0){ 
      for( i = 0; i < 7; i++) /* preamble is [)>rs05gs or [)>rs06gs */
         PDFObjGet(lpObj);      
   }  
   
   return(ecinum);   

}
#endif
/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      EncodeNUM
*
* Description:       Encode the next 'nBytes' using the numeric mode
*                    encoding scheme and place into barcode.
*
*                    We are guaranteed to never be asked to add more
*                    data than the 'cw' can hold.
*
* Synopsis:          uint16 EncodeNUM( LPPDFObject lpObj, uint16 nBytes, 
*                       LPCWRec lpCw )
*
*  Parameters:       lpObj - input stream
*                    nBytes - number of bytes to encode
*                    lpCw - pdf codeword array to add data to
*
*  Returns:          Returns nBytes
*
* Local Calls:       add_10to900()
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Encode nbytes of data using NUM mode
* End Pseudocode *****************************************************
**********************************************************************/

uint16 EncodeNUM( LPPDFObject lpObj, uint16 nBytes, LPCWRec lpCw )
{
   uint16 ttl_groups;      /* Number of groups of 44 digits to encode */
   uint16 ttl_remain;      /* Number of digits remaining which do not fit into 44 digit groups */
   uint16 i;
   uint16 cws[ NUM_CWLEN ];    /* 44 digits into 15 codewords */
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */
    uint16    *lpCwdata;

    lpCwdata = &lpCw->data[0];
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */

   ttl_groups = nBytes / 44;
   ttl_remain = nBytes % 44;
   /*
      Convert groups of 44 digits at a time
   */
   while( ttl_groups-- ) {
      MEMSET( cws, 0, sizeof(cws) );
      /* 
         Preceed numeric string by '1'.  This is done so no significant 
         zeros are lost during the encode process.
         i.e. If the string '000123' were to be encoded without a leading 
         '1', the decoder would only output '123'
      */
      for( cws[NUM_CWLEN-1]=1, i=0; i < 44; i++ ) {
         /*
         * Caller guarantees that PDFObjGet() can retrieve the required 
         * number of bytes: nBytes
         */
         add_10to900( cws, (uchar)(PDFObjGet(lpObj) - '0') );
      }
      /* 
         Place the calculated codewords into the codeword output stream
      */
      for( i=0; i < NUM_CWLEN; i++ )
/* for TLCS C900 BUG  1998.03.24    T.GOTO    */
/* ///         lpCw->data[ lpCw->n++ ] = cws[i];    */
         lpCwdata[ lpCw->n++ ] = cws[i];
   }
   /* 
      Convert any remaining digits
   */
   if( ttl_remain ) {
      MEMSET( cws, 0, sizeof(cws) );

      for( cws[NUM_CWLEN-1]=1, i=0; i < ttl_remain; i++ ) {
         add_10to900( cws, (uchar)(PDFObjGet(lpObj) - '0') );
      }
      /*
         find beginning of codeword stream and place into output barcode
      */
      for( i=0; i < NUM_CWLEN; i++ ) {
         if ( cws[ i ] )
            while( i < NUM_CWLEN )
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */
/* ///               lpCw->data[ lpCw->n++ ] = cws[ i++ ];    */
               lpCwdata[ lpCw->n++ ] = cws[ i++ ];
      }
   }
   return( nBytes );
}

/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      EncodeBIN
*
* Description:       Encode the next 'nbytes' bytes (plus 1 if encodeGS is true) using the binary
*                    encoding sheme. This method translates the bytes
*                    into base 900 codeword sequences packed 6 bytes
*                    to 5 codewords -- maps base 256 to base 900.
*
*                    We are guaranteed to never be asked to add more
*                    data than the 'cw' can hold.
*
* Synopsis:          uint EncodeBIN( LPPDFObject lpObj, uint16 nBytes, 
*                       LPCWRec lpCw , Bool encodeGS)
*
*  Parameters:       lpObj - input stream
*                    nBytes - number of bytes to encode
*                    lpCw - pdf codeword array to add data to 
*                    encodeGS - if true, a gs is encoded before any data 
*
*  Returns:          Returns the number of bytes encoded including the gs if needed
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Encode nbytes of data or nbytes + 1 if encodeGS is true, using BIN mode
* End Pseudocode *****************************************************
**********************************************************************/ 

/* note that during 128 emulation encodeGS will always be false so that the number of bytes processed 
** should always be the nBytes
*/

uint16 EncodeBIN( LPPDFObject lpObj, uint16 nBytes, LPCWRec lpCw, Bool encodeGS )
{
   uint16 groups_of_6;     /* Total number of sets of 6 bytes to be encoded */
   uint16 remaining;       /* The remaining bytes to be appended to output stream */
   uint32 work0, work1, work2;
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */
    uint16    *lpCwdata;

    lpCwdata = &lpCw->data[0];
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */
   
   if(encodeGS)
      nBytes += 1;
   groups_of_6 = nBytes / 6;
   remaining = nBytes % 6;
   /*
      Convert sequences of 6 base 256 values into 5 base 900 codewords
   */ 
   while( groups_of_6-- ) {
      /*
         The input is treated as a 48-bit binary number, and
         converted to base-900.  The results (which occupy
         a maximum of 5 code words) is the encoded quantity.
         This routine, for speed, treats the 48-bit number
         as a 32-bit number and a 16-bit number, related as
         follows:
            Num48 = Num32 * 65536 + Num16
         Thus, Num32 is made up of the first 4 bytes of the
         input, and Num16 is the last two.
      */   
      /* First, assembly Num32.              */
                  
      if(encodeGS){
         work0 = GS_MACRO_CHAR;
         encodeGS = FALSE;
      }  
      else                    
         work0 = (uint32)PDFObjGet( lpObj );
      work0 = (work0 << 8) + PDFObjGet( lpObj );
      work0 = (work0 << 8) + PDFObjGet( lpObj );
      work0 = (work0 << 8) + PDFObjGet( lpObj );
      /*
         Now, reduce Num32 into base-900, using work0 as the
         least significant quantity, and work1 and work2 as
         the next two "positions".  Note that we use a trick
         to save time here.  A worst-case 32-bit number (all
         ones) would actually require *four* base-900 "digits"
         We only push things out to three, however, because
         the third item is, at most, 5302.  This is small
         enough to avoid overflow in the "*65536" operation,
         so we can save a div and mod operation at this point.
      */   
      work1 = work0 / 900;
      work0 %= 900;
      work2 = work1 / 900;
      work1 %= 900;
      /*
         Now we multiply the least-significant by 65536 and
         add in the Num16.  This is done by shifting, being
         more efficient than actual multiplication.  The
         remainder of this divided by 900 is the least-
         signficant code word of the output.
      */
      work0 = (work0 << 8) + PDFObjGet( lpObj );
      work0 = (work0 << 8) + PDFObjGet( lpObj );

/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///      lpCw->data[ lpCw->n + 4 ] = (uint16)(work0 % 900);        */
      lpCwdata[ lpCw->n + 4 ] = (uint16)(work0 % 900);
      /*   
         Now we "ripple" the "*65536" and the carries up the
         line, extracting the remainders as we go.
      */
      work1 = (work1 << 16) + (work0 / 900);
/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///      lpCw->data[ lpCw->n + 3 ] = (uint16)(work1 % 900);        */
      lpCwdata[ lpCw->n + 3 ] = (uint16)(work1 % 900);
   
      work2 = (work2 << 16) + (work1 / 900);
/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///      lpCw->data[ lpCw->n + 2 ] = (uint16)(work2 % 900);        */
      lpCwdata[ lpCw->n + 2 ] = (uint16)(work2 % 900);
   
      work2 /= 900;
/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///      lpCw->data[ lpCw->n + 1 ] = (uint16)(work2 % 900);        */
/* ///      lpCw->data[ lpCw->n + 0 ] = (uint16)(work2 / 900);        */
      lpCwdata[ lpCw->n + 1 ] = (uint16)(work2 % 900);
      lpCwdata[ lpCw->n + 0 ] = (uint16)(work2 / 900);

      lpCw->n += 5;
   }
   /* 
      If the number of bytes to encode is not divisable by 6 bytes,
      tack on the remaining input bytes, one byte per codeword.
   */
   while( remaining-- ) {
      if(encodeGS){
/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///         lpCw->data[ lpCw->n++ ] = GS_MACRO_CHAR;            */
         lpCwdata[ lpCw->n++ ] = GS_MACRO_CHAR;
         encodeGS = FALSE;
      }  
      else
/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///         lpCw->data[ lpCw->n++ ] = (uint16)PDFObjGet( lpObj );    */
         lpCwdata[ lpCw->n++ ] = (uint16)PDFObjGet( lpObj );
   }
   return( nBytes );
}

/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      EncodeTC
*
* Description:       Encode the next 'nbytes' byte using the TC encoding
*                    scheme. The input data is translated into codewords
*                    with the help of the pack_excseq() routine.  This
*                    routine will also make sure we do not exceed the
*                    barcode codeword limit. If this occurs, we UNGET
*                    the data which caused the overrflow and return
*                    with a FALSE status.
*
* Synopsis:          uint16 EncodeTC( LPPDFObject lpObj, uint16 nBytes, 
*                       LPCWRec lpCw, TCSUBMODE *tcmode )
*
*  Parameters:       lpObj - input stream
*                    nBytes - number of byte to encode
*                    lpCw - pdf codeword array to add data to
*                    tcmode - current TC submode to encode under, is
*                              returned updated to state after encode
*
*  Returns:          Returns the number of bytes that were processed. 
*                   
*
* Local Calls:       map2tcseq()
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Encode nbytes of data using TC mode
* End Pseudocode *****************************************************
**********************************************************************/
uint16 EncodeTC( LPPDFObject lpObj, uint16 nBytes, LPCWRec lpCw, TCSUBMODE FAR *pTCmode )
{
   uchar cw_halves;     /* half codewords occupied in 'codeword' */
   uint16 codeword;     /* working codeword copy */
   int16 bc_halves;    /* remaining codeword halves in barcode */
   uchar byte;          /* next input by to encode */
   CWSequence seq;      /* encoded byte into TC character sequence */
   uint16 i;  
   uint16 nInitialBytes = nBytes;  /* added this so return value is number of bytes that were encoded */
/* for TLCS C900 BUG  1998.03.24    T.GOTO    */
    uint16    *lpCwdata;

    lpCwdata = &lpCw->data[0];
/* for TLCS C900 BUG  1998.03.24    T.GOTO    */
   /*
      setup to create codewords
   */
   cw_halves = 0;    /* no half codewords assigned */
   codeword = 0;     /* working codeword is empty */
   bc_halves = (int16)((lpCw->max_data - lpCw->n) * 2);
   seq.submode = *pTCmode;
            
   if(nBytes == 0)
      return(0);            
   while( nBytes-- ) {
/*      PDFASSERT( !PDFObjIsEOF(lpObj) ); */

      byte = (uchar)PDFObjGet( lpObj );
      /* 
         Find what submode this byte belongs in. If required, the sequence
         map contains submode switches 
      */
      map2tcseq( (CWSequence FAR *)&seq, byte, lpObj );
      bc_halves -= seq.len;
      /*
         Need to determine if current sequence will fit into barcode.
         If not, we return a FALSE status which flags the hi-level to
         return the encoded byte to the input stream.
      */
      if ( bc_halves >= 0 ) {
         for( i=0; i < seq.len; i++ ) {
            /*
               create the PDF codewords for TC mode. Each codeword contains
               two halves -- each half represents a value based upon the active
               sub-mode
            */
            codeword += (cw_halves++ == 0 ? (int16)(seq.data[i]) * 30 : seq.data[i]);
            if ( cw_halves == 2 ) {
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */
/* ///               lpCw->data[ lpCw->n++ ] = codeword;    */
               lpCwdata[ lpCw->n++ ] = codeword;
               cw_halves = 0;
               codeword = 0;
            }
         }
      }
      else {      /* won't fit into barcode -- break out */
         PDFObjUnget( lpObj, byte );   
         nBytes++;
         break;
      }
   }         
   nBytes++;
   /*
      see if pending codeword needs to be flushed
   */
   if ( cw_halves == 1 ) {
      if ( PDFObjIsECIFormat( lpObj ) ) {
         /*
         * ECI Protocl: We no longer pad with a 29 due to a problem in ECI
         * formatted data. If we break out of the TC sequence due to an ECI
         * latch command in the data then the following data may still be ASCII
         * and therefore the punct-shift codeword would apply to the next data
         * byte. This may cause a problem if that byte is not a member of PUNCT
         * and would require a latch -- which is illegal from a shift. Therefore
         * we pad with a latch code based upon which sub-mode we're in
         */
         static const struct {
            uint8 nValue;
            TCSUBMODE nSubmode;
         } abPadBySubmode[ 4 ] = {
            { 27, TC_LOWER },    /* TC_ALPHA : Lower Latch */
            { 28, TC_MIXED },    /* TC_LOWER : Mixed Latch */
            { 28, TC_ALPHA },    /* TC_MIXED : Alpha Latch */
            { 29, TC_ALPHA }     /* TC_PUNCT : Alpha Latch */
         };
/* for TLCS C900 BUG  1998.03.24    T.GOTO                        */
/* ///         lpCw->data[ lpCw->n++ ] = codeword + abPadBySubmode[ seq.submode ].nValue;    */
         lpCwdata[ lpCw->n++ ] = codeword + abPadBySubmode[ seq.submode ].nValue;
         seq.submode = abPadBySubmode[ seq.submode ].nSubmode;
      }
      else {
/* for TLCS C900 BUG  1998.03.24    T.GOTO                        */
/* ///         lpCw->data[ lpCw->n++ ] = codeword + 29;                        */ /* 29 is NOP for all sub-modes */
         lpCwdata[ lpCw->n++ ] = codeword + 29;/* 29 is NOP for all sub-modes */
         /*
            Rev 1.1: If we are currently in TC_PUNCT mode and use a pad (29)
                     then we must update the current mode since 29 in PUNCT is 
                     an ALPHA latch
         */
         if ( seq.submode == TC_PUNCT )
            seq.submode = TC_ALPHA;
      }
   }
   /*
      update TC sub-mode to caller
   */
   *pTCmode = seq.submode;
   /*
      we completey added all TC if remaining count is 0
   */
   return( nInitialBytes - nBytes  );   /* changed to return number of bytes encoded instead of Bool */
}  

/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      encode_data
*
* Description:       Encode a single barcode's worth of data from the
*                    input stream. This routine represents the top
*                    level (controlling routine) for building a PDF
*                    barcode from an input stream.
*
* Synopsis:          void encode_data_normally( LPPDFObject lpObj, 
*                       LPCAppParamsRec lpAppRec, LPCWRec lpCw )
*
*  Parameters:       lpObj - input data stream
*                    lpAppRec - application PDF parameters/settings
*                    lpCw - PDF codeword array
*
* External Calls:    setup_cwrec()
*
* Local Calls:       encode_data_normally(), EmulateCode128()
*                    
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Encode input data into codewords
* End Pseudocode *****************************************************
**********************************************************************/
static PDFSTATUS encode_data_normally( LPPDFObject lpObj, LPCAppParamsRec lpAppRec, LPCWRec lpCw );

PDFSTATUS encode_data( LPPDFObject lpObj, LPCAppParamsRec lpAppRec, LPCWRec lpCw )
{                 
   PDFSTATUS status;
#ifndef NO_MICROPDF          
   /*
   * Lets make a quick check on... 
   */
   if ( (lpAppRec->c128Emulation != PDF128_EMUL_OFF) && PDFObjIsECIFormat(lpObj) ) {
      /*
      * Wrong...we don't allow ECI stuff for code 128 emulation
      */
      return ERR_C128CONTENT;
   } 
#endif          
   /*
      initialize the codeword record with data limits -- if unable to
      assign values then return reason why
   */ 
 
   if ( (status = setup_cwrec( lpAppRec, lpCw )) != 0 )
      return( status );  
   PDFObjLookReset( lpObj );

        
        
#ifndef NO_MICROPDF
   /*
   * Otherwise, if Code-128 emultation is enabled then we try to encode the data
   * using this scheme....
   */
   if ( lpAppRec->c128Emulation != PDF128_EMUL_OFF ) {
      status = ERR_ARGUMENT;   /* Should never get here - screened in PDFAPI.C */
   }
   else
#endif /* ifndef no_micropdf */        
      status = encode_data_normally(lpObj, lpAppRec, lpCw);
   return(status);   
}

/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      encode_data_normally
*
* Description:       Encode a single barcode's worth of data from the
*                    input stream. This routine represents the top
*                    level (controlling routine) for building a PDF
*                    barcode from an input stream when code 128 emulation 
*                    for MicroPDF is not used.
*
* Synopsis:          void encode_data( LPPDFObject lpObj, 
*                       LPCAppParamsRec lpAppRec, LPCWRec lpCw )
*
*  Parameters:       lpObj - input data stream
*                    lpAppRec - application PDF parameters/settings
*                    lpCw - PDF codeword array
*
* External Calls:    setup_cwrec()
*
* Local Calls:       optimize_mode(), EncodeBIN(), EncodeNUM(),
*                    EncodeTC()
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Encode input data into codewords
* End Pseudocode *****************************************************
**********************************************************************/

static PDFSTATUS encode_data_normally( LPPDFObject lpObj, LPCAppParamsRec lpAppRec, LPCWRec lpCw )
{
   ENCODEMODE mode;
   TCSUBMODE tcmode;
   uint16 nBytes;
   PDFSTATUS status;
   Bool fOkayToEncode = TRUE; 
   ENCODEMODE ImpliedLatch = MODE_NA;  
   Bool fFirstSymbol;                  
   Bool rs_eot_missing = FALSE;
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */
    uint16    *lpCwdata;

    lpCwdata = &lpCw->data[0];
/* for TLCS C900 BUG  1998.03.24    T.GOTO        */
   
   /*
      encode PDF barcode always starts in TC submode ALPHA, not necessarily for MicroPDF 
   */                
   
   status = ERR_NOERROR;                 
#ifndef NO_MICROPDF
   if ( lpAppRec->symtype == STYLE_MICRO )
      mode = MODE_NA;
   else
#endif
      mode = MODE_TC;

   tcmode = TC_ALPHA;
        

   /*
      if application has requested binary mode only, then honor this
   */              
   if ( lpAppRec->fBinaryOnly ) {   

      PDFSIZET nBytesInStream;
      /*
         Binary can pack 6 bytes into 5 codewords -- with a 1:1 ratio for
         non multiples of 6 bytes.
         Subtract one codeword for binary latch codeword.
      */
      uint16 nMaxCws = lpCw->max_data - lpCw->n;
      uint16 nMaxBytes = (((nMaxCws-1) / 5) * 6) + ((nMaxCws-1) % 5);
      /*
      * Set number of bytes to encode as smaller of maximum symbol
      * capacity or entire input stream length
      */
      nBytesInStream = PDFObjGetLen(lpObj) - PDFObjTell(lpObj);
      if ( nBytesInStream <= (uint32)nMaxBytes )
         nBytes = (uint16)nBytesInStream;
      else
         nBytes = nMaxBytes;
      /*
      * If we have bytes to encode (not zero) then insert proper
      * binary latch and encode stream
      */
      if ( nBytes != 0 ) {
/* for TLCS C900 BUG  1998.03.24    T.GOTO                    */
/* ///         lpCw->data[ lpCw->n++ ] = (nBytes % 6) ? LATCH_BIN : LATCH_BIN6;        */
         lpCwdata[ lpCw->n++ ] = (nBytes % 6) ? LATCH_BIN : LATCH_BIN6;
         /*
         * Encode entire barcode contents as binary
         */
         (void)EncodeBIN( lpObj, nBytes, lpCw, FALSE ); /* FALSE for gs to encode at beginning of data*/
      }
   }
   else{

      /*
      if this is micro pdf and we are not using eci's and this is the first symbol, 
      then if the input begins with the conformance string [)>05 or {)>06 
      remove it and set the flag to remove the trailer.  Note that if this is a macro pdf symbol
      the trailer of rs eot must be the last data of the last symbol.  As soon as the trailer is found,
      the remainder of the data will be ignored. a.s. 10/20/97
      */
                                                             
/* // 98.04.14 #ifndef PDF_NOMACROPDF                */
/* // 98.04.14       fFirstSymbol = (lpAppRec->lpMpdf == NULL)|| ((lpAppRec->lpMpdf != NULL) &&  (lpAppRec->lpMpdf->nBlockCount == 0)); */
/* // 98.04.14 #else                         */
      fFirstSymbol = TRUE;      
/* // 98.04.14 #endif                         */

#ifndef NO_MICROPDF         
      if ( (lpAppRec->symtype == STYLE_MICRO) && (lpCw->n == 0) && fFirstSymbol && 
                    (!PDFObjIsECIFormat( lpObj )) && !lpAppRec->fNoMacroCharSub){
         int16 id = 0;    
       if(id == PreambleExists(lpObj)){  /* removes preamble, returns application or data identifier */ 
         if(id){
            if ( lpCw->n >= lpCw->max_data ) { /* no room in first symbol for this data - can happen in structured append */
                fOkayToEncode = FALSE;      
                status = ERR_TOOMUCHDATA;
            }   
            else if(lpAppRec->lpMpdf != NULL){
               /* a.s. make macro char substitution and structured append mutually exclusive for now */
               fOkayToEncode = FALSE;      
               status = ERR_C128CONTENT;
            }
            else {    
                rs_eot_missing = TRUE;    
               PDFObjSetMacroCharSub( lpObj, TRUE );
               if(id == 5){                                            
/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///                  lpCw->data[ lpCw->n++ ] = 916;            */
                  lpCwdata[ lpCw->n++ ] = 916;
                  mode = MODE_NUM; 
                  ImpliedLatch =  MODE_NUM; 
               }
               else{ /* id is 6 */
/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///                  lpCw->data[ lpCw->n++ ] = 917;            */
                  lpCwdata[ lpCw->n++ ] = 917;
                  mode = MODE_TC;
                  tcmode = TC_MIXED;        
                  ImpliedLatch =  MODE_TC; 
               }
            }  
         } else {
            PDFObjSetMacroCharSub( lpObj, FALSE ); 
     }
         } 
         else /* no mh10 05 or 06 header */ 
            PDFObjSetMacroCharSub( lpObj, FALSE ); 
        
      }
      else if ((lpAppRec->symtype != STYLE_MICRO) || PDFObjIsECIFormat( lpObj ) || lpAppRec->fNoMacroCharSub)
         PDFObjSetMacroCharSub( lpObj, FALSE ); /* set state to false if application prohibits macro char substitution */
/* // 98.04.14 #else                            */
/* // 98.04.14       PDFObjSetMacroCharSub( lpObj, FALSE );         */
#endif      

   

      while( fOkayToEncode ) {                                                      
         Bool fFoundMacroCharacter;
                                                                
          /* flag for seeing if there is room for an extra latch is false */
         switch( optimize_mode( lpObj, lpCw, mode, &nBytes, &fFoundMacroCharacter, &ImpliedLatch, FALSE  ) ) {
            case MODE_BIN:
               if ( mode != MODE_BIN ) {
                  if ( (nBytes == 1) && (mode == MODE_TC) ){
                     /*
                     * since only one byte just shift into binary
                     * note that if we found a macro character as the first data char optimize returns 0 for nBytes and  
                     */

                     
/* for TLCS C900 BUG  1998.03.24    T.GOTO                    */
/* ///                     lpCw->data[ lpCw->n++ ] = SHIFT_BIN;                 */
/* ///                     lpCw->data[ lpCw->n++ ] = (uint16)PDFObjGet( lpObj );     */
                     lpCwdata[ lpCw->n++ ] = SHIFT_BIN;     
                     lpCwdata[ lpCw->n++ ] = (uint16)PDFObjGet( lpObj ); 
                     ImpliedLatch = MODE_NA;
                  }   
                  else {
                     /*
                        latch into binary mode -- determine if multiple
                        of 6 data bytes or not
                     */
                  
                    
                     /*
                     * Note the position in the codeword array for the binary
                     * mode latch codeword. We will fill this when we know 
                     * how many bytes we're actually processed from the stream 
                     * unless this is micropdf and using an eci and this is the first codeword after the eci
                     * in which case the latch is implied.
                     */  
                     if(nBytes > 0)
                     {  
                     
                        if(ImpliedLatch == MODE_BIN){  /* implied latch to binary if micropdf eci (and not mutiple of 6) */
                           EncodeBIN( lpObj, nBytes, lpCw, FALSE );  /* if eci's we never look at macro chars */
                        }   
                        else{ 
/* for TLCS C900 BUG  1998.03.24    T.GOTO                            */
/* ///                           lpCw->data[ lpCw->n++ ] = (nBytes % 6) ? LATCH_BIN : LATCH_BIN6;       */
                           lpCwdata[ lpCw->n++ ] = (nBytes % 6) ? LATCH_BIN : LATCH_BIN6;   
                           EncodeBIN( lpObj, nBytes, lpCw, FALSE );
                        }
                     }  
                     ImpliedLatch = MODE_NA;
                     if(!fFoundMacroCharacter)          
                        mode = MODE_BIN; 
                  } /* end else nbytes != 1 or we were not in tc mode */  
               }   
#ifndef NO_MICROPDF                                             
                  if(fFoundMacroCharacter) {
                         
                     int16 byte;                     
                        /** found macro char at end of data - thats what got us out of optimize If byte is not
                        ** rs char we will need to first see if there is room to store this in the current symbol before we get it
                        ** reset look pointer - look at first byte etc. 
                        */ 
                     PDFObjLookReset(lpObj); 
                     byte = PDFObjLook(lpObj); 
                     if(byte == RS_MACRO_CHAR){
                        byte = PDFObjGet(lpObj); /* throw it away */ 
                        if(PDFObjLook(lpObj) != EOT_MACRO_CHAR) /* invalid */
                        {     
                           status = ERR_INVALIDMACROCHAR;  /* !!!! */
                           fOkayToEncode = FALSE; 
                           break; /* break out of case */
                        }   
                        else
                            rs_eot_missing = FALSE;
                        byte = PDFObjGet(lpObj); /* throw away the eot*/ 
                        if(PDFObjLook(lpObj) != -1) /* more data after eot - invalid */               
                        {
                            status = ERR_INVALIDMACROCHAR;  /* !!!! */
                        }           
                        fOkayToEncode = FALSE; /* we're done */
                        break; /* break out of case */
                     }
                     else {/* the above byte was a gs run optimize to find the best mode */ 
                        ENCODEMODE next_mode;                                          
                        /* first check to make sure the next char is not another gs OR an rs following a gs 
                        ** or eof without an rs eot - return error
                        */
                        byte = PDFObjLook(lpObj); 
                        if((byte == GS_MACRO_CHAR) || (byte == RS_MACRO_CHAR) || (byte == -1))
                        {                                     
                           status = ERR_INVALIDMACROCHAR;  /* !!!! */
                           fOkayToEncode = FALSE; 
                           break; /* break out of case */
                        }
                        PDFObjLookReset(lpObj);               
                        byte = PDFObjGet(lpObj); /* throw gs away */  
                        
                        /* param is TRUE to let optimize know that there is an extra gs character to encode 
                        ** before encoding data - also, optimize does the obj reset and takes into account
                        ** that we need a place for the 90n latch at the beginning. 
                        */
                        next_mode = optimize_mode( lpObj, lpCw, MODE_NA, &nBytes, &fFoundMacroCharacter, 
                                                                                    &ImpliedLatch, TRUE ); 
                        if (next_mode == MODE_EOF) /* not enough room to store the gs */
                        {                             
                           /* optimize did the obj reset for us to signal eof or not */
                           mode = MODE_EOF;     
                              
                           fOkayToEncode = FALSE; /* we're done for this symbol - we'll get too much data error */          
                        }  
                        else if(next_mode == MODE_TC)     
                        {
                           mode = MODE_TC;  
                           PDFObjLookReset(lpObj);               
                           tcmode = find_best_submode(lpObj);        
                                    PDFObjLookReset(lpObj);                                          
                           if(tcmode == TC_ALPHA) {
/* for TLCS C900 BUG  1998.03.24    T.GOTO                */
/* ///                              lpCw->data[ lpCw->n++ ] = 903;         */
                              lpCwdata[ lpCw->n++ ] = 903; 
                           }  
                           else{
/* for TLCS C900 BUG  1998.03.24    T.GOTO                */
/* ///                              lpCw->data[ lpCw->n++ ] = 904;         */
                              lpCwdata[ lpCw->n++ ] = 904; 
                           }  
                           if ( EncodeTC( lpObj, nBytes, lpCw, &tcmode ) != nBytes )
                              fOkayToEncode = FALSE;                               
                                 
                           
                        }  
                        else if(next_mode == MODE_NUM){     
                           mode = MODE_NUM; 
/* for TLCS C900 BUG  1998.03.24    T.GOTO                */
/* ///                           lpCw->data[ lpCw->n++ ] = 905;         */
                           lpCwdata[ lpCw->n++ ] = 905; 
                           EncodeNUM( lpObj, nBytes, lpCw );
                        }  
                        else if(next_mode == MODE_BIN) /* more bin data after the gs BUT it can't start with another gs */
                        {   /* however, it can end with another gs  */                               
                           int16 latchIndex;
                           mode = MODE_BIN;  
                           latchIndex = lpCw->n++; 
                           
                           if ( (EncodeBIN( lpObj, nBytes, lpCw, 1 ) % 6) == 0 )
                              lpCw->data[ latchIndex ] = LATCH_BIN6;
                           else
                              lpCw->data[ latchIndex ] = LATCH_BIN;
                               
                        } 
                        else{
                                   status = ERR_INVALIDECIESCAPE;  /* !!!! */                                                              
                           fOkayToEncode = FALSE;                
                                }                           
                        if(fFoundMacroCharacter) /* found a new one at the end of the data BIN data we just encoded  */
                           mode = MODE_NA;       /* or we were in numeric or text mode when we found the gs          */
                     } /* end else the char was not the rs macro char */   
                  } /* end if found macro char */                    
#endif                  
               
               break;

            case MODE_NUM:
               ImpliedLatch = MODE_NA;
               if ( mode != MODE_NUM ) {
/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///                  lpCw->data[ lpCw->n++ ] = LATCH_NUM;        */
                  lpCwdata[ lpCw->n++ ] = LATCH_NUM;
                  mode = MODE_NUM;
               }
               EncodeNUM( lpObj, nBytes, lpCw ); 
               if(fFoundMacroCharacter) /* this will cause us to go to bin mode next time */
                  mode = MODE_NA;
               break;
            case MODE_TC:
               ImpliedLatch = MODE_NA;
               if ( mode != MODE_TC ) {
/* for TLCS C900 BUG  1998.03.24    T.GOTO            */
/* ///                  lpCw->data[ lpCw->n++ ] = LATCH_TC;        */
                  lpCwdata[ lpCw->n++ ] = LATCH_TC;
                  mode = MODE_TC;
                  tcmode = TC_ALPHA;
               } 
                             
               fOkayToEncode = (EncodeTC( lpObj, nBytes, lpCw, &tcmode ) == nBytes) ? TRUE : FALSE;
               if(fFoundMacroCharacter)  /* this will cause us to go to bin mode next time */
               {                
                   PDFObjLookReset(lpObj);                                          
                   if(PDFObjLook(lpObj) == GS_MACRO_CHAR)                  
                      mode = MODE_NA;
               }   
               break;

            case MODE_ECI: {
               int32 nECI = 0;  
/****************************************        B-N(伀)            *********************************/
/*               Bool fModeIsSet = FALSE;                                    */
/****************************************        B-N(仾)            *********************************/
               CW cwECISeq[ 3 ];
               int16 i, nECISeqLen;
               /*
               * Read next 6 bytes (digits) from the stream and enter the 
               * requested ECI mode
               */
               for( i=0; i < 6; i++ ) {
                  nECI = (nECI * 10) + (PDFObjGet( lpObj ) - '0');
               }
               /*
               * Make check for shorthand ECI for MicroPDF format. If ECI tag
               * leads the data AND the ECI value is 900 thru 1,799 then we use
               * the ECI shorthand notation 
               * Also, check for eic at beginning of symbol for implied binary latch    
               * Note - when structured append is supported, binary latch is implied for beginning of 
               * subsequent symbols also, But the eci shorthand can only be used in the first symbol.
               */  
               ImpliedLatch = MODE_NA;
#ifndef NO_MICROPDF               
               if ( (lpAppRec->symtype == STYLE_MICRO) && (lpCw->n == 0) && fFirstSymbol &&
                    ((900L <= nECI) && (nECI <= 1799L)) ) {
                  nECISeqLen = 1; 
                  cwECISeq[ 0 ] = (CW)(nECI - 900);                                     
                  ImpliedLatch = MODE_BIN;
               }  
               else
#endif               
                  if ( (0L <= nECI) && (nECI <= 899L) ) {
                  nECISeqLen = 2;

                  cwECISeq[ 0 ] = 927;
                  cwECISeq[ 1 ] = (CW)nECI;
               }
               else if ( (900L <= nECI) && (nECI <= 810899L) ) {
                  nECISeqLen = 3;

                  cwECISeq[ 0 ] = 926;
                  cwECISeq[ 1 ] = (CW)( (nECI / 900) - 1);
                  cwECISeq[ 2 ] = (CW)(nECI % 900);
               }
               else if ( (810900L <= nECI) && (nECI <= 811799L) ) {
                  nECISeqLen = 2;

                  cwECISeq[ 0 ] = 925;
                  cwECISeq[ 1 ] = (CW)(nECI - 810900L);
               }
               else  /* ERROR - Illegal ECI sequence */
                  return ERR_INVALIDECIESCAPE;  /* !!!! */
               /*
               * We now try to add the sequence to the codeword array checking
               * for capacity errors
               */
               if ( (lpCw->n + nECISeqLen) <= lpCw->max_data ) {
                  for( i=0; i < nECISeqLen; i++ )
/* for TLCS C900 BUG  1998.03.24    T.GOTO                */
/* ///                     lpCw->data[ lpCw->n++ ] = cwECISeq[ i ];        */
                     lpCwdata[ lpCw->n++ ] = cwECISeq[ i ];
               }
               else /* Exceeded capacity of symbol */
                  return ERR_TOOMUCHDATA; /* !!!! */
               /*
               * We force a mode latch immediately following the ECI
               * sequence to terminate the prior mode if the current mode is not
               * TC (we can inject an ECI sequence ay any point in a TC sequence
               * Note: when eci's are totally supported, we should preceed the eci with the mode latch
               * when not in tc mode.
               */
               if (mode != MODE_TC) 
                  mode = MODE_NA;
            }
            break;
            
         default:                                                    
             if(rs_eot_missing && PDFObjIsLookEOF(lpObj)) /* if at eof, it should have fit if it found rs eot */
                 status = ERR_INVALIDMACROCHAR;  /* !!!! */
            fOkayToEncode = FALSE;
            break;
         } /* end case */

         
      } /* end while */


   } /* end else */  

   return(status);
}

#ifndef NO_MICROPDF         /* if micropdf is not defined, code128 cannot be defined either */

/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      find_best_submode
*
* Description:       determine if a latch to alpha or mixed submode would result
*                    in fewer codewords to encode depending on the next data to be encoded.
*
* Synopsis:          find_best_submode(LPPDFObject lpio );
*
*                    
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Look into the data stream to see if alpha or mixed is the better submode
* End Pseudocode *****************************************************
**********************************************************************/

static TCSUBMODE find_best_submode( LPPDFObject lpio )
{
   uchar byte;  
   TCSUBMODE tcsubmode;
   /*
   * We 'look' at the next character from the input stream and attempt
   * to map it into a TC sequence using the current TC submode. We use
   * the 'look' methods since we may not have room in the bar code to
   * accept the TC sequence we return. Note that the ShouldxxLatch
   * routines will also use the 'look' methods to examine past this
   * character to make latch/shift determinations
   */
   byte = (uchar)PDFObjLook( lpio );
   if ( isTcMixed( byte ) )
       tcsubmode =  TC_MIXED;
   else if ( isTcAlpha( byte ) ) 
       tcsubmode = TC_ALPHA;
   else if ( isTcLower( byte ) ) 
       tcsubmode = TC_ALPHA; /* either mixed or alpha generate a lower latch so it doesn't matter */
   else  /* its punctuation */ 
   {                                        
      if( ShouldPunctLatch( lpio ) ) 
         tcsubmode =  TC_MIXED;  /* since alpha doesn't have a latch, alpha would generate ps pch ps pch*/
      else{ /* the next byte after this current byte of punctuation is not punctuation - 
           ** if its mixed if we go to mixed we generate ps, psch then mixed char
           ** if its mixed if we go to alpha we generate pl pch al ml then mixed char
           ** so if its mixed we want to go to mixed.
           ** if it's alpha if we go to alpha we generate       pl pch al then alpha char
           ** if it's alpha if we go to mixed we would generate ps pch al then alpha char
           ** so if it's alpha since it doesn't matter, we will go to alpha
           ** if its lower if we go to mixed we generate ps psch ll then lower char
           ** if its lower if we go to alpha we generate pl pch al ll then lower char
           ** so if its lower we want to go to mixed
           */
         byte = (uchar)PDFObjLook( lpio );
/****************************************        B-N(伀)            *********************************/
/*         if (byte != -1)                                            */
         if ((char)byte != -1)
/****************************************        B-N(仾)            *********************************/
         {
            if(isTC(byte))
            {
               if( isTcAlpha( byte ) ) 
                  tcsubmode = TC_ALPHA;
               else  
                  tcsubmode =  TC_MIXED;
            }
            else
               tcsubmode = TC_ALPHA; /* doesn't matter */
         }
         else
            tcsubmode = TC_ALPHA; /* doesn't matter */
      }     
   }        
   return(tcsubmode);
}

#endif

MPDFENCODE.C文件 ///

/****************************************        B-N(伀)            *********************************/
/****************************************        B-N(仾)            *********************************/
#include <stdlib.h>
/* #include <stdio.h>    */
#include <string.h>

#include "pdfapi.h"
#include "apienc.h"

typedef enum { 
   ERR_NONE = 0, ERR_MALLOC, ERR_RENDER, ERR_ENCODE, ERR_FILECREATE
} ERRCODES;

unsigned short d[1000];      /* Data Codeword Array */

extern const uint16 abMicroRowMap[ MICRO_INDEXCOUNT ];
extern const uint16 abMicroColMap[ MICRO_INDEXCOUNT ];
extern const uint16 anMicroECCMap[ MICRO_INDEXCOUNT ];

static const short Micro_Order_col[4][12] = {
{ 0,  1,  2,  3,  4,  5, -1, -1, -1, -1, -1, -1},
{ 6,  7,  8,  9, 10, 11, 12, -1, -1, -1, -1, -1},
{13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -1, -1},
{33, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1}
};
static const short Micro_Order_auto[35] = {
0, 1, 6, 33, 2, 13, 3, 7, 4, 14, 23, 5, 8, 15, 24, 9, 16, 10, 25, 17, 11, 26, 12, 18, 27, 19, 28, 20, 29, 21, 30, 22, 31, 32, -1
};

const uint8 gabMicroLeftPattMap[ MICRO_INDEXCOUNT ] = {
/* 1x 11  14  17  20  24  28 */
       0,  7, 35, 18,  8, 24,

/* 2x  8  11  14  17  20  23  26 */
       0,  0,  7, 35, 18,  8, 26,

/* 3x  6   8  10  12  15  20  26  32  38  44     */
/* 4x  6   8  10  12  15  20  26  32  38  44   4 */
       0,  6, 14, 24, 36,  0,  0, 20, 14,  0,
       0,  6, 14, 24, 36,  0,  0, 20, 14,  0, 46

};
const uint8 gabMicroRightPattMap[ MICRO_INDEXCOUNT ] = {
/* 1x 11  14  17  20  24  28 */
       8,  7, 35, 18, 16, 32,

/* 2x  8  11  14  17  20  23  26 */
       0,  8,  7, 35, 18, 16, 34,

/* 3x  6   8  10  12  15  20  26  32  38  44     */
/* 4x  6   8  10  12  15  20  26  32  38  44   4 */
       0,  6, 14, 24, 36, 32, 16, 36, 46, 48,
       0,  6, 14, 24, 36, 32, 16, 36, 46, 48, 42

};
const uint8 gabMicroCenterPattMap[ MICRO_INDEXCOUNT ] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

/* 3x  6   8  10  12  15  20  26  32  38  44     */
/* 4x  6   8  10  12  15  20  26  32  38  44   4 */
       0,  6, 14, 24, 36, 16,  8, 28, 30, 24,
       0,  6, 14, 24, 36, 16,  8, 28, 30, 24, 18
};

LPCWRec lpPDFcodewords;
short *encode_main
     (
      unsigned char  *data_in_buff,
      unsigned short   data_len,
      unsigned short   sec_lvl,
      unsigned short   cols_cnt,
      unsigned short   rows_cnt,
      unsigned short   matrix_mode
       )

{
   long i, cw_cnt;
   PDFObject objIn;
   PDFDetailRec DetailRec;
/****************************************        B-N(伀)            *********************************/
/*   short micro_size;                                                */
/*   short micro_cnt, tmp_cols, tmp_cols2;                                    */

   short micro_size = 0;
   short micro_cnt = 0;
   short tmp_cols, tmp_cols2;
/****************************************        B-N(仾)            *********************************/
   unsigned short *src, *dest;
   d[0] = 0;
   d[1] = 0;
   PDFSetDefaults();
   if (matrix_mode == 0) {
      /* NORMAL PDF */
      PDFSetSymbolStyle(STYLE_NORMAL);
      PDFSetECCLevel (sec_lvl);
      if ((rows_cnt != 0) && ((3 > rows_cnt) || (rows_cnt > 90))) {
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
        d[3] = 0;
        d[4] = 0;
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
         return ((short *) &d[0] );
      }
      if ((cols_cnt != 0) && ((1 > cols_cnt) || (cols_cnt > 30 ))) {
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
        d[3] = 0;
        d[4] = 0;
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
         return ((short *) &d[0] );
      }
      if ((rows_cnt == 0) && (cols_cnt == 0)) {
         /* rows and cols both auto */
         PDFSetAspect("1:2");
      } else {
         PDFSetDimType( USE_FIXED );
         PDFSetRowCol(rows_cnt, cols_cnt);  /* barcode aspect ratio -- wide synbol */
      }
   } else {
      /* MICRO PDF */
      micro_cnt = 0;
      /* rows and cols both auto */
      if ((cols_cnt != 0) && (rows_cnt != 0)) {
         /* cols and rows both fixed */
         while ((micro_size = Micro_Order_col[cols_cnt - 1][micro_cnt]) != -1) {
            if ((abMicroRowMap[micro_size]) == rows_cnt) {
               PDFSetSymbolStyle(STYLE_MICRO|(micro_size<<8));
               goto GO_ENCODE;
            }
            micro_cnt++;
         }
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
        d[3] = 0;
        d[4] = 0;
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
         return ((short *) &d[0] );
      } else if ((cols_cnt != 0) && (rows_cnt == 0)) {
         /* cols fixed */
         micro_size = Micro_Order_col[cols_cnt - 1][micro_cnt];
      } else if ((cols_cnt == 0) && (rows_cnt != 0)){
         /* rows fixed */
         for (tmp_cols = 1; tmp_cols < 5; tmp_cols ++) {
            micro_cnt = 0;
            while ((micro_size = Micro_Order_col[tmp_cols - 1][micro_cnt]) != -1) {
               if ((abMicroRowMap[micro_size]) == rows_cnt) {
                  PDFSetSymbolStyle(STYLE_MICRO|(micro_size<<8));
                  goto GO_ENCODE;
               }
               micro_cnt++;
            }
         }
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
        d[3] = 0;
        d[4] = 0;
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
         return ((short *) &d[0] );
      } else {
         /* cols and rows both auto */
         micro_size = 0;
      }
      PDFSetSymbolStyle(STYLE_MICRO|(micro_size<<8));
   }
   /*
   * Setup the source for data to be encoded...and encode it
   */
GO_ENCODE: ;
RETRY_ENCODE: ;
   MakeMemoryObject( &objIn, PDFINPUT, data_in_buff );
   if ( PDFEncode( &objIn, (PDFSIZET)data_len ) == STATUS_ENCODEOK ) {
      if (!PDFGetDetails(&DetailRec)) {
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
        d[3] = 0;
        d[4] = 0;
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
         return ((short *) &d[0] );
      }
   }
   else {
      if (matrix_mode == 1) {
        /* Micro PDF */
        /* Try next size of Micro PDF */
/* // 98.04.14 #ifdef _MSC_VER                                */
/* // 98.04.14          printf ("%d %d failure %d cws\n", abMicroColMap[micro_size], abMicroRowMap[micro_size], abMicroColMap[micro_size]*abMicroRowMap[micro_size]);    */
/* // 98.04.14 #endif                                    */
         if ((cols_cnt != 0) && (rows_cnt != 0)) {
            /* cols and rows both fixed */
            /* error and return */
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
            d[3] = 0;
            d[4] = 0;
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
            return ((short *) &d[0] );
         } else if ((cols_cnt != 0) && (rows_cnt == 0)) {
            /* cols fixed */
            micro_cnt++;
            micro_size = Micro_Order_col[cols_cnt - 1][micro_cnt];
            if (micro_size < 0)
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
            {
                d[3] = 0;
                d[4] = 0;
               return ((short *) &d[0] );
            }
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
         } else if ((cols_cnt == 0) && (rows_cnt != 0)){
            /* rows fixed */
            tmp_cols2 = abMicroColMap[micro_size];
            /* rows fixed */
            for (tmp_cols = tmp_cols2 + 1; tmp_cols < 5; tmp_cols ++) {
               micro_cnt = 0;
               while ((micro_size = Micro_Order_col[tmp_cols - 1][micro_cnt]) != -1) {
                  if ((abMicroRowMap[micro_size]) == rows_cnt) {
                     PDFSetSymbolStyle(STYLE_MICRO|(micro_size<<8));
                     goto RETRY_ENCODE;
                  }
                  micro_cnt++;
               }
            }
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
            d[3] = 0;
            d[4] = 0;
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
            return ((short *) &d[0] );
         } else {
            /* cols and rows both auto */
            micro_cnt++;
            micro_size = Micro_Order_auto[micro_cnt];
            if (micro_size < 0)
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
            {
                d[3] = 0;
                d[4] = 0;
               return ((short *) &d[0] );
            }
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
         }
         PDFSetSymbolStyle(STYLE_MICRO|(micro_size<<8));
         goto RETRY_ENCODE;
      }
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
        d[3] = 0;
        d[4] = 0;
/* PDF ERROR RETURN ROW & COLMUN SET AS 0  1998.03.24    T.GOTO        */
      return ((short *) &d[0] );
   }
   d[3] = DetailRec.nCols;
   d[4] = DetailRec.nRows;
   cw_cnt = (long)(d[3]) * (long)(d[4]);
   if (matrix_mode == 1) {
      /* MICRO PDF */
      lpPDFcodewords = PDFGetMicroPDFCodewords ();
   
      d[0] = gabMicroRightPattMap[micro_size];
      d[1] = gabMicroCenterPattMap[micro_size];
      d[2] = gabMicroLeftPattMap[micro_size];
   } else {
      /* NORMAL PDF */
      lpPDFcodewords = PDFGetCodewords ();
      d[0] = 0;
      d[1] = 0;
      d[2] = 0;
      d[3] = DetailRec.nCols;
      d[4] = DetailRec.nRows;
   }
   src = &(lpPDFcodewords->data[0]);
   src += (cw_cnt - 1L);
   dest = &(d[5L]);
   for (i = 0; i < cw_cnt; i ++ ) {
      *dest++ = *src--;
   }
   return ((short *) &d[0] );
}

 

PDFCW.C文件、、//

/****************************************        B-N(伀)            *********************************/
/****************************************        B-N(仾)            *********************************/
/*********************************************************************
* Module Header
*
*  Identification:   pdfcw.c - Active Barcode Record Module
*  Copyright (c) 1993-1997 Symbol Technologies, Inc.
*
* Edit History:      
*  $Log: PDFCW.C $
*  Revision 1.4  1997/11/25 18:15:48  Anne
*  Removed include for micropdf.h since all micropdf stuff was moved to
*  pdfapi.h
*  Revision 1.3  1997/06/16 19:00:18  toml
*  Added "pretty padding" for microPDF symbols -- the padding
*  sequence does not produce a noticeable pattern
*  Revision 1.2  1997/04/18 19:11:08  toml
*  Don't init the codeword record with a place for the symbol length
*  descriptor codeword if building MicroPDF
*  Revision 1.1  1997/02/18 15:40:38  toml
*  Initial revision
*
*  Description:      Initializes and updates the barcode record during
*                    an encode and rendering.
*
*  Call Tree:         
*
**********************************************************************/

/*********************************************************************
                                 Include Files
*********************************************************************/
#include "pdfapi.h"
#include "apienc.h"
#include "pdfobj.h"
#include "ecc.h"


/*********************************************************************
                                    Defines
*********************************************************************/
#define  PAD_CW   900
#define  ELEMENTS( a )     ( sizeof(a)/sizeof(a[0]) ) 

typedef enum { ECC_ESTIMATE, ECC_ABSOLUTE } ECCCALCENUM;

/*********************************************************************
                                  Local Data
*********************************************************************/
/*
   Used to determine maximum codeword count under row/column constraints:
      Indexed by column limit, yields maximum codeword count achievable
*/
static const struct {
   uint8 cw_count,      /* barcode codeword count (relative 900) */
         row_limit;     /* row value required for codeword count */
} matrixmap[ 31 ] = {
   /*
      map not used for limits which produce <= 928 codewords
      (see setup_cwrec() for use)
   */
   {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
   /*
      never require map for 10 column limit (90*10 == 900), so we use this
      entry to terminate our search on "row >= row_limit"
   */
   { 00, 91 },    /* col == 10 -- contains max row limit loop constraint */

   { 24, 84 },    /* col == 11 */
   { 24, 77 },    /* col == 12 */
   { 23, 71 },    /* col == 13 */
   { 24, 66 },    /* col == 14 */
   { 15, 61 },    /* col == 15 */
   { 28, 58 },    /* col == 16 */
   { 18, 54 },    /* col == 17 */
   { 18, 51 },    /* col == 18 */
   { 12, 48 },    /* col == 19 */
   { 20, 46 },    /* col == 20 */
   { 24, 44 },    /* col == 21 */
   { 24, 42 },    /* col == 22 */
   { 20, 40 },    /* col == 23 */
   { 12, 38 },    /* col == 24 */
   { 25, 37 },    /* col == 25 */
   { 10, 35 },    /* col == 16 */
   { 18, 34 },    /* col == 27 */
   { 24, 33 },    /* col == 28 */
   { 28, 32 },    /* col == 29 */
   { 00, 30 }     /* col == 30 */
};

/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      EccLevelFromPercent
*
* Description:       Calculate an ECC/EDC level for a barcode as a percentage
*                    of data codewords in barcode.  
*                       
* Synopsis:          uint16 EccLevelFromPercent( uint16 percent, uint16 num_cws, 
*                       ECCCALCENUM type )
*                       
*  Parameters:       percentage - error correction/detection percentage
*                                 of codewords based on data codeword content
*                    num_cws - total codeword count of barcode (type == 
*                              ESTIMATE) or total data codeword count (type
*                              == ABSOLUTE)
*                    type = ESTIMATE or ABSOLUTE
*                       
*  Return Value:     Returns the ECC/EDC level of 0 thru 8.
*                       
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  If we have the target barcode length Then
*     TotalCW = DataCW + (DataCW * Percentage)
*     DataCW = TotalCW / (1 + Percentage)
*     ECC = TotalCW - (TotalCW / (1 + Percentage))
*  Else
*     ECC = data-codewords * percentage
*  EndIf
*  ECC-level = Map ECC codewords to ECC level
*  Return ECC-level
* End Pseudocode *****************************************************
**********************************************************************/
static uint16 EccLevelFromPercent( uint16 nPercent, uint16 nNumCws, ECCCALCENUM eccType )
{
   /*
   * Given a calculated ECC codeword count, will map to ECC level. The map
   * contains lower bounds (in codewords) for mapping to corresponding level
   */
   static const uint16 nECCLowerBounds[ 9 ] = {
        0,      /* level 0 - never reached */
        0,      /* level 1  (  0 -> 3)    */
        4,      /* level 2  (  4 -> 10 )  */
        11,     /* level 3  ( 11 -> 20)   */
        21,     /* level 4  ( 21 -> 45)   */
        46,     /* level 5  ( 46 -> 100)  */
        101,    /* level 6  (101 -> 200)  */
        201,    /* level 7  (201 -> 400)  */
        401     /* level 8  (401 -> ...)  */
   };
   uint16 nNumEccCws;
   uint16 nEccLevel;
   /*
   * Make quick work of zero percent ECC -- equates to ECC level 0
   */
   if ( nPercent == 0 )
      return( 0 );

   if ( eccType == ECC_ESTIMATE ) {
      /*
      * The num_cws value represents the barcode target length, therefore
      * it is data plus ECC. We must determine number of security codewords 
      * based on percentage:
      *    TotalCW = DataCW + (DataCW * Percentage)
      *    DataCW = TotalCW / (1 + Percentage)
      *    ECC = TotalCW - (TotalCW / (1 + Percentage))
      */
      uint32 lNumCws = nNumCws * 100UL;

      nNumEccCws = nNumCws - (uint16)( lNumCws / (100UL + nPercent) );
   }
   else
      /*
      * We know how many data codewords there are, therefore the level
      * is just a percentage of the codeword count
      */
      nNumEccCws = (uint16)( ((int32)nNumCws * (int32)nPercent + 50L) / 100L);
   /*
   * With requested ECC codeword count (ecc) find which band it falls into
   * from the nECCLowerBounds map
   */
   for( nEccLevel = 8; nEccLevel != 0; nEccLevel-- ) {
      if ( nNumEccCws >= nECCLowerBounds[ nEccLevel ] )
         break;
   }
   return( nEccLevel );
}
/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      assign_rowcol
*
* Description:       This routine will determine the row and column
*                    dimensions for the barcode based on application
*                    constraints. A best match for the number of
*                    codewords in the barcode against aspect ratio,
*                    row and columns limits is found. If a barcode
*                    which meets the applications constraints could
*                    not be constructed then the returned dimensions
*                    are zero.
*
*                    This function is invoked during the image rendering
*                    phase: PDFMakeImage.
*
* Synopsis:          Bool assign_rowcol( LPCAppParamsRec lpAppParam, 
*                       uint16 nTotalCws, LPMatrixDim lpMatrix )
*
*  Parameters:       lpAppParam - application barcode constraints
*                    nTotalCws - total codeword length of barcode
*                    lpMatrix - returned row/column values
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  If application row,col limits
*     Calc row,col based upon aspect ratio
*  Else
*     Calc row,col based upon fixed row and/or col
*  EndIf
*  Return success/failure status
* End Pseudocode *****************************************************
**********************************************************************/
static Bool assign_rowcol( LPCAppParamsRec lpAppParam, uint16 nTotalCws,
   LPMatrixDim lpMatrix )
{
   uint16 rows, cols;
   uint16 last_col;        /* last valid barcode matrix index */
   uint16 width;           /* width of barcode in elements */
   uint16 last_aspect;     /* aspect ratio of last valid barcode */
   /*
      fix the row/col values based upon the aspect ratio or fixed limits
   */
   if ( lpAppParam->dimtype == USE_LIMITS ) {
      /*
         calculate all possible matrix combinations for given codeword count
         (start with 1 column in width and calculate up to column limit)
      */
      width = CalcPDFBitwidth( lpAppParam->symtype, 1 );

      last_aspect = last_col = 0;
      rows = 3;         /* minimum row value */

      for( cols = 1; cols <= lpAppParam->cols; cols++, width += 17 ) {
         rows = (nTotalCws + cols - 1) / cols;
         if ( rows < 3 )
            rows = 3;

         if ( (rows <= lpAppParam->rows) && (rows * cols <= 928) ) {
            uint32 nOverallHeight = (uint32)lpAppParam->module_height * rows * 100UL;
            uint16 aspect = (uint16)( nOverallHeight / (uint16)(width * lpAppParam->module_width) );
            /*
               if we reached our aspect ratio limit, check for prior aspect
               ratio and see which one is the better match
            */
            if ( lpAppParam->pdf_aspect >= aspect ) {
               if ( last_aspect ) {
                  uint16 diff1 = last_aspect - lpAppParam->pdf_aspect;
                  if ( diff1 < (lpAppParam->pdf_aspect - aspect) ) {
                     cols = last_col;
                     rows = (nTotalCws + last_col - 1) / last_col;
                  }
               }
               break;
            }
            last_aspect = aspect;
            last_col = cols;
         }
      }
      /*
         if we broke out of loop then we use the matched aspect ratio else
         we see if we had any matrices at all
      */
      if ( cols > lpAppParam->cols ) {
         if ( last_col ) {
            cols = last_col;
            rows = (nTotalCws + last_col - 1) / last_col;
         }
         else
            rows = cols = 0;     /* no matches for data */
      }
   }
   else {
      rows = lpAppParam->rows;
      cols = lpAppParam->cols;
      /*
         if both are not defined then we must calculate one of them
      */
      if ( !(rows && cols) ) {
         if ( rows )
            cols = (nTotalCws + rows - 1) / rows;
         else { /* if ( cols ) */ 
            rows = (nTotalCws + cols - 1) / cols;
            if ( rows < 3 )
               rows = 3;
         }
      }
      /*
         check for invalid barcode size
      */
      if ( !((rows * cols <= 928) && (rows <= 90) && (cols <= 30)) )
         rows = cols = 0;
   }
   lpMatrix->rows = rows, lpMatrix->cols = cols;

   return( rows && cols ? TRUE : FALSE );
}
/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      assign_ecc
*
* Description:       This routine will determine the ECC level to
*                    assign to the barcode based on application
*                    constraints and data length.
*
*                    This function is invoked during the image rendering
*                    phase: PDFMakeImage.
*
* Synopsis:          uint16 assign_ecc( LPCAppParamsRec lpAppParam, 
*                       uint16 nDataCws )
*
*  Parameters:       lpAppParam - application barcode constraints
*                    nDataCws - total codewords assign for data
*
*  Returns:          Returns the ECC level to assign to barcode.
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  If percentage request
*     Determine ECC overhead as percentage
*  Else
*     Use fixed level
*  EndIf
*  Return level
* End Pseudocode *****************************************************
**********************************************************************/
static uint16 assign_ecc( LPCAppParamsRec lpAppParam, uint16 nDataCws )
{
   uint16 nTotalCws;
   uint16 ecc_level;

   if ( !lpAppParam->fEccFixed ) {  /* calc ECC level as percentage */
      /*
         If we're using fixed row/col counts then we require special process-
         ing for ECC determination. By fixing one of the row/col values we
         may introduce a significant amount of padding codewords -- these
         padding codewords, which are also data codewords, should be taken
         into consideration with ECC percentage.
      */
      if ( lpAppParam->dimtype == USE_FIXED ) {
         if ( !(lpAppParam->rows && lpAppParam->cols) ) {
            if ( lpAppParam->rows ) {     /* adjust columns to hold data */
               uint16 cols = (nDataCws + lpAppParam->rows - 1) / lpAppParam->rows;

               nTotalCws = (!cols ? 1 : cols) * lpAppParam->rows;
            }
            else { /* ( lpAppParam->cols )   adjust rows to hold data */
               uint16 rows = (nDataCws + lpAppParam->cols - 1) / lpAppParam->cols;

               nTotalCws = (rows < 3 ? 3 : rows) * lpAppParam->cols;
            }
            ecc_level = EccLevelFromPercent( lpAppParam->nEccPercent, nTotalCws, ECC_ABSOLUTE );
         }
         else
            /*
               Else the matrix size is fixed, therefore we know overal size
               of barcode but we need to know the amount of room assigned
               for ECC. This amount (the percentage) is calculated by
               cal_ecc_level() using the ESTIMATE request
            */
            ecc_level = EccLevelFromPercent( lpAppParam->nEccPercent,
                  (uint16)(lpAppParam->rows * lpAppParam->cols), ECC_ESTIMATE );

      }
      /*
         Since row/col can be adjusted to accomodate data+ECC codewords, we
         make our ECC calculation based on data codewords
      */
      else
         ecc_level = EccLevelFromPercent( lpAppParam->nEccPercent, nDataCws, ECC_ABSOLUTE );
   }
   else
      ecc_level = lpAppParam->nEccLevel;

   return( ecc_level );
}

/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      setup_cwrec
*
* Description:       Initializes the codeword record based upon appli-
*                    cation setting found in 'appset': sets up the
*                    maximum matrix size of barcode based on row/col
*                    limits, calculates the ECC level based on max
*                    barcode.
*
* Synopsis:          int setup_cwrec( LPCAppParamsRec lpAppParam, 
*                       LPCWRec lpCw )
*
*  Parameters:       lpAppParam - application constraints/settings for barcode
*                    lpCw - PDF codeword array record to initialize
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  Assign limits for barcode based on application constraints
* End Pseudocode *****************************************************
**********************************************************************/
PDFSTATUS setup_cwrec( LPCAppParamsRec lpAppParam, LPCWRec lpCw )
{
   uint16 nECCws;
   uint16 ecc_level;
   /* 
      Initialize number of codewords to 1
      The first codeword is always the total number of data codewords
      in the bar code, therefore the minimum number of codewords is 1
   */
   lpCw->n = 1;

#ifndef NO_MICROPDF
   /*
   * ...except of course if its MicroPDF, then all symbols DO NOT begin
   * with a symbol length descriptor codeword -- we start at index 0
   */
   if ( lpAppParam->symtype == STYLE_MICRO )
      lpCw->n = 0;
#endif
   /*
      Place a target length based upon row and column limits specified
      by caller.  Two lengths are calculated:
         o Overall barcode length based upon row/col limits
         o Maximum data codeword content based upon ECC overhead

      For macro PDF we limit barcode content based upon aspect ratio
      requested by application. For example, a request for a 1:1 aspect
      ratio forces us to use 790 (79x10) since a 928 maximum length can
      only yield a (58x16) 1:2 or (32x29) 1:5.8. Since we can spread the
      data over multiple barcodes, limiting the size is no problem.
   */
   if ( lpAppParam->dimtype == USE_LIMITS ) {

      if ( lpAppParam->lpMpdf ) {
         /*
            The overall width accounts for start/stop and left/right row
            indicators. We begin with the maximum width and work down till
            we reach a valid barcode matching the requested aspect ratio
         */
         uint32 width = (uint32)CalcPDFBitwidth( lpAppParam->symtype, lpAppParam->cols );
/****************************************        B-N(伀)            *********************************/
/*         uint16 rows, cols;                                            */

         uint16 rows = 0;
     uint16 cols;
/****************************************        B-N(仾)            *********************************/

         for( cols = lpAppParam->cols; cols >= 1; cols--, width -= 17 ) {
            rows = (uint16)(lpAppParam->pdf_aspect * width * lpAppParam->module_width) / 
                           (100 * lpAppParam->module_height);
            if ( (rows <= lpAppParam->rows) && ((rows * cols) <= 928) )
               break;
         }
         if ( cols ) {
            /*
            * Disable warning for possible uninitialize rows value, -e771.
            * Since cols is guaranteed to be one or more we always set rows
            * to some value
            */
            /*lint -e771 */
            lpCw->max_len = (rows < 3 ? 3 : rows) * cols; /*lint -restore */
         }
         else {
            /*
               No matter how few columns, we could not meet the aspect ratio;
               therefore the minimum column width (1) is used
            */
            lpCw->max_len = lpAppParam->rows;
         }
      }
      else {
         /*
            For normal PDF (non-macro) we always try to construct the
            largest barcode possible -- taking into consideration the
            application imposed constraints (row,col) and requests (aspect
            ratio)
         */
         lpCw->max_len = (uint16)lpAppParam->rows * (uint16)lpAppParam->cols;
         if ( lpCw->max_len > 928 ) {
            /*
               determine max barcode based upon row and/or column limits
            */
            uint8 max_cw = 0;
            uint16 row_l = lpAppParam->rows;
            uint16 col_l = lpAppParam->cols;
      
            do {
               if ( matrixmap[ col_l ].cw_count > max_cw )
                  max_cw = matrixmap[ col_l ].cw_count;
            } while( row_l >= matrixmap[ --col_l ].row_limit );
      
            lpCw->max_len = 900 + max_cw;
         }
      }
   }
   /*
      else application has "fixed" either the row, column or both
   */
   else {
      if ( lpAppParam->rows && lpAppParam->cols )
         lpCw->max_len = (uint16)lpAppParam->rows * (uint16)lpAppParam->cols;
      else if ( lpAppParam->cols ) {
         uint16 rows = (928 / lpAppParam->cols);

         lpCw->max_len = (rows > 90 ? 90 : rows) * lpAppParam->cols;
      }
      else {
         uint16 cols = (928 / lpAppParam->rows);

         lpCw->max_len = (cols > 30 ? 30 : cols) * lpAppParam->rows;
      }
   }
#ifndef NO_MICROPDF         
   if ( lpAppParam->symtype == STYLE_MICRO ) {
      nECCws = MICROECCLEN( lpAppParam->nMicroECC );
   }
   else
#endif
   {
      if ( lpAppParam->fEccFixed )
         ecc_level = lpAppParam->nEccLevel;
      else
         ecc_level = EccLevelFromPercent( lpAppParam->nEccPercent, lpCw->max_len, ECC_ESTIMATE );

      nECCws = ECCLEN( ecc_level );
   }
   /*
      Setup barcode data limits based on row/column limits and overall
      requirements for ECC.  Return error codes for inability to meet
      application requests
   */
   if ( nECCws >= (lpCw->max_len - 1) )
      return( ERR_ECCEXCEEDSCAPACITY );

   lpCw->max_data = lpCw->max_len - nECCws;
   /*
      We also adjust the max data content to account for macro PDF codewords
   */
/* // 98.04.14 #ifndef PDF_NOMACROPDF                                        */
/* // 98.04.14    if ( lpAppParam->lpMpdf ) {                                    */
/* // 98.04.14       uint16 mpcb_len = (*lpAppParam->lpMpdf->pfnGetMPCBLen)( lpAppParam->lpMpdf, MPCBLEN_ACTIVE );    */
/* // 98.04.14                                                       */
/* // 98.04.14          Make sure MPCB does not exceed data content of barcode:                    */
/* // 98.04.14             barcode always contains a length codeword...therefore                 */
/* // 98.04.14             data content size is cw->max_data-1                            */
/* // 98.04.14                                                       */
/* // 98.04.14       if ( mpcb_len > (lpCw->max_data - 1) )                            */
/* // 98.04.14          return( ERR_MPCBTOOMUCH );                                */
/* // 98.04.14                                                       */
/* // 98.04.14          Filling the barcode with all MPCB info is fine for the 1st barcode,            */
/* // 98.04.14          since all optional fields are placed into 1st, however no room                */
/* // 98.04.14          in subsequent barcodes presents a problem. If this is the case                */
/* // 98.04.14          we will never have room for data -- raise exception for this.                */
/* // 98.04.14                                                     */
/* // 98.04.14          Compare against (max_data-1) since the data length codeword is                */
/* // 98.04.14          included in this value -- we are interested in data region only                */
/* // 98.04.14                                                       */
/* // 98.04.14       if ( (*lpAppParam->lpMpdf->pfnGetMPCBLen)(lpAppParam->lpMpdf,MPCBLEN_NOT1ST) == (lpCw->max_data-1) )    */
/* // 98.04.14          return( ERR_MPCBTOOMUCH );                                */
/* // 98.04.14                                                     */
/* // 98.04.14       lpCw->max_data -= mpcb_len;                                */
/* // 98.04.14    }                                                */
/* // 98.04.14 #endif                                                */
   return( ERR_NOERROR );
}
/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      bcstats
*
* Description:       This routine will take the active barcode
*                    record data and calculate the parameters required
*                    to render it: row & column counts, ECC level, MPDF
*                    codewords and padding codewords.
*
* Synopsis:          int bcstats( LPCWRec lpCw, LPEncodeInfoRec lpEnc, 
*                       LPCAppParamsRec lpAppParam )
*
*  Parameters:       lpCw - barcode codeword data
*                    lpEnc  - barcode information calculated by routine
*                    lpAppParam - application barcode constraints
*
*  Return Value:     Returns ERR_NOERROR on successful completion; an
*                    error code otherwise.
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  If we have valid barcode data Then
*     Calculate physical parameters
*  EndIf
*  Return status
* End Pseudocode *****************************************************
**********************************************************************/
PDFSTATUS bcstats( LPCWRec lpCw, LPEncodeInfoRec lpEnc, LPCAppParamsRec lpAppParam )
{
   uint16 nECCws;
   /*
      verify we have a barcode to format
   */
   if ( !lpCw )
      return( ERR_NOACTIVEBARCODE );
   /*
      determine number of codewords required for the macro PDF control block
   */
/* // 98.04.14 #ifndef PDF_NOMACROPDF                                        */
/* // 98.04.14    if ( lpAppParam->lpMpdf )                                    */
/* // 98.04.14       lpEnc->mpdf_cws = (*lpAppParam->lpMpdf->pfnGetMPCBLen)( lpAppParam->lpMpdf, MPCBLEN_ACTIVE );    */
/* // 98.04.14    else                                                */
/* // 98.04.14 #endif                                                */
      lpEnc->mpdf_cws = 0;
   /*
      determine the ECC level to assign based on application constraints
   */
#ifndef NO_MICROPDF
   if ( lpAppParam->symtype == STYLE_MICRO ) {
      nECCws = MICROECCLEN( lpAppParam->nMicroECC );
   }
   else 
#endif
   {
      lpEnc->ecc_level = assign_ecc( lpAppParam, (uint16)(lpCw->n + lpEnc->mpdf_cws) );
      nECCws = ECCLEN( lpEnc->ecc_level );
   }
   /*
      we now know the total codewords required for barcode:
   
         Total cw's = Data + macro PDF  + ECC polynomial

      see if a matrix can be created which will hold these
   */
   if ( assign_rowcol( lpAppParam, (uint16)(lpCw->n + lpEnc->mpdf_cws + nECCws),
                       &lpEnc->dmatrix ) ) {
      /*
         assign barcode limits based upon row/col dimensions
      */
      lpCw->max_len = lpEnc->dmatrix.rows * lpEnc->dmatrix.cols;
      lpCw->max_data = lpCw->max_len - nECCws;
      /*
         assign statistic info fields
      */
      lpEnc->data_cws = lpCw->n;
      lpEnc->pad_cws  = lpCw->max_data - lpCw->n - lpEnc->mpdf_cws;
      lpEnc->nrows = lpEnc->dmatrix.rows;
      /*
      *  Instead of blindly padding the symbol with useless information
      *  (normally padded with 900's) we attempt to pad with ECC data. We
      *  increase the ECC to fill the padding codeword area -- this will
      *  normally have an effect with fixed row and column barcodes.
      */
      if ( lpAppParam->fPadWithECC ) {
         while( lpEnc->ecc_level < 8 ) {
            uint16 ecc_delta = ECCLEN(lpEnc->ecc_level+1) - ECCLEN(lpEnc->ecc_level);
   
            if ( ecc_delta <= lpEnc->pad_cws ) {
               /*
               *  Adjust the padding codewords by the increased number of ECC
               *  codewords being added.
               */
               lpEnc->pad_cws -= ecc_delta;
               lpEnc->ecc_level++;
            }
            else
               break;
         }
      }
      /*
         Calculate the number of columns of data codewords to provide in
         the data[] array. This count will include left and right row
         indicators if they apply
      */
      lpEnc->ncols = lpEnc->dmatrix.cols;
      if ( lpAppParam->symtype == STYLE_NORMAL )
         lpEnc->ncols += 2;        /* add left and right row indicators */
      else if ( (lpAppParam->symtype == STYLE_TRUNCATED) || (lpAppParam->symtype == STYLE_BARE) )
         lpEnc->ncols++;           /* add only left row indicator */
      /*
      * ELSE for STYLE_NAKED && STYLE_MICRO we only supply data region codewords
      */
      /*
         transfer remaining barcode info to IFD
      */
      lpEnc->symtype    = lpAppParam->symtype;
      lpEnc->nMicroSize = lpAppParam->nMicroSize;
      lpEnc->mod_width  = lpAppParam->module_width;
      lpEnc->mod_height = lpAppParam->module_height;
   }
   else
      return( ERR_TOOMANYCW );

   return( ERR_NOERROR );
}
/*********************************************************************                      
* Routine Header *****************************************************
*
* Routine Name:      bcbuild
*
* Description:       This routine will construct a PDF barcode from
*                    the data record, lpCw. The physical characteristics
*                    are determined, through bcstats(), and the complete
*                    codeword array is built -- this includes left/right
*                    row indicator information, data codewords, MPCB 
*                    codewords and the ECC polynomial.
*
* Synopsis:          int bcbuild( LPCWRec lpCw, LPEncodeInfoRec lpEnc, 
*                       LPCAppParamsRec lpAppParam )
*
*  Parameters:       lpCw - barcode codeword data
*                    lpEnc - barcode information calculated by routine
*                    lpAppParam - application barcode constraints
*
*  Return Value:     Returns ERR_NOERROR on successful completion; an
*                    error code otherwise.
*
**********************************************************************/
/*********************************************************************
* Pseudocode:
*  If valid physical constraints
*     Build barcode into ifd
*  EndIf
*  Return status
* End Pseudocode *****************************************************
**********************************************************************/
PDFSTATUS bcbuild( LPCWRec lpCw, LPEncodeInfoRec lpEnc, LPCAppParamsRec lpAppParam )
{   
   uint16 i;
   PDFSTATUS status;
   uint8 r,c;
   LPCW lpDestCw, lpSrcCw;
   uint16 anLRIndicator[3], anRRIndicator[3];
/* for TLCS C900 BUG  1998.03.24    T.GOTO                                */
    uint16    *lpCwdata;

    lpCwdata = &lpCw->data[0];
/* for TLCS C900 BUG  1998.03.24    T.GOTO                                */
   /*
      assign EncodeInfoRec fields -- if fields are valid then transfer 
      codeword information over to construct barcode
   */
   if ( (status = bcstats( lpCw, lpEnc, lpAppParam )) == ERR_NOERROR ) {
      /*
         save the current codeword count to restore it when we're done
      */
      uint16 nOrigCodewordCount = lpCw->n;
      /*
         add padding codewords required (if any)
      */
      if ( lpEnc->pad_cws > 0 ) {
#ifndef NO_MICROPDF
         if ( lpAppParam->symtype == STYLE_MICRO ) {
            static const CW acwPad[] = { 838, 779, 867, 865, 898, 868, 839, 900 };
            Bool fDoInjectExtra;
            uint16 nPadIndex, nInjectCounter;
            /*
            * Stuff a TC latch into the stream since we use a TC submode
            * sequence to pad fill
            */
/* for TLCS C900 BUG  1998.03.24    T.GOTO                                */
/* ///            lpCw->data[ lpCw->n++ ] = 900;                                */
            lpCwdata[ lpCw->n++ ] = 900;
            fDoInjectExtra = (lpEnc->dmatrix.cols == 2) || (lpEnc->dmatrix.cols == 4);

            nPadIndex = nInjectCounter = 0;

            for( i=1; i < lpEnc->pad_cws; i++ ) {
               /*
               * For MicroPDF we want to stagger the padding patterns so
               * it is not constant pattern when there is a high degree
               * of unused space
               */
               if ( fDoInjectExtra ) {
                  if ( nPadIndex == ELEMENTS(acwPad) ) {
                     nPadIndex = 0;
                     /*
                     * If we've added three sequence patterns already then we 
                     * need to stagger the sequence some more by stuffing in
                     * an extra TC latch
                     */
                     if ( ++nInjectCounter == 3 )  {
/* for TLCS C900 BUG  1998.03.24    T.GOTO                                */
/* ///                        lpCw->data[ lpCw->n++ ] = 900;                            */
                        lpCwdata[ lpCw->n++ ] = 900;
                        nInjectCounter = 0;
                        continue;
                     }
                  }
               }
               else {
                  if ( nPadIndex == ELEMENTS(acwPad) )
                     nPadIndex = 0;
               }
/* for TLCS C900 BUG  1998.03.24    T.GOTO                                */
/* ///               lpCw->data[ lpCw->n++ ] = acwPad[ nPadIndex++ ];                        */
               lpCwdata[ lpCw->n++ ] = acwPad[ nPadIndex++ ];
            }
         }
         else
#endif
         for( i=0; i < lpEnc->pad_cws; i++ ) {
/* for TLCS C900 BUG  1998.03.24    T.GOTO                                */
/* ///               lpCw->data[ lpCw->n++ ] = 900;                                */
               lpCwdata[ lpCw->n++ ] = 900;
         }
      } /* end if padding codewords required */
      /*
         place the MPCB record codewords into barcode (if applicable)
      */
/* // 98.04.14 #ifndef PDF_NOMACROPDF                                        */
/* // 98.04.14       if ( lpAppParam->lpMpdf )                                    */
/* // 98.04.14          (*lpAppParam->lpMpdf->pfnAppendMPCBData)( lpAppParam->lpMpdf, lpCw );            */
/* // 98.04.14 #endif                                                */
      /*
      * Complete the barcode by assigning data length and adding ECC poly. If
      * this is a MicroPDF bar code then we DO NOT place an SLD codeword into
      * the first position
      */
#ifndef NO_MICROPDF
      if ( lpAppParam->symtype != STYLE_MICRO )
         lpCw->data[ 0 ] = lpCw->n;

      if ( lpAppParam->symtype == STYLE_MICRO )
/* for TLCS C900 BUG  1998.03.26    T.GOTO                                */
/* ///         AddMicroECCPoly( lpCw->data, lpCw->n, lpAppParam->nMicroECC, &lpCw->data[lpCw->n] );        */
         AddMicroECCPoly( lpCw->data, lpCw->n, lpAppParam->nMicroECC, &lpCwdata[lpCw->n] );
      else
#endif
/* for TLCS C900 BUG  1998.03.26    T.GOTO                                */
/* ///         add_ecc_poly( lpCw->data, lpCw->n, lpEnc->ecc_level, &lpCw->data[lpCw->n] );            */
         add_ecc_poly( lpCw->data, lpCw->n, lpEnc->ecc_level, &lpCwdata[lpCw->n] );
      /*
         restore the codeword length back to original so that application
         can re-size or remake image
      */
      lpCw->n = nOrigCodewordCount;
      /*
      *  Xfer all data codewords, constructing row indicators as we go,
      *  to the EncodeInfoRec structure.
      *  Pre-calculate the three row indicator constants:
      *     k1 = (rows - 1) / 3
      *     k2 = (ecc_level * 3) + ((rows-1) % 3)
      *     k3 = (cols - 1)
      *
      *  Setup the Left/Right row indicator value arrays using these
      *  values and indexed through (Row % 3). The assignment of
      *  row indicator value based on (Row % 3) value is:
      *      (Row % 3)        Left Row           Right Row
      *      --------------------------------------------
      *          0        (30 * Row/3) + k1    (30 * Row/3) + k3
      *          1        (30 * Row/3) + k2    (30 * Row/3) + k1
      *          2        (30 * Row/3) + k3    (30 * Row/3) + k2
      */
      anLRIndicator[0] = (lpEnc->dmatrix.rows - 1) / 3;
      anLRIndicator[1] = (lpEnc->ecc_level * 3) + ((lpEnc->dmatrix.rows - 1) % 3);
      anLRIndicator[2] = lpEnc->dmatrix.cols - 1;

      anRRIndicator[0] = anLRIndicator[2];
      anRRIndicator[1] = anLRIndicator[0];
      anRRIndicator[2] = anLRIndicator[1];

      lpDestCw = lpEnc->data;    /* codeword array including overhead */
      lpSrcCw  = lpCw->data;     /* data region and ECC codewords */
      for( r=0; r < (uint8)lpEnc->dmatrix.rows; r++ ) {
         /*
         * Add the left row indicator - non for naked PDF symbols
         */
#ifndef NO_MICROPDF
         if ( lpAppParam->symtype != STYLE_MICRO )
#endif
         if ( lpAppParam->symtype != STYLE_NAKED )
            *lpDestCw++ = (30 * (r/3)) + anLRIndicator[ r % 3 ];
         /*
         * Pack in the columns data codewords
         */
         for( c=0; c < (uint8)lpEnc->dmatrix.cols; c++ )
            *lpDestCw++ = *lpSrcCw++;
         /*
         * Add right row indicator -- only for normal PDF symbols
         */
         if ( lpAppParam->symtype == STYLE_NORMAL )
            *lpDestCw++ = (30 * (r/3)) + anRRIndicator[ r % 3 ];
      }
   }
   return( status );
}

 

  • 17
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值