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