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