w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

t1decode.c
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * t1decode.c
4  *
5  * PostScript Type 1 decoding routines (body).
6  *
7  * Copyright (C) 2000-2020 by
8  * David Turner, Robert Wilhelm, and Werner Lemberg.
9  *
10  * This file is part of the FreeType project, and may only be used,
11  * modified, and distributed under the terms of the FreeType project
12  * license, LICENSE.TXT. By continuing to use, modify, or distribute
13  * this file you indicate that you have read the license and
14  * understand and accept it fully.
15  *
16  */
17 
18 
19 #include <freetype/internal/ftcalc.h>
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/pshints.h>
22 #include <freetype/internal/fthash.h>
23 #include <freetype/ftoutln.h>
24 
25 #include "t1decode.h"
26 #include "psobjs.h"
27 
28 #include "psauxerr.h"
29 
30 /* ensure proper sign extension */
31 #define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) )
32 
33  /**************************************************************************
34  *
35  * The macro FT_COMPONENT is used in trace mode. It is an implicit
36  * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
37  * messages during execution.
38  */
39 #undef FT_COMPONENT
40 #define FT_COMPONENT t1decode
41 
42 
43  typedef enum T1_Operator_
44  {
45  op_none = 0,
72 
73  op_max /* never remove this one */
74 
76 
77 
78  static
80  {
81  0, /* none */
82  0, /* endchar */
83  2, /* hsbw */
84  5, /* seac */
85  4, /* sbw */
86  0, /* closepath */
87  1, /* hlineto */
88  1, /* hmoveto */
89  4, /* hvcurveto */
90  2, /* rlineto */
91  2, /* rmoveto */
92  6, /* rrcurveto */
93  4, /* vhcurveto */
94  1, /* vlineto */
95  1, /* vmoveto */
96  0, /* dotsection */
97  2, /* hstem */
98  6, /* hstem3 */
99  2, /* vstem */
100  6, /* vstem3 */
101  2, /* div */
102  -1, /* callothersubr */
103  1, /* callsubr */
104  0, /* pop */
105  0, /* return */
106  2, /* setcurrentpoint */
107  2 /* opcode 15 (undocumented and obsolete) */
108  };
109 
110 
111  /**************************************************************************
112  *
113  * @Function:
114  * t1_lookup_glyph_by_stdcharcode_ps
115  *
116  * @Description:
117  * Looks up a given glyph by its StandardEncoding charcode. Used to
118  * implement the SEAC Type 1 operator in the Adobe engine
119  *
120  * @Input:
121  * face ::
122  * The current face object.
123  *
124  * charcode ::
125  * The character code to look for.
126  *
127  * @Return:
128  * A glyph index in the font face. Returns -1 if the corresponding
129  * glyph wasn't found.
130  */
133  FT_Int charcode )
134  {
135  FT_UInt n;
136  const FT_String* glyph_name;
137  FT_Service_PsCMaps psnames = decoder->psnames;
138 
139 
140  /* check range of standard char code */
141  if ( charcode < 0 || charcode > 255 )
142  return -1;
143 
144  glyph_name = psnames->adobe_std_strings(
145  psnames->adobe_std_encoding[charcode]);
146 
147  for ( n = 0; n < decoder->num_glyphs; n++ )
148  {
149  FT_String* name = (FT_String*)decoder->glyph_names[n];
150 
151 
152  if ( name &&
153  name[0] == glyph_name[0] &&
154  ft_strcmp( name, glyph_name ) == 0 )
155  return (FT_Int)n;
156  }
157 
158  return -1;
159  }
160 
161 
162 #ifdef T1_CONFIG_OPTION_OLD_ENGINE
163 
164  /**************************************************************************
165  *
166  * @Function:
167  * t1_lookup_glyph_by_stdcharcode
168  *
169  * @Description:
170  * Looks up a given glyph by its StandardEncoding charcode. Used to
171  * implement the SEAC Type 1 operator.
172  *
173  * @Input:
174  * face ::
175  * The current face object.
176  *
177  * charcode ::
178  * The character code to look for.
179  *
180  * @Return:
181  * A glyph index in the font face. Returns -1 if the corresponding
182  * glyph wasn't found.
183  */
184  static FT_Int
185  t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder,
186  FT_Int charcode )
187  {
188  FT_UInt n;
189  const FT_String* glyph_name;
190  FT_Service_PsCMaps psnames = decoder->psnames;
191 
192 
193  /* check range of standard char code */
194  if ( charcode < 0 || charcode > 255 )
195  return -1;
196 
197  glyph_name = psnames->adobe_std_strings(
198  psnames->adobe_std_encoding[charcode]);
199 
200  for ( n = 0; n < decoder->num_glyphs; n++ )
201  {
202  FT_String* name = (FT_String*)decoder->glyph_names[n];
203 
204 
205  if ( name &&
206  name[0] == glyph_name[0] &&
207  ft_strcmp( name, glyph_name ) == 0 )
208  return (FT_Int)n;
209  }
210 
211  return -1;
212  }
213 
214 
215  /* parse a single Type 1 glyph */
217  t1_decoder_parse_glyph( T1_Decoder decoder,
218  FT_UInt glyph )
219  {
220  return decoder->parse_callback( decoder, glyph );
221  }
222 
223 
224  /**************************************************************************
225  *
226  * @Function:
227  * t1operator_seac
228  *
229  * @Description:
230  * Implements the `seac' Type 1 operator for a Type 1 decoder.
231  *
232  * @Input:
233  * decoder ::
234  * The current CID decoder.
235  *
236  * asb ::
237  * The accent's side bearing.
238  *
239  * adx ::
240  * The horizontal offset of the accent.
241  *
242  * ady ::
243  * The vertical offset of the accent.
244  *
245  * bchar ::
246  * The base character's StandardEncoding charcode.
247  *
248  * achar ::
249  * The accent character's StandardEncoding charcode.
250  *
251  * @Return:
252  * FreeType error code. 0 means success.
253  */
254  static FT_Error
255  t1operator_seac( T1_Decoder decoder,
256  FT_Pos asb,
257  FT_Pos adx,
258  FT_Pos ady,
259  FT_Int bchar,
260  FT_Int achar )
261  {
262  FT_Error error;
263  FT_Int bchar_index, achar_index;
264 #if 0
265  FT_Int n_base_points;
266  FT_Outline* base = decoder->builder.base;
267 #endif
268  FT_Vector left_bearing, advance;
269 
270 #ifdef FT_CONFIG_OPTION_INCREMENTAL
271  T1_Face face = (T1_Face)decoder->builder.face;
272 #endif
273 
274 
275  if ( decoder->seac )
276  {
277  FT_ERROR(( "t1operator_seac: invalid nested seac\n" ));
278  return FT_THROW( Syntax_Error );
279  }
280 
281  if ( decoder->builder.metrics_only )
282  {
283  FT_ERROR(( "t1operator_seac: unexpected seac\n" ));
284  return FT_THROW( Syntax_Error );
285  }
286 
287  /* seac weirdness */
288  adx += decoder->builder.left_bearing.x;
289 
290  /* `glyph_names' is set to 0 for CID fonts which do not */
291  /* include an encoding. How can we deal with these? */
292 #ifdef FT_CONFIG_OPTION_INCREMENTAL
293  if ( decoder->glyph_names == 0 &&
294  !face->root.internal->incremental_interface )
295 #else
296  if ( decoder->glyph_names == 0 )
297 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
298  {
299  FT_ERROR(( "t1operator_seac:"
300  " glyph names table not available in this font\n" ));
301  return FT_THROW( Syntax_Error );
302  }
303 
304 #ifdef FT_CONFIG_OPTION_INCREMENTAL
305  if ( face->root.internal->incremental_interface )
306  {
307  /* the caller must handle the font encoding also */
308  bchar_index = bchar;
309  achar_index = achar;
310  }
311  else
312 #endif
313  {
314  bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
315  achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
316  }
317 
318  if ( bchar_index < 0 || achar_index < 0 )
319  {
320  FT_ERROR(( "t1operator_seac:"
321  " invalid seac character code arguments\n" ));
322  return FT_THROW( Syntax_Error );
323  }
324 
325  /* if we are trying to load a composite glyph, do not load the */
326  /* accent character and return the array of subglyphs. */
327  if ( decoder->builder.no_recurse )
328  {
330  FT_GlyphLoader loader = glyph->internal->loader;
331  FT_SubGlyph subg;
332 
333 
334  /* reallocate subglyph array if necessary */
335  error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
336  if ( error )
337  goto Exit;
338 
339  subg = loader->current.subglyphs;
340 
341  /* subglyph 0 = base character */
342  subg->index = bchar_index;
345  subg->arg1 = 0;
346  subg->arg2 = 0;
347  subg++;
348 
349  /* subglyph 1 = accent character */
350  subg->index = achar_index;
352  subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb );
353  subg->arg2 = (FT_Int)FIXED_TO_INT( ady );
354 
355  /* set up remaining glyph fields */
356  glyph->num_subglyphs = 2;
357  glyph->subglyphs = loader->base.subglyphs;
359 
360  loader->current.num_subglyphs = 2;
361  goto Exit;
362  }
363 
364  /* First load `bchar' in builder */
365  /* now load the unscaled outline */
366 
367  FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
368 
369  /* save the left bearing and width of the SEAC */
370  /* glyph as they will be erased by the next load */
371 
372  left_bearing = decoder->builder.left_bearing;
373  advance = decoder->builder.advance;
374 
375  /* the seac operator must not be nested */
376  decoder->seac = TRUE;
377  error = t1_decoder_parse_glyph( decoder, (FT_UInt)bchar_index );
378  decoder->seac = FALSE;
379  if ( error )
380  goto Exit;
381 
382  /* If the SEAC glyph doesn't have a (H)SBW of its */
383  /* own use the values from the base glyph. */
384 
385  if ( decoder->builder.parse_state != T1_Parse_Have_Width )
386  {
387  left_bearing = decoder->builder.left_bearing;
388  advance = decoder->builder.advance;
389  }
390 
391  decoder->builder.left_bearing.x = 0;
392  decoder->builder.left_bearing.y = 0;
393 
394  decoder->builder.pos_x = adx - asb;
395  decoder->builder.pos_y = ady;
396 
397  /* Now load `achar' on top of */
398  /* the base outline */
399 
400  /* the seac operator must not be nested */
401  decoder->seac = TRUE;
402  error = t1_decoder_parse_glyph( decoder, (FT_UInt)achar_index );
403  decoder->seac = FALSE;
404  if ( error )
405  goto Exit;
406 
407  /* restore the left side bearing and advance width */
408  /* of the SEAC glyph or base character (saved above) */
409 
410  decoder->builder.left_bearing = left_bearing;
411  decoder->builder.advance = advance;
412 
413  decoder->builder.pos_x = 0;
414  decoder->builder.pos_y = 0;
415 
416  Exit:
417  return error;
418  }
419 
420 
421  /**************************************************************************
422  *
423  * @Function:
424  * t1_decoder_parse_charstrings
425  *
426  * @Description:
427  * Parses a given Type 1 charstrings program.
428  *
429  * @Input:
430  * decoder ::
431  * The current Type 1 decoder.
432  *
433  * charstring_base ::
434  * The base address of the charstring stream.
435  *
436  * charstring_len ::
437  * The length in bytes of the charstring stream.
438  *
439  * @Return:
440  * FreeType error code. 0 means success.
441  */
443  t1_decoder_parse_charstrings( T1_Decoder decoder,
444  FT_Byte* charstring_base,
445  FT_UInt charstring_len )
446  {
447  FT_Error error;
449  FT_Byte* ip;
450  FT_Byte* limit;
451  T1_Builder builder = &decoder->builder;
452  FT_Pos x, y, orig_x, orig_y;
453  FT_Int known_othersubr_result_cnt = 0;
454  FT_Int unknown_othersubr_result_cnt = 0;
455  FT_Bool large_int;
456  FT_Fixed seed;
457 
458  T1_Hints_Funcs hinter;
459 
460 #ifdef FT_DEBUG_LEVEL_TRACE
461  FT_Bool bol = TRUE;
462 #endif
463 
464 
465  /* compute random seed from stack address of parameter */
466  seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed ^
467  (FT_Offset)(char*)&decoder ^
468  (FT_Offset)(char*)&charstring_base ) &
469  FT_ULONG_MAX );
470  seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
471  if ( seed == 0 )
472  seed = 0x7384;
473 
474  /* First of all, initialize the decoder */
475  decoder->top = decoder->stack;
476  decoder->zone = decoder->zones;
477  zone = decoder->zones;
478 
479  builder->parse_state = T1_Parse_Start;
480 
481  hinter = (T1_Hints_Funcs)builder->hints_funcs;
482 
483  /* a font that reads BuildCharArray without setting */
484  /* its values first is buggy, but ... */
485  FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
486  ( decoder->buildchar == NULL ) );
487 
488  if ( decoder->buildchar && decoder->len_buildchar > 0 )
489  FT_ARRAY_ZERO( decoder->buildchar, decoder->len_buildchar );
490 
491  zone->base = charstring_base;
492  limit = zone->limit = charstring_base + charstring_len;
493  ip = zone->cursor = zone->base;
494 
495  error = FT_Err_Ok;
496 
497  x = orig_x = builder->pos_x;
498  y = orig_y = builder->pos_y;
499 
500  /* begin hints recording session, if any */
501  if ( hinter )
502  hinter->open( hinter->hints );
503 
504  large_int = FALSE;
505 
506  /* now, execute loop */
507  while ( ip < limit )
508  {
509  FT_Long* top = decoder->top;
511  FT_Int32 value = 0;
512 
513 
514  FT_ASSERT( known_othersubr_result_cnt == 0 ||
515  unknown_othersubr_result_cnt == 0 );
516 
517 #ifdef FT_DEBUG_LEVEL_TRACE
518  if ( bol )
519  {
520  FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
521  bol = FALSE;
522  }
523 #endif
524 
525  /**********************************************************************
526  *
527  * Decode operator or operand
528  *
529  */
530 
531  /* first of all, decompress operator or value */
532  switch ( *ip++ )
533  {
534  case 1:
535  op = op_hstem;
536  break;
537 
538  case 3:
539  op = op_vstem;
540  break;
541  case 4:
542  op = op_vmoveto;
543  break;
544  case 5:
545  op = op_rlineto;
546  break;
547  case 6:
548  op = op_hlineto;
549  break;
550  case 7:
551  op = op_vlineto;
552  break;
553  case 8:
554  op = op_rrcurveto;
555  break;
556  case 9:
557  op = op_closepath;
558  break;
559  case 10:
560  op = op_callsubr;
561  break;
562  case 11:
563  op = op_return;
564  break;
565 
566  case 13:
567  op = op_hsbw;
568  break;
569  case 14:
570  op = op_endchar;
571  break;
572 
573  case 15: /* undocumented, obsolete operator */
574  op = op_unknown15;
575  break;
576 
577  case 21:
578  op = op_rmoveto;
579  break;
580  case 22:
581  op = op_hmoveto;
582  break;
583 
584  case 30:
585  op = op_vhcurveto;
586  break;
587  case 31:
588  op = op_hvcurveto;
589  break;
590 
591  case 12:
592  if ( ip >= limit )
593  {
594  FT_ERROR(( "t1_decoder_parse_charstrings:"
595  " invalid escape (12+EOF)\n" ));
596  goto Syntax_Error;
597  }
598 
599  switch ( *ip++ )
600  {
601  case 0:
602  op = op_dotsection;
603  break;
604  case 1:
605  op = op_vstem3;
606  break;
607  case 2:
608  op = op_hstem3;
609  break;
610  case 6:
611  op = op_seac;
612  break;
613  case 7:
614  op = op_sbw;
615  break;
616  case 12:
617  op = op_div;
618  break;
619  case 16:
621  break;
622  case 17:
623  op = op_pop;
624  break;
625  case 33:
627  break;
628 
629  default:
630  FT_ERROR(( "t1_decoder_parse_charstrings:"
631  " invalid escape (12+%d)\n",
632  ip[-1] ));
633  goto Syntax_Error;
634  }
635  break;
636 
637  case 255: /* four bytes integer */
638  if ( ip + 4 > limit )
639  {
640  FT_ERROR(( "t1_decoder_parse_charstrings:"
641  " unexpected EOF in integer\n" ));
642  goto Syntax_Error;
643  }
644 
645  value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
646  ( (FT_UInt32)ip[1] << 16 ) |
647  ( (FT_UInt32)ip[2] << 8 ) |
648  (FT_UInt32)ip[3] );
649  ip += 4;
650 
651  /* According to the specification, values > 32000 or < -32000 must */
652  /* be followed by a `div' operator to make the result be in the */
653  /* range [-32000;32000]. We expect that the second argument of */
654  /* `div' is not a large number. Additionally, we don't handle */
655  /* stuff like `<large1> <large2> <num> div <num> div' or */
656  /* <large1> <large2> <num> div div'. This is probably not allowed */
657  /* anyway. */
658  if ( value > 32000 || value < -32000 )
659  {
660  if ( large_int )
661  FT_ERROR(( "t1_decoder_parse_charstrings:"
662  " no `div' after large integer\n" ));
663  else
664  large_int = TRUE;
665  }
666  else
667  {
668  if ( !large_int )
669  value = (FT_Int32)( (FT_UInt32)value << 16 );
670  }
671 
672  break;
673 
674  default:
675  if ( ip[-1] >= 32 )
676  {
677  if ( ip[-1] < 247 )
678  value = (FT_Int32)ip[-1] - 139;
679  else
680  {
681  if ( ++ip > limit )
682  {
683  FT_ERROR(( "t1_decoder_parse_charstrings:"
684  " unexpected EOF in integer\n" ));
685  goto Syntax_Error;
686  }
687 
688  if ( ip[-2] < 251 )
689  value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108;
690  else
691  value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
692  }
693 
694  if ( !large_int )
695  value = (FT_Int32)( (FT_UInt32)value << 16 );
696  }
697  else
698  {
699  FT_ERROR(( "t1_decoder_parse_charstrings:"
700  " invalid byte (%d)\n", ip[-1] ));
701  goto Syntax_Error;
702  }
703  }
704 
705  if ( unknown_othersubr_result_cnt > 0 )
706  {
707  switch ( op )
708  {
709  case op_callsubr:
710  case op_return:
711  case op_none:
712  case op_pop:
713  break;
714 
715  default:
716  /* all operands have been transferred by previous pops */
717  unknown_othersubr_result_cnt = 0;
718  break;
719  }
720  }
721 
722  if ( large_int && !( op == op_none || op == op_div ) )
723  {
724  FT_ERROR(( "t1_decoder_parse_charstrings:"
725  " no `div' after large integer\n" ));
726 
727  large_int = FALSE;
728  }
729 
730  /**********************************************************************
731  *
732  * Push value on stack, or process operator
733  *
734  */
735  if ( op == op_none )
736  {
737  if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
738  {
739  FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" ));
740  goto Syntax_Error;
741  }
742 
743 #ifdef FT_DEBUG_LEVEL_TRACE
744  if ( large_int )
745  FT_TRACE4(( " %d", value ));
746  else
747  FT_TRACE4(( " %d", value / 65536 ));
748 #endif
749 
750  *top++ = value;
751  decoder->top = top;
752  }
753  else if ( op == op_callothersubr ) /* callothersubr */
754  {
755  FT_Int subr_no;
756  FT_Int arg_cnt;
757 
758 
759 #ifdef FT_DEBUG_LEVEL_TRACE
760  FT_TRACE4(( " callothersubr\n" ));
761  bol = TRUE;
762 #endif
763 
764  if ( top - decoder->stack < 2 )
765  goto Stack_Underflow;
766 
767  top -= 2;
768 
769  subr_no = Fix2Int( top[1] );
770  arg_cnt = Fix2Int( top[0] );
771 
772  /************************************************************
773  *
774  * remove all operands to callothersubr from the stack
775  *
776  * for handled othersubrs, where we know the number of
777  * arguments, we increase the stack by the value of
778  * known_othersubr_result_cnt
779  *
780  * for unhandled othersubrs the following pops adjust the
781  * stack pointer as necessary
782  */
783 
784  if ( arg_cnt > top - decoder->stack )
785  goto Stack_Underflow;
786 
787  top -= arg_cnt;
788 
789  known_othersubr_result_cnt = 0;
790  unknown_othersubr_result_cnt = 0;
791 
792  /* XXX TODO: The checks to `arg_count == <whatever>' */
793  /* might not be correct; an othersubr expects a certain */
794  /* number of operands on the PostScript stack (as opposed */
795  /* to the T1 stack) but it doesn't have to put them there */
796  /* by itself; previous othersubrs might have left the */
797  /* operands there if they were not followed by an */
798  /* appropriate number of pops */
799  /* */
800  /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
801  /* accept a font that contains charstrings like */
802  /* */
803  /* 100 200 2 20 callothersubr */
804  /* 300 1 20 callothersubr pop */
805  /* */
806  /* Perhaps this is the reason why BuildCharArray exists. */
807 
808  switch ( subr_no )
809  {
810  case 0: /* end flex feature */
811  if ( arg_cnt != 3 )
812  goto Unexpected_OtherSubr;
813 
814  if ( !decoder->flex_state ||
815  decoder->num_flex_vectors != 7 )
816  {
817  FT_ERROR(( "t1_decoder_parse_charstrings:"
818  " unexpected flex end\n" ));
819  goto Syntax_Error;
820  }
821 
822  /* the two `results' are popped by the following setcurrentpoint */
823  top[0] = x;
824  top[1] = y;
825  known_othersubr_result_cnt = 2;
826  break;
827 
828  case 1: /* start flex feature */
829  if ( arg_cnt != 0 )
830  goto Unexpected_OtherSubr;
831 
832  if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
833  FT_SET_ERROR( t1_builder_check_points( builder, 6 ) ) )
834  goto Fail;
835 
836  decoder->flex_state = 1;
837  decoder->num_flex_vectors = 0;
838  break;
839 
840  case 2: /* add flex vectors */
841  {
842  FT_Int idx;
843 
844 
845  if ( arg_cnt != 0 )
846  goto Unexpected_OtherSubr;
847 
848  if ( !decoder->flex_state )
849  {
850  FT_ERROR(( "t1_decoder_parse_charstrings:"
851  " missing flex start\n" ));
852  goto Syntax_Error;
853  }
854 
855  /* note that we should not add a point for index 0; */
856  /* this will move our current position to the flex */
857  /* point without adding any point to the outline */
858  idx = decoder->num_flex_vectors++;
859  if ( idx > 0 && idx < 7 )
860  {
861  /* in malformed fonts it is possible to have other */
862  /* opcodes in the middle of a flex (which don't */
863  /* increase `num_flex_vectors'); we thus have to */
864  /* check whether we can add a point */
865  if ( FT_SET_ERROR( t1_builder_check_points( builder, 1 ) ) )
866  goto Syntax_Error;
867 
868  t1_builder_add_point( builder,
869  x,
870  y,
871  (FT_Byte)( idx == 3 || idx == 6 ) );
872  }
873  }
874  break;
875 
876  case 3: /* change hints */
877  if ( arg_cnt != 1 )
878  goto Unexpected_OtherSubr;
879 
880  known_othersubr_result_cnt = 1;
881 
882  if ( hinter )
883  hinter->reset( hinter->hints,
884  (FT_UInt)builder->current->n_points );
885  break;
886 
887  case 12:
888  case 13:
889  /* counter control hints, clear stack */
890  top = decoder->stack;
891  break;
892 
893  case 14:
894  case 15:
895  case 16:
896  case 17:
897  case 18: /* multiple masters */
898  {
899  PS_Blend blend = decoder->blend;
900  FT_UInt num_points, nn, mm;
901  FT_Long* delta;
902  FT_Long* values;
903 
904 
905  if ( !blend )
906  {
907  FT_ERROR(( "t1_decoder_parse_charstrings:"
908  " unexpected multiple masters operator\n" ));
909  goto Syntax_Error;
910  }
911 
912  num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );
913  if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )
914  {
915  FT_ERROR(( "t1_decoder_parse_charstrings:"
916  " incorrect number of multiple masters arguments\n" ));
917  goto Syntax_Error;
918  }
919 
920  /* We want to compute */
921  /* */
922  /* a0*w0 + a1*w1 + ... + ak*wk */
923  /* */
924  /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */
925  /* */
926  /* However, given that w0 + w1 + ... + wk == 1, we can */
927  /* rewrite it easily as */
928  /* */
929  /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
930  /* */
931  /* where k == num_designs-1. */
932  /* */
933  /* I guess that's why it's written in this `compact' */
934  /* form. */
935  /* */
936  delta = top + num_points;
937  values = top;
938  for ( nn = 0; nn < num_points; nn++ )
939  {
940  FT_Long tmp = values[0];
941 
942 
943  for ( mm = 1; mm < blend->num_designs; mm++ )
944  tmp = ADD_LONG( tmp,
945  FT_MulFix( *delta++,
946  blend->weight_vector[mm] ) );
947 
948  *values++ = tmp;
949  }
950 
951  known_othersubr_result_cnt = (FT_Int)num_points;
952  break;
953  }
954 
955  case 19:
956  /* <idx> 1 19 callothersubr */
957  /* => replace elements starting from index cvi( <idx> ) */
958  /* of BuildCharArray with WeightVector */
959  {
960  FT_Int idx;
961  PS_Blend blend = decoder->blend;
962 
963 
964  if ( arg_cnt != 1 || !blend )
965  goto Unexpected_OtherSubr;
966 
967  idx = Fix2Int( top[0] );
968 
969  if ( idx < 0 ||
970  (FT_UInt)idx + blend->num_designs > decoder->len_buildchar )
971  goto Unexpected_OtherSubr;
972 
973  ft_memcpy( &decoder->buildchar[idx],
974  blend->weight_vector,
975  blend->num_designs *
976  sizeof ( blend->weight_vector[0] ) );
977  }
978  break;
979 
980  case 20:
981  /* <arg1> <arg2> 2 20 callothersubr pop */
982  /* ==> push <arg1> + <arg2> onto T1 stack */
983  if ( arg_cnt != 2 )
984  goto Unexpected_OtherSubr;
985 
986  top[0] = ADD_LONG( top[0], top[1] );
987 
988  known_othersubr_result_cnt = 1;
989  break;
990 
991  case 21:
992  /* <arg1> <arg2> 2 21 callothersubr pop */
993  /* ==> push <arg1> - <arg2> onto T1 stack */
994  if ( arg_cnt != 2 )
995  goto Unexpected_OtherSubr;
996 
997  top[0] = SUB_LONG( top[0], top[1] );
998 
999  known_othersubr_result_cnt = 1;
1000  break;
1001 
1002  case 22:
1003  /* <arg1> <arg2> 2 22 callothersubr pop */
1004  /* ==> push <arg1> * <arg2> onto T1 stack */
1005  if ( arg_cnt != 2 )
1006  goto Unexpected_OtherSubr;
1007 
1008  top[0] = FT_MulFix( top[0], top[1] );
1009 
1010  known_othersubr_result_cnt = 1;
1011  break;
1012 
1013  case 23:
1014  /* <arg1> <arg2> 2 23 callothersubr pop */
1015  /* ==> push <arg1> / <arg2> onto T1 stack */
1016  if ( arg_cnt != 2 || top[1] == 0 )
1017  goto Unexpected_OtherSubr;
1018 
1019  top[0] = FT_DivFix( top[0], top[1] );
1020 
1021  known_othersubr_result_cnt = 1;
1022  break;
1023 
1024  case 24:
1025  /* <val> <idx> 2 24 callothersubr */
1026  /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
1027  {
1028  FT_Int idx;
1029  PS_Blend blend = decoder->blend;
1030 
1031 
1032  if ( arg_cnt != 2 || !blend )
1033  goto Unexpected_OtherSubr;
1034 
1035  idx = Fix2Int( top[1] );
1036 
1037  if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
1038  goto Unexpected_OtherSubr;
1039 
1040  decoder->buildchar[idx] = top[0];
1041  }
1042  break;
1043 
1044  case 25:
1045  /* <idx> 1 25 callothersubr pop */
1046  /* ==> push BuildCharArray[cvi( idx )] */
1047  /* onto T1 stack */
1048  {
1049  FT_Int idx;
1050  PS_Blend blend = decoder->blend;
1051 
1052 
1053  if ( arg_cnt != 1 || !blend )
1054  goto Unexpected_OtherSubr;
1055 
1056  idx = Fix2Int( top[0] );
1057 
1058  if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
1059  goto Unexpected_OtherSubr;
1060 
1061  top[0] = decoder->buildchar[idx];
1062  }
1063 
1064  known_othersubr_result_cnt = 1;
1065  break;
1066 
1067 #if 0
1068  case 26:
1069  /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
1070  /* leave mark on T1 stack */
1071  /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */
1072  XXX which routine has left its mark on the (PostScript) stack?;
1073  break;
1074 #endif
1075 
1076  case 27:
1077  /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
1078  /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
1079  /* otherwise push <res2> */
1080  if ( arg_cnt != 4 )
1081  goto Unexpected_OtherSubr;
1082 
1083  if ( top[2] > top[3] )
1084  top[0] = top[1];
1085 
1086  known_othersubr_result_cnt = 1;
1087  break;
1088 
1089  case 28:
1090  /* 0 28 callothersubr pop */
1091  /* => push random value from interval [0, 1) onto stack */
1092  if ( arg_cnt != 0 )
1093  goto Unexpected_OtherSubr;
1094 
1095  {
1096  FT_Fixed Rand;
1097 
1098 
1099  Rand = seed;
1100  if ( Rand >= 0x8000L )
1101  Rand++;
1102 
1103  top[0] = Rand;
1104 
1105  seed = FT_MulFix( seed, 0x10000L - seed );
1106  if ( seed == 0 )
1107  seed += 0x2873;
1108  }
1109 
1110  known_othersubr_result_cnt = 1;
1111  break;
1112 
1113  default:
1114  if ( arg_cnt >= 0 && subr_no >= 0 )
1115  {
1116  FT_ERROR(( "t1_decoder_parse_charstrings:"
1117  " unknown othersubr [%d %d], wish me luck\n",
1118  arg_cnt, subr_no ));
1119  unknown_othersubr_result_cnt = arg_cnt;
1120  break;
1121  }
1122  /* fall through */
1123 
1124  Unexpected_OtherSubr:
1125  FT_ERROR(( "t1_decoder_parse_charstrings:"
1126  " invalid othersubr [%d %d]\n", arg_cnt, subr_no ));
1127  goto Syntax_Error;
1128  }
1129 
1130  top += known_othersubr_result_cnt;
1131 
1132  decoder->top = top;
1133  }
1134  else /* general operator */
1135  {
1136  FT_Int num_args = t1_args_count[op];
1137 
1138 
1139  FT_ASSERT( num_args >= 0 );
1140 
1141  if ( top - decoder->stack < num_args )
1142  goto Stack_Underflow;
1143 
1144  /* XXX Operators usually take their operands from the */
1145  /* bottom of the stack, i.e., the operands are */
1146  /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */
1147  /* only div, callsubr, and callothersubr are different. */
1148  /* In practice it doesn't matter (?). */
1149 
1150 #ifdef FT_DEBUG_LEVEL_TRACE
1151 
1152  switch ( op )
1153  {
1154  case op_callsubr:
1155  case op_div:
1156  case op_callothersubr:
1157  case op_pop:
1158  case op_return:
1159  break;
1160 
1161  default:
1162  if ( top - decoder->stack != num_args )
1163  FT_TRACE0(( "t1_decoder_parse_charstrings:"
1164  " too much operands on the stack"
1165  " (seen %d, expected %d)\n",
1166  top - decoder->stack, num_args ));
1167  break;
1168  }
1169 
1170 #endif /* FT_DEBUG_LEVEL_TRACE */
1171 
1172  top -= num_args;
1173 
1174  switch ( op )
1175  {
1176  case op_endchar:
1177  FT_TRACE4(( " endchar\n" ));
1178 
1179  t1_builder_close_contour( builder );
1180 
1181  /* close hints recording session */
1182  if ( hinter )
1183  {
1184  if ( hinter->close( hinter->hints,
1185  (FT_UInt)builder->current->n_points ) )
1186  goto Syntax_Error;
1187 
1188  /* apply hints to the loaded glyph outline now */
1189  error = hinter->apply( hinter->hints,
1190  builder->current,
1191  (PSH_Globals)builder->hints_globals,
1192  decoder->hint_mode );
1193  if ( error )
1194  goto Fail;
1195  }
1196 
1197  /* add current outline to the glyph slot */
1198  FT_GlyphLoader_Add( builder->loader );
1199 
1200  /* the compiler should optimize away this empty loop but ... */
1201 
1202 #ifdef FT_DEBUG_LEVEL_TRACE
1203 
1204  if ( decoder->len_buildchar > 0 )
1205  {
1206  FT_UInt i;
1207 
1208 
1209  FT_TRACE4(( "BuildCharArray = [ " ));
1210 
1211  for ( i = 0; i < decoder->len_buildchar; i++ )
1212  FT_TRACE4(( "%d ", decoder->buildchar[i] ));
1213 
1214  FT_TRACE4(( "]\n" ));
1215  }
1216 
1217 #endif /* FT_DEBUG_LEVEL_TRACE */
1218 
1219  FT_TRACE4(( "\n" ));
1220 
1221  /* return now! */
1222  return FT_Err_Ok;
1223 
1224  case op_hsbw:
1225  FT_TRACE4(( " hsbw" ));
1226 
1227  builder->parse_state = T1_Parse_Have_Width;
1228 
1229  builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
1230  top[0] );
1231 
1232  builder->advance.x = top[1];
1233  builder->advance.y = 0;
1234 
1235  orig_x = x = ADD_LONG( builder->pos_x, top[0] );
1236  orig_y = y = builder->pos_y;
1237 
1238  FT_UNUSED( orig_y );
1239 
1240  /* `metrics_only' indicates that we only want to compute the */
1241  /* glyph's metrics (lsb + advance width) without loading the */
1242  /* rest of it; so exit immediately */
1243  if ( builder->metrics_only )
1244  {
1245  FT_TRACE4(( "\n" ));
1246  return FT_Err_Ok;
1247  }
1248 
1249  break;
1250 
1251  case op_seac:
1252  return t1operator_seac( decoder,
1253  top[0],
1254  top[1],
1255  top[2],
1256  Fix2Int( top[3] ),
1257  Fix2Int( top[4] ) );
1258 
1259  case op_sbw:
1260  FT_TRACE4(( " sbw" ));
1261 
1262  builder->parse_state = T1_Parse_Have_Width;
1263 
1264  builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
1265  top[0] );
1266  builder->left_bearing.y = ADD_LONG( builder->left_bearing.y,
1267  top[1] );
1268 
1269  builder->advance.x = top[2];
1270  builder->advance.y = top[3];
1271 
1272  x = ADD_LONG( builder->pos_x, top[0] );
1273  y = ADD_LONG( builder->pos_y, top[1] );
1274 
1275  /* `metrics_only' indicates that we only want to compute the */
1276  /* glyph's metrics (lsb + advance width) without loading the */
1277  /* rest of it; so exit immediately */
1278  if ( builder->metrics_only )
1279  {
1280  FT_TRACE4(( "\n" ));
1281  return FT_Err_Ok;
1282  }
1283 
1284  break;
1285 
1286  case op_closepath:
1287  FT_TRACE4(( " closepath" ));
1288 
1289  /* if there is no path, `closepath' is a no-op */
1290  if ( builder->parse_state == T1_Parse_Have_Path ||
1291  builder->parse_state == T1_Parse_Have_Moveto )
1292  t1_builder_close_contour( builder );
1293 
1294  builder->parse_state = T1_Parse_Have_Width;
1295  break;
1296 
1297  case op_hlineto:
1298  FT_TRACE4(( " hlineto" ));
1299 
1300  if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
1301  goto Fail;
1302 
1303  x = ADD_LONG( x, top[0] );
1304  goto Add_Line;
1305 
1306  case op_hmoveto:
1307  FT_TRACE4(( " hmoveto" ));
1308 
1309  x = ADD_LONG( x, top[0] );
1310 
1311  if ( !decoder->flex_state )
1312  {
1313  if ( builder->parse_state == T1_Parse_Start )
1314  goto Syntax_Error;
1315  builder->parse_state = T1_Parse_Have_Moveto;
1316  }
1317  break;
1318 
1319  case op_hvcurveto:
1320  FT_TRACE4(( " hvcurveto" ));
1321 
1322  if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
1323  FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) )
1324  goto Fail;
1325 
1326  x = ADD_LONG( x, top[0] );
1327  t1_builder_add_point( builder, x, y, 0 );
1328 
1329  x = ADD_LONG( x, top[1] );
1330  y = ADD_LONG( y, top[2] );
1331  t1_builder_add_point( builder, x, y, 0 );
1332 
1333  y = ADD_LONG( y, top[3] );
1334  t1_builder_add_point( builder, x, y, 1 );
1335  break;
1336 
1337  case op_rlineto:
1338  FT_TRACE4(( " rlineto" ));
1339 
1340  if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
1341  goto Fail;
1342 
1343  x = ADD_LONG( x, top[0] );
1344  y = ADD_LONG( y, top[1] );
1345 
1346  Add_Line:
1347  if ( FT_SET_ERROR( t1_builder_add_point1( builder, x, y ) ) )
1348  goto Fail;
1349  break;
1350 
1351  case op_rmoveto:
1352  FT_TRACE4(( " rmoveto" ));
1353 
1354  x = ADD_LONG( x, top[0] );
1355  y = ADD_LONG( y, top[1] );
1356 
1357  if ( !decoder->flex_state )
1358  {
1359  if ( builder->parse_state == T1_Parse_Start )
1360  goto Syntax_Error;
1361  builder->parse_state = T1_Parse_Have_Moveto;
1362  }
1363  break;
1364 
1365  case op_rrcurveto:
1366  FT_TRACE4(( " rrcurveto" ));
1367 
1368  if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
1369  FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) )
1370  goto Fail;
1371 
1372  x = ADD_LONG( x, top[0] );
1373  y = ADD_LONG( y, top[1] );
1374  t1_builder_add_point( builder, x, y, 0 );
1375 
1376  x = ADD_LONG( x, top[2] );
1377  y = ADD_LONG( y, top[3] );
1378  t1_builder_add_point( builder, x, y, 0 );
1379 
1380  x = ADD_LONG( x, top[4] );
1381  y = ADD_LONG( y, top[5] );
1382  t1_builder_add_point( builder, x, y, 1 );
1383  break;
1384 
1385  case op_vhcurveto:
1386  FT_TRACE4(( " vhcurveto" ));
1387 
1388  if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
1389  FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) )
1390  goto Fail;
1391 
1392  y = ADD_LONG( y, top[0] );
1393  t1_builder_add_point( builder, x, y, 0 );
1394 
1395  x = ADD_LONG( x, top[1] );
1396  y = ADD_LONG( y, top[2] );
1397  t1_builder_add_point( builder, x, y, 0 );
1398 
1399  x = ADD_LONG( x, top[3] );
1400  t1_builder_add_point( builder, x, y, 1 );
1401  break;
1402 
1403  case op_vlineto:
1404  FT_TRACE4(( " vlineto" ));
1405 
1406  if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
1407  goto Fail;
1408 
1409  y = ADD_LONG( y, top[0] );
1410  goto Add_Line;
1411 
1412  case op_vmoveto:
1413  FT_TRACE4(( " vmoveto" ));
1414 
1415  y = ADD_LONG( y, top[0] );
1416 
1417  if ( !decoder->flex_state )
1418  {
1419  if ( builder->parse_state == T1_Parse_Start )
1420  goto Syntax_Error;
1421  builder->parse_state = T1_Parse_Have_Moveto;
1422  }
1423  break;
1424 
1425  case op_div:
1426  FT_TRACE4(( " div" ));
1427 
1428  /* if `large_int' is set, we divide unscaled numbers; */
1429  /* otherwise, we divide numbers in 16.16 format -- */
1430  /* in both cases, it is the same operation */
1431  *top = FT_DivFix( top[0], top[1] );
1432  top++;
1433 
1434  large_int = FALSE;
1435  break;
1436 
1437  case op_callsubr:
1438  {
1439  FT_Int idx;
1440 
1441 
1442  FT_TRACE4(( " callsubr" ));
1443 
1444  idx = Fix2Int( top[0] );
1445 
1446  if ( decoder->subrs_hash )
1447  {
1448  size_t* val = ft_hash_num_lookup( idx,
1449  decoder->subrs_hash );
1450 
1451 
1452  if ( val )
1453  idx = *val;
1454  else
1455  idx = -1;
1456  }
1457 
1458  if ( idx < 0 || idx >= decoder->num_subrs )
1459  {
1460  FT_ERROR(( "t1_decoder_parse_charstrings:"
1461  " invalid subrs index\n" ));
1462  goto Syntax_Error;
1463  }
1464 
1465  if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
1466  {
1467  FT_ERROR(( "t1_decoder_parse_charstrings:"
1468  " too many nested subrs\n" ));
1469  goto Syntax_Error;
1470  }
1471 
1472  zone->cursor = ip; /* save current instruction pointer */
1473 
1474  zone++;
1475 
1476  /* The Type 1 driver stores subroutines without the seed bytes. */
1477  /* The CID driver stores subroutines with seed bytes. This */
1478  /* case is taken care of when decoder->subrs_len == 0. */
1479  zone->base = decoder->subrs[idx];
1480 
1481  if ( decoder->subrs_len )
1482  zone->limit = zone->base + decoder->subrs_len[idx];
1483  else
1484  {
1485  /* We are using subroutines from a CID font. We must adjust */
1486  /* for the seed bytes. */
1487  zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
1488  zone->limit = decoder->subrs[idx + 1];
1489  }
1490 
1491  zone->cursor = zone->base;
1492 
1493  if ( !zone->base )
1494  {
1495  FT_ERROR(( "t1_decoder_parse_charstrings:"
1496  " invoking empty subrs\n" ));
1497  goto Syntax_Error;
1498  }
1499 
1500  decoder->zone = zone;
1501  ip = zone->base;
1502  limit = zone->limit;
1503  break;
1504  }
1505 
1506  case op_pop:
1507  FT_TRACE4(( " pop" ));
1508 
1509  if ( known_othersubr_result_cnt > 0 )
1510  {
1511  known_othersubr_result_cnt--;
1512  /* ignore, we pushed the operands ourselves */
1513  break;
1514  }
1515 
1516  if ( unknown_othersubr_result_cnt == 0 )
1517  {
1518  FT_ERROR(( "t1_decoder_parse_charstrings:"
1519  " no more operands for othersubr\n" ));
1520  goto Syntax_Error;
1521  }
1522 
1523  unknown_othersubr_result_cnt--;
1524  top++; /* `push' the operand to callothersubr onto the stack */
1525  break;
1526 
1527  case op_return:
1528  FT_TRACE4(( " return" ));
1529 
1530  if ( zone <= decoder->zones )
1531  {
1532  FT_ERROR(( "t1_decoder_parse_charstrings:"
1533  " unexpected return\n" ));
1534  goto Syntax_Error;
1535  }
1536 
1537  zone--;
1538  ip = zone->cursor;
1539  limit = zone->limit;
1540  decoder->zone = zone;
1541  break;
1542 
1543  case op_dotsection:
1544  FT_TRACE4(( " dotsection" ));
1545 
1546  break;
1547 
1548  case op_hstem:
1549  FT_TRACE4(( " hstem" ));
1550 
1551  /* record horizontal hint */
1552  if ( hinter )
1553  {
1554  /* top[0] += builder->left_bearing.y; */
1555  hinter->stem( hinter->hints, 1, top );
1556  }
1557  break;
1558 
1559  case op_hstem3:
1560  FT_TRACE4(( " hstem3" ));
1561 
1562  /* record horizontal counter-controlled hints */
1563  if ( hinter )
1564  hinter->stem3( hinter->hints, 1, top );
1565  break;
1566 
1567  case op_vstem:
1568  FT_TRACE4(( " vstem" ));
1569 
1570  /* record vertical hint */
1571  if ( hinter )
1572  {
1573  top[0] = ADD_LONG( top[0], orig_x );
1574  hinter->stem( hinter->hints, 0, top );
1575  }
1576  break;
1577 
1578  case op_vstem3:
1579  FT_TRACE4(( " vstem3" ));
1580 
1581  /* record vertical counter-controlled hints */
1582  if ( hinter )
1583  {
1584  FT_Pos dx = orig_x;
1585 
1586 
1587  top[0] = ADD_LONG( top[0], dx );
1588  top[2] = ADD_LONG( top[2], dx );
1589  top[4] = ADD_LONG( top[4], dx );
1590  hinter->stem3( hinter->hints, 0, top );
1591  }
1592  break;
1593 
1594  case op_setcurrentpoint:
1595  FT_TRACE4(( " setcurrentpoint" ));
1596 
1597  /* From the T1 specification, section 6.4: */
1598  /* */
1599  /* The setcurrentpoint command is used only in */
1600  /* conjunction with results from OtherSubrs procedures. */
1601 
1602  /* known_othersubr_result_cnt != 0 is already handled */
1603  /* above. */
1604 
1605  /* Note, however, that both Ghostscript and Adobe */
1606  /* Distiller handle this situation by silently ignoring */
1607  /* the inappropriate `setcurrentpoint' instruction. So */
1608  /* we do the same. */
1609 #if 0
1610 
1611  if ( decoder->flex_state != 1 )
1612  {
1613  FT_ERROR(( "t1_decoder_parse_charstrings:"
1614  " unexpected `setcurrentpoint'\n" ));
1615  goto Syntax_Error;
1616  }
1617  else
1618  ...
1619 #endif
1620 
1621  x = top[0];
1622  y = top[1];
1623  decoder->flex_state = 0;
1624  break;
1625 
1626  case op_unknown15:
1627  FT_TRACE4(( " opcode_15" ));
1628  /* nothing to do except to pop the two arguments */
1629  break;
1630 
1631  default:
1632  FT_ERROR(( "t1_decoder_parse_charstrings:"
1633  " unhandled opcode %d\n", op ));
1634  goto Syntax_Error;
1635  }
1636 
1637  /* XXX Operators usually clear the operand stack; */
1638  /* only div, callsubr, callothersubr, pop, and */
1639  /* return are different. */
1640  /* In practice it doesn't matter (?). */
1641 
1642  decoder->top = top;
1643 
1644 #ifdef FT_DEBUG_LEVEL_TRACE
1645  FT_TRACE4(( "\n" ));
1646  bol = TRUE;
1647 #endif
1648 
1649  } /* general operator processing */
1650 
1651  } /* while ip < limit */
1652 
1653  FT_TRACE4(( "..end..\n\n" ));
1654 
1655  Fail:
1656  return error;
1657 
1658  Syntax_Error:
1659  return FT_THROW( Syntax_Error );
1660 
1661  Stack_Underflow:
1662  return FT_THROW( Stack_Underflow );
1663  }
1664 
1665 
1666 #else /* !T1_CONFIG_OPTION_OLD_ENGINE */
1667 
1668 
1669  /**************************************************************************
1670  *
1671  * @Function:
1672  * t1_decoder_parse_metrics
1673  *
1674  * @Description:
1675  * Parses a given Type 1 charstrings program to extract width
1676  *
1677  * @Input:
1678  * decoder ::
1679  * The current Type 1 decoder.
1680  *
1681  * charstring_base ::
1682  * The base address of the charstring stream.
1683  *
1684  * charstring_len ::
1685  * The length in bytes of the charstring stream.
1686  *
1687  * @Return:
1688  * FreeType error code. 0 means success.
1689  */
1692  FT_Byte* charstring_base,
1693  FT_UInt charstring_len )
1694  {
1696  FT_Byte* ip;
1697  FT_Byte* limit;
1698  T1_Builder builder = &decoder->builder;
1699  FT_Bool large_int;
1700 
1701 #ifdef FT_DEBUG_LEVEL_TRACE
1702  FT_Bool bol = TRUE;
1703 #endif
1704 
1705 
1706  /* First of all, initialize the decoder */
1707  decoder->top = decoder->stack;
1708  decoder->zone = decoder->zones;
1709  zone = decoder->zones;
1710 
1711  builder->parse_state = T1_Parse_Start;
1712 
1713  zone->base = charstring_base;
1714  limit = zone->limit = charstring_base + charstring_len;
1715  ip = zone->cursor = zone->base;
1716 
1717  large_int = FALSE;
1718 
1719  /* now, execute loop */
1720  while ( ip < limit )
1721  {
1722  FT_Long* top = decoder->top;
1724  FT_Int32 value = 0;
1725 
1726 
1727 #ifdef FT_DEBUG_LEVEL_TRACE
1728  if ( bol )
1729  {
1730  FT_TRACE5(( " (%ld)", decoder->top - decoder->stack ));
1731  bol = FALSE;
1732  }
1733 #endif
1734 
1735  /**********************************************************************
1736  *
1737  * Decode operator or operand
1738  *
1739  */
1740 
1741  /* first of all, decompress operator or value */
1742  switch ( *ip++ )
1743  {
1744  case 1:
1745  case 3:
1746  case 4:
1747  case 5:
1748  case 6:
1749  case 7:
1750  case 8:
1751  case 9:
1752  case 14:
1753  case 15:
1754  case 21:
1755  case 22:
1756  case 30:
1757  case 31:
1758  goto No_Width;
1759 
1760  case 10:
1761  op = op_callsubr;
1762  break;
1763  case 11:
1764  op = op_return;
1765  break;
1766 
1767  case 13:
1768  op = op_hsbw;
1769  break;
1770 
1771  case 12:
1772  if ( ip >= limit )
1773  {
1774  FT_ERROR(( "t1_decoder_parse_metrics:"
1775  " invalid escape (12+EOF)\n" ));
1776  goto Syntax_Error;
1777  }
1778 
1779  switch ( *ip++ )
1780  {
1781  case 7:
1782  op = op_sbw;
1783  break;
1784  case 12:
1785  op = op_div;
1786  break;
1787 
1788  default:
1789  goto No_Width;
1790  }
1791  break;
1792 
1793  case 255: /* four bytes integer */
1794  if ( ip + 4 > limit )
1795  {
1796  FT_ERROR(( "t1_decoder_parse_metrics:"
1797  " unexpected EOF in integer\n" ));
1798  goto Syntax_Error;
1799  }
1800 
1801  value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
1802  ( (FT_UInt32)ip[1] << 16 ) |
1803  ( (FT_UInt32)ip[2] << 8 ) |
1804  (FT_UInt32)ip[3] );
1805  ip += 4;
1806 
1807  /* According to the specification, values > 32000 or < -32000 must */
1808  /* be followed by a `div' operator to make the result be in the */
1809  /* range [-32000;32000]. We expect that the second argument of */
1810  /* `div' is not a large number. Additionally, we don't handle */
1811  /* stuff like `<large1> <large2> <num> div <num> div' or */
1812  /* <large1> <large2> <num> div div'. This is probably not allowed */
1813  /* anyway. */
1814  if ( value > 32000 || value < -32000 )
1815  {
1816  if ( large_int )
1817  {
1818  FT_ERROR(( "t1_decoder_parse_metrics:"
1819  " no `div' after large integer\n" ));
1820  goto Syntax_Error;
1821  }
1822  else
1823  large_int = TRUE;
1824  }
1825  else
1826  {
1827  if ( !large_int )
1828  value = (FT_Int32)( (FT_UInt32)value << 16 );
1829  }
1830 
1831  break;
1832 
1833  default:
1834  if ( ip[-1] >= 32 )
1835  {
1836  if ( ip[-1] < 247 )
1837  value = (FT_Int32)ip[-1] - 139;
1838  else
1839  {
1840  if ( ++ip > limit )
1841  {
1842  FT_ERROR(( "t1_decoder_parse_metrics:"
1843  " unexpected EOF in integer\n" ));
1844  goto Syntax_Error;
1845  }
1846 
1847  if ( ip[-2] < 251 )
1848  value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108;
1849  else
1850  value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
1851  }
1852 
1853  if ( !large_int )
1854  value = (FT_Int32)( (FT_UInt32)value << 16 );
1855  }
1856  else
1857  {
1858  FT_ERROR(( "t1_decoder_parse_metrics:"
1859  " invalid byte (%d)\n", ip[-1] ));
1860  goto Syntax_Error;
1861  }
1862  }
1863 
1864  if ( large_int && !( op == op_none || op == op_div ) )
1865  {
1866  FT_ERROR(( "t1_decoder_parse_metrics:"
1867  " no `div' after large integer\n" ));
1868  goto Syntax_Error;
1869  }
1870 
1871  /**********************************************************************
1872  *
1873  * Push value on stack, or process operator
1874  *
1875  */
1876  if ( op == op_none )
1877  {
1878  if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
1879  {
1880  FT_ERROR(( "t1_decoder_parse_metrics: stack overflow\n" ));
1881  goto Syntax_Error;
1882  }
1883 
1884 #ifdef FT_DEBUG_LEVEL_TRACE
1885  if ( large_int )
1886  FT_TRACE4(( " %d", value ));
1887  else
1888  FT_TRACE4(( " %d", value / 65536 ));
1889 #endif
1890 
1891  *top++ = value;
1892  decoder->top = top;
1893  }
1894  else /* general operator */
1895  {
1896  FT_Int num_args = t1_args_count[op];
1897 
1898 
1899  FT_ASSERT( num_args >= 0 );
1900 
1901  if ( top - decoder->stack < num_args )
1902  goto Stack_Underflow;
1903 
1904 #ifdef FT_DEBUG_LEVEL_TRACE
1905 
1906  switch ( op )
1907  {
1908  case op_callsubr:
1909  case op_div:
1910  case op_return:
1911  break;
1912 
1913  default:
1914  if ( top - decoder->stack != num_args )
1915  FT_TRACE0(( "t1_decoder_parse_metrics:"
1916  " too much operands on the stack"
1917  " (seen %ld, expected %d)\n",
1918  top - decoder->stack, num_args ));
1919  break;
1920  }
1921 
1922 #endif /* FT_DEBUG_LEVEL_TRACE */
1923 
1924  top -= num_args;
1925 
1926  switch ( op )
1927  {
1928  case op_hsbw:
1929  FT_TRACE4(( " hsbw" ));
1930 
1931  builder->parse_state = T1_Parse_Have_Width;
1932 
1933  builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
1934  top[0] );
1935 
1936  builder->advance.x = top[1];
1937  builder->advance.y = 0;
1938 
1939  /* we only want to compute the glyph's metrics */
1940  /* (lsb + advance width) without loading the */
1941  /* rest of it; so exit immediately */
1942  FT_TRACE4(( "\n" ));
1943  return FT_Err_Ok;
1944 
1945  case op_sbw:
1946  FT_TRACE4(( " sbw" ));
1947 
1948  builder->parse_state = T1_Parse_Have_Width;
1949 
1950  builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
1951  top[0] );
1952  builder->left_bearing.y = ADD_LONG( builder->left_bearing.y,
1953  top[1] );
1954 
1955  builder->advance.x = top[2];
1956  builder->advance.y = top[3];
1957 
1958  /* we only want to compute the glyph's metrics */
1959  /* (lsb + advance width), without loading the */
1960  /* rest of it; so exit immediately */
1961  FT_TRACE4(( "\n" ));
1962  return FT_Err_Ok;
1963 
1964  case op_div:
1965  FT_TRACE4(( " div" ));
1966 
1967  /* if `large_int' is set, we divide unscaled numbers; */
1968  /* otherwise, we divide numbers in 16.16 format -- */
1969  /* in both cases, it is the same operation */
1970  *top = FT_DivFix( top[0], top[1] );
1971  top++;
1972 
1973  large_int = FALSE;
1974  break;
1975 
1976  case op_callsubr:
1977  {
1978  FT_Int idx;
1979 
1980 
1981  FT_TRACE4(( " callsubr" ));
1982 
1983  idx = Fix2Int( top[0] );
1984 
1985  if ( decoder->subrs_hash )
1986  {
1987  size_t* val = ft_hash_num_lookup( idx,
1988  decoder->subrs_hash );
1989 
1990 
1991  if ( val )
1992  idx = *val;
1993  else
1994  idx = -1;
1995  }
1996 
1997  if ( idx < 0 || idx >= decoder->num_subrs )
1998  {
1999  FT_ERROR(( "t1_decoder_parse_metrics:"
2000  " invalid subrs index\n" ));
2001  goto Syntax_Error;
2002  }
2003 
2004  if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
2005  {
2006  FT_ERROR(( "t1_decoder_parse_metrics:"
2007  " too many nested subrs\n" ));
2008  goto Syntax_Error;
2009  }
2010 
2011  zone->cursor = ip; /* save current instruction pointer */
2012 
2013  zone++;
2014 
2015  /* The Type 1 driver stores subroutines without the seed bytes. */
2016  /* The CID driver stores subroutines with seed bytes. This */
2017  /* case is taken care of when decoder->subrs_len == 0. */
2018  zone->base = decoder->subrs[idx];
2019 
2020  if ( decoder->subrs_len )
2021  zone->limit = zone->base + decoder->subrs_len[idx];
2022  else
2023  {
2024  /* We are using subroutines from a CID font. We must adjust */
2025  /* for the seed bytes. */
2026  zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
2027  zone->limit = decoder->subrs[idx + 1];
2028  }
2029 
2030  zone->cursor = zone->base;
2031 
2032  if ( !zone->base )
2033  {
2034  FT_ERROR(( "t1_decoder_parse_metrics:"
2035  " invoking empty subrs\n" ));
2036  goto Syntax_Error;
2037  }
2038 
2039  decoder->zone = zone;
2040  ip = zone->base;
2041  limit = zone->limit;
2042  break;
2043  }
2044 
2045  case op_return:
2046  FT_TRACE4(( " return" ));
2047 
2048  if ( zone <= decoder->zones )
2049  {
2050  FT_ERROR(( "t1_decoder_parse_metrics:"
2051  " unexpected return\n" ));
2052  goto Syntax_Error;
2053  }
2054 
2055  zone--;
2056  ip = zone->cursor;
2057  limit = zone->limit;
2058  decoder->zone = zone;
2059  break;
2060 
2061  default:
2062  FT_ERROR(( "t1_decoder_parse_metrics:"
2063  " unhandled opcode %d\n", op ));
2064  goto Syntax_Error;
2065  }
2066 
2067  decoder->top = top;
2068 
2069  } /* general operator processing */
2070 
2071  } /* while ip < limit */
2072 
2073  FT_TRACE4(( "..end..\n\n" ));
2074 
2075  No_Width:
2076  FT_ERROR(( "t1_decoder_parse_metrics:"
2077  " no width, found op %d instead\n",
2078  ip[-1] ));
2079  Syntax_Error:
2080  return FT_THROW( Syntax_Error );
2081 
2082  Stack_Underflow:
2083  return FT_THROW( Stack_Underflow );
2084  }
2085 
2086 #endif /* !T1_CONFIG_OPTION_OLD_ENGINE */
2087 
2088 
2089  /* initialize T1 decoder */
2092  FT_Face face,
2093  FT_Size size,
2095  FT_Byte** glyph_names,
2096  PS_Blend blend,
2097  FT_Bool hinting,
2098  FT_Render_Mode hint_mode,
2099  T1_Decoder_Callback parse_callback )
2100  {
2101  FT_ZERO( decoder );
2102 
2103  /* retrieve `psnames' interface from list of current modules */
2104  {
2105  FT_Service_PsCMaps psnames;
2106 
2107 
2108  FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
2109  if ( !psnames )
2110  {
2111  FT_ERROR(( "t1_decoder_init:"
2112  " the `psnames' module is not available\n" ));
2113  return FT_THROW( Unimplemented_Feature );
2114  }
2115 
2116  decoder->psnames = psnames;
2117  }
2118 
2119  t1_builder_init( &decoder->builder, face, size, slot, hinting );
2120 
2121  /* decoder->buildchar and decoder->len_buildchar have to be */
2122  /* initialized by the caller since we cannot know the length */
2123  /* of the BuildCharArray */
2124 
2125  decoder->num_glyphs = (FT_UInt)face->num_glyphs;
2126  decoder->glyph_names = glyph_names;
2127  decoder->hint_mode = hint_mode;
2128  decoder->blend = blend;
2129  decoder->parse_callback = parse_callback;
2130 
2131  decoder->funcs = t1_decoder_funcs;
2132 
2133  return FT_Err_Ok;
2134  }
2135 
2136 
2137  /* finalize T1 decoder */
2138  FT_LOCAL_DEF( void )
2140  {
2141  FT_Memory memory = decoder->builder.memory;
2142 
2143 
2144  t1_builder_done( &decoder->builder );
2145 
2146  if ( decoder->cf2_instance.finalizer )
2147  {
2148  decoder->cf2_instance.finalizer( decoder->cf2_instance.data );
2149  FT_FREE( decoder->cf2_instance.data );
2150  }
2151  }
2152 
2153 
2154 /* END */
#define the
Definition: aptex-macros.h:490
#define mark
Definition: aptex-macros.h:374
#define name
#define advance
Definition: aptex-macros.h:464
#define n
Definition: t4ht.c:1290
@ FALSE
Definition: dd.h:101
@ TRUE
Definition: dd.h:102
#define error(a)
Definition: dviinfo.c:48
void Exit(int code)
Definition: dvispc.c:374
uint8 ** orig_y
Definition: eyuvtoppm.c:51
int base
Definition: gsftopk.c:1502
#define T1_MAX_CHARSTRINGS_OPERANDS
Definition: ftoption.h:767
#define T1_MAX_SUBRS_CALLS
Definition: ftoption.h:756
#define ft_memcpy
Definition: ftstdlib.h:82
#define ft_strcmp
Definition: ftstdlib.h:86
#define FT_ULONG_MAX
Definition: ftstdlib.h:68
#define FT_UNUSED(arg)
enum FT_Render_Mode_ FT_Render_Mode
FT_DivFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:607
#define FT_SUBGLYPH_FLAG_USE_MY_METRICS
Definition: freetype.h:3960
struct FT_GlyphSlotRec_ * FT_GlyphSlot
Definition: freetype.h:532
#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
Definition: freetype.h:3955
FT_MulFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:508
cannot open resource broken file module version is too low unimplemented feature broken offset within table missing module invalid glyph index unsupported glyph image format invalid outline too many hints invalid object handle invalid module handle invalid size handle invalid charmap handle invalid stream handle too many extensions unlisted object invalid stream seek invalid stream read invalid frame operation invalid frame read raster corrupted negative height while rastering invalid opcode stack overflow bad argument invalid reference found ENDF opcode in execution stream invalid code range too many function definitions SFNT font table missing name table missing horizontal PostScript(post) table missing" ) FT_ERRORDEF_( Invalid_Horiz_Metrics
@ FT_GLYPH_FORMAT_COMPOSITE
Definition: ftimage.h:747
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:57
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:64
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
unsigned char FT_Byte
Definition: fttypes.h:154
signed long FT_Fixed
Definition: fttypes.h:287
int FT_Error
Definition: fttypes.h:299
signed long FT_Long
Definition: fttypes.h:242
char FT_String
Definition: fttypes.h:187
unsigned int FT_UInt
Definition: fttypes.h:231
size_t FT_Offset
Definition: fttypes.h:323
signed int FT_Int
Definition: fttypes.h:220
#define FT_LOCAL_DEF(x)
#define FIXED_TO_INT(x)
Definition: ftcalc.h:450
#define SUB_LONG(a, b)
Definition: ftcalc.h:474
#define ADD_LONG(a, b)
Definition: ftcalc.h:472
#define FT_ASSERT(condition)
Definition: ftdebug.h:241
#define FT_TRACE0(varformat)
Definition: ftdebug.h:187
#define FT_ERROR(varformat)
Definition: ftdebug.h:211
#define FT_TRACE5(varformat)
Definition: ftdebug.h:192
#define FT_THROW(e)
Definition: ftdebug.h:243
#define FT_TRACE4(varformat)
Definition: ftdebug.h:191
FT_GlyphLoader_Add(FT_GlyphLoader loader)
Definition: ftgloadr.c:340
FT_GlyphLoader_Prepare(FT_GlyphLoader loader)
Definition: ftgloadr.c:324
FT_GlyphLoader_CheckSubGlyphs(FT_GlyphLoader loader, FT_UInt n_subs)
Definition: ftgloadr.c:293
size_t * ft_hash_num_lookup(FT_Int num, FT_Hash hash)
Definition: fthash.c:326
#define FT_SET_ERROR(expression)
Definition: ftmemory.h:43
#define FT_FREE(ptr)
Definition: ftmemory.h:337
#define FT_ZERO(p)
Definition: ftmemory.h:246
#define FT_ARRAY_ZERO(dest, count)
Definition: ftmemory.h:249
#define NULL
Definition: ftobjs.h:61
#define FT_FACE_FIND_GLOBAL_SERVICE(face, ptr, id)
Definition: ftserv.h:128
FT_Error(* T1_Decoder_Callback)(T1_Decoder decoder, FT_UInt glyph_index)
Definition: psaux.h:899
@ T1_Parse_Have_Width
Definition: psaux.h:756
@ T1_Parse_Have_Path
Definition: psaux.h:758
@ T1_Parse_Start
Definition: psaux.h:755
@ T1_Parse_Have_Moveto
Definition: psaux.h:757
const struct T1_Hints_FuncsRec_ * T1_Hints_Funcs
Definition: pshints.h:116
typedefFT_BEGIN_HEADER struct PSH_GlobalsRec_ * PSH_Globals
Definition: pshints.h:40
struct T1_FaceRec_ * T1_Face
Definition: t1types.h:198
small capitals from c petite p scientific i
Definition: afcover.h:80
sizeof(AF_ModuleRec)
return FT_Err_Ok
Definition: ftbbox.c:526
FT_UInt idx
Definition: cffcmap.c:135
FT_Face face
Definition: cffdrivr.c:659
FT_CALLBACK_TABLE_DEF const T1_Decoder_FuncsRec t1_decoder_funcs
Definition: psauxmod.c:87
t1_builder_close_contour(T1_Builder builder)
Definition: psobjs.c:1753
t1_builder_start_point(T1_Builder builder, FT_Pos x, FT_Pos y)
Definition: psobjs.c:1728
t1_builder_init(T1_Builder builder, FT_Face face, FT_Size size, FT_GlyphSlot glyph, FT_Bool hinting)
Definition: psobjs.c:1574
t1_builder_add_point1(T1_Builder builder, FT_Pos x, FT_Pos y)
Definition: psobjs.c:1676
t1_builder_check_points(T1_Builder builder, FT_Int count)
Definition: psobjs.c:1643
t1_builder_done(T1_Builder builder)
Definition: psobjs.c:1631
t1_builder_add_point(T1_Builder builder, FT_Pos x, FT_Pos y, FT_Byte flag)
Definition: psobjs.c:1652
t1_decoder_parse_metrics(T1_Decoder decoder, FT_Byte *charstring_base, FT_UInt charstring_len)
Definition: t1decode.c:1691
enum T1_Operator_ T1_Operator
t1_decoder_done(T1_Decoder decoder)
Definition: t1decode.c:2139
t1_decoder_init(T1_Decoder decoder, FT_Face face, FT_Size size, FT_GlyphSlot slot, FT_Byte **glyph_names, PS_Blend blend, FT_Bool hinting, FT_Render_Mode hint_mode, T1_Decoder_Callback parse_callback)
Definition: t1decode.c:2091
t1_lookup_glyph_by_stdcharcode_ps(PS_Decoder *decoder, FT_Int charcode)
Definition: t1decode.c:132
T1_Operator_
Definition: t1decode.c:44
@ op_hmoveto
Definition: t1decode.c:52
@ op_vstem
Definition: t1decode.c:63
@ op_dotsection
Definition: t1decode.c:60
@ op_vmoveto
Definition: t1decode.c:59
@ op_hlineto
Definition: t1decode.c:51
@ op_rlineto
Definition: t1decode.c:54
@ op_hstem
Definition: t1decode.c:61
@ op_rrcurveto
Definition: t1decode.c:56
@ op_vhcurveto
Definition: t1decode.c:57
@ op_unknown15
Definition: t1decode.c:71
@ op_seac
Definition: t1decode.c:48
@ op_hsbw
Definition: t1decode.c:47
@ op_closepath
Definition: t1decode.c:50
@ op_div
Definition: t1decode.c:65
@ op_setcurrentpoint
Definition: t1decode.c:70
@ op_rmoveto
Definition: t1decode.c:55
@ op_sbw
Definition: t1decode.c:49
@ op_vlineto
Definition: t1decode.c:58
@ op_pop
Definition: t1decode.c:68
@ op_callsubr
Definition: t1decode.c:67
@ op_max
Definition: t1decode.c:73
@ op_callothersubr
Definition: t1decode.c:66
@ op_hstem3
Definition: t1decode.c:62
@ op_vstem3
Definition: t1decode.c:64
@ op_return
Definition: t1decode.c:69
@ op_endchar
Definition: t1decode.c:46
@ op_none
Definition: t1decode.c:45
@ op_hvcurveto
Definition: t1decode.c:53
kerning y
Definition: ttdriver.c:212
int int double double double char double char * top
Definition: gdfx.h:19
unsigned bchar
float x
Definition: cordic.py:15
union value value
Definition: obx.h:44
static int delta
Definition: pbmtolj.c:36
static void blend(struct RGBColour *src, struct RGBColour *dst)
Definition: picttoppm.c:1294
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld endif[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld_src SRC pixld MASK if DST_R else pixld DST_R endif if
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
integer nn[24]
Definition: pmxab.c:90
static int size
Definition: ppmlabel.c:24
static const FT_Int t1_args_count[op_max]
Definition: t1decode.c:79
#define Fix2Int(f)
Definition: t1decode.c:31
slotref slot
Definition: opcodes.h:237
FT_Long num_glyphs
Definition: freetype.h:1036
FT_Face_Internal internal
Definition: freetype.h:1080
short n_points
Definition: ftimage.h:339
FT_Pos x
Definition: ftimage.h:77
FT_Pos y
Definition: ftimage.h:78
FT_Bool no_recurse
Definition: psaux.h:845
FT_GlyphSlot glyph
Definition: psaux.h:831
void * hints_globals
Definition: psaux.h:850
FT_Vector advance
Definition: psaux.h:840
FT_Outline * current
Definition: psaux.h:834
FT_Face face
Definition: psaux.h:830
void * hints_funcs
Definition: psaux.h:849
FT_Vector left_bearing
Definition: psaux.h:839
FT_Bool metrics_only
Definition: psaux.h:847
FT_Pos pos_y
Definition: psaux.h:837
FT_Pos pos_x
Definition: psaux.h:836
FT_GlyphLoader loader
Definition: psaux.h:832
T1_ParseState parse_state
Definition: psaux.h:843
FT_Outline * base
Definition: psaux.h:833
FT_UInt * subrs_len
Definition: psaux.h:957
PS_Blend blend
Definition: psaux.h:967
FT_UInt num_glyphs
Definition: psaux.h:951
FT_Int flex_state
Definition: psaux.h:963
FT_Render_Mode hint_mode
Definition: psaux.h:969
FT_Long * top
Definition: psaux.h:945
FT_Int num_flex_vectors
Definition: psaux.h:964
FT_Long * buildchar
Definition: psaux.h:974
FT_Bool seac
Definition: psaux.h:977
FT_Byte ** subrs
Definition: psaux.h:956
FT_UInt len_buildchar
Definition: psaux.h:975
FT_Long stack[T1_MAX_CHARSTRINGS_OPERANDS]
Definition: psaux.h:944
FT_Int num_subrs
Definition: psaux.h:955
T1_BuilderRec builder
Definition: psaux.h:942
T1_Decoder_Callback parse_callback
Definition: psaux.h:971
T1_Decoder_ZoneRec zones[T1_MAX_SUBRS_CALLS+1]
Definition: psaux.h:947
FT_Byte ** glyph_names
Definition: psaux.h:952
FT_Service_PsCMaps psnames
Definition: psaux.h:950
FT_Hash subrs_hash
Definition: psaux.h:958
T1_Decoder_Zone zone
Definition: psaux.h:948
FT_Int lenIV
Definition: psaux.h:954
T1_Hints_ApplyFunc apply
Definition: pshints.h:349
T1_Hints_OpenFunc open
Definition: pshints.h:344
T1_Hints_ResetFunc reset
Definition: pshints.h:348
T1_Hints hints
Definition: pshints.h:343
T1_Hints_CloseFunc close
Definition: pshints.h:345
T1_Hints_SetStemFunc stem
Definition: pshints.h:346
T1_Hints_SetStem3Func stem3
Definition: pshints.h:347
Definition: pbmfont.h:4
Definition: sh.h:1226
Definition: spc_misc.c:56
Definition: strexpr.c:21
Definition: zic.c:110
val
Definition: tex4ht.c:3227
op
Definition: tex4ht.c:3129
#define ip
Definition: stack.c:14
Definition: obx.h:51
#define limit(x)
Definition: yuvsplittoppm.c:26
static struct zone * zones
Definition: zic.c:291