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