zenilib: zenilib/jni/external/freetype2/src/type1/t1load.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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