1 /***************************************************************************/ 
   5 /*    CID-keyed Type1 font loader (body).                                  */ 
   7 /*  Copyright 1996-2000 by                                                 */ 
   8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */ 
  10 /*  This file is part of the FreeType project, and may only be used,       */ 
  11 /*  modified, and distributed under the terms of the FreeType project      */ 
  12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */ 
  13 /*  this file you indicate that you have read the license and              */ 
  14 /*  understand and accept it fully.                                        */ 
  16 /***************************************************************************/ 
  19 #include <freetype/internal/ftdebug.h> 
  20 #include <freetype/config/ftconfig.h> 
  21 #include <freetype/ftmm.h> 
  23 #include <freetype/internal/t1types.h> 
  24 #include <freetype/internal/t1errors.h> 
  27 #ifdef FT_FLAT_COMPILE 
  33 #include <cid/cidload.h> 
  39 #include <ctype.h>  /* for isspace(), isalnum() */ 
  42   /*************************************************************************/ 
  44   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */ 
  45   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */ 
  46   /* messages during execution.                                            */ 
  49 #define FT_COMPONENT  trace_cidload 
  52   /* read a single offset */ 
  54   FT_Long  
cid_get_offset( FT_Byte
**  start
, 
  61     for ( result 
= 0; offsize 
> 0; offsize
-- ) 
  73   void  cid_decrypt( FT_Byte
*   buffer
, 
  82       plain     
= ( *buffer 
^ ( seed 
>> 8 ) ); 
  83       seed      
= ( *buffer 
+ seed 
) * 52845 + 22719; 
  90   /*************************************************************************/ 
  91   /*************************************************************************/ 
  93   /*****                    TYPE 1 SYMBOL PARSING                      *****/ 
  95   /*************************************************************************/ 
  96   /*************************************************************************/ 
 100   FT_Error  
cid_load_keyword( CID_Face              face
, 
 102                               const CID_Field_Rec
*  keyword 
) 
 105     CID_Parser
*  parser 
= &loader
->parser
; 
 107     CID_Info
*    cid 
= &face
->cid
; 
 110     /* if the keyword has a dedicated callback, call it */ 
 111     if ( keyword
->type 
== t1_field_callback 
) 
 113       error 
= keyword
->reader( face
, parser 
); 
 117     /* we must now compute the address of our target object */ 
 118     switch ( keyword
->location 
) 
 120     case t1_field_cid_info
: 
 121       object 
= (FT_Byte
*)cid
; 
 124     case t1_field_font_info
: 
 125       object 
= (FT_Byte
*)&cid
->font_info
; 
 133         if ( parser
->num_dict 
< 0 ) 
 135           FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n", 
 137           error 
= T1_Err_Syntax_Error
; 
 141         dict 
= cid
->font_dicts 
+ parser
->num_dict
; 
 142         switch ( keyword
->location 
) 
 144         case t1_field_private
: 
 145           object 
= (FT_Byte
*)&dict
->private_dict
; 
 149           object 
= (FT_Byte
*)dict
; 
 154     /* now, load the keyword data in the object's field(s) */ 
 155     if ( keyword
->type 
== t1_field_integer_array 
|| 
 156          keyword
->type 
== t1_field_fixed_array   
) 
 157       error 
= CID_Load_Field_Table( parser
, keyword
, object 
); 
 159       error 
= CID_Load_Field( parser
, keyword
, object 
); 
 167   FT_Error  
parse_font_bbox( CID_Face     face
, 
 171     FT_BBox
*  bbox 
= &face
->cid
.font_bbox
; 
 174     (void)CID_ToCoordArray( parser
, 4, temp 
); 
 175     bbox
->xMin 
= temp
[0]; 
 176     bbox
->yMin 
= temp
[1]; 
 177     bbox
->xMax 
= temp
[2]; 
 178     bbox
->yMax 
= temp
[3]; 
 180     return T1_Err_Ok
;       /* this is a callback function; */ 
 181                             /* we must return an error code */ 
 186   FT_Error  
parse_font_matrix( CID_Face     face
, 
 194     if ( parser
->num_dict 
>= 0 ) 
 196       dict   
= face
->cid
.font_dicts 
+ parser
->num_dict
; 
 197       matrix 
= &dict
->font_matrix
; 
 199       (void)CID_ToFixedArray( parser
, 4, temp
, 3 ); 
 200       matrix
->xx 
= temp
[0]; 
 201       matrix
->yx 
= temp
[1]; 
 202       matrix
->xy 
= temp
[2]; 
 203       matrix
->yy 
= temp
[3]; 
 206     return T1_Err_Ok
;       /* this is a callback function; */ 
 207                             /* we must return an error code */ 
 212   FT_Error  
parse_fd_array( CID_Face     face
, 
 215     CID_Info
*  cid    
= &face
->cid
; 
 216     FT_Memory  memory 
= face
->root
.memory
; 
 217     FT_Error   error  
= T1_Err_Ok
; 
 221     num_dicts 
= CID_ToInt( parser 
); 
 223     if ( !cid
->font_dicts 
) 
 228       if ( ALLOC_ARRAY( cid
->font_dicts
, num_dicts
, CID_FontDict 
) ) 
 231       cid
->num_dicts 
= (FT_UInt
)num_dicts
; 
 233       /* don't forget to set a few defaults */ 
 234       for ( n 
= 0; n 
< cid
->num_dicts
; n
++ ) 
 236         CID_FontDict
*  dict 
= cid
->font_dicts 
+ n
; 
 239         /* default value for lenIV */ 
 240         dict
->private_dict
.lenIV 
= 4; 
 250   const CID_Field_Rec  t1_field_records
[] = 
 253 #ifdef FT_FLAT_COMPILE 
 255 #include "cidtokens.h" 
 259 #include <cid/cidtokens.h> 
 263     { 0, t1_field_cid_info
, t1_field_none
, 0, 0, 0, 0, 0 } 
 268   int  is_alpha( char  c 
) 
 270     return ( isalnum( c 
) || 
 277   void  skip_whitespace( CID_Parser
*  parser 
) 
 279     FT_Byte
*  cur 
= parser
->cursor
; 
 282     while ( cur 
< parser
->limit 
&& isspace( *cur 
) ) 
 285     parser
->cursor 
= cur
; 
 290   FT_Error  
parse_dict( CID_Face     face
, 
 295     CID_Parser
*  parser 
= &loader
->parser
; 
 298     parser
->cursor 
= base
; 
 299     parser
->limit  
= base 
+ size
; 
 304       FT_Byte
*  limit 
= cur 
+ size
; 
 307       for ( ;cur 
< limit
; cur
++ ) 
 309         /* look for `%ADOBeginFontDict' */ 
 310         if ( *cur 
== '%' && cur 
+ 20 < limit 
&& 
 311              strncmp( (char*)cur
, "%ADOBeginFontDict", 17 ) == 0 ) 
 315           /* if /FDArray was found, then cid->num_dicts is > 0, and */ 
 316           /* we can start increasing parser->num_dict               */ 
 317           if ( face
->cid
.num_dicts 
> 0 ) 
 320         /* look for immediates */ 
 321         else if ( *cur 
== '/' && cur 
+ 2 < limit 
) 
 330           while ( cur2 
< limit 
&& is_alpha( *cur2 
) ) 
 334           if ( len 
> 0 && len 
< 22 ) 
 336             /* now compare the immediate name to the keyword table */ 
 337             const CID_Field_Rec
*  keyword 
= t1_field_records
; 
 345               name 
= (FT_Byte
*)keyword
->ident
; 
 349               if ( cur
[0] == name
[0]                          && 
 350                    len 
== (FT_Int
)strlen( (const char*)name 
) ) 
 355                 for ( n 
= 1; n 
< len
; n
++ ) 
 356                   if ( cur
[n
] != name
[n
] ) 
 361                   /* we found it - run the parsing callback */ 
 362                   parser
->cursor 
= cur2
; 
 363                   skip_whitespace( parser 
); 
 364                   parser
->error 
= cid_load_keyword( face
, loader
, keyword 
); 
 366                     return parser
->error
; 
 368                   cur 
= parser
->cursor
; 
 378     return parser
->error
; 
 382   /* read the subrmap and the subrs of each font dict */ 
 384   FT_Error  
cid_read_subrs( CID_Face  face 
) 
 386     CID_Info
*   cid    
= &face
->cid
; 
 387     FT_Memory   memory 
= face
->root
.memory
; 
 388     FT_Stream   stream 
= face
->root
.stream
; 
 392     FT_UInt     max_offsets 
= 0; 
 393     FT_ULong
*   offsets 
= 0; 
 396     if ( ALLOC_ARRAY( face
->subrs
, cid
->num_dicts
, CID_Subrs 
) ) 
 400     for ( n 
= 0; n 
< cid
->num_dicts
; n
++, subr
++ ) 
 402       CID_FontDict
*  dict 
= cid
->font_dicts 
+ n
; 
 403       FT_UInt        count
, num_subrs 
= dict
->num_subrs
; 
 408       /* reallocate offsets array if needed */ 
 409       if ( num_subrs 
+ 1 > max_offsets 
) 
 411         FT_UInt  new_max 
= ( num_subrs 
+ 1 + 3 ) & -4; 
 414         if ( REALLOC_ARRAY( offsets
, max_offsets
, new_max
, FT_ULong 
) ) 
 417         max_offsets 
= new_max
; 
 420       /* read the subrmap's offsets */ 
 421       if ( FILE_Seek( cid
->data_offset 
+ dict
->subrmap_offset 
) || 
 422            ACCESS_Frame( ( num_subrs 
+ 1 ) * dict
->sd_bytes 
)   ) 
 425       p 
= (FT_Byte
*)stream
->cursor
; 
 426       for ( count 
= 0; count 
<= num_subrs
; count
++ ) 
 427         offsets
[count
] = cid_get_offset( &p
, (FT_Byte
)dict
->sd_bytes 
); 
 431       /* now, compute the size of subrs charstrings, */ 
 432       /* allocate, and read them                     */ 
 433       data_len 
= offsets
[num_subrs
] - offsets
[0]; 
 435       if ( ALLOC_ARRAY( subr
->code
, num_subrs 
+ 1, FT_Byte
* ) || 
 436            ALLOC( subr
->code
[0], data_len 
)                   ) 
 439       if ( FILE_Seek( cid
->data_offset 
+ offsets
[0] ) || 
 440            FILE_Read( subr
->code
[0], data_len 
)  ) 
 443       /* set up pointers */ 
 444       for ( count 
= 1; count 
<= num_subrs
; count
++ ) 
 449         len               
= offsets
[count
] - offsets
[count 
- 1]; 
 450         subr
->code
[count
] = subr
->code
[count 
- 1] + len
; 
 453       /* decrypt subroutines */ 
 454       for ( count 
= 0; count 
< num_subrs
; count
++ ) 
 459         len 
= offsets
[count 
+ 1] - offsets
[count
]; 
 460         cid_decrypt( subr
->code
[count
], len
, 4330 ); 
 463       subr
->num_subrs 
= num_subrs
; 
 473       for ( n 
= 0; n 
< cid
->num_dicts
; n
++ ) 
 475         if ( face
->subrs
[n
].code 
) 
 476           FREE( face
->subrs
[n
].code
[0] ); 
 478         FREE( face
->subrs
[n
].code 
); 
 487   void t1_init_loader( CID_Loader
*  loader
, 
 492     MEM_Set( loader
, 0, sizeof ( *loader 
) ); 
 497   void t1_done_loader( CID_Loader
*  loader 
) 
 499     CID_Parser
*  parser 
= &loader
->parser
; 
 502     /* finalize parser */ 
 503     CID_Done_Parser( parser 
); 
 508   FT_Error  
CID_Open_Face( CID_Face  face 
) 
 515     t1_init_loader( &loader
, face 
); 
 517     parser 
= &loader
.parser
; 
 518     error 
= CID_New_Parser( parser
, face
->root
.stream
, face
->root
.memory 
); 
 522     error 
= parse_dict( face
, &loader
, 
 524                         parser
->postscript_len 
); 
 528     face
->cid
.data_offset 
= loader
.parser
.data_offset
; 
 529     error 
= cid_read_subrs( face 
); 
 532     t1_done_loader( &loader 
);