]> git.saurik.com Git - wxWidgets.git/blob - src/freetype/cid/cidload.c
Fixed Cygwin crash on toolbar tooltip
[wxWidgets.git] / src / freetype / cid / cidload.c
1 /***************************************************************************/
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
18
19 #include <freetype/internal/ftdebug.h>
20 #include <freetype/config/ftconfig.h>
21 #include <freetype/ftmm.h>
22
23 #include <freetype/internal/t1types.h>
24 #include <freetype/internal/t1errors.h>
25
26
27 #ifdef FT_FLAT_COMPILE
28
29 #include "cidload.h"
30
31 #else
32
33 #include <cid/cidload.h>
34
35 #endif
36
37
38 #include <stdio.h>
39 #include <ctype.h> /* for isspace(), isalnum() */
40
41
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 /* */
48 #undef FT_COMPONENT
49 #define FT_COMPONENT trace_cidload
50
51
52 /* read a single offset */
53 LOCAL_FUNC
54 FT_Long cid_get_offset( FT_Byte** start,
55 FT_Byte offsize )
56 {
57 FT_Long result;
58 FT_Byte* p = *start;
59
60
61 for ( result = 0; offsize > 0; offsize-- )
62 {
63 result <<= 8;
64 result |= *p++;
65 }
66
67 *start = p;
68 return result;
69 }
70
71
72 LOCAL_FUNC
73 void cid_decrypt( FT_Byte* buffer,
74 FT_Int length,
75 FT_UShort seed )
76 {
77 while ( length > 0 )
78 {
79 FT_Byte plain;
80
81
82 plain = ( *buffer ^ ( seed >> 8 ) );
83 seed = ( *buffer + seed ) * 52845 + 22719;
84 *buffer++ = plain;
85 length--;
86 }
87 }
88
89
90 /*************************************************************************/
91 /*************************************************************************/
92 /***** *****/
93 /***** TYPE 1 SYMBOL PARSING *****/
94 /***** *****/
95 /*************************************************************************/
96 /*************************************************************************/
97
98
99 static
100 FT_Error cid_load_keyword( CID_Face face,
101 CID_Loader* loader,
102 const CID_Field_Rec* keyword )
103 {
104 FT_Error error;
105 CID_Parser* parser = &loader->parser;
106 FT_Byte* object;
107 CID_Info* cid = &face->cid;
108
109
110 /* if the keyword has a dedicated callback, call it */
111 if ( keyword->type == t1_field_callback )
112 {
113 error = keyword->reader( face, parser );
114 goto Exit;
115 }
116
117 /* we must now compute the address of our target object */
118 switch ( keyword->location )
119 {
120 case t1_field_cid_info:
121 object = (FT_Byte*)cid;
122 break;
123
124 case t1_field_font_info:
125 object = (FT_Byte*)&cid->font_info;
126 break;
127
128 default:
129 {
130 CID_FontDict* dict;
131
132
133 if ( parser->num_dict < 0 )
134 {
135 FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
136 keyword->ident ));
137 error = T1_Err_Syntax_Error;
138 goto Exit;
139 }
140
141 dict = cid->font_dicts + parser->num_dict;
142 switch ( keyword->location )
143 {
144 case t1_field_private:
145 object = (FT_Byte*)&dict->private_dict;
146 break;
147
148 default:
149 object = (FT_Byte*)dict;
150 }
151 }
152 }
153
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 );
158 else
159 error = CID_Load_Field( parser, keyword, object );
160
161 Exit:
162 return error;
163 }
164
165
166 static
167 FT_Error parse_font_bbox( CID_Face face,
168 CID_Parser* parser )
169 {
170 FT_Short temp[4];
171 FT_BBox* bbox = &face->cid.font_bbox;
172
173
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];
179
180 return T1_Err_Ok; /* this is a callback function; */
181 /* we must return an error code */
182 }
183
184
185 static
186 FT_Error parse_font_matrix( CID_Face face,
187 CID_Parser* parser )
188 {
189 FT_Matrix* matrix;
190 CID_FontDict* dict;
191 FT_Fixed temp[4];
192
193
194 if ( parser->num_dict >= 0 )
195 {
196 dict = face->cid.font_dicts + parser->num_dict;
197 matrix = &dict->font_matrix;
198
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];
204 }
205
206 return T1_Err_Ok; /* this is a callback function; */
207 /* we must return an error code */
208 }
209
210
211 static
212 FT_Error parse_fd_array( CID_Face face,
213 CID_Parser* parser )
214 {
215 CID_Info* cid = &face->cid;
216 FT_Memory memory = face->root.memory;
217 FT_Error error = T1_Err_Ok;
218 FT_Long num_dicts;
219
220
221 num_dicts = CID_ToInt( parser );
222
223 if ( !cid->font_dicts )
224 {
225 FT_Int n;
226
227
228 if ( ALLOC_ARRAY( cid->font_dicts, num_dicts, CID_FontDict ) )
229 goto Exit;
230
231 cid->num_dicts = (FT_UInt)num_dicts;
232
233 /* don't forget to set a few defaults */
234 for ( n = 0; n < cid->num_dicts; n++ )
235 {
236 CID_FontDict* dict = cid->font_dicts + n;
237
238
239 /* default value for lenIV */
240 dict->private_dict.lenIV = 4;
241 }
242 }
243
244 Exit:
245 return error;
246 }
247
248
249 static
250 const CID_Field_Rec t1_field_records[] =
251 {
252
253 #ifdef FT_FLAT_COMPILE
254
255 #include "cidtokens.h"
256
257 #else
258
259 #include <cid/cidtokens.h>
260
261 #endif
262
263 { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
264 };
265
266
267 static
268 int is_alpha( char c )
269 {
270 return ( isalnum( c ) ||
271 c == '.' ||
272 c == '_' );
273 }
274
275
276 static
277 void skip_whitespace( CID_Parser* parser )
278 {
279 FT_Byte* cur = parser->cursor;
280
281
282 while ( cur < parser->limit && isspace( *cur ) )
283 cur++;
284
285 parser->cursor = cur;
286 }
287
288
289 static
290 FT_Error parse_dict( CID_Face face,
291 CID_Loader* loader,
292 FT_Byte* base,
293 FT_Long size )
294 {
295 CID_Parser* parser = &loader->parser;
296
297
298 parser->cursor = base;
299 parser->limit = base + size;
300 parser->error = 0;
301
302 {
303 FT_Byte* cur = base;
304 FT_Byte* limit = cur + size;
305
306
307 for ( ;cur < limit; cur++ )
308 {
309 /* look for `%ADOBeginFontDict' */
310 if ( *cur == '%' && cur + 20 < limit &&
311 strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
312 {
313 cur += 17;
314
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 )
318 parser->num_dict++;
319 }
320 /* look for immediates */
321 else if ( *cur == '/' && cur + 2 < limit )
322 {
323 FT_Byte* cur2;
324 FT_Int len;
325
326
327 cur++;
328
329 cur2 = cur;
330 while ( cur2 < limit && is_alpha( *cur2 ) )
331 cur2++;
332
333 len = cur2 - cur;
334 if ( len > 0 && len < 22 )
335 {
336 /* now compare the immediate name to the keyword table */
337 const CID_Field_Rec* keyword = t1_field_records;
338
339
340 for (;;)
341 {
342 FT_Byte* name;
343
344
345 name = (FT_Byte*)keyword->ident;
346 if ( !name )
347 break;
348
349 if ( cur[0] == name[0] &&
350 len == (FT_Int)strlen( (const char*)name ) )
351 {
352 FT_Int n;
353
354
355 for ( n = 1; n < len; n++ )
356 if ( cur[n] != name[n] )
357 break;
358
359 if ( n >= len )
360 {
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 );
365 if ( parser->error )
366 return parser->error;
367
368 cur = parser->cursor;
369 break;
370 }
371 }
372 keyword++;
373 }
374 }
375 }
376 }
377 }
378 return parser->error;
379 }
380
381
382 /* read the subrmap and the subrs of each font dict */
383 static
384 FT_Error cid_read_subrs( CID_Face face )
385 {
386 CID_Info* cid = &face->cid;
387 FT_Memory memory = face->root.memory;
388 FT_Stream stream = face->root.stream;
389 FT_Error error;
390 FT_Int n;
391 CID_Subrs* subr;
392 FT_UInt max_offsets = 0;
393 FT_ULong* offsets = 0;
394
395
396 if ( ALLOC_ARRAY( face->subrs, cid->num_dicts, CID_Subrs ) )
397 goto Exit;
398
399 subr = face->subrs;
400 for ( n = 0; n < cid->num_dicts; n++, subr++ )
401 {
402 CID_FontDict* dict = cid->font_dicts + n;
403 FT_UInt count, num_subrs = dict->num_subrs;
404 FT_ULong data_len;
405 FT_Byte* p;
406
407
408 /* reallocate offsets array if needed */
409 if ( num_subrs + 1 > max_offsets )
410 {
411 FT_UInt new_max = ( num_subrs + 1 + 3 ) & -4;
412
413
414 if ( REALLOC_ARRAY( offsets, max_offsets, new_max, FT_ULong ) )
415 goto Fail;
416
417 max_offsets = new_max;
418 }
419
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 ) )
423 goto Fail;
424
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 );
428
429 FORGET_Frame();
430
431 /* now, compute the size of subrs charstrings, */
432 /* allocate, and read them */
433 data_len = offsets[num_subrs] - offsets[0];
434
435 if ( ALLOC_ARRAY( subr->code, num_subrs + 1, FT_Byte* ) ||
436 ALLOC( subr->code[0], data_len ) )
437 goto Fail;
438
439 if ( FILE_Seek( cid->data_offset + offsets[0] ) ||
440 FILE_Read( subr->code[0], data_len ) )
441 goto Exit;
442
443 /* set up pointers */
444 for ( count = 1; count <= num_subrs; count++ )
445 {
446 FT_UInt len;
447
448
449 len = offsets[count] - offsets[count - 1];
450 subr->code[count] = subr->code[count - 1] + len;
451 }
452
453 /* decrypt subroutines */
454 for ( count = 0; count < num_subrs; count++ )
455 {
456 FT_UInt len;
457
458
459 len = offsets[count + 1] - offsets[count];
460 cid_decrypt( subr->code[count], len, 4330 );
461 }
462
463 subr->num_subrs = num_subrs;
464 }
465
466 Exit:
467 FREE( offsets );
468 return error;
469
470 Fail:
471 if ( face->subrs )
472 {
473 for ( n = 0; n < cid->num_dicts; n++ )
474 {
475 if ( face->subrs[n].code )
476 FREE( face->subrs[n].code[0] );
477
478 FREE( face->subrs[n].code );
479 }
480 FREE( face->subrs );
481 }
482 goto Exit;
483 }
484
485
486 static
487 void t1_init_loader( CID_Loader* loader,
488 CID_Face face )
489 {
490 FT_UNUSED( face );
491
492 MEM_Set( loader, 0, sizeof ( *loader ) );
493 }
494
495
496 static
497 void t1_done_loader( CID_Loader* loader )
498 {
499 CID_Parser* parser = &loader->parser;
500
501
502 /* finalize parser */
503 CID_Done_Parser( parser );
504 }
505
506
507 LOCAL_FUNC
508 FT_Error CID_Open_Face( CID_Face face )
509 {
510 CID_Loader loader;
511 CID_Parser* parser;
512 FT_Error error;
513
514
515 t1_init_loader( &loader, face );
516
517 parser = &loader.parser;
518 error = CID_New_Parser( parser, face->root.stream, face->root.memory );
519 if ( error )
520 goto Exit;
521
522 error = parse_dict( face, &loader,
523 parser->postscript,
524 parser->postscript_len );
525 if ( error )
526 goto Exit;
527
528 face->cid.data_offset = loader.parser.data_offset;
529 error = cid_read_subrs( face );
530
531 Exit:
532 t1_done_loader( &loader );
533 return error;
534 }
535
536
537 /* END */