blob: 09735a02ccb5d7dfed1c16a7f24466d292567750 [file] [log] [blame]
Werner Lemberge3c11d72000-06-16 06:49:56 +00001/***************************************************************************/
2/* */
3/* cidload.c */
4/* */
5/* CID-keyed Type1 font loader (body). */
6/* */
7/* Copyright 1996-2000 by */
8/* 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
David Turner04aa8002000-06-01 03:27:48 +000018
19#include <freetype/internal/ftdebug.h>
20#include <freetype/config/ftconfig.h>
21#include <freetype/ftmm.h>
22
23#include <freetype/internal/t1types.h>
Werner Lemberge1d5dd72000-06-07 04:48:12 +000024#include <freetype/internal/t1errors.h>
David Turnera90663f2000-07-08 00:41:13 +000025
Werner Lemberg7fa51b52000-07-08 19:51:42 +000026
David Turnera90663f2000-07-08 00:41:13 +000027#ifdef FT_FLAT_COMPILE
Werner Lemberg7fa51b52000-07-08 19:51:42 +000028
David Turnera90663f2000-07-08 00:41:13 +000029#include "cidload.h"
Werner Lemberg7fa51b52000-07-08 19:51:42 +000030
David Turnera90663f2000-07-08 00:41:13 +000031#else
Werner Lemberg7fa51b52000-07-08 19:51:42 +000032
David Turnera90663f2000-07-08 00:41:13 +000033#include <cid/cidload.h>
Werner Lemberg7fa51b52000-07-08 19:51:42 +000034
David Turnera90663f2000-07-08 00:41:13 +000035#endif
Werner Lemberge3c11d72000-06-16 06:49:56 +000036
Werner Lemberg7fa51b52000-07-08 19:51:42 +000037
David Turner04aa8002000-06-01 03:27:48 +000038#include <stdio.h>
Werner Lemberge3c11d72000-06-16 06:49:56 +000039#include <ctype.h> /* for isspace(), isalnum() */
David Turner04aa8002000-06-01 03:27:48 +000040
Werner Lemberge3c11d72000-06-16 06:49:56 +000041
42 /*************************************************************************/
43 /* */
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. */
47 /* */
David Turner04aa8002000-06-01 03:27:48 +000048#undef FT_COMPONENT
Werner Lemberge3c11d72000-06-16 06:49:56 +000049#define FT_COMPONENT trace_cidload
David Turner04aa8002000-06-01 03:27:48 +000050
Werner Lemberge3c11d72000-06-16 06:49:56 +000051
Werner Lembergac39ecd2000-06-30 22:24:36 +000052 /* read a single offset */
David Turner04aa8002000-06-01 03:27:48 +000053 LOCAL_FUNC
David Turnerf9b8dec2000-06-16 19:34:52 +000054 FT_Long cid_get_offset( FT_Byte** start,
55 FT_Byte offsize )
David Turner04aa8002000-06-01 03:27:48 +000056 {
David Turnerf9b8dec2000-06-16 19:34:52 +000057 FT_Long result;
58 FT_Byte* p = *start;
Werner Lemberge3c11d72000-06-16 06:49:56 +000059
60
David Turner04aa8002000-06-01 03:27:48 +000061 for ( result = 0; offsize > 0; offsize-- )
Werner Lembergac39ecd2000-06-30 22:24:36 +000062 {
63 result <<= 8;
64 result |= *p++;
65 }
Werner Lemberge3c11d72000-06-16 06:49:56 +000066
David Turner04aa8002000-06-01 03:27:48 +000067 *start = p;
68 return result;
69 }
70
71
72 LOCAL_FUNC
David Turnerf9b8dec2000-06-16 19:34:52 +000073 void cid_decrypt( FT_Byte* buffer,
74 FT_Int length,
75 FT_UShort seed )
David Turner04aa8002000-06-01 03:27:48 +000076 {
77 while ( length > 0 )
78 {
David Turnerf9b8dec2000-06-16 19:34:52 +000079 FT_Byte plain;
David Turner04aa8002000-06-01 03:27:48 +000080
Werner Lemberge3c11d72000-06-16 06:49:56 +000081
82 plain = ( *buffer ^ ( seed >> 8 ) );
83 seed = ( *buffer + seed ) * 52845 + 22719;
David Turner04aa8002000-06-01 03:27:48 +000084 *buffer++ = plain;
85 length--;
86 }
87 }
88
89
Werner Lemberge3c11d72000-06-16 06:49:56 +000090 /*************************************************************************/
91 /*************************************************************************/
92 /***** *****/
93 /***** TYPE 1 SYMBOL PARSING *****/
94 /***** *****/
95 /*************************************************************************/
96 /*************************************************************************/
David Turner04aa8002000-06-01 03:27:48 +000097
98
Werner Lemberge3c11d72000-06-16 06:49:56 +000099 static
David Turner34f1c2f2000-08-23 22:47:44 +0000100 FT_Error cid_load_keyword( CID_Face face,
101 CID_Loader* loader,
102 const T1_Field* keyword )
David Turner04aa8002000-06-01 03:27:48 +0000103 {
Werner Lembergac39ecd2000-06-30 22:24:36 +0000104 FT_Error error;
105 CID_Parser* parser = &loader->parser;
106 FT_Byte* object;
David Turner34f1c2f2000-08-23 22:47:44 +0000107 void* dummy_object;
Werner Lembergac39ecd2000-06-30 22:24:36 +0000108 CID_Info* cid = &face->cid;
David Turner04aa8002000-06-01 03:27:48 +0000109
Werner Lemberge3c11d72000-06-16 06:49:56 +0000110
David Turner04aa8002000-06-01 03:27:48 +0000111 /* if the keyword has a dedicated callback, call it */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000112 if ( keyword->type == t1_field_callback )
David Turner04aa8002000-06-01 03:27:48 +0000113 {
David Turner34f1c2f2000-08-23 22:47:44 +0000114 keyword->reader( (FT_Face)face, parser );
115 error = parser->root.error;
David Turner04aa8002000-06-01 03:27:48 +0000116 goto Exit;
117 }
118
119 /* we must now compute the address of our target object */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000120 switch ( keyword->location )
David Turner04aa8002000-06-01 03:27:48 +0000121 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000122 case t1_field_cid_info:
David Turnerf9b8dec2000-06-16 19:34:52 +0000123 object = (FT_Byte*)cid;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000124 break;
125
126 case t1_field_font_info:
David Turnerf9b8dec2000-06-16 19:34:52 +0000127 object = (FT_Byte*)&cid->font_info;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000128 break;
129
130 default:
131 {
132 CID_FontDict* dict;
133
134
135 if ( parser->num_dict < 0 )
David Turner04aa8002000-06-01 03:27:48 +0000136 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000137 FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
138 keyword->ident ));
139 error = T1_Err_Syntax_Error;
140 goto Exit;
David Turner04aa8002000-06-01 03:27:48 +0000141 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000142
143 dict = cid->font_dicts + parser->num_dict;
144 switch ( keyword->location )
145 {
146 case t1_field_private:
David Turnerf9b8dec2000-06-16 19:34:52 +0000147 object = (FT_Byte*)&dict->private_dict;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000148 break;
149
150 default:
David Turnerf9b8dec2000-06-16 19:34:52 +0000151 object = (FT_Byte*)dict;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000152 }
153 }
David Turner04aa8002000-06-01 03:27:48 +0000154 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000155
David Turner34f1c2f2000-08-23 22:47:44 +0000156 dummy_object = object;
157
David Turner04aa8002000-06-01 03:27:48 +0000158 /* now, load the keyword data in the object's field(s) */
159 if ( keyword->type == t1_field_integer_array ||
160 keyword->type == t1_field_fixed_array )
David Turner34f1c2f2000-08-23 22:47:44 +0000161 error = CID_Load_Field_Table( &loader->parser, keyword,
162 &dummy_object );
David Turner04aa8002000-06-01 03:27:48 +0000163 else
David Turner34f1c2f2000-08-23 22:47:44 +0000164 error = CID_Load_Field( &loader->parser, keyword, &dummy_object );
David Turner04aa8002000-06-01 03:27:48 +0000165 Exit:
166 return error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000167 }
David Turner04aa8002000-06-01 03:27:48 +0000168
169
Werner Lemberg29a90e22000-08-03 00:03:08 +0000170 LOCAL_FUNC_X
David Turnerf9b8dec2000-06-16 19:34:52 +0000171 FT_Error parse_font_bbox( CID_Face face,
Werner Lemberge3c11d72000-06-16 06:49:56 +0000172 CID_Parser* parser )
David Turner04aa8002000-06-01 03:27:48 +0000173 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000174 FT_Short temp[4];
175 FT_BBox* bbox = &face->cid.font_bbox;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000176
David Turner04aa8002000-06-01 03:27:48 +0000177
178 (void)CID_ToCoordArray( parser, 4, temp );
179 bbox->xMin = temp[0];
180 bbox->yMin = temp[1];
181 bbox->xMax = temp[2];
182 bbox->yMax = temp[3];
Werner Lemberge3c11d72000-06-16 06:49:56 +0000183
184 return T1_Err_Ok; /* this is a callback function; */
185 /* we must return an error code */
David Turner04aa8002000-06-01 03:27:48 +0000186 }
187
Werner Lemberge3c11d72000-06-16 06:49:56 +0000188
Werner Lemberg29a90e22000-08-03 00:03:08 +0000189 LOCAL_FUNC_X
David Turnerf9b8dec2000-06-16 19:34:52 +0000190 FT_Error parse_font_matrix( CID_Face face,
Werner Lemberge3c11d72000-06-16 06:49:56 +0000191 CID_Parser* parser )
David Turner04aa8002000-06-01 03:27:48 +0000192 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000193 FT_Matrix* matrix;
David Turner34f1c2f2000-08-23 22:47:44 +0000194 FT_Vector* offset;
David Turner04aa8002000-06-01 03:27:48 +0000195 CID_FontDict* dict;
David Turner34f1c2f2000-08-23 22:47:44 +0000196 FT_Fixed temp[6];
David Turner04aa8002000-06-01 03:27:48 +0000197
Werner Lemberge3c11d72000-06-16 06:49:56 +0000198
199 if ( parser->num_dict >= 0 )
David Turner04aa8002000-06-01 03:27:48 +0000200 {
201 dict = face->cid.font_dicts + parser->num_dict;
202 matrix = &dict->font_matrix;
David Turner34f1c2f2000-08-23 22:47:44 +0000203 offset = &dict->font_offset;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000204
David Turner34f1c2f2000-08-23 22:47:44 +0000205 (void)CID_ToFixedArray( parser, 6, temp, 3 );
206
207 /* we need to scale the values by 1.0/temp[3] */
208 if ( temp[3] != 0x10000L )
209 {
210 temp[0] = FT_DivFix( temp[0], temp[3] );
211 temp[1] = FT_DivFix( temp[1], temp[3] );
212 temp[2] = FT_DivFix( temp[2], temp[3] );
213 temp[4] = FT_DivFix( temp[4], temp[3] );
214 temp[5] = FT_DivFix( temp[5], temp[3] );
215 temp[3] = 0x10000L;
216 }
217
David Turner04aa8002000-06-01 03:27:48 +0000218 matrix->xx = temp[0];
219 matrix->yx = temp[1];
220 matrix->xy = temp[2];
221 matrix->yy = temp[3];
David Turnerf00a4de2000-10-03 22:03:09 +0000222
Werner Lemberg6fbe4db2000-10-05 04:53:31 +0000223 /* note that the font offsets are expressed in integer font units */
David Turnerf00a4de2000-10-03 22:03:09 +0000224 offset->x = temp[4] >> 16;
225 offset->y = temp[5] >> 16;
David Turner04aa8002000-06-01 03:27:48 +0000226 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000227
228 return T1_Err_Ok; /* this is a callback function; */
229 /* we must return an error code */
David Turner04aa8002000-06-01 03:27:48 +0000230 }
231
Werner Lemberge3c11d72000-06-16 06:49:56 +0000232
Werner Lemberg29a90e22000-08-03 00:03:08 +0000233 LOCAL_FUNC_X
David Turnerf9b8dec2000-06-16 19:34:52 +0000234 FT_Error parse_fd_array( CID_Face face,
Werner Lemberge3c11d72000-06-16 06:49:56 +0000235 CID_Parser* parser )
David Turner04aa8002000-06-01 03:27:48 +0000236 {
237 CID_Info* cid = &face->cid;
238 FT_Memory memory = face->root.memory;
David Turnerf9b8dec2000-06-16 19:34:52 +0000239 FT_Error error = T1_Err_Ok;
240 FT_Long num_dicts;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000241
242
243 num_dicts = CID_ToInt( parser );
244
David Turner04aa8002000-06-01 03:27:48 +0000245 if ( !cid->font_dicts )
246 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000247 FT_Int n;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000248
249
David Turner04aa8002000-06-01 03:27:48 +0000250 if ( ALLOC_ARRAY( cid->font_dicts, num_dicts, CID_FontDict ) )
251 goto Exit;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000252
David Turnerf9b8dec2000-06-16 19:34:52 +0000253 cid->num_dicts = (FT_UInt)num_dicts;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000254
255 /* don't forget to set a few defaults */
David Turner04aa8002000-06-01 03:27:48 +0000256 for ( n = 0; n < cid->num_dicts; n++ )
257 {
258 CID_FontDict* dict = cid->font_dicts + n;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000259
260
261 /* default value for lenIV */
David Turner04aa8002000-06-01 03:27:48 +0000262 dict->private_dict.lenIV = 4;
263 }
264 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000265
David Turner04aa8002000-06-01 03:27:48 +0000266 Exit:
267 return error;
268 }
269
270
David Turner04aa8002000-06-01 03:27:48 +0000271 static
David Turner34f1c2f2000-08-23 22:47:44 +0000272 const T1_Field cid_field_records[] =
David Turner04aa8002000-06-01 03:27:48 +0000273 {
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000274
David Turnera90663f2000-07-08 00:41:13 +0000275#ifdef FT_FLAT_COMPILE
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000276
David Turnera90663f2000-07-08 00:41:13 +0000277#include "cidtokens.h"
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000278
David Turnera90663f2000-07-08 00:41:13 +0000279#else
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000280
David Turnera90663f2000-07-08 00:41:13 +0000281#include <cid/cidtokens.h>
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000282
David Turnera90663f2000-07-08 00:41:13 +0000283#endif
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000284
David Turner34f1c2f2000-08-23 22:47:44 +0000285 T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
286 T1_FIELD_CALLBACK( "FDArray", parse_fd_array )
287 T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
Werner Lemberg4e9dae62000-08-29 16:50:01 +0000288 { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
David Turner04aa8002000-06-01 03:27:48 +0000289 };
290
291
292 static
Werner Lemberge3c11d72000-06-16 06:49:56 +0000293 int is_alpha( char c )
David Turner04aa8002000-06-01 03:27:48 +0000294 {
Werner Lemberg35ca3422000-07-31 12:14:27 +0000295 return ( isalnum( (int)c ) ||
296 c == '.' ||
297 c == '_' );
David Turner04aa8002000-06-01 03:27:48 +0000298 }
299
David Turner04aa8002000-06-01 03:27:48 +0000300
David Turner04aa8002000-06-01 03:27:48 +0000301
David Turner04aa8002000-06-01 03:27:48 +0000302 static
David Turner34f1c2f2000-08-23 22:47:44 +0000303 FT_Error cid_parse_dict( CID_Face face,
304 CID_Loader* loader,
305 FT_Byte* base,
306 FT_Long size )
David Turner04aa8002000-06-01 03:27:48 +0000307 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000308 CID_Parser* parser = &loader->parser;
309
David Turner04aa8002000-06-01 03:27:48 +0000310
David Turner34f1c2f2000-08-23 22:47:44 +0000311 parser->root.cursor = base;
312 parser->root.limit = base + size;
313 parser->root.error = 0;
David Turner04aa8002000-06-01 03:27:48 +0000314
315 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000316 FT_Byte* cur = base;
317 FT_Byte* limit = cur + size;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000318
David Turner04aa8002000-06-01 03:27:48 +0000319
320 for ( ;cur < limit; cur++ )
321 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000322 /* look for `%ADOBeginFontDict' */
David Turner04aa8002000-06-01 03:27:48 +0000323 if ( *cur == '%' && cur + 20 < limit &&
324 strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
325 {
326 cur += 17;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000327
David Turner04aa8002000-06-01 03:27:48 +0000328 /* if /FDArray was found, then cid->num_dicts is > 0, and */
329 /* we can start increasing parser->num_dict */
330 if ( face->cid.num_dicts > 0 )
331 parser->num_dict++;
332 }
333 /* look for immediates */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000334 else if ( *cur == '/' && cur + 2 < limit )
David Turner04aa8002000-06-01 03:27:48 +0000335 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000336 FT_Byte* cur2;
337 FT_Int len;
David Turner04aa8002000-06-01 03:27:48 +0000338
Werner Lemberge3c11d72000-06-16 06:49:56 +0000339
340 cur++;
341
David Turner04aa8002000-06-01 03:27:48 +0000342 cur2 = cur;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000343 while ( cur2 < limit && is_alpha( *cur2 ) )
344 cur2++;
David Turner04aa8002000-06-01 03:27:48 +0000345
Werner Lemberge3c11d72000-06-16 06:49:56 +0000346 len = cur2 - cur;
347 if ( len > 0 && len < 22 )
David Turner04aa8002000-06-01 03:27:48 +0000348 {
Werner Lembergac39ecd2000-06-30 22:24:36 +0000349 /* now compare the immediate name to the keyword table */
David Turner34f1c2f2000-08-23 22:47:44 +0000350 const T1_Field* keyword = cid_field_records;
David Turner04aa8002000-06-01 03:27:48 +0000351
Werner Lemberge3c11d72000-06-16 06:49:56 +0000352
David Turner04aa8002000-06-01 03:27:48 +0000353 for (;;)
354 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000355 FT_Byte* name;
David Turner04aa8002000-06-01 03:27:48 +0000356
David Turner04aa8002000-06-01 03:27:48 +0000357
David Turnerf9b8dec2000-06-16 19:34:52 +0000358 name = (FT_Byte*)keyword->ident;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000359 if ( !name )
360 break;
361
362 if ( cur[0] == name[0] &&
David Turnerf9b8dec2000-06-16 19:34:52 +0000363 len == (FT_Int)strlen( (const char*)name ) )
David Turner04aa8002000-06-01 03:27:48 +0000364 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000365 FT_Int n;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000366
367
David Turner04aa8002000-06-01 03:27:48 +0000368 for ( n = 1; n < len; n++ )
Werner Lemberge3c11d72000-06-16 06:49:56 +0000369 if ( cur[n] != name[n] )
David Turner04aa8002000-06-01 03:27:48 +0000370 break;
371
Werner Lemberge3c11d72000-06-16 06:49:56 +0000372 if ( n >= len )
David Turner04aa8002000-06-01 03:27:48 +0000373 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000374 /* we found it - run the parsing callback */
David Turner34f1c2f2000-08-23 22:47:44 +0000375 parser->root.cursor = cur2;
376 CID_Skip_Spaces( parser );
Werner Lembergd1b74752000-08-24 16:29:15 +0000377 parser->root.error = cid_load_keyword( face,
378 loader,
379 keyword );
David Turner34f1c2f2000-08-23 22:47:44 +0000380 if ( parser->root.error )
381 return parser->root.error;
David Turner04aa8002000-06-01 03:27:48 +0000382
David Turner34f1c2f2000-08-23 22:47:44 +0000383 cur = parser->root.cursor;
David Turner04aa8002000-06-01 03:27:48 +0000384 break;
385 }
386 }
387 keyword++;
388 }
389 }
390 }
391 }
392 }
David Turner34f1c2f2000-08-23 22:47:44 +0000393 return parser->root.error;
David Turner04aa8002000-06-01 03:27:48 +0000394 }
395
396
David Turner04aa8002000-06-01 03:27:48 +0000397 /* read the subrmap and the subrs of each font dict */
398 static
David Turnerf9b8dec2000-06-16 19:34:52 +0000399 FT_Error cid_read_subrs( CID_Face face )
David Turner04aa8002000-06-01 03:27:48 +0000400 {
401 CID_Info* cid = &face->cid;
402 FT_Memory memory = face->root.memory;
403 FT_Stream stream = face->root.stream;
David Turnerf9b8dec2000-06-16 19:34:52 +0000404 FT_Error error;
David Turnera1be2dc2000-06-27 23:20:35 +0000405 FT_Int n;
David Turner04aa8002000-06-01 03:27:48 +0000406 CID_Subrs* subr;
David Turnerf9b8dec2000-06-16 19:34:52 +0000407 FT_UInt max_offsets = 0;
408 FT_ULong* offsets = 0;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000409
410
David Turner04aa8002000-06-01 03:27:48 +0000411 if ( ALLOC_ARRAY( face->subrs, cid->num_dicts, CID_Subrs ) )
412 goto Exit;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000413
David Turner04aa8002000-06-01 03:27:48 +0000414 subr = face->subrs;
415 for ( n = 0; n < cid->num_dicts; n++, subr++ )
416 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000417 CID_FontDict* dict = cid->font_dicts + n;
David Turnerf9b8dec2000-06-16 19:34:52 +0000418 FT_UInt count, num_subrs = dict->num_subrs;
419 FT_ULong data_len;
420 FT_Byte* p;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000421
422
David Turner04aa8002000-06-01 03:27:48 +0000423 /* reallocate offsets array if needed */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000424 if ( num_subrs + 1 > max_offsets )
David Turner04aa8002000-06-01 03:27:48 +0000425 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000426 FT_UInt new_max = ( num_subrs + 1 + 3 ) & -4;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000427
428
David Turnerf9b8dec2000-06-16 19:34:52 +0000429 if ( REALLOC_ARRAY( offsets, max_offsets, new_max, FT_ULong ) )
David Turner04aa8002000-06-01 03:27:48 +0000430 goto Fail;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000431
David Turner04aa8002000-06-01 03:27:48 +0000432 max_offsets = new_max;
433 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000434
David Turner04aa8002000-06-01 03:27:48 +0000435 /* read the subrmap's offsets */
436 if ( FILE_Seek( cid->data_offset + dict->subrmap_offset ) ||
Werner Lemberge3c11d72000-06-16 06:49:56 +0000437 ACCESS_Frame( ( num_subrs + 1 ) * dict->sd_bytes ) )
David Turner04aa8002000-06-01 03:27:48 +0000438 goto Fail;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000439
David Turner04aa8002000-06-01 03:27:48 +0000440 p = (FT_Byte*)stream->cursor;
441 for ( count = 0; count <= num_subrs; count++ )
David Turner81bb4ad2000-06-28 04:19:49 +0000442 offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000443
David Turner04aa8002000-06-01 03:27:48 +0000444 FORGET_Frame();
Werner Lemberge3c11d72000-06-16 06:49:56 +0000445
446 /* now, compute the size of subrs charstrings, */
447 /* allocate, and read them */
David Turner04aa8002000-06-01 03:27:48 +0000448 data_len = offsets[num_subrs] - offsets[0];
Werner Lemberge3c11d72000-06-16 06:49:56 +0000449
Werner Lembergac39ecd2000-06-30 22:24:36 +0000450 if ( ALLOC_ARRAY( subr->code, num_subrs + 1, FT_Byte* ) ||
451 ALLOC( subr->code[0], data_len ) )
David Turner04aa8002000-06-01 03:27:48 +0000452 goto Fail;
453
454 if ( FILE_Seek( cid->data_offset + offsets[0] ) ||
455 FILE_Read( subr->code[0], data_len ) )
456 goto Exit;
457
458 /* set up pointers */
459 for ( count = 1; count <= num_subrs; count++ )
460 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000461 FT_UInt len;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000462
463
464 len = offsets[count] - offsets[count - 1];
465 subr->code[count] = subr->code[count - 1] + len;
David Turner04aa8002000-06-01 03:27:48 +0000466 }
467
Werner Lemberge3c11d72000-06-16 06:49:56 +0000468 /* decrypt subroutines */
David Turner04aa8002000-06-01 03:27:48 +0000469 for ( count = 0; count < num_subrs; count++ )
470 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000471 FT_UInt len;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000472
473
474 len = offsets[count + 1] - offsets[count];
David Turner04aa8002000-06-01 03:27:48 +0000475 cid_decrypt( subr->code[count], len, 4330 );
476 }
477
478 subr->num_subrs = num_subrs;
479 }
480
481 Exit:
482 FREE( offsets );
483 return error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000484
David Turner04aa8002000-06-01 03:27:48 +0000485 Fail:
Werner Lemberge3c11d72000-06-16 06:49:56 +0000486 if ( face->subrs )
David Turner04aa8002000-06-01 03:27:48 +0000487 {
488 for ( n = 0; n < cid->num_dicts; n++ )
489 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000490 if ( face->subrs[n].code )
David Turner04aa8002000-06-01 03:27:48 +0000491 FREE( face->subrs[n].code[0] );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000492
David Turner04aa8002000-06-01 03:27:48 +0000493 FREE( face->subrs[n].code );
494 }
495 FREE( face->subrs );
496 }
497 goto Exit;
498 }
499
Werner Lemberge3c11d72000-06-16 06:49:56 +0000500
David Turner04aa8002000-06-01 03:27:48 +0000501 static
Werner Lemberge3c11d72000-06-16 06:49:56 +0000502 void t1_init_loader( CID_Loader* loader,
503 CID_Face face )
David Turner04aa8002000-06-01 03:27:48 +0000504 {
David Turnerc6a92202000-07-04 18:12:13 +0000505 FT_UNUSED( face );
David Turner04aa8002000-06-01 03:27:48 +0000506
Werner Lemberge3c11d72000-06-16 06:49:56 +0000507 MEM_Set( loader, 0, sizeof ( *loader ) );
David Turner04aa8002000-06-01 03:27:48 +0000508 }
509
Werner Lemberge3c11d72000-06-16 06:49:56 +0000510
David Turner04aa8002000-06-01 03:27:48 +0000511 static
Werner Lemberge3c11d72000-06-16 06:49:56 +0000512 void t1_done_loader( CID_Loader* loader )
David Turner04aa8002000-06-01 03:27:48 +0000513 {
514 CID_Parser* parser = &loader->parser;
515
Werner Lemberge3c11d72000-06-16 06:49:56 +0000516
David Turner04aa8002000-06-01 03:27:48 +0000517 /* finalize parser */
518 CID_Done_Parser( parser );
519 }
520
Werner Lemberge3c11d72000-06-16 06:49:56 +0000521
David Turner04aa8002000-06-01 03:27:48 +0000522 LOCAL_FUNC
David Turnerf9b8dec2000-06-16 19:34:52 +0000523 FT_Error CID_Open_Face( CID_Face face )
David Turner04aa8002000-06-01 03:27:48 +0000524 {
525 CID_Loader loader;
526 CID_Parser* parser;
David Turnerf9b8dec2000-06-16 19:34:52 +0000527 FT_Error error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000528
David Turner04aa8002000-06-01 03:27:48 +0000529
530 t1_init_loader( &loader, face );
531
532 parser = &loader.parser;
David Turner34f1c2f2000-08-23 22:47:44 +0000533 error = CID_New_Parser( parser, face->root.stream, face->root.memory,
534 (PSAux_Interface*)face->psaux );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000535 if ( error )
536 goto Exit;
David Turner04aa8002000-06-01 03:27:48 +0000537
David Turner34f1c2f2000-08-23 22:47:44 +0000538 error = cid_parse_dict( face, &loader,
539 parser->postscript,
540 parser->postscript_len );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000541 if ( error )
542 goto Exit;
David Turner04aa8002000-06-01 03:27:48 +0000543
544 face->cid.data_offset = loader.parser.data_offset;
545 error = cid_read_subrs( face );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000546
David Turner04aa8002000-06-01 03:27:48 +0000547 Exit:
548 t1_done_loader( &loader );
549 return error;
550 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000551
552
553/* END */