1 /***************************************************************************/ 
   5 /*    Experimental Type 1 Glyph Loader (body).                             */ 
   7 /*  Copyright 1996-2000 by                                                 */ 
   8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */ 
  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.                                        */ 
  16 /***************************************************************************/ 
  19 #ifdef FT_FLAT_COMPILE 
  25 #include <type1z/z1gload.h> 
  30 #include <freetype/internal/ftdebug.h> 
  31 #include <freetype/internal/ftstream.h> 
  32 #include <freetype/ftoutln.h> 
  34 #include <string.h>     /* for strcmp() */ 
  37   /*************************************************************************/ 
  39   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */ 
  40   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */ 
  41   /* messages during execution.                                            */ 
  44 #define FT_COMPONENT  trace_z1gload 
  47   typedef enum  Z1_Operator_
 
  76     op_max    
/* never remove this one */ 
  81   const FT_Int  t1_args_count
[op_max
] = 
 104    -1, /* callothersubr */ 
 108     2  /* setcurrentpoint */ 
 112   /*************************************************************************/ 
 113   /*************************************************************************/ 
 114   /*************************************************************************/ 
 115   /**********                                                      *********/ 
 116   /**********                                                      *********/ 
 117   /**********             GENERIC CHARSTRING PARSING               *********/ 
 118   /**********                                                      *********/ 
 119   /**********                                                      *********/ 
 120   /*************************************************************************/ 
 121   /*************************************************************************/ 
 122   /*************************************************************************/ 
 125   /*************************************************************************/ 
 128   /*    Z1_Init_Builder                                                    */ 
 131   /*    Initializes a given glyph builder.                                 */ 
 134   /*    builder :: A pointer to the glyph builder to initialize.           */ 
 137   /*    face    :: The current face object.                                */ 
 139   /*    size    :: The current size object.                                */ 
 141   /*    glyph   :: The current glyph object.                               */ 
 144   void  Z1_Init_Builder( Z1_Builder
*   builder
, 
 149     builder
->path_begun  
= 0; 
 150     builder
->load_points 
= 1; 
 152     builder
->face   
= face
; 
 153     builder
->glyph  
= glyph
; 
 154     builder
->memory 
= face
->root
.memory
; 
 158       FT_GlyphLoader
*  loader 
= glyph
->root
.loader
; 
 161       builder
->loader  
= loader
; 
 162       builder
->current 
= &loader
->current
.outline
; 
 163       builder
->base    
= &loader
->base
.outline
; 
 165       FT_GlyphLoader_Rewind( loader 
); 
 170       builder
->scale_x 
= size
->root
.metrics
.x_scale
; 
 171       builder
->scale_y 
= size
->root
.metrics
.y_scale
; 
 177     builder
->left_bearing
.x 
= 0; 
 178     builder
->left_bearing
.y 
= 0; 
 179     builder
->advance
.x      
= 0; 
 180     builder
->advance
.y      
= 0; 
 184   /*************************************************************************/ 
 187   /*    Z1_Done_Builder                                                    */ 
 190   /*    Finalizes a given glyph builder.  Its contents can still be used   */ 
 191   /*    after the call, but the function saves important information       */ 
 192   /*    within the corresponding glyph slot.                               */ 
 195   /*    builder :: A pointer to the glyph builder to finalize.             */ 
 198   void Z1_Done_Builder( Z1_Builder
*  builder 
) 
 200     Z1_GlyphSlot  glyph 
= builder
->glyph
; 
 204       glyph
->root
.outline 
= *builder
->base
; 
 208   /*************************************************************************/ 
 211   /*    Z1_Init_Decoder                                                    */ 
 214   /*    Initializes a given glyph decoder.                                 */ 
 217   /*    decoder :: A pointer to the glyph builder to initialize.           */ 
 220   void  Z1_Init_Decoder( Z1_Decoder
* decoder 
) 
 224     decoder
->flex_state       
= 0; 
 225     decoder
->num_flex_vectors 
= 0; 
 229     MEM_Set( &decoder
->builder
, 0, sizeof ( decoder
->builder 
) ); 
 233   /* check that there is enough space for `count' more points */ 
 235   FT_Error  
check_points( Z1_Builder
*  builder
, 
 238     return FT_GlyphLoader_Check_Points( builder
->loader
, count
, 0 ); 
 242   /* add a new point; do not check space */ 
 244   void  add_point( Z1_Builder
*  builder
, 
 249     FT_Outline
*  outline 
= builder
->current
; 
 252     if ( builder
->load_points 
) 
 254       FT_Vector
*  point   
= outline
->points 
+ outline
->n_points
; 
 255       FT_Byte
*    control 
= (FT_Byte
*)outline
->tags 
+ outline
->n_points
; 
 260       *control 
= flag 
? FT_Curve_Tag_On 
: FT_Curve_Tag_Cubic
; 
 262       builder
->last 
= *point
; 
 269   /* check space for a new on-curve point, then add it */ 
 271   FT_Error  
add_point1( Z1_Builder
*  builder
, 
 278     error 
= check_points( builder
, 1 ); 
 280       add_point( builder
, x
, y
, 1 ); 
 286   /* check space for a new contour, then add it */ 
 288   FT_Error  
add_contour( Z1_Builder
*  builder 
) 
 290     FT_Outline
*  outline 
= builder
->current
; 
 294     if ( !builder
->load_points 
) 
 296       outline
->n_contours
++; 
 300     /* reallocate contours array if necessary */ 
 301     error 
= FT_GlyphLoader_Check_Points( builder
->loader
, 0, 1 ); 
 304       if ( outline
->n_contours 
> 0 ) 
 305         outline
->contours
[outline
->n_contours 
- 1] = outline
->n_points 
- 1; 
 307       outline
->n_contours
++; 
 314   /* if a path was begun, add its first on-curve point */ 
 316   FT_Error  
start_point( Z1_Builder
*  builder
, 
 320     /* test whether we are building a new contour */ 
 321     if ( !builder
->path_begun 
) 
 326       builder
->path_begun 
= 1; 
 327       error 
= add_contour( builder 
); 
 331     return add_point1( builder
, x
, y 
); 
 335   /* close the current contour */ 
 337   void  close_contour( Z1_Builder
*  builder 
) 
 339     FT_Outline
*  outline 
= builder
->current
; 
 342     /* XXX: we must not include the last point in the path if it */ 
 343     /*      is located on the first point                        */ 
 344     if ( outline
->n_points 
> 1 ) 
 347       FT_Vector
*  p1    
= outline
->points 
+ first
; 
 348       FT_Vector
*  p2    
= outline
->points 
+ outline
->n_points
-1; 
 351       if ( outline
->n_contours 
> 1 ) 
 353         first 
= outline
->contours
[outline
->n_contours 
- 2] + 1; 
 354         p1    
= outline
->points 
+ first
; 
 357       if ( p1
->x 
== p2
->x 
&& p1
->y 
== p2
->y 
) 
 361     if ( outline
->n_contours 
> 0 ) 
 362       outline
->contours
[outline
->n_contours 
- 1] = outline
->n_points 
- 1; 
 366   /*************************************************************************/ 
 369   /*    lookup_glyph_by_stdcharcode                                        */ 
 372   /*    Looks up a given glyph by its StandardEncoding charcode.  Used     */ 
 373   /*    to implement the SEAC Type 1 operator.                             */ 
 376   /*    face     :: The current face object.                               */ 
 378   /*    charcode :: The character code to look for.                        */ 
 381   /*    A glyph index in the font face.  Returns -1 if the corresponding   */ 
 382   /*    glyph wasn't found.                                                */ 
 385   FT_Int  
lookup_glyph_by_stdcharcode( T1_Face  face
, 
 389     const FT_String
*    glyph_name
; 
 390     PSNames_Interface
*  psnames 
= (PSNames_Interface
*)face
->psnames
; 
 393     /* check range of standard char code */ 
 394     if ( charcode 
< 0 || charcode 
> 255 ) 
 397     glyph_name 
= psnames
->adobe_std_strings( 
 398                    psnames
->adobe_std_encoding
[charcode
]); 
 400     for ( n 
= 0; n 
< face
->type1
.num_glyphs
; n
++ ) 
 402       FT_String
*  name 
= (FT_String
*)face
->type1
.glyph_names
[n
]; 
 405       if ( name 
&& strcmp( name
,glyph_name 
) == 0 ) 
 413   /*************************************************************************/ 
 416   /*    t1operator_seac                                                    */ 
 419   /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */ 
 422   /*    decoder :: The current CID decoder.                                */ 
 424   /*    asb     :: The accent's side bearing.                              */ 
 426   /*    adx     :: The horizontal offset of the accent.                    */ 
 428   /*    ady     :: The vertical offset of the accent.                      */ 
 430   /*    bchar   :: The base character's StandardEncoding charcode.         */ 
 432   /*    achar   :: The accent character's StandardEncoding charcode.       */ 
 435   /*    FreeType error code.  0 means success.                             */ 
 438   FT_Error  
t1operator_seac( Z1_Decoder
*  decoder
, 
 446     FT_Int       bchar_index
, achar_index
, n_base_points
; 
 447     FT_Outline
*  base 
= decoder
->builder
.base
; 
 448     FT_Vector    left_bearing
, advance
; 
 449     T1_Face      face  
= decoder
->builder
.face
; 
 450     T1_Font
*     type1 
= &face
->type1
; 
 453     bchar_index 
= lookup_glyph_by_stdcharcode( face
, bchar 
); 
 454     achar_index 
= lookup_glyph_by_stdcharcode( face
, achar 
); 
 456     if ( bchar_index 
< 0 || achar_index 
< 0 ) 
 458       FT_ERROR(( "t1operator_seac:" )); 
 459       FT_ERROR(( " invalid seac character code arguments\n" )); 
 460       return T1_Err_Syntax_Error
; 
 463     /* if we are trying to load a composite glyph, do not load the */ 
 464     /* accent character and return the array of subglyphs.         */ 
 465     if ( decoder
->builder
.no_recurse 
) 
 467       FT_GlyphSlot     glyph  
= (FT_GlyphSlot
)decoder
->builder
.glyph
; 
 468       FT_GlyphLoader
*  loader 
= glyph
->loader
; 
 472       /* reallocate subglyph array if necessary */ 
 473       error 
= FT_GlyphLoader_Check_Subglyphs( loader
, 2 ); 
 477       subg 
= loader
->current
.subglyphs
; 
 479       /* subglyph 0 = base character */ 
 480       subg
->index 
= bchar_index
; 
 481       subg
->flags 
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 
| 
 482                     FT_SUBGLYPH_FLAG_USE_MY_METRICS
; 
 487       /* subglyph 1 = accent character */ 
 488       subg
->index 
= achar_index
; 
 489       subg
->flags 
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
; 
 490       subg
->arg1  
= adx 
- asb
; 
 493       /* set up remaining glyph fields */ 
 494       glyph
->num_subglyphs 
= 2; 
 495       glyph
->subglyphs     
= loader
->base
.subglyphs
; 
 496       glyph
->format        
= ft_glyph_format_composite
; 
 498       loader
->current
.num_subglyphs 
= 2; 
 501     /* First load `bchar' in builder */ 
 502     /* now load the unscaled outline */ 
 504     FT_GlyphLoader_Prepare( decoder
->builder
.loader 
);  /* prepare loader */ 
 506     error 
= Z1_Parse_CharStrings( decoder
, 
 507                                   type1
->charstrings    
[bchar_index
], 
 508                                   type1
->charstrings_len
[bchar_index
], 
 515     n_base_points 
= base
->n_points
; 
 517     /* save the left bearing and width of the base character */ 
 518     /* as they will be erased by the next load.              */ 
 520     left_bearing 
= decoder
->builder
.left_bearing
; 
 521     advance      
= decoder
->builder
.advance
; 
 523     decoder
->builder
.left_bearing
.x 
= 0; 
 524     decoder
->builder
.left_bearing
.y 
= 0; 
 526     /* Now load `achar' on top of */ 
 527     /* the base outline           */ 
 528     error 
= Z1_Parse_CharStrings( decoder
, 
 529                                   type1
->charstrings    
[achar_index
], 
 530                                   type1
->charstrings_len
[achar_index
], 
 537     /* restore the left side bearing and   */ 
 538     /* advance width of the base character */ 
 540     decoder
->builder
.left_bearing 
= left_bearing
; 
 541     decoder
->builder
.advance      
= advance
; 
 543     /* Finally, move the accent */ 
 544     if ( decoder
->builder
.load_points 
) 
 549       dummy
.n_points 
= base
->n_points 
- n_base_points
; 
 550       dummy
.points   
= base
->points   
+ n_base_points
; 
 551       FT_Outline_Translate( &dummy
, adx 
- asb
, ady 
); 
 559 #define USE_ARGS( n )  do                            \ 
 562                          if ( top < decoder->stack ) \ 
 563                            goto Stack_Underflow;     \ 
 567   /*************************************************************************/ 
 570   /*    Z1_Parse_CharStrings                                               */ 
 573   /*    Parses a given Type 1 charstrings program.                         */ 
 576   /*    decoder         :: The current Type 1 decoder.                     */ 
 578   /*    charstring_base :: The base address of the charstring stream.      */ 
 580   /*    charstring_len  :: The length in bytes of the charstring stream.   */ 
 582   /*    num_subrs       :: The number of sub-routines.                     */ 
 584   /*    subrs_base      :: An array of sub-routines addresses.             */ 
 586   /*    subrs_len       :: An array of sub-routines lengths.               */ 
 589   /*    Free error code.  0 means success.                                 */ 
 592   FT_Error  
Z1_Parse_CharStrings( Z1_Decoder
*  decoder
, 
 593                                   FT_Byte
*     charstring_base
, 
 594                                   FT_Int       charstring_len
, 
 596                                   FT_Byte
**    subrs_base
, 
 600     Z1_Decoder_Zone
*  zone
; 
 603     Z1_Builder
*       builder 
= &decoder
->builder
; 
 608     /* First of all, initialize the decoder */ 
 609     decoder
->top  
= decoder
->stack
; 
 610     decoder
->zone 
= decoder
->zones
; 
 611     zone          
= decoder
->zones
; 
 613     builder
->path_begun  
= 0; 
 615     zone
->base           
= charstring_base
; 
 616     limit 
= zone
->limit  
= charstring_base 
+ charstring_len
; 
 617     ip    
= zone
->cursor 
= zone
->base
; 
 620     outline 
= builder
->current
; 
 625     /* now, execute loop */ 
 628       FT_Int
*      top   
= decoder
->top
; 
 629       Z1_Operator  op    
= op_none
; 
 633       /*********************************************************************/ 
 635       /* Decode operator or operand                                        */ 
 639       /* first of all, decompress operator or value */ 
 698           FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+EOF)\n" )); 
 723           op 
= op_callothersubr
; 
 729           op 
= op_setcurrentpoint
; 
 733           FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n", 
 739       case 255:    /* four bytes integer */ 
 740         if ( ip 
+ 4 > limit 
) 
 742           FT_ERROR(( "Z1_Parse_CharStrings: unexpected EOF in integer\n" )); 
 746         value 
= ( (FT_Long
)ip
[0] << 24 ) | 
 747                 ( (FT_Long
)ip
[1] << 16 ) | 
 748                 ( (FT_Long
)ip
[2] << 8  ) | 
 757             value 
= (FT_Long
)ip
[-1] - 139; 
 762               FT_ERROR(( "Z1_Parse_CharStrings:" )); 
 763               FT_ERROR(( " unexpected EOF in integer\n" )); 
 768             value 
=  ( (FT_Long
)( ip
[-2] - 247 ) << 8 ) + ip
[-1] + 108; 
 770             value 
= -( ( ( (FT_Long
)ip
[-2] - 251 ) << 8 ) + ip
[-1] + 108 ); 
 775           FT_ERROR(( "Z1_Parse_CharStrings: invalid byte (%d)\n", 
 781       /*********************************************************************/ 
 783       /*  Push value on stack, or process operator                         */ 
 788         if ( top 
- decoder
->stack 
>= T1_MAX_CHARSTRINGS_OPERANDS 
) 
 790           FT_ERROR(( "Z1_Parse_CharStrings: stack overflow!\n" )); 
 794         FT_TRACE4(( " %ld", value 
)); 
 799       else if ( op 
== op_callothersubr 
)  /* callothersubr */ 
 801         FT_TRACE4(( " callothersubr" )); 
 803         if ( top 
- decoder
->stack 
< 2 ) 
 804           goto Stack_Underflow
; 
 809         case 1:                     /* start flex feature */ 
 811             goto Unexpected_OtherSubr
; 
 813           decoder
->flex_state        
= 1; 
 814           decoder
->num_flex_vectors  
= 0; 
 815           if ( start_point( builder
, x
, y 
) || 
 816                check_points( builder
, 6 )   ) 
 820         case 2:                     /* add flex vectors */ 
 825               goto Unexpected_OtherSubr
; 
 827             /* note that we should not add a point for index 0; */ 
 828             /* this will move our current position to the flex  */ 
 829             /* point without adding any point to the outline    */ 
 830             index 
= decoder
->num_flex_vectors
++; 
 831             if ( index 
> 0 && index 
< 7 ) 
 835                          (FT_Byte
)( index 
== 3 || index 
== 6 ) ); 
 839         case 0:                     /* end flex feature */ 
 841             goto Unexpected_OtherSubr
; 
 843           if ( decoder
->flex_state       
== 0 || 
 844                decoder
->num_flex_vectors 
!= 7 ) 
 846             FT_ERROR(( "Z1_Parse_CharStrings: unexpected flex end\n" )); 
 850           /* now consume the remaining `pop pop setcurpoint' */ 
 851           if ( ip 
+ 6 > limit 
|| 
 852                ip
[0] != 12 || ip
[1] != 17 || /* pop */ 
 853                ip
[2] != 12 || ip
[3] != 17 || /* pop */ 
 854                ip
[4] != 12 || ip
[5] != 33 )  /* setcurpoint */ 
 856             FT_ERROR(( "Z1_Parse_CharStrings: invalid flex charstring\n" )); 
 861           decoder
->flex_state 
= 0; 
 864         case 3:                     /* change hints */ 
 866             goto Unexpected_OtherSubr
; 
 868           /* eat the following `pop' */ 
 869           if ( ip 
+ 2 > limit 
) 
 871             FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n", 
 876           if ( ip
[0] != 12 || ip
[1] != 17 ) 
 878             FT_ERROR(( "Z1_Parse_CharStrings:" )); 
 879             FT_ERROR(( " `pop' expected, found (%d %d)\n", 
 888           /* counter control hints, clear stack */ 
 889           top 
= decoder
->stack
; 
 896         case 18:                    /* multiple masters */ 
 898             T1_Blend
*  blend 
= decoder
->blend
; 
 899             FT_UInt    num_points
, nn
, mm
; 
 906               FT_ERROR(( "Z1_Parse_CharStrings:" )); 
 907               FT_ERROR(( " unexpected multiple masters operator!\n" )); 
 911             num_points 
= top
[1] - 13 + ( top
[1] == 18 ); 
 912             if ( top
[0] != (FT_Int
)( num_points 
* blend
->num_designs 
) ) 
 914               FT_ERROR(( "Z1_Parse_CharStrings:" )); 
 915               FT_ERROR(( " incorrect number of mm arguments\n" )); 
 919             top 
-= blend
->num_designs
*num_points
; 
 920             if ( top 
< decoder
->stack 
) 
 921               goto Stack_Underflow
; 
 923             /* we want to compute:                                   */ 
 925             /*  a0*w0 + a1*w1 + ... + ak*wk                          */ 
 927             /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */ 
 928             /* however, given that w0 + w1 + ... + wk == 1, we can   */ 
 929             /* rewrite it easily as:                                 */ 
 931             /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */ 
 933             /* where k == num_designs-1                              */ 
 935             /* I guess that's why it's written in this `compact'     */ 
 938             delta  
= top 
+ num_points
; 
 940             for ( nn 
= 0; nn 
< num_points
; nn
++ ) 
 942               FT_Int  x 
= values
[0]; 
 945               for ( mm 
= 1; mm 
< blend
->num_designs
; mm
++ ) 
 946                 x 
+= FT_MulFix( *delta
++, blend
->weight_vector
[mm
] ); 
 950             /* note that `top' will be incremented later by calls to `pop' */ 
 955         Unexpected_OtherSubr
: 
 956           FT_ERROR(( "Z1_Parse_CharStrings: invalid othersubr [%d %d]!\n", 
 962       else  /* general operator */ 
 964         FT_Int  num_args 
= t1_args_count
[op
]; 
 967         if ( top 
- decoder
->stack 
< num_args 
) 
 968           goto Stack_Underflow
; 
 975           FT_TRACE4(( " endchar" )); 
 977           close_contour( builder 
); 
 979           /* add current outline to the glyph slot */ 
 980           FT_GlyphLoader_Add( builder
->loader 
); 
 983           FT_TRACE4(( "\n\n" )); 
 987           FT_TRACE4(( " hsbw" )); 
 989           builder
->left_bearing
.x 
+= top
[0]; 
 990           builder
->advance
.x       
= top
[1]; 
 991           builder
->advance
.y       
= 0; 
 993           builder
->last
.x 
= x 
= top
[0]; 
 994           builder
->last
.y 
= y 
= 0; 
 996           /* the `metrics_only' indicates that we only want to compute */ 
 997           /* the glyph's metrics (lsb + advance width), not load the   */ 
 998           /* rest of it; so exit immediately                           */ 
 999           if ( builder
->metrics_only 
) 
1005           /* return immediately after the processing */ 
1006           return t1operator_seac( decoder
, top
[0], top
[1], 
1007                                            top
[2], top
[3], top
[4] ); 
1010           FT_TRACE4(( " sbw" )); 
1012           builder
->left_bearing
.x 
+= top
[0]; 
1013           builder
->left_bearing
.y 
+= top
[1]; 
1014           builder
->advance
.x       
= top
[2]; 
1015           builder
->advance
.y       
= top
[3]; 
1017           builder
->last
.x 
= x 
= top
[0]; 
1018           builder
->last
.y 
= y 
= top
[1]; 
1020           /* the `metrics_only' indicates that we only want to compute */ 
1021           /* the glyph's metrics (lsb + advance width), not load the   */ 
1022           /* rest of it; so exit immediately                           */ 
1023           if ( builder
->metrics_only 
) 
1029           FT_TRACE4(( " closepath" )); 
1031           close_contour( builder 
); 
1032           builder
->path_begun 
= 0; 
1036           FT_TRACE4(( " hlineto" )); 
1038           if ( start_point( builder
, x
, y 
) ) 
1045           FT_TRACE4(( " hmoveto" )); 
1051           FT_TRACE4(( " hvcurveto" )); 
1053           if ( start_point( builder
, x
, y 
) || 
1054                check_points( builder
, 3 )   ) 
1058           add_point( builder
, x
, y
, 0 ); 
1061           add_point( builder
, x
, y
, 0 ); 
1063           add_point( builder
, x
, y
, 1 ); 
1067           FT_TRACE4(( " rlineto" )); 
1069           if ( start_point( builder
, x
, y 
) ) 
1076           if ( add_point1( builder
, x
, y 
) ) 
1081           FT_TRACE4(( " rmoveto" )); 
1088           FT_TRACE4(( " rcurveto" )); 
1090           if ( start_point( builder
, x
, y 
) || 
1091                check_points( builder
, 3 )   ) 
1096           add_point( builder
, x
, y
, 0 ); 
1100           add_point( builder
, x
, y
, 0 ); 
1104           add_point( builder
, x
, y
, 1 ); 
1108           FT_TRACE4(( " vhcurveto" )); 
1110           if ( start_point( builder
, x
, y 
) || 
1111                check_points( builder
, 3 )   ) 
1115           add_point( builder
, x
, y
, 0 ); 
1118           add_point( builder
, x
, y
, 0 ); 
1120           add_point( builder
, x
, y
, 1 ); 
1124           FT_TRACE4(( " vlineto" )); 
1126           if ( start_point( builder
, x
, y 
) ) 
1133           FT_TRACE4(( " vmoveto" )); 
1139           FT_TRACE4(( " div" )); 
1143             *top 
= top
[0] / top
[1]; 
1148             FT_ERROR(( "Z1_Parse_CharStrings: division by 0\n" )); 
1158             FT_TRACE4(( " callsubr" )); 
1161             if ( index 
< 0 || index 
>= num_subrs 
) 
1163               FT_ERROR(( "Z1_Parse_CharStrings: invalid subrs index\n" )); 
1167             if ( zone 
- decoder
->zones 
>= T1_MAX_SUBRS_CALLS 
) 
1169               FT_ERROR(( "Z1_Parse_CharStrings: too many nested subrs\n" )); 
1173             zone
->cursor 
= ip
;  /* save current instruction pointer */ 
1176             zone
->base   
= subrs_base
[index
]; 
1177             zone
->limit  
= zone
->base 
+ subrs_len
[index
]; 
1178             zone
->cursor 
= zone
->base
; 
1182               FT_ERROR(( "Z1_Parse_CharStrings: invoking empty subrs!\n" )); 
1186             decoder
->zone 
= zone
; 
1188             limit         
= zone
->limit
; 
1193           FT_TRACE4(( " pop" )); 
1195           /* theorically, the arguments are already on the stack */ 
1200           FT_TRACE4(( " return" )); 
1202           if ( zone 
<= decoder
->zones 
) 
1204             FT_ERROR(( "Z1_Parse_CharStrings: unexpected return\n" )); 
1210           limit         
= zone
->limit
; 
1211           decoder
->zone 
= zone
; 
1215           FT_TRACE4(( " dotsection" )); 
1220           FT_TRACE4(( " hstem" )); 
1225           FT_TRACE4(( " hstem3" )); 
1230           FT_TRACE4(( " vstem" )); 
1235           FT_TRACE4(( " vstem3" )); 
1239         case op_setcurrentpoint
: 
1240           FT_TRACE4(( " setcurrentpoint" )); 
1242           FT_ERROR(( "Z1_Parse_CharStrings:" )); 
1243           FT_ERROR(( " unexpected `setcurrentpoint'\n" )); 
1247           FT_ERROR(( "Z1_Parse_CharStrings: unhandled opcode %d\n", op 
)); 
1253       } /* general operator processing */ 
1255     } /* while ip < limit */ 
1257     FT_TRACE4(( "..end..\n\n" )); 
1261     return T1_Err_Syntax_Error
; 
1264     return T1_Err_Stack_Underflow
; 
1267     return builder
->error
; 
1271   /*************************************************************************/ 
1272   /*************************************************************************/ 
1273   /*************************************************************************/ 
1274   /**********                                                      *********/ 
1275   /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/ 
1276   /**********                                                      *********/ 
1277   /**********    The following code is in charge of computing      *********/ 
1278   /**********    the maximum advance width of the font.  It        *********/ 
1279   /**********    quickly processes each glyph charstring to        *********/ 
1280   /**********    extract the value from either a `sbw' or `seac'   *********/ 
1281   /**********    operator.                                         *********/ 
1282   /**********                                                      *********/ 
1283   /*************************************************************************/ 
1284   /*************************************************************************/ 
1285   /*************************************************************************/ 
1289   FT_Error  
Z1_Compute_Max_Advance( T1_Face  face
, 
1290                                     FT_Int
*  max_advance 
) 
1295     T1_Font
*    type1 
= &face
->type1
; 
1300     /* Initialize load decoder */ 
1301     Z1_Init_Decoder( &decoder 
); 
1302     Z1_Init_Builder( &decoder
.builder
, face
, 0, 0 ); 
1304     decoder
.blend                
= face
->blend
; 
1305     decoder
.builder
.metrics_only 
= 1; 
1306     decoder
.builder
.load_points  
= 0; 
1308     /* for each glyph, parse the glyph charstring and extract */ 
1309     /* the advance width                                      */ 
1310     for ( glyph_index 
= 0; glyph_index 
< type1
->num_glyphs
; glyph_index
++ ) 
1312       /* now get load the unscaled outline */ 
1313       error 
= Z1_Parse_CharStrings( &decoder
, 
1314                                     type1
->charstrings    
[glyph_index
], 
1315                                     type1
->charstrings_len
[glyph_index
], 
1319       /* ignore the error if one occured - skip to next glyph */ 
1322     *max_advance 
= decoder
.builder
.advance
.x
; 
1327   /*************************************************************************/ 
1328   /*************************************************************************/ 
1329   /*************************************************************************/ 
1330   /**********                                                      *********/ 
1331   /**********               UNHINTED GLYPH LOADER                  *********/ 
1332   /**********                                                      *********/ 
1333   /**********    The following code is in charge of loading a      *********/ 
1334   /**********    single outline.  It completely ignores hinting    *********/ 
1335   /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/ 
1336   /**********                                                      *********/ 
1337   /**********      The Type 1 hinter is located in `t1hint.c'      *********/ 
1338   /**********                                                      *********/ 
1339   /*************************************************************************/ 
1340   /*************************************************************************/ 
1341   /*************************************************************************/ 
1345   FT_Error  
Z1_Load_Glyph( Z1_GlyphSlot  glyph
, 
1352     T1_Face     face 
= (T1_Face
)glyph
->root
.face
; 
1354     T1_Font
*    type1 
= &face
->type1
; 
1357     if ( load_flags 
& FT_LOAD_NO_RECURSE 
) 
1358       load_flags 
|= FT_LOAD_NO_SCALE 
| FT_LOAD_NO_HINTING
; 
1360     glyph
->x_scale 
= size
->root
.metrics
.x_scale
; 
1361     glyph
->y_scale 
= size
->root
.metrics
.y_scale
; 
1363     glyph
->root
.outline
.n_points   
= 0; 
1364     glyph
->root
.outline
.n_contours 
= 0; 
1366     hinting 
= ( load_flags 
& FT_LOAD_NO_SCALE   
) == 0 && 
1367               ( load_flags 
& FT_LOAD_NO_HINTING 
) == 0; 
1369     glyph
->root
.format 
= ft_glyph_format_outline
; 
1371     Z1_Init_Decoder( &decoder 
); 
1372     Z1_Init_Builder( &decoder
.builder
, face
, size
, glyph 
); 
1374     decoder
.blend              
= ((T1_Face
)glyph
->root
.face
)->blend
; 
1375     decoder
.builder
.no_recurse 
= ( load_flags 
& FT_LOAD_NO_RECURSE 
) != 0; 
1377     /* now load the unscaled outline */ 
1378     error 
= Z1_Parse_CharStrings( &decoder
, 
1379                                   type1
->charstrings    
[glyph_index
], 
1380                                   type1
->charstrings_len
[glyph_index
], 
1385     /* save new glyph tables */ 
1386     Z1_Done_Builder( &decoder
.builder 
); 
1388     /* now, set the metrics -- this is rather simple, as   */ 
1389     /* the left side bearing is the xMin, and the top side */ 
1390     /* bearing the yMax                                    */ 
1393       glyph
->root
.outline
.flags 
&= ft_outline_owner
; 
1394       glyph
->root
.outline
.flags 
|= ft_outline_reverse_fill
; 
1396       /* for composite glyphs, return only left side bearing and */ 
1398       if ( load_flags 
& FT_LOAD_NO_RECURSE 
) 
1400         glyph
->root
.metrics
.horiBearingX 
= decoder
.builder
.left_bearing
.x
; 
1401         glyph
->root
.metrics
.horiAdvance  
= decoder
.builder
.advance
.x
; 
1406         FT_Glyph_Metrics
* metrics 
= &glyph
->root
.metrics
; 
1409         /* copy the _unscaled_ advance width */ 
1410         metrics
->horiAdvance 
= decoder
.builder
.advance
.x
; 
1412         /* make up vertical metrics */ 
1413         metrics
->vertBearingX 
= 0; 
1414         metrics
->vertBearingY 
= 0; 
1415         metrics
->vertAdvance  
= 0; 
1417         glyph
->root
.format 
= ft_glyph_format_outline
; 
1419         if ( size 
&& size
->root
.metrics
.y_ppem 
< 24 ) 
1420           glyph
->root
.outline
.flags 
|= ft_outline_high_precision
; 
1423         glyph
->root
.outline
.second_pass    
= TRUE
; 
1424         glyph
->root
.outline
.high_precision 
= size
->root
.metrics
.y_ppem 
< 24; 
1425         glyph
->root
.outline
.dropout_mode   
= 2; 
1428         if ( ( load_flags 
& FT_LOAD_NO_SCALE 
) == 0 ) 
1430           /* scale the outline and the metrics */ 
1432           FT_Outline
*  cur 
= decoder
.builder
.base
; 
1433           FT_Vector
*   vec 
= cur
->points
; 
1434           FT_Fixed     x_scale 
= glyph
->x_scale
; 
1435           FT_Fixed     y_scale 
= glyph
->y_scale
; 
1438           /* First of all, scale the points */ 
1439           for ( n 
= cur
->n_points
; n 
> 0; n
--, vec
++ ) 
1441             vec
->x 
= FT_MulFix( vec
->x
, x_scale 
); 
1442             vec
->y 
= FT_MulFix( vec
->y
, y_scale 
); 
1445           FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox 
); 
1447           /* Then scale the metrics */ 
1448           metrics
->horiAdvance  
= FT_MulFix( metrics
->horiAdvance
,  x_scale 
); 
1449           metrics
->vertAdvance  
= FT_MulFix( metrics
->vertAdvance
,  y_scale 
); 
1451           metrics
->vertBearingX 
= FT_MulFix( metrics
->vertBearingX
, x_scale 
); 
1452           metrics
->vertBearingY 
= FT_MulFix( metrics
->vertBearingY
, y_scale 
); 
1455         /* apply the font matrix */ 
1456         FT_Outline_Transform( &glyph
->root
.outline
, 
1457                               &face
->type1
.font_matrix 
); 
1459         /* compute the other metrics */ 
1460         FT_Outline_Get_CBox( &glyph
->root
.outline
, &cbox 
); 
1462         /* grid fit the bounding box if necessary */ 
1467           cbox
.xMax  
= ( cbox
.xMax
+63 ) & -64; 
1468           cbox
.yMax  
= ( cbox
.yMax
+63 ) & -64; 
1471         metrics
->width  
= cbox
.xMax 
- cbox
.xMin
; 
1472         metrics
->height 
= cbox
.yMax 
- cbox
.yMin
; 
1474         metrics
->horiBearingX 
= cbox
.xMin
; 
1475         metrics
->horiBearingY 
= cbox
.yMax
;