blob: 44073dd44f3053f10505395f10b180f45de50385 [file] [log] [blame]
Werner Lemberge3c11d72000-06-16 06:49:56 +00001/***************************************************************************/
2/* */
3/* cidload.c */
4/* */
5/* CID-keyed Type1 font loader (body). */
6/* */
Werner Lemberg415235d2001-06-28 17:49:10 +00007/* Copyright 1996-2001 by */
Werner Lemberge3c11d72000-06-16 06:49:56 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
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. */
15/* */
16/***************************************************************************/
17
Werner Lembergcc069be2000-12-08 16:17:16 +000018
19#include <ft2build.h>
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
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000024
David Turner8d3a4012001-03-20 11:14:24 +000025#include "cidload.h"
Werner Lembergcc069be2000-12-08 16:17:16 +000026
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000027#include "ciderrs.h"
28
Werner Lembergcc069be2000-12-08 16:17:16 +000029#include <stdio.h>
30#include <ctype.h> /* for isspace(), isalnum() */
David Turner04aa8002000-06-01 03:27:48 +000031
Werner Lemberge3c11d72000-06-16 06:49:56 +000032
33 /*************************************************************************/
34 /* */
35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
37 /* messages during execution. */
38 /* */
David Turner04aa8002000-06-01 03:27:48 +000039#undef FT_COMPONENT
Werner Lemberge3c11d72000-06-16 06:49:56 +000040#define FT_COMPONENT trace_cidload
David Turner04aa8002000-06-01 03:27:48 +000041
Werner Lemberge3c11d72000-06-16 06:49:56 +000042
Werner Lembergac39ecd2000-06-30 22:24:36 +000043 /* read a single offset */
David Turnerbc82f1b2002-03-01 02:26:22 +000044 FT_LOCAL_DEF( FT_Long )
Werner Lemberg93616ec2001-06-27 19:46:12 +000045 cid_get_offset( FT_Byte** start,
46 FT_Byte offsize )
David Turner04aa8002000-06-01 03:27:48 +000047 {
David Turnerf9b8dec2000-06-16 19:34:52 +000048 FT_Long result;
49 FT_Byte* p = *start;
Werner Lemberge3c11d72000-06-16 06:49:56 +000050
51
David Turner04aa8002000-06-01 03:27:48 +000052 for ( result = 0; offsize > 0; offsize-- )
Werner Lembergac39ecd2000-06-30 22:24:36 +000053 {
54 result <<= 8;
55 result |= *p++;
56 }
Werner Lemberge3c11d72000-06-16 06:49:56 +000057
David Turner04aa8002000-06-01 03:27:48 +000058 *start = p;
59 return result;
60 }
61
62
David Turnerbc82f1b2002-03-01 02:26:22 +000063 FT_LOCAL_DEF( void )
Werner Lemberg93616ec2001-06-27 19:46:12 +000064 cid_decrypt( FT_Byte* buffer,
65 FT_Offset length,
66 FT_UShort seed )
David Turner04aa8002000-06-01 03:27:48 +000067 {
68 while ( length > 0 )
69 {
David Turnerf9b8dec2000-06-16 19:34:52 +000070 FT_Byte plain;
David Turner04aa8002000-06-01 03:27:48 +000071
Werner Lemberge3c11d72000-06-16 06:49:56 +000072
David Turner8edbcab2001-06-19 08:28:24 +000073 plain = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
Werner Lemberga560a1e2001-07-03 12:45:24 +000074 seed = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );
David Turner04aa8002000-06-01 03:27:48 +000075 *buffer++ = plain;
76 length--;
77 }
78 }
79
80
Werner Lemberge3c11d72000-06-16 06:49:56 +000081 /*************************************************************************/
82 /*************************************************************************/
83 /***** *****/
84 /***** TYPE 1 SYMBOL PARSING *****/
85 /***** *****/
86 /*************************************************************************/
87 /*************************************************************************/
David Turner04aa8002000-06-01 03:27:48 +000088
89
Werner Lemberg93616ec2001-06-27 19:46:12 +000090 static FT_Error
91 cid_load_keyword( CID_Face face,
92 CID_Loader* loader,
David Turner4e7eeee2002-02-28 16:10:29 +000093 const T1_Field keyword )
David Turner04aa8002000-06-01 03:27:48 +000094 {
Werner Lembergac39ecd2000-06-30 22:24:36 +000095 FT_Error error;
96 CID_Parser* parser = &loader->parser;
97 FT_Byte* object;
David Turner34f1c2f2000-08-23 22:47:44 +000098 void* dummy_object;
David Turner29644172002-02-28 18:59:37 +000099 CID_FaceInfo cid = &face->cid;
David Turner04aa8002000-06-01 03:27:48 +0000100
Werner Lemberge3c11d72000-06-16 06:49:56 +0000101
David Turner04aa8002000-06-01 03:27:48 +0000102 /* if the keyword has a dedicated callback, call it */
David Turner4e7eeee2002-02-28 16:10:29 +0000103 if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
David Turner04aa8002000-06-01 03:27:48 +0000104 {
David Turner34f1c2f2000-08-23 22:47:44 +0000105 keyword->reader( (FT_Face)face, parser );
106 error = parser->root.error;
David Turner04aa8002000-06-01 03:27:48 +0000107 goto Exit;
108 }
109
110 /* we must now compute the address of our target object */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000111 switch ( keyword->location )
David Turner04aa8002000-06-01 03:27:48 +0000112 {
David Turner429978b2002-03-14 10:09:35 +0000113 case T1_FIELD_LOCATION_CID_INFO:
David Turnerf9b8dec2000-06-16 19:34:52 +0000114 object = (FT_Byte*)cid;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000115 break;
116
David Turner429978b2002-03-14 10:09:35 +0000117 case T1_FIELD_LOCATION_FONT_INFO:
David Turnerf9b8dec2000-06-16 19:34:52 +0000118 object = (FT_Byte*)&cid->font_info;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000119 break;
120
121 default:
122 {
David Turner29644172002-02-28 18:59:37 +0000123 CID_FaceDict dict;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000124
125
126 if ( parser->num_dict < 0 )
David Turner04aa8002000-06-01 03:27:48 +0000127 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000128 FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
129 keyword->ident ));
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000130 error = CID_Err_Syntax_Error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000131 goto Exit;
David Turner04aa8002000-06-01 03:27:48 +0000132 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000133
134 dict = cid->font_dicts + parser->num_dict;
135 switch ( keyword->location )
136 {
David Turner429978b2002-03-14 10:09:35 +0000137 case T1_FIELD_LOCATION_PRIVATE:
David Turnerf9b8dec2000-06-16 19:34:52 +0000138 object = (FT_Byte*)&dict->private_dict;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000139 break;
140
141 default:
David Turnerf9b8dec2000-06-16 19:34:52 +0000142 object = (FT_Byte*)dict;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000143 }
144 }
David Turner04aa8002000-06-01 03:27:48 +0000145 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000146
David Turner34f1c2f2000-08-23 22:47:44 +0000147 dummy_object = object;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000148
David Turner04aa8002000-06-01 03:27:48 +0000149 /* now, load the keyword data in the object's field(s) */
David Turner4e7eeee2002-02-28 16:10:29 +0000150 if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
151 keyword->type == T1_FIELD_TYPE_FIXED_ARRAY )
David Turner34f1c2f2000-08-23 22:47:44 +0000152 error = CID_Load_Field_Table( &loader->parser, keyword,
153 &dummy_object );
David Turner04aa8002000-06-01 03:27:48 +0000154 else
David Turner34f1c2f2000-08-23 22:47:44 +0000155 error = CID_Load_Field( &loader->parser, keyword, &dummy_object );
David Turner04aa8002000-06-01 03:27:48 +0000156 Exit:
157 return error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000158 }
David Turner04aa8002000-06-01 03:27:48 +0000159
160
Werner Lemberg93616ec2001-06-27 19:46:12 +0000161 FT_CALLBACK_DEF( FT_Error )
David Turnerdee78132001-06-27 09:26:46 +0000162 parse_font_bbox( CID_Face face,
163 CID_Parser* parser )
David Turner04aa8002000-06-01 03:27:48 +0000164 {
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000165 FT_Fixed temp[4];
David Turnerf9b8dec2000-06-16 19:34:52 +0000166 FT_BBox* bbox = &face->cid.font_bbox;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000167
David Turner04aa8002000-06-01 03:27:48 +0000168
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000169 (void)CID_ToFixedArray( parser, 4, temp, 0 );
170 bbox->xMin = FT_RoundFix( temp[0] );
171 bbox->yMin = FT_RoundFix( temp[1] );
172 bbox->xMax = FT_RoundFix( temp[2] );
173 bbox->yMax = FT_RoundFix( temp[3] );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000174
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000175 return CID_Err_Ok; /* this is a callback function; */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000176 /* we must return an error code */
David Turner04aa8002000-06-01 03:27:48 +0000177 }
178
Werner Lemberge3c11d72000-06-16 06:49:56 +0000179
Werner Lemberg93616ec2001-06-27 19:46:12 +0000180 FT_CALLBACK_DEF( FT_Error )
David Turnerdee78132001-06-27 09:26:46 +0000181 parse_font_matrix( CID_Face face,
182 CID_Parser* parser )
David Turner04aa8002000-06-01 03:27:48 +0000183 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000184 FT_Matrix* matrix;
David Turner34f1c2f2000-08-23 22:47:44 +0000185 FT_Vector* offset;
David Turner29644172002-02-28 18:59:37 +0000186 CID_FaceDict dict;
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000187 FT_Face root = (FT_Face)&face->root;
David Turner34f1c2f2000-08-23 22:47:44 +0000188 FT_Fixed temp[6];
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000189 FT_Fixed temp_scale;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000190
Werner Lemberg29bac132001-03-11 11:28:39 +0000191
Werner Lemberge3c11d72000-06-16 06:49:56 +0000192 if ( parser->num_dict >= 0 )
David Turner04aa8002000-06-01 03:27:48 +0000193 {
194 dict = face->cid.font_dicts + parser->num_dict;
195 matrix = &dict->font_matrix;
David Turner34f1c2f2000-08-23 22:47:44 +0000196 offset = &dict->font_offset;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000197
David Turner34f1c2f2000-08-23 22:47:44 +0000198 (void)CID_ToFixedArray( parser, 6, temp, 3 );
199
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000200 temp_scale = ABS( temp[3] );
201
Werner Lemberg29bac132001-03-11 11:28:39 +0000202 /* Set Units per EM based on FontMatrix values. We set the value to */
203 /* `1000/temp_scale', because temp_scale was already multiplied by */
204 /* 1000 (in t1_tofixed(), from psobjs.c). */
David Turner37981102001-03-19 11:34:49 +0000205 root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,
David Turner09d55ce2001-05-11 18:08:58 +0000206 FT_DivFix( temp_scale, 1000 ) ) );
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000207
David Turner34f1c2f2000-08-23 22:47:44 +0000208 /* we need to scale the values by 1.0/temp[3] */
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000209 if ( temp_scale != 0x10000L )
David Turner34f1c2f2000-08-23 22:47:44 +0000210 {
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000211 temp[0] = FT_DivFix( temp[0], temp_scale );
212 temp[1] = FT_DivFix( temp[1], temp_scale );
213 temp[2] = FT_DivFix( temp[2], temp_scale );
214 temp[4] = FT_DivFix( temp[4], temp_scale );
215 temp[5] = FT_DivFix( temp[5], temp_scale );
David Turner34f1c2f2000-08-23 22:47:44 +0000216 temp[3] = 0x10000L;
217 }
218
David Turner04aa8002000-06-01 03:27:48 +0000219 matrix->xx = temp[0];
220 matrix->yx = temp[1];
221 matrix->xy = temp[2];
222 matrix->yy = temp[3];
Werner Lemberge4b32a52000-10-31 20:42:18 +0000223
Werner Lemberg6fbe4db2000-10-05 04:53:31 +0000224 /* note that the font offsets are expressed in integer font units */
David Turnerf00a4de2000-10-03 22:03:09 +0000225 offset->x = temp[4] >> 16;
226 offset->y = temp[5] >> 16;
David Turner04aa8002000-06-01 03:27:48 +0000227 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000228
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000229 return CID_Err_Ok; /* this is a callback function; */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000230 /* we must return an error code */
David Turner04aa8002000-06-01 03:27:48 +0000231 }
232
Werner Lemberge3c11d72000-06-16 06:49:56 +0000233
Werner Lemberg93616ec2001-06-27 19:46:12 +0000234 FT_CALLBACK_DEF( FT_Error )
David Turnerdee78132001-06-27 09:26:46 +0000235 parse_fd_array( CID_Face face,
236 CID_Parser* parser )
David Turner04aa8002000-06-01 03:27:48 +0000237 {
David Turner29644172002-02-28 18:59:37 +0000238 CID_FaceInfo cid = &face->cid;
David Turner04aa8002000-06-01 03:27:48 +0000239 FT_Memory memory = face->root.memory;
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000240 FT_Error error = CID_Err_Ok;
David Turnerf9b8dec2000-06-16 19:34:52 +0000241 FT_Long num_dicts;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000242
243
244 num_dicts = CID_ToInt( parser );
245
David Turner04aa8002000-06-01 03:27:48 +0000246 if ( !cid->font_dicts )
247 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000248 FT_Int n;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000249
250
David Turnere459d742002-03-22 13:52:37 +0000251 if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
David Turner04aa8002000-06-01 03:27:48 +0000252 goto Exit;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000253
David Turnerf9b8dec2000-06-16 19:34:52 +0000254 cid->num_dicts = (FT_UInt)num_dicts;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000255
256 /* don't forget to set a few defaults */
David Turner04aa8002000-06-01 03:27:48 +0000257 for ( n = 0; n < cid->num_dicts; n++ )
258 {
David Turner29644172002-02-28 18:59:37 +0000259 CID_FaceDict dict = cid->font_dicts + n;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000260
261
262 /* default value for lenIV */
David Turner04aa8002000-06-01 03:27:48 +0000263 dict->private_dict.lenIV = 4;
264 }
265 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000266
David Turner04aa8002000-06-01 03:27:48 +0000267 Exit:
268 return error;
269 }
270
271
David Turner04aa8002000-06-01 03:27:48 +0000272 static
David Turner4e7eeee2002-02-28 16:10:29 +0000273 const T1_FieldRec cid_field_records[] =
David Turner04aa8002000-06-01 03:27:48 +0000274 {
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000275
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000276#include "cidtoken.h"
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000277
David Turner34f1c2f2000-08-23 22:47:44 +0000278 T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
279 T1_FIELD_CALLBACK( "FDArray", parse_fd_array )
280 T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
David Turner429978b2002-03-14 10:09:35 +0000281 { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
David Turner04aa8002000-06-01 03:27:48 +0000282 };
283
284
Werner Lemberg93616ec2001-06-27 19:46:12 +0000285 static int
286 is_alpha( char c )
David Turner04aa8002000-06-01 03:27:48 +0000287 {
Werner Lemberg35ca3422000-07-31 12:14:27 +0000288 return ( isalnum( (int)c ) ||
289 c == '.' ||
290 c == '_' );
David Turner04aa8002000-06-01 03:27:48 +0000291 }
292
David Turner04aa8002000-06-01 03:27:48 +0000293
Werner Lemberg93616ec2001-06-27 19:46:12 +0000294 static FT_Error
295 cid_parse_dict( CID_Face face,
296 CID_Loader* loader,
297 FT_Byte* base,
298 FT_Long size )
David Turner04aa8002000-06-01 03:27:48 +0000299 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000300 CID_Parser* parser = &loader->parser;
301
David Turner04aa8002000-06-01 03:27:48 +0000302
David Turner34f1c2f2000-08-23 22:47:44 +0000303 parser->root.cursor = base;
304 parser->root.limit = base + size;
305 parser->root.error = 0;
David Turner04aa8002000-06-01 03:27:48 +0000306
307 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000308 FT_Byte* cur = base;
309 FT_Byte* limit = cur + size;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000310
David Turner04aa8002000-06-01 03:27:48 +0000311
312 for ( ;cur < limit; cur++ )
313 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000314 /* look for `%ADOBeginFontDict' */
David Turner04aa8002000-06-01 03:27:48 +0000315 if ( *cur == '%' && cur + 20 < limit &&
316 strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
317 {
318 cur += 17;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000319
David Turner04aa8002000-06-01 03:27:48 +0000320 /* if /FDArray was found, then cid->num_dicts is > 0, and */
321 /* we can start increasing parser->num_dict */
322 if ( face->cid.num_dicts > 0 )
323 parser->num_dict++;
324 }
325 /* look for immediates */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000326 else if ( *cur == '/' && cur + 2 < limit )
David Turner04aa8002000-06-01 03:27:48 +0000327 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000328 FT_Byte* cur2;
329 FT_Int len;
David Turner04aa8002000-06-01 03:27:48 +0000330
Werner Lemberge3c11d72000-06-16 06:49:56 +0000331
332 cur++;
333
David Turner04aa8002000-06-01 03:27:48 +0000334 cur2 = cur;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000335 while ( cur2 < limit && is_alpha( *cur2 ) )
336 cur2++;
David Turner04aa8002000-06-01 03:27:48 +0000337
Werner Lemberg914b2892001-03-10 17:07:42 +0000338 len = (FT_Int)( cur2 - cur );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000339 if ( len > 0 && len < 22 )
David Turner04aa8002000-06-01 03:27:48 +0000340 {
Werner Lembergac39ecd2000-06-30 22:24:36 +0000341 /* now compare the immediate name to the keyword table */
David Turner4e7eeee2002-02-28 16:10:29 +0000342 T1_Field keyword = (T1_Field) cid_field_records;
David Turner04aa8002000-06-01 03:27:48 +0000343
Werner Lemberge3c11d72000-06-16 06:49:56 +0000344
David Turner04aa8002000-06-01 03:27:48 +0000345 for (;;)
346 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000347 FT_Byte* name;
David Turner04aa8002000-06-01 03:27:48 +0000348
David Turner04aa8002000-06-01 03:27:48 +0000349
David Turnerf9b8dec2000-06-16 19:34:52 +0000350 name = (FT_Byte*)keyword->ident;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000351 if ( !name )
352 break;
353
354 if ( cur[0] == name[0] &&
David Turnerf9b8dec2000-06-16 19:34:52 +0000355 len == (FT_Int)strlen( (const char*)name ) )
David Turner04aa8002000-06-01 03:27:48 +0000356 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000357 FT_Int n;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000358
359
David Turner04aa8002000-06-01 03:27:48 +0000360 for ( n = 1; n < len; n++ )
Werner Lemberge3c11d72000-06-16 06:49:56 +0000361 if ( cur[n] != name[n] )
David Turner04aa8002000-06-01 03:27:48 +0000362 break;
363
Werner Lemberge3c11d72000-06-16 06:49:56 +0000364 if ( n >= len )
David Turner04aa8002000-06-01 03:27:48 +0000365 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000366 /* we found it - run the parsing callback */
David Turner34f1c2f2000-08-23 22:47:44 +0000367 parser->root.cursor = cur2;
368 CID_Skip_Spaces( parser );
Werner Lembergd1b74752000-08-24 16:29:15 +0000369 parser->root.error = cid_load_keyword( face,
370 loader,
371 keyword );
David Turner34f1c2f2000-08-23 22:47:44 +0000372 if ( parser->root.error )
373 return parser->root.error;
David Turner04aa8002000-06-01 03:27:48 +0000374
David Turner34f1c2f2000-08-23 22:47:44 +0000375 cur = parser->root.cursor;
David Turner04aa8002000-06-01 03:27:48 +0000376 break;
377 }
378 }
379 keyword++;
380 }
381 }
382 }
383 }
384 }
David Turner34f1c2f2000-08-23 22:47:44 +0000385 return parser->root.error;
David Turner04aa8002000-06-01 03:27:48 +0000386 }
387
388
David Turner04aa8002000-06-01 03:27:48 +0000389 /* read the subrmap and the subrs of each font dict */
Werner Lemberg93616ec2001-06-27 19:46:12 +0000390 static FT_Error
391 cid_read_subrs( CID_Face face )
David Turner04aa8002000-06-01 03:27:48 +0000392 {
David Turner29644172002-02-28 18:59:37 +0000393 CID_FaceInfo cid = &face->cid;
David Turner04aa8002000-06-01 03:27:48 +0000394 FT_Memory memory = face->root.memory;
395 FT_Stream stream = face->root.stream;
David Turnerf9b8dec2000-06-16 19:34:52 +0000396 FT_Error error;
David Turnera1be2dc2000-06-27 23:20:35 +0000397 FT_Int n;
David Turner29644172002-02-28 18:59:37 +0000398 CID_Subrs subr;
David Turnerf9b8dec2000-06-16 19:34:52 +0000399 FT_UInt max_offsets = 0;
400 FT_ULong* offsets = 0;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000401
402
David Turnere459d742002-03-22 13:52:37 +0000403 if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )
David Turner04aa8002000-06-01 03:27:48 +0000404 goto Exit;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000405
David Turner04aa8002000-06-01 03:27:48 +0000406 subr = face->subrs;
407 for ( n = 0; n < cid->num_dicts; n++, subr++ )
408 {
David Turner29644172002-02-28 18:59:37 +0000409 CID_FaceDict dict = cid->font_dicts + n;
Tom Kacvinsky68621132001-03-12 02:17:50 +0000410 FT_Int lenIV = dict->private_dict.lenIV;
David Turnerf9b8dec2000-06-16 19:34:52 +0000411 FT_UInt count, num_subrs = dict->num_subrs;
412 FT_ULong data_len;
413 FT_Byte* p;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000414
415
David Turner04aa8002000-06-01 03:27:48 +0000416 /* reallocate offsets array if needed */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000417 if ( num_subrs + 1 > max_offsets )
David Turner04aa8002000-06-01 03:27:48 +0000418 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000419 FT_UInt new_max = ( num_subrs + 1 + 3 ) & -4;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000420
421
David Turnere459d742002-03-22 13:52:37 +0000422 if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )
David Turner04aa8002000-06-01 03:27:48 +0000423 goto Fail;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000424
David Turner04aa8002000-06-01 03:27:48 +0000425 max_offsets = new_max;
426 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000427
David Turner04aa8002000-06-01 03:27:48 +0000428 /* read the subrmap's offsets */
David Turner7d3a2642002-03-20 10:49:31 +0000429 if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||
430 FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes ) )
David Turner04aa8002000-06-01 03:27:48 +0000431 goto Fail;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000432
David Turner04aa8002000-06-01 03:27:48 +0000433 p = (FT_Byte*)stream->cursor;
434 for ( count = 0; count <= num_subrs; count++ )
David Turner81bb4ad2000-06-28 04:19:49 +0000435 offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000436
David Turner7d3a2642002-03-20 10:49:31 +0000437 FT_FRAME_EXIT();
Werner Lemberge3c11d72000-06-16 06:49:56 +0000438
439 /* now, compute the size of subrs charstrings, */
440 /* allocate, and read them */
David Turner04aa8002000-06-01 03:27:48 +0000441 data_len = offsets[num_subrs] - offsets[0];
Werner Lemberge3c11d72000-06-16 06:49:56 +0000442
David Turnere459d742002-03-22 13:52:37 +0000443 if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||
444 FT_ALLOC( subr->code[0], data_len ) )
David Turner04aa8002000-06-01 03:27:48 +0000445 goto Fail;
446
David Turner7d3a2642002-03-20 10:49:31 +0000447 if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
448 FT_STREAM_READ( subr->code[0], data_len ) )
David Turner3a664fc2001-12-21 15:26:19 +0000449 goto Fail;
David Turner04aa8002000-06-01 03:27:48 +0000450
451 /* set up pointers */
452 for ( count = 1; count <= num_subrs; count++ )
453 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000454 FT_UInt len;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000455
456
457 len = offsets[count] - offsets[count - 1];
458 subr->code[count] = subr->code[count - 1] + len;
David Turner04aa8002000-06-01 03:27:48 +0000459 }
460
Werner Lemberg9a8b5362001-03-12 22:33:52 +0000461 /* decrypt subroutines, but only if lenIV >= 0 */
Tom Kacvinsky68621132001-03-12 02:17:50 +0000462 if ( lenIV >= 0 )
David Turner04aa8002000-06-01 03:27:48 +0000463 {
Tom Kacvinsky68621132001-03-12 02:17:50 +0000464 for ( count = 0; count < num_subrs; count++ )
465 {
466 FT_UInt len;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000467
468
Tom Kacvinsky68621132001-03-12 02:17:50 +0000469 len = offsets[count + 1] - offsets[count];
470 cid_decrypt( subr->code[count], len, 4330 );
471 }
David Turner04aa8002000-06-01 03:27:48 +0000472 }
473
474 subr->num_subrs = num_subrs;
475 }
476
477 Exit:
David Turnere459d742002-03-22 13:52:37 +0000478 FT_FREE( offsets );
David Turner04aa8002000-06-01 03:27:48 +0000479 return error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000480
David Turner04aa8002000-06-01 03:27:48 +0000481 Fail:
Werner Lemberge3c11d72000-06-16 06:49:56 +0000482 if ( face->subrs )
David Turner04aa8002000-06-01 03:27:48 +0000483 {
484 for ( n = 0; n < cid->num_dicts; n++ )
485 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000486 if ( face->subrs[n].code )
David Turnere459d742002-03-22 13:52:37 +0000487 FT_FREE( face->subrs[n].code[0] );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000488
David Turnere459d742002-03-22 13:52:37 +0000489 FT_FREE( face->subrs[n].code );
David Turner04aa8002000-06-01 03:27:48 +0000490 }
David Turnere459d742002-03-22 13:52:37 +0000491 FT_FREE( face->subrs );
David Turner04aa8002000-06-01 03:27:48 +0000492 }
493 goto Exit;
494 }
495
Werner Lemberge3c11d72000-06-16 06:49:56 +0000496
Werner Lemberg93616ec2001-06-27 19:46:12 +0000497 static void
498 t1_init_loader( CID_Loader* loader,
499 CID_Face face )
David Turner04aa8002000-06-01 03:27:48 +0000500 {
David Turnerc6a92202000-07-04 18:12:13 +0000501 FT_UNUSED( face );
David Turner04aa8002000-06-01 03:27:48 +0000502
David Turnere459d742002-03-22 13:52:37 +0000503 FT_MEM_SET( loader, 0, sizeof ( *loader ) );
David Turner04aa8002000-06-01 03:27:48 +0000504 }
505
Werner Lemberge3c11d72000-06-16 06:49:56 +0000506
Werner Lemberg93616ec2001-06-27 19:46:12 +0000507 static void
508 t1_done_loader( CID_Loader* loader )
David Turner04aa8002000-06-01 03:27:48 +0000509 {
510 CID_Parser* parser = &loader->parser;
511
Werner Lemberge3c11d72000-06-16 06:49:56 +0000512
David Turner04aa8002000-06-01 03:27:48 +0000513 /* finalize parser */
514 CID_Done_Parser( parser );
515 }
516
Werner Lemberge3c11d72000-06-16 06:49:56 +0000517
David Turnerbc82f1b2002-03-01 02:26:22 +0000518 FT_LOCAL_DEF( FT_Error )
Werner Lemberg93616ec2001-06-27 19:46:12 +0000519 CID_Open_Face( CID_Face face )
David Turner04aa8002000-06-01 03:27:48 +0000520 {
521 CID_Loader loader;
522 CID_Parser* parser;
David Turnerf9b8dec2000-06-16 19:34:52 +0000523 FT_Error error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000524
David Turner04aa8002000-06-01 03:27:48 +0000525
526 t1_init_loader( &loader, face );
527
528 parser = &loader.parser;
David Turner34f1c2f2000-08-23 22:47:44 +0000529 error = CID_New_Parser( parser, face->root.stream, face->root.memory,
David Turner4e7eeee2002-02-28 16:10:29 +0000530 (PSAux_Service)face->psaux );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000531 if ( error )
532 goto Exit;
David Turner04aa8002000-06-01 03:27:48 +0000533
David Turner34f1c2f2000-08-23 22:47:44 +0000534 error = cid_parse_dict( face, &loader,
535 parser->postscript,
536 parser->postscript_len );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000537 if ( error )
538 goto Exit;
David Turner04aa8002000-06-01 03:27:48 +0000539
540 face->cid.data_offset = loader.parser.data_offset;
541 error = cid_read_subrs( face );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000542
David Turner04aa8002000-06-01 03:27:48 +0000543 Exit:
544 t1_done_loader( &loader );
545 return error;
546 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000547
548
549/* END */