Sync with trunk r63343.
[reactos.git] / lib / 3rdparty / freetype / src / type1 / t1load.c
1 /***************************************************************************/
2 /* */
3 /* t1load.c */
4 /* */
5 /* Type 1 font loader (body). */
6 /* */
7 /* Copyright 1996-2014 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 /*************************************************************************/
20 /* */
21 /* This is the new and improved Type 1 data loader for FreeType 2. The */
22 /* old loader has several problems: it is slow, complex, difficult to */
23 /* maintain, and contains incredible hacks to make it accept some */
24 /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */
25 /* the Type 1 fonts on my machine still aren't loaded correctly by it. */
26 /* */
27 /* This version is much simpler, much faster and also easier to read and */
28 /* maintain by a great order of magnitude. The idea behind it is to */
29 /* _not_ try to read the Type 1 token stream with a state machine (i.e. */
30 /* a Postscript-like interpreter) but rather to perform simple pattern */
31 /* matching. */
32 /* */
33 /* Indeed, nearly all data definitions follow a simple pattern like */
34 /* */
35 /* ... /Field <data> ... */
36 /* */
37 /* where <data> can be a number, a boolean, a string, or an array of */
38 /* numbers. There are a few exceptions, namely the encoding, font name, */
39 /* charstrings, and subrs; they are handled with a special pattern */
40 /* matching routine. */
41 /* */
42 /* All other common cases are handled very simply. The matching rules */
43 /* are defined in the file `t1tokens.h' through the use of several */
44 /* macros calls PARSE_XXX. This file is included twice here; the first */
45 /* time to generate parsing callback functions, the second time to */
46 /* generate a table of keywords (with pointers to the associated */
47 /* callback functions). */
48 /* */
49 /* The function `parse_dict' simply scans *linearly* a given dictionary */
50 /* (either the top-level or private one) and calls the appropriate */
51 /* callback when it encounters an immediate keyword. */
52 /* */
53 /* This is by far the fastest way one can find to parse and read all */
54 /* data. */
55 /* */
56 /* This led to tremendous code size reduction. Note that later, the */
57 /* glyph loader will also be _greatly_ simplified, and the automatic */
58 /* hinter will replace the clumsy `t1hinter'. */
59 /* */
60 /*************************************************************************/
61
62
63 #include <ft2build.h>
64 #include FT_INTERNAL_DEBUG_H
65 #include FT_CONFIG_CONFIG_H
66 #include FT_MULTIPLE_MASTERS_H
67 #include FT_INTERNAL_TYPE1_TYPES_H
68 #include FT_INTERNAL_CALC_H
69
70 #include "t1load.h"
71 #include "t1errors.h"
72
73
74 #ifdef FT_CONFIG_OPTION_INCREMENTAL
75 #define IS_INCREMENTAL (FT_Bool)( face->root.internal->incremental_interface != 0 )
76 #else
77 #define IS_INCREMENTAL 0
78 #endif
79
80
81 /*************************************************************************/
82 /* */
83 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
84 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
85 /* messages during execution. */
86 /* */
87 #undef FT_COMPONENT
88 #define FT_COMPONENT trace_t1load
89
90
91 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
92
93
94 /*************************************************************************/
95 /*************************************************************************/
96 /***** *****/
97 /***** MULTIPLE MASTERS SUPPORT *****/
98 /***** *****/
99 /*************************************************************************/
100 /*************************************************************************/
101
102 static FT_Error
103 t1_allocate_blend( T1_Face face,
104 FT_UInt num_designs,
105 FT_UInt num_axis )
106 {
107 PS_Blend blend;
108 FT_Memory memory = face->root.memory;
109 FT_Error error = FT_Err_Ok;
110
111
112 blend = face->blend;
113 if ( !blend )
114 {
115 if ( FT_NEW( blend ) )
116 goto Exit;
117
118 blend->num_default_design_vector = 0;
119
120 face->blend = blend;
121 }
122
123 /* allocate design data if needed */
124 if ( num_designs > 0 )
125 {
126 if ( blend->num_designs == 0 )
127 {
128 FT_UInt nn;
129
130
131 /* allocate the blend `private' and `font_info' dictionaries */
132 if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) ||
133 FT_NEW_ARRAY( blend->privates [1], num_designs ) ||
134 FT_NEW_ARRAY( blend->bboxes [1], num_designs ) ||
135 FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) )
136 goto Exit;
137
138 blend->default_weight_vector = blend->weight_vector + num_designs;
139
140 blend->font_infos[0] = &face->type1.font_info;
141 blend->privates [0] = &face->type1.private_dict;
142 blend->bboxes [0] = &face->type1.font_bbox;
143
144 for ( nn = 2; nn <= num_designs; nn++ )
145 {
146 blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
147 blend->privates [nn] = blend->privates [nn - 1] + 1;
148 blend->bboxes [nn] = blend->bboxes [nn - 1] + 1;
149 }
150
151 blend->num_designs = num_designs;
152 }
153 else if ( blend->num_designs != num_designs )
154 goto Fail;
155 }
156
157 /* allocate axis data if needed */
158 if ( num_axis > 0 )
159 {
160 if ( blend->num_axis != 0 && blend->num_axis != num_axis )
161 goto Fail;
162
163 blend->num_axis = num_axis;
164 }
165
166 /* allocate the blend design pos table if needed */
167 num_designs = blend->num_designs;
168 num_axis = blend->num_axis;
169 if ( num_designs && num_axis && blend->design_pos[0] == 0 )
170 {
171 FT_UInt n;
172
173
174 if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) )
175 goto Exit;
176
177 for ( n = 1; n < num_designs; n++ )
178 blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
179 }
180
181 Exit:
182 return error;
183
184 Fail:
185 error = FT_THROW( Invalid_File_Format );
186 goto Exit;
187 }
188
189
190 FT_LOCAL_DEF( FT_Error )
191 T1_Get_Multi_Master( T1_Face face,
192 FT_Multi_Master* master )
193 {
194 PS_Blend blend = face->blend;
195 FT_UInt n;
196 FT_Error error;
197
198
199 error = FT_THROW( Invalid_Argument );
200
201 if ( blend )
202 {
203 master->num_axis = blend->num_axis;
204 master->num_designs = blend->num_designs;
205
206 for ( n = 0; n < blend->num_axis; n++ )
207 {
208 FT_MM_Axis* axis = master->axis + n;
209 PS_DesignMap map = blend->design_map + n;
210
211
212 axis->name = blend->axis_names[n];
213 axis->minimum = map->design_points[0];
214 axis->maximum = map->design_points[map->num_points - 1];
215 }
216
217 error = FT_Err_Ok;
218 }
219
220 return error;
221 }
222
223
224 /*************************************************************************/
225 /* */
226 /* Given a normalized (blend) coordinate, figure out the design */
227 /* coordinate appropriate for that value. */
228 /* */
229 FT_LOCAL_DEF( FT_Fixed )
230 mm_axis_unmap( PS_DesignMap axismap,
231 FT_Fixed ncv )
232 {
233 int j;
234
235
236 if ( ncv <= axismap->blend_points[0] )
237 return INT_TO_FIXED( axismap->design_points[0] );
238
239 for ( j = 1; j < axismap->num_points; ++j )
240 {
241 if ( ncv <= axismap->blend_points[j] )
242 return INT_TO_FIXED( axismap->design_points[j - 1] ) +
243 ( axismap->design_points[j] - axismap->design_points[j - 1] ) *
244 FT_DivFix( ncv - axismap->blend_points[j - 1],
245 axismap->blend_points[j] -
246 axismap->blend_points[j - 1] );
247 }
248
249 return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] );
250 }
251
252
253 /*************************************************************************/
254 /* */
255 /* Given a vector of weights, one for each design, figure out the */
256 /* normalized axis coordinates which gave rise to those weights. */
257 /* */
258 FT_LOCAL_DEF( void )
259 mm_weights_unmap( FT_Fixed* weights,
260 FT_Fixed* axiscoords,
261 FT_UInt axis_count )
262 {
263 FT_ASSERT( axis_count <= T1_MAX_MM_AXIS );
264
265 if ( axis_count == 1 )
266 axiscoords[0] = weights[1];
267
268 else if ( axis_count == 2 )
269 {
270 axiscoords[0] = weights[3] + weights[1];
271 axiscoords[1] = weights[3] + weights[2];
272 }
273
274 else if ( axis_count == 3 )
275 {
276 axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1];
277 axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2];
278 axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4];
279 }
280
281 else
282 {
283 axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] +
284 weights[7] + weights[5] + weights[3] + weights[1];
285 axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] +
286 weights[7] + weights[6] + weights[3] + weights[2];
287 axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] +
288 weights[7] + weights[6] + weights[5] + weights[4];
289 axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] +
290 weights[11] + weights[10] + weights[9] + weights[8];
291 }
292 }
293
294
295 /*************************************************************************/
296 /* */
297 /* Just a wrapper around T1_Get_Multi_Master to support the different */
298 /* arguments needed by the GX var distortable fonts. */
299 /* */
300 FT_LOCAL_DEF( FT_Error )
301 T1_Get_MM_Var( T1_Face face,
302 FT_MM_Var* *master )
303 {
304 FT_Memory memory = face->root.memory;
305 FT_MM_Var *mmvar = NULL;
306 FT_Multi_Master mmaster;
307 FT_Error error;
308 FT_UInt i;
309 FT_Fixed axiscoords[T1_MAX_MM_AXIS];
310 PS_Blend blend = face->blend;
311
312
313 error = T1_Get_Multi_Master( face, &mmaster );
314 if ( error )
315 goto Exit;
316 if ( FT_ALLOC( mmvar,
317 sizeof ( FT_MM_Var ) +
318 mmaster.num_axis * sizeof ( FT_Var_Axis ) ) )
319 goto Exit;
320
321 mmvar->num_axis = mmaster.num_axis;
322 mmvar->num_designs = mmaster.num_designs;
323 mmvar->num_namedstyles = ~0U; /* Does not apply */
324 mmvar->axis = (FT_Var_Axis*)&mmvar[1];
325 /* Point to axes after MM_Var struct */
326 mmvar->namedstyle = NULL;
327
328 for ( i = 0 ; i < mmaster.num_axis; ++i )
329 {
330 mmvar->axis[i].name = mmaster.axis[i].name;
331 mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum);
332 mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum);
333 mmvar->axis[i].def = ( mmvar->axis[i].minimum +
334 mmvar->axis[i].maximum ) / 2;
335 /* Does not apply. But this value is in range */
336 mmvar->axis[i].strid = ~0U; /* Does not apply */
337 mmvar->axis[i].tag = ~0U; /* Does not apply */
338
339 if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 )
340 mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' );
341 else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 )
342 mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' );
343 else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 )
344 mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' );
345 }
346
347 if ( blend->num_designs == ( 1U << blend->num_axis ) )
348 {
349 mm_weights_unmap( blend->default_weight_vector,
350 axiscoords,
351 blend->num_axis );
352
353 for ( i = 0; i < mmaster.num_axis; ++i )
354 mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i],
355 axiscoords[i] );
356 }
357
358 *master = mmvar;
359
360 Exit:
361 return error;
362 }
363
364
365 FT_LOCAL_DEF( FT_Error )
366 T1_Set_MM_Blend( T1_Face face,
367 FT_UInt num_coords,
368 FT_Fixed* coords )
369 {
370 PS_Blend blend = face->blend;
371 FT_Error error;
372 FT_UInt n, m;
373
374
375 error = FT_ERR( Invalid_Argument );
376
377 if ( blend && blend->num_axis == num_coords )
378 {
379 /* recompute the weight vector from the blend coordinates */
380 for ( n = 0; n < blend->num_designs; n++ )
381 {
382 FT_Fixed result = 0x10000L; /* 1.0 fixed */
383
384
385 for ( m = 0; m < blend->num_axis; m++ )
386 {
387 FT_Fixed factor;
388
389
390 /* get current blend axis position */
391 factor = coords[m];
392 if ( factor < 0 )
393 factor = 0;
394 if ( factor > 0x10000L )
395 factor = 0x10000L;
396
397 if ( ( n & ( 1 << m ) ) == 0 )
398 factor = 0x10000L - factor;
399
400 result = FT_MulFix( result, factor );
401 }
402 blend->weight_vector[n] = result;
403 }
404
405 error = FT_Err_Ok;
406 }
407
408 return error;
409 }
410
411
412 FT_LOCAL_DEF( FT_Error )
413 T1_Set_MM_Design( T1_Face face,
414 FT_UInt num_coords,
415 FT_Long* coords )
416 {
417 PS_Blend blend = face->blend;
418 FT_Error error;
419 FT_UInt n, p;
420
421
422 error = FT_ERR( Invalid_Argument );
423 if ( blend && blend->num_axis == num_coords )
424 {
425 /* compute the blend coordinates through the blend design map */
426 FT_Fixed final_blends[T1_MAX_MM_DESIGNS];
427
428
429 for ( n = 0; n < blend->num_axis; n++ )
430 {
431 FT_Long design = coords[n];
432 FT_Fixed the_blend;
433 PS_DesignMap map = blend->design_map + n;
434 FT_Long* designs = map->design_points;
435 FT_Fixed* blends = map->blend_points;
436 FT_Int before = -1, after = -1;
437
438
439 for ( p = 0; p < (FT_UInt)map->num_points; p++ )
440 {
441 FT_Long p_design = designs[p];
442
443
444 /* exact match? */
445 if ( design == p_design )
446 {
447 the_blend = blends[p];
448 goto Found;
449 }
450
451 if ( design < p_design )
452 {
453 after = p;
454 break;
455 }
456
457 before = p;
458 }
459
460 /* now interpolate if necessary */
461 if ( before < 0 )
462 the_blend = blends[0];
463
464 else if ( after < 0 )
465 the_blend = blends[map->num_points - 1];
466
467 else
468 the_blend = FT_MulDiv( design - designs[before],
469 blends [after] - blends [before],
470 designs[after] - designs[before] );
471
472 Found:
473 final_blends[n] = the_blend;
474 }
475
476 error = T1_Set_MM_Blend( face, num_coords, final_blends );
477 }
478
479 return error;
480 }
481
482
483 /*************************************************************************/
484 /* */
485 /* Just a wrapper around T1_Set_MM_Design to support the different */
486 /* arguments needed by the GX var distortable fonts. */
487 /* */
488 FT_LOCAL_DEF( FT_Error )
489 T1_Set_Var_Design( T1_Face face,
490 FT_UInt num_coords,
491 FT_Fixed* coords )
492 {
493 FT_Long lcoords[4]; /* maximum axis count is 4 */
494 FT_UInt i;
495 FT_Error error;
496
497
498 error = FT_ERR( Invalid_Argument );
499 if ( num_coords <= 4 && num_coords > 0 )
500 {
501 for ( i = 0; i < num_coords; ++i )
502 lcoords[i] = FIXED_TO_INT( coords[i] );
503 error = T1_Set_MM_Design( face, num_coords, lcoords );
504 }
505
506 return error;
507 }
508
509
510 FT_LOCAL_DEF( void )
511 T1_Done_Blend( T1_Face face )
512 {
513 FT_Memory memory = face->root.memory;
514 PS_Blend blend = face->blend;
515
516
517 if ( blend )
518 {
519 FT_UInt num_designs = blend->num_designs;
520 FT_UInt num_axis = blend->num_axis;
521 FT_UInt n;
522
523
524 /* release design pos table */
525 FT_FREE( blend->design_pos[0] );
526 for ( n = 1; n < num_designs; n++ )
527 blend->design_pos[n] = NULL;
528
529 /* release blend `private' and `font info' dictionaries */
530 FT_FREE( blend->privates[1] );
531 FT_FREE( blend->font_infos[1] );
532 FT_FREE( blend->bboxes[1] );
533
534 for ( n = 0; n < num_designs; n++ )
535 {
536 blend->privates [n] = NULL;
537 blend->font_infos[n] = NULL;
538 blend->bboxes [n] = NULL;
539 }
540
541 /* release weight vectors */
542 FT_FREE( blend->weight_vector );
543 blend->default_weight_vector = NULL;
544
545 /* release axis names */
546 for ( n = 0; n < num_axis; n++ )
547 FT_FREE( blend->axis_names[n] );
548
549 /* release design map */
550 for ( n = 0; n < num_axis; n++ )
551 {
552 PS_DesignMap dmap = blend->design_map + n;
553
554
555 FT_FREE( dmap->design_points );
556 dmap->num_points = 0;
557 }
558
559 FT_FREE( face->blend );
560 }
561 }
562
563
564 static void
565 parse_blend_axis_types( T1_Face face,
566 T1_Loader loader )
567 {
568 T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];
569 FT_Int n, num_axis;
570 FT_Error error = FT_Err_Ok;
571 PS_Blend blend;
572 FT_Memory memory;
573
574
575 /* take an array of objects */
576 T1_ToTokenArray( &loader->parser, axis_tokens,
577 T1_MAX_MM_AXIS, &num_axis );
578 if ( num_axis < 0 )
579 {
580 error = FT_ERR( Ignore );
581 goto Exit;
582 }
583 if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
584 {
585 FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
586 num_axis ));
587 error = FT_THROW( Invalid_File_Format );
588 goto Exit;
589 }
590
591 /* allocate blend if necessary */
592 error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
593 if ( error )
594 goto Exit;
595
596 blend = face->blend;
597 memory = face->root.memory;
598
599 /* each token is an immediate containing the name of the axis */
600 for ( n = 0; n < num_axis; n++ )
601 {
602 T1_Token token = axis_tokens + n;
603 FT_Byte* name;
604 FT_PtrDist len;
605
606
607 /* skip first slash, if any */
608 if ( token->start[0] == '/' )
609 token->start++;
610
611 len = token->limit - token->start;
612 if ( len == 0 )
613 {
614 error = FT_THROW( Invalid_File_Format );
615 goto Exit;
616 }
617
618 if ( FT_ALLOC( blend->axis_names[n], (FT_Long)( len + 1 ) ) )
619 goto Exit;
620
621 name = (FT_Byte*)blend->axis_names[n];
622 FT_MEM_COPY( name, token->start, len );
623 name[len] = '\0';
624 }
625
626 Exit:
627 loader->parser.root.error = error;
628 }
629
630
631 static void
632 parse_blend_design_positions( T1_Face face,
633 T1_Loader loader )
634 {
635 T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS];
636 FT_Int num_designs;
637 FT_Int num_axis;
638 T1_Parser parser = &loader->parser;
639
640 FT_Error error = FT_Err_Ok;
641 PS_Blend blend;
642
643
644 /* get the array of design tokens -- compute number of designs */
645 T1_ToTokenArray( parser, design_tokens,
646 T1_MAX_MM_DESIGNS, &num_designs );
647 if ( num_designs < 0 )
648 {
649 error = FT_ERR( Ignore );
650 goto Exit;
651 }
652 if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
653 {
654 FT_ERROR(( "parse_blend_design_positions:"
655 " incorrect number of designs: %d\n",
656 num_designs ));
657 error = FT_THROW( Invalid_File_Format );
658 goto Exit;
659 }
660
661 {
662 FT_Byte* old_cursor = parser->root.cursor;
663 FT_Byte* old_limit = parser->root.limit;
664 FT_Int n;
665
666
667 blend = face->blend;
668 num_axis = 0; /* make compiler happy */
669
670 for ( n = 0; n < num_designs; n++ )
671 {
672 T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];
673 T1_Token token;
674 FT_Int axis, n_axis;
675
676
677 /* read axis/coordinates tokens */
678 token = design_tokens + n;
679 parser->root.cursor = token->start;
680 parser->root.limit = token->limit;
681 T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
682
683 if ( n == 0 )
684 {
685 if ( n_axis <= 0 || n_axis > T1_MAX_MM_AXIS )
686 {
687 FT_ERROR(( "parse_blend_design_positions:"
688 " invalid number of axes: %d\n",
689 n_axis ));
690 error = FT_THROW( Invalid_File_Format );
691 goto Exit;
692 }
693
694 num_axis = n_axis;
695 error = t1_allocate_blend( face, num_designs, num_axis );
696 if ( error )
697 goto Exit;
698 blend = face->blend;
699 }
700 else if ( n_axis != num_axis )
701 {
702 FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
703 error = FT_THROW( Invalid_File_Format );
704 goto Exit;
705 }
706
707 /* now read each axis token into the design position */
708 for ( axis = 0; axis < n_axis; axis++ )
709 {
710 T1_Token token2 = axis_tokens + axis;
711
712
713 parser->root.cursor = token2->start;
714 parser->root.limit = token2->limit;
715 blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
716 }
717 }
718
719 loader->parser.root.cursor = old_cursor;
720 loader->parser.root.limit = old_limit;
721 }
722
723 Exit:
724 loader->parser.root.error = error;
725 }
726
727
728 static void
729 parse_blend_design_map( T1_Face face,
730 T1_Loader loader )
731 {
732 FT_Error error = FT_Err_Ok;
733 T1_Parser parser = &loader->parser;
734 PS_Blend blend;
735 T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];
736 FT_Int n, num_axis;
737 FT_Byte* old_cursor;
738 FT_Byte* old_limit;
739 FT_Memory memory = face->root.memory;
740
741
742 T1_ToTokenArray( parser, axis_tokens,
743 T1_MAX_MM_AXIS, &num_axis );
744 if ( num_axis < 0 )
745 {
746 error = FT_ERR( Ignore );
747 goto Exit;
748 }
749 if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
750 {
751 FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
752 num_axis ));
753 error = FT_THROW( Invalid_File_Format );
754 goto Exit;
755 }
756
757 old_cursor = parser->root.cursor;
758 old_limit = parser->root.limit;
759
760 error = t1_allocate_blend( face, 0, num_axis );
761 if ( error )
762 goto Exit;
763 blend = face->blend;
764
765 /* now read each axis design map */
766 for ( n = 0; n < num_axis; n++ )
767 {
768 PS_DesignMap map = blend->design_map + n;
769 T1_Token axis_token;
770 T1_TokenRec point_tokens[T1_MAX_MM_MAP_POINTS];
771 FT_Int p, num_points;
772
773
774 axis_token = axis_tokens + n;
775
776 parser->root.cursor = axis_token->start;
777 parser->root.limit = axis_token->limit;
778 T1_ToTokenArray( parser, point_tokens,
779 T1_MAX_MM_MAP_POINTS, &num_points );
780
781 if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
782 {
783 FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
784 error = FT_THROW( Invalid_File_Format );
785 goto Exit;
786 }
787
788 /* allocate design map data */
789 if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) )
790 goto Exit;
791 map->blend_points = map->design_points + num_points;
792 map->num_points = (FT_Byte)num_points;
793
794 for ( p = 0; p < num_points; p++ )
795 {
796 T1_Token point_token;
797
798
799 point_token = point_tokens + p;
800
801 /* don't include delimiting brackets */
802 parser->root.cursor = point_token->start + 1;
803 parser->root.limit = point_token->limit - 1;
804
805 map->design_points[p] = T1_ToInt( parser );
806 map->blend_points [p] = T1_ToFixed( parser, 0 );
807 }
808 }
809
810 parser->root.cursor = old_cursor;
811 parser->root.limit = old_limit;
812
813 Exit:
814 parser->root.error = error;
815 }
816
817
818 static void
819 parse_weight_vector( T1_Face face,
820 T1_Loader loader )
821 {
822 T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS];
823 FT_Int num_designs;
824 FT_Error error = FT_Err_Ok;
825 T1_Parser parser = &loader->parser;
826 PS_Blend blend = face->blend;
827 T1_Token token;
828 FT_Int n;
829 FT_Byte* old_cursor;
830 FT_Byte* old_limit;
831
832
833 T1_ToTokenArray( parser, design_tokens,
834 T1_MAX_MM_DESIGNS, &num_designs );
835 if ( num_designs < 0 )
836 {
837 error = FT_ERR( Ignore );
838 goto Exit;
839 }
840 if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
841 {
842 FT_ERROR(( "parse_weight_vector:"
843 " incorrect number of designs: %d\n",
844 num_designs ));
845 error = FT_THROW( Invalid_File_Format );
846 goto Exit;
847 }
848
849 if ( !blend || !blend->num_designs )
850 {
851 error = t1_allocate_blend( face, num_designs, 0 );
852 if ( error )
853 goto Exit;
854 blend = face->blend;
855 }
856 else if ( blend->num_designs != (FT_UInt)num_designs )
857 {
858 FT_ERROR(( "parse_weight_vector:"
859 " /BlendDesignPosition and /WeightVector have\n"
860 " "
861 " different number of elements\n" ));
862 error = FT_THROW( Invalid_File_Format );
863 goto Exit;
864 }
865
866 old_cursor = parser->root.cursor;
867 old_limit = parser->root.limit;
868
869 for ( n = 0; n < num_designs; n++ )
870 {
871 token = design_tokens + n;
872 parser->root.cursor = token->start;
873 parser->root.limit = token->limit;
874
875 blend->default_weight_vector[n] =
876 blend->weight_vector[n] = T1_ToFixed( parser, 0 );
877 }
878
879 parser->root.cursor = old_cursor;
880 parser->root.limit = old_limit;
881
882 Exit:
883 parser->root.error = error;
884 }
885
886
887 /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */
888 /* we're only interested in the number of array elements */
889 static void
890 parse_buildchar( T1_Face face,
891 T1_Loader loader )
892 {
893 face->len_buildchar = T1_ToFixedArray( &loader->parser, 0, NULL, 0 );
894
895 return;
896 }
897
898
899 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
900
901
902
903
904 /*************************************************************************/
905 /*************************************************************************/
906 /***** *****/
907 /***** TYPE 1 SYMBOL PARSING *****/
908 /***** *****/
909 /*************************************************************************/
910 /*************************************************************************/
911
912 static FT_Error
913 t1_load_keyword( T1_Face face,
914 T1_Loader loader,
915 const T1_Field field )
916 {
917 FT_Error error;
918 void* dummy_object;
919 void** objects;
920 FT_UInt max_objects;
921 PS_Blend blend = face->blend;
922
923
924 if ( blend && blend->num_designs == 0 )
925 blend = NULL;
926
927 /* if the keyword has a dedicated callback, call it */
928 if ( field->type == T1_FIELD_TYPE_CALLBACK )
929 {
930 field->reader( (FT_Face)face, loader );
931 error = loader->parser.root.error;
932 goto Exit;
933 }
934
935 /* now, the keyword is either a simple field, or a table of fields; */
936 /* we are now going to take care of it */
937 switch ( field->location )
938 {
939 case T1_FIELD_LOCATION_FONT_INFO:
940 dummy_object = &face->type1.font_info;
941 objects = &dummy_object;
942 max_objects = 0;
943
944 if ( blend )
945 {
946 objects = (void**)blend->font_infos;
947 max_objects = blend->num_designs;
948 }
949 break;
950
951 case T1_FIELD_LOCATION_FONT_EXTRA:
952 dummy_object = &face->type1.font_extra;
953 objects = &dummy_object;
954 max_objects = 0;
955 break;
956
957 case T1_FIELD_LOCATION_PRIVATE:
958 dummy_object = &face->type1.private_dict;
959 objects = &dummy_object;
960 max_objects = 0;
961
962 if ( blend )
963 {
964 objects = (void**)blend->privates;
965 max_objects = blend->num_designs;
966 }
967 break;
968
969 case T1_FIELD_LOCATION_BBOX:
970 dummy_object = &face->type1.font_bbox;
971 objects = &dummy_object;
972 max_objects = 0;
973
974 if ( blend )
975 {
976 objects = (void**)blend->bboxes;
977 max_objects = blend->num_designs;
978 }
979 break;
980
981 case T1_FIELD_LOCATION_LOADER:
982 dummy_object = loader;
983 objects = &dummy_object;
984 max_objects = 0;
985 break;
986
987 case T1_FIELD_LOCATION_FACE:
988 dummy_object = face;
989 objects = &dummy_object;
990 max_objects = 0;
991 break;
992
993 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
994 case T1_FIELD_LOCATION_BLEND:
995 dummy_object = face->blend;
996 objects = &dummy_object;
997 max_objects = 0;
998 break;
999 #endif
1000
1001 default:
1002 dummy_object = &face->type1;
1003 objects = &dummy_object;
1004 max_objects = 0;
1005 }
1006
1007 if ( *objects )
1008 {
1009 if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
1010 field->type == T1_FIELD_TYPE_FIXED_ARRAY )
1011 error = T1_Load_Field_Table( &loader->parser, field,
1012 objects, max_objects, 0 );
1013 else
1014 error = T1_Load_Field( &loader->parser, field,
1015 objects, max_objects, 0 );
1016 }
1017 else
1018 {
1019 FT_TRACE1(( "t1_load_keyword: ignoring keyword `%s'"
1020 " which is not valid at this point\n"
1021 " (probably due to missing keywords)\n",
1022 field->ident ));
1023 error = FT_Err_Ok;
1024 }
1025
1026 Exit:
1027 return error;
1028 }
1029
1030
1031 static void
1032 parse_private( T1_Face face,
1033 T1_Loader loader )
1034 {
1035 FT_UNUSED( face );
1036
1037 loader->keywords_encountered |= T1_PRIVATE;
1038 }
1039
1040
1041 static int
1042 read_binary_data( T1_Parser parser,
1043 FT_Long* size,
1044 FT_Byte** base,
1045 FT_Bool incremental )
1046 {
1047 FT_Byte* cur;
1048 FT_Byte* limit = parser->root.limit;
1049
1050
1051 /* the binary data has one of the following formats */
1052 /* */
1053 /* `size' [white*] RD white ....... ND */
1054 /* `size' [white*] -| white ....... |- */
1055 /* */
1056
1057 T1_Skip_Spaces( parser );
1058
1059 cur = parser->root.cursor;
1060
1061 if ( cur < limit && ft_isdigit( *cur ) )
1062 {
1063 FT_Long s = T1_ToInt( parser );
1064
1065
1066 T1_Skip_PS_Token( parser ); /* `RD' or `-|' or something else */
1067
1068 /* there is only one whitespace char after the */
1069 /* `RD' or `-|' token */
1070 *base = parser->root.cursor + 1;
1071
1072 if ( s >= 0 && s < limit - *base )
1073 {
1074 parser->root.cursor += s + 1;
1075 *size = s;
1076 return !parser->root.error;
1077 }
1078 }
1079
1080 if( !incremental )
1081 {
1082 FT_ERROR(( "read_binary_data: invalid size field\n" ));
1083 parser->root.error = FT_THROW( Invalid_File_Format );
1084 }
1085
1086 return 0;
1087 }
1088
1089
1090 /* We now define the routines to handle the `/Encoding', `/Subrs', */
1091 /* and `/CharStrings' dictionaries. */
1092
1093 static void
1094 t1_parse_font_matrix( T1_Face face,
1095 T1_Loader loader )
1096 {
1097 T1_Parser parser = &loader->parser;
1098 FT_Matrix* matrix = &face->type1.font_matrix;
1099 FT_Vector* offset = &face->type1.font_offset;
1100 FT_Face root = (FT_Face)&face->root;
1101 FT_Fixed temp[6];
1102 FT_Fixed temp_scale;
1103 FT_Int result;
1104
1105
1106 result = T1_ToFixedArray( parser, 6, temp, 3 );
1107
1108 if ( result < 6 )
1109 {
1110 parser->root.error = FT_THROW( Invalid_File_Format );
1111 return;
1112 }
1113
1114 temp_scale = FT_ABS( temp[3] );
1115
1116 if ( temp_scale == 0 )
1117 {
1118 FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
1119 parser->root.error = FT_THROW( Invalid_File_Format );
1120 return;
1121 }
1122
1123 /* Set Units per EM based on FontMatrix values. We set the value to */
1124 /* 1000 / temp_scale, because temp_scale was already multiplied by */
1125 /* 1000 (in t1_tofixed, from psobjs.c). */
1126
1127 root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );
1128
1129 /* we need to scale the values by 1.0/temp_scale */
1130 if ( temp_scale != 0x10000L )
1131 {
1132 temp[0] = FT_DivFix( temp[0], temp_scale );
1133 temp[1] = FT_DivFix( temp[1], temp_scale );
1134 temp[2] = FT_DivFix( temp[2], temp_scale );
1135 temp[4] = FT_DivFix( temp[4], temp_scale );
1136 temp[5] = FT_DivFix( temp[5], temp_scale );
1137 temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
1138 }
1139
1140 matrix->xx = temp[0];
1141 matrix->yx = temp[1];
1142 matrix->xy = temp[2];
1143 matrix->yy = temp[3];
1144
1145 /* note that the offsets must be expressed in integer font units */
1146 offset->x = temp[4] >> 16;
1147 offset->y = temp[5] >> 16;
1148 }
1149
1150
1151 static void
1152 parse_encoding( T1_Face face,
1153 T1_Loader loader )
1154 {
1155 T1_Parser parser = &loader->parser;
1156 FT_Byte* cur;
1157 FT_Byte* limit = parser->root.limit;
1158
1159 PSAux_Service psaux = (PSAux_Service)face->psaux;
1160
1161
1162 T1_Skip_Spaces( parser );
1163 cur = parser->root.cursor;
1164 if ( cur >= limit )
1165 {
1166 FT_ERROR(( "parse_encoding: out of bounds\n" ));
1167 parser->root.error = FT_THROW( Invalid_File_Format );
1168 return;
1169 }
1170
1171 /* if we have a number or `[', the encoding is an array, */
1172 /* and we must load it now */
1173 if ( ft_isdigit( *cur ) || *cur == '[' )
1174 {
1175 T1_Encoding encode = &face->type1.encoding;
1176 FT_Int count, n;
1177 PS_Table char_table = &loader->encoding_table;
1178 FT_Memory memory = parser->root.memory;
1179 FT_Error error;
1180 FT_Bool only_immediates = 0;
1181
1182
1183 /* read the number of entries in the encoding; should be 256 */
1184 if ( *cur == '[' )
1185 {
1186 count = 256;
1187 only_immediates = 1;
1188 parser->root.cursor++;
1189 }
1190 else
1191 count = (FT_Int)T1_ToInt( parser );
1192
1193 T1_Skip_Spaces( parser );
1194 if ( parser->root.cursor >= limit )
1195 return;
1196
1197 /* we use a T1_Table to store our charnames */
1198 loader->num_chars = encode->num_chars = count;
1199 if ( FT_NEW_ARRAY( encode->char_index, count ) ||
1200 FT_NEW_ARRAY( encode->char_name, count ) ||
1201 FT_SET_ERROR( psaux->ps_table_funcs->init(
1202 char_table, count, memory ) ) )
1203 {
1204 parser->root.error = error;
1205 return;
1206 }
1207
1208 /* We need to `zero' out encoding_table.elements */
1209 for ( n = 0; n < count; n++ )
1210 {
1211 char* notdef = (char *)".notdef";
1212
1213
1214 T1_Add_Table( char_table, n, notdef, 8 );
1215 }
1216
1217 /* Now we need to read records of the form */
1218 /* */
1219 /* ... charcode /charname ... */
1220 /* */
1221 /* for each entry in our table. */
1222 /* */
1223 /* We simply look for a number followed by an immediate */
1224 /* name. Note that this ignores correctly the sequence */
1225 /* that is often seen in type1 fonts: */
1226 /* */
1227 /* 0 1 255 { 1 index exch /.notdef put } for dup */
1228 /* */
1229 /* used to clean the encoding array before anything else. */
1230 /* */
1231 /* Alternatively, if the array is directly given as */
1232 /* */
1233 /* /Encoding [ ... ] */
1234 /* */
1235 /* we only read immediates. */
1236
1237 n = 0;
1238 T1_Skip_Spaces( parser );
1239
1240 while ( parser->root.cursor < limit )
1241 {
1242 cur = parser->root.cursor;
1243
1244 /* we stop when we encounter a `def' or `]' */
1245 if ( *cur == 'd' && cur + 3 < limit )
1246 {
1247 if ( cur[1] == 'e' &&
1248 cur[2] == 'f' &&
1249 IS_PS_DELIM( cur[3] ) )
1250 {
1251 FT_TRACE6(( "encoding end\n" ));
1252 cur += 3;
1253 break;
1254 }
1255 }
1256 if ( *cur == ']' )
1257 {
1258 FT_TRACE6(( "encoding end\n" ));
1259 cur++;
1260 break;
1261 }
1262
1263 /* check whether we've found an entry */
1264 if ( ft_isdigit( *cur ) || only_immediates )
1265 {
1266 FT_Int charcode;
1267
1268
1269 if ( only_immediates )
1270 charcode = n;
1271 else
1272 {
1273 charcode = (FT_Int)T1_ToInt( parser );
1274 T1_Skip_Spaces( parser );
1275
1276 /* protect against invalid charcode */
1277 if ( cur == parser->root.cursor )
1278 {
1279 parser->root.error = FT_THROW( Unknown_File_Format );
1280 return;
1281 }
1282 }
1283
1284 cur = parser->root.cursor;
1285
1286 if ( cur + 2 < limit && *cur == '/' && n < count )
1287 {
1288 FT_PtrDist len;
1289
1290
1291 cur++;
1292
1293 parser->root.cursor = cur;
1294 T1_Skip_PS_Token( parser );
1295 if ( parser->root.cursor >= limit )
1296 return;
1297 if ( parser->root.error )
1298 return;
1299
1300 len = parser->root.cursor - cur;
1301
1302 parser->root.error = T1_Add_Table( char_table, charcode,
1303 cur, len + 1 );
1304 if ( parser->root.error )
1305 return;
1306 char_table->elements[charcode][len] = '\0';
1307
1308 n++;
1309 }
1310 else if ( only_immediates )
1311 {
1312 /* Since the current position is not updated for */
1313 /* immediates-only mode we would get an infinite loop if */
1314 /* we don't do anything here. */
1315 /* */
1316 /* This encoding array is not valid according to the type1 */
1317 /* specification (it might be an encoding for a CID type1 */
1318 /* font, however), so we conclude that this font is NOT a */
1319 /* type1 font. */
1320 parser->root.error = FT_THROW( Unknown_File_Format );
1321 return;
1322 }
1323 }
1324 else
1325 {
1326 T1_Skip_PS_Token( parser );
1327 if ( parser->root.error )
1328 return;
1329 }
1330
1331 T1_Skip_Spaces( parser );
1332 }
1333
1334 face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
1335 parser->root.cursor = cur;
1336 }
1337
1338 /* Otherwise, we should have either `StandardEncoding', */
1339 /* `ExpertEncoding', or `ISOLatin1Encoding' */
1340 else
1341 {
1342 if ( cur + 17 < limit &&
1343 ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
1344 face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
1345
1346 else if ( cur + 15 < limit &&
1347 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
1348 face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
1349
1350 else if ( cur + 18 < limit &&
1351 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
1352 face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
1353
1354 else
1355 parser->root.error = FT_ERR( Ignore );
1356 }
1357 }
1358
1359
1360 static void
1361 parse_subrs( T1_Face face,
1362 T1_Loader loader )
1363 {
1364 T1_Parser parser = &loader->parser;
1365 PS_Table table = &loader->subrs;
1366 FT_Memory memory = parser->root.memory;
1367 FT_Error error;
1368 FT_Int num_subrs;
1369
1370 PSAux_Service psaux = (PSAux_Service)face->psaux;
1371
1372
1373 T1_Skip_Spaces( parser );
1374
1375 /* test for empty array */
1376 if ( parser->root.cursor < parser->root.limit &&
1377 *parser->root.cursor == '[' )
1378 {
1379 T1_Skip_PS_Token( parser );
1380 T1_Skip_Spaces ( parser );
1381 if ( parser->root.cursor >= parser->root.limit ||
1382 *parser->root.cursor != ']' )
1383 parser->root.error = FT_THROW( Invalid_File_Format );
1384 return;
1385 }
1386
1387 num_subrs = (FT_Int)T1_ToInt( parser );
1388
1389 /* position the parser right before the `dup' of the first subr */
1390 T1_Skip_PS_Token( parser ); /* `array' */
1391 if ( parser->root.error )
1392 return;
1393 T1_Skip_Spaces( parser );
1394
1395 /* initialize subrs array -- with synthetic fonts it is possible */
1396 /* we get here twice */
1397 if ( !loader->num_subrs )
1398 {
1399 error = psaux->ps_table_funcs->init( table, num_subrs, memory );
1400 if ( error )
1401 goto Fail;
1402 }
1403
1404 /* the format is simple: */
1405 /* */
1406 /* `index' + binary data */
1407 /* */
1408 for (;;)
1409 {
1410 FT_Long idx, size;
1411 FT_Byte* base;
1412
1413
1414 /* If we are out of data, or if the next token isn't `dup', */
1415 /* we are done. */
1416 if ( parser->root.cursor + 4 >= parser->root.limit ||
1417 ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
1418 break;
1419
1420 T1_Skip_PS_Token( parser ); /* `dup' */
1421
1422 idx = T1_ToInt( parser );
1423
1424 if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) )
1425 return;
1426
1427 /* The binary string is followed by one token, e.g. `NP' */
1428 /* (bound to `noaccess put') or by two separate tokens: */
1429 /* `noaccess' & `put'. We position the parser right */
1430 /* before the next `dup', if any. */
1431 T1_Skip_PS_Token( parser ); /* `NP' or `|' or `noaccess' */
1432 if ( parser->root.error )
1433 return;
1434 T1_Skip_Spaces ( parser );
1435
1436 if ( parser->root.cursor + 4 < parser->root.limit &&
1437 ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
1438 {
1439 T1_Skip_PS_Token( parser ); /* skip `put' */
1440 T1_Skip_Spaces ( parser );
1441 }
1442
1443 /* with synthetic fonts it is possible we get here twice */
1444 if ( loader->num_subrs )
1445 continue;
1446
1447 /* some fonts use a value of -1 for lenIV to indicate that */
1448 /* the charstrings are unencoded */
1449 /* */
1450 /* thanks to Tom Kacvinsky for pointing this out */
1451 /* */
1452 if ( face->type1.private_dict.lenIV >= 0 )
1453 {
1454 FT_Byte* temp;
1455
1456
1457 /* some fonts define empty subr records -- this is not totally */
1458 /* compliant to the specification (which says they should at */
1459 /* least contain a `return'), but we support them anyway */
1460 if ( size < face->type1.private_dict.lenIV )
1461 {
1462 error = FT_THROW( Invalid_File_Format );
1463 goto Fail;
1464 }
1465
1466 /* t1_decrypt() shouldn't write to base -- make temporary copy */
1467 if ( FT_ALLOC( temp, size ) )
1468 goto Fail;
1469 FT_MEM_COPY( temp, base, size );
1470 psaux->t1_decrypt( temp, size, 4330 );
1471 size -= face->type1.private_dict.lenIV;
1472 error = T1_Add_Table( table, (FT_Int)idx,
1473 temp + face->type1.private_dict.lenIV, size );
1474 FT_FREE( temp );
1475 }
1476 else
1477 error = T1_Add_Table( table, (FT_Int)idx, base, size );
1478 if ( error )
1479 goto Fail;
1480 }
1481
1482 if ( !loader->num_subrs )
1483 loader->num_subrs = num_subrs;
1484
1485 return;
1486
1487 Fail:
1488 parser->root.error = error;
1489 }
1490
1491
1492 #define TABLE_EXTEND 5
1493
1494
1495 static void
1496 parse_charstrings( T1_Face face,
1497 T1_Loader loader )
1498 {
1499 T1_Parser parser = &loader->parser;
1500 PS_Table code_table = &loader->charstrings;
1501 PS_Table name_table = &loader->glyph_names;
1502 PS_Table swap_table = &loader->swap_table;
1503 FT_Memory memory = parser->root.memory;
1504 FT_Error error;
1505
1506 PSAux_Service psaux = (PSAux_Service)face->psaux;
1507
1508 FT_Byte* cur;
1509 FT_Byte* limit = parser->root.limit;
1510 FT_Int n, num_glyphs;
1511 FT_UInt notdef_index = 0;
1512 FT_Byte notdef_found = 0;
1513
1514
1515 num_glyphs = (FT_Int)T1_ToInt( parser );
1516 if ( num_glyphs < 0 )
1517 {
1518 error = FT_THROW( Invalid_File_Format );
1519 goto Fail;
1520 }
1521
1522 /* some fonts like Optima-Oblique not only define the /CharStrings */
1523 /* array but access it also */
1524 if ( num_glyphs == 0 || parser->root.error )
1525 return;
1526
1527 /* initialize tables, leaving space for addition of .notdef, */
1528 /* if necessary, and a few other glyphs to handle buggy */
1529 /* fonts which have more glyphs than specified. */
1530
1531 /* for some non-standard fonts like `Optima' which provides */
1532 /* different outlines depending on the resolution it is */
1533 /* possible to get here twice */
1534 if ( !loader->num_glyphs )
1535 {
1536 error = psaux->ps_table_funcs->init(
1537 code_table, num_glyphs + 1 + TABLE_EXTEND, memory );
1538 if ( error )
1539 goto Fail;
1540
1541 error = psaux->ps_table_funcs->init(
1542 name_table, num_glyphs + 1 + TABLE_EXTEND, memory );
1543 if ( error )
1544 goto Fail;
1545
1546 /* Initialize table for swapping index notdef_index and */
1547 /* index 0 names and codes (if necessary). */
1548
1549 error = psaux->ps_table_funcs->init( swap_table, 4, memory );
1550 if ( error )
1551 goto Fail;
1552 }
1553
1554 n = 0;
1555
1556 for (;;)
1557 {
1558 FT_Long size;
1559 FT_Byte* base;
1560
1561
1562 /* the format is simple: */
1563 /* `/glyphname' + binary data */
1564
1565 T1_Skip_Spaces( parser );
1566
1567 cur = parser->root.cursor;
1568 if ( cur >= limit )
1569 break;
1570
1571 /* we stop when we find a `def' or `end' keyword */
1572 if ( cur + 3 < limit && IS_PS_DELIM( cur[3] ) )
1573 {
1574 if ( cur[0] == 'd' &&
1575 cur[1] == 'e' &&
1576 cur[2] == 'f' )
1577 {
1578 /* There are fonts which have this: */
1579 /* */
1580 /* /CharStrings 118 dict def */
1581 /* Private begin */
1582 /* CharStrings begin */
1583 /* ... */
1584 /* */
1585 /* To catch this we ignore `def' if */
1586 /* no charstring has actually been */
1587 /* seen. */
1588 if ( n )
1589 break;
1590 }
1591
1592 if ( cur[0] == 'e' &&
1593 cur[1] == 'n' &&
1594 cur[2] == 'd' )
1595 break;
1596 }
1597
1598 T1_Skip_PS_Token( parser );
1599 if ( parser->root.error )
1600 return;
1601
1602 if ( *cur == '/' )
1603 {
1604 FT_PtrDist len;
1605
1606
1607 if ( cur + 1 >= limit )
1608 {
1609 error = FT_THROW( Invalid_File_Format );
1610 goto Fail;
1611 }
1612
1613 cur++; /* skip `/' */
1614 len = parser->root.cursor - cur;
1615
1616 if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) )
1617 return;
1618
1619 /* for some non-standard fonts like `Optima' which provides */
1620 /* different outlines depending on the resolution it is */
1621 /* possible to get here twice */
1622 if ( loader->num_glyphs )
1623 continue;
1624
1625 error = T1_Add_Table( name_table, n, cur, len + 1 );
1626 if ( error )
1627 goto Fail;
1628
1629 /* add a trailing zero to the name table */
1630 name_table->elements[n][len] = '\0';
1631
1632 /* record index of /.notdef */
1633 if ( *cur == '.' &&
1634 ft_strcmp( ".notdef",
1635 (const char*)(name_table->elements[n]) ) == 0 )
1636 {
1637 notdef_index = n;
1638 notdef_found = 1;
1639 }
1640
1641 if ( face->type1.private_dict.lenIV >= 0 &&
1642 n < num_glyphs + TABLE_EXTEND )
1643 {
1644 FT_Byte* temp;
1645
1646
1647 if ( size <= face->type1.private_dict.lenIV )
1648 {
1649 error = FT_THROW( Invalid_File_Format );
1650 goto Fail;
1651 }
1652
1653 /* t1_decrypt() shouldn't write to base -- make temporary copy */
1654 if ( FT_ALLOC( temp, size ) )
1655 goto Fail;
1656 FT_MEM_COPY( temp, base, size );
1657 psaux->t1_decrypt( temp, size, 4330 );
1658 size -= face->type1.private_dict.lenIV;
1659 error = T1_Add_Table( code_table, n,
1660 temp + face->type1.private_dict.lenIV, size );
1661 FT_FREE( temp );
1662 }
1663 else
1664 error = T1_Add_Table( code_table, n, base, size );
1665 if ( error )
1666 goto Fail;
1667
1668 n++;
1669 }
1670 }
1671
1672 loader->num_glyphs = n;
1673
1674 /* if /.notdef is found but does not occupy index 0, do our magic. */
1675 if ( notdef_found &&
1676 ft_strcmp( ".notdef", (const char*)name_table->elements[0] ) )
1677 {
1678 /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
1679 /* name and code entries to swap_table. Then place notdef_index */
1680 /* name and code entries into swap_table. Then swap name and code */
1681 /* entries at indices notdef_index and 0 using values stored in */
1682 /* swap_table. */
1683
1684 /* Index 0 name */
1685 error = T1_Add_Table( swap_table, 0,
1686 name_table->elements[0],
1687 name_table->lengths [0] );
1688 if ( error )
1689 goto Fail;
1690
1691 /* Index 0 code */
1692 error = T1_Add_Table( swap_table, 1,
1693 code_table->elements[0],
1694 code_table->lengths [0] );
1695 if ( error )
1696 goto Fail;
1697
1698 /* Index notdef_index name */
1699 error = T1_Add_Table( swap_table, 2,
1700 name_table->elements[notdef_index],
1701 name_table->lengths [notdef_index] );
1702 if ( error )
1703 goto Fail;
1704
1705 /* Index notdef_index code */
1706 error = T1_Add_Table( swap_table, 3,
1707 code_table->elements[notdef_index],
1708 code_table->lengths [notdef_index] );
1709 if ( error )
1710 goto Fail;
1711
1712 error = T1_Add_Table( name_table, notdef_index,
1713 swap_table->elements[0],
1714 swap_table->lengths [0] );
1715 if ( error )
1716 goto Fail;
1717
1718 error = T1_Add_Table( code_table, notdef_index,
1719 swap_table->elements[1],
1720 swap_table->lengths [1] );
1721 if ( error )
1722 goto Fail;
1723
1724 error = T1_Add_Table( name_table, 0,
1725 swap_table->elements[2],
1726 swap_table->lengths [2] );
1727 if ( error )
1728 goto Fail;
1729
1730 error = T1_Add_Table( code_table, 0,
1731 swap_table->elements[3],
1732 swap_table->lengths [3] );
1733 if ( error )
1734 goto Fail;
1735
1736 }
1737 else if ( !notdef_found )
1738 {
1739 /* notdef_index is already 0, or /.notdef is undefined in */
1740 /* charstrings dictionary. Worry about /.notdef undefined. */
1741 /* We take index 0 and add it to the end of the table(s) */
1742 /* and add our own /.notdef glyph to index 0. */
1743
1744 /* 0 333 hsbw endchar */
1745 FT_Byte notdef_glyph[] = { 0x8B, 0xF7, 0xE1, 0x0D, 0x0E };
1746 char* notdef_name = (char *)".notdef";
1747
1748
1749 error = T1_Add_Table( swap_table, 0,
1750 name_table->elements[0],
1751 name_table->lengths [0] );
1752 if ( error )
1753 goto Fail;
1754
1755 error = T1_Add_Table( swap_table, 1,
1756 code_table->elements[0],
1757 code_table->lengths [0] );
1758 if ( error )
1759 goto Fail;
1760
1761 error = T1_Add_Table( name_table, 0, notdef_name, 8 );
1762 if ( error )
1763 goto Fail;
1764
1765 error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );
1766
1767 if ( error )
1768 goto Fail;
1769
1770 error = T1_Add_Table( name_table, n,
1771 swap_table->elements[0],
1772 swap_table->lengths [0] );
1773 if ( error )
1774 goto Fail;
1775
1776 error = T1_Add_Table( code_table, n,
1777 swap_table->elements[1],
1778 swap_table->lengths [1] );
1779 if ( error )
1780 goto Fail;
1781
1782 /* we added a glyph. */
1783 loader->num_glyphs += 1;
1784 }
1785
1786 return;
1787
1788 Fail:
1789 parser->root.error = error;
1790 }
1791
1792
1793 /*************************************************************************/
1794 /* */
1795 /* Define the token field static variables. This is a set of */
1796 /* T1_FieldRec variables. */
1797 /* */
1798 /*************************************************************************/
1799
1800
1801 static
1802 const T1_FieldRec t1_keywords[] =
1803 {
1804
1805 #include "t1tokens.h"
1806
1807 /* now add the special functions... */
1808 T1_FIELD_CALLBACK( "FontMatrix", t1_parse_font_matrix,
1809 T1_FIELD_DICT_FONTDICT )
1810 T1_FIELD_CALLBACK( "Encoding", parse_encoding,
1811 T1_FIELD_DICT_FONTDICT )
1812 T1_FIELD_CALLBACK( "Subrs", parse_subrs,
1813 T1_FIELD_DICT_PRIVATE )
1814 T1_FIELD_CALLBACK( "CharStrings", parse_charstrings,
1815 T1_FIELD_DICT_PRIVATE )
1816 T1_FIELD_CALLBACK( "Private", parse_private,
1817 T1_FIELD_DICT_FONTDICT )
1818
1819 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
1820 T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions,
1821 T1_FIELD_DICT_FONTDICT )
1822 T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map,
1823 T1_FIELD_DICT_FONTDICT )
1824 T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types,
1825 T1_FIELD_DICT_FONTDICT )
1826 T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector,
1827 T1_FIELD_DICT_FONTDICT )
1828 T1_FIELD_CALLBACK( "BuildCharArray", parse_buildchar,
1829 T1_FIELD_DICT_PRIVATE )
1830 #endif
1831
1832 { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
1833 };
1834
1835
1836 #define T1_FIELD_COUNT \
1837 ( sizeof ( t1_keywords ) / sizeof ( t1_keywords[0] ) )
1838
1839
1840 static FT_Error
1841 parse_dict( T1_Face face,
1842 T1_Loader loader,
1843 FT_Byte* base,
1844 FT_Long size )
1845 {
1846 T1_Parser parser = &loader->parser;
1847 FT_Byte *limit, *start_binary = NULL;
1848 FT_Bool have_integer = 0;
1849
1850
1851 parser->root.cursor = base;
1852 parser->root.limit = base + size;
1853 parser->root.error = FT_Err_Ok;
1854
1855 limit = parser->root.limit;
1856
1857 T1_Skip_Spaces( parser );
1858
1859 while ( parser->root.cursor < limit )
1860 {
1861 FT_Byte* cur;
1862
1863
1864 cur = parser->root.cursor;
1865
1866 /* look for `eexec' */
1867 if ( IS_PS_TOKEN( cur, limit, "eexec" ) )
1868 break;
1869
1870 /* look for `closefile' which ends the eexec section */
1871 else if ( IS_PS_TOKEN( cur, limit, "closefile" ) )
1872 break;
1873
1874 /* in a synthetic font the base font starts after a */
1875 /* `FontDictionary' token that is placed after a Private dict */
1876 else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) )
1877 {
1878 if ( loader->keywords_encountered & T1_PRIVATE )
1879 loader->keywords_encountered |=
1880 T1_FONTDIR_AFTER_PRIVATE;
1881 parser->root.cursor += 13;
1882 }
1883
1884 /* check whether we have an integer */
1885 else if ( ft_isdigit( *cur ) )
1886 {
1887 start_binary = cur;
1888 T1_Skip_PS_Token( parser );
1889 if ( parser->root.error )
1890 goto Exit;
1891 have_integer = 1;
1892 }
1893
1894 /* in valid Type 1 fonts we don't see `RD' or `-|' directly */
1895 /* since those tokens are handled by parse_subrs and */
1896 /* parse_charstrings */
1897 else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' &&
1898 have_integer )
1899 {
1900 FT_Long s;
1901 FT_Byte* b;
1902
1903
1904 parser->root.cursor = start_binary;
1905 if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) )
1906 return FT_THROW( Invalid_File_Format );
1907 have_integer = 0;
1908 }
1909
1910 else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' &&
1911 have_integer )
1912 {
1913 FT_Long s;
1914 FT_Byte* b;
1915
1916
1917 parser->root.cursor = start_binary;
1918 if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) )
1919 return FT_THROW( Invalid_File_Format );
1920 have_integer = 0;
1921 }
1922
1923 /* look for immediates */
1924 else if ( *cur == '/' && cur + 2 < limit )
1925 {
1926 FT_PtrDist len;
1927
1928
1929 cur++;
1930
1931 parser->root.cursor = cur;
1932 T1_Skip_PS_Token( parser );
1933 if ( parser->root.error )
1934 goto Exit;
1935
1936 len = parser->root.cursor - cur;
1937
1938 if ( len > 0 && len < 22 && parser->root.cursor < limit )
1939 {
1940 /* now compare the immediate name to the keyword table */
1941 T1_Field keyword = (T1_Field)t1_keywords;
1942
1943
1944 for (;;)
1945 {
1946 FT_Byte* name;
1947
1948
1949 name = (FT_Byte*)keyword->ident;
1950 if ( !name )
1951 break;
1952
1953 if ( cur[0] == name[0] &&
1954 len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
1955 ft_memcmp( cur, name, len ) == 0 )
1956 {
1957 /* We found it -- run the parsing callback! */
1958 /* We record every instance of every field */
1959 /* (until we reach the base font of a */
1960 /* synthetic font) to deal adequately with */
1961 /* multiple master fonts; this is also */
1962 /* necessary because later PostScript */
1963 /* definitions override earlier ones. */
1964
1965 /* Once we encounter `FontDirectory' after */
1966 /* `/Private', we know that this is a synthetic */
1967 /* font; except for `/CharStrings' we are not */
1968 /* interested in anything that follows this */
1969 /* `FontDirectory'. */
1970
1971 /* MM fonts have more than one /Private token at */
1972 /* the top level; let's hope that all the junk */
1973 /* that follows the first /Private token is not */
1974 /* interesting to us. */
1975
1976 /* According to Adobe Tech Note #5175 (CID-Keyed */
1977 /* Font Installation for ATM Software) a `begin' */
1978 /* must be followed by exactly one `end', and */
1979 /* `begin' -- `end' pairs must be accurately */
1980 /* paired. We could use this to distinguish */
1981 /* between the global Private and the Private */
1982 /* dict that is a member of the Blend dict. */
1983
1984 const FT_UInt dict =
1985 ( loader->keywords_encountered & T1_PRIVATE )
1986 ? T1_FIELD_DICT_PRIVATE
1987 : T1_FIELD_DICT_FONTDICT;
1988
1989 if ( !( dict & keyword->dict ) )
1990 {
1991 FT_TRACE1(( "parse_dict: found `%s' but ignoring it"
1992 " since it is in the wrong dictionary\n",
1993 keyword->ident ));
1994 break;
1995 }
1996
1997 if ( !( loader->keywords_encountered &
1998 T1_FONTDIR_AFTER_PRIVATE ) ||
1999 ft_strcmp( (const char*)name, "CharStrings" ) == 0 )
2000 {
2001 parser->root.error = t1_load_keyword( face,
2002 loader,
2003 keyword );
2004 if ( parser->root.error != FT_Err_Ok )
2005 {
2006 if ( FT_ERR_EQ( parser->root.error, Ignore ) )
2007 parser->root.error = FT_Err_Ok;
2008 else
2009 return parser->root.error;
2010 }
2011 }
2012 break;
2013 }
2014
2015 keyword++;
2016 }
2017 }
2018
2019 have_integer = 0;
2020 }
2021 else
2022 {
2023 T1_Skip_PS_Token( parser );
2024 if ( parser->root.error )
2025 goto Exit;
2026 have_integer = 0;
2027 }
2028
2029 T1_Skip_Spaces( parser );
2030 }
2031
2032 Exit:
2033 return parser->root.error;
2034 }
2035
2036
2037 static void
2038 t1_init_loader( T1_Loader loader,
2039 T1_Face face )
2040 {
2041 FT_UNUSED( face );
2042
2043 FT_MEM_ZERO( loader, sizeof ( *loader ) );
2044 loader->num_glyphs = 0;
2045 loader->num_chars = 0;
2046
2047 /* initialize the tables -- simply set their `init' field to 0 */
2048 loader->encoding_table.init = 0;
2049 loader->charstrings.init = 0;
2050 loader->glyph_names.init = 0;
2051 loader->subrs.init = 0;
2052 loader->swap_table.init = 0;
2053 loader->fontdata = 0;
2054 loader->keywords_encountered = 0;
2055 }
2056
2057
2058 static void
2059 t1_done_loader( T1_Loader loader )
2060 {
2061 T1_Parser parser = &loader->parser;
2062
2063
2064 /* finalize tables */
2065 T1_Release_Table( &loader->encoding_table );
2066 T1_Release_Table( &loader->charstrings );
2067 T1_Release_Table( &loader->glyph_names );
2068 T1_Release_Table( &loader->swap_table );
2069 T1_Release_Table( &loader->subrs );
2070
2071 /* finalize parser */
2072 T1_Finalize_Parser( parser );
2073 }
2074
2075
2076 FT_LOCAL_DEF( FT_Error )
2077 T1_Open_Face( T1_Face face )
2078 {
2079 T1_LoaderRec loader;
2080 T1_Parser parser;
2081 T1_Font type1 = &face->type1;
2082 PS_Private priv = &type1->private_dict;
2083 FT_Error error;
2084
2085 PSAux_Service psaux = (PSAux_Service)face->psaux;
2086
2087
2088 t1_init_loader( &loader, face );
2089
2090 /* default values */
2091 face->ndv_idx = -1;
2092 face->cdv_idx = -1;
2093 face->len_buildchar = 0;
2094
2095 priv->blue_shift = 7;
2096 priv->blue_fuzz = 1;
2097 priv->lenIV = 4;
2098 priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
2099 priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
2100
2101 parser = &loader.parser;
2102 error = T1_New_Parser( parser,
2103 face->root.stream,
2104 face->root.memory,
2105 psaux );
2106 if ( error )
2107 goto Exit;
2108
2109 error = parse_dict( face, &loader,
2110 parser->base_dict, parser->base_len );
2111 if ( error )
2112 goto Exit;
2113
2114 error = T1_Get_Private_Dict( parser, psaux );
2115 if ( error )
2116 goto Exit;
2117
2118 error = parse_dict( face, &loader,
2119 parser->private_dict, parser->private_len );
2120 if ( error )
2121 goto Exit;
2122
2123 /* ensure even-ness of `num_blue_values' */
2124 priv->num_blue_values &= ~1;
2125
2126 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
2127
2128 if ( face->blend &&
2129 face->blend->num_default_design_vector != 0 &&
2130 face->blend->num_default_design_vector != face->blend->num_axis )
2131 {
2132 /* we don't use it currently so just warn, reset, and ignore */
2133 FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries "
2134 "while there are %u axes.\n",
2135 face->blend->num_default_design_vector,
2136 face->blend->num_axis ));
2137
2138 face->blend->num_default_design_vector = 0;
2139 }
2140
2141 /* the following can happen for MM instances; we then treat the */
2142 /* font as a normal PS font */
2143 if ( face->blend &&
2144 ( !face->blend->num_designs || !face->blend->num_axis ) )
2145 T1_Done_Blend( face );
2146
2147 /* another safety check */
2148 if ( face->blend )
2149 {
2150 FT_UInt i;
2151
2152
2153 for ( i = 0; i < face->blend->num_axis; i++ )
2154 if ( !face->blend->design_map[i].num_points )
2155 {
2156 T1_Done_Blend( face );
2157 break;
2158 }
2159 }
2160
2161 if ( face->blend )
2162 {
2163 if ( face->len_buildchar > 0 )
2164 {
2165 FT_Memory memory = face->root.memory;
2166
2167
2168 if ( FT_NEW_ARRAY( face->buildchar, face->len_buildchar ) )
2169 {
2170 FT_ERROR(( "T1_Open_Face: cannot allocate BuildCharArray\n" ));
2171 face->len_buildchar = 0;
2172 goto Exit;
2173 }
2174 }
2175 }
2176 else
2177 face->len_buildchar = 0;
2178
2179 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
2180
2181 /* now, propagate the subrs, charstrings, and glyphnames tables */
2182 /* to the Type1 data */
2183 type1->num_glyphs = loader.num_glyphs;
2184
2185 if ( loader.subrs.init )
2186 {
2187 loader.subrs.init = 0;
2188 type1->num_subrs = loader.num_subrs;
2189 type1->subrs_block = loader.subrs.block;
2190 type1->subrs = loader.subrs.elements;
2191 type1->subrs_len = loader.subrs.lengths;
2192 }
2193
2194 if ( !IS_INCREMENTAL )
2195 if ( !loader.charstrings.init )
2196 {
2197 FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face\n" ));
2198 error = FT_THROW( Invalid_File_Format );
2199 }
2200
2201 loader.charstrings.init = 0;
2202 type1->charstrings_block = loader.charstrings.block;
2203 type1->charstrings = loader.charstrings.elements;
2204 type1->charstrings_len = loader.charstrings.lengths;
2205
2206 /* we copy the glyph names `block' and `elements' fields; */
2207 /* the `lengths' field must be released later */
2208 type1->glyph_names_block = loader.glyph_names.block;
2209 type1->glyph_names = (FT_String**)loader.glyph_names.elements;
2210 loader.glyph_names.block = 0;
2211 loader.glyph_names.elements = 0;
2212
2213 /* we must now build type1.encoding when we have a custom array */
2214 if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
2215 {
2216 FT_Int charcode, idx, min_char, max_char;
2217 FT_Byte* glyph_name;
2218
2219
2220 /* OK, we do the following: for each element in the encoding */
2221 /* table, look up the index of the glyph having the same name */
2222 /* the index is then stored in type1.encoding.char_index, and */
2223 /* the name to type1.encoding.char_name */
2224
2225 min_char = 0;
2226 max_char = 0;
2227
2228 charcode = 0;
2229 for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
2230 {
2231 FT_Byte* char_name;
2232
2233
2234 type1->encoding.char_index[charcode] = 0;
2235 type1->encoding.char_name [charcode] = (char *)".notdef";
2236
2237 char_name = loader.encoding_table.elements[charcode];
2238 if ( char_name )
2239 for ( idx = 0; idx < type1->num_glyphs; idx++ )
2240 {
2241 glyph_name = (FT_Byte*)type1->glyph_names[idx];
2242 if ( ft_strcmp( (const char*)char_name,
2243 (const char*)glyph_name ) == 0 )
2244 {
2245 type1->encoding.char_index[charcode] = (FT_UShort)idx;
2246 type1->encoding.char_name [charcode] = (char*)glyph_name;
2247
2248 /* Change min/max encoded char only if glyph name is */
2249 /* not /.notdef */
2250 if ( ft_strcmp( (const char*)".notdef",
2251 (const char*)glyph_name ) != 0 )
2252 {
2253 if ( charcode < min_char )
2254 min_char = charcode;
2255 if ( charcode >= max_char )
2256 max_char = charcode + 1;
2257 }
2258 break;
2259 }
2260 }
2261 }
2262
2263 type1->encoding.code_first = min_char;
2264 type1->encoding.code_last = max_char;
2265 type1->encoding.num_chars = loader.num_chars;
2266 }
2267
2268 Exit:
2269 t1_done_loader( &loader );
2270 return error;
2271 }
2272
2273
2274 /* END */