blob: 8d96ea6ee46af29f7a5fe37c6105e6ea03a19851 [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 Lemberg22ad9ef2005-05-09 22:11:36 +00007/* Copyright 1996-2001, 2002, 2003, 2004, 2005 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 Lemberge3c11d72000-06-16 06:49:56 +000029
30 /*************************************************************************/
31 /* */
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. */
35 /* */
David Turner04aa8002000-06-01 03:27:48 +000036#undef FT_COMPONENT
Werner Lemberge3c11d72000-06-16 06:49:56 +000037#define FT_COMPONENT trace_cidload
David Turner04aa8002000-06-01 03:27:48 +000038
Werner Lemberge3c11d72000-06-16 06:49:56 +000039
Werner Lembergac39ecd2000-06-30 22:24:36 +000040 /* read a single offset */
David Turnerbc82f1b2002-03-01 02:26:22 +000041 FT_LOCAL_DEF( FT_Long )
Werner Lemberg52f911a2003-10-07 05:49:41 +000042 cid_get_offset( FT_Byte* *start,
Werner Lemberg93616ec2001-06-27 19:46:12 +000043 FT_Byte offsize )
David Turner04aa8002000-06-01 03:27:48 +000044 {
David Turnerf9b8dec2000-06-16 19:34:52 +000045 FT_Long result;
46 FT_Byte* p = *start;
Werner Lemberge3c11d72000-06-16 06:49:56 +000047
48
David Turner04aa8002000-06-01 03:27:48 +000049 for ( result = 0; offsize > 0; offsize-- )
Werner Lembergac39ecd2000-06-30 22:24:36 +000050 {
51 result <<= 8;
52 result |= *p++;
53 }
Werner Lemberge3c11d72000-06-16 06:49:56 +000054
David Turner04aa8002000-06-01 03:27:48 +000055 *start = p;
56 return result;
57 }
58
59
Werner Lemberge3c11d72000-06-16 06:49:56 +000060 /*************************************************************************/
61 /*************************************************************************/
62 /***** *****/
63 /***** TYPE 1 SYMBOL PARSING *****/
64 /***** *****/
65 /*************************************************************************/
66 /*************************************************************************/
David Turner04aa8002000-06-01 03:27:48 +000067
68
Werner Lemberg93616ec2001-06-27 19:46:12 +000069 static FT_Error
Werner Lemberg44be4d52002-03-30 17:08:04 +000070 cid_load_keyword( CID_Face face,
71 CID_Loader* loader,
David Turner4e7eeee2002-02-28 16:10:29 +000072 const T1_Field keyword )
David Turner04aa8002000-06-01 03:27:48 +000073 {
Werner Lemberg44be4d52002-03-30 17:08:04 +000074 FT_Error error;
75 CID_Parser* parser = &loader->parser;
76 FT_Byte* object;
77 void* dummy_object;
78 CID_FaceInfo cid = &face->cid;
David Turner04aa8002000-06-01 03:27:48 +000079
Werner Lemberge3c11d72000-06-16 06:49:56 +000080
David Turner04aa8002000-06-01 03:27:48 +000081 /* if the keyword has a dedicated callback, call it */
David Turner4e7eeee2002-02-28 16:10:29 +000082 if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
David Turner04aa8002000-06-01 03:27:48 +000083 {
David Turner34f1c2f2000-08-23 22:47:44 +000084 keyword->reader( (FT_Face)face, parser );
85 error = parser->root.error;
David Turner04aa8002000-06-01 03:27:48 +000086 goto Exit;
87 }
88
89 /* we must now compute the address of our target object */
Werner Lemberge3c11d72000-06-16 06:49:56 +000090 switch ( keyword->location )
David Turner04aa8002000-06-01 03:27:48 +000091 {
David Turner429978b2002-03-14 10:09:35 +000092 case T1_FIELD_LOCATION_CID_INFO:
David Turnerf9b8dec2000-06-16 19:34:52 +000093 object = (FT_Byte*)cid;
Werner Lemberge3c11d72000-06-16 06:49:56 +000094 break;
95
David Turner429978b2002-03-14 10:09:35 +000096 case T1_FIELD_LOCATION_FONT_INFO:
David Turnerf9b8dec2000-06-16 19:34:52 +000097 object = (FT_Byte*)&cid->font_info;
Werner Lemberge3c11d72000-06-16 06:49:56 +000098 break;
99
Werner Lembergfdc042b2003-06-12 04:59:07 +0000100 case T1_FIELD_LOCATION_BBOX:
101 object = (FT_Byte*)&cid->font_bbox;
102 break;
103
Werner Lemberge3c11d72000-06-16 06:49:56 +0000104 default:
105 {
David Turner29644172002-02-28 18:59:37 +0000106 CID_FaceDict dict;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000107
108
109 if ( parser->num_dict < 0 )
David Turner04aa8002000-06-01 03:27:48 +0000110 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000111 FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
112 keyword->ident ));
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000113 error = CID_Err_Syntax_Error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000114 goto Exit;
David Turner04aa8002000-06-01 03:27:48 +0000115 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000116
117 dict = cid->font_dicts + parser->num_dict;
118 switch ( keyword->location )
119 {
David Turner429978b2002-03-14 10:09:35 +0000120 case T1_FIELD_LOCATION_PRIVATE:
David Turnerf9b8dec2000-06-16 19:34:52 +0000121 object = (FT_Byte*)&dict->private_dict;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000122 break;
123
124 default:
David Turnerf9b8dec2000-06-16 19:34:52 +0000125 object = (FT_Byte*)dict;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000126 }
127 }
David Turner04aa8002000-06-01 03:27:48 +0000128 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000129
David Turner34f1c2f2000-08-23 22:47:44 +0000130 dummy_object = object;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000131
David Turner04aa8002000-06-01 03:27:48 +0000132 /* now, load the keyword data in the object's field(s) */
David Turner4e7eeee2002-02-28 16:10:29 +0000133 if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
134 keyword->type == T1_FIELD_TYPE_FIXED_ARRAY )
David Turnerb08fe2d2002-08-27 20:20:29 +0000135 error = cid_parser_load_field_table( &loader->parser, keyword,
Werner Lembergbf7c8322003-06-06 05:07:53 +0000136 &dummy_object );
David Turner04aa8002000-06-01 03:27:48 +0000137 else
Werner Lembergbf7c8322003-06-06 05:07:53 +0000138 error = cid_parser_load_field( &loader->parser,
139 keyword, &dummy_object );
David Turner04aa8002000-06-01 03:27:48 +0000140 Exit:
141 return error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000142 }
David Turner04aa8002000-06-01 03:27:48 +0000143
144
Werner Lemberg93616ec2001-06-27 19:46:12 +0000145 FT_CALLBACK_DEF( FT_Error )
David Turnerdee78132001-06-27 09:26:46 +0000146 parse_font_matrix( CID_Face face,
147 CID_Parser* parser )
David Turner04aa8002000-06-01 03:27:48 +0000148 {
Werner Lemberg44be4d52002-03-30 17:08:04 +0000149 FT_Matrix* matrix;
150 FT_Vector* offset;
David Turner29644172002-02-28 18:59:37 +0000151 CID_FaceDict dict;
Werner Lemberg44be4d52002-03-30 17:08:04 +0000152 FT_Face root = (FT_Face)&face->root;
153 FT_Fixed temp[6];
154 FT_Fixed temp_scale;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000155
Werner Lemberg29bac132001-03-11 11:28:39 +0000156
Werner Lemberge3c11d72000-06-16 06:49:56 +0000157 if ( parser->num_dict >= 0 )
David Turner04aa8002000-06-01 03:27:48 +0000158 {
159 dict = face->cid.font_dicts + parser->num_dict;
160 matrix = &dict->font_matrix;
David Turner34f1c2f2000-08-23 22:47:44 +0000161 offset = &dict->font_offset;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000162
David Turnerb08fe2d2002-08-27 20:20:29 +0000163 (void)cid_parser_to_fixed_array( parser, 6, temp, 3 );
David Turner34f1c2f2000-08-23 22:47:44 +0000164
Werner Lembergdfa46192004-03-05 09:26:24 +0000165 temp_scale = FT_ABS( temp[3] );
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000166
Werner Lemberg52f911a2003-10-07 05:49:41 +0000167 /* Set units per EM based on FontMatrix values. We set the value to */
Werner Lemberg29bac132001-03-11 11:28:39 +0000168 /* `1000/temp_scale', because temp_scale was already multiplied by */
Werner Lemberg52f911a2003-10-07 05:49:41 +0000169 /* 1000 (in `t1_tofixed', from psobjs.c). */
David Turner37981102001-03-19 11:34:49 +0000170 root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,
David Turner09d55ce2001-05-11 18:08:58 +0000171 FT_DivFix( temp_scale, 1000 ) ) );
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000172
David Turner34f1c2f2000-08-23 22:47:44 +0000173 /* we need to scale the values by 1.0/temp[3] */
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000174 if ( temp_scale != 0x10000L )
David Turner34f1c2f2000-08-23 22:47:44 +0000175 {
Tom Kacvinsky025c2f32001-03-10 19:04:41 +0000176 temp[0] = FT_DivFix( temp[0], temp_scale );
177 temp[1] = FT_DivFix( temp[1], temp_scale );
178 temp[2] = FT_DivFix( temp[2], temp_scale );
179 temp[4] = FT_DivFix( temp[4], temp_scale );
180 temp[5] = FT_DivFix( temp[5], temp_scale );
David Turner34f1c2f2000-08-23 22:47:44 +0000181 temp[3] = 0x10000L;
182 }
183
David Turner04aa8002000-06-01 03:27:48 +0000184 matrix->xx = temp[0];
185 matrix->yx = temp[1];
186 matrix->xy = temp[2];
187 matrix->yy = temp[3];
Werner Lemberge4b32a52000-10-31 20:42:18 +0000188
Werner Lemberg6fbe4db2000-10-05 04:53:31 +0000189 /* note that the font offsets are expressed in integer font units */
David Turnerf00a4de2000-10-03 22:03:09 +0000190 offset->x = temp[4] >> 16;
191 offset->y = temp[5] >> 16;
David Turner04aa8002000-06-01 03:27:48 +0000192 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000193
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000194 return CID_Err_Ok; /* this is a callback function; */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000195 /* we must return an error code */
David Turner04aa8002000-06-01 03:27:48 +0000196 }
197
Werner Lemberge3c11d72000-06-16 06:49:56 +0000198
Werner Lemberg93616ec2001-06-27 19:46:12 +0000199 FT_CALLBACK_DEF( FT_Error )
David Turnerdee78132001-06-27 09:26:46 +0000200 parse_fd_array( CID_Face face,
201 CID_Parser* parser )
David Turner04aa8002000-06-01 03:27:48 +0000202 {
David Turner29644172002-02-28 18:59:37 +0000203 CID_FaceInfo cid = &face->cid;
Werner Lemberg44be4d52002-03-30 17:08:04 +0000204 FT_Memory memory = face->root.memory;
205 FT_Error error = CID_Err_Ok;
206 FT_Long num_dicts;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000207
208
David Turnerb08fe2d2002-08-27 20:20:29 +0000209 num_dicts = cid_parser_to_int( parser );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000210
David Turner04aa8002000-06-01 03:27:48 +0000211 if ( !cid->font_dicts )
212 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000213 FT_Int n;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000214
215
David Turnere459d742002-03-22 13:52:37 +0000216 if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
David Turner04aa8002000-06-01 03:27:48 +0000217 goto Exit;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000218
David Turnerf9b8dec2000-06-16 19:34:52 +0000219 cid->num_dicts = (FT_UInt)num_dicts;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000220
221 /* don't forget to set a few defaults */
David Turner04aa8002000-06-01 03:27:48 +0000222 for ( n = 0; n < cid->num_dicts; n++ )
223 {
David Turner29644172002-02-28 18:59:37 +0000224 CID_FaceDict dict = cid->font_dicts + n;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000225
226
227 /* default value for lenIV */
David Turner04aa8002000-06-01 03:27:48 +0000228 dict->private_dict.lenIV = 4;
229 }
230 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000231
David Turner04aa8002000-06-01 03:27:48 +0000232 Exit:
233 return error;
234 }
235
236
David Turner04aa8002000-06-01 03:27:48 +0000237 static
David Turner4e7eeee2002-02-28 16:10:29 +0000238 const T1_FieldRec cid_field_records[] =
David Turner04aa8002000-06-01 03:27:48 +0000239 {
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000240
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000241#include "cidtoken.h"
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000242
Werner Lemberga959c3c2003-06-14 07:40:09 +0000243 T1_FIELD_CALLBACK( "FDArray", parse_fd_array )
David Turner34f1c2f2000-08-23 22:47:44 +0000244 T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
Werner Lembergfdc042b2003-06-12 04:59:07 +0000245
David Turner429978b2002-03-14 10:09:35 +0000246 { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
David Turner04aa8002000-06-01 03:27:48 +0000247 };
248
249
Werner Lemberg93616ec2001-06-27 19:46:12 +0000250 static FT_Error
251 cid_parse_dict( CID_Face face,
252 CID_Loader* loader,
253 FT_Byte* base,
254 FT_Long size )
David Turner04aa8002000-06-01 03:27:48 +0000255 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000256 CID_Parser* parser = &loader->parser;
257
David Turner04aa8002000-06-01 03:27:48 +0000258
David Turner34f1c2f2000-08-23 22:47:44 +0000259 parser->root.cursor = base;
260 parser->root.limit = base + size;
Werner Lemberg52f911a2003-10-07 05:49:41 +0000261 parser->root.error = CID_Err_Ok;
David Turner04aa8002000-06-01 03:27:48 +0000262
263 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000264 FT_Byte* cur = base;
265 FT_Byte* limit = cur + size;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000266
David Turner04aa8002000-06-01 03:27:48 +0000267
Werner Lemberg52f911a2003-10-07 05:49:41 +0000268 for (;;)
David Turner04aa8002000-06-01 03:27:48 +0000269 {
Werner Lemberg52f911a2003-10-07 05:49:41 +0000270 FT_Byte* newlimit;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000271
Werner Lemberg52f911a2003-10-07 05:49:41 +0000272
273 parser->root.cursor = cur;
274 cid_parser_skip_spaces( parser );
275
276 if ( parser->root.cursor >= limit )
277 newlimit = limit - 1 - 17;
278 else
279 newlimit = parser->root.cursor - 17;
280
281 /* look for `%ADOBeginFontDict' */
282 for ( ; cur < newlimit; cur++ )
283 {
284 if ( *cur == '%' &&
285 ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
286 {
287 /* if /FDArray was found, then cid->num_dicts is > 0, and */
288 /* we can start increasing parser->num_dict */
289 if ( face->cid.num_dicts > 0 )
290 parser->num_dict++;
291 }
David Turner04aa8002000-06-01 03:27:48 +0000292 }
Werner Lemberg52f911a2003-10-07 05:49:41 +0000293
294 cur = parser->root.cursor;
295 /* no error can occur in cid_parser_skip_spaces */
296 if ( cur >= limit )
297 break;
298
299 cid_parser_skip_PS_token( parser );
300 if ( parser->root.cursor >= limit || parser->root.error )
301 break;
302
David Turner04aa8002000-06-01 03:27:48 +0000303 /* look for immediates */
Werner Lemberg52f911a2003-10-07 05:49:41 +0000304 if ( *cur == '/' && cur + 2 < limit )
David Turner04aa8002000-06-01 03:27:48 +0000305 {
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000306 FT_PtrDist len;
David Turner04aa8002000-06-01 03:27:48 +0000307
Werner Lemberge3c11d72000-06-16 06:49:56 +0000308
309 cur++;
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000310 len = parser->root.cursor - cur;
Werner Lemberg52f911a2003-10-07 05:49:41 +0000311
Werner Lemberge3c11d72000-06-16 06:49:56 +0000312 if ( len > 0 && len < 22 )
David Turner04aa8002000-06-01 03:27:48 +0000313 {
Werner Lembergac39ecd2000-06-30 22:24:36 +0000314 /* now compare the immediate name to the keyword table */
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000315 T1_Field keyword = (T1_Field)cid_field_records;
David Turner04aa8002000-06-01 03:27:48 +0000316
Werner Lemberge3c11d72000-06-16 06:49:56 +0000317
David Turner04aa8002000-06-01 03:27:48 +0000318 for (;;)
319 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000320 FT_Byte* name;
David Turner04aa8002000-06-01 03:27:48 +0000321
David Turner04aa8002000-06-01 03:27:48 +0000322
David Turnerf9b8dec2000-06-16 19:34:52 +0000323 name = (FT_Byte*)keyword->ident;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000324 if ( !name )
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000325 break;
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000326
Werner Lemberg023a4bf2004-10-14 11:33:04 +0000327 if ( cur[0] == name[0] &&
328 len == (FT_PtrDist)ft_strlen( (const char*)name ) )
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000329 {
330 FT_PtrDist n;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000331
332
David Turner04aa8002000-06-01 03:27:48 +0000333 for ( n = 1; n < len; n++ )
Werner Lemberge3c11d72000-06-16 06:49:56 +0000334 if ( cur[n] != name[n] )
David Turner04aa8002000-06-01 03:27:48 +0000335 break;
336
Werner Lemberge3c11d72000-06-16 06:49:56 +0000337 if ( n >= len )
David Turner04aa8002000-06-01 03:27:48 +0000338 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000339 /* we found it - run the parsing callback */
Werner Lembergd1b74752000-08-24 16:29:15 +0000340 parser->root.error = cid_load_keyword( face,
341 loader,
342 keyword );
David Turner34f1c2f2000-08-23 22:47:44 +0000343 if ( parser->root.error )
344 return parser->root.error;
David Turner04aa8002000-06-01 03:27:48 +0000345 break;
346 }
347 }
348 keyword++;
349 }
350 }
351 }
Werner Lemberg52f911a2003-10-07 05:49:41 +0000352
353 cur = parser->root.cursor;
David Turner04aa8002000-06-01 03:27:48 +0000354 }
355 }
David Turner34f1c2f2000-08-23 22:47:44 +0000356 return parser->root.error;
David Turner04aa8002000-06-01 03:27:48 +0000357 }
358
359
David Turner04aa8002000-06-01 03:27:48 +0000360 /* read the subrmap and the subrs of each font dict */
Werner Lemberg93616ec2001-06-27 19:46:12 +0000361 static FT_Error
362 cid_read_subrs( CID_Face face )
David Turner04aa8002000-06-01 03:27:48 +0000363 {
Werner Lemberg75aae7d2003-06-12 07:11:05 +0000364 CID_FaceInfo cid = &face->cid;
365 FT_Memory memory = face->root.memory;
Werner Lembergef512e32004-01-23 19:52:40 +0000366 FT_Stream stream = face->cid_stream;
Werner Lemberg75aae7d2003-06-12 07:11:05 +0000367 FT_Error error;
368 FT_Int n;
369 CID_Subrs subr;
370 FT_UInt max_offsets = 0;
371 FT_ULong* offsets = 0;
372 PSAux_Service psaux = (PSAux_Service)face->psaux;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000373
374
David Turnere459d742002-03-22 13:52:37 +0000375 if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )
David Turner04aa8002000-06-01 03:27:48 +0000376 goto Exit;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000377
David Turner04aa8002000-06-01 03:27:48 +0000378 subr = face->subrs;
379 for ( n = 0; n < cid->num_dicts; n++, subr++ )
380 {
David Turner29644172002-02-28 18:59:37 +0000381 CID_FaceDict dict = cid->font_dicts + n;
Werner Lemberg44be4d52002-03-30 17:08:04 +0000382 FT_Int lenIV = dict->private_dict.lenIV;
383 FT_UInt count, num_subrs = dict->num_subrs;
384 FT_ULong data_len;
385 FT_Byte* p;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000386
387
David Turner04aa8002000-06-01 03:27:48 +0000388 /* reallocate offsets array if needed */
Werner Lemberge3c11d72000-06-16 06:49:56 +0000389 if ( num_subrs + 1 > max_offsets )
David Turner04aa8002000-06-01 03:27:48 +0000390 {
David Turner87c0d302003-12-24 01:10:46 +0000391 FT_UInt new_max = FT_PAD_CEIL( num_subrs + 1, 4 );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000392
393
David Turnere459d742002-03-22 13:52:37 +0000394 if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )
David Turner04aa8002000-06-01 03:27:48 +0000395 goto Fail;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000396
David Turner04aa8002000-06-01 03:27:48 +0000397 max_offsets = new_max;
398 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000399
David Turner04aa8002000-06-01 03:27:48 +0000400 /* read the subrmap's offsets */
David Turner7d3a2642002-03-20 10:49:31 +0000401 if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||
Werner Lembergef512e32004-01-23 19:52:40 +0000402 FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes ) )
David Turner04aa8002000-06-01 03:27:48 +0000403 goto Fail;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000404
David Turner04aa8002000-06-01 03:27:48 +0000405 p = (FT_Byte*)stream->cursor;
406 for ( count = 0; count <= num_subrs; count++ )
David Turner81bb4ad2000-06-28 04:19:49 +0000407 offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000408
David Turner7d3a2642002-03-20 10:49:31 +0000409 FT_FRAME_EXIT();
Werner Lemberge3c11d72000-06-16 06:49:56 +0000410
411 /* now, compute the size of subrs charstrings, */
412 /* allocate, and read them */
David Turner04aa8002000-06-01 03:27:48 +0000413 data_len = offsets[num_subrs] - offsets[0];
Werner Lemberge3c11d72000-06-16 06:49:56 +0000414
David Turnere459d742002-03-22 13:52:37 +0000415 if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||
416 FT_ALLOC( subr->code[0], data_len ) )
David Turner04aa8002000-06-01 03:27:48 +0000417 goto Fail;
418
David Turner7d3a2642002-03-20 10:49:31 +0000419 if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
420 FT_STREAM_READ( subr->code[0], data_len ) )
David Turner3a664fc2001-12-21 15:26:19 +0000421 goto Fail;
David Turner04aa8002000-06-01 03:27:48 +0000422
423 /* set up pointers */
424 for ( count = 1; count <= num_subrs; count++ )
425 {
Werner Lemberg68e9f922002-09-27 11:09:23 +0000426 FT_ULong len;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000427
428
429 len = offsets[count] - offsets[count - 1];
430 subr->code[count] = subr->code[count - 1] + len;
David Turner04aa8002000-06-01 03:27:48 +0000431 }
432
Werner Lemberg9a8b5362001-03-12 22:33:52 +0000433 /* decrypt subroutines, but only if lenIV >= 0 */
Tom Kacvinsky68621132001-03-12 02:17:50 +0000434 if ( lenIV >= 0 )
David Turner04aa8002000-06-01 03:27:48 +0000435 {
Tom Kacvinsky68621132001-03-12 02:17:50 +0000436 for ( count = 0; count < num_subrs; count++ )
437 {
Werner Lemberg68e9f922002-09-27 11:09:23 +0000438 FT_ULong len;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000439
440
Tom Kacvinsky68621132001-03-12 02:17:50 +0000441 len = offsets[count + 1] - offsets[count];
Werner Lemberg75aae7d2003-06-12 07:11:05 +0000442 psaux->t1_decrypt( subr->code[count], len, 4330 );
Tom Kacvinsky68621132001-03-12 02:17:50 +0000443 }
David Turner04aa8002000-06-01 03:27:48 +0000444 }
445
446 subr->num_subrs = num_subrs;
447 }
448
449 Exit:
David Turnere459d742002-03-22 13:52:37 +0000450 FT_FREE( offsets );
David Turner04aa8002000-06-01 03:27:48 +0000451 return error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000452
David Turner04aa8002000-06-01 03:27:48 +0000453 Fail:
Werner Lemberge3c11d72000-06-16 06:49:56 +0000454 if ( face->subrs )
David Turner04aa8002000-06-01 03:27:48 +0000455 {
456 for ( n = 0; n < cid->num_dicts; n++ )
457 {
Werner Lemberge3c11d72000-06-16 06:49:56 +0000458 if ( face->subrs[n].code )
David Turnere459d742002-03-22 13:52:37 +0000459 FT_FREE( face->subrs[n].code[0] );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000460
David Turnere459d742002-03-22 13:52:37 +0000461 FT_FREE( face->subrs[n].code );
David Turner04aa8002000-06-01 03:27:48 +0000462 }
David Turnere459d742002-03-22 13:52:37 +0000463 FT_FREE( face->subrs );
David Turner04aa8002000-06-01 03:27:48 +0000464 }
465 goto Exit;
466 }
467
Werner Lemberge3c11d72000-06-16 06:49:56 +0000468
Werner Lemberg93616ec2001-06-27 19:46:12 +0000469 static void
470 t1_init_loader( CID_Loader* loader,
471 CID_Face face )
David Turner04aa8002000-06-01 03:27:48 +0000472 {
David Turnerc6a92202000-07-04 18:12:13 +0000473 FT_UNUSED( face );
David Turner04aa8002000-06-01 03:27:48 +0000474
Werner Lembergb3d5e9c2002-07-28 05:05:24 +0000475 FT_MEM_ZERO( loader, sizeof ( *loader ) );
David Turner04aa8002000-06-01 03:27:48 +0000476 }
477
Werner Lemberge3c11d72000-06-16 06:49:56 +0000478
Werner Lemberg93616ec2001-06-27 19:46:12 +0000479 static void
480 t1_done_loader( CID_Loader* loader )
David Turner04aa8002000-06-01 03:27:48 +0000481 {
482 CID_Parser* parser = &loader->parser;
483
Werner Lemberge3c11d72000-06-16 06:49:56 +0000484
David Turner04aa8002000-06-01 03:27:48 +0000485 /* finalize parser */
David Turnerb08fe2d2002-08-27 20:20:29 +0000486 cid_parser_done( parser );
David Turner04aa8002000-06-01 03:27:48 +0000487 }
488
Werner Lemberge3c11d72000-06-16 06:49:56 +0000489
Werner Lembergef512e32004-01-23 19:52:40 +0000490 static FT_Error
491 cid_hex_to_binary( FT_Byte* data,
492 FT_Long data_len,
493 FT_ULong offset,
494 CID_Face face )
495 {
496 FT_Stream stream = face->root.stream;
497 FT_Error error;
498
499 FT_Byte buffer[256];
500 FT_Byte *p, *plimit;
501 FT_Byte *d, *dlimit;
502 FT_Byte val;
503
504 FT_Bool upper_nibble, done;
505
506
507 if ( FT_STREAM_SEEK( offset ) )
508 goto Exit;
509
510 d = data;
511 dlimit = d + data_len;
512 p = buffer;
513 plimit = p;
514
515 upper_nibble = 1;
516 done = 0;
517
518 while ( d < dlimit )
519 {
520 if ( p >= plimit )
521 {
522 FT_ULong oldpos = FT_STREAM_POS();
523 FT_ULong size = stream->size - oldpos;
524
525
526 if ( size == 0 )
527 {
528 error = CID_Err_Syntax_Error;
529 goto Exit;
530 }
531
532 if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) )
533 goto Exit;
534 p = buffer;
535 plimit = p + FT_STREAM_POS() - oldpos;
536 }
537
538 if ( ft_isdigit( *p ) )
Werner Lemberg22ad9ef2005-05-09 22:11:36 +0000539 val = (FT_Byte)( *p - '0' );
Werner Lembergef512e32004-01-23 19:52:40 +0000540 else if ( *p >= 'a' && *p <= 'f' )
Werner Lemberg22ad9ef2005-05-09 22:11:36 +0000541 val = (FT_Byte)( *p - 'a' );
Werner Lembergef512e32004-01-23 19:52:40 +0000542 else if ( *p >= 'A' && *p <= 'F' )
Werner Lemberg22ad9ef2005-05-09 22:11:36 +0000543 val = (FT_Byte)( *p - 'A' + 10 );
Werner Lembergef512e32004-01-23 19:52:40 +0000544 else if ( *p == ' ' ||
545 *p == '\t' ||
546 *p == '\r' ||
547 *p == '\n' ||
548 *p == '\f' ||
549 *p == '\0' )
550 {
551 p++;
552 continue;
553 }
554 else if ( *p == '>' )
555 {
556 val = 0;
557 done = 1;
558 }
559 else
560 {
561 error = CID_Err_Syntax_Error;
562 goto Exit;
563 }
564
565 if ( upper_nibble )
Werner Lemberg22ad9ef2005-05-09 22:11:36 +0000566 *d = (FT_Byte)( val << 4 );
Werner Lembergef512e32004-01-23 19:52:40 +0000567 else
568 {
Werner Lemberg22ad9ef2005-05-09 22:11:36 +0000569 *d = (FT_Byte)( *d + val );
Werner Lembergef512e32004-01-23 19:52:40 +0000570 d++;
571 }
572
Werner Lemberg22ad9ef2005-05-09 22:11:36 +0000573 upper_nibble = (FT_Byte)( 1 - upper_nibble );
Werner Lembergef512e32004-01-23 19:52:40 +0000574
575 if ( done )
576 break;
577
578 p++;
579 }
580
581 error = CID_Err_Ok;
582
583 Exit:
584 return error;
585 }
586
587
David Turnerbc82f1b2002-03-01 02:26:22 +0000588 FT_LOCAL_DEF( FT_Error )
Werner Lembergef512e32004-01-23 19:52:40 +0000589 cid_face_open( CID_Face face,
590 FT_Int face_index )
David Turner04aa8002000-06-01 03:27:48 +0000591 {
Werner Lemberg44be4d52002-03-30 17:08:04 +0000592 CID_Loader loader;
593 CID_Parser* parser;
Werner Lembergef512e32004-01-23 19:52:40 +0000594 FT_Memory memory = face->root.memory;
Werner Lemberg44be4d52002-03-30 17:08:04 +0000595 FT_Error error;
Werner Lemberge3c11d72000-06-16 06:49:56 +0000596
David Turner04aa8002000-06-01 03:27:48 +0000597
598 t1_init_loader( &loader, face );
599
600 parser = &loader.parser;
David Turnerb08fe2d2002-08-27 20:20:29 +0000601 error = cid_parser_new( parser, face->root.stream, face->root.memory,
David Turner4e7eeee2002-02-28 16:10:29 +0000602 (PSAux_Service)face->psaux );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000603 if ( error )
604 goto Exit;
David Turner04aa8002000-06-01 03:27:48 +0000605
David Turner34f1c2f2000-08-23 22:47:44 +0000606 error = cid_parse_dict( face, &loader,
607 parser->postscript,
608 parser->postscript_len );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000609 if ( error )
610 goto Exit;
David Turner04aa8002000-06-01 03:27:48 +0000611
Werner Lembergef512e32004-01-23 19:52:40 +0000612 if ( face_index < 0 )
613 goto Exit;
614
Werner Lemberg95867072004-02-12 08:33:20 +0000615 if ( FT_NEW( face->cid_stream ) )
616 goto Exit;
617
Werner Lembergef512e32004-01-23 19:52:40 +0000618 if ( parser->binary_length )
619 {
620 /* we must convert the data section from hexadecimal to binary */
621 if ( FT_ALLOC( face->binary_data, parser->binary_length ) ||
622 cid_hex_to_binary( face->binary_data, parser->binary_length,
623 parser->data_offset, face ) )
624 goto Exit;
625
Werner Lembergef512e32004-01-23 19:52:40 +0000626 FT_Stream_OpenMemory( face->cid_stream,
627 face->binary_data, parser->binary_length );
628 face->cid.data_offset = 0;
629 }
630 else
631 {
Werner Lemberg95867072004-02-12 08:33:20 +0000632 *face->cid_stream = *face->root.stream;
Werner Lembergef512e32004-01-23 19:52:40 +0000633 face->cid.data_offset = loader.parser.data_offset;
634 }
635
David Turner04aa8002000-06-01 03:27:48 +0000636 error = cid_read_subrs( face );
Werner Lemberge3c11d72000-06-16 06:49:56 +0000637
David Turner04aa8002000-06-01 03:27:48 +0000638 Exit:
639 t1_done_loader( &loader );
640 return error;
641 }
Werner Lemberge3c11d72000-06-16 06:49:56 +0000642
643
644/* END */