1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* pfrobjs.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* FreeType PFR object methods (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 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 "pfrobjs.h" 20*37da2899SCharles.Forsyth #include "pfrload.h" 21*37da2899SCharles.Forsyth #include "pfrgload.h" 22*37da2899SCharles.Forsyth #include "pfrcmap.h" 23*37da2899SCharles.Forsyth #include "pfrsbit.h" 24*37da2899SCharles.Forsyth #include FT_OUTLINE_H 25*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 26*37da2899SCharles.Forsyth 27*37da2899SCharles.Forsyth #include "pfrerror.h" 28*37da2899SCharles.Forsyth 29*37da2899SCharles.Forsyth #undef FT_COMPONENT 30*37da2899SCharles.Forsyth #define FT_COMPONENT trace_pfr 31*37da2899SCharles.Forsyth 32*37da2899SCharles.Forsyth 33*37da2899SCharles.Forsyth /*************************************************************************/ 34*37da2899SCharles.Forsyth /*************************************************************************/ 35*37da2899SCharles.Forsyth /***** *****/ 36*37da2899SCharles.Forsyth /***** FACE OBJECT METHODS *****/ 37*37da2899SCharles.Forsyth /***** *****/ 38*37da2899SCharles.Forsyth /*************************************************************************/ 39*37da2899SCharles.Forsyth /*************************************************************************/ 40*37da2899SCharles.Forsyth 41*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) pfr_face_done(PFR_Face face)42*37da2899SCharles.Forsyth pfr_face_done( PFR_Face face ) 43*37da2899SCharles.Forsyth { 44*37da2899SCharles.Forsyth /* finalize the physical font record */ 45*37da2899SCharles.Forsyth pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) ); 46*37da2899SCharles.Forsyth 47*37da2899SCharles.Forsyth /* no need to finalize the logical font or the header */ 48*37da2899SCharles.Forsyth } 49*37da2899SCharles.Forsyth 50*37da2899SCharles.Forsyth 51*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) pfr_face_init(FT_Stream stream,PFR_Face face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)52*37da2899SCharles.Forsyth pfr_face_init( FT_Stream stream, 53*37da2899SCharles.Forsyth PFR_Face face, 54*37da2899SCharles.Forsyth FT_Int face_index, 55*37da2899SCharles.Forsyth FT_Int num_params, 56*37da2899SCharles.Forsyth FT_Parameter* params ) 57*37da2899SCharles.Forsyth { 58*37da2899SCharles.Forsyth FT_Error error; 59*37da2899SCharles.Forsyth 60*37da2899SCharles.Forsyth FT_UNUSED( num_params ); 61*37da2899SCharles.Forsyth FT_UNUSED( params ); 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsyth 64*37da2899SCharles.Forsyth /* load the header and check it */ 65*37da2899SCharles.Forsyth error = pfr_header_load( &face->header, stream ); 66*37da2899SCharles.Forsyth if ( error ) 67*37da2899SCharles.Forsyth goto Exit; 68*37da2899SCharles.Forsyth 69*37da2899SCharles.Forsyth if ( !pfr_header_check( &face->header ) ) 70*37da2899SCharles.Forsyth { 71*37da2899SCharles.Forsyth FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" )); 72*37da2899SCharles.Forsyth error = PFR_Err_Unknown_File_Format; 73*37da2899SCharles.Forsyth goto Exit; 74*37da2899SCharles.Forsyth } 75*37da2899SCharles.Forsyth 76*37da2899SCharles.Forsyth /* check face index */ 77*37da2899SCharles.Forsyth { 78*37da2899SCharles.Forsyth FT_UInt num_faces; 79*37da2899SCharles.Forsyth 80*37da2899SCharles.Forsyth 81*37da2899SCharles.Forsyth error = pfr_log_font_count( stream, 82*37da2899SCharles.Forsyth face->header.log_dir_offset, 83*37da2899SCharles.Forsyth &num_faces ); 84*37da2899SCharles.Forsyth if ( error ) 85*37da2899SCharles.Forsyth goto Exit; 86*37da2899SCharles.Forsyth 87*37da2899SCharles.Forsyth face->root.num_faces = num_faces; 88*37da2899SCharles.Forsyth } 89*37da2899SCharles.Forsyth 90*37da2899SCharles.Forsyth if ( face_index < 0 ) 91*37da2899SCharles.Forsyth goto Exit; 92*37da2899SCharles.Forsyth 93*37da2899SCharles.Forsyth if ( face_index >= face->root.num_faces ) 94*37da2899SCharles.Forsyth { 95*37da2899SCharles.Forsyth FT_ERROR(( "pfr_face_init: invalid face index\n" )); 96*37da2899SCharles.Forsyth error = PFR_Err_Invalid_Argument; 97*37da2899SCharles.Forsyth goto Exit; 98*37da2899SCharles.Forsyth } 99*37da2899SCharles.Forsyth 100*37da2899SCharles.Forsyth /* load the face */ 101*37da2899SCharles.Forsyth error = pfr_log_font_load( 102*37da2899SCharles.Forsyth &face->log_font, stream, face_index, 103*37da2899SCharles.Forsyth face->header.log_dir_offset, 104*37da2899SCharles.Forsyth FT_BOOL( face->header.phy_font_max_size_high != 0 ) ); 105*37da2899SCharles.Forsyth if ( error ) 106*37da2899SCharles.Forsyth goto Exit; 107*37da2899SCharles.Forsyth 108*37da2899SCharles.Forsyth /* now load the physical font descriptor */ 109*37da2899SCharles.Forsyth error = pfr_phy_font_load( &face->phy_font, stream, 110*37da2899SCharles.Forsyth face->log_font.phys_offset, 111*37da2899SCharles.Forsyth face->log_font.phys_size ); 112*37da2899SCharles.Forsyth if ( error ) 113*37da2899SCharles.Forsyth goto Exit; 114*37da2899SCharles.Forsyth 115*37da2899SCharles.Forsyth /* now, set-up all root face fields */ 116*37da2899SCharles.Forsyth { 117*37da2899SCharles.Forsyth FT_Face root = FT_FACE( face ); 118*37da2899SCharles.Forsyth PFR_PhyFont phy_font = &face->phy_font; 119*37da2899SCharles.Forsyth 120*37da2899SCharles.Forsyth 121*37da2899SCharles.Forsyth root->face_index = face_index; 122*37da2899SCharles.Forsyth root->num_glyphs = phy_font->num_chars; 123*37da2899SCharles.Forsyth root->face_flags = FT_FACE_FLAG_SCALABLE; 124*37da2899SCharles.Forsyth 125*37da2899SCharles.Forsyth if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 ) 126*37da2899SCharles.Forsyth root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 127*37da2899SCharles.Forsyth 128*37da2899SCharles.Forsyth if ( phy_font->flags & PFR_PHY_VERTICAL ) 129*37da2899SCharles.Forsyth root->face_flags |= FT_FACE_FLAG_VERTICAL; 130*37da2899SCharles.Forsyth else 131*37da2899SCharles.Forsyth root->face_flags |= FT_FACE_FLAG_HORIZONTAL; 132*37da2899SCharles.Forsyth 133*37da2899SCharles.Forsyth if ( phy_font->num_strikes > 0 ) 134*37da2899SCharles.Forsyth root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; 135*37da2899SCharles.Forsyth 136*37da2899SCharles.Forsyth if ( phy_font->num_kern_pairs > 0 ) 137*37da2899SCharles.Forsyth root->face_flags |= FT_FACE_FLAG_KERNING; 138*37da2899SCharles.Forsyth 139*37da2899SCharles.Forsyth root->family_name = phy_font->font_id; 140*37da2899SCharles.Forsyth root->style_name = NULL; /* no style name in font file */ 141*37da2899SCharles.Forsyth 142*37da2899SCharles.Forsyth root->num_fixed_sizes = 0; 143*37da2899SCharles.Forsyth root->available_sizes = 0; 144*37da2899SCharles.Forsyth 145*37da2899SCharles.Forsyth root->bbox = phy_font->bbox; 146*37da2899SCharles.Forsyth root->units_per_EM = (FT_UShort)phy_font->outline_resolution; 147*37da2899SCharles.Forsyth root->ascender = (FT_Short) phy_font->bbox.yMax; 148*37da2899SCharles.Forsyth root->descender = (FT_Short) phy_font->bbox.yMin; 149*37da2899SCharles.Forsyth root->height = (FT_Short) 150*37da2899SCharles.Forsyth ( ( ( root->ascender - root->descender ) * 12 ) 151*37da2899SCharles.Forsyth / 10 ); 152*37da2899SCharles.Forsyth 153*37da2899SCharles.Forsyth /* now compute maximum advance width */ 154*37da2899SCharles.Forsyth if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 ) 155*37da2899SCharles.Forsyth root->max_advance_width = (FT_Short)phy_font->standard_advance; 156*37da2899SCharles.Forsyth else 157*37da2899SCharles.Forsyth { 158*37da2899SCharles.Forsyth FT_Int max = 0; 159*37da2899SCharles.Forsyth FT_UInt count = phy_font->num_chars; 160*37da2899SCharles.Forsyth PFR_Char gchar = phy_font->chars; 161*37da2899SCharles.Forsyth 162*37da2899SCharles.Forsyth 163*37da2899SCharles.Forsyth for ( ; count > 0; count--, gchar++ ) 164*37da2899SCharles.Forsyth { 165*37da2899SCharles.Forsyth if ( max < gchar->advance ) 166*37da2899SCharles.Forsyth max = gchar->advance; 167*37da2899SCharles.Forsyth } 168*37da2899SCharles.Forsyth 169*37da2899SCharles.Forsyth root->max_advance_width = (FT_Short)max; 170*37da2899SCharles.Forsyth } 171*37da2899SCharles.Forsyth 172*37da2899SCharles.Forsyth root->max_advance_height = root->height; 173*37da2899SCharles.Forsyth 174*37da2899SCharles.Forsyth root->underline_position = (FT_Short)( - root->units_per_EM / 10 ); 175*37da2899SCharles.Forsyth root->underline_thickness = (FT_Short)( root->units_per_EM / 30 ); 176*37da2899SCharles.Forsyth 177*37da2899SCharles.Forsyth /* create charmap */ 178*37da2899SCharles.Forsyth { 179*37da2899SCharles.Forsyth FT_CharMapRec charmap; 180*37da2899SCharles.Forsyth 181*37da2899SCharles.Forsyth 182*37da2899SCharles.Forsyth charmap.face = root; 183*37da2899SCharles.Forsyth charmap.platform_id = 3; 184*37da2899SCharles.Forsyth charmap.encoding_id = 1; 185*37da2899SCharles.Forsyth charmap.encoding = FT_ENCODING_UNICODE; 186*37da2899SCharles.Forsyth 187*37da2899SCharles.Forsyth FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL ); 188*37da2899SCharles.Forsyth 189*37da2899SCharles.Forsyth #if 0 190*37da2899SCharles.Forsyth /* Select default charmap */ 191*37da2899SCharles.Forsyth if (root->num_charmaps) 192*37da2899SCharles.Forsyth root->charmap = root->charmaps[0]; 193*37da2899SCharles.Forsyth #endif 194*37da2899SCharles.Forsyth } 195*37da2899SCharles.Forsyth 196*37da2899SCharles.Forsyth /* check whether we've loaded any kerning pairs */ 197*37da2899SCharles.Forsyth if ( phy_font->num_kern_pairs ) 198*37da2899SCharles.Forsyth root->face_flags |= FT_FACE_FLAG_KERNING; 199*37da2899SCharles.Forsyth } 200*37da2899SCharles.Forsyth 201*37da2899SCharles.Forsyth Exit: 202*37da2899SCharles.Forsyth return error; 203*37da2899SCharles.Forsyth } 204*37da2899SCharles.Forsyth 205*37da2899SCharles.Forsyth 206*37da2899SCharles.Forsyth /*************************************************************************/ 207*37da2899SCharles.Forsyth /*************************************************************************/ 208*37da2899SCharles.Forsyth /***** *****/ 209*37da2899SCharles.Forsyth /***** SLOT OBJECT METHOD *****/ 210*37da2899SCharles.Forsyth /***** *****/ 211*37da2899SCharles.Forsyth /*************************************************************************/ 212*37da2899SCharles.Forsyth /*************************************************************************/ 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) pfr_slot_init(PFR_Slot slot)215*37da2899SCharles.Forsyth pfr_slot_init( PFR_Slot slot ) 216*37da2899SCharles.Forsyth { 217*37da2899SCharles.Forsyth FT_GlyphLoader loader = slot->root.internal->loader; 218*37da2899SCharles.Forsyth 219*37da2899SCharles.Forsyth pfr_glyph_init( &slot->glyph, loader ); 220*37da2899SCharles.Forsyth 221*37da2899SCharles.Forsyth return 0; 222*37da2899SCharles.Forsyth } 223*37da2899SCharles.Forsyth 224*37da2899SCharles.Forsyth 225*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) pfr_slot_done(PFR_Slot slot)226*37da2899SCharles.Forsyth pfr_slot_done( PFR_Slot slot ) 227*37da2899SCharles.Forsyth { 228*37da2899SCharles.Forsyth pfr_glyph_done( &slot->glyph ); 229*37da2899SCharles.Forsyth } 230*37da2899SCharles.Forsyth 231*37da2899SCharles.Forsyth 232*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) pfr_slot_load(PFR_Slot slot,PFR_Size size,FT_UInt gindex,FT_Int32 load_flags)233*37da2899SCharles.Forsyth pfr_slot_load( PFR_Slot slot, 234*37da2899SCharles.Forsyth PFR_Size size, 235*37da2899SCharles.Forsyth FT_UInt gindex, 236*37da2899SCharles.Forsyth FT_Int32 load_flags ) 237*37da2899SCharles.Forsyth { 238*37da2899SCharles.Forsyth FT_Error error; 239*37da2899SCharles.Forsyth PFR_Face face = (PFR_Face)slot->root.face; 240*37da2899SCharles.Forsyth PFR_Char gchar; 241*37da2899SCharles.Forsyth FT_Outline* outline = &slot->root.outline; 242*37da2899SCharles.Forsyth FT_ULong gps_offset; 243*37da2899SCharles.Forsyth 244*37da2899SCharles.Forsyth if (gindex > 0) 245*37da2899SCharles.Forsyth gindex--; 246*37da2899SCharles.Forsyth 247*37da2899SCharles.Forsyth /* check that the glyph index is correct */ 248*37da2899SCharles.Forsyth FT_ASSERT( gindex < face->phy_font.num_chars ); 249*37da2899SCharles.Forsyth 250*37da2899SCharles.Forsyth /* try to load an embedded bitmap */ 251*37da2899SCharles.Forsyth if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 ) 252*37da2899SCharles.Forsyth { 253*37da2899SCharles.Forsyth error = pfr_slot_load_bitmap( slot, size, gindex ); 254*37da2899SCharles.Forsyth if ( error == 0 ) 255*37da2899SCharles.Forsyth goto Exit; 256*37da2899SCharles.Forsyth } 257*37da2899SCharles.Forsyth 258*37da2899SCharles.Forsyth gchar = face->phy_font.chars + gindex; 259*37da2899SCharles.Forsyth slot->root.format = FT_GLYPH_FORMAT_OUTLINE; 260*37da2899SCharles.Forsyth outline->n_points = 0; 261*37da2899SCharles.Forsyth outline->n_contours = 0; 262*37da2899SCharles.Forsyth gps_offset = face->header.gps_section_offset; 263*37da2899SCharles.Forsyth 264*37da2899SCharles.Forsyth /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */ 265*37da2899SCharles.Forsyth error = pfr_glyph_load( &slot->glyph, face->root.stream, 266*37da2899SCharles.Forsyth gps_offset, gchar->gps_offset, gchar->gps_size ); 267*37da2899SCharles.Forsyth 268*37da2899SCharles.Forsyth if ( !error ) 269*37da2899SCharles.Forsyth { 270*37da2899SCharles.Forsyth FT_BBox cbox; 271*37da2899SCharles.Forsyth FT_Glyph_Metrics* metrics = &slot->root.metrics; 272*37da2899SCharles.Forsyth FT_Pos advance; 273*37da2899SCharles.Forsyth FT_Int em_metrics, em_outline; 274*37da2899SCharles.Forsyth FT_Bool scaling; 275*37da2899SCharles.Forsyth 276*37da2899SCharles.Forsyth 277*37da2899SCharles.Forsyth scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); 278*37da2899SCharles.Forsyth 279*37da2899SCharles.Forsyth /* copy outline data */ 280*37da2899SCharles.Forsyth *outline = slot->glyph.loader->base.outline; 281*37da2899SCharles.Forsyth 282*37da2899SCharles.Forsyth outline->flags &= ~FT_OUTLINE_OWNER; 283*37da2899SCharles.Forsyth outline->flags |= FT_OUTLINE_REVERSE_FILL; 284*37da2899SCharles.Forsyth 285*37da2899SCharles.Forsyth if ( size && size->root.metrics.y_ppem < 24 ) 286*37da2899SCharles.Forsyth outline->flags |= FT_OUTLINE_HIGH_PRECISION; 287*37da2899SCharles.Forsyth 288*37da2899SCharles.Forsyth /* compute the advance vector */ 289*37da2899SCharles.Forsyth metrics->horiAdvance = 0; 290*37da2899SCharles.Forsyth metrics->vertAdvance = 0; 291*37da2899SCharles.Forsyth 292*37da2899SCharles.Forsyth advance = gchar->advance; 293*37da2899SCharles.Forsyth em_metrics = face->phy_font.metrics_resolution; 294*37da2899SCharles.Forsyth em_outline = face->phy_font.outline_resolution; 295*37da2899SCharles.Forsyth 296*37da2899SCharles.Forsyth if ( em_metrics != em_outline ) 297*37da2899SCharles.Forsyth advance = FT_MulDiv( advance, em_outline, em_metrics ); 298*37da2899SCharles.Forsyth 299*37da2899SCharles.Forsyth if ( face->phy_font.flags & PFR_PHY_VERTICAL ) 300*37da2899SCharles.Forsyth metrics->vertAdvance = advance; 301*37da2899SCharles.Forsyth else 302*37da2899SCharles.Forsyth metrics->horiAdvance = advance; 303*37da2899SCharles.Forsyth 304*37da2899SCharles.Forsyth slot->root.linearHoriAdvance = metrics->horiAdvance; 305*37da2899SCharles.Forsyth slot->root.linearVertAdvance = metrics->vertAdvance; 306*37da2899SCharles.Forsyth 307*37da2899SCharles.Forsyth /* make-up vertical metrics(?) */ 308*37da2899SCharles.Forsyth metrics->vertBearingX = 0; 309*37da2899SCharles.Forsyth metrics->vertBearingY = 0; 310*37da2899SCharles.Forsyth 311*37da2899SCharles.Forsyth /* scale when needed */ 312*37da2899SCharles.Forsyth if ( scaling ) 313*37da2899SCharles.Forsyth { 314*37da2899SCharles.Forsyth FT_Int n; 315*37da2899SCharles.Forsyth FT_Fixed x_scale = size->root.metrics.x_scale; 316*37da2899SCharles.Forsyth FT_Fixed y_scale = size->root.metrics.y_scale; 317*37da2899SCharles.Forsyth FT_Vector* vec = outline->points; 318*37da2899SCharles.Forsyth 319*37da2899SCharles.Forsyth 320*37da2899SCharles.Forsyth /* scale outline points */ 321*37da2899SCharles.Forsyth for ( n = 0; n < outline->n_points; n++, vec++ ) 322*37da2899SCharles.Forsyth { 323*37da2899SCharles.Forsyth vec->x = FT_MulFix( vec->x, x_scale ); 324*37da2899SCharles.Forsyth vec->y = FT_MulFix( vec->y, y_scale ); 325*37da2899SCharles.Forsyth } 326*37da2899SCharles.Forsyth 327*37da2899SCharles.Forsyth /* scale the advance */ 328*37da2899SCharles.Forsyth metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 329*37da2899SCharles.Forsyth metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 330*37da2899SCharles.Forsyth } 331*37da2899SCharles.Forsyth 332*37da2899SCharles.Forsyth /* compute the rest of the metrics */ 333*37da2899SCharles.Forsyth FT_Outline_Get_CBox( outline, &cbox ); 334*37da2899SCharles.Forsyth 335*37da2899SCharles.Forsyth metrics->width = cbox.xMax - cbox.xMin; 336*37da2899SCharles.Forsyth metrics->height = cbox.yMax - cbox.yMin; 337*37da2899SCharles.Forsyth metrics->horiBearingX = cbox.xMin; 338*37da2899SCharles.Forsyth metrics->horiBearingY = cbox.yMax - metrics->height; 339*37da2899SCharles.Forsyth } 340*37da2899SCharles.Forsyth 341*37da2899SCharles.Forsyth Exit: 342*37da2899SCharles.Forsyth return error; 343*37da2899SCharles.Forsyth } 344*37da2899SCharles.Forsyth 345*37da2899SCharles.Forsyth 346*37da2899SCharles.Forsyth /*************************************************************************/ 347*37da2899SCharles.Forsyth /*************************************************************************/ 348*37da2899SCharles.Forsyth /***** *****/ 349*37da2899SCharles.Forsyth /***** KERNING METHOD *****/ 350*37da2899SCharles.Forsyth /***** *****/ 351*37da2899SCharles.Forsyth /*************************************************************************/ 352*37da2899SCharles.Forsyth /*************************************************************************/ 353*37da2899SCharles.Forsyth 354*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) pfr_face_get_kerning(PFR_Face face,FT_UInt glyph1,FT_UInt glyph2,FT_Vector * kerning)355*37da2899SCharles.Forsyth pfr_face_get_kerning( PFR_Face face, 356*37da2899SCharles.Forsyth FT_UInt glyph1, 357*37da2899SCharles.Forsyth FT_UInt glyph2, 358*37da2899SCharles.Forsyth FT_Vector* kerning ) 359*37da2899SCharles.Forsyth { 360*37da2899SCharles.Forsyth FT_Error error; 361*37da2899SCharles.Forsyth PFR_PhyFont phy_font = &face->phy_font; 362*37da2899SCharles.Forsyth PFR_KernItem item = phy_font->kern_items; 363*37da2899SCharles.Forsyth FT_UInt32 idx = PFR_KERN_INDEX( glyph1, glyph2 ); 364*37da2899SCharles.Forsyth 365*37da2899SCharles.Forsyth 366*37da2899SCharles.Forsyth kerning->x = 0; 367*37da2899SCharles.Forsyth kerning->y = 0; 368*37da2899SCharles.Forsyth 369*37da2899SCharles.Forsyth /* find the kerning item containing our pair */ 370*37da2899SCharles.Forsyth while ( item ) 371*37da2899SCharles.Forsyth { 372*37da2899SCharles.Forsyth if ( item->pair1 <= idx && idx <= item->pair2 ) 373*37da2899SCharles.Forsyth goto Found_Item; 374*37da2899SCharles.Forsyth 375*37da2899SCharles.Forsyth item = item->next; 376*37da2899SCharles.Forsyth } 377*37da2899SCharles.Forsyth 378*37da2899SCharles.Forsyth /* not found */ 379*37da2899SCharles.Forsyth goto Exit; 380*37da2899SCharles.Forsyth 381*37da2899SCharles.Forsyth Found_Item: 382*37da2899SCharles.Forsyth { 383*37da2899SCharles.Forsyth /* perform simply binary search within the item */ 384*37da2899SCharles.Forsyth FT_UInt min, mid, max; 385*37da2899SCharles.Forsyth FT_Stream stream = face->root.stream; 386*37da2899SCharles.Forsyth FT_Byte* p; 387*37da2899SCharles.Forsyth 388*37da2899SCharles.Forsyth 389*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( item->offset ) || 390*37da2899SCharles.Forsyth FT_FRAME_ENTER( item->pair_count * item->pair_size ) ) 391*37da2899SCharles.Forsyth goto Exit; 392*37da2899SCharles.Forsyth 393*37da2899SCharles.Forsyth min = 0; 394*37da2899SCharles.Forsyth max = item->pair_count; 395*37da2899SCharles.Forsyth while ( min < max ) 396*37da2899SCharles.Forsyth { 397*37da2899SCharles.Forsyth FT_UInt char1, char2, charcode; 398*37da2899SCharles.Forsyth 399*37da2899SCharles.Forsyth 400*37da2899SCharles.Forsyth mid = ( min + max ) >> 1; 401*37da2899SCharles.Forsyth p = stream->cursor + mid*item->pair_size; 402*37da2899SCharles.Forsyth 403*37da2899SCharles.Forsyth if ( item->flags & PFR_KERN_2BYTE_CHAR ) 404*37da2899SCharles.Forsyth { 405*37da2899SCharles.Forsyth char1 = FT_NEXT_USHORT( p ); 406*37da2899SCharles.Forsyth char2 = FT_NEXT_USHORT( p ); 407*37da2899SCharles.Forsyth } 408*37da2899SCharles.Forsyth else 409*37da2899SCharles.Forsyth { 410*37da2899SCharles.Forsyth char1 = FT_NEXT_USHORT( p ); 411*37da2899SCharles.Forsyth char2 = FT_NEXT_USHORT( p ); 412*37da2899SCharles.Forsyth } 413*37da2899SCharles.Forsyth charcode = PFR_KERN_INDEX( char1, char2 ); 414*37da2899SCharles.Forsyth 415*37da2899SCharles.Forsyth if ( idx == charcode ) 416*37da2899SCharles.Forsyth { 417*37da2899SCharles.Forsyth if ( item->flags & PFR_KERN_2BYTE_ADJ ) 418*37da2899SCharles.Forsyth kerning->x = item->base_adj + FT_NEXT_SHORT( p ); 419*37da2899SCharles.Forsyth else 420*37da2899SCharles.Forsyth kerning->x = item->base_adj + FT_NEXT_CHAR( p ); 421*37da2899SCharles.Forsyth 422*37da2899SCharles.Forsyth break; 423*37da2899SCharles.Forsyth } 424*37da2899SCharles.Forsyth if ( idx > charcode ) 425*37da2899SCharles.Forsyth min = mid + 1; 426*37da2899SCharles.Forsyth else 427*37da2899SCharles.Forsyth max = mid; 428*37da2899SCharles.Forsyth } 429*37da2899SCharles.Forsyth 430*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 431*37da2899SCharles.Forsyth } 432*37da2899SCharles.Forsyth 433*37da2899SCharles.Forsyth Exit: 434*37da2899SCharles.Forsyth return 0; 435*37da2899SCharles.Forsyth } 436*37da2899SCharles.Forsyth 437*37da2899SCharles.Forsyth /* END */ 438