1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* cffgload.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* OpenType Glyph Loader (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 1996-2001, 2002 by */ 8*37da2899SCharles.Forsyth /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9*37da2899SCharles.Forsyth /* */ 10*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 11*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 12*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 14*37da2899SCharles.Forsyth /* understand and accept it fully. */ 15*37da2899SCharles.Forsyth /* */ 16*37da2899SCharles.Forsyth /***************************************************************************/ 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth #include <ft2build.h> 20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 21*37da2899SCharles.Forsyth #include FT_INTERNAL_CALC_H 22*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H 23*37da2899SCharles.Forsyth #include FT_INTERNAL_SFNT_H 24*37da2899SCharles.Forsyth #include FT_OUTLINE_H 25*37da2899SCharles.Forsyth #include FT_TRUETYPE_TAGS_H 26*37da2899SCharles.Forsyth #include FT_INTERNAL_POSTSCRIPT_HINTS_H 27*37da2899SCharles.Forsyth 28*37da2899SCharles.Forsyth #include "cffobjs.h" 29*37da2899SCharles.Forsyth #include "cffload.h" 30*37da2899SCharles.Forsyth #include "cffgload.h" 31*37da2899SCharles.Forsyth 32*37da2899SCharles.Forsyth #include "cfferrs.h" 33*37da2899SCharles.Forsyth 34*37da2899SCharles.Forsyth 35*37da2899SCharles.Forsyth /*************************************************************************/ 36*37da2899SCharles.Forsyth /* */ 37*37da2899SCharles.Forsyth /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 38*37da2899SCharles.Forsyth /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 39*37da2899SCharles.Forsyth /* messages during execution. */ 40*37da2899SCharles.Forsyth /* */ 41*37da2899SCharles.Forsyth #undef FT_COMPONENT 42*37da2899SCharles.Forsyth #define FT_COMPONENT trace_cffgload 43*37da2899SCharles.Forsyth 44*37da2899SCharles.Forsyth 45*37da2899SCharles.Forsyth typedef enum CFF_Operator_ 46*37da2899SCharles.Forsyth { 47*37da2899SCharles.Forsyth cff_op_unknown = 0, 48*37da2899SCharles.Forsyth 49*37da2899SCharles.Forsyth cff_op_rmoveto, 50*37da2899SCharles.Forsyth cff_op_hmoveto, 51*37da2899SCharles.Forsyth cff_op_vmoveto, 52*37da2899SCharles.Forsyth 53*37da2899SCharles.Forsyth cff_op_rlineto, 54*37da2899SCharles.Forsyth cff_op_hlineto, 55*37da2899SCharles.Forsyth cff_op_vlineto, 56*37da2899SCharles.Forsyth 57*37da2899SCharles.Forsyth cff_op_rrcurveto, 58*37da2899SCharles.Forsyth cff_op_hhcurveto, 59*37da2899SCharles.Forsyth cff_op_hvcurveto, 60*37da2899SCharles.Forsyth cff_op_rcurveline, 61*37da2899SCharles.Forsyth cff_op_rlinecurve, 62*37da2899SCharles.Forsyth cff_op_vhcurveto, 63*37da2899SCharles.Forsyth cff_op_vvcurveto, 64*37da2899SCharles.Forsyth 65*37da2899SCharles.Forsyth cff_op_flex, 66*37da2899SCharles.Forsyth cff_op_hflex, 67*37da2899SCharles.Forsyth cff_op_hflex1, 68*37da2899SCharles.Forsyth cff_op_flex1, 69*37da2899SCharles.Forsyth 70*37da2899SCharles.Forsyth cff_op_endchar, 71*37da2899SCharles.Forsyth 72*37da2899SCharles.Forsyth cff_op_hstem, 73*37da2899SCharles.Forsyth cff_op_vstem, 74*37da2899SCharles.Forsyth cff_op_hstemhm, 75*37da2899SCharles.Forsyth cff_op_vstemhm, 76*37da2899SCharles.Forsyth 77*37da2899SCharles.Forsyth cff_op_hintmask, 78*37da2899SCharles.Forsyth cff_op_cntrmask, 79*37da2899SCharles.Forsyth cff_op_dotsection, /* deprecated, acts as no-op */ 80*37da2899SCharles.Forsyth 81*37da2899SCharles.Forsyth cff_op_abs, 82*37da2899SCharles.Forsyth cff_op_add, 83*37da2899SCharles.Forsyth cff_op_sub, 84*37da2899SCharles.Forsyth cff_op_div, 85*37da2899SCharles.Forsyth cff_op_neg, 86*37da2899SCharles.Forsyth cff_op_random, 87*37da2899SCharles.Forsyth cff_op_mul, 88*37da2899SCharles.Forsyth cff_op_sqrt, 89*37da2899SCharles.Forsyth 90*37da2899SCharles.Forsyth cff_op_blend, 91*37da2899SCharles.Forsyth 92*37da2899SCharles.Forsyth cff_op_drop, 93*37da2899SCharles.Forsyth cff_op_exch, 94*37da2899SCharles.Forsyth cff_op_index, 95*37da2899SCharles.Forsyth cff_op_roll, 96*37da2899SCharles.Forsyth cff_op_dup, 97*37da2899SCharles.Forsyth 98*37da2899SCharles.Forsyth cff_op_put, 99*37da2899SCharles.Forsyth cff_op_get, 100*37da2899SCharles.Forsyth cff_op_store, 101*37da2899SCharles.Forsyth cff_op_load, 102*37da2899SCharles.Forsyth 103*37da2899SCharles.Forsyth cff_op_and, 104*37da2899SCharles.Forsyth cff_op_or, 105*37da2899SCharles.Forsyth cff_op_not, 106*37da2899SCharles.Forsyth cff_op_eq, 107*37da2899SCharles.Forsyth cff_op_ifelse, 108*37da2899SCharles.Forsyth 109*37da2899SCharles.Forsyth cff_op_callsubr, 110*37da2899SCharles.Forsyth cff_op_callgsubr, 111*37da2899SCharles.Forsyth cff_op_return, 112*37da2899SCharles.Forsyth 113*37da2899SCharles.Forsyth /* do not remove */ 114*37da2899SCharles.Forsyth cff_op_max 115*37da2899SCharles.Forsyth 116*37da2899SCharles.Forsyth } CFF_Operator; 117*37da2899SCharles.Forsyth 118*37da2899SCharles.Forsyth 119*37da2899SCharles.Forsyth #define CFF_COUNT_CHECK_WIDTH 0x80 120*37da2899SCharles.Forsyth #define CFF_COUNT_EXACT 0x40 121*37da2899SCharles.Forsyth #define CFF_COUNT_CLEAR_STACK 0x20 122*37da2899SCharles.Forsyth 123*37da2899SCharles.Forsyth 124*37da2899SCharles.Forsyth static const FT_Byte cff_argument_counts[] = 125*37da2899SCharles.Forsyth { 126*37da2899SCharles.Forsyth 0, /* unknown */ 127*37da2899SCharles.Forsyth 128*37da2899SCharles.Forsyth 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */ 129*37da2899SCharles.Forsyth 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, 130*37da2899SCharles.Forsyth 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, 131*37da2899SCharles.Forsyth 132*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */ 133*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, 134*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, 135*37da2899SCharles.Forsyth 136*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */ 137*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, 138*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, 139*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, 140*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, 141*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, 142*37da2899SCharles.Forsyth 0 | CFF_COUNT_CLEAR_STACK, 143*37da2899SCharles.Forsyth 144*37da2899SCharles.Forsyth 13, /* flex */ 145*37da2899SCharles.Forsyth 7, 146*37da2899SCharles.Forsyth 9, 147*37da2899SCharles.Forsyth 11, 148*37da2899SCharles.Forsyth 149*37da2899SCharles.Forsyth 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */ 150*37da2899SCharles.Forsyth 151*37da2899SCharles.Forsyth 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */ 152*37da2899SCharles.Forsyth 2 | CFF_COUNT_CHECK_WIDTH, 153*37da2899SCharles.Forsyth 2 | CFF_COUNT_CHECK_WIDTH, 154*37da2899SCharles.Forsyth 2 | CFF_COUNT_CHECK_WIDTH, 155*37da2899SCharles.Forsyth 156*37da2899SCharles.Forsyth 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */ 157*37da2899SCharles.Forsyth 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */ 158*37da2899SCharles.Forsyth 0, /* dotsection */ 159*37da2899SCharles.Forsyth 160*37da2899SCharles.Forsyth 1, /* abs */ 161*37da2899SCharles.Forsyth 2, 162*37da2899SCharles.Forsyth 2, 163*37da2899SCharles.Forsyth 2, 164*37da2899SCharles.Forsyth 1, 165*37da2899SCharles.Forsyth 0, 166*37da2899SCharles.Forsyth 2, 167*37da2899SCharles.Forsyth 1, 168*37da2899SCharles.Forsyth 169*37da2899SCharles.Forsyth 1, /* blend */ 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth 1, /* drop */ 172*37da2899SCharles.Forsyth 2, 173*37da2899SCharles.Forsyth 1, 174*37da2899SCharles.Forsyth 2, 175*37da2899SCharles.Forsyth 1, 176*37da2899SCharles.Forsyth 177*37da2899SCharles.Forsyth 2, /* put */ 178*37da2899SCharles.Forsyth 1, 179*37da2899SCharles.Forsyth 4, 180*37da2899SCharles.Forsyth 3, 181*37da2899SCharles.Forsyth 182*37da2899SCharles.Forsyth 2, /* and */ 183*37da2899SCharles.Forsyth 2, 184*37da2899SCharles.Forsyth 1, 185*37da2899SCharles.Forsyth 2, 186*37da2899SCharles.Forsyth 4, 187*37da2899SCharles.Forsyth 188*37da2899SCharles.Forsyth 1, /* callsubr */ 189*37da2899SCharles.Forsyth 1, 190*37da2899SCharles.Forsyth 0 191*37da2899SCharles.Forsyth }; 192*37da2899SCharles.Forsyth 193*37da2899SCharles.Forsyth 194*37da2899SCharles.Forsyth /*************************************************************************/ 195*37da2899SCharles.Forsyth /*************************************************************************/ 196*37da2899SCharles.Forsyth /*************************************************************************/ 197*37da2899SCharles.Forsyth /********** *********/ 198*37da2899SCharles.Forsyth /********** *********/ 199*37da2899SCharles.Forsyth /********** GENERIC CHARSTRING PARSING *********/ 200*37da2899SCharles.Forsyth /********** *********/ 201*37da2899SCharles.Forsyth /********** *********/ 202*37da2899SCharles.Forsyth /*************************************************************************/ 203*37da2899SCharles.Forsyth /*************************************************************************/ 204*37da2899SCharles.Forsyth /*************************************************************************/ 205*37da2899SCharles.Forsyth 206*37da2899SCharles.Forsyth 207*37da2899SCharles.Forsyth /*************************************************************************/ 208*37da2899SCharles.Forsyth /* */ 209*37da2899SCharles.Forsyth /* <Function> */ 210*37da2899SCharles.Forsyth /* cff_builder_init */ 211*37da2899SCharles.Forsyth /* */ 212*37da2899SCharles.Forsyth /* <Description> */ 213*37da2899SCharles.Forsyth /* Initializes a given glyph builder. */ 214*37da2899SCharles.Forsyth /* */ 215*37da2899SCharles.Forsyth /* <InOut> */ 216*37da2899SCharles.Forsyth /* builder :: A pointer to the glyph builder to initialize. */ 217*37da2899SCharles.Forsyth /* */ 218*37da2899SCharles.Forsyth /* <Input> */ 219*37da2899SCharles.Forsyth /* face :: The current face object. */ 220*37da2899SCharles.Forsyth /* */ 221*37da2899SCharles.Forsyth /* size :: The current size object. */ 222*37da2899SCharles.Forsyth /* */ 223*37da2899SCharles.Forsyth /* glyph :: The current glyph object. */ 224*37da2899SCharles.Forsyth /* */ 225*37da2899SCharles.Forsyth static void cff_builder_init(CFF_Builder * builder,TT_Face face,CFF_Size size,CFF_GlyphSlot glyph,FT_Bool hinting)226*37da2899SCharles.Forsyth cff_builder_init( CFF_Builder* builder, 227*37da2899SCharles.Forsyth TT_Face face, 228*37da2899SCharles.Forsyth CFF_Size size, 229*37da2899SCharles.Forsyth CFF_GlyphSlot glyph, 230*37da2899SCharles.Forsyth FT_Bool hinting ) 231*37da2899SCharles.Forsyth { 232*37da2899SCharles.Forsyth builder->path_begun = 0; 233*37da2899SCharles.Forsyth builder->load_points = 1; 234*37da2899SCharles.Forsyth 235*37da2899SCharles.Forsyth builder->face = face; 236*37da2899SCharles.Forsyth builder->glyph = glyph; 237*37da2899SCharles.Forsyth builder->memory = face->root.memory; 238*37da2899SCharles.Forsyth 239*37da2899SCharles.Forsyth if ( glyph ) 240*37da2899SCharles.Forsyth { 241*37da2899SCharles.Forsyth FT_GlyphLoader loader = glyph->root.internal->loader; 242*37da2899SCharles.Forsyth 243*37da2899SCharles.Forsyth 244*37da2899SCharles.Forsyth builder->loader = loader; 245*37da2899SCharles.Forsyth builder->base = &loader->base.outline; 246*37da2899SCharles.Forsyth builder->current = &loader->current.outline; 247*37da2899SCharles.Forsyth FT_GlyphLoader_Rewind( loader ); 248*37da2899SCharles.Forsyth 249*37da2899SCharles.Forsyth builder->hint_flags = FT_FACE(face)->internal->hint_flags; 250*37da2899SCharles.Forsyth builder->hints_globals = 0; 251*37da2899SCharles.Forsyth builder->hints_funcs = 0; 252*37da2899SCharles.Forsyth 253*37da2899SCharles.Forsyth if ( hinting && size ) 254*37da2899SCharles.Forsyth { 255*37da2899SCharles.Forsyth builder->hints_globals = size->internal; 256*37da2899SCharles.Forsyth builder->hints_funcs = glyph->root.internal->glyph_hints; 257*37da2899SCharles.Forsyth } 258*37da2899SCharles.Forsyth } 259*37da2899SCharles.Forsyth 260*37da2899SCharles.Forsyth if ( size ) 261*37da2899SCharles.Forsyth { 262*37da2899SCharles.Forsyth builder->scale_x = size->metrics.x_scale; 263*37da2899SCharles.Forsyth builder->scale_y = size->metrics.y_scale; 264*37da2899SCharles.Forsyth } 265*37da2899SCharles.Forsyth 266*37da2899SCharles.Forsyth builder->pos_x = 0; 267*37da2899SCharles.Forsyth builder->pos_y = 0; 268*37da2899SCharles.Forsyth 269*37da2899SCharles.Forsyth builder->left_bearing.x = 0; 270*37da2899SCharles.Forsyth builder->left_bearing.y = 0; 271*37da2899SCharles.Forsyth builder->advance.x = 0; 272*37da2899SCharles.Forsyth builder->advance.y = 0; 273*37da2899SCharles.Forsyth } 274*37da2899SCharles.Forsyth 275*37da2899SCharles.Forsyth 276*37da2899SCharles.Forsyth /*************************************************************************/ 277*37da2899SCharles.Forsyth /* */ 278*37da2899SCharles.Forsyth /* <Function> */ 279*37da2899SCharles.Forsyth /* cff_builder_done */ 280*37da2899SCharles.Forsyth /* */ 281*37da2899SCharles.Forsyth /* <Description> */ 282*37da2899SCharles.Forsyth /* Finalizes a given glyph builder. Its contents can still be used */ 283*37da2899SCharles.Forsyth /* after the call, but the function saves important information */ 284*37da2899SCharles.Forsyth /* within the corresponding glyph slot. */ 285*37da2899SCharles.Forsyth /* */ 286*37da2899SCharles.Forsyth /* <Input> */ 287*37da2899SCharles.Forsyth /* builder :: A pointer to the glyph builder to finalize. */ 288*37da2899SCharles.Forsyth /* */ 289*37da2899SCharles.Forsyth static void cff_builder_done(CFF_Builder * builder)290*37da2899SCharles.Forsyth cff_builder_done( CFF_Builder* builder ) 291*37da2899SCharles.Forsyth { 292*37da2899SCharles.Forsyth CFF_GlyphSlot glyph = builder->glyph; 293*37da2899SCharles.Forsyth 294*37da2899SCharles.Forsyth 295*37da2899SCharles.Forsyth if ( glyph ) 296*37da2899SCharles.Forsyth glyph->root.outline = *builder->base; 297*37da2899SCharles.Forsyth } 298*37da2899SCharles.Forsyth 299*37da2899SCharles.Forsyth 300*37da2899SCharles.Forsyth /*************************************************************************/ 301*37da2899SCharles.Forsyth /* */ 302*37da2899SCharles.Forsyth /* <Function> */ 303*37da2899SCharles.Forsyth /* cff_compute_bias */ 304*37da2899SCharles.Forsyth /* */ 305*37da2899SCharles.Forsyth /* <Description> */ 306*37da2899SCharles.Forsyth /* Computes the bias value in dependence of the number of glyph */ 307*37da2899SCharles.Forsyth /* subroutines. */ 308*37da2899SCharles.Forsyth /* */ 309*37da2899SCharles.Forsyth /* <Input> */ 310*37da2899SCharles.Forsyth /* num_subrs :: The number of glyph subroutines. */ 311*37da2899SCharles.Forsyth /* */ 312*37da2899SCharles.Forsyth /* <Return> */ 313*37da2899SCharles.Forsyth /* The bias value. */ 314*37da2899SCharles.Forsyth static FT_Int cff_compute_bias(FT_UInt num_subrs)315*37da2899SCharles.Forsyth cff_compute_bias( FT_UInt num_subrs ) 316*37da2899SCharles.Forsyth { 317*37da2899SCharles.Forsyth FT_Int result; 318*37da2899SCharles.Forsyth 319*37da2899SCharles.Forsyth 320*37da2899SCharles.Forsyth if ( num_subrs < 1240 ) 321*37da2899SCharles.Forsyth result = 107; 322*37da2899SCharles.Forsyth else if ( num_subrs < 33900U ) 323*37da2899SCharles.Forsyth result = 1131; 324*37da2899SCharles.Forsyth else 325*37da2899SCharles.Forsyth result = 32768U; 326*37da2899SCharles.Forsyth 327*37da2899SCharles.Forsyth return result; 328*37da2899SCharles.Forsyth } 329*37da2899SCharles.Forsyth 330*37da2899SCharles.Forsyth 331*37da2899SCharles.Forsyth /*************************************************************************/ 332*37da2899SCharles.Forsyth /* */ 333*37da2899SCharles.Forsyth /* <Function> */ 334*37da2899SCharles.Forsyth /* cff_decoder_init */ 335*37da2899SCharles.Forsyth /* */ 336*37da2899SCharles.Forsyth /* <Description> */ 337*37da2899SCharles.Forsyth /* Initializes a given glyph decoder. */ 338*37da2899SCharles.Forsyth /* */ 339*37da2899SCharles.Forsyth /* <InOut> */ 340*37da2899SCharles.Forsyth /* decoder :: A pointer to the glyph builder to initialize. */ 341*37da2899SCharles.Forsyth /* */ 342*37da2899SCharles.Forsyth /* <Input> */ 343*37da2899SCharles.Forsyth /* face :: The current face object. */ 344*37da2899SCharles.Forsyth /* */ 345*37da2899SCharles.Forsyth /* size :: The current size object. */ 346*37da2899SCharles.Forsyth /* */ 347*37da2899SCharles.Forsyth /* slot :: The current glyph object. */ 348*37da2899SCharles.Forsyth /* */ 349*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) cff_decoder_init(CFF_Decoder * decoder,TT_Face face,CFF_Size size,CFF_GlyphSlot slot,FT_Bool hinting,FT_Render_Mode hint_mode)350*37da2899SCharles.Forsyth cff_decoder_init( CFF_Decoder* decoder, 351*37da2899SCharles.Forsyth TT_Face face, 352*37da2899SCharles.Forsyth CFF_Size size, 353*37da2899SCharles.Forsyth CFF_GlyphSlot slot, 354*37da2899SCharles.Forsyth FT_Bool hinting, 355*37da2899SCharles.Forsyth FT_Render_Mode hint_mode ) 356*37da2899SCharles.Forsyth { 357*37da2899SCharles.Forsyth CFF_Font cff = (CFF_Font)face->extra.data; 358*37da2899SCharles.Forsyth 359*37da2899SCharles.Forsyth 360*37da2899SCharles.Forsyth /* clear everything */ 361*37da2899SCharles.Forsyth FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); 362*37da2899SCharles.Forsyth 363*37da2899SCharles.Forsyth /* initialize builder */ 364*37da2899SCharles.Forsyth cff_builder_init( &decoder->builder, face, size, slot, hinting ); 365*37da2899SCharles.Forsyth 366*37da2899SCharles.Forsyth /* initialize Type2 decoder */ 367*37da2899SCharles.Forsyth decoder->num_globals = cff->num_global_subrs; 368*37da2899SCharles.Forsyth decoder->globals = cff->global_subrs; 369*37da2899SCharles.Forsyth decoder->globals_bias = cff_compute_bias( decoder->num_globals ); 370*37da2899SCharles.Forsyth 371*37da2899SCharles.Forsyth decoder->hint_mode = hint_mode; 372*37da2899SCharles.Forsyth } 373*37da2899SCharles.Forsyth 374*37da2899SCharles.Forsyth 375*37da2899SCharles.Forsyth /* this function is used to select the locals subrs array */ 376*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) cff_decoder_prepare(CFF_Decoder * decoder,FT_UInt glyph_index)377*37da2899SCharles.Forsyth cff_decoder_prepare( CFF_Decoder* decoder, 378*37da2899SCharles.Forsyth FT_UInt glyph_index ) 379*37da2899SCharles.Forsyth { 380*37da2899SCharles.Forsyth CFF_Font cff = (CFF_Font)decoder->builder.face->extra.data; 381*37da2899SCharles.Forsyth CFF_SubFont sub = &cff->top_font; 382*37da2899SCharles.Forsyth 383*37da2899SCharles.Forsyth 384*37da2899SCharles.Forsyth /* manage CID fonts */ 385*37da2899SCharles.Forsyth if ( cff->num_subfonts >= 1 ) 386*37da2899SCharles.Forsyth { 387*37da2899SCharles.Forsyth FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); 388*37da2899SCharles.Forsyth 389*37da2899SCharles.Forsyth 390*37da2899SCharles.Forsyth sub = cff->subfonts[fd_index]; 391*37da2899SCharles.Forsyth } 392*37da2899SCharles.Forsyth 393*37da2899SCharles.Forsyth decoder->num_locals = sub->num_local_subrs; 394*37da2899SCharles.Forsyth decoder->locals = sub->local_subrs; 395*37da2899SCharles.Forsyth decoder->locals_bias = cff_compute_bias( decoder->num_locals ); 396*37da2899SCharles.Forsyth 397*37da2899SCharles.Forsyth decoder->glyph_width = sub->private_dict.default_width; 398*37da2899SCharles.Forsyth decoder->nominal_width = sub->private_dict.nominal_width; 399*37da2899SCharles.Forsyth } 400*37da2899SCharles.Forsyth 401*37da2899SCharles.Forsyth 402*37da2899SCharles.Forsyth /* check that there is enough room for `count' more points */ 403*37da2899SCharles.Forsyth static FT_Error check_points(CFF_Builder * builder,FT_Int count)404*37da2899SCharles.Forsyth check_points( CFF_Builder* builder, 405*37da2899SCharles.Forsyth FT_Int count ) 406*37da2899SCharles.Forsyth { 407*37da2899SCharles.Forsyth return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 ); 408*37da2899SCharles.Forsyth } 409*37da2899SCharles.Forsyth 410*37da2899SCharles.Forsyth 411*37da2899SCharles.Forsyth /* add a new point, do not check space */ 412*37da2899SCharles.Forsyth static void cff_builder_add_point(CFF_Builder * builder,FT_Pos x,FT_Pos y,FT_Byte flag)413*37da2899SCharles.Forsyth cff_builder_add_point( CFF_Builder* builder, 414*37da2899SCharles.Forsyth FT_Pos x, 415*37da2899SCharles.Forsyth FT_Pos y, 416*37da2899SCharles.Forsyth FT_Byte flag ) 417*37da2899SCharles.Forsyth { 418*37da2899SCharles.Forsyth FT_Outline* outline = builder->current; 419*37da2899SCharles.Forsyth 420*37da2899SCharles.Forsyth 421*37da2899SCharles.Forsyth if ( builder->load_points ) 422*37da2899SCharles.Forsyth { 423*37da2899SCharles.Forsyth FT_Vector* point = outline->points + outline->n_points; 424*37da2899SCharles.Forsyth FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; 425*37da2899SCharles.Forsyth 426*37da2899SCharles.Forsyth 427*37da2899SCharles.Forsyth point->x = x >> 16; 428*37da2899SCharles.Forsyth point->y = y >> 16; 429*37da2899SCharles.Forsyth *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); 430*37da2899SCharles.Forsyth 431*37da2899SCharles.Forsyth builder->last = *point; 432*37da2899SCharles.Forsyth } 433*37da2899SCharles.Forsyth 434*37da2899SCharles.Forsyth outline->n_points++; 435*37da2899SCharles.Forsyth } 436*37da2899SCharles.Forsyth 437*37da2899SCharles.Forsyth 438*37da2899SCharles.Forsyth /* check space for a new on-curve point, then add it */ 439*37da2899SCharles.Forsyth static FT_Error cff_builder_add_point1(CFF_Builder * builder,FT_Pos x,FT_Pos y)440*37da2899SCharles.Forsyth cff_builder_add_point1( CFF_Builder* builder, 441*37da2899SCharles.Forsyth FT_Pos x, 442*37da2899SCharles.Forsyth FT_Pos y ) 443*37da2899SCharles.Forsyth { 444*37da2899SCharles.Forsyth FT_Error error; 445*37da2899SCharles.Forsyth 446*37da2899SCharles.Forsyth 447*37da2899SCharles.Forsyth error = check_points( builder, 1 ); 448*37da2899SCharles.Forsyth if ( !error ) 449*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 450*37da2899SCharles.Forsyth 451*37da2899SCharles.Forsyth return error; 452*37da2899SCharles.Forsyth } 453*37da2899SCharles.Forsyth 454*37da2899SCharles.Forsyth 455*37da2899SCharles.Forsyth /* check room for a new contour, then add it */ 456*37da2899SCharles.Forsyth static FT_Error cff_builder_add_contour(CFF_Builder * builder)457*37da2899SCharles.Forsyth cff_builder_add_contour( CFF_Builder* builder ) 458*37da2899SCharles.Forsyth { 459*37da2899SCharles.Forsyth FT_Outline* outline = builder->current; 460*37da2899SCharles.Forsyth FT_Error error; 461*37da2899SCharles.Forsyth 462*37da2899SCharles.Forsyth 463*37da2899SCharles.Forsyth if ( !builder->load_points ) 464*37da2899SCharles.Forsyth { 465*37da2899SCharles.Forsyth outline->n_contours++; 466*37da2899SCharles.Forsyth return CFF_Err_Ok; 467*37da2899SCharles.Forsyth } 468*37da2899SCharles.Forsyth 469*37da2899SCharles.Forsyth error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 ); 470*37da2899SCharles.Forsyth if ( !error ) 471*37da2899SCharles.Forsyth { 472*37da2899SCharles.Forsyth if ( outline->n_contours > 0 ) 473*37da2899SCharles.Forsyth outline->contours[outline->n_contours - 1] = 474*37da2899SCharles.Forsyth (short)( outline->n_points - 1 ); 475*37da2899SCharles.Forsyth 476*37da2899SCharles.Forsyth outline->n_contours++; 477*37da2899SCharles.Forsyth } 478*37da2899SCharles.Forsyth 479*37da2899SCharles.Forsyth return error; 480*37da2899SCharles.Forsyth } 481*37da2899SCharles.Forsyth 482*37da2899SCharles.Forsyth 483*37da2899SCharles.Forsyth /* if a path was begun, add its first on-curve point */ 484*37da2899SCharles.Forsyth static FT_Error cff_builder_start_point(CFF_Builder * builder,FT_Pos x,FT_Pos y)485*37da2899SCharles.Forsyth cff_builder_start_point( CFF_Builder* builder, 486*37da2899SCharles.Forsyth FT_Pos x, 487*37da2899SCharles.Forsyth FT_Pos y ) 488*37da2899SCharles.Forsyth { 489*37da2899SCharles.Forsyth FT_Error error = 0; 490*37da2899SCharles.Forsyth 491*37da2899SCharles.Forsyth 492*37da2899SCharles.Forsyth /* test whether we are building a new contour */ 493*37da2899SCharles.Forsyth if ( !builder->path_begun ) 494*37da2899SCharles.Forsyth { 495*37da2899SCharles.Forsyth builder->path_begun = 1; 496*37da2899SCharles.Forsyth error = cff_builder_add_contour( builder ); 497*37da2899SCharles.Forsyth if ( !error ) 498*37da2899SCharles.Forsyth error = cff_builder_add_point1( builder, x, y ); 499*37da2899SCharles.Forsyth } 500*37da2899SCharles.Forsyth 501*37da2899SCharles.Forsyth return error; 502*37da2899SCharles.Forsyth } 503*37da2899SCharles.Forsyth 504*37da2899SCharles.Forsyth 505*37da2899SCharles.Forsyth /* close the current contour */ 506*37da2899SCharles.Forsyth static void cff_builder_close_contour(CFF_Builder * builder)507*37da2899SCharles.Forsyth cff_builder_close_contour( CFF_Builder* builder ) 508*37da2899SCharles.Forsyth { 509*37da2899SCharles.Forsyth FT_Outline* outline = builder->current; 510*37da2899SCharles.Forsyth 511*37da2899SCharles.Forsyth 512*37da2899SCharles.Forsyth /* XXXX: We must not include the last point in the path if it */ 513*37da2899SCharles.Forsyth /* is located on the first point. */ 514*37da2899SCharles.Forsyth if ( outline->n_points > 1 ) 515*37da2899SCharles.Forsyth { 516*37da2899SCharles.Forsyth FT_Int first = 0; 517*37da2899SCharles.Forsyth FT_Vector* p1 = outline->points + first; 518*37da2899SCharles.Forsyth FT_Vector* p2 = outline->points + outline->n_points - 1; 519*37da2899SCharles.Forsyth FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; 520*37da2899SCharles.Forsyth 521*37da2899SCharles.Forsyth 522*37da2899SCharles.Forsyth if ( outline->n_contours > 1 ) 523*37da2899SCharles.Forsyth { 524*37da2899SCharles.Forsyth first = outline->contours[outline->n_contours - 2] + 1; 525*37da2899SCharles.Forsyth p1 = outline->points + first; 526*37da2899SCharles.Forsyth } 527*37da2899SCharles.Forsyth 528*37da2899SCharles.Forsyth /* `delete' last point only if it coincides with the first */ 529*37da2899SCharles.Forsyth /* point and if it is not a control point (which can happen). */ 530*37da2899SCharles.Forsyth if ( p1->x == p2->x && p1->y == p2->y ) 531*37da2899SCharles.Forsyth if ( *control == FT_CURVE_TAG_ON ) 532*37da2899SCharles.Forsyth outline->n_points--; 533*37da2899SCharles.Forsyth } 534*37da2899SCharles.Forsyth 535*37da2899SCharles.Forsyth if ( outline->n_contours > 0 ) 536*37da2899SCharles.Forsyth outline->contours[outline->n_contours - 1] = 537*37da2899SCharles.Forsyth (short)( outline->n_points - 1 ); 538*37da2899SCharles.Forsyth } 539*37da2899SCharles.Forsyth 540*37da2899SCharles.Forsyth 541*37da2899SCharles.Forsyth static FT_Int cff_lookup_glyph_by_stdcharcode(CFF_Font cff,FT_Int charcode)542*37da2899SCharles.Forsyth cff_lookup_glyph_by_stdcharcode( CFF_Font cff, 543*37da2899SCharles.Forsyth FT_Int charcode ) 544*37da2899SCharles.Forsyth { 545*37da2899SCharles.Forsyth FT_UInt n; 546*37da2899SCharles.Forsyth FT_UShort glyph_sid; 547*37da2899SCharles.Forsyth 548*37da2899SCharles.Forsyth 549*37da2899SCharles.Forsyth /* check range of standard char code */ 550*37da2899SCharles.Forsyth if ( charcode < 0 || charcode > 255 ) 551*37da2899SCharles.Forsyth return -1; 552*37da2899SCharles.Forsyth 553*37da2899SCharles.Forsyth /* Get code to SID mapping from `cff_standard_encoding'. */ 554*37da2899SCharles.Forsyth glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode ); 555*37da2899SCharles.Forsyth 556*37da2899SCharles.Forsyth for ( n = 0; n < cff->num_glyphs; n++ ) 557*37da2899SCharles.Forsyth { 558*37da2899SCharles.Forsyth if ( cff->charset.sids[n] == glyph_sid ) 559*37da2899SCharles.Forsyth return n; 560*37da2899SCharles.Forsyth } 561*37da2899SCharles.Forsyth 562*37da2899SCharles.Forsyth return -1; 563*37da2899SCharles.Forsyth } 564*37da2899SCharles.Forsyth 565*37da2899SCharles.Forsyth 566*37da2899SCharles.Forsyth static FT_Error cff_get_glyph_data(TT_Face face,FT_UInt glyph_index,FT_Byte ** pointer,FT_ULong * length)567*37da2899SCharles.Forsyth cff_get_glyph_data( TT_Face face, 568*37da2899SCharles.Forsyth FT_UInt glyph_index, 569*37da2899SCharles.Forsyth FT_Byte** pointer, 570*37da2899SCharles.Forsyth FT_ULong* length ) 571*37da2899SCharles.Forsyth { 572*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL 573*37da2899SCharles.Forsyth /* For incremental fonts get the character data using the */ 574*37da2899SCharles.Forsyth /* callback function. */ 575*37da2899SCharles.Forsyth if ( face->root.internal->incremental_interface ) 576*37da2899SCharles.Forsyth { 577*37da2899SCharles.Forsyth FT_Data data; 578*37da2899SCharles.Forsyth FT_Error error = 579*37da2899SCharles.Forsyth face->root.internal->incremental_interface->funcs->get_glyph_data( 580*37da2899SCharles.Forsyth face->root.internal->incremental_interface->object, 581*37da2899SCharles.Forsyth glyph_index, &data ); 582*37da2899SCharles.Forsyth 583*37da2899SCharles.Forsyth 584*37da2899SCharles.Forsyth *pointer = (FT_Byte*)data.pointer; 585*37da2899SCharles.Forsyth *length = data.length; 586*37da2899SCharles.Forsyth 587*37da2899SCharles.Forsyth return error; 588*37da2899SCharles.Forsyth } 589*37da2899SCharles.Forsyth else 590*37da2899SCharles.Forsyth #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 591*37da2899SCharles.Forsyth 592*37da2899SCharles.Forsyth { 593*37da2899SCharles.Forsyth CFF_Font cff = (CFF_Font)(face->extra.data); 594*37da2899SCharles.Forsyth 595*37da2899SCharles.Forsyth 596*37da2899SCharles.Forsyth return cff_index_access_element( &cff->charstrings_index, glyph_index, 597*37da2899SCharles.Forsyth pointer, length ); 598*37da2899SCharles.Forsyth } 599*37da2899SCharles.Forsyth } 600*37da2899SCharles.Forsyth 601*37da2899SCharles.Forsyth 602*37da2899SCharles.Forsyth static void cff_free_glyph_data(TT_Face face,FT_Byte ** pointer,FT_ULong length)603*37da2899SCharles.Forsyth cff_free_glyph_data( TT_Face face, 604*37da2899SCharles.Forsyth FT_Byte** pointer, 605*37da2899SCharles.Forsyth FT_ULong length ) 606*37da2899SCharles.Forsyth { 607*37da2899SCharles.Forsyth #ifndef FT_CONFIG_OPTION_INCREMENTAL 608*37da2899SCharles.Forsyth FT_UNUSED( length ); 609*37da2899SCharles.Forsyth #endif 610*37da2899SCharles.Forsyth 611*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL 612*37da2899SCharles.Forsyth /* For incremental fonts get the character data using the */ 613*37da2899SCharles.Forsyth /* callback function. */ 614*37da2899SCharles.Forsyth if ( face->root.internal->incremental_interface ) 615*37da2899SCharles.Forsyth { 616*37da2899SCharles.Forsyth FT_Data data; 617*37da2899SCharles.Forsyth 618*37da2899SCharles.Forsyth 619*37da2899SCharles.Forsyth data.pointer = *pointer; 620*37da2899SCharles.Forsyth data.length = length; 621*37da2899SCharles.Forsyth 622*37da2899SCharles.Forsyth face->root.internal->incremental_interface->funcs->free_glyph_data( 623*37da2899SCharles.Forsyth face->root.internal->incremental_interface->object,&data ); 624*37da2899SCharles.Forsyth } 625*37da2899SCharles.Forsyth else 626*37da2899SCharles.Forsyth #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 627*37da2899SCharles.Forsyth 628*37da2899SCharles.Forsyth { 629*37da2899SCharles.Forsyth CFF_Font cff = (CFF_Font)(face->extra.data); 630*37da2899SCharles.Forsyth 631*37da2899SCharles.Forsyth 632*37da2899SCharles.Forsyth cff_index_forget_element( &cff->charstrings_index, pointer ); 633*37da2899SCharles.Forsyth } 634*37da2899SCharles.Forsyth } 635*37da2899SCharles.Forsyth 636*37da2899SCharles.Forsyth 637*37da2899SCharles.Forsyth static FT_Error cff_operator_seac(CFF_Decoder * decoder,FT_Pos adx,FT_Pos ady,FT_Int bchar,FT_Int achar)638*37da2899SCharles.Forsyth cff_operator_seac( CFF_Decoder* decoder, 639*37da2899SCharles.Forsyth FT_Pos adx, 640*37da2899SCharles.Forsyth FT_Pos ady, 641*37da2899SCharles.Forsyth FT_Int bchar, 642*37da2899SCharles.Forsyth FT_Int achar ) 643*37da2899SCharles.Forsyth { 644*37da2899SCharles.Forsyth FT_Error error; 645*37da2899SCharles.Forsyth FT_Int bchar_index, achar_index, n_base_points; 646*37da2899SCharles.Forsyth FT_Outline* base = decoder->builder.base; 647*37da2899SCharles.Forsyth TT_Face face = decoder->builder.face; 648*37da2899SCharles.Forsyth FT_Vector left_bearing, advance; 649*37da2899SCharles.Forsyth FT_Byte* charstring; 650*37da2899SCharles.Forsyth FT_ULong charstring_len; 651*37da2899SCharles.Forsyth 652*37da2899SCharles.Forsyth 653*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL 654*37da2899SCharles.Forsyth /* Incremental fonts don't necessarily have valid charsets. */ 655*37da2899SCharles.Forsyth /* They use the character code, not the glyph index, in this case. */ 656*37da2899SCharles.Forsyth if ( face->root.internal->incremental_interface ) 657*37da2899SCharles.Forsyth { 658*37da2899SCharles.Forsyth bchar_index = bchar; 659*37da2899SCharles.Forsyth achar_index = achar; 660*37da2899SCharles.Forsyth } 661*37da2899SCharles.Forsyth else 662*37da2899SCharles.Forsyth #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 663*37da2899SCharles.Forsyth { 664*37da2899SCharles.Forsyth CFF_Font cff = (CFF_Font)(face->extra.data); 665*37da2899SCharles.Forsyth 666*37da2899SCharles.Forsyth 667*37da2899SCharles.Forsyth bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); 668*37da2899SCharles.Forsyth achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar ); 669*37da2899SCharles.Forsyth } 670*37da2899SCharles.Forsyth 671*37da2899SCharles.Forsyth if ( bchar_index < 0 || achar_index < 0 ) 672*37da2899SCharles.Forsyth { 673*37da2899SCharles.Forsyth FT_ERROR(( "cff_operator_seac:" )); 674*37da2899SCharles.Forsyth FT_ERROR(( " invalid seac character code arguments\n" )); 675*37da2899SCharles.Forsyth return CFF_Err_Syntax_Error; 676*37da2899SCharles.Forsyth } 677*37da2899SCharles.Forsyth 678*37da2899SCharles.Forsyth /* If we are trying to load a composite glyph, do not load the */ 679*37da2899SCharles.Forsyth /* accent character and return the array of subglyphs. */ 680*37da2899SCharles.Forsyth if ( decoder->builder.no_recurse ) 681*37da2899SCharles.Forsyth { 682*37da2899SCharles.Forsyth FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; 683*37da2899SCharles.Forsyth FT_GlyphLoader loader = glyph->internal->loader; 684*37da2899SCharles.Forsyth FT_SubGlyph subg; 685*37da2899SCharles.Forsyth 686*37da2899SCharles.Forsyth 687*37da2899SCharles.Forsyth /* reallocate subglyph array if necessary */ 688*37da2899SCharles.Forsyth error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); 689*37da2899SCharles.Forsyth if ( error ) 690*37da2899SCharles.Forsyth goto Exit; 691*37da2899SCharles.Forsyth 692*37da2899SCharles.Forsyth subg = loader->current.subglyphs; 693*37da2899SCharles.Forsyth 694*37da2899SCharles.Forsyth /* subglyph 0 = base character */ 695*37da2899SCharles.Forsyth subg->index = bchar_index; 696*37da2899SCharles.Forsyth subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | 697*37da2899SCharles.Forsyth FT_SUBGLYPH_FLAG_USE_MY_METRICS; 698*37da2899SCharles.Forsyth subg->arg1 = 0; 699*37da2899SCharles.Forsyth subg->arg2 = 0; 700*37da2899SCharles.Forsyth subg++; 701*37da2899SCharles.Forsyth 702*37da2899SCharles.Forsyth /* subglyph 1 = accent character */ 703*37da2899SCharles.Forsyth subg->index = achar_index; 704*37da2899SCharles.Forsyth subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; 705*37da2899SCharles.Forsyth subg->arg1 = (FT_Int)adx; 706*37da2899SCharles.Forsyth subg->arg2 = (FT_Int)ady; 707*37da2899SCharles.Forsyth 708*37da2899SCharles.Forsyth /* set up remaining glyph fields */ 709*37da2899SCharles.Forsyth glyph->num_subglyphs = 2; 710*37da2899SCharles.Forsyth glyph->subglyphs = loader->base.subglyphs; 711*37da2899SCharles.Forsyth glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 712*37da2899SCharles.Forsyth 713*37da2899SCharles.Forsyth loader->current.num_subglyphs = 2; 714*37da2899SCharles.Forsyth } 715*37da2899SCharles.Forsyth 716*37da2899SCharles.Forsyth /* First load `bchar' in builder */ 717*37da2899SCharles.Forsyth error = cff_get_glyph_data( face, bchar_index, 718*37da2899SCharles.Forsyth &charstring, &charstring_len ); 719*37da2899SCharles.Forsyth if ( !error ) 720*37da2899SCharles.Forsyth { 721*37da2899SCharles.Forsyth error = cff_decoder_parse_charstrings( decoder, charstring, 722*37da2899SCharles.Forsyth charstring_len ); 723*37da2899SCharles.Forsyth 724*37da2899SCharles.Forsyth if ( error ) 725*37da2899SCharles.Forsyth goto Exit; 726*37da2899SCharles.Forsyth 727*37da2899SCharles.Forsyth cff_free_glyph_data( face, &charstring, charstring_len ); 728*37da2899SCharles.Forsyth } 729*37da2899SCharles.Forsyth 730*37da2899SCharles.Forsyth n_base_points = base->n_points; 731*37da2899SCharles.Forsyth 732*37da2899SCharles.Forsyth /* Save the left bearing and width of the base character */ 733*37da2899SCharles.Forsyth /* as they will be erased by the next load. */ 734*37da2899SCharles.Forsyth 735*37da2899SCharles.Forsyth left_bearing = decoder->builder.left_bearing; 736*37da2899SCharles.Forsyth advance = decoder->builder.advance; 737*37da2899SCharles.Forsyth 738*37da2899SCharles.Forsyth decoder->builder.left_bearing.x = 0; 739*37da2899SCharles.Forsyth decoder->builder.left_bearing.y = 0; 740*37da2899SCharles.Forsyth 741*37da2899SCharles.Forsyth /* Now load `achar' on top of the base outline. */ 742*37da2899SCharles.Forsyth error = cff_get_glyph_data( face, achar_index, 743*37da2899SCharles.Forsyth &charstring, &charstring_len ); 744*37da2899SCharles.Forsyth if ( !error ) 745*37da2899SCharles.Forsyth { 746*37da2899SCharles.Forsyth error = cff_decoder_parse_charstrings( decoder, charstring, 747*37da2899SCharles.Forsyth charstring_len ); 748*37da2899SCharles.Forsyth 749*37da2899SCharles.Forsyth if ( error ) 750*37da2899SCharles.Forsyth goto Exit; 751*37da2899SCharles.Forsyth 752*37da2899SCharles.Forsyth cff_free_glyph_data( face, &charstring, charstring_len ); 753*37da2899SCharles.Forsyth } 754*37da2899SCharles.Forsyth 755*37da2899SCharles.Forsyth /* Restore the left side bearing and advance width */ 756*37da2899SCharles.Forsyth /* of the base character. */ 757*37da2899SCharles.Forsyth decoder->builder.left_bearing = left_bearing; 758*37da2899SCharles.Forsyth decoder->builder.advance = advance; 759*37da2899SCharles.Forsyth 760*37da2899SCharles.Forsyth /* Finally, move the accent. */ 761*37da2899SCharles.Forsyth if ( decoder->builder.load_points ) 762*37da2899SCharles.Forsyth { 763*37da2899SCharles.Forsyth FT_Outline dummy; 764*37da2899SCharles.Forsyth 765*37da2899SCharles.Forsyth 766*37da2899SCharles.Forsyth dummy.n_points = (short)( base->n_points - n_base_points ); 767*37da2899SCharles.Forsyth dummy.points = base->points + n_base_points; 768*37da2899SCharles.Forsyth 769*37da2899SCharles.Forsyth FT_Outline_Translate( &dummy, adx, ady ); 770*37da2899SCharles.Forsyth } 771*37da2899SCharles.Forsyth 772*37da2899SCharles.Forsyth Exit: 773*37da2899SCharles.Forsyth return error; 774*37da2899SCharles.Forsyth } 775*37da2899SCharles.Forsyth 776*37da2899SCharles.Forsyth 777*37da2899SCharles.Forsyth /*************************************************************************/ 778*37da2899SCharles.Forsyth /* */ 779*37da2899SCharles.Forsyth /* <Function> */ 780*37da2899SCharles.Forsyth /* cff_decoder_parse_charstrings */ 781*37da2899SCharles.Forsyth /* */ 782*37da2899SCharles.Forsyth /* <Description> */ 783*37da2899SCharles.Forsyth /* Parses a given Type 2 charstrings program. */ 784*37da2899SCharles.Forsyth /* */ 785*37da2899SCharles.Forsyth /* <InOut> */ 786*37da2899SCharles.Forsyth /* decoder :: The current Type 1 decoder. */ 787*37da2899SCharles.Forsyth /* */ 788*37da2899SCharles.Forsyth /* <Input> */ 789*37da2899SCharles.Forsyth /* charstring_base :: The base of the charstring stream. */ 790*37da2899SCharles.Forsyth /* */ 791*37da2899SCharles.Forsyth /* charstring_len :: The length in bytes of the charstring stream. */ 792*37da2899SCharles.Forsyth /* */ 793*37da2899SCharles.Forsyth /* <Return> */ 794*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 795*37da2899SCharles.Forsyth /* */ 796*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) cff_decoder_parse_charstrings(CFF_Decoder * decoder,FT_Byte * charstring_base,FT_ULong charstring_len)797*37da2899SCharles.Forsyth cff_decoder_parse_charstrings( CFF_Decoder* decoder, 798*37da2899SCharles.Forsyth FT_Byte* charstring_base, 799*37da2899SCharles.Forsyth FT_ULong charstring_len ) 800*37da2899SCharles.Forsyth { 801*37da2899SCharles.Forsyth FT_Error error; 802*37da2899SCharles.Forsyth CFF_Decoder_Zone* zone; 803*37da2899SCharles.Forsyth FT_Byte* ip; 804*37da2899SCharles.Forsyth FT_Byte* limit; 805*37da2899SCharles.Forsyth CFF_Builder* builder = &decoder->builder; 806*37da2899SCharles.Forsyth FT_Pos x, y; 807*37da2899SCharles.Forsyth FT_Fixed seed; 808*37da2899SCharles.Forsyth FT_Fixed* stack; 809*37da2899SCharles.Forsyth 810*37da2899SCharles.Forsyth T2_Hints_Funcs hinter; 811*37da2899SCharles.Forsyth 812*37da2899SCharles.Forsyth 813*37da2899SCharles.Forsyth /* set default width */ 814*37da2899SCharles.Forsyth decoder->num_hints = 0; 815*37da2899SCharles.Forsyth decoder->read_width = 1; 816*37da2899SCharles.Forsyth 817*37da2899SCharles.Forsyth /* compute random seed from stack address of parameter */ 818*37da2899SCharles.Forsyth seed = (FT_Fixed)(char*)&seed ^ 819*37da2899SCharles.Forsyth (FT_Fixed)(char*)&decoder ^ 820*37da2899SCharles.Forsyth (FT_Fixed)(char*)&charstring_base; 821*37da2899SCharles.Forsyth seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFF; 822*37da2899SCharles.Forsyth if ( seed == 0 ) 823*37da2899SCharles.Forsyth seed = 0x7384; 824*37da2899SCharles.Forsyth 825*37da2899SCharles.Forsyth /* initialize the decoder */ 826*37da2899SCharles.Forsyth decoder->top = decoder->stack; 827*37da2899SCharles.Forsyth decoder->zone = decoder->zones; 828*37da2899SCharles.Forsyth zone = decoder->zones; 829*37da2899SCharles.Forsyth stack = decoder->top; 830*37da2899SCharles.Forsyth 831*37da2899SCharles.Forsyth hinter = (T2_Hints_Funcs) builder->hints_funcs; 832*37da2899SCharles.Forsyth 833*37da2899SCharles.Forsyth builder->path_begun = 0; 834*37da2899SCharles.Forsyth 835*37da2899SCharles.Forsyth zone->base = charstring_base; 836*37da2899SCharles.Forsyth limit = zone->limit = charstring_base + charstring_len; 837*37da2899SCharles.Forsyth ip = zone->cursor = zone->base; 838*37da2899SCharles.Forsyth 839*37da2899SCharles.Forsyth error = CFF_Err_Ok; 840*37da2899SCharles.Forsyth 841*37da2899SCharles.Forsyth x = builder->pos_x; 842*37da2899SCharles.Forsyth y = builder->pos_y; 843*37da2899SCharles.Forsyth 844*37da2899SCharles.Forsyth /* begin hints recording session, if any */ 845*37da2899SCharles.Forsyth if ( hinter ) 846*37da2899SCharles.Forsyth hinter->open( hinter->hints ); 847*37da2899SCharles.Forsyth 848*37da2899SCharles.Forsyth /* now, execute loop */ 849*37da2899SCharles.Forsyth while ( ip < limit ) 850*37da2899SCharles.Forsyth { 851*37da2899SCharles.Forsyth CFF_Operator op; 852*37da2899SCharles.Forsyth FT_Byte v; 853*37da2899SCharles.Forsyth 854*37da2899SCharles.Forsyth 855*37da2899SCharles.Forsyth /********************************************************************/ 856*37da2899SCharles.Forsyth /* */ 857*37da2899SCharles.Forsyth /* Decode operator or operand */ 858*37da2899SCharles.Forsyth /* */ 859*37da2899SCharles.Forsyth v = *ip++; 860*37da2899SCharles.Forsyth if ( v >= 32 || v == 28 ) 861*37da2899SCharles.Forsyth { 862*37da2899SCharles.Forsyth FT_Int shift = 16; 863*37da2899SCharles.Forsyth FT_Int32 val; 864*37da2899SCharles.Forsyth 865*37da2899SCharles.Forsyth 866*37da2899SCharles.Forsyth /* this is an operand, push it on the stack */ 867*37da2899SCharles.Forsyth if ( v == 28 ) 868*37da2899SCharles.Forsyth { 869*37da2899SCharles.Forsyth if ( ip + 1 >= limit ) 870*37da2899SCharles.Forsyth goto Syntax_Error; 871*37da2899SCharles.Forsyth val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] ); 872*37da2899SCharles.Forsyth ip += 2; 873*37da2899SCharles.Forsyth } 874*37da2899SCharles.Forsyth else if ( v < 247 ) 875*37da2899SCharles.Forsyth val = (FT_Long)v - 139; 876*37da2899SCharles.Forsyth else if ( v < 251 ) 877*37da2899SCharles.Forsyth { 878*37da2899SCharles.Forsyth if ( ip >= limit ) 879*37da2899SCharles.Forsyth goto Syntax_Error; 880*37da2899SCharles.Forsyth val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108; 881*37da2899SCharles.Forsyth } 882*37da2899SCharles.Forsyth else if ( v < 255 ) 883*37da2899SCharles.Forsyth { 884*37da2899SCharles.Forsyth if ( ip >= limit ) 885*37da2899SCharles.Forsyth goto Syntax_Error; 886*37da2899SCharles.Forsyth val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108; 887*37da2899SCharles.Forsyth } 888*37da2899SCharles.Forsyth else 889*37da2899SCharles.Forsyth { 890*37da2899SCharles.Forsyth if ( ip + 3 >= limit ) 891*37da2899SCharles.Forsyth goto Syntax_Error; 892*37da2899SCharles.Forsyth val = ( (FT_Int32)ip[0] << 24 ) | 893*37da2899SCharles.Forsyth ( (FT_Int32)ip[1] << 16 ) | 894*37da2899SCharles.Forsyth ( (FT_Int32)ip[2] << 8 ) | 895*37da2899SCharles.Forsyth ip[3]; 896*37da2899SCharles.Forsyth ip += 4; 897*37da2899SCharles.Forsyth shift = 0; 898*37da2899SCharles.Forsyth } 899*37da2899SCharles.Forsyth if ( decoder->top - stack >= CFF_MAX_OPERANDS ) 900*37da2899SCharles.Forsyth goto Stack_Overflow; 901*37da2899SCharles.Forsyth 902*37da2899SCharles.Forsyth val <<= shift; 903*37da2899SCharles.Forsyth *decoder->top++ = val; 904*37da2899SCharles.Forsyth 905*37da2899SCharles.Forsyth #ifdef FT_DEBUG_LEVEL_TRACE 906*37da2899SCharles.Forsyth if ( !( val & 0xFFFF ) ) 907*37da2899SCharles.Forsyth FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) )); 908*37da2899SCharles.Forsyth else 909*37da2899SCharles.Forsyth FT_TRACE4(( " %.2f", val / 65536.0 )); 910*37da2899SCharles.Forsyth #endif 911*37da2899SCharles.Forsyth 912*37da2899SCharles.Forsyth } 913*37da2899SCharles.Forsyth else 914*37da2899SCharles.Forsyth { 915*37da2899SCharles.Forsyth FT_Fixed* args = decoder->top; 916*37da2899SCharles.Forsyth FT_Int num_args = (FT_Int)( args - decoder->stack ); 917*37da2899SCharles.Forsyth FT_Int req_args; 918*37da2899SCharles.Forsyth 919*37da2899SCharles.Forsyth 920*37da2899SCharles.Forsyth /* find operator */ 921*37da2899SCharles.Forsyth op = cff_op_unknown; 922*37da2899SCharles.Forsyth 923*37da2899SCharles.Forsyth switch ( v ) 924*37da2899SCharles.Forsyth { 925*37da2899SCharles.Forsyth case 1: 926*37da2899SCharles.Forsyth op = cff_op_hstem; 927*37da2899SCharles.Forsyth break; 928*37da2899SCharles.Forsyth case 3: 929*37da2899SCharles.Forsyth op = cff_op_vstem; 930*37da2899SCharles.Forsyth break; 931*37da2899SCharles.Forsyth case 4: 932*37da2899SCharles.Forsyth op = cff_op_vmoveto; 933*37da2899SCharles.Forsyth break; 934*37da2899SCharles.Forsyth case 5: 935*37da2899SCharles.Forsyth op = cff_op_rlineto; 936*37da2899SCharles.Forsyth break; 937*37da2899SCharles.Forsyth case 6: 938*37da2899SCharles.Forsyth op = cff_op_hlineto; 939*37da2899SCharles.Forsyth break; 940*37da2899SCharles.Forsyth case 7: 941*37da2899SCharles.Forsyth op = cff_op_vlineto; 942*37da2899SCharles.Forsyth break; 943*37da2899SCharles.Forsyth case 8: 944*37da2899SCharles.Forsyth op = cff_op_rrcurveto; 945*37da2899SCharles.Forsyth break; 946*37da2899SCharles.Forsyth case 10: 947*37da2899SCharles.Forsyth op = cff_op_callsubr; 948*37da2899SCharles.Forsyth break; 949*37da2899SCharles.Forsyth case 11: 950*37da2899SCharles.Forsyth op = cff_op_return; 951*37da2899SCharles.Forsyth break; 952*37da2899SCharles.Forsyth case 12: 953*37da2899SCharles.Forsyth { 954*37da2899SCharles.Forsyth if ( ip >= limit ) 955*37da2899SCharles.Forsyth goto Syntax_Error; 956*37da2899SCharles.Forsyth v = *ip++; 957*37da2899SCharles.Forsyth 958*37da2899SCharles.Forsyth switch ( v ) 959*37da2899SCharles.Forsyth { 960*37da2899SCharles.Forsyth case 0: 961*37da2899SCharles.Forsyth op = cff_op_dotsection; 962*37da2899SCharles.Forsyth break; 963*37da2899SCharles.Forsyth case 3: 964*37da2899SCharles.Forsyth op = cff_op_and; 965*37da2899SCharles.Forsyth break; 966*37da2899SCharles.Forsyth case 4: 967*37da2899SCharles.Forsyth op = cff_op_or; 968*37da2899SCharles.Forsyth break; 969*37da2899SCharles.Forsyth case 5: 970*37da2899SCharles.Forsyth op = cff_op_not; 971*37da2899SCharles.Forsyth break; 972*37da2899SCharles.Forsyth case 8: 973*37da2899SCharles.Forsyth op = cff_op_store; 974*37da2899SCharles.Forsyth break; 975*37da2899SCharles.Forsyth case 9: 976*37da2899SCharles.Forsyth op = cff_op_abs; 977*37da2899SCharles.Forsyth break; 978*37da2899SCharles.Forsyth case 10: 979*37da2899SCharles.Forsyth op = cff_op_add; 980*37da2899SCharles.Forsyth break; 981*37da2899SCharles.Forsyth case 11: 982*37da2899SCharles.Forsyth op = cff_op_sub; 983*37da2899SCharles.Forsyth break; 984*37da2899SCharles.Forsyth case 12: 985*37da2899SCharles.Forsyth op = cff_op_div; 986*37da2899SCharles.Forsyth break; 987*37da2899SCharles.Forsyth case 13: 988*37da2899SCharles.Forsyth op = cff_op_load; 989*37da2899SCharles.Forsyth break; 990*37da2899SCharles.Forsyth case 14: 991*37da2899SCharles.Forsyth op = cff_op_neg; 992*37da2899SCharles.Forsyth break; 993*37da2899SCharles.Forsyth case 15: 994*37da2899SCharles.Forsyth op = cff_op_eq; 995*37da2899SCharles.Forsyth break; 996*37da2899SCharles.Forsyth case 18: 997*37da2899SCharles.Forsyth op = cff_op_drop; 998*37da2899SCharles.Forsyth break; 999*37da2899SCharles.Forsyth case 20: 1000*37da2899SCharles.Forsyth op = cff_op_put; 1001*37da2899SCharles.Forsyth break; 1002*37da2899SCharles.Forsyth case 21: 1003*37da2899SCharles.Forsyth op = cff_op_get; 1004*37da2899SCharles.Forsyth break; 1005*37da2899SCharles.Forsyth case 22: 1006*37da2899SCharles.Forsyth op = cff_op_ifelse; 1007*37da2899SCharles.Forsyth break; 1008*37da2899SCharles.Forsyth case 23: 1009*37da2899SCharles.Forsyth op = cff_op_random; 1010*37da2899SCharles.Forsyth break; 1011*37da2899SCharles.Forsyth case 24: 1012*37da2899SCharles.Forsyth op = cff_op_mul; 1013*37da2899SCharles.Forsyth break; 1014*37da2899SCharles.Forsyth case 26: 1015*37da2899SCharles.Forsyth op = cff_op_sqrt; 1016*37da2899SCharles.Forsyth break; 1017*37da2899SCharles.Forsyth case 27: 1018*37da2899SCharles.Forsyth op = cff_op_dup; 1019*37da2899SCharles.Forsyth break; 1020*37da2899SCharles.Forsyth case 28: 1021*37da2899SCharles.Forsyth op = cff_op_exch; 1022*37da2899SCharles.Forsyth break; 1023*37da2899SCharles.Forsyth case 29: 1024*37da2899SCharles.Forsyth op = cff_op_index; 1025*37da2899SCharles.Forsyth break; 1026*37da2899SCharles.Forsyth case 30: 1027*37da2899SCharles.Forsyth op = cff_op_roll; 1028*37da2899SCharles.Forsyth break; 1029*37da2899SCharles.Forsyth case 34: 1030*37da2899SCharles.Forsyth op = cff_op_hflex; 1031*37da2899SCharles.Forsyth break; 1032*37da2899SCharles.Forsyth case 35: 1033*37da2899SCharles.Forsyth op = cff_op_flex; 1034*37da2899SCharles.Forsyth break; 1035*37da2899SCharles.Forsyth case 36: 1036*37da2899SCharles.Forsyth op = cff_op_hflex1; 1037*37da2899SCharles.Forsyth break; 1038*37da2899SCharles.Forsyth case 37: 1039*37da2899SCharles.Forsyth op = cff_op_flex1; 1040*37da2899SCharles.Forsyth break; 1041*37da2899SCharles.Forsyth default: 1042*37da2899SCharles.Forsyth /* decrement ip for syntax error message */ 1043*37da2899SCharles.Forsyth ip--; 1044*37da2899SCharles.Forsyth } 1045*37da2899SCharles.Forsyth } 1046*37da2899SCharles.Forsyth break; 1047*37da2899SCharles.Forsyth case 14: 1048*37da2899SCharles.Forsyth op = cff_op_endchar; 1049*37da2899SCharles.Forsyth break; 1050*37da2899SCharles.Forsyth case 16: 1051*37da2899SCharles.Forsyth op = cff_op_blend; 1052*37da2899SCharles.Forsyth break; 1053*37da2899SCharles.Forsyth case 18: 1054*37da2899SCharles.Forsyth op = cff_op_hstemhm; 1055*37da2899SCharles.Forsyth break; 1056*37da2899SCharles.Forsyth case 19: 1057*37da2899SCharles.Forsyth op = cff_op_hintmask; 1058*37da2899SCharles.Forsyth break; 1059*37da2899SCharles.Forsyth case 20: 1060*37da2899SCharles.Forsyth op = cff_op_cntrmask; 1061*37da2899SCharles.Forsyth break; 1062*37da2899SCharles.Forsyth case 21: 1063*37da2899SCharles.Forsyth op = cff_op_rmoveto; 1064*37da2899SCharles.Forsyth break; 1065*37da2899SCharles.Forsyth case 22: 1066*37da2899SCharles.Forsyth op = cff_op_hmoveto; 1067*37da2899SCharles.Forsyth break; 1068*37da2899SCharles.Forsyth case 23: 1069*37da2899SCharles.Forsyth op = cff_op_vstemhm; 1070*37da2899SCharles.Forsyth break; 1071*37da2899SCharles.Forsyth case 24: 1072*37da2899SCharles.Forsyth op = cff_op_rcurveline; 1073*37da2899SCharles.Forsyth break; 1074*37da2899SCharles.Forsyth case 25: 1075*37da2899SCharles.Forsyth op = cff_op_rlinecurve; 1076*37da2899SCharles.Forsyth break; 1077*37da2899SCharles.Forsyth case 26: 1078*37da2899SCharles.Forsyth op = cff_op_vvcurveto; 1079*37da2899SCharles.Forsyth break; 1080*37da2899SCharles.Forsyth case 27: 1081*37da2899SCharles.Forsyth op = cff_op_hhcurveto; 1082*37da2899SCharles.Forsyth break; 1083*37da2899SCharles.Forsyth case 29: 1084*37da2899SCharles.Forsyth op = cff_op_callgsubr; 1085*37da2899SCharles.Forsyth break; 1086*37da2899SCharles.Forsyth case 30: 1087*37da2899SCharles.Forsyth op = cff_op_vhcurveto; 1088*37da2899SCharles.Forsyth break; 1089*37da2899SCharles.Forsyth case 31: 1090*37da2899SCharles.Forsyth op = cff_op_hvcurveto; 1091*37da2899SCharles.Forsyth break; 1092*37da2899SCharles.Forsyth default: 1093*37da2899SCharles.Forsyth ; 1094*37da2899SCharles.Forsyth } 1095*37da2899SCharles.Forsyth if ( op == cff_op_unknown ) 1096*37da2899SCharles.Forsyth goto Syntax_Error; 1097*37da2899SCharles.Forsyth 1098*37da2899SCharles.Forsyth /* check arguments */ 1099*37da2899SCharles.Forsyth req_args = cff_argument_counts[op]; 1100*37da2899SCharles.Forsyth if ( req_args & CFF_COUNT_CHECK_WIDTH ) 1101*37da2899SCharles.Forsyth { 1102*37da2899SCharles.Forsyth args = stack; 1103*37da2899SCharles.Forsyth 1104*37da2899SCharles.Forsyth if ( num_args > 0 && decoder->read_width ) 1105*37da2899SCharles.Forsyth { 1106*37da2899SCharles.Forsyth /* If `nominal_width' is non-zero, the number is really a */ 1107*37da2899SCharles.Forsyth /* difference against `nominal_width'. Else, the number here */ 1108*37da2899SCharles.Forsyth /* is truly a width, not a difference against `nominal_width'. */ 1109*37da2899SCharles.Forsyth /* If the font does not set `nominal_width', then */ 1110*37da2899SCharles.Forsyth /* `nominal_width' defaults to zero, and so we can set */ 1111*37da2899SCharles.Forsyth /* `glyph_width' to `nominal_width' plus number on the stack */ 1112*37da2899SCharles.Forsyth /* -- for either case. */ 1113*37da2899SCharles.Forsyth 1114*37da2899SCharles.Forsyth FT_Int set_width_ok; 1115*37da2899SCharles.Forsyth 1116*37da2899SCharles.Forsyth 1117*37da2899SCharles.Forsyth switch ( op ) 1118*37da2899SCharles.Forsyth { 1119*37da2899SCharles.Forsyth case cff_op_hmoveto: 1120*37da2899SCharles.Forsyth case cff_op_vmoveto: 1121*37da2899SCharles.Forsyth set_width_ok = num_args & 2; 1122*37da2899SCharles.Forsyth break; 1123*37da2899SCharles.Forsyth 1124*37da2899SCharles.Forsyth case cff_op_hstem: 1125*37da2899SCharles.Forsyth case cff_op_vstem: 1126*37da2899SCharles.Forsyth case cff_op_hstemhm: 1127*37da2899SCharles.Forsyth case cff_op_vstemhm: 1128*37da2899SCharles.Forsyth case cff_op_rmoveto: 1129*37da2899SCharles.Forsyth set_width_ok = num_args & 1; 1130*37da2899SCharles.Forsyth break; 1131*37da2899SCharles.Forsyth 1132*37da2899SCharles.Forsyth case cff_op_endchar: 1133*37da2899SCharles.Forsyth /* If there is a width specified for endchar, we either have */ 1134*37da2899SCharles.Forsyth /* 1 argument or 5 arguments. We like to argue. */ 1135*37da2899SCharles.Forsyth set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) ); 1136*37da2899SCharles.Forsyth break; 1137*37da2899SCharles.Forsyth 1138*37da2899SCharles.Forsyth default: 1139*37da2899SCharles.Forsyth set_width_ok = 0; 1140*37da2899SCharles.Forsyth break; 1141*37da2899SCharles.Forsyth } 1142*37da2899SCharles.Forsyth 1143*37da2899SCharles.Forsyth if ( set_width_ok ) 1144*37da2899SCharles.Forsyth { 1145*37da2899SCharles.Forsyth decoder->glyph_width = decoder->nominal_width + 1146*37da2899SCharles.Forsyth ( stack[0] >> 16 ); 1147*37da2899SCharles.Forsyth 1148*37da2899SCharles.Forsyth /* Consumed an argument. */ 1149*37da2899SCharles.Forsyth num_args--; 1150*37da2899SCharles.Forsyth args++; 1151*37da2899SCharles.Forsyth } 1152*37da2899SCharles.Forsyth } 1153*37da2899SCharles.Forsyth 1154*37da2899SCharles.Forsyth decoder->read_width = 0; 1155*37da2899SCharles.Forsyth req_args = 0; 1156*37da2899SCharles.Forsyth } 1157*37da2899SCharles.Forsyth 1158*37da2899SCharles.Forsyth req_args &= 15; 1159*37da2899SCharles.Forsyth if ( num_args < req_args ) 1160*37da2899SCharles.Forsyth goto Stack_Underflow; 1161*37da2899SCharles.Forsyth args -= req_args; 1162*37da2899SCharles.Forsyth num_args -= req_args; 1163*37da2899SCharles.Forsyth 1164*37da2899SCharles.Forsyth switch ( op ) 1165*37da2899SCharles.Forsyth { 1166*37da2899SCharles.Forsyth case cff_op_hstem: 1167*37da2899SCharles.Forsyth case cff_op_vstem: 1168*37da2899SCharles.Forsyth case cff_op_hstemhm: 1169*37da2899SCharles.Forsyth case cff_op_vstemhm: 1170*37da2899SCharles.Forsyth /* the number of arguments is always even here */ 1171*37da2899SCharles.Forsyth FT_TRACE4(( op == cff_op_hstem ? " hstem" : 1172*37da2899SCharles.Forsyth ( op == cff_op_vstem ? " vstem" : 1173*37da2899SCharles.Forsyth ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) )); 1174*37da2899SCharles.Forsyth 1175*37da2899SCharles.Forsyth if ( hinter ) 1176*37da2899SCharles.Forsyth hinter->stems( hinter->hints, 1177*37da2899SCharles.Forsyth ( op == cff_op_hstem || op == cff_op_hstemhm ), 1178*37da2899SCharles.Forsyth num_args / 2, 1179*37da2899SCharles.Forsyth args ); 1180*37da2899SCharles.Forsyth 1181*37da2899SCharles.Forsyth decoder->num_hints += num_args / 2; 1182*37da2899SCharles.Forsyth args = stack; 1183*37da2899SCharles.Forsyth break; 1184*37da2899SCharles.Forsyth 1185*37da2899SCharles.Forsyth case cff_op_hintmask: 1186*37da2899SCharles.Forsyth case cff_op_cntrmask: 1187*37da2899SCharles.Forsyth FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); 1188*37da2899SCharles.Forsyth 1189*37da2899SCharles.Forsyth /* implement vstem when needed -- */ 1190*37da2899SCharles.Forsyth /* the specification doesn't say it, but this also works */ 1191*37da2899SCharles.Forsyth /* with the 'cntrmask' operator */ 1192*37da2899SCharles.Forsyth /* */ 1193*37da2899SCharles.Forsyth if ( num_args > 0 ) 1194*37da2899SCharles.Forsyth { 1195*37da2899SCharles.Forsyth if ( hinter ) 1196*37da2899SCharles.Forsyth hinter->stems( hinter->hints, 1197*37da2899SCharles.Forsyth 0, 1198*37da2899SCharles.Forsyth num_args / 2, 1199*37da2899SCharles.Forsyth args ); 1200*37da2899SCharles.Forsyth 1201*37da2899SCharles.Forsyth decoder->num_hints += num_args / 2; 1202*37da2899SCharles.Forsyth } 1203*37da2899SCharles.Forsyth 1204*37da2899SCharles.Forsyth if ( hinter ) 1205*37da2899SCharles.Forsyth { 1206*37da2899SCharles.Forsyth if ( op == cff_op_hintmask ) 1207*37da2899SCharles.Forsyth hinter->hintmask( hinter->hints, 1208*37da2899SCharles.Forsyth builder->current->n_points, 1209*37da2899SCharles.Forsyth decoder->num_hints, 1210*37da2899SCharles.Forsyth ip ); 1211*37da2899SCharles.Forsyth else 1212*37da2899SCharles.Forsyth hinter->counter( hinter->hints, 1213*37da2899SCharles.Forsyth decoder->num_hints, 1214*37da2899SCharles.Forsyth ip ); 1215*37da2899SCharles.Forsyth } 1216*37da2899SCharles.Forsyth 1217*37da2899SCharles.Forsyth #ifdef FT_DEBUG_LEVEL_TRACE 1218*37da2899SCharles.Forsyth { 1219*37da2899SCharles.Forsyth FT_UInt maskbyte; 1220*37da2899SCharles.Forsyth 1221*37da2899SCharles.Forsyth 1222*37da2899SCharles.Forsyth FT_TRACE4(( " " )); 1223*37da2899SCharles.Forsyth 1224*37da2899SCharles.Forsyth for ( maskbyte = 0; 1225*37da2899SCharles.Forsyth maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3); 1226*37da2899SCharles.Forsyth maskbyte++, ip++ ) 1227*37da2899SCharles.Forsyth FT_TRACE4(( "%02X", *ip )); 1228*37da2899SCharles.Forsyth } 1229*37da2899SCharles.Forsyth #else 1230*37da2899SCharles.Forsyth ip += ( decoder->num_hints + 7 ) >> 3; 1231*37da2899SCharles.Forsyth #endif 1232*37da2899SCharles.Forsyth if ( ip >= limit ) 1233*37da2899SCharles.Forsyth goto Syntax_Error; 1234*37da2899SCharles.Forsyth args = stack; 1235*37da2899SCharles.Forsyth break; 1236*37da2899SCharles.Forsyth 1237*37da2899SCharles.Forsyth case cff_op_rmoveto: 1238*37da2899SCharles.Forsyth FT_TRACE4(( " rmoveto" )); 1239*37da2899SCharles.Forsyth 1240*37da2899SCharles.Forsyth cff_builder_close_contour( builder ); 1241*37da2899SCharles.Forsyth builder->path_begun = 0; 1242*37da2899SCharles.Forsyth x += args[0]; 1243*37da2899SCharles.Forsyth y += args[1]; 1244*37da2899SCharles.Forsyth args = stack; 1245*37da2899SCharles.Forsyth break; 1246*37da2899SCharles.Forsyth 1247*37da2899SCharles.Forsyth case cff_op_vmoveto: 1248*37da2899SCharles.Forsyth FT_TRACE4(( " vmoveto" )); 1249*37da2899SCharles.Forsyth 1250*37da2899SCharles.Forsyth cff_builder_close_contour( builder ); 1251*37da2899SCharles.Forsyth builder->path_begun = 0; 1252*37da2899SCharles.Forsyth y += args[0]; 1253*37da2899SCharles.Forsyth args = stack; 1254*37da2899SCharles.Forsyth break; 1255*37da2899SCharles.Forsyth 1256*37da2899SCharles.Forsyth case cff_op_hmoveto: 1257*37da2899SCharles.Forsyth FT_TRACE4(( " hmoveto" )); 1258*37da2899SCharles.Forsyth 1259*37da2899SCharles.Forsyth cff_builder_close_contour( builder ); 1260*37da2899SCharles.Forsyth builder->path_begun = 0; 1261*37da2899SCharles.Forsyth x += args[0]; 1262*37da2899SCharles.Forsyth args = stack; 1263*37da2899SCharles.Forsyth break; 1264*37da2899SCharles.Forsyth 1265*37da2899SCharles.Forsyth case cff_op_rlineto: 1266*37da2899SCharles.Forsyth FT_TRACE4(( " rlineto" )); 1267*37da2899SCharles.Forsyth 1268*37da2899SCharles.Forsyth if ( cff_builder_start_point ( builder, x, y ) || 1269*37da2899SCharles.Forsyth check_points( builder, num_args / 2 ) ) 1270*37da2899SCharles.Forsyth goto Memory_Error; 1271*37da2899SCharles.Forsyth 1272*37da2899SCharles.Forsyth if ( num_args < 2 || num_args & 1 ) 1273*37da2899SCharles.Forsyth goto Stack_Underflow; 1274*37da2899SCharles.Forsyth 1275*37da2899SCharles.Forsyth args = stack; 1276*37da2899SCharles.Forsyth while ( args < decoder->top ) 1277*37da2899SCharles.Forsyth { 1278*37da2899SCharles.Forsyth x += args[0]; 1279*37da2899SCharles.Forsyth y += args[1]; 1280*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1281*37da2899SCharles.Forsyth args += 2; 1282*37da2899SCharles.Forsyth } 1283*37da2899SCharles.Forsyth args = stack; 1284*37da2899SCharles.Forsyth break; 1285*37da2899SCharles.Forsyth 1286*37da2899SCharles.Forsyth case cff_op_hlineto: 1287*37da2899SCharles.Forsyth case cff_op_vlineto: 1288*37da2899SCharles.Forsyth { 1289*37da2899SCharles.Forsyth FT_Int phase = ( op == cff_op_hlineto ); 1290*37da2899SCharles.Forsyth 1291*37da2899SCharles.Forsyth 1292*37da2899SCharles.Forsyth FT_TRACE4(( op == cff_op_hlineto ? " hlineto" 1293*37da2899SCharles.Forsyth : " vlineto" )); 1294*37da2899SCharles.Forsyth 1295*37da2899SCharles.Forsyth if ( cff_builder_start_point ( builder, x, y ) || 1296*37da2899SCharles.Forsyth check_points( builder, num_args ) ) 1297*37da2899SCharles.Forsyth goto Memory_Error; 1298*37da2899SCharles.Forsyth 1299*37da2899SCharles.Forsyth args = stack; 1300*37da2899SCharles.Forsyth while (args < decoder->top ) 1301*37da2899SCharles.Forsyth { 1302*37da2899SCharles.Forsyth if ( phase ) 1303*37da2899SCharles.Forsyth x += args[0]; 1304*37da2899SCharles.Forsyth else 1305*37da2899SCharles.Forsyth y += args[0]; 1306*37da2899SCharles.Forsyth 1307*37da2899SCharles.Forsyth if ( cff_builder_add_point1( builder, x, y ) ) 1308*37da2899SCharles.Forsyth goto Memory_Error; 1309*37da2899SCharles.Forsyth 1310*37da2899SCharles.Forsyth args++; 1311*37da2899SCharles.Forsyth phase ^= 1; 1312*37da2899SCharles.Forsyth } 1313*37da2899SCharles.Forsyth args = stack; 1314*37da2899SCharles.Forsyth } 1315*37da2899SCharles.Forsyth break; 1316*37da2899SCharles.Forsyth 1317*37da2899SCharles.Forsyth case cff_op_rrcurveto: 1318*37da2899SCharles.Forsyth FT_TRACE4(( " rrcurveto" )); 1319*37da2899SCharles.Forsyth 1320*37da2899SCharles.Forsyth /* check number of arguments; must be a multiple of 6 */ 1321*37da2899SCharles.Forsyth if ( num_args % 6 != 0 ) 1322*37da2899SCharles.Forsyth goto Stack_Underflow; 1323*37da2899SCharles.Forsyth 1324*37da2899SCharles.Forsyth if ( cff_builder_start_point ( builder, x, y ) || 1325*37da2899SCharles.Forsyth check_points( builder, num_args / 2 ) ) 1326*37da2899SCharles.Forsyth goto Memory_Error; 1327*37da2899SCharles.Forsyth 1328*37da2899SCharles.Forsyth args = stack; 1329*37da2899SCharles.Forsyth while ( args < decoder->top ) 1330*37da2899SCharles.Forsyth { 1331*37da2899SCharles.Forsyth x += args[0]; 1332*37da2899SCharles.Forsyth y += args[1]; 1333*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1334*37da2899SCharles.Forsyth x += args[2]; 1335*37da2899SCharles.Forsyth y += args[3]; 1336*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1337*37da2899SCharles.Forsyth x += args[4]; 1338*37da2899SCharles.Forsyth y += args[5]; 1339*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1340*37da2899SCharles.Forsyth args += 6; 1341*37da2899SCharles.Forsyth } 1342*37da2899SCharles.Forsyth args = stack; 1343*37da2899SCharles.Forsyth break; 1344*37da2899SCharles.Forsyth 1345*37da2899SCharles.Forsyth case cff_op_vvcurveto: 1346*37da2899SCharles.Forsyth FT_TRACE4(( " vvcurveto" )); 1347*37da2899SCharles.Forsyth 1348*37da2899SCharles.Forsyth if ( cff_builder_start_point ( builder, x, y ) ) 1349*37da2899SCharles.Forsyth goto Memory_Error; 1350*37da2899SCharles.Forsyth 1351*37da2899SCharles.Forsyth args = stack; 1352*37da2899SCharles.Forsyth if ( num_args & 1 ) 1353*37da2899SCharles.Forsyth { 1354*37da2899SCharles.Forsyth x += args[0]; 1355*37da2899SCharles.Forsyth args++; 1356*37da2899SCharles.Forsyth num_args--; 1357*37da2899SCharles.Forsyth } 1358*37da2899SCharles.Forsyth 1359*37da2899SCharles.Forsyth if ( num_args % 4 != 0 ) 1360*37da2899SCharles.Forsyth goto Stack_Underflow; 1361*37da2899SCharles.Forsyth 1362*37da2899SCharles.Forsyth if ( check_points( builder, 3 * ( num_args / 4 ) ) ) 1363*37da2899SCharles.Forsyth goto Memory_Error; 1364*37da2899SCharles.Forsyth 1365*37da2899SCharles.Forsyth while ( args < decoder->top ) 1366*37da2899SCharles.Forsyth { 1367*37da2899SCharles.Forsyth y += args[0]; 1368*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1369*37da2899SCharles.Forsyth x += args[1]; 1370*37da2899SCharles.Forsyth y += args[2]; 1371*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1372*37da2899SCharles.Forsyth y += args[3]; 1373*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1374*37da2899SCharles.Forsyth args += 4; 1375*37da2899SCharles.Forsyth } 1376*37da2899SCharles.Forsyth args = stack; 1377*37da2899SCharles.Forsyth break; 1378*37da2899SCharles.Forsyth 1379*37da2899SCharles.Forsyth case cff_op_hhcurveto: 1380*37da2899SCharles.Forsyth FT_TRACE4(( " hhcurveto" )); 1381*37da2899SCharles.Forsyth 1382*37da2899SCharles.Forsyth if ( cff_builder_start_point ( builder, x, y ) ) 1383*37da2899SCharles.Forsyth goto Memory_Error; 1384*37da2899SCharles.Forsyth 1385*37da2899SCharles.Forsyth args = stack; 1386*37da2899SCharles.Forsyth if ( num_args & 1 ) 1387*37da2899SCharles.Forsyth { 1388*37da2899SCharles.Forsyth y += args[0]; 1389*37da2899SCharles.Forsyth args++; 1390*37da2899SCharles.Forsyth num_args--; 1391*37da2899SCharles.Forsyth } 1392*37da2899SCharles.Forsyth 1393*37da2899SCharles.Forsyth if ( num_args % 4 != 0 ) 1394*37da2899SCharles.Forsyth goto Stack_Underflow; 1395*37da2899SCharles.Forsyth 1396*37da2899SCharles.Forsyth if ( check_points( builder, 3 * ( num_args / 4 ) ) ) 1397*37da2899SCharles.Forsyth goto Memory_Error; 1398*37da2899SCharles.Forsyth 1399*37da2899SCharles.Forsyth while ( args < decoder->top ) 1400*37da2899SCharles.Forsyth { 1401*37da2899SCharles.Forsyth x += args[0]; 1402*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1403*37da2899SCharles.Forsyth x += args[1]; 1404*37da2899SCharles.Forsyth y += args[2]; 1405*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1406*37da2899SCharles.Forsyth x += args[3]; 1407*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1408*37da2899SCharles.Forsyth args += 4; 1409*37da2899SCharles.Forsyth } 1410*37da2899SCharles.Forsyth args = stack; 1411*37da2899SCharles.Forsyth break; 1412*37da2899SCharles.Forsyth 1413*37da2899SCharles.Forsyth case cff_op_vhcurveto: 1414*37da2899SCharles.Forsyth case cff_op_hvcurveto: 1415*37da2899SCharles.Forsyth { 1416*37da2899SCharles.Forsyth FT_Int phase; 1417*37da2899SCharles.Forsyth 1418*37da2899SCharles.Forsyth 1419*37da2899SCharles.Forsyth FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto" 1420*37da2899SCharles.Forsyth : " hvcurveto" )); 1421*37da2899SCharles.Forsyth 1422*37da2899SCharles.Forsyth if ( cff_builder_start_point ( builder, x, y ) ) 1423*37da2899SCharles.Forsyth goto Memory_Error; 1424*37da2899SCharles.Forsyth 1425*37da2899SCharles.Forsyth args = stack; 1426*37da2899SCharles.Forsyth if (num_args < 4 || ( num_args % 4 ) > 1 ) 1427*37da2899SCharles.Forsyth goto Stack_Underflow; 1428*37da2899SCharles.Forsyth 1429*37da2899SCharles.Forsyth if ( check_points( builder, ( num_args / 4 ) * 3 ) ) 1430*37da2899SCharles.Forsyth goto Stack_Underflow; 1431*37da2899SCharles.Forsyth 1432*37da2899SCharles.Forsyth phase = ( op == cff_op_hvcurveto ); 1433*37da2899SCharles.Forsyth 1434*37da2899SCharles.Forsyth while ( num_args >= 4 ) 1435*37da2899SCharles.Forsyth { 1436*37da2899SCharles.Forsyth num_args -= 4; 1437*37da2899SCharles.Forsyth if ( phase ) 1438*37da2899SCharles.Forsyth { 1439*37da2899SCharles.Forsyth x += args[0]; 1440*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1441*37da2899SCharles.Forsyth x += args[1]; 1442*37da2899SCharles.Forsyth y += args[2]; 1443*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1444*37da2899SCharles.Forsyth y += args[3]; 1445*37da2899SCharles.Forsyth if ( num_args == 1 ) 1446*37da2899SCharles.Forsyth x += args[4]; 1447*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1448*37da2899SCharles.Forsyth } 1449*37da2899SCharles.Forsyth else 1450*37da2899SCharles.Forsyth { 1451*37da2899SCharles.Forsyth y += args[0]; 1452*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1453*37da2899SCharles.Forsyth x += args[1]; 1454*37da2899SCharles.Forsyth y += args[2]; 1455*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1456*37da2899SCharles.Forsyth x += args[3]; 1457*37da2899SCharles.Forsyth if ( num_args == 1 ) 1458*37da2899SCharles.Forsyth y += args[4]; 1459*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1460*37da2899SCharles.Forsyth } 1461*37da2899SCharles.Forsyth args += 4; 1462*37da2899SCharles.Forsyth phase ^= 1; 1463*37da2899SCharles.Forsyth } 1464*37da2899SCharles.Forsyth args = stack; 1465*37da2899SCharles.Forsyth } 1466*37da2899SCharles.Forsyth break; 1467*37da2899SCharles.Forsyth 1468*37da2899SCharles.Forsyth case cff_op_rlinecurve: 1469*37da2899SCharles.Forsyth { 1470*37da2899SCharles.Forsyth FT_Int num_lines = ( num_args - 6 ) / 2; 1471*37da2899SCharles.Forsyth 1472*37da2899SCharles.Forsyth 1473*37da2899SCharles.Forsyth FT_TRACE4(( " rlinecurve" )); 1474*37da2899SCharles.Forsyth 1475*37da2899SCharles.Forsyth if ( num_args < 8 || ( num_args - 6 ) & 1 ) 1476*37da2899SCharles.Forsyth goto Stack_Underflow; 1477*37da2899SCharles.Forsyth 1478*37da2899SCharles.Forsyth if ( cff_builder_start_point( builder, x, y ) || 1479*37da2899SCharles.Forsyth check_points( builder, num_lines + 3 ) ) 1480*37da2899SCharles.Forsyth goto Memory_Error; 1481*37da2899SCharles.Forsyth 1482*37da2899SCharles.Forsyth args = stack; 1483*37da2899SCharles.Forsyth 1484*37da2899SCharles.Forsyth /* first, add the line segments */ 1485*37da2899SCharles.Forsyth while ( num_lines > 0 ) 1486*37da2899SCharles.Forsyth { 1487*37da2899SCharles.Forsyth x += args[0]; 1488*37da2899SCharles.Forsyth y += args[1]; 1489*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1490*37da2899SCharles.Forsyth args += 2; 1491*37da2899SCharles.Forsyth num_lines--; 1492*37da2899SCharles.Forsyth } 1493*37da2899SCharles.Forsyth 1494*37da2899SCharles.Forsyth /* then the curve */ 1495*37da2899SCharles.Forsyth x += args[0]; 1496*37da2899SCharles.Forsyth y += args[1]; 1497*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1498*37da2899SCharles.Forsyth x += args[2]; 1499*37da2899SCharles.Forsyth y += args[3]; 1500*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1501*37da2899SCharles.Forsyth x += args[4]; 1502*37da2899SCharles.Forsyth y += args[5]; 1503*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1504*37da2899SCharles.Forsyth args = stack; 1505*37da2899SCharles.Forsyth } 1506*37da2899SCharles.Forsyth break; 1507*37da2899SCharles.Forsyth 1508*37da2899SCharles.Forsyth case cff_op_rcurveline: 1509*37da2899SCharles.Forsyth { 1510*37da2899SCharles.Forsyth FT_Int num_curves = ( num_args - 2 ) / 6; 1511*37da2899SCharles.Forsyth 1512*37da2899SCharles.Forsyth 1513*37da2899SCharles.Forsyth FT_TRACE4(( " rcurveline" )); 1514*37da2899SCharles.Forsyth 1515*37da2899SCharles.Forsyth if ( num_args < 8 || ( num_args - 2 ) % 6 ) 1516*37da2899SCharles.Forsyth goto Stack_Underflow; 1517*37da2899SCharles.Forsyth 1518*37da2899SCharles.Forsyth if ( cff_builder_start_point ( builder, x, y ) || 1519*37da2899SCharles.Forsyth check_points( builder, num_curves*3 + 2 ) ) 1520*37da2899SCharles.Forsyth goto Memory_Error; 1521*37da2899SCharles.Forsyth 1522*37da2899SCharles.Forsyth args = stack; 1523*37da2899SCharles.Forsyth 1524*37da2899SCharles.Forsyth /* first, add the curves */ 1525*37da2899SCharles.Forsyth while ( num_curves > 0 ) 1526*37da2899SCharles.Forsyth { 1527*37da2899SCharles.Forsyth x += args[0]; 1528*37da2899SCharles.Forsyth y += args[1]; 1529*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1530*37da2899SCharles.Forsyth x += args[2]; 1531*37da2899SCharles.Forsyth y += args[3]; 1532*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1533*37da2899SCharles.Forsyth x += args[4]; 1534*37da2899SCharles.Forsyth y += args[5]; 1535*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1536*37da2899SCharles.Forsyth args += 6; 1537*37da2899SCharles.Forsyth num_curves--; 1538*37da2899SCharles.Forsyth } 1539*37da2899SCharles.Forsyth 1540*37da2899SCharles.Forsyth /* then the final line */ 1541*37da2899SCharles.Forsyth x += args[0]; 1542*37da2899SCharles.Forsyth y += args[1]; 1543*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1544*37da2899SCharles.Forsyth args = stack; 1545*37da2899SCharles.Forsyth } 1546*37da2899SCharles.Forsyth break; 1547*37da2899SCharles.Forsyth 1548*37da2899SCharles.Forsyth case cff_op_hflex1: 1549*37da2899SCharles.Forsyth { 1550*37da2899SCharles.Forsyth FT_Pos start_y; 1551*37da2899SCharles.Forsyth 1552*37da2899SCharles.Forsyth 1553*37da2899SCharles.Forsyth FT_TRACE4(( " hflex1" )); 1554*37da2899SCharles.Forsyth 1555*37da2899SCharles.Forsyth args = stack; 1556*37da2899SCharles.Forsyth 1557*37da2899SCharles.Forsyth /* adding five more points; 4 control points, 1 on-curve point */ 1558*37da2899SCharles.Forsyth /* make sure we have enough space for the start point if it */ 1559*37da2899SCharles.Forsyth /* needs to be added.. */ 1560*37da2899SCharles.Forsyth if ( cff_builder_start_point( builder, x, y ) || 1561*37da2899SCharles.Forsyth check_points( builder, 6 ) ) 1562*37da2899SCharles.Forsyth goto Memory_Error; 1563*37da2899SCharles.Forsyth 1564*37da2899SCharles.Forsyth /* Record the starting point's y postion for later use */ 1565*37da2899SCharles.Forsyth start_y = y; 1566*37da2899SCharles.Forsyth 1567*37da2899SCharles.Forsyth /* first control point */ 1568*37da2899SCharles.Forsyth x += args[0]; 1569*37da2899SCharles.Forsyth y += args[1]; 1570*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1571*37da2899SCharles.Forsyth 1572*37da2899SCharles.Forsyth /* second control point */ 1573*37da2899SCharles.Forsyth x += args[2]; 1574*37da2899SCharles.Forsyth y += args[3]; 1575*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1576*37da2899SCharles.Forsyth 1577*37da2899SCharles.Forsyth /* join point; on curve, with y-value the same as the last */ 1578*37da2899SCharles.Forsyth /* control point's y-value */ 1579*37da2899SCharles.Forsyth x += args[4]; 1580*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1581*37da2899SCharles.Forsyth 1582*37da2899SCharles.Forsyth /* third control point, with y-value the same as the join */ 1583*37da2899SCharles.Forsyth /* point's y-value */ 1584*37da2899SCharles.Forsyth x += args[5]; 1585*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1586*37da2899SCharles.Forsyth 1587*37da2899SCharles.Forsyth /* fourth control point */ 1588*37da2899SCharles.Forsyth x += args[6]; 1589*37da2899SCharles.Forsyth y += args[7]; 1590*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1591*37da2899SCharles.Forsyth 1592*37da2899SCharles.Forsyth /* ending point, with y-value the same as the start */ 1593*37da2899SCharles.Forsyth x += args[8]; 1594*37da2899SCharles.Forsyth y = start_y; 1595*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1596*37da2899SCharles.Forsyth 1597*37da2899SCharles.Forsyth args = stack; 1598*37da2899SCharles.Forsyth break; 1599*37da2899SCharles.Forsyth } 1600*37da2899SCharles.Forsyth 1601*37da2899SCharles.Forsyth case cff_op_hflex: 1602*37da2899SCharles.Forsyth { 1603*37da2899SCharles.Forsyth FT_Pos start_y; 1604*37da2899SCharles.Forsyth 1605*37da2899SCharles.Forsyth 1606*37da2899SCharles.Forsyth FT_TRACE4(( " hflex" )); 1607*37da2899SCharles.Forsyth 1608*37da2899SCharles.Forsyth args = stack; 1609*37da2899SCharles.Forsyth 1610*37da2899SCharles.Forsyth /* adding six more points; 4 control points, 2 on-curve points */ 1611*37da2899SCharles.Forsyth if ( cff_builder_start_point( builder, x, y ) || 1612*37da2899SCharles.Forsyth check_points ( builder, 6 ) ) 1613*37da2899SCharles.Forsyth goto Memory_Error; 1614*37da2899SCharles.Forsyth 1615*37da2899SCharles.Forsyth /* record the starting point's y-position for later use */ 1616*37da2899SCharles.Forsyth start_y = y; 1617*37da2899SCharles.Forsyth 1618*37da2899SCharles.Forsyth /* first control point */ 1619*37da2899SCharles.Forsyth x += args[0]; 1620*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1621*37da2899SCharles.Forsyth 1622*37da2899SCharles.Forsyth /* second control point */ 1623*37da2899SCharles.Forsyth x += args[1]; 1624*37da2899SCharles.Forsyth y += args[2]; 1625*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1626*37da2899SCharles.Forsyth 1627*37da2899SCharles.Forsyth /* join point; on curve, with y-value the same as the last */ 1628*37da2899SCharles.Forsyth /* control point's y-value */ 1629*37da2899SCharles.Forsyth x += args[3]; 1630*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1631*37da2899SCharles.Forsyth 1632*37da2899SCharles.Forsyth /* third control point, with y-value the same as the join */ 1633*37da2899SCharles.Forsyth /* point's y-value */ 1634*37da2899SCharles.Forsyth x += args[4]; 1635*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1636*37da2899SCharles.Forsyth 1637*37da2899SCharles.Forsyth /* fourth control point */ 1638*37da2899SCharles.Forsyth x += args[5]; 1639*37da2899SCharles.Forsyth y = start_y; 1640*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 0 ); 1641*37da2899SCharles.Forsyth 1642*37da2899SCharles.Forsyth /* ending point, with y-value the same as the start point's */ 1643*37da2899SCharles.Forsyth /* y-value -- we don't add this point, though */ 1644*37da2899SCharles.Forsyth x += args[6]; 1645*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1646*37da2899SCharles.Forsyth 1647*37da2899SCharles.Forsyth args = stack; 1648*37da2899SCharles.Forsyth break; 1649*37da2899SCharles.Forsyth } 1650*37da2899SCharles.Forsyth 1651*37da2899SCharles.Forsyth case cff_op_flex1: 1652*37da2899SCharles.Forsyth { 1653*37da2899SCharles.Forsyth FT_Pos start_x, start_y; /* record start x, y values for alter */ 1654*37da2899SCharles.Forsyth /* use */ 1655*37da2899SCharles.Forsyth FT_Int dx = 0, dy = 0; /* used in horizontal/vertical */ 1656*37da2899SCharles.Forsyth /* algorithm below */ 1657*37da2899SCharles.Forsyth FT_Int horizontal, count; 1658*37da2899SCharles.Forsyth 1659*37da2899SCharles.Forsyth 1660*37da2899SCharles.Forsyth FT_TRACE4(( " flex1" )); 1661*37da2899SCharles.Forsyth 1662*37da2899SCharles.Forsyth /* adding six more points; 4 control points, 2 on-curve points */ 1663*37da2899SCharles.Forsyth if ( cff_builder_start_point( builder, x, y ) || 1664*37da2899SCharles.Forsyth check_points( builder, 6 ) ) 1665*37da2899SCharles.Forsyth goto Memory_Error; 1666*37da2899SCharles.Forsyth 1667*37da2899SCharles.Forsyth /* record the starting point's x, y postion for later use */ 1668*37da2899SCharles.Forsyth start_x = x; 1669*37da2899SCharles.Forsyth start_y = y; 1670*37da2899SCharles.Forsyth 1671*37da2899SCharles.Forsyth /* XXX: figure out whether this is supposed to be a horizontal */ 1672*37da2899SCharles.Forsyth /* or vertical flex; the Type 2 specification is vague... */ 1673*37da2899SCharles.Forsyth 1674*37da2899SCharles.Forsyth args = stack; 1675*37da2899SCharles.Forsyth 1676*37da2899SCharles.Forsyth /* grab up to the last argument */ 1677*37da2899SCharles.Forsyth for ( count = 5; count > 0; count-- ) 1678*37da2899SCharles.Forsyth { 1679*37da2899SCharles.Forsyth dx += (FT_Int)args[0]; 1680*37da2899SCharles.Forsyth dy += (FT_Int)args[1]; 1681*37da2899SCharles.Forsyth args += 2; 1682*37da2899SCharles.Forsyth } 1683*37da2899SCharles.Forsyth 1684*37da2899SCharles.Forsyth /* rewind */ 1685*37da2899SCharles.Forsyth args = stack; 1686*37da2899SCharles.Forsyth 1687*37da2899SCharles.Forsyth if ( dx < 0 ) dx = -dx; 1688*37da2899SCharles.Forsyth if ( dy < 0 ) dy = -dy; 1689*37da2899SCharles.Forsyth 1690*37da2899SCharles.Forsyth /* strange test, but here it is... */ 1691*37da2899SCharles.Forsyth horizontal = ( dx > dy ); 1692*37da2899SCharles.Forsyth 1693*37da2899SCharles.Forsyth for ( count = 5; count > 0; count-- ) 1694*37da2899SCharles.Forsyth { 1695*37da2899SCharles.Forsyth x += args[0]; 1696*37da2899SCharles.Forsyth y += args[1]; 1697*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, (FT_Bool)( count == 3 ) ); 1698*37da2899SCharles.Forsyth args += 2; 1699*37da2899SCharles.Forsyth } 1700*37da2899SCharles.Forsyth 1701*37da2899SCharles.Forsyth /* is last operand an x- or y-delta? */ 1702*37da2899SCharles.Forsyth if ( horizontal ) 1703*37da2899SCharles.Forsyth { 1704*37da2899SCharles.Forsyth x += args[0]; 1705*37da2899SCharles.Forsyth y = start_y; 1706*37da2899SCharles.Forsyth } 1707*37da2899SCharles.Forsyth else 1708*37da2899SCharles.Forsyth { 1709*37da2899SCharles.Forsyth x = start_x; 1710*37da2899SCharles.Forsyth y += args[0]; 1711*37da2899SCharles.Forsyth } 1712*37da2899SCharles.Forsyth 1713*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1 ); 1714*37da2899SCharles.Forsyth 1715*37da2899SCharles.Forsyth args = stack; 1716*37da2899SCharles.Forsyth break; 1717*37da2899SCharles.Forsyth } 1718*37da2899SCharles.Forsyth 1719*37da2899SCharles.Forsyth case cff_op_flex: 1720*37da2899SCharles.Forsyth { 1721*37da2899SCharles.Forsyth FT_UInt count; 1722*37da2899SCharles.Forsyth 1723*37da2899SCharles.Forsyth 1724*37da2899SCharles.Forsyth FT_TRACE4(( " flex" )); 1725*37da2899SCharles.Forsyth 1726*37da2899SCharles.Forsyth if ( cff_builder_start_point( builder, x, y ) || 1727*37da2899SCharles.Forsyth check_points( builder, 6 ) ) 1728*37da2899SCharles.Forsyth goto Memory_Error; 1729*37da2899SCharles.Forsyth 1730*37da2899SCharles.Forsyth args = stack; 1731*37da2899SCharles.Forsyth for ( count = 6; count > 0; count-- ) 1732*37da2899SCharles.Forsyth { 1733*37da2899SCharles.Forsyth x += args[0]; 1734*37da2899SCharles.Forsyth y += args[1]; 1735*37da2899SCharles.Forsyth cff_builder_add_point( builder, x, y, 1736*37da2899SCharles.Forsyth (FT_Bool)( count == 3 || count == 0 ) ); 1737*37da2899SCharles.Forsyth args += 2; 1738*37da2899SCharles.Forsyth } 1739*37da2899SCharles.Forsyth 1740*37da2899SCharles.Forsyth args = stack; 1741*37da2899SCharles.Forsyth } 1742*37da2899SCharles.Forsyth break; 1743*37da2899SCharles.Forsyth 1744*37da2899SCharles.Forsyth case cff_op_endchar: 1745*37da2899SCharles.Forsyth FT_TRACE4(( " endchar" )); 1746*37da2899SCharles.Forsyth 1747*37da2899SCharles.Forsyth /* We are going to emulate the seac operator. */ 1748*37da2899SCharles.Forsyth if ( num_args == 4 ) 1749*37da2899SCharles.Forsyth { 1750*37da2899SCharles.Forsyth error = cff_operator_seac( decoder, 1751*37da2899SCharles.Forsyth args[0] >> 16, 1752*37da2899SCharles.Forsyth args[1] >> 16, 1753*37da2899SCharles.Forsyth (FT_Int)( args[2] >> 16 ), 1754*37da2899SCharles.Forsyth (FT_Int)( args[3] >> 16 ) ); 1755*37da2899SCharles.Forsyth args += 4; 1756*37da2899SCharles.Forsyth } 1757*37da2899SCharles.Forsyth 1758*37da2899SCharles.Forsyth if ( !error ) 1759*37da2899SCharles.Forsyth error = CFF_Err_Ok; 1760*37da2899SCharles.Forsyth 1761*37da2899SCharles.Forsyth cff_builder_close_contour( builder ); 1762*37da2899SCharles.Forsyth 1763*37da2899SCharles.Forsyth /* close hints recording session */ 1764*37da2899SCharles.Forsyth if ( hinter ) 1765*37da2899SCharles.Forsyth { 1766*37da2899SCharles.Forsyth if (hinter->close( hinter->hints, builder->current->n_points ) ) 1767*37da2899SCharles.Forsyth goto Syntax_Error; 1768*37da2899SCharles.Forsyth 1769*37da2899SCharles.Forsyth /* apply hints to the loaded glyph outline now */ 1770*37da2899SCharles.Forsyth hinter->apply( hinter->hints, 1771*37da2899SCharles.Forsyth builder->current, 1772*37da2899SCharles.Forsyth (PSH_Globals)builder->hints_globals, 1773*37da2899SCharles.Forsyth builder->hint_flags ); 1774*37da2899SCharles.Forsyth } 1775*37da2899SCharles.Forsyth 1776*37da2899SCharles.Forsyth /* add current outline to the glyph slot */ 1777*37da2899SCharles.Forsyth FT_GlyphLoader_Add( builder->loader ); 1778*37da2899SCharles.Forsyth 1779*37da2899SCharles.Forsyth /* return now! */ 1780*37da2899SCharles.Forsyth FT_TRACE4(( "\n\n" )); 1781*37da2899SCharles.Forsyth return error; 1782*37da2899SCharles.Forsyth 1783*37da2899SCharles.Forsyth case cff_op_abs: 1784*37da2899SCharles.Forsyth FT_TRACE4(( " abs" )); 1785*37da2899SCharles.Forsyth 1786*37da2899SCharles.Forsyth if ( args[0] < 0 ) 1787*37da2899SCharles.Forsyth args[0] = -args[0]; 1788*37da2899SCharles.Forsyth args++; 1789*37da2899SCharles.Forsyth break; 1790*37da2899SCharles.Forsyth 1791*37da2899SCharles.Forsyth case cff_op_add: 1792*37da2899SCharles.Forsyth FT_TRACE4(( " add" )); 1793*37da2899SCharles.Forsyth 1794*37da2899SCharles.Forsyth args[0] += args[1]; 1795*37da2899SCharles.Forsyth args++; 1796*37da2899SCharles.Forsyth break; 1797*37da2899SCharles.Forsyth 1798*37da2899SCharles.Forsyth case cff_op_sub: 1799*37da2899SCharles.Forsyth FT_TRACE4(( " sub" )); 1800*37da2899SCharles.Forsyth 1801*37da2899SCharles.Forsyth args[0] -= args[1]; 1802*37da2899SCharles.Forsyth args++; 1803*37da2899SCharles.Forsyth break; 1804*37da2899SCharles.Forsyth 1805*37da2899SCharles.Forsyth case cff_op_div: 1806*37da2899SCharles.Forsyth FT_TRACE4(( " div" )); 1807*37da2899SCharles.Forsyth 1808*37da2899SCharles.Forsyth args[0] = FT_DivFix( args[0], args[1] ); 1809*37da2899SCharles.Forsyth args++; 1810*37da2899SCharles.Forsyth break; 1811*37da2899SCharles.Forsyth 1812*37da2899SCharles.Forsyth case cff_op_neg: 1813*37da2899SCharles.Forsyth FT_TRACE4(( " neg" )); 1814*37da2899SCharles.Forsyth 1815*37da2899SCharles.Forsyth args[0] = -args[0]; 1816*37da2899SCharles.Forsyth args++; 1817*37da2899SCharles.Forsyth break; 1818*37da2899SCharles.Forsyth 1819*37da2899SCharles.Forsyth case cff_op_random: 1820*37da2899SCharles.Forsyth { 1821*37da2899SCharles.Forsyth FT_Fixed Rand; 1822*37da2899SCharles.Forsyth 1823*37da2899SCharles.Forsyth 1824*37da2899SCharles.Forsyth FT_TRACE4(( " rand" )); 1825*37da2899SCharles.Forsyth 1826*37da2899SCharles.Forsyth Rand = seed; 1827*37da2899SCharles.Forsyth if ( Rand >= 0x8000 ) 1828*37da2899SCharles.Forsyth Rand++; 1829*37da2899SCharles.Forsyth 1830*37da2899SCharles.Forsyth args[0] = Rand; 1831*37da2899SCharles.Forsyth seed = FT_MulFix( seed, 0x10000L - seed ); 1832*37da2899SCharles.Forsyth if ( seed == 0 ) 1833*37da2899SCharles.Forsyth seed += 0x2873; 1834*37da2899SCharles.Forsyth args++; 1835*37da2899SCharles.Forsyth } 1836*37da2899SCharles.Forsyth break; 1837*37da2899SCharles.Forsyth 1838*37da2899SCharles.Forsyth case cff_op_mul: 1839*37da2899SCharles.Forsyth FT_TRACE4(( " mul" )); 1840*37da2899SCharles.Forsyth 1841*37da2899SCharles.Forsyth args[0] = FT_MulFix( args[0], args[1] ); 1842*37da2899SCharles.Forsyth args++; 1843*37da2899SCharles.Forsyth break; 1844*37da2899SCharles.Forsyth 1845*37da2899SCharles.Forsyth case cff_op_sqrt: 1846*37da2899SCharles.Forsyth FT_TRACE4(( " sqrt" )); 1847*37da2899SCharles.Forsyth 1848*37da2899SCharles.Forsyth if ( args[0] > 0 ) 1849*37da2899SCharles.Forsyth { 1850*37da2899SCharles.Forsyth FT_Int count = 9; 1851*37da2899SCharles.Forsyth FT_Fixed root = args[0]; 1852*37da2899SCharles.Forsyth FT_Fixed new_root; 1853*37da2899SCharles.Forsyth 1854*37da2899SCharles.Forsyth 1855*37da2899SCharles.Forsyth for (;;) 1856*37da2899SCharles.Forsyth { 1857*37da2899SCharles.Forsyth new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; 1858*37da2899SCharles.Forsyth if ( new_root == root || count <= 0 ) 1859*37da2899SCharles.Forsyth break; 1860*37da2899SCharles.Forsyth root = new_root; 1861*37da2899SCharles.Forsyth } 1862*37da2899SCharles.Forsyth args[0] = new_root; 1863*37da2899SCharles.Forsyth } 1864*37da2899SCharles.Forsyth else 1865*37da2899SCharles.Forsyth args[0] = 0; 1866*37da2899SCharles.Forsyth args++; 1867*37da2899SCharles.Forsyth break; 1868*37da2899SCharles.Forsyth 1869*37da2899SCharles.Forsyth case cff_op_drop: 1870*37da2899SCharles.Forsyth /* nothing */ 1871*37da2899SCharles.Forsyth FT_TRACE4(( " drop" )); 1872*37da2899SCharles.Forsyth 1873*37da2899SCharles.Forsyth break; 1874*37da2899SCharles.Forsyth 1875*37da2899SCharles.Forsyth case cff_op_exch: 1876*37da2899SCharles.Forsyth { 1877*37da2899SCharles.Forsyth FT_Fixed tmp; 1878*37da2899SCharles.Forsyth 1879*37da2899SCharles.Forsyth 1880*37da2899SCharles.Forsyth FT_TRACE4(( " exch" )); 1881*37da2899SCharles.Forsyth 1882*37da2899SCharles.Forsyth tmp = args[0]; 1883*37da2899SCharles.Forsyth args[0] = args[1]; 1884*37da2899SCharles.Forsyth args[1] = tmp; 1885*37da2899SCharles.Forsyth args += 2; 1886*37da2899SCharles.Forsyth } 1887*37da2899SCharles.Forsyth break; 1888*37da2899SCharles.Forsyth 1889*37da2899SCharles.Forsyth case cff_op_index: 1890*37da2899SCharles.Forsyth { 1891*37da2899SCharles.Forsyth FT_Int idx = (FT_Int)( args[0] >> 16 ); 1892*37da2899SCharles.Forsyth 1893*37da2899SCharles.Forsyth 1894*37da2899SCharles.Forsyth FT_TRACE4(( " index" )); 1895*37da2899SCharles.Forsyth 1896*37da2899SCharles.Forsyth if ( idx < 0 ) 1897*37da2899SCharles.Forsyth idx = 0; 1898*37da2899SCharles.Forsyth else if ( idx > num_args - 2 ) 1899*37da2899SCharles.Forsyth idx = num_args - 2; 1900*37da2899SCharles.Forsyth args[0] = args[-( idx + 1 )]; 1901*37da2899SCharles.Forsyth args++; 1902*37da2899SCharles.Forsyth } 1903*37da2899SCharles.Forsyth break; 1904*37da2899SCharles.Forsyth 1905*37da2899SCharles.Forsyth case cff_op_roll: 1906*37da2899SCharles.Forsyth { 1907*37da2899SCharles.Forsyth FT_Int count = (FT_Int)( args[0] >> 16 ); 1908*37da2899SCharles.Forsyth FT_Int idx = (FT_Int)( args[1] >> 16 ); 1909*37da2899SCharles.Forsyth 1910*37da2899SCharles.Forsyth 1911*37da2899SCharles.Forsyth FT_TRACE4(( " roll" )); 1912*37da2899SCharles.Forsyth 1913*37da2899SCharles.Forsyth if ( count <= 0 ) 1914*37da2899SCharles.Forsyth count = 1; 1915*37da2899SCharles.Forsyth 1916*37da2899SCharles.Forsyth args -= count; 1917*37da2899SCharles.Forsyth if ( args < stack ) 1918*37da2899SCharles.Forsyth goto Stack_Underflow; 1919*37da2899SCharles.Forsyth 1920*37da2899SCharles.Forsyth if ( idx >= 0 ) 1921*37da2899SCharles.Forsyth { 1922*37da2899SCharles.Forsyth while ( idx > 0 ) 1923*37da2899SCharles.Forsyth { 1924*37da2899SCharles.Forsyth FT_Fixed tmp = args[count - 1]; 1925*37da2899SCharles.Forsyth FT_Int i; 1926*37da2899SCharles.Forsyth 1927*37da2899SCharles.Forsyth 1928*37da2899SCharles.Forsyth for ( i = count - 2; i >= 0; i-- ) 1929*37da2899SCharles.Forsyth args[i + 1] = args[i]; 1930*37da2899SCharles.Forsyth args[0] = tmp; 1931*37da2899SCharles.Forsyth idx--; 1932*37da2899SCharles.Forsyth } 1933*37da2899SCharles.Forsyth } 1934*37da2899SCharles.Forsyth else 1935*37da2899SCharles.Forsyth { 1936*37da2899SCharles.Forsyth while ( idx < 0 ) 1937*37da2899SCharles.Forsyth { 1938*37da2899SCharles.Forsyth FT_Fixed tmp = args[0]; 1939*37da2899SCharles.Forsyth FT_Int i; 1940*37da2899SCharles.Forsyth 1941*37da2899SCharles.Forsyth 1942*37da2899SCharles.Forsyth for ( i = 0; i < count - 1; i++ ) 1943*37da2899SCharles.Forsyth args[i] = args[i + 1]; 1944*37da2899SCharles.Forsyth args[count - 1] = tmp; 1945*37da2899SCharles.Forsyth idx++; 1946*37da2899SCharles.Forsyth } 1947*37da2899SCharles.Forsyth } 1948*37da2899SCharles.Forsyth args += count; 1949*37da2899SCharles.Forsyth } 1950*37da2899SCharles.Forsyth break; 1951*37da2899SCharles.Forsyth 1952*37da2899SCharles.Forsyth case cff_op_dup: 1953*37da2899SCharles.Forsyth FT_TRACE4(( " dup" )); 1954*37da2899SCharles.Forsyth 1955*37da2899SCharles.Forsyth args[1] = args[0]; 1956*37da2899SCharles.Forsyth args++; 1957*37da2899SCharles.Forsyth break; 1958*37da2899SCharles.Forsyth 1959*37da2899SCharles.Forsyth case cff_op_put: 1960*37da2899SCharles.Forsyth { 1961*37da2899SCharles.Forsyth FT_Fixed val = args[0]; 1962*37da2899SCharles.Forsyth FT_Int idx = (FT_Int)( args[1] >> 16 ); 1963*37da2899SCharles.Forsyth 1964*37da2899SCharles.Forsyth 1965*37da2899SCharles.Forsyth FT_TRACE4(( " put" )); 1966*37da2899SCharles.Forsyth 1967*37da2899SCharles.Forsyth if ( idx >= 0 && idx < decoder->len_buildchar ) 1968*37da2899SCharles.Forsyth decoder->buildchar[idx] = val; 1969*37da2899SCharles.Forsyth } 1970*37da2899SCharles.Forsyth break; 1971*37da2899SCharles.Forsyth 1972*37da2899SCharles.Forsyth case cff_op_get: 1973*37da2899SCharles.Forsyth { 1974*37da2899SCharles.Forsyth FT_Int idx = (FT_Int)( args[0] >> 16 ); 1975*37da2899SCharles.Forsyth FT_Fixed val = 0; 1976*37da2899SCharles.Forsyth 1977*37da2899SCharles.Forsyth 1978*37da2899SCharles.Forsyth FT_TRACE4(( " get" )); 1979*37da2899SCharles.Forsyth 1980*37da2899SCharles.Forsyth if ( idx >= 0 && idx < decoder->len_buildchar ) 1981*37da2899SCharles.Forsyth val = decoder->buildchar[idx]; 1982*37da2899SCharles.Forsyth 1983*37da2899SCharles.Forsyth args[0] = val; 1984*37da2899SCharles.Forsyth args++; 1985*37da2899SCharles.Forsyth } 1986*37da2899SCharles.Forsyth break; 1987*37da2899SCharles.Forsyth 1988*37da2899SCharles.Forsyth case cff_op_store: 1989*37da2899SCharles.Forsyth FT_TRACE4(( " store ")); 1990*37da2899SCharles.Forsyth 1991*37da2899SCharles.Forsyth goto Unimplemented; 1992*37da2899SCharles.Forsyth 1993*37da2899SCharles.Forsyth case cff_op_load: 1994*37da2899SCharles.Forsyth FT_TRACE4(( " load" )); 1995*37da2899SCharles.Forsyth 1996*37da2899SCharles.Forsyth goto Unimplemented; 1997*37da2899SCharles.Forsyth 1998*37da2899SCharles.Forsyth case cff_op_dotsection: 1999*37da2899SCharles.Forsyth /* this operator is deprecated and ignored by the parser */ 2000*37da2899SCharles.Forsyth FT_TRACE4(( " dotsection" )); 2001*37da2899SCharles.Forsyth break; 2002*37da2899SCharles.Forsyth 2003*37da2899SCharles.Forsyth case cff_op_and: 2004*37da2899SCharles.Forsyth { 2005*37da2899SCharles.Forsyth FT_Fixed cond = args[0] && args[1]; 2006*37da2899SCharles.Forsyth 2007*37da2899SCharles.Forsyth 2008*37da2899SCharles.Forsyth FT_TRACE4(( " and" )); 2009*37da2899SCharles.Forsyth 2010*37da2899SCharles.Forsyth args[0] = cond ? 0x10000L : 0; 2011*37da2899SCharles.Forsyth args++; 2012*37da2899SCharles.Forsyth } 2013*37da2899SCharles.Forsyth break; 2014*37da2899SCharles.Forsyth 2015*37da2899SCharles.Forsyth case cff_op_or: 2016*37da2899SCharles.Forsyth { 2017*37da2899SCharles.Forsyth FT_Fixed cond = args[0] || args[1]; 2018*37da2899SCharles.Forsyth 2019*37da2899SCharles.Forsyth 2020*37da2899SCharles.Forsyth FT_TRACE4(( " or" )); 2021*37da2899SCharles.Forsyth 2022*37da2899SCharles.Forsyth args[0] = cond ? 0x10000L : 0; 2023*37da2899SCharles.Forsyth args++; 2024*37da2899SCharles.Forsyth } 2025*37da2899SCharles.Forsyth break; 2026*37da2899SCharles.Forsyth 2027*37da2899SCharles.Forsyth case cff_op_eq: 2028*37da2899SCharles.Forsyth { 2029*37da2899SCharles.Forsyth FT_Fixed cond = !args[0]; 2030*37da2899SCharles.Forsyth 2031*37da2899SCharles.Forsyth 2032*37da2899SCharles.Forsyth FT_TRACE4(( " eq" )); 2033*37da2899SCharles.Forsyth 2034*37da2899SCharles.Forsyth args[0] = cond ? 0x10000L : 0; 2035*37da2899SCharles.Forsyth args++; 2036*37da2899SCharles.Forsyth } 2037*37da2899SCharles.Forsyth break; 2038*37da2899SCharles.Forsyth 2039*37da2899SCharles.Forsyth case cff_op_ifelse: 2040*37da2899SCharles.Forsyth { 2041*37da2899SCharles.Forsyth FT_Fixed cond = (args[2] <= args[3]); 2042*37da2899SCharles.Forsyth 2043*37da2899SCharles.Forsyth 2044*37da2899SCharles.Forsyth FT_TRACE4(( " ifelse" )); 2045*37da2899SCharles.Forsyth 2046*37da2899SCharles.Forsyth if ( !cond ) 2047*37da2899SCharles.Forsyth args[0] = args[1]; 2048*37da2899SCharles.Forsyth args++; 2049*37da2899SCharles.Forsyth } 2050*37da2899SCharles.Forsyth break; 2051*37da2899SCharles.Forsyth 2052*37da2899SCharles.Forsyth case cff_op_callsubr: 2053*37da2899SCharles.Forsyth { 2054*37da2899SCharles.Forsyth FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + 2055*37da2899SCharles.Forsyth decoder->locals_bias ); 2056*37da2899SCharles.Forsyth 2057*37da2899SCharles.Forsyth 2058*37da2899SCharles.Forsyth FT_TRACE4(( " callsubr(%d)", idx )); 2059*37da2899SCharles.Forsyth 2060*37da2899SCharles.Forsyth if ( idx >= decoder->num_locals ) 2061*37da2899SCharles.Forsyth { 2062*37da2899SCharles.Forsyth FT_ERROR(( "cff_decoder_parse_charstrings:" )); 2063*37da2899SCharles.Forsyth FT_ERROR(( " invalid local subr index\n" )); 2064*37da2899SCharles.Forsyth goto Syntax_Error; 2065*37da2899SCharles.Forsyth } 2066*37da2899SCharles.Forsyth 2067*37da2899SCharles.Forsyth if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) 2068*37da2899SCharles.Forsyth { 2069*37da2899SCharles.Forsyth FT_ERROR(( "cff_decoder_parse_charstrings:" 2070*37da2899SCharles.Forsyth " too many nested subrs\n" )); 2071*37da2899SCharles.Forsyth goto Syntax_Error; 2072*37da2899SCharles.Forsyth } 2073*37da2899SCharles.Forsyth 2074*37da2899SCharles.Forsyth zone->cursor = ip; /* save current instruction pointer */ 2075*37da2899SCharles.Forsyth 2076*37da2899SCharles.Forsyth zone++; 2077*37da2899SCharles.Forsyth zone->base = decoder->locals[idx]; 2078*37da2899SCharles.Forsyth zone->limit = decoder->locals[idx + 1]; 2079*37da2899SCharles.Forsyth zone->cursor = zone->base; 2080*37da2899SCharles.Forsyth 2081*37da2899SCharles.Forsyth if ( !zone->base ) 2082*37da2899SCharles.Forsyth { 2083*37da2899SCharles.Forsyth FT_ERROR(( "cff_decoder_parse_charstrings:" 2084*37da2899SCharles.Forsyth " invoking empty subrs!\n" )); 2085*37da2899SCharles.Forsyth goto Syntax_Error; 2086*37da2899SCharles.Forsyth } 2087*37da2899SCharles.Forsyth 2088*37da2899SCharles.Forsyth decoder->zone = zone; 2089*37da2899SCharles.Forsyth ip = zone->base; 2090*37da2899SCharles.Forsyth limit = zone->limit; 2091*37da2899SCharles.Forsyth } 2092*37da2899SCharles.Forsyth break; 2093*37da2899SCharles.Forsyth 2094*37da2899SCharles.Forsyth case cff_op_callgsubr: 2095*37da2899SCharles.Forsyth { 2096*37da2899SCharles.Forsyth FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + 2097*37da2899SCharles.Forsyth decoder->globals_bias ); 2098*37da2899SCharles.Forsyth 2099*37da2899SCharles.Forsyth 2100*37da2899SCharles.Forsyth FT_TRACE4(( " callgsubr(%d)", idx )); 2101*37da2899SCharles.Forsyth 2102*37da2899SCharles.Forsyth if ( idx >= decoder->num_globals ) 2103*37da2899SCharles.Forsyth { 2104*37da2899SCharles.Forsyth FT_ERROR(( "cff_decoder_parse_charstrings:" )); 2105*37da2899SCharles.Forsyth FT_ERROR(( " invalid global subr index\n" )); 2106*37da2899SCharles.Forsyth goto Syntax_Error; 2107*37da2899SCharles.Forsyth } 2108*37da2899SCharles.Forsyth 2109*37da2899SCharles.Forsyth if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) 2110*37da2899SCharles.Forsyth { 2111*37da2899SCharles.Forsyth FT_ERROR(( "cff_decoder_parse_charstrings:" 2112*37da2899SCharles.Forsyth " too many nested subrs\n" )); 2113*37da2899SCharles.Forsyth goto Syntax_Error; 2114*37da2899SCharles.Forsyth } 2115*37da2899SCharles.Forsyth 2116*37da2899SCharles.Forsyth zone->cursor = ip; /* save current instruction pointer */ 2117*37da2899SCharles.Forsyth 2118*37da2899SCharles.Forsyth zone++; 2119*37da2899SCharles.Forsyth zone->base = decoder->globals[idx]; 2120*37da2899SCharles.Forsyth zone->limit = decoder->globals[idx + 1]; 2121*37da2899SCharles.Forsyth zone->cursor = zone->base; 2122*37da2899SCharles.Forsyth 2123*37da2899SCharles.Forsyth if ( !zone->base ) 2124*37da2899SCharles.Forsyth { 2125*37da2899SCharles.Forsyth FT_ERROR(( "cff_decoder_parse_charstrings:" 2126*37da2899SCharles.Forsyth " invoking empty subrs!\n" )); 2127*37da2899SCharles.Forsyth goto Syntax_Error; 2128*37da2899SCharles.Forsyth } 2129*37da2899SCharles.Forsyth 2130*37da2899SCharles.Forsyth decoder->zone = zone; 2131*37da2899SCharles.Forsyth ip = zone->base; 2132*37da2899SCharles.Forsyth limit = zone->limit; 2133*37da2899SCharles.Forsyth } 2134*37da2899SCharles.Forsyth break; 2135*37da2899SCharles.Forsyth 2136*37da2899SCharles.Forsyth case cff_op_return: 2137*37da2899SCharles.Forsyth FT_TRACE4(( " return" )); 2138*37da2899SCharles.Forsyth 2139*37da2899SCharles.Forsyth if ( decoder->zone <= decoder->zones ) 2140*37da2899SCharles.Forsyth { 2141*37da2899SCharles.Forsyth FT_ERROR(( "cff_decoder_parse_charstrings:" 2142*37da2899SCharles.Forsyth " unexpected return\n" )); 2143*37da2899SCharles.Forsyth goto Syntax_Error; 2144*37da2899SCharles.Forsyth } 2145*37da2899SCharles.Forsyth 2146*37da2899SCharles.Forsyth decoder->zone--; 2147*37da2899SCharles.Forsyth zone = decoder->zone; 2148*37da2899SCharles.Forsyth ip = zone->cursor; 2149*37da2899SCharles.Forsyth limit = zone->limit; 2150*37da2899SCharles.Forsyth break; 2151*37da2899SCharles.Forsyth 2152*37da2899SCharles.Forsyth default: 2153*37da2899SCharles.Forsyth Unimplemented: 2154*37da2899SCharles.Forsyth FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); 2155*37da2899SCharles.Forsyth 2156*37da2899SCharles.Forsyth if ( ip[-1] == 12 ) 2157*37da2899SCharles.Forsyth FT_ERROR(( " %d", ip[0] )); 2158*37da2899SCharles.Forsyth FT_ERROR(( "\n" )); 2159*37da2899SCharles.Forsyth 2160*37da2899SCharles.Forsyth return CFF_Err_Unimplemented_Feature; 2161*37da2899SCharles.Forsyth } 2162*37da2899SCharles.Forsyth 2163*37da2899SCharles.Forsyth decoder->top = args; 2164*37da2899SCharles.Forsyth 2165*37da2899SCharles.Forsyth } /* general operator processing */ 2166*37da2899SCharles.Forsyth 2167*37da2899SCharles.Forsyth } /* while ip < limit */ 2168*37da2899SCharles.Forsyth 2169*37da2899SCharles.Forsyth FT_TRACE4(( "..end..\n\n" )); 2170*37da2899SCharles.Forsyth 2171*37da2899SCharles.Forsyth return error; 2172*37da2899SCharles.Forsyth 2173*37da2899SCharles.Forsyth Syntax_Error: 2174*37da2899SCharles.Forsyth FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error!" )); 2175*37da2899SCharles.Forsyth return CFF_Err_Invalid_File_Format; 2176*37da2899SCharles.Forsyth 2177*37da2899SCharles.Forsyth Stack_Underflow: 2178*37da2899SCharles.Forsyth FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow!" )); 2179*37da2899SCharles.Forsyth return CFF_Err_Too_Few_Arguments; 2180*37da2899SCharles.Forsyth 2181*37da2899SCharles.Forsyth Stack_Overflow: 2182*37da2899SCharles.Forsyth FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow!" )); 2183*37da2899SCharles.Forsyth return CFF_Err_Stack_Overflow; 2184*37da2899SCharles.Forsyth 2185*37da2899SCharles.Forsyth Memory_Error: 2186*37da2899SCharles.Forsyth return builder->error; 2187*37da2899SCharles.Forsyth } 2188*37da2899SCharles.Forsyth 2189*37da2899SCharles.Forsyth 2190*37da2899SCharles.Forsyth /*************************************************************************/ 2191*37da2899SCharles.Forsyth /*************************************************************************/ 2192*37da2899SCharles.Forsyth /*************************************************************************/ 2193*37da2899SCharles.Forsyth /********** *********/ 2194*37da2899SCharles.Forsyth /********** *********/ 2195*37da2899SCharles.Forsyth /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ 2196*37da2899SCharles.Forsyth /********** *********/ 2197*37da2899SCharles.Forsyth /********** The following code is in charge of computing *********/ 2198*37da2899SCharles.Forsyth /********** the maximum advance width of the font. It *********/ 2199*37da2899SCharles.Forsyth /********** quickly processes each glyph charstring to *********/ 2200*37da2899SCharles.Forsyth /********** extract the value from either a `sbw' or `seac' *********/ 2201*37da2899SCharles.Forsyth /********** operator. *********/ 2202*37da2899SCharles.Forsyth /********** *********/ 2203*37da2899SCharles.Forsyth /*************************************************************************/ 2204*37da2899SCharles.Forsyth /*************************************************************************/ 2205*37da2899SCharles.Forsyth /*************************************************************************/ 2206*37da2899SCharles.Forsyth 2207*37da2899SCharles.Forsyth 2208*37da2899SCharles.Forsyth #if 0 /* unused until we support pure CFF fonts */ 2209*37da2899SCharles.Forsyth 2210*37da2899SCharles.Forsyth 2211*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) 2212*37da2899SCharles.Forsyth cff_compute_max_advance( TT_Face face, 2213*37da2899SCharles.Forsyth FT_Int* max_advance ) 2214*37da2899SCharles.Forsyth { 2215*37da2899SCharles.Forsyth FT_Error error = 0; 2216*37da2899SCharles.Forsyth CFF_Decoder decoder; 2217*37da2899SCharles.Forsyth FT_Int glyph_index; 2218*37da2899SCharles.Forsyth CFF_Font cff = (CFF_Font)face->other; 2219*37da2899SCharles.Forsyth 2220*37da2899SCharles.Forsyth 2221*37da2899SCharles.Forsyth *max_advance = 0; 2222*37da2899SCharles.Forsyth 2223*37da2899SCharles.Forsyth /* Initialize load decoder */ 2224*37da2899SCharles.Forsyth cff_decoder_init( &decoder, face, 0, 0, 0, 0 ); 2225*37da2899SCharles.Forsyth 2226*37da2899SCharles.Forsyth decoder.builder.metrics_only = 1; 2227*37da2899SCharles.Forsyth decoder.builder.load_points = 0; 2228*37da2899SCharles.Forsyth 2229*37da2899SCharles.Forsyth /* For each glyph, parse the glyph charstring and extract */ 2230*37da2899SCharles.Forsyth /* the advance width. */ 2231*37da2899SCharles.Forsyth for ( glyph_index = 0; glyph_index < face->root.num_glyphs; 2232*37da2899SCharles.Forsyth glyph_index++ ) 2233*37da2899SCharles.Forsyth { 2234*37da2899SCharles.Forsyth FT_Byte* charstring; 2235*37da2899SCharles.Forsyth FT_ULong charstring_len; 2236*37da2899SCharles.Forsyth 2237*37da2899SCharles.Forsyth 2238*37da2899SCharles.Forsyth /* now get load the unscaled outline */ 2239*37da2899SCharles.Forsyth error = cff_get_glyph_data( face, glyph_index, 2240*37da2899SCharles.Forsyth &charstring, &charstring_len ); 2241*37da2899SCharles.Forsyth if ( !error ) 2242*37da2899SCharles.Forsyth { 2243*37da2899SCharles.Forsyth cff_decoder_prepare( &decoder, glyph_index ); 2244*37da2899SCharles.Forsyth error = cff_decoder_parse_charstrings( &decoder, 2245*37da2899SCharles.Forsyth charstring, charstring_len ); 2246*37da2899SCharles.Forsyth 2247*37da2899SCharles.Forsyth cff_free_glyph_data( face, &charstring, &charstring_len ); 2248*37da2899SCharles.Forsyth } 2249*37da2899SCharles.Forsyth 2250*37da2899SCharles.Forsyth /* ignore the error if one has occurred -- skip to next glyph */ 2251*37da2899SCharles.Forsyth error = 0; 2252*37da2899SCharles.Forsyth } 2253*37da2899SCharles.Forsyth 2254*37da2899SCharles.Forsyth *max_advance = decoder.builder.advance.x; 2255*37da2899SCharles.Forsyth 2256*37da2899SCharles.Forsyth return CFF_Err_Ok; 2257*37da2899SCharles.Forsyth } 2258*37da2899SCharles.Forsyth 2259*37da2899SCharles.Forsyth 2260*37da2899SCharles.Forsyth #endif /* 0 */ 2261*37da2899SCharles.Forsyth 2262*37da2899SCharles.Forsyth 2263*37da2899SCharles.Forsyth /*************************************************************************/ 2264*37da2899SCharles.Forsyth /*************************************************************************/ 2265*37da2899SCharles.Forsyth /*************************************************************************/ 2266*37da2899SCharles.Forsyth /********** *********/ 2267*37da2899SCharles.Forsyth /********** *********/ 2268*37da2899SCharles.Forsyth /********** UNHINTED GLYPH LOADER *********/ 2269*37da2899SCharles.Forsyth /********** *********/ 2270*37da2899SCharles.Forsyth /********** The following code is in charge of loading a *********/ 2271*37da2899SCharles.Forsyth /********** single outline. It completely ignores hinting *********/ 2272*37da2899SCharles.Forsyth /********** and is used when FT_LOAD_NO_HINTING is set. *********/ 2273*37da2899SCharles.Forsyth /********** *********/ 2274*37da2899SCharles.Forsyth /*************************************************************************/ 2275*37da2899SCharles.Forsyth /*************************************************************************/ 2276*37da2899SCharles.Forsyth /*************************************************************************/ 2277*37da2899SCharles.Forsyth 2278*37da2899SCharles.Forsyth 2279*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) cff_slot_load(CFF_GlyphSlot glyph,CFF_Size size,FT_Int glyph_index,FT_Int32 load_flags)2280*37da2899SCharles.Forsyth cff_slot_load( CFF_GlyphSlot glyph, 2281*37da2899SCharles.Forsyth CFF_Size size, 2282*37da2899SCharles.Forsyth FT_Int glyph_index, 2283*37da2899SCharles.Forsyth FT_Int32 load_flags ) 2284*37da2899SCharles.Forsyth { 2285*37da2899SCharles.Forsyth FT_Error error; 2286*37da2899SCharles.Forsyth CFF_Decoder decoder; 2287*37da2899SCharles.Forsyth TT_Face face = (TT_Face)glyph->root.face; 2288*37da2899SCharles.Forsyth FT_Bool hinting; 2289*37da2899SCharles.Forsyth CFF_Font cff = (CFF_Font)face->extra.data; 2290*37da2899SCharles.Forsyth 2291*37da2899SCharles.Forsyth FT_Matrix font_matrix; 2292*37da2899SCharles.Forsyth FT_Vector font_offset; 2293*37da2899SCharles.Forsyth 2294*37da2899SCharles.Forsyth 2295*37da2899SCharles.Forsyth if ( load_flags & FT_LOAD_NO_RECURSE ) 2296*37da2899SCharles.Forsyth load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 2297*37da2899SCharles.Forsyth 2298*37da2899SCharles.Forsyth glyph->x_scale = 0x10000L; 2299*37da2899SCharles.Forsyth glyph->y_scale = 0x10000L; 2300*37da2899SCharles.Forsyth if ( size ) 2301*37da2899SCharles.Forsyth { 2302*37da2899SCharles.Forsyth glyph->x_scale = size->metrics.x_scale; 2303*37da2899SCharles.Forsyth glyph->y_scale = size->metrics.y_scale; 2304*37da2899SCharles.Forsyth } 2305*37da2899SCharles.Forsyth 2306*37da2899SCharles.Forsyth glyph->root.outline.n_points = 0; 2307*37da2899SCharles.Forsyth glyph->root.outline.n_contours = 0; 2308*37da2899SCharles.Forsyth 2309*37da2899SCharles.Forsyth hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && 2310*37da2899SCharles.Forsyth ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); 2311*37da2899SCharles.Forsyth 2312*37da2899SCharles.Forsyth glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ 2313*37da2899SCharles.Forsyth 2314*37da2899SCharles.Forsyth { 2315*37da2899SCharles.Forsyth FT_Byte* charstring; 2316*37da2899SCharles.Forsyth FT_ULong charstring_len; 2317*37da2899SCharles.Forsyth 2318*37da2899SCharles.Forsyth 2319*37da2899SCharles.Forsyth cff_decoder_init( &decoder, face, size, glyph, hinting, 2320*37da2899SCharles.Forsyth FT_LOAD_TARGET_MODE(load_flags) ); 2321*37da2899SCharles.Forsyth 2322*37da2899SCharles.Forsyth decoder.builder.no_recurse = 2323*37da2899SCharles.Forsyth (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); 2324*37da2899SCharles.Forsyth 2325*37da2899SCharles.Forsyth /* now load the unscaled outline */ 2326*37da2899SCharles.Forsyth error = cff_get_glyph_data( face, glyph_index, 2327*37da2899SCharles.Forsyth &charstring, &charstring_len ); 2328*37da2899SCharles.Forsyth if ( !error ) 2329*37da2899SCharles.Forsyth { 2330*37da2899SCharles.Forsyth cff_decoder_prepare( &decoder, glyph_index ); 2331*37da2899SCharles.Forsyth error = cff_decoder_parse_charstrings( &decoder, 2332*37da2899SCharles.Forsyth charstring, charstring_len ); 2333*37da2899SCharles.Forsyth 2334*37da2899SCharles.Forsyth cff_free_glyph_data( face, &charstring, charstring_len ); 2335*37da2899SCharles.Forsyth 2336*37da2899SCharles.Forsyth 2337*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL 2338*37da2899SCharles.Forsyth /* Control data and length may not be available for incremental */ 2339*37da2899SCharles.Forsyth /* fonts. */ 2340*37da2899SCharles.Forsyth if ( face->root.internal->incremental_interface ) 2341*37da2899SCharles.Forsyth { 2342*37da2899SCharles.Forsyth glyph->root.control_data = 0; 2343*37da2899SCharles.Forsyth glyph->root.control_len = 0; 2344*37da2899SCharles.Forsyth } 2345*37da2899SCharles.Forsyth else 2346*37da2899SCharles.Forsyth #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 2347*37da2899SCharles.Forsyth 2348*37da2899SCharles.Forsyth /* We set control_data and control_len if charstrings is loaded. */ 2349*37da2899SCharles.Forsyth /* See how charstring loads at cff_index_access_element() in */ 2350*37da2899SCharles.Forsyth /* cffload.c. */ 2351*37da2899SCharles.Forsyth { 2352*37da2899SCharles.Forsyth CFF_IndexRec csindex = cff->charstrings_index; 2353*37da2899SCharles.Forsyth 2354*37da2899SCharles.Forsyth 2355*37da2899SCharles.Forsyth glyph->root.control_data = 2356*37da2899SCharles.Forsyth csindex.bytes + csindex.offsets[glyph_index] - 1; 2357*37da2899SCharles.Forsyth glyph->root.control_len = 2358*37da2899SCharles.Forsyth charstring_len; 2359*37da2899SCharles.Forsyth } 2360*37da2899SCharles.Forsyth } 2361*37da2899SCharles.Forsyth 2362*37da2899SCharles.Forsyth /* save new glyph tables */ 2363*37da2899SCharles.Forsyth cff_builder_done( &decoder.builder ); 2364*37da2899SCharles.Forsyth } 2365*37da2899SCharles.Forsyth 2366*37da2899SCharles.Forsyth font_matrix = cff->top_font.font_dict.font_matrix; 2367*37da2899SCharles.Forsyth font_offset = cff->top_font.font_dict.font_offset; 2368*37da2899SCharles.Forsyth 2369*37da2899SCharles.Forsyth /* Now, set the metrics -- this is rather simple, as */ 2370*37da2899SCharles.Forsyth /* the left side bearing is the xMin, and the top side */ 2371*37da2899SCharles.Forsyth /* bearing the yMax. */ 2372*37da2899SCharles.Forsyth if ( !error ) 2373*37da2899SCharles.Forsyth { 2374*37da2899SCharles.Forsyth /* For composite glyphs, return only left side bearing and */ 2375*37da2899SCharles.Forsyth /* advance width. */ 2376*37da2899SCharles.Forsyth if ( load_flags & FT_LOAD_NO_RECURSE ) 2377*37da2899SCharles.Forsyth { 2378*37da2899SCharles.Forsyth FT_Slot_Internal internal = glyph->root.internal; 2379*37da2899SCharles.Forsyth 2380*37da2899SCharles.Forsyth 2381*37da2899SCharles.Forsyth glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; 2382*37da2899SCharles.Forsyth glyph->root.metrics.horiAdvance = decoder.glyph_width; 2383*37da2899SCharles.Forsyth internal->glyph_matrix = font_matrix; 2384*37da2899SCharles.Forsyth internal->glyph_delta = font_offset; 2385*37da2899SCharles.Forsyth internal->glyph_transformed = 1; 2386*37da2899SCharles.Forsyth } 2387*37da2899SCharles.Forsyth else 2388*37da2899SCharles.Forsyth { 2389*37da2899SCharles.Forsyth FT_BBox cbox; 2390*37da2899SCharles.Forsyth FT_Glyph_Metrics* metrics = &glyph->root.metrics; 2391*37da2899SCharles.Forsyth 2392*37da2899SCharles.Forsyth 2393*37da2899SCharles.Forsyth /* copy the _unscaled_ advance width */ 2394*37da2899SCharles.Forsyth metrics->horiAdvance = decoder.glyph_width; 2395*37da2899SCharles.Forsyth glyph->root.linearHoriAdvance = decoder.glyph_width; 2396*37da2899SCharles.Forsyth glyph->root.internal->glyph_transformed = 0; 2397*37da2899SCharles.Forsyth 2398*37da2899SCharles.Forsyth /* make up vertical metrics */ 2399*37da2899SCharles.Forsyth metrics->vertBearingX = 0; 2400*37da2899SCharles.Forsyth metrics->vertBearingY = 0; 2401*37da2899SCharles.Forsyth metrics->vertAdvance = 0; 2402*37da2899SCharles.Forsyth 2403*37da2899SCharles.Forsyth glyph->root.linearVertAdvance = 0; 2404*37da2899SCharles.Forsyth 2405*37da2899SCharles.Forsyth glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; 2406*37da2899SCharles.Forsyth 2407*37da2899SCharles.Forsyth glyph->root.outline.flags = 0; 2408*37da2899SCharles.Forsyth if ( size && size->metrics.y_ppem < 24 ) 2409*37da2899SCharles.Forsyth glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; 2410*37da2899SCharles.Forsyth 2411*37da2899SCharles.Forsyth glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; 2412*37da2899SCharles.Forsyth 2413*37da2899SCharles.Forsyth /* apply the font matrix */ 2414*37da2899SCharles.Forsyth FT_Outline_Transform( &glyph->root.outline, &font_matrix ); 2415*37da2899SCharles.Forsyth 2416*37da2899SCharles.Forsyth FT_Outline_Translate( &glyph->root.outline, 2417*37da2899SCharles.Forsyth font_offset.x, 2418*37da2899SCharles.Forsyth font_offset.y ); 2419*37da2899SCharles.Forsyth 2420*37da2899SCharles.Forsyth if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) 2421*37da2899SCharles.Forsyth { 2422*37da2899SCharles.Forsyth /* scale the outline and the metrics */ 2423*37da2899SCharles.Forsyth FT_Int n; 2424*37da2899SCharles.Forsyth FT_Outline* cur = &glyph->root.outline; 2425*37da2899SCharles.Forsyth FT_Vector* vec = cur->points; 2426*37da2899SCharles.Forsyth FT_Fixed x_scale = glyph->x_scale; 2427*37da2899SCharles.Forsyth FT_Fixed y_scale = glyph->y_scale; 2428*37da2899SCharles.Forsyth 2429*37da2899SCharles.Forsyth 2430*37da2899SCharles.Forsyth /* First of all, scale the points */ 2431*37da2899SCharles.Forsyth if ( !hinting ) 2432*37da2899SCharles.Forsyth for ( n = cur->n_points; n > 0; n--, vec++ ) 2433*37da2899SCharles.Forsyth { 2434*37da2899SCharles.Forsyth vec->x = FT_MulFix( vec->x, x_scale ); 2435*37da2899SCharles.Forsyth vec->y = FT_MulFix( vec->y, y_scale ); 2436*37da2899SCharles.Forsyth } 2437*37da2899SCharles.Forsyth 2438*37da2899SCharles.Forsyth FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); 2439*37da2899SCharles.Forsyth 2440*37da2899SCharles.Forsyth /* Then scale the metrics */ 2441*37da2899SCharles.Forsyth metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 2442*37da2899SCharles.Forsyth metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 2443*37da2899SCharles.Forsyth 2444*37da2899SCharles.Forsyth metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); 2445*37da2899SCharles.Forsyth metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); 2446*37da2899SCharles.Forsyth 2447*37da2899SCharles.Forsyth if ( hinting ) 2448*37da2899SCharles.Forsyth { 2449*37da2899SCharles.Forsyth metrics->horiAdvance = ( metrics->horiAdvance + 32 ) & -64; 2450*37da2899SCharles.Forsyth metrics->vertAdvance = ( metrics->vertAdvance + 32 ) & -64; 2451*37da2899SCharles.Forsyth 2452*37da2899SCharles.Forsyth metrics->vertBearingX = ( metrics->vertBearingX + 32 ) & -64; 2453*37da2899SCharles.Forsyth metrics->vertBearingY = ( metrics->vertBearingY + 32 ) & -64; 2454*37da2899SCharles.Forsyth } 2455*37da2899SCharles.Forsyth } 2456*37da2899SCharles.Forsyth 2457*37da2899SCharles.Forsyth /* compute the other metrics */ 2458*37da2899SCharles.Forsyth FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); 2459*37da2899SCharles.Forsyth 2460*37da2899SCharles.Forsyth /* grid fit the bounding box if necessary */ 2461*37da2899SCharles.Forsyth if ( hinting ) 2462*37da2899SCharles.Forsyth { 2463*37da2899SCharles.Forsyth cbox.xMin &= -64; 2464*37da2899SCharles.Forsyth cbox.yMin &= -64; 2465*37da2899SCharles.Forsyth cbox.xMax = ( cbox.xMax + 63 ) & -64; 2466*37da2899SCharles.Forsyth cbox.yMax = ( cbox.yMax + 63 ) & -64; 2467*37da2899SCharles.Forsyth } 2468*37da2899SCharles.Forsyth 2469*37da2899SCharles.Forsyth metrics->width = cbox.xMax - cbox.xMin; 2470*37da2899SCharles.Forsyth metrics->height = cbox.yMax - cbox.yMin; 2471*37da2899SCharles.Forsyth 2472*37da2899SCharles.Forsyth metrics->horiBearingX = cbox.xMin; 2473*37da2899SCharles.Forsyth metrics->horiBearingY = cbox.yMax; 2474*37da2899SCharles.Forsyth } 2475*37da2899SCharles.Forsyth } 2476*37da2899SCharles.Forsyth 2477*37da2899SCharles.Forsyth return error; 2478*37da2899SCharles.Forsyth } 2479*37da2899SCharles.Forsyth 2480*37da2899SCharles.Forsyth 2481*37da2899SCharles.Forsyth /* END */ 2482