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