1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* pshrec.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* FreeType PostScript hints recorder (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 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_FREETYPE_H 21*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H 22*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 23*37da2899SCharles.Forsyth #include "pshrec.h" 24*37da2899SCharles.Forsyth #include "pshalgo.h" 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsyth #undef FT_COMPONENT 27*37da2899SCharles.Forsyth #define FT_COMPONENT trace_pshrec 28*37da2899SCharles.Forsyth 29*37da2899SCharles.Forsyth #ifdef DEBUG_HINTER 30*37da2899SCharles.Forsyth PS_Hints ps_debug_hints = 0; 31*37da2899SCharles.Forsyth int ps_debug_no_horz_hints = 0; 32*37da2899SCharles.Forsyth int ps_debug_no_vert_hints = 0; 33*37da2899SCharles.Forsyth #endif 34*37da2899SCharles.Forsyth 35*37da2899SCharles.Forsyth 36*37da2899SCharles.Forsyth /*************************************************************************/ 37*37da2899SCharles.Forsyth /*************************************************************************/ 38*37da2899SCharles.Forsyth /***** *****/ 39*37da2899SCharles.Forsyth /***** PS_HINT MANAGEMENT *****/ 40*37da2899SCharles.Forsyth /***** *****/ 41*37da2899SCharles.Forsyth /*************************************************************************/ 42*37da2899SCharles.Forsyth /*************************************************************************/ 43*37da2899SCharles.Forsyth 44*37da2899SCharles.Forsyth /* destroy hints table */ 45*37da2899SCharles.Forsyth static void ps_hint_table_done(PS_Hint_Table table,FT_Memory memory)46*37da2899SCharles.Forsyth ps_hint_table_done( PS_Hint_Table table, 47*37da2899SCharles.Forsyth FT_Memory memory ) 48*37da2899SCharles.Forsyth { 49*37da2899SCharles.Forsyth FT_FREE( table->hints ); 50*37da2899SCharles.Forsyth table->num_hints = 0; 51*37da2899SCharles.Forsyth table->max_hints = 0; 52*37da2899SCharles.Forsyth } 53*37da2899SCharles.Forsyth 54*37da2899SCharles.Forsyth 55*37da2899SCharles.Forsyth /* ensure that a table can contain "count" elements */ 56*37da2899SCharles.Forsyth static FT_Error ps_hint_table_ensure(PS_Hint_Table table,FT_UInt count,FT_Memory memory)57*37da2899SCharles.Forsyth ps_hint_table_ensure( PS_Hint_Table table, 58*37da2899SCharles.Forsyth FT_UInt count, 59*37da2899SCharles.Forsyth FT_Memory memory ) 60*37da2899SCharles.Forsyth { 61*37da2899SCharles.Forsyth FT_UInt old_max = table->max_hints; 62*37da2899SCharles.Forsyth FT_UInt new_max = count; 63*37da2899SCharles.Forsyth FT_Error error = 0; 64*37da2899SCharles.Forsyth 65*37da2899SCharles.Forsyth 66*37da2899SCharles.Forsyth if ( new_max > old_max ) 67*37da2899SCharles.Forsyth { 68*37da2899SCharles.Forsyth /* try to grow the table */ 69*37da2899SCharles.Forsyth new_max = ( new_max + 7 ) & -8; 70*37da2899SCharles.Forsyth if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) ) 71*37da2899SCharles.Forsyth table->max_hints = new_max; 72*37da2899SCharles.Forsyth } 73*37da2899SCharles.Forsyth return error; 74*37da2899SCharles.Forsyth } 75*37da2899SCharles.Forsyth 76*37da2899SCharles.Forsyth 77*37da2899SCharles.Forsyth static FT_Error ps_hint_table_alloc(PS_Hint_Table table,FT_Memory memory,PS_Hint * ahint)78*37da2899SCharles.Forsyth ps_hint_table_alloc( PS_Hint_Table table, 79*37da2899SCharles.Forsyth FT_Memory memory, 80*37da2899SCharles.Forsyth PS_Hint *ahint ) 81*37da2899SCharles.Forsyth { 82*37da2899SCharles.Forsyth FT_Error error = 0; 83*37da2899SCharles.Forsyth FT_UInt count; 84*37da2899SCharles.Forsyth PS_Hint hint = 0; 85*37da2899SCharles.Forsyth 86*37da2899SCharles.Forsyth 87*37da2899SCharles.Forsyth count = table->num_hints; 88*37da2899SCharles.Forsyth count++; 89*37da2899SCharles.Forsyth 90*37da2899SCharles.Forsyth if ( count >= table->max_hints ) 91*37da2899SCharles.Forsyth { 92*37da2899SCharles.Forsyth error = ps_hint_table_ensure( table, count, memory ); 93*37da2899SCharles.Forsyth if ( error ) 94*37da2899SCharles.Forsyth goto Exit; 95*37da2899SCharles.Forsyth } 96*37da2899SCharles.Forsyth 97*37da2899SCharles.Forsyth hint = table->hints + count - 1; 98*37da2899SCharles.Forsyth hint->pos = 0; 99*37da2899SCharles.Forsyth hint->len = 0; 100*37da2899SCharles.Forsyth hint->flags = 0; 101*37da2899SCharles.Forsyth 102*37da2899SCharles.Forsyth table->num_hints = count; 103*37da2899SCharles.Forsyth 104*37da2899SCharles.Forsyth Exit: 105*37da2899SCharles.Forsyth *ahint = hint; 106*37da2899SCharles.Forsyth return error; 107*37da2899SCharles.Forsyth } 108*37da2899SCharles.Forsyth 109*37da2899SCharles.Forsyth 110*37da2899SCharles.Forsyth /*************************************************************************/ 111*37da2899SCharles.Forsyth /*************************************************************************/ 112*37da2899SCharles.Forsyth /***** *****/ 113*37da2899SCharles.Forsyth /***** PS_MASK MANAGEMENT *****/ 114*37da2899SCharles.Forsyth /***** *****/ 115*37da2899SCharles.Forsyth /*************************************************************************/ 116*37da2899SCharles.Forsyth /*************************************************************************/ 117*37da2899SCharles.Forsyth 118*37da2899SCharles.Forsyth /* destroy mask */ 119*37da2899SCharles.Forsyth static void ps_mask_done(PS_Mask mask,FT_Memory memory)120*37da2899SCharles.Forsyth ps_mask_done( PS_Mask mask, 121*37da2899SCharles.Forsyth FT_Memory memory ) 122*37da2899SCharles.Forsyth { 123*37da2899SCharles.Forsyth FT_FREE( mask->bytes ); 124*37da2899SCharles.Forsyth mask->num_bits = 0; 125*37da2899SCharles.Forsyth mask->max_bits = 0; 126*37da2899SCharles.Forsyth mask->end_point = 0; 127*37da2899SCharles.Forsyth } 128*37da2899SCharles.Forsyth 129*37da2899SCharles.Forsyth 130*37da2899SCharles.Forsyth /* ensure that a mask can contain "count" bits */ 131*37da2899SCharles.Forsyth static FT_Error ps_mask_ensure(PS_Mask mask,FT_UInt count,FT_Memory memory)132*37da2899SCharles.Forsyth ps_mask_ensure( PS_Mask mask, 133*37da2899SCharles.Forsyth FT_UInt count, 134*37da2899SCharles.Forsyth FT_Memory memory ) 135*37da2899SCharles.Forsyth { 136*37da2899SCharles.Forsyth FT_UInt old_max = ( mask->max_bits + 7 ) >> 3; 137*37da2899SCharles.Forsyth FT_UInt new_max = ( count + 7 ) >> 3; 138*37da2899SCharles.Forsyth FT_Error error = 0; 139*37da2899SCharles.Forsyth 140*37da2899SCharles.Forsyth 141*37da2899SCharles.Forsyth if ( new_max > old_max ) 142*37da2899SCharles.Forsyth { 143*37da2899SCharles.Forsyth new_max = ( new_max + 7 ) & -8; 144*37da2899SCharles.Forsyth if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) ) 145*37da2899SCharles.Forsyth mask->max_bits = new_max * 8; 146*37da2899SCharles.Forsyth } 147*37da2899SCharles.Forsyth return error; 148*37da2899SCharles.Forsyth } 149*37da2899SCharles.Forsyth 150*37da2899SCharles.Forsyth 151*37da2899SCharles.Forsyth /* test a bit value in a given mask */ 152*37da2899SCharles.Forsyth static FT_Int ps_mask_test_bit(PS_Mask mask,FT_Int idx)153*37da2899SCharles.Forsyth ps_mask_test_bit( PS_Mask mask, 154*37da2899SCharles.Forsyth FT_Int idx ) 155*37da2899SCharles.Forsyth { 156*37da2899SCharles.Forsyth if ( (FT_UInt)idx >= mask->num_bits ) 157*37da2899SCharles.Forsyth return 0; 158*37da2899SCharles.Forsyth 159*37da2899SCharles.Forsyth return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) ); 160*37da2899SCharles.Forsyth } 161*37da2899SCharles.Forsyth 162*37da2899SCharles.Forsyth 163*37da2899SCharles.Forsyth /* clear a given bit */ 164*37da2899SCharles.Forsyth static void ps_mask_clear_bit(PS_Mask mask,FT_Int idx)165*37da2899SCharles.Forsyth ps_mask_clear_bit( PS_Mask mask, 166*37da2899SCharles.Forsyth FT_Int idx ) 167*37da2899SCharles.Forsyth { 168*37da2899SCharles.Forsyth FT_Byte* p; 169*37da2899SCharles.Forsyth 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth if ( (FT_UInt)idx >= mask->num_bits ) 172*37da2899SCharles.Forsyth return; 173*37da2899SCharles.Forsyth 174*37da2899SCharles.Forsyth p = mask->bytes + ( idx >> 3 ); 175*37da2899SCharles.Forsyth p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) ); 176*37da2899SCharles.Forsyth } 177*37da2899SCharles.Forsyth 178*37da2899SCharles.Forsyth 179*37da2899SCharles.Forsyth /* set a given bit, possibly grow the mask */ 180*37da2899SCharles.Forsyth static FT_Error ps_mask_set_bit(PS_Mask mask,FT_Int idx,FT_Memory memory)181*37da2899SCharles.Forsyth ps_mask_set_bit( PS_Mask mask, 182*37da2899SCharles.Forsyth FT_Int idx, 183*37da2899SCharles.Forsyth FT_Memory memory ) 184*37da2899SCharles.Forsyth { 185*37da2899SCharles.Forsyth FT_Error error = 0; 186*37da2899SCharles.Forsyth FT_Byte* p; 187*37da2899SCharles.Forsyth 188*37da2899SCharles.Forsyth 189*37da2899SCharles.Forsyth if ( idx < 0 ) 190*37da2899SCharles.Forsyth goto Exit; 191*37da2899SCharles.Forsyth 192*37da2899SCharles.Forsyth if ( (FT_UInt)idx >= mask->num_bits ) 193*37da2899SCharles.Forsyth { 194*37da2899SCharles.Forsyth error = ps_mask_ensure( mask, idx + 1, memory ); 195*37da2899SCharles.Forsyth if ( error ) 196*37da2899SCharles.Forsyth goto Exit; 197*37da2899SCharles.Forsyth 198*37da2899SCharles.Forsyth mask->num_bits = idx + 1; 199*37da2899SCharles.Forsyth } 200*37da2899SCharles.Forsyth 201*37da2899SCharles.Forsyth p = mask->bytes + ( idx >> 3 ); 202*37da2899SCharles.Forsyth p[0] = (FT_Byte)( p[0] | ( 0x80 >> ( idx & 7 ) ) ); 203*37da2899SCharles.Forsyth 204*37da2899SCharles.Forsyth Exit: 205*37da2899SCharles.Forsyth return error; 206*37da2899SCharles.Forsyth } 207*37da2899SCharles.Forsyth 208*37da2899SCharles.Forsyth 209*37da2899SCharles.Forsyth /* destroy mask table */ 210*37da2899SCharles.Forsyth static void ps_mask_table_done(PS_Mask_Table table,FT_Memory memory)211*37da2899SCharles.Forsyth ps_mask_table_done( PS_Mask_Table table, 212*37da2899SCharles.Forsyth FT_Memory memory ) 213*37da2899SCharles.Forsyth { 214*37da2899SCharles.Forsyth FT_UInt count = table->max_masks; 215*37da2899SCharles.Forsyth PS_Mask mask = table->masks; 216*37da2899SCharles.Forsyth 217*37da2899SCharles.Forsyth 218*37da2899SCharles.Forsyth for ( ; count > 0; count--, mask++ ) 219*37da2899SCharles.Forsyth ps_mask_done( mask, memory ); 220*37da2899SCharles.Forsyth 221*37da2899SCharles.Forsyth FT_FREE( table->masks ); 222*37da2899SCharles.Forsyth table->num_masks = 0; 223*37da2899SCharles.Forsyth table->max_masks = 0; 224*37da2899SCharles.Forsyth } 225*37da2899SCharles.Forsyth 226*37da2899SCharles.Forsyth 227*37da2899SCharles.Forsyth /* ensure that a mask table can contain "count" masks */ 228*37da2899SCharles.Forsyth static FT_Error ps_mask_table_ensure(PS_Mask_Table table,FT_UInt count,FT_Memory memory)229*37da2899SCharles.Forsyth ps_mask_table_ensure( PS_Mask_Table table, 230*37da2899SCharles.Forsyth FT_UInt count, 231*37da2899SCharles.Forsyth FT_Memory memory ) 232*37da2899SCharles.Forsyth { 233*37da2899SCharles.Forsyth FT_UInt old_max = table->max_masks; 234*37da2899SCharles.Forsyth FT_UInt new_max = count; 235*37da2899SCharles.Forsyth FT_Error error = 0; 236*37da2899SCharles.Forsyth 237*37da2899SCharles.Forsyth 238*37da2899SCharles.Forsyth if ( new_max > old_max ) 239*37da2899SCharles.Forsyth { 240*37da2899SCharles.Forsyth new_max = ( new_max + 7 ) & -8; 241*37da2899SCharles.Forsyth if ( !FT_RENEW_ARRAY( table->masks, old_max, new_max ) ) 242*37da2899SCharles.Forsyth table->max_masks = new_max; 243*37da2899SCharles.Forsyth } 244*37da2899SCharles.Forsyth return error; 245*37da2899SCharles.Forsyth } 246*37da2899SCharles.Forsyth 247*37da2899SCharles.Forsyth 248*37da2899SCharles.Forsyth /* allocate a new mask in a table */ 249*37da2899SCharles.Forsyth static FT_Error ps_mask_table_alloc(PS_Mask_Table table,FT_Memory memory,PS_Mask * amask)250*37da2899SCharles.Forsyth ps_mask_table_alloc( PS_Mask_Table table, 251*37da2899SCharles.Forsyth FT_Memory memory, 252*37da2899SCharles.Forsyth PS_Mask *amask ) 253*37da2899SCharles.Forsyth { 254*37da2899SCharles.Forsyth FT_UInt count; 255*37da2899SCharles.Forsyth FT_Error error = 0; 256*37da2899SCharles.Forsyth PS_Mask mask = 0; 257*37da2899SCharles.Forsyth 258*37da2899SCharles.Forsyth 259*37da2899SCharles.Forsyth count = table->num_masks; 260*37da2899SCharles.Forsyth count++; 261*37da2899SCharles.Forsyth 262*37da2899SCharles.Forsyth if ( count > table->max_masks ) 263*37da2899SCharles.Forsyth { 264*37da2899SCharles.Forsyth error = ps_mask_table_ensure( table, count, memory ); 265*37da2899SCharles.Forsyth if ( error ) 266*37da2899SCharles.Forsyth goto Exit; 267*37da2899SCharles.Forsyth } 268*37da2899SCharles.Forsyth 269*37da2899SCharles.Forsyth mask = table->masks + count - 1; 270*37da2899SCharles.Forsyth mask->num_bits = 0; 271*37da2899SCharles.Forsyth mask->end_point = 0; 272*37da2899SCharles.Forsyth table->num_masks = count; 273*37da2899SCharles.Forsyth 274*37da2899SCharles.Forsyth Exit: 275*37da2899SCharles.Forsyth *amask = mask; 276*37da2899SCharles.Forsyth return error; 277*37da2899SCharles.Forsyth } 278*37da2899SCharles.Forsyth 279*37da2899SCharles.Forsyth 280*37da2899SCharles.Forsyth /* return last hint mask in a table, create one if the table is empty */ 281*37da2899SCharles.Forsyth static FT_Error ps_mask_table_last(PS_Mask_Table table,FT_Memory memory,PS_Mask * amask)282*37da2899SCharles.Forsyth ps_mask_table_last( PS_Mask_Table table, 283*37da2899SCharles.Forsyth FT_Memory memory, 284*37da2899SCharles.Forsyth PS_Mask *amask ) 285*37da2899SCharles.Forsyth { 286*37da2899SCharles.Forsyth FT_Error error = 0; 287*37da2899SCharles.Forsyth FT_UInt count; 288*37da2899SCharles.Forsyth PS_Mask mask; 289*37da2899SCharles.Forsyth 290*37da2899SCharles.Forsyth 291*37da2899SCharles.Forsyth count = table->num_masks; 292*37da2899SCharles.Forsyth if ( count == 0 ) 293*37da2899SCharles.Forsyth { 294*37da2899SCharles.Forsyth error = ps_mask_table_alloc( table, memory, &mask ); 295*37da2899SCharles.Forsyth if ( error ) 296*37da2899SCharles.Forsyth goto Exit; 297*37da2899SCharles.Forsyth } 298*37da2899SCharles.Forsyth else 299*37da2899SCharles.Forsyth mask = table->masks + count - 1; 300*37da2899SCharles.Forsyth 301*37da2899SCharles.Forsyth Exit: 302*37da2899SCharles.Forsyth *amask = mask; 303*37da2899SCharles.Forsyth return error; 304*37da2899SCharles.Forsyth } 305*37da2899SCharles.Forsyth 306*37da2899SCharles.Forsyth 307*37da2899SCharles.Forsyth /* set a new mask to a given bit range */ 308*37da2899SCharles.Forsyth static FT_Error ps_mask_table_set_bits(PS_Mask_Table table,FT_Byte * source,FT_UInt bit_pos,FT_UInt bit_count,FT_Memory memory)309*37da2899SCharles.Forsyth ps_mask_table_set_bits( PS_Mask_Table table, 310*37da2899SCharles.Forsyth FT_Byte* source, 311*37da2899SCharles.Forsyth FT_UInt bit_pos, 312*37da2899SCharles.Forsyth FT_UInt bit_count, 313*37da2899SCharles.Forsyth FT_Memory memory ) 314*37da2899SCharles.Forsyth { 315*37da2899SCharles.Forsyth FT_Error error = 0; 316*37da2899SCharles.Forsyth PS_Mask mask; 317*37da2899SCharles.Forsyth 318*37da2899SCharles.Forsyth 319*37da2899SCharles.Forsyth /* allocate new mask, and grow it to "bit_count" bits */ 320*37da2899SCharles.Forsyth error = ps_mask_table_alloc( table, memory, &mask ); 321*37da2899SCharles.Forsyth if ( error ) 322*37da2899SCharles.Forsyth goto Exit; 323*37da2899SCharles.Forsyth 324*37da2899SCharles.Forsyth error = ps_mask_ensure( mask, bit_count, memory ); 325*37da2899SCharles.Forsyth if ( error ) 326*37da2899SCharles.Forsyth goto Exit; 327*37da2899SCharles.Forsyth 328*37da2899SCharles.Forsyth mask->num_bits = bit_count; 329*37da2899SCharles.Forsyth 330*37da2899SCharles.Forsyth /* now, copy bits */ 331*37da2899SCharles.Forsyth { 332*37da2899SCharles.Forsyth FT_Byte* read = source + ( bit_pos >> 3 ); 333*37da2899SCharles.Forsyth FT_Int rmask = 0x80 >> ( bit_pos & 7 ); 334*37da2899SCharles.Forsyth FT_Byte* write = mask->bytes; 335*37da2899SCharles.Forsyth FT_Int wmask = 0x80; 336*37da2899SCharles.Forsyth FT_Int val; 337*37da2899SCharles.Forsyth 338*37da2899SCharles.Forsyth 339*37da2899SCharles.Forsyth for ( ; bit_count > 0; bit_count-- ) 340*37da2899SCharles.Forsyth { 341*37da2899SCharles.Forsyth val = write[0] & ~wmask; 342*37da2899SCharles.Forsyth 343*37da2899SCharles.Forsyth if ( read[0] & rmask ) 344*37da2899SCharles.Forsyth val |= wmask; 345*37da2899SCharles.Forsyth 346*37da2899SCharles.Forsyth write[0] = (FT_Byte)val; 347*37da2899SCharles.Forsyth 348*37da2899SCharles.Forsyth rmask >>= 1; 349*37da2899SCharles.Forsyth if ( rmask == 0 ) 350*37da2899SCharles.Forsyth { 351*37da2899SCharles.Forsyth read++; 352*37da2899SCharles.Forsyth rmask = 0x80; 353*37da2899SCharles.Forsyth } 354*37da2899SCharles.Forsyth 355*37da2899SCharles.Forsyth wmask >>= 1; 356*37da2899SCharles.Forsyth if ( wmask == 0 ) 357*37da2899SCharles.Forsyth { 358*37da2899SCharles.Forsyth write++; 359*37da2899SCharles.Forsyth wmask = 0x80; 360*37da2899SCharles.Forsyth } 361*37da2899SCharles.Forsyth } 362*37da2899SCharles.Forsyth } 363*37da2899SCharles.Forsyth 364*37da2899SCharles.Forsyth Exit: 365*37da2899SCharles.Forsyth return error; 366*37da2899SCharles.Forsyth } 367*37da2899SCharles.Forsyth 368*37da2899SCharles.Forsyth 369*37da2899SCharles.Forsyth /* test whether two masks in a table intersect */ 370*37da2899SCharles.Forsyth static FT_Int ps_mask_table_test_intersect(PS_Mask_Table table,FT_Int index1,FT_Int index2)371*37da2899SCharles.Forsyth ps_mask_table_test_intersect( PS_Mask_Table table, 372*37da2899SCharles.Forsyth FT_Int index1, 373*37da2899SCharles.Forsyth FT_Int index2 ) 374*37da2899SCharles.Forsyth { 375*37da2899SCharles.Forsyth PS_Mask mask1 = table->masks + index1; 376*37da2899SCharles.Forsyth PS_Mask mask2 = table->masks + index2; 377*37da2899SCharles.Forsyth FT_Byte* p1 = mask1->bytes; 378*37da2899SCharles.Forsyth FT_Byte* p2 = mask2->bytes; 379*37da2899SCharles.Forsyth FT_UInt count1 = mask1->num_bits; 380*37da2899SCharles.Forsyth FT_UInt count2 = mask2->num_bits; 381*37da2899SCharles.Forsyth FT_UInt count; 382*37da2899SCharles.Forsyth 383*37da2899SCharles.Forsyth 384*37da2899SCharles.Forsyth count = ( count1 <= count2 ) ? count1 : count2; 385*37da2899SCharles.Forsyth for ( ; count >= 8; count -= 8 ) 386*37da2899SCharles.Forsyth { 387*37da2899SCharles.Forsyth if ( p1[0] & p2[0] ) 388*37da2899SCharles.Forsyth return 1; 389*37da2899SCharles.Forsyth 390*37da2899SCharles.Forsyth p1++; 391*37da2899SCharles.Forsyth p2++; 392*37da2899SCharles.Forsyth } 393*37da2899SCharles.Forsyth 394*37da2899SCharles.Forsyth if ( count == 0 ) 395*37da2899SCharles.Forsyth return 0; 396*37da2899SCharles.Forsyth 397*37da2899SCharles.Forsyth return ( p1[0] & p2[0] ) & ~( 0xFF >> count ); 398*37da2899SCharles.Forsyth } 399*37da2899SCharles.Forsyth 400*37da2899SCharles.Forsyth 401*37da2899SCharles.Forsyth /* merge two masks, used by ps_mask_table_merge_all */ 402*37da2899SCharles.Forsyth static FT_Error ps_mask_table_merge(PS_Mask_Table table,FT_Int index1,FT_Int index2,FT_Memory memory)403*37da2899SCharles.Forsyth ps_mask_table_merge( PS_Mask_Table table, 404*37da2899SCharles.Forsyth FT_Int index1, 405*37da2899SCharles.Forsyth FT_Int index2, 406*37da2899SCharles.Forsyth FT_Memory memory ) 407*37da2899SCharles.Forsyth { 408*37da2899SCharles.Forsyth FT_UInt temp; 409*37da2899SCharles.Forsyth FT_Error error = 0; 410*37da2899SCharles.Forsyth 411*37da2899SCharles.Forsyth 412*37da2899SCharles.Forsyth /* swap index1 and index2 so that index1 < index2 */ 413*37da2899SCharles.Forsyth if ( index1 > index2 ) 414*37da2899SCharles.Forsyth { 415*37da2899SCharles.Forsyth temp = index1; 416*37da2899SCharles.Forsyth index1 = index2; 417*37da2899SCharles.Forsyth index2 = temp; 418*37da2899SCharles.Forsyth } 419*37da2899SCharles.Forsyth 420*37da2899SCharles.Forsyth if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks ) 421*37da2899SCharles.Forsyth { 422*37da2899SCharles.Forsyth /* we need to merge the bitsets of index1 and index2 with a */ 423*37da2899SCharles.Forsyth /* simple union */ 424*37da2899SCharles.Forsyth PS_Mask mask1 = table->masks + index1; 425*37da2899SCharles.Forsyth PS_Mask mask2 = table->masks + index2; 426*37da2899SCharles.Forsyth FT_UInt count1 = mask1->num_bits; 427*37da2899SCharles.Forsyth FT_UInt count2 = mask2->num_bits; 428*37da2899SCharles.Forsyth FT_Int delta; 429*37da2899SCharles.Forsyth 430*37da2899SCharles.Forsyth 431*37da2899SCharles.Forsyth if ( count2 > 0 ) 432*37da2899SCharles.Forsyth { 433*37da2899SCharles.Forsyth FT_UInt pos; 434*37da2899SCharles.Forsyth FT_Byte* read; 435*37da2899SCharles.Forsyth FT_Byte* write; 436*37da2899SCharles.Forsyth 437*37da2899SCharles.Forsyth 438*37da2899SCharles.Forsyth /* if "count2" is greater than "count1", we need to grow the */ 439*37da2899SCharles.Forsyth /* first bitset, and clear the highest bits */ 440*37da2899SCharles.Forsyth if ( count2 > count1 ) 441*37da2899SCharles.Forsyth { 442*37da2899SCharles.Forsyth error = ps_mask_ensure( mask1, count2, memory ); 443*37da2899SCharles.Forsyth if ( error ) 444*37da2899SCharles.Forsyth goto Exit; 445*37da2899SCharles.Forsyth 446*37da2899SCharles.Forsyth for ( pos = count1; pos < count2; pos++ ) 447*37da2899SCharles.Forsyth ps_mask_clear_bit( mask1, pos ); 448*37da2899SCharles.Forsyth } 449*37da2899SCharles.Forsyth 450*37da2899SCharles.Forsyth /* merge (unite) the bitsets */ 451*37da2899SCharles.Forsyth read = mask2->bytes; 452*37da2899SCharles.Forsyth write = mask1->bytes; 453*37da2899SCharles.Forsyth pos = (FT_UInt)( ( count2 + 7 ) >> 3 ); 454*37da2899SCharles.Forsyth 455*37da2899SCharles.Forsyth for ( ; pos > 0; pos-- ) 456*37da2899SCharles.Forsyth { 457*37da2899SCharles.Forsyth write[0] = (FT_Byte)( write[0] | read[0] ); 458*37da2899SCharles.Forsyth write++; 459*37da2899SCharles.Forsyth read++; 460*37da2899SCharles.Forsyth } 461*37da2899SCharles.Forsyth } 462*37da2899SCharles.Forsyth 463*37da2899SCharles.Forsyth /* Now, remove "mask2" from the list. We need to keep the masks */ 464*37da2899SCharles.Forsyth /* sorted in order of importance, so move table elements. */ 465*37da2899SCharles.Forsyth mask2->num_bits = 0; 466*37da2899SCharles.Forsyth mask2->end_point = 0; 467*37da2899SCharles.Forsyth 468*37da2899SCharles.Forsyth delta = table->num_masks - 1 - index2; /* number of masks to move */ 469*37da2899SCharles.Forsyth if ( delta > 0 ) 470*37da2899SCharles.Forsyth { 471*37da2899SCharles.Forsyth /* move to end of table for reuse */ 472*37da2899SCharles.Forsyth PS_MaskRec dummy = *mask2; 473*37da2899SCharles.Forsyth 474*37da2899SCharles.Forsyth 475*37da2899SCharles.Forsyth ft_memmove( mask2, mask2 + 1, delta * sizeof ( PS_MaskRec ) ); 476*37da2899SCharles.Forsyth 477*37da2899SCharles.Forsyth mask2[delta] = dummy; 478*37da2899SCharles.Forsyth } 479*37da2899SCharles.Forsyth 480*37da2899SCharles.Forsyth table->num_masks--; 481*37da2899SCharles.Forsyth } 482*37da2899SCharles.Forsyth else 483*37da2899SCharles.Forsyth FT_ERROR(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n", 484*37da2899SCharles.Forsyth index1, index2 )); 485*37da2899SCharles.Forsyth 486*37da2899SCharles.Forsyth Exit: 487*37da2899SCharles.Forsyth return error; 488*37da2899SCharles.Forsyth } 489*37da2899SCharles.Forsyth 490*37da2899SCharles.Forsyth 491*37da2899SCharles.Forsyth /* Try to merge all masks in a given table. This is used to merge */ 492*37da2899SCharles.Forsyth /* all counter masks into independent counter "paths". */ 493*37da2899SCharles.Forsyth /* */ 494*37da2899SCharles.Forsyth static FT_Error ps_mask_table_merge_all(PS_Mask_Table table,FT_Memory memory)495*37da2899SCharles.Forsyth ps_mask_table_merge_all( PS_Mask_Table table, 496*37da2899SCharles.Forsyth FT_Memory memory ) 497*37da2899SCharles.Forsyth { 498*37da2899SCharles.Forsyth FT_Int index1, index2; 499*37da2899SCharles.Forsyth FT_Error error = 0; 500*37da2899SCharles.Forsyth 501*37da2899SCharles.Forsyth 502*37da2899SCharles.Forsyth for ( index1 = table->num_masks - 1; index1 > 0; index1-- ) 503*37da2899SCharles.Forsyth { 504*37da2899SCharles.Forsyth for ( index2 = index1 - 1; index2 >= 0; index2-- ) 505*37da2899SCharles.Forsyth { 506*37da2899SCharles.Forsyth if ( ps_mask_table_test_intersect( table, index1, index2 ) ) 507*37da2899SCharles.Forsyth { 508*37da2899SCharles.Forsyth error = ps_mask_table_merge( table, index2, index1, memory ); 509*37da2899SCharles.Forsyth if ( error ) 510*37da2899SCharles.Forsyth goto Exit; 511*37da2899SCharles.Forsyth 512*37da2899SCharles.Forsyth break; 513*37da2899SCharles.Forsyth } 514*37da2899SCharles.Forsyth } 515*37da2899SCharles.Forsyth } 516*37da2899SCharles.Forsyth 517*37da2899SCharles.Forsyth Exit: 518*37da2899SCharles.Forsyth return error; 519*37da2899SCharles.Forsyth } 520*37da2899SCharles.Forsyth 521*37da2899SCharles.Forsyth 522*37da2899SCharles.Forsyth /*************************************************************************/ 523*37da2899SCharles.Forsyth /*************************************************************************/ 524*37da2899SCharles.Forsyth /***** *****/ 525*37da2899SCharles.Forsyth /***** PS_DIMENSION MANAGEMENT *****/ 526*37da2899SCharles.Forsyth /***** *****/ 527*37da2899SCharles.Forsyth /*************************************************************************/ 528*37da2899SCharles.Forsyth /*************************************************************************/ 529*37da2899SCharles.Forsyth 530*37da2899SCharles.Forsyth 531*37da2899SCharles.Forsyth /* finalize a given dimension */ 532*37da2899SCharles.Forsyth static void ps_dimension_done(PS_Dimension dimension,FT_Memory memory)533*37da2899SCharles.Forsyth ps_dimension_done( PS_Dimension dimension, 534*37da2899SCharles.Forsyth FT_Memory memory ) 535*37da2899SCharles.Forsyth { 536*37da2899SCharles.Forsyth ps_mask_table_done( &dimension->counters, memory ); 537*37da2899SCharles.Forsyth ps_mask_table_done( &dimension->masks, memory ); 538*37da2899SCharles.Forsyth ps_hint_table_done( &dimension->hints, memory ); 539*37da2899SCharles.Forsyth } 540*37da2899SCharles.Forsyth 541*37da2899SCharles.Forsyth 542*37da2899SCharles.Forsyth /* initialize a given dimension */ 543*37da2899SCharles.Forsyth static void ps_dimension_init(PS_Dimension dimension)544*37da2899SCharles.Forsyth ps_dimension_init( PS_Dimension dimension ) 545*37da2899SCharles.Forsyth { 546*37da2899SCharles.Forsyth dimension->hints.num_hints = 0; 547*37da2899SCharles.Forsyth dimension->masks.num_masks = 0; 548*37da2899SCharles.Forsyth dimension->counters.num_masks = 0; 549*37da2899SCharles.Forsyth } 550*37da2899SCharles.Forsyth 551*37da2899SCharles.Forsyth 552*37da2899SCharles.Forsyth #if 0 553*37da2899SCharles.Forsyth 554*37da2899SCharles.Forsyth /* set a bit at a given index in the current hint mask */ 555*37da2899SCharles.Forsyth static FT_Error 556*37da2899SCharles.Forsyth ps_dimension_set_mask_bit( PS_Dimension dim, 557*37da2899SCharles.Forsyth FT_UInt idx, 558*37da2899SCharles.Forsyth FT_Memory memory ) 559*37da2899SCharles.Forsyth { 560*37da2899SCharles.Forsyth PS_Mask mask; 561*37da2899SCharles.Forsyth FT_Error error = 0; 562*37da2899SCharles.Forsyth 563*37da2899SCharles.Forsyth 564*37da2899SCharles.Forsyth /* get last hint mask */ 565*37da2899SCharles.Forsyth error = ps_mask_table_last( &dim->masks, memory, &mask ); 566*37da2899SCharles.Forsyth if ( error ) 567*37da2899SCharles.Forsyth goto Exit; 568*37da2899SCharles.Forsyth 569*37da2899SCharles.Forsyth error = ps_mask_set_bit( mask, idx, memory ); 570*37da2899SCharles.Forsyth 571*37da2899SCharles.Forsyth Exit: 572*37da2899SCharles.Forsyth return error; 573*37da2899SCharles.Forsyth } 574*37da2899SCharles.Forsyth 575*37da2899SCharles.Forsyth #endif 576*37da2899SCharles.Forsyth 577*37da2899SCharles.Forsyth /* set the end point in a mask, called from "End" & "Reset" methods */ 578*37da2899SCharles.Forsyth static void ps_dimension_end_mask(PS_Dimension dim,FT_UInt end_point)579*37da2899SCharles.Forsyth ps_dimension_end_mask( PS_Dimension dim, 580*37da2899SCharles.Forsyth FT_UInt end_point ) 581*37da2899SCharles.Forsyth { 582*37da2899SCharles.Forsyth FT_UInt count = dim->masks.num_masks; 583*37da2899SCharles.Forsyth PS_Mask mask; 584*37da2899SCharles.Forsyth 585*37da2899SCharles.Forsyth 586*37da2899SCharles.Forsyth if ( count > 0 ) 587*37da2899SCharles.Forsyth { 588*37da2899SCharles.Forsyth mask = dim->masks.masks + count - 1; 589*37da2899SCharles.Forsyth mask->end_point = end_point; 590*37da2899SCharles.Forsyth } 591*37da2899SCharles.Forsyth } 592*37da2899SCharles.Forsyth 593*37da2899SCharles.Forsyth 594*37da2899SCharles.Forsyth /* set the end point in the current mask, then create a new empty one */ 595*37da2899SCharles.Forsyth /* (called by "Reset" method) */ 596*37da2899SCharles.Forsyth static FT_Error ps_dimension_reset_mask(PS_Dimension dim,FT_UInt end_point,FT_Memory memory)597*37da2899SCharles.Forsyth ps_dimension_reset_mask( PS_Dimension dim, 598*37da2899SCharles.Forsyth FT_UInt end_point, 599*37da2899SCharles.Forsyth FT_Memory memory ) 600*37da2899SCharles.Forsyth { 601*37da2899SCharles.Forsyth PS_Mask mask; 602*37da2899SCharles.Forsyth 603*37da2899SCharles.Forsyth 604*37da2899SCharles.Forsyth /* end current mask */ 605*37da2899SCharles.Forsyth ps_dimension_end_mask( dim, end_point ); 606*37da2899SCharles.Forsyth 607*37da2899SCharles.Forsyth /* allocate new one */ 608*37da2899SCharles.Forsyth return ps_mask_table_alloc( &dim->masks, memory, &mask ); 609*37da2899SCharles.Forsyth } 610*37da2899SCharles.Forsyth 611*37da2899SCharles.Forsyth 612*37da2899SCharles.Forsyth /* set a new mask, called from the "T2Stem" method */ 613*37da2899SCharles.Forsyth static FT_Error ps_dimension_set_mask_bits(PS_Dimension dim,const FT_Byte * source,FT_UInt source_pos,FT_UInt source_bits,FT_UInt end_point,FT_Memory memory)614*37da2899SCharles.Forsyth ps_dimension_set_mask_bits( PS_Dimension dim, 615*37da2899SCharles.Forsyth const FT_Byte* source, 616*37da2899SCharles.Forsyth FT_UInt source_pos, 617*37da2899SCharles.Forsyth FT_UInt source_bits, 618*37da2899SCharles.Forsyth FT_UInt end_point, 619*37da2899SCharles.Forsyth FT_Memory memory ) 620*37da2899SCharles.Forsyth { 621*37da2899SCharles.Forsyth FT_Error error = 0; 622*37da2899SCharles.Forsyth 623*37da2899SCharles.Forsyth 624*37da2899SCharles.Forsyth /* reset current mask, if any */ 625*37da2899SCharles.Forsyth error = ps_dimension_reset_mask( dim, end_point, memory ); 626*37da2899SCharles.Forsyth if ( error ) 627*37da2899SCharles.Forsyth goto Exit; 628*37da2899SCharles.Forsyth 629*37da2899SCharles.Forsyth /* set bits in new mask */ 630*37da2899SCharles.Forsyth error = ps_mask_table_set_bits( &dim->masks, (FT_Byte*)source, 631*37da2899SCharles.Forsyth source_pos, source_bits, memory ); 632*37da2899SCharles.Forsyth 633*37da2899SCharles.Forsyth Exit: 634*37da2899SCharles.Forsyth return error; 635*37da2899SCharles.Forsyth } 636*37da2899SCharles.Forsyth 637*37da2899SCharles.Forsyth 638*37da2899SCharles.Forsyth /* add a new single stem (called from "T1Stem" method) */ 639*37da2899SCharles.Forsyth static FT_Error ps_dimension_add_t1stem(PS_Dimension dim,FT_Int pos,FT_Int len,FT_Memory memory,FT_Int * aindex)640*37da2899SCharles.Forsyth ps_dimension_add_t1stem( PS_Dimension dim, 641*37da2899SCharles.Forsyth FT_Int pos, 642*37da2899SCharles.Forsyth FT_Int len, 643*37da2899SCharles.Forsyth FT_Memory memory, 644*37da2899SCharles.Forsyth FT_Int *aindex ) 645*37da2899SCharles.Forsyth { 646*37da2899SCharles.Forsyth FT_Error error = 0; 647*37da2899SCharles.Forsyth FT_UInt flags = 0; 648*37da2899SCharles.Forsyth 649*37da2899SCharles.Forsyth 650*37da2899SCharles.Forsyth /* detect ghost stem */ 651*37da2899SCharles.Forsyth if ( len < 0 ) 652*37da2899SCharles.Forsyth { 653*37da2899SCharles.Forsyth flags |= PS_HINT_FLAG_GHOST; 654*37da2899SCharles.Forsyth if ( len == -21 ) 655*37da2899SCharles.Forsyth { 656*37da2899SCharles.Forsyth flags |= PS_HINT_FLAG_BOTTOM; 657*37da2899SCharles.Forsyth pos += len; 658*37da2899SCharles.Forsyth } 659*37da2899SCharles.Forsyth len = 0; 660*37da2899SCharles.Forsyth } 661*37da2899SCharles.Forsyth 662*37da2899SCharles.Forsyth if ( aindex ) 663*37da2899SCharles.Forsyth *aindex = -1; 664*37da2899SCharles.Forsyth 665*37da2899SCharles.Forsyth /* now, lookup stem in the current hints table */ 666*37da2899SCharles.Forsyth { 667*37da2899SCharles.Forsyth PS_Mask mask; 668*37da2899SCharles.Forsyth FT_UInt idx; 669*37da2899SCharles.Forsyth FT_UInt max = dim->hints.num_hints; 670*37da2899SCharles.Forsyth PS_Hint hint = dim->hints.hints; 671*37da2899SCharles.Forsyth 672*37da2899SCharles.Forsyth 673*37da2899SCharles.Forsyth for ( idx = 0; idx < max; idx++, hint++ ) 674*37da2899SCharles.Forsyth { 675*37da2899SCharles.Forsyth if ( hint->pos == pos && hint->len == len ) 676*37da2899SCharles.Forsyth break; 677*37da2899SCharles.Forsyth } 678*37da2899SCharles.Forsyth 679*37da2899SCharles.Forsyth /* we need to create a new hint in the table */ 680*37da2899SCharles.Forsyth if ( idx >= max ) 681*37da2899SCharles.Forsyth { 682*37da2899SCharles.Forsyth error = ps_hint_table_alloc( &dim->hints, memory, &hint ); 683*37da2899SCharles.Forsyth if ( error ) 684*37da2899SCharles.Forsyth goto Exit; 685*37da2899SCharles.Forsyth 686*37da2899SCharles.Forsyth hint->pos = pos; 687*37da2899SCharles.Forsyth hint->len = len; 688*37da2899SCharles.Forsyth hint->flags = flags; 689*37da2899SCharles.Forsyth } 690*37da2899SCharles.Forsyth 691*37da2899SCharles.Forsyth /* now, store the hint in the current mask */ 692*37da2899SCharles.Forsyth error = ps_mask_table_last( &dim->masks, memory, &mask ); 693*37da2899SCharles.Forsyth if ( error ) 694*37da2899SCharles.Forsyth goto Exit; 695*37da2899SCharles.Forsyth 696*37da2899SCharles.Forsyth error = ps_mask_set_bit( mask, idx, memory ); 697*37da2899SCharles.Forsyth if ( error ) 698*37da2899SCharles.Forsyth goto Exit; 699*37da2899SCharles.Forsyth 700*37da2899SCharles.Forsyth if ( aindex ) 701*37da2899SCharles.Forsyth *aindex = (FT_Int)idx; 702*37da2899SCharles.Forsyth } 703*37da2899SCharles.Forsyth 704*37da2899SCharles.Forsyth Exit: 705*37da2899SCharles.Forsyth return error; 706*37da2899SCharles.Forsyth } 707*37da2899SCharles.Forsyth 708*37da2899SCharles.Forsyth 709*37da2899SCharles.Forsyth /* add a "hstem3/vstem3" counter to our dimension table */ 710*37da2899SCharles.Forsyth static FT_Error ps_dimension_add_counter(PS_Dimension dim,FT_Int hint1,FT_Int hint2,FT_Int hint3,FT_Memory memory)711*37da2899SCharles.Forsyth ps_dimension_add_counter( PS_Dimension dim, 712*37da2899SCharles.Forsyth FT_Int hint1, 713*37da2899SCharles.Forsyth FT_Int hint2, 714*37da2899SCharles.Forsyth FT_Int hint3, 715*37da2899SCharles.Forsyth FT_Memory memory ) 716*37da2899SCharles.Forsyth { 717*37da2899SCharles.Forsyth FT_Error error = 0; 718*37da2899SCharles.Forsyth FT_UInt count = dim->counters.num_masks; 719*37da2899SCharles.Forsyth PS_Mask counter = dim->counters.masks; 720*37da2899SCharles.Forsyth 721*37da2899SCharles.Forsyth 722*37da2899SCharles.Forsyth /* try to find an existing counter mask that already uses */ 723*37da2899SCharles.Forsyth /* one of these stems here */ 724*37da2899SCharles.Forsyth for ( ; count > 0; count--, counter++ ) 725*37da2899SCharles.Forsyth { 726*37da2899SCharles.Forsyth if ( ps_mask_test_bit( counter, hint1 ) || 727*37da2899SCharles.Forsyth ps_mask_test_bit( counter, hint2 ) || 728*37da2899SCharles.Forsyth ps_mask_test_bit( counter, hint3 ) ) 729*37da2899SCharles.Forsyth break; 730*37da2899SCharles.Forsyth } 731*37da2899SCharles.Forsyth 732*37da2899SCharles.Forsyth /* creat a new counter when needed */ 733*37da2899SCharles.Forsyth if ( count == 0 ) 734*37da2899SCharles.Forsyth { 735*37da2899SCharles.Forsyth error = ps_mask_table_alloc( &dim->counters, memory, &counter ); 736*37da2899SCharles.Forsyth if ( error ) 737*37da2899SCharles.Forsyth goto Exit; 738*37da2899SCharles.Forsyth } 739*37da2899SCharles.Forsyth 740*37da2899SCharles.Forsyth /* now, set the bits for our hints in the counter mask */ 741*37da2899SCharles.Forsyth error = ps_mask_set_bit( counter, hint1, memory ); 742*37da2899SCharles.Forsyth if ( error ) 743*37da2899SCharles.Forsyth goto Exit; 744*37da2899SCharles.Forsyth 745*37da2899SCharles.Forsyth error = ps_mask_set_bit( counter, hint2, memory ); 746*37da2899SCharles.Forsyth if ( error ) 747*37da2899SCharles.Forsyth goto Exit; 748*37da2899SCharles.Forsyth 749*37da2899SCharles.Forsyth error = ps_mask_set_bit( counter, hint3, memory ); 750*37da2899SCharles.Forsyth if ( error ) 751*37da2899SCharles.Forsyth goto Exit; 752*37da2899SCharles.Forsyth 753*37da2899SCharles.Forsyth Exit: 754*37da2899SCharles.Forsyth return error; 755*37da2899SCharles.Forsyth } 756*37da2899SCharles.Forsyth 757*37da2899SCharles.Forsyth 758*37da2899SCharles.Forsyth /* end of recording session for a given dimension */ 759*37da2899SCharles.Forsyth static FT_Error ps_dimension_end(PS_Dimension dim,FT_UInt end_point,FT_Memory memory)760*37da2899SCharles.Forsyth ps_dimension_end( PS_Dimension dim, 761*37da2899SCharles.Forsyth FT_UInt end_point, 762*37da2899SCharles.Forsyth FT_Memory memory ) 763*37da2899SCharles.Forsyth { 764*37da2899SCharles.Forsyth /* end hint mask table */ 765*37da2899SCharles.Forsyth ps_dimension_end_mask( dim, end_point ); 766*37da2899SCharles.Forsyth 767*37da2899SCharles.Forsyth /* merge all counter masks into independent "paths" */ 768*37da2899SCharles.Forsyth return ps_mask_table_merge_all( &dim->counters, memory ); 769*37da2899SCharles.Forsyth } 770*37da2899SCharles.Forsyth 771*37da2899SCharles.Forsyth 772*37da2899SCharles.Forsyth /*************************************************************************/ 773*37da2899SCharles.Forsyth /*************************************************************************/ 774*37da2899SCharles.Forsyth /***** *****/ 775*37da2899SCharles.Forsyth /***** PS_RECORDER MANAGEMENT *****/ 776*37da2899SCharles.Forsyth /***** *****/ 777*37da2899SCharles.Forsyth /*************************************************************************/ 778*37da2899SCharles.Forsyth /*************************************************************************/ 779*37da2899SCharles.Forsyth 780*37da2899SCharles.Forsyth 781*37da2899SCharles.Forsyth /* destroy hints */ 782*37da2899SCharles.Forsyth FT_LOCAL( void ) ps_hints_done(PS_Hints hints)783*37da2899SCharles.Forsyth ps_hints_done( PS_Hints hints ) 784*37da2899SCharles.Forsyth { 785*37da2899SCharles.Forsyth FT_Memory memory = hints->memory; 786*37da2899SCharles.Forsyth 787*37da2899SCharles.Forsyth 788*37da2899SCharles.Forsyth ps_dimension_done( &hints->dimension[0], memory ); 789*37da2899SCharles.Forsyth ps_dimension_done( &hints->dimension[1], memory ); 790*37da2899SCharles.Forsyth 791*37da2899SCharles.Forsyth hints->error = 0; 792*37da2899SCharles.Forsyth hints->memory = 0; 793*37da2899SCharles.Forsyth } 794*37da2899SCharles.Forsyth 795*37da2899SCharles.Forsyth 796*37da2899SCharles.Forsyth FT_LOCAL( FT_Error ) ps_hints_init(PS_Hints hints,FT_Memory memory)797*37da2899SCharles.Forsyth ps_hints_init( PS_Hints hints, 798*37da2899SCharles.Forsyth FT_Memory memory ) 799*37da2899SCharles.Forsyth { 800*37da2899SCharles.Forsyth FT_MEM_ZERO( hints, sizeof ( *hints ) ); 801*37da2899SCharles.Forsyth hints->memory = memory; 802*37da2899SCharles.Forsyth return 0; 803*37da2899SCharles.Forsyth } 804*37da2899SCharles.Forsyth 805*37da2899SCharles.Forsyth 806*37da2899SCharles.Forsyth /* initialize a hints for a new session */ 807*37da2899SCharles.Forsyth static void ps_hints_open(PS_Hints hints,PS_Hint_Type hint_type)808*37da2899SCharles.Forsyth ps_hints_open( PS_Hints hints, 809*37da2899SCharles.Forsyth PS_Hint_Type hint_type ) 810*37da2899SCharles.Forsyth { 811*37da2899SCharles.Forsyth switch ( hint_type ) 812*37da2899SCharles.Forsyth { 813*37da2899SCharles.Forsyth case PS_HINT_TYPE_1: 814*37da2899SCharles.Forsyth case PS_HINT_TYPE_2: 815*37da2899SCharles.Forsyth hints->error = 0; 816*37da2899SCharles.Forsyth hints->hint_type = hint_type; 817*37da2899SCharles.Forsyth 818*37da2899SCharles.Forsyth ps_dimension_init( &hints->dimension[0] ); 819*37da2899SCharles.Forsyth ps_dimension_init( &hints->dimension[1] ); 820*37da2899SCharles.Forsyth break; 821*37da2899SCharles.Forsyth 822*37da2899SCharles.Forsyth default: 823*37da2899SCharles.Forsyth hints->error = FT_Err_Invalid_Argument; 824*37da2899SCharles.Forsyth hints->hint_type = hint_type; 825*37da2899SCharles.Forsyth 826*37da2899SCharles.Forsyth FT_ERROR(( "ps_hints_open: invalid charstring type!\n" )); 827*37da2899SCharles.Forsyth break; 828*37da2899SCharles.Forsyth } 829*37da2899SCharles.Forsyth } 830*37da2899SCharles.Forsyth 831*37da2899SCharles.Forsyth 832*37da2899SCharles.Forsyth /* add one or more stems to the current hints table */ 833*37da2899SCharles.Forsyth static void ps_hints_stem(PS_Hints hints,FT_Int dimension,FT_UInt count,FT_Long * stems)834*37da2899SCharles.Forsyth ps_hints_stem( PS_Hints hints, 835*37da2899SCharles.Forsyth FT_Int dimension, 836*37da2899SCharles.Forsyth FT_UInt count, 837*37da2899SCharles.Forsyth FT_Long* stems ) 838*37da2899SCharles.Forsyth { 839*37da2899SCharles.Forsyth if ( !hints->error ) 840*37da2899SCharles.Forsyth { 841*37da2899SCharles.Forsyth /* limit "dimension" to 0..1 */ 842*37da2899SCharles.Forsyth if ( dimension < 0 || dimension > 1 ) 843*37da2899SCharles.Forsyth { 844*37da2899SCharles.Forsyth FT_ERROR(( "ps_hints_stem: invalid dimension (%d) used\n", 845*37da2899SCharles.Forsyth dimension )); 846*37da2899SCharles.Forsyth dimension = ( dimension != 0 ); 847*37da2899SCharles.Forsyth } 848*37da2899SCharles.Forsyth 849*37da2899SCharles.Forsyth /* record the stems in the current hints/masks table */ 850*37da2899SCharles.Forsyth switch ( hints->hint_type ) 851*37da2899SCharles.Forsyth { 852*37da2899SCharles.Forsyth case PS_HINT_TYPE_1: /* Type 1 "hstem" or "vstem" operator */ 853*37da2899SCharles.Forsyth case PS_HINT_TYPE_2: /* Type 2 "hstem" or "vstem" operator */ 854*37da2899SCharles.Forsyth { 855*37da2899SCharles.Forsyth PS_Dimension dim = &hints->dimension[dimension]; 856*37da2899SCharles.Forsyth 857*37da2899SCharles.Forsyth 858*37da2899SCharles.Forsyth for ( ; count > 0; count--, stems += 2 ) 859*37da2899SCharles.Forsyth { 860*37da2899SCharles.Forsyth FT_Error error; 861*37da2899SCharles.Forsyth FT_Memory memory = hints->memory; 862*37da2899SCharles.Forsyth 863*37da2899SCharles.Forsyth 864*37da2899SCharles.Forsyth error = ps_dimension_add_t1stem( dim, stems[0], stems[1], 865*37da2899SCharles.Forsyth memory, NULL ); 866*37da2899SCharles.Forsyth if ( error ) 867*37da2899SCharles.Forsyth { 868*37da2899SCharles.Forsyth FT_ERROR(( "ps_hints_stem: could not add stem" 869*37da2899SCharles.Forsyth " (%d,%d) to hints table\n", stems[0], stems[1] )); 870*37da2899SCharles.Forsyth 871*37da2899SCharles.Forsyth hints->error = error; 872*37da2899SCharles.Forsyth return; 873*37da2899SCharles.Forsyth } 874*37da2899SCharles.Forsyth } 875*37da2899SCharles.Forsyth break; 876*37da2899SCharles.Forsyth } 877*37da2899SCharles.Forsyth 878*37da2899SCharles.Forsyth default: 879*37da2899SCharles.Forsyth FT_ERROR(( "ps_hints_stem: called with invalid hint type (%d)\n", 880*37da2899SCharles.Forsyth hints->hint_type )); 881*37da2899SCharles.Forsyth break; 882*37da2899SCharles.Forsyth } 883*37da2899SCharles.Forsyth } 884*37da2899SCharles.Forsyth } 885*37da2899SCharles.Forsyth 886*37da2899SCharles.Forsyth 887*37da2899SCharles.Forsyth /* add one Type1 counter stem to the current hints table */ 888*37da2899SCharles.Forsyth static void ps_hints_t1stem3(PS_Hints hints,FT_Int dimension,FT_Long * stems)889*37da2899SCharles.Forsyth ps_hints_t1stem3( PS_Hints hints, 890*37da2899SCharles.Forsyth FT_Int dimension, 891*37da2899SCharles.Forsyth FT_Long* stems ) 892*37da2899SCharles.Forsyth { 893*37da2899SCharles.Forsyth FT_Error error = 0; 894*37da2899SCharles.Forsyth 895*37da2899SCharles.Forsyth 896*37da2899SCharles.Forsyth if ( !hints->error ) 897*37da2899SCharles.Forsyth { 898*37da2899SCharles.Forsyth PS_Dimension dim; 899*37da2899SCharles.Forsyth FT_Memory memory = hints->memory; 900*37da2899SCharles.Forsyth FT_Int count; 901*37da2899SCharles.Forsyth FT_Int idx[3]; 902*37da2899SCharles.Forsyth 903*37da2899SCharles.Forsyth 904*37da2899SCharles.Forsyth /* limit "dimension" to 0..1 */ 905*37da2899SCharles.Forsyth if ( dimension < 0 || dimension > 1 ) 906*37da2899SCharles.Forsyth { 907*37da2899SCharles.Forsyth FT_ERROR(( "ps_hints_t1stem3: invalid dimension (%d) used\n", 908*37da2899SCharles.Forsyth dimension )); 909*37da2899SCharles.Forsyth dimension = ( dimension != 0 ); 910*37da2899SCharles.Forsyth } 911*37da2899SCharles.Forsyth 912*37da2899SCharles.Forsyth dim = &hints->dimension[dimension]; 913*37da2899SCharles.Forsyth 914*37da2899SCharles.Forsyth /* there must be 6 elements in the 'stem' array */ 915*37da2899SCharles.Forsyth if ( hints->hint_type == PS_HINT_TYPE_1 ) 916*37da2899SCharles.Forsyth { 917*37da2899SCharles.Forsyth /* add the three stems to our hints/masks table */ 918*37da2899SCharles.Forsyth for ( count = 0; count < 3; count++, stems += 2 ) 919*37da2899SCharles.Forsyth { 920*37da2899SCharles.Forsyth error = ps_dimension_add_t1stem( dim, stems[0], stems[1], 921*37da2899SCharles.Forsyth memory, &idx[count] ); 922*37da2899SCharles.Forsyth if ( error ) 923*37da2899SCharles.Forsyth goto Fail; 924*37da2899SCharles.Forsyth } 925*37da2899SCharles.Forsyth 926*37da2899SCharles.Forsyth /* now, add the hints to the counters table */ 927*37da2899SCharles.Forsyth error = ps_dimension_add_counter( dim, idx[0], idx[1], idx[2], 928*37da2899SCharles.Forsyth memory ); 929*37da2899SCharles.Forsyth if ( error ) 930*37da2899SCharles.Forsyth goto Fail; 931*37da2899SCharles.Forsyth } 932*37da2899SCharles.Forsyth else 933*37da2899SCharles.Forsyth { 934*37da2899SCharles.Forsyth FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type!\n" )); 935*37da2899SCharles.Forsyth error = FT_Err_Invalid_Argument; 936*37da2899SCharles.Forsyth goto Fail; 937*37da2899SCharles.Forsyth } 938*37da2899SCharles.Forsyth } 939*37da2899SCharles.Forsyth 940*37da2899SCharles.Forsyth return; 941*37da2899SCharles.Forsyth 942*37da2899SCharles.Forsyth Fail: 943*37da2899SCharles.Forsyth FT_ERROR(( "ps_hints_t1stem3: could not add counter stems to table\n" )); 944*37da2899SCharles.Forsyth hints->error = error; 945*37da2899SCharles.Forsyth } 946*37da2899SCharles.Forsyth 947*37da2899SCharles.Forsyth 948*37da2899SCharles.Forsyth /* reset hints (only with Type 1 hints) */ 949*37da2899SCharles.Forsyth static void ps_hints_t1reset(PS_Hints hints,FT_UInt end_point)950*37da2899SCharles.Forsyth ps_hints_t1reset( PS_Hints hints, 951*37da2899SCharles.Forsyth FT_UInt end_point ) 952*37da2899SCharles.Forsyth { 953*37da2899SCharles.Forsyth FT_Error error = 0; 954*37da2899SCharles.Forsyth 955*37da2899SCharles.Forsyth 956*37da2899SCharles.Forsyth if ( !hints->error ) 957*37da2899SCharles.Forsyth { 958*37da2899SCharles.Forsyth FT_Memory memory = hints->memory; 959*37da2899SCharles.Forsyth 960*37da2899SCharles.Forsyth 961*37da2899SCharles.Forsyth if ( hints->hint_type == PS_HINT_TYPE_1 ) 962*37da2899SCharles.Forsyth { 963*37da2899SCharles.Forsyth error = ps_dimension_reset_mask( &hints->dimension[0], 964*37da2899SCharles.Forsyth end_point, memory ); 965*37da2899SCharles.Forsyth if ( error ) 966*37da2899SCharles.Forsyth goto Fail; 967*37da2899SCharles.Forsyth 968*37da2899SCharles.Forsyth error = ps_dimension_reset_mask( &hints->dimension[1], 969*37da2899SCharles.Forsyth end_point, memory ); 970*37da2899SCharles.Forsyth if ( error ) 971*37da2899SCharles.Forsyth goto Fail; 972*37da2899SCharles.Forsyth } 973*37da2899SCharles.Forsyth else 974*37da2899SCharles.Forsyth { 975*37da2899SCharles.Forsyth /* invalid hint type */ 976*37da2899SCharles.Forsyth error = FT_Err_Invalid_Argument; 977*37da2899SCharles.Forsyth goto Fail; 978*37da2899SCharles.Forsyth } 979*37da2899SCharles.Forsyth } 980*37da2899SCharles.Forsyth return; 981*37da2899SCharles.Forsyth 982*37da2899SCharles.Forsyth Fail: 983*37da2899SCharles.Forsyth hints->error = error; 984*37da2899SCharles.Forsyth } 985*37da2899SCharles.Forsyth 986*37da2899SCharles.Forsyth 987*37da2899SCharles.Forsyth /* Type2 "hintmask" operator, add a new hintmask to each direction */ 988*37da2899SCharles.Forsyth static void ps_hints_t2mask(PS_Hints hints,FT_UInt end_point,FT_UInt bit_count,const FT_Byte * bytes)989*37da2899SCharles.Forsyth ps_hints_t2mask( PS_Hints hints, 990*37da2899SCharles.Forsyth FT_UInt end_point, 991*37da2899SCharles.Forsyth FT_UInt bit_count, 992*37da2899SCharles.Forsyth const FT_Byte* bytes ) 993*37da2899SCharles.Forsyth { 994*37da2899SCharles.Forsyth FT_Error error; 995*37da2899SCharles.Forsyth 996*37da2899SCharles.Forsyth 997*37da2899SCharles.Forsyth if ( !hints->error ) 998*37da2899SCharles.Forsyth { 999*37da2899SCharles.Forsyth PS_Dimension dim = hints->dimension; 1000*37da2899SCharles.Forsyth FT_Memory memory = hints->memory; 1001*37da2899SCharles.Forsyth FT_UInt count1 = dim[0].hints.num_hints; 1002*37da2899SCharles.Forsyth FT_UInt count2 = dim[1].hints.num_hints; 1003*37da2899SCharles.Forsyth 1004*37da2899SCharles.Forsyth 1005*37da2899SCharles.Forsyth /* check bit count; must be equal to current total hint count */ 1006*37da2899SCharles.Forsyth if ( bit_count != count1 + count2 ) 1007*37da2899SCharles.Forsyth { 1008*37da2899SCharles.Forsyth FT_ERROR(( "ps_hints_t2mask: " 1009*37da2899SCharles.Forsyth "called with invalid bitcount %d (instead of %d)\n", 1010*37da2899SCharles.Forsyth bit_count, count1 + count2 )); 1011*37da2899SCharles.Forsyth 1012*37da2899SCharles.Forsyth /* simply ignore the operator */ 1013*37da2899SCharles.Forsyth return; 1014*37da2899SCharles.Forsyth } 1015*37da2899SCharles.Forsyth 1016*37da2899SCharles.Forsyth /* set-up new horizontal and vertical hint mask now */ 1017*37da2899SCharles.Forsyth error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1, 1018*37da2899SCharles.Forsyth end_point, memory ); 1019*37da2899SCharles.Forsyth if ( error ) 1020*37da2899SCharles.Forsyth goto Fail; 1021*37da2899SCharles.Forsyth 1022*37da2899SCharles.Forsyth error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2, 1023*37da2899SCharles.Forsyth end_point, memory ); 1024*37da2899SCharles.Forsyth if ( error ) 1025*37da2899SCharles.Forsyth goto Fail; 1026*37da2899SCharles.Forsyth } 1027*37da2899SCharles.Forsyth return; 1028*37da2899SCharles.Forsyth 1029*37da2899SCharles.Forsyth Fail: 1030*37da2899SCharles.Forsyth hints->error = error; 1031*37da2899SCharles.Forsyth } 1032*37da2899SCharles.Forsyth 1033*37da2899SCharles.Forsyth 1034*37da2899SCharles.Forsyth static void ps_hints_t2counter(PS_Hints hints,FT_UInt bit_count,const FT_Byte * bytes)1035*37da2899SCharles.Forsyth ps_hints_t2counter( PS_Hints hints, 1036*37da2899SCharles.Forsyth FT_UInt bit_count, 1037*37da2899SCharles.Forsyth const FT_Byte* bytes ) 1038*37da2899SCharles.Forsyth { 1039*37da2899SCharles.Forsyth FT_Error error; 1040*37da2899SCharles.Forsyth 1041*37da2899SCharles.Forsyth 1042*37da2899SCharles.Forsyth if ( !hints->error ) 1043*37da2899SCharles.Forsyth { 1044*37da2899SCharles.Forsyth PS_Dimension dim = hints->dimension; 1045*37da2899SCharles.Forsyth FT_Memory memory = hints->memory; 1046*37da2899SCharles.Forsyth FT_UInt count1 = dim[0].hints.num_hints; 1047*37da2899SCharles.Forsyth FT_UInt count2 = dim[1].hints.num_hints; 1048*37da2899SCharles.Forsyth 1049*37da2899SCharles.Forsyth 1050*37da2899SCharles.Forsyth /* check bit count, must be equal to current total hint count */ 1051*37da2899SCharles.Forsyth if ( bit_count != count1 + count2 ) 1052*37da2899SCharles.Forsyth { 1053*37da2899SCharles.Forsyth FT_ERROR(( "ps_hints_t2counter: " 1054*37da2899SCharles.Forsyth "called with invalid bitcount %d (instead of %d)\n", 1055*37da2899SCharles.Forsyth bit_count, count1 + count2 )); 1056*37da2899SCharles.Forsyth 1057*37da2899SCharles.Forsyth /* simply ignore the operator */ 1058*37da2899SCharles.Forsyth return; 1059*37da2899SCharles.Forsyth } 1060*37da2899SCharles.Forsyth 1061*37da2899SCharles.Forsyth /* set-up new horizontal and vertical hint mask now */ 1062*37da2899SCharles.Forsyth error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1, 1063*37da2899SCharles.Forsyth 0, memory ); 1064*37da2899SCharles.Forsyth if ( error ) 1065*37da2899SCharles.Forsyth goto Fail; 1066*37da2899SCharles.Forsyth 1067*37da2899SCharles.Forsyth error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2, 1068*37da2899SCharles.Forsyth 0, memory ); 1069*37da2899SCharles.Forsyth if ( error ) 1070*37da2899SCharles.Forsyth goto Fail; 1071*37da2899SCharles.Forsyth } 1072*37da2899SCharles.Forsyth return; 1073*37da2899SCharles.Forsyth 1074*37da2899SCharles.Forsyth Fail: 1075*37da2899SCharles.Forsyth hints->error = error; 1076*37da2899SCharles.Forsyth } 1077*37da2899SCharles.Forsyth 1078*37da2899SCharles.Forsyth 1079*37da2899SCharles.Forsyth /* end recording session */ 1080*37da2899SCharles.Forsyth static FT_Error ps_hints_close(PS_Hints hints,FT_UInt end_point)1081*37da2899SCharles.Forsyth ps_hints_close( PS_Hints hints, 1082*37da2899SCharles.Forsyth FT_UInt end_point ) 1083*37da2899SCharles.Forsyth { 1084*37da2899SCharles.Forsyth FT_Error error; 1085*37da2899SCharles.Forsyth 1086*37da2899SCharles.Forsyth 1087*37da2899SCharles.Forsyth error = hints->error; 1088*37da2899SCharles.Forsyth if ( !error ) 1089*37da2899SCharles.Forsyth { 1090*37da2899SCharles.Forsyth FT_Memory memory = hints->memory; 1091*37da2899SCharles.Forsyth PS_Dimension dim = hints->dimension; 1092*37da2899SCharles.Forsyth 1093*37da2899SCharles.Forsyth 1094*37da2899SCharles.Forsyth error = ps_dimension_end( &dim[0], end_point, memory ); 1095*37da2899SCharles.Forsyth if ( !error ) 1096*37da2899SCharles.Forsyth { 1097*37da2899SCharles.Forsyth error = ps_dimension_end( &dim[1], end_point, memory ); 1098*37da2899SCharles.Forsyth } 1099*37da2899SCharles.Forsyth } 1100*37da2899SCharles.Forsyth 1101*37da2899SCharles.Forsyth #ifdef DEBUG_HINTER 1102*37da2899SCharles.Forsyth if ( !error ) 1103*37da2899SCharles.Forsyth ps_debug_hints = hints; 1104*37da2899SCharles.Forsyth #endif 1105*37da2899SCharles.Forsyth return error; 1106*37da2899SCharles.Forsyth } 1107*37da2899SCharles.Forsyth 1108*37da2899SCharles.Forsyth 1109*37da2899SCharles.Forsyth /*************************************************************************/ 1110*37da2899SCharles.Forsyth /*************************************************************************/ 1111*37da2899SCharles.Forsyth /***** *****/ 1112*37da2899SCharles.Forsyth /***** TYPE 1 HINTS RECORDING INTERFACE *****/ 1113*37da2899SCharles.Forsyth /***** *****/ 1114*37da2899SCharles.Forsyth /*************************************************************************/ 1115*37da2899SCharles.Forsyth /*************************************************************************/ 1116*37da2899SCharles.Forsyth 1117*37da2899SCharles.Forsyth static void t1_hints_open(T1_Hints hints)1118*37da2899SCharles.Forsyth t1_hints_open( T1_Hints hints ) 1119*37da2899SCharles.Forsyth { 1120*37da2899SCharles.Forsyth ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 ); 1121*37da2899SCharles.Forsyth } 1122*37da2899SCharles.Forsyth 1123*37da2899SCharles.Forsyth static void t1_hints_stem(T1_Hints hints,FT_Int dimension,FT_Long * coords)1124*37da2899SCharles.Forsyth t1_hints_stem( T1_Hints hints, 1125*37da2899SCharles.Forsyth FT_Int dimension, 1126*37da2899SCharles.Forsyth FT_Long* coords ) 1127*37da2899SCharles.Forsyth { 1128*37da2899SCharles.Forsyth ps_hints_stem( (PS_Hints)hints, dimension, 1, coords ); 1129*37da2899SCharles.Forsyth } 1130*37da2899SCharles.Forsyth 1131*37da2899SCharles.Forsyth 1132*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) t1_hints_funcs_init(T1_Hints_FuncsRec * funcs)1133*37da2899SCharles.Forsyth t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ) 1134*37da2899SCharles.Forsyth { 1135*37da2899SCharles.Forsyth FT_MEM_ZERO( (char*)funcs, sizeof ( *funcs ) ); 1136*37da2899SCharles.Forsyth 1137*37da2899SCharles.Forsyth funcs->open = (T1_Hints_OpenFunc) t1_hints_open; 1138*37da2899SCharles.Forsyth funcs->close = (T1_Hints_CloseFunc) ps_hints_close; 1139*37da2899SCharles.Forsyth funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem; 1140*37da2899SCharles.Forsyth funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3; 1141*37da2899SCharles.Forsyth funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset; 1142*37da2899SCharles.Forsyth funcs->apply = (T1_Hints_ApplyFunc) PS_HINTS_APPLY_FUNC; 1143*37da2899SCharles.Forsyth } 1144*37da2899SCharles.Forsyth 1145*37da2899SCharles.Forsyth 1146*37da2899SCharles.Forsyth /*************************************************************************/ 1147*37da2899SCharles.Forsyth /*************************************************************************/ 1148*37da2899SCharles.Forsyth /***** *****/ 1149*37da2899SCharles.Forsyth /***** TYPE 2 HINTS RECORDING INTERFACE *****/ 1150*37da2899SCharles.Forsyth /***** *****/ 1151*37da2899SCharles.Forsyth /*************************************************************************/ 1152*37da2899SCharles.Forsyth /*************************************************************************/ 1153*37da2899SCharles.Forsyth 1154*37da2899SCharles.Forsyth static void t2_hints_open(T2_Hints hints)1155*37da2899SCharles.Forsyth t2_hints_open( T2_Hints hints ) 1156*37da2899SCharles.Forsyth { 1157*37da2899SCharles.Forsyth ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_2 ); 1158*37da2899SCharles.Forsyth } 1159*37da2899SCharles.Forsyth 1160*37da2899SCharles.Forsyth 1161*37da2899SCharles.Forsyth static void t2_hints_stems(T2_Hints hints,FT_Int dimension,FT_Int count,FT_Fixed * coords)1162*37da2899SCharles.Forsyth t2_hints_stems( T2_Hints hints, 1163*37da2899SCharles.Forsyth FT_Int dimension, 1164*37da2899SCharles.Forsyth FT_Int count, 1165*37da2899SCharles.Forsyth FT_Fixed* coords ) 1166*37da2899SCharles.Forsyth { 1167*37da2899SCharles.Forsyth FT_Pos stems[32], y, n, total = count; 1168*37da2899SCharles.Forsyth 1169*37da2899SCharles.Forsyth 1170*37da2899SCharles.Forsyth y = 0; 1171*37da2899SCharles.Forsyth while ( total > 0 ) 1172*37da2899SCharles.Forsyth { 1173*37da2899SCharles.Forsyth /* determine number of stems to write */ 1174*37da2899SCharles.Forsyth count = total; 1175*37da2899SCharles.Forsyth if ( count > 16 ) 1176*37da2899SCharles.Forsyth count = 16; 1177*37da2899SCharles.Forsyth 1178*37da2899SCharles.Forsyth /* compute integer stem positions in font units */ 1179*37da2899SCharles.Forsyth for ( n = 0; n < count * 2; n++ ) 1180*37da2899SCharles.Forsyth { 1181*37da2899SCharles.Forsyth y += coords[n]; 1182*37da2899SCharles.Forsyth stems[n] = ( y + 0x8000 ) >> 16; 1183*37da2899SCharles.Forsyth } 1184*37da2899SCharles.Forsyth 1185*37da2899SCharles.Forsyth /* compute lengths */ 1186*37da2899SCharles.Forsyth for ( n = 0; n < count * 2; n += 2 ) 1187*37da2899SCharles.Forsyth stems[n + 1] = stems[n + 1] - stems[n]; 1188*37da2899SCharles.Forsyth 1189*37da2899SCharles.Forsyth /* add them to the current dimension */ 1190*37da2899SCharles.Forsyth ps_hints_stem( (PS_Hints)hints, dimension, count, stems ); 1191*37da2899SCharles.Forsyth 1192*37da2899SCharles.Forsyth total -= count; 1193*37da2899SCharles.Forsyth } 1194*37da2899SCharles.Forsyth } 1195*37da2899SCharles.Forsyth 1196*37da2899SCharles.Forsyth 1197*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) t2_hints_funcs_init(T2_Hints_FuncsRec * funcs)1198*37da2899SCharles.Forsyth t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ) 1199*37da2899SCharles.Forsyth { 1200*37da2899SCharles.Forsyth FT_MEM_ZERO( funcs, sizeof ( *funcs ) ); 1201*37da2899SCharles.Forsyth 1202*37da2899SCharles.Forsyth funcs->open = (T2_Hints_OpenFunc) t2_hints_open; 1203*37da2899SCharles.Forsyth funcs->close = (T2_Hints_CloseFunc) ps_hints_close; 1204*37da2899SCharles.Forsyth funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; 1205*37da2899SCharles.Forsyth funcs->hintmask= (T2_Hints_MaskFunc) ps_hints_t2mask; 1206*37da2899SCharles.Forsyth funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter; 1207*37da2899SCharles.Forsyth funcs->apply = (T2_Hints_ApplyFunc) PS_HINTS_APPLY_FUNC; 1208*37da2899SCharles.Forsyth } 1209*37da2899SCharles.Forsyth 1210*37da2899SCharles.Forsyth 1211*37da2899SCharles.Forsyth /* END */ 1212