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
);