1 /***************************************************************************/
5 /* CID-keyed Type1 font loader (body). */
7 /* Copyright 1996-2001, 2002 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 /***************************************************************************/
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_CONFIG_CONFIG_H
22 #include FT_MULTIPLE_MASTERS_H
23 #include FT_INTERNAL_TYPE1_TYPES_H
30 /*************************************************************************/
32 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
33 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
34 /* messages during execution. */
37 #define FT_COMPONENT trace_cidload
40 /* read a single offset */
41 FT_LOCAL_DEF( FT_Long
)
42 cid_get_offset( FT_Byte
** start
,
49 for ( result
= 0; offsize
> 0; offsize
-- )
61 cid_decrypt( FT_Byte
* buffer
,
70 plain
= (FT_Byte
)( *buffer
^ ( seed
>> 8 ) );
71 seed
= (FT_UShort
)( ( *buffer
+ seed
) * 52845U + 22719 );
78 /*************************************************************************/
79 /*************************************************************************/
81 /***** TYPE 1 SYMBOL PARSING *****/
83 /*************************************************************************/
84 /*************************************************************************/
88 cid_load_keyword( CID_Face face
,
90 const T1_Field keyword
)
93 CID_Parser
* parser
= &loader
->parser
;
96 CID_FaceInfo cid
= &face
->cid
;
99 /* if the keyword has a dedicated callback, call it */
100 if ( keyword
->type
== T1_FIELD_TYPE_CALLBACK
)
102 keyword
->reader( (FT_Face
)face
, parser
);
103 error
= parser
->root
.error
;
107 /* we must now compute the address of our target object */
108 switch ( keyword
->location
)
110 case T1_FIELD_LOCATION_CID_INFO
:
111 object
= (FT_Byte
*)cid
;
114 case T1_FIELD_LOCATION_FONT_INFO
:
115 object
= (FT_Byte
*)&cid
->font_info
;
123 if ( parser
->num_dict
< 0 )
125 FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
127 error
= CID_Err_Syntax_Error
;
131 dict
= cid
->font_dicts
+ parser
->num_dict
;
132 switch ( keyword
->location
)
134 case T1_FIELD_LOCATION_PRIVATE
:
135 object
= (FT_Byte
*)&dict
->private_dict
;
139 object
= (FT_Byte
*)dict
;
144 dummy_object
= object
;
146 /* now, load the keyword data in the object's field(s) */
147 if ( keyword
->type
== T1_FIELD_TYPE_INTEGER_ARRAY
||
148 keyword
->type
== T1_FIELD_TYPE_FIXED_ARRAY
)
149 error
= CID_Load_Field_Table( &loader
->parser
, keyword
,
152 error
= CID_Load_Field( &loader
->parser
, keyword
, &dummy_object
);
158 FT_CALLBACK_DEF( FT_Error
)
159 parse_font_bbox( CID_Face face
,
163 FT_BBox
* bbox
= &face
->cid
.font_bbox
;
166 (void)CID_ToFixedArray( parser
, 4, temp
, 0 );
167 bbox
->xMin
= FT_RoundFix( temp
[0] );
168 bbox
->yMin
= FT_RoundFix( temp
[1] );
169 bbox
->xMax
= FT_RoundFix( temp
[2] );
170 bbox
->yMax
= FT_RoundFix( temp
[3] );
172 return CID_Err_Ok
; /* this is a callback function; */
173 /* we must return an error code */
177 FT_CALLBACK_DEF( FT_Error
)
178 parse_font_matrix( CID_Face face
,
184 FT_Face root
= (FT_Face
)&face
->root
;
189 if ( parser
->num_dict
>= 0 )
191 dict
= face
->cid
.font_dicts
+ parser
->num_dict
;
192 matrix
= &dict
->font_matrix
;
193 offset
= &dict
->font_offset
;
195 (void)CID_ToFixedArray( parser
, 6, temp
, 3 );
197 temp_scale
= ABS( temp
[3] );
199 /* Set Units per EM based on FontMatrix values. We set the value to */
200 /* `1000/temp_scale', because temp_scale was already multiplied by */
201 /* 1000 (in t1_tofixed(), from psobjs.c). */
202 root
->units_per_EM
= (FT_UShort
)( FT_DivFix( 0x10000L
,
203 FT_DivFix( temp_scale
, 1000 ) ) );
205 /* we need to scale the values by 1.0/temp[3] */
206 if ( temp_scale
!= 0x10000L
)
208 temp
[0] = FT_DivFix( temp
[0], temp_scale
);
209 temp
[1] = FT_DivFix( temp
[1], temp_scale
);
210 temp
[2] = FT_DivFix( temp
[2], temp_scale
);
211 temp
[4] = FT_DivFix( temp
[4], temp_scale
);
212 temp
[5] = FT_DivFix( temp
[5], temp_scale
);
216 matrix
->xx
= temp
[0];
217 matrix
->yx
= temp
[1];
218 matrix
->xy
= temp
[2];
219 matrix
->yy
= temp
[3];
221 /* note that the font offsets are expressed in integer font units */
222 offset
->x
= temp
[4] >> 16;
223 offset
->y
= temp
[5] >> 16;
226 return CID_Err_Ok
; /* this is a callback function; */
227 /* we must return an error code */
231 FT_CALLBACK_DEF( FT_Error
)
232 parse_fd_array( CID_Face face
,
235 CID_FaceInfo cid
= &face
->cid
;
236 FT_Memory memory
= face
->root
.memory
;
237 FT_Error error
= CID_Err_Ok
;
241 num_dicts
= CID_ToInt( parser
);
243 if ( !cid
->font_dicts
)
248 if ( FT_NEW_ARRAY( cid
->font_dicts
, num_dicts
) )
251 cid
->num_dicts
= (FT_UInt
)num_dicts
;
253 /* don't forget to set a few defaults */
254 for ( n
= 0; n
< cid
->num_dicts
; n
++ )
256 CID_FaceDict dict
= cid
->font_dicts
+ n
;
259 /* default value for lenIV */
260 dict
->private_dict
.lenIV
= 4;
270 const T1_FieldRec cid_field_records
[] =
273 #include "cidtoken.h"
275 T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox
)
276 T1_FIELD_CALLBACK( "FDArray", parse_fd_array
)
277 T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix
)
278 { 0, T1_FIELD_LOCATION_CID_INFO
, T1_FIELD_TYPE_NONE
, 0, 0, 0, 0, 0 }
285 return ( ft_isalnum( (int)c
) ||
292 cid_parse_dict( CID_Face face
,
297 CID_Parser
* parser
= &loader
->parser
;
300 parser
->root
.cursor
= base
;
301 parser
->root
.limit
= base
+ size
;
302 parser
->root
.error
= 0;
306 FT_Byte
* limit
= cur
+ size
;
309 for ( ;cur
< limit
; cur
++ )
311 /* look for `%ADOBeginFontDict' */
312 if ( *cur
== '%' && cur
+ 20 < limit
&&
313 ft_strncmp( (char*)cur
, "%ADOBeginFontDict", 17 ) == 0 )
317 /* if /FDArray was found, then cid->num_dicts is > 0, and */
318 /* we can start increasing parser->num_dict */
319 if ( face
->cid
.num_dicts
> 0 )
322 /* look for immediates */
323 else if ( *cur
== '/' && cur
+ 2 < limit
)
332 while ( cur2
< limit
&& is_alpha( *cur2
) )
335 len
= (FT_Int
)( cur2
- cur
);
336 if ( len
> 0 && len
< 22 )
338 /* now compare the immediate name to the keyword table */
339 T1_Field keyword
= (T1_Field
) cid_field_records
;
347 name
= (FT_Byte
*)keyword
->ident
;
351 if ( cur
[0] == name
[0] &&
352 len
== (FT_Int
)ft_strlen( (const char*)name
) )
357 for ( n
= 1; n
< len
; n
++ )
358 if ( cur
[n
] != name
[n
] )
363 /* we found it - run the parsing callback */
364 parser
->root
.cursor
= cur2
;
365 CID_Skip_Spaces( parser
);
366 parser
->root
.error
= cid_load_keyword( face
,
369 if ( parser
->root
.error
)
370 return parser
->root
.error
;
372 cur
= parser
->root
.cursor
;
382 return parser
->root
.error
;
386 /* read the subrmap and the subrs of each font dict */
388 cid_read_subrs( CID_Face face
)
390 CID_FaceInfo cid
= &face
->cid
;
391 FT_Memory memory
= face
->root
.memory
;
392 FT_Stream stream
= face
->root
.stream
;
396 FT_UInt max_offsets
= 0;
397 FT_ULong
* offsets
= 0;
400 if ( FT_NEW_ARRAY( face
->subrs
, cid
->num_dicts
) )
404 for ( n
= 0; n
< cid
->num_dicts
; n
++, subr
++ )
406 CID_FaceDict dict
= cid
->font_dicts
+ n
;
407 FT_Int lenIV
= dict
->private_dict
.lenIV
;
408 FT_UInt count
, num_subrs
= dict
->num_subrs
;
413 /* reallocate offsets array if needed */
414 if ( num_subrs
+ 1 > max_offsets
)
416 FT_UInt new_max
= ( num_subrs
+ 1 + 3 ) & -4;
419 if ( FT_RENEW_ARRAY( offsets
, max_offsets
, new_max
) )
422 max_offsets
= new_max
;
425 /* read the subrmap's offsets */
426 if ( FT_STREAM_SEEK( cid
->data_offset
+ dict
->subrmap_offset
) ||
427 FT_FRAME_ENTER( ( num_subrs
+ 1 ) * dict
->sd_bytes
) )
430 p
= (FT_Byte
*)stream
->cursor
;
431 for ( count
= 0; count
<= num_subrs
; count
++ )
432 offsets
[count
] = cid_get_offset( &p
, (FT_Byte
)dict
->sd_bytes
);
436 /* now, compute the size of subrs charstrings, */
437 /* allocate, and read them */
438 data_len
= offsets
[num_subrs
] - offsets
[0];
440 if ( FT_NEW_ARRAY( subr
->code
, num_subrs
+ 1 ) ||
441 FT_ALLOC( subr
->code
[0], data_len
) )
444 if ( FT_STREAM_SEEK( cid
->data_offset
+ offsets
[0] ) ||
445 FT_STREAM_READ( subr
->code
[0], data_len
) )
448 /* set up pointers */
449 for ( count
= 1; count
<= num_subrs
; count
++ )
454 len
= offsets
[count
] - offsets
[count
- 1];
455 subr
->code
[count
] = subr
->code
[count
- 1] + len
;
458 /* decrypt subroutines, but only if lenIV >= 0 */
461 for ( count
= 0; count
< num_subrs
; count
++ )
466 len
= offsets
[count
+ 1] - offsets
[count
];
467 cid_decrypt( subr
->code
[count
], len
, 4330 );
471 subr
->num_subrs
= num_subrs
;
481 for ( n
= 0; n
< cid
->num_dicts
; n
++ )
483 if ( face
->subrs
[n
].code
)
484 FT_FREE( face
->subrs
[n
].code
[0] );
486 FT_FREE( face
->subrs
[n
].code
);
488 FT_FREE( face
->subrs
);
495 t1_init_loader( CID_Loader
* loader
,
500 FT_MEM_SET( loader
, 0, sizeof ( *loader
) );
505 t1_done_loader( CID_Loader
* loader
)
507 CID_Parser
* parser
= &loader
->parser
;
510 /* finalize parser */
511 CID_Done_Parser( parser
);
515 FT_LOCAL_DEF( FT_Error
)
516 CID_Open_Face( CID_Face face
)
523 t1_init_loader( &loader
, face
);
525 parser
= &loader
.parser
;
526 error
= CID_New_Parser( parser
, face
->root
.stream
, face
->root
.memory
,
527 (PSAux_Service
)face
->psaux
);
531 error
= cid_parse_dict( face
, &loader
,
533 parser
->postscript_len
);
537 face
->cid
.data_offset
= loader
.parser
.data_offset
;
538 error
= cid_read_subrs( face
);
541 t1_done_loader( &loader
);