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