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