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