1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ftgloadr.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* The FreeType glyph loader (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 <ft2build.h> 20*37da2899SCharles.Forsyth #include FT_INTERNAL_GLYPH_LOADER_H 21*37da2899SCharles.Forsyth #include FT_INTERNAL_MEMORY_H 22*37da2899SCharles.Forsyth 23*37da2899SCharles.Forsyth #undef FT_COMPONENT 24*37da2899SCharles.Forsyth #define FT_COMPONENT trace_gloader 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsyth 27*37da2899SCharles.Forsyth /*************************************************************************/ 28*37da2899SCharles.Forsyth /*************************************************************************/ 29*37da2899SCharles.Forsyth /*************************************************************************/ 30*37da2899SCharles.Forsyth /***** *****/ 31*37da2899SCharles.Forsyth /***** *****/ 32*37da2899SCharles.Forsyth /***** G L Y P H L O A D E R *****/ 33*37da2899SCharles.Forsyth /***** *****/ 34*37da2899SCharles.Forsyth /***** *****/ 35*37da2899SCharles.Forsyth /*************************************************************************/ 36*37da2899SCharles.Forsyth /*************************************************************************/ 37*37da2899SCharles.Forsyth /*************************************************************************/ 38*37da2899SCharles.Forsyth 39*37da2899SCharles.Forsyth /*************************************************************************/ 40*37da2899SCharles.Forsyth /* */ 41*37da2899SCharles.Forsyth /* The glyph loader is a simple object which is used to load a set of */ 42*37da2899SCharles.Forsyth /* glyphs easily. It is critical for the correct loading of composites. */ 43*37da2899SCharles.Forsyth /* */ 44*37da2899SCharles.Forsyth /* Ideally, one can see it as a stack of abstract `glyph' objects. */ 45*37da2899SCharles.Forsyth /* */ 46*37da2899SCharles.Forsyth /* loader.base Is really the bottom of the stack. It describes a */ 47*37da2899SCharles.Forsyth /* single glyph image made of the juxtaposition of */ 48*37da2899SCharles.Forsyth /* several glyphs (those `in the stack'). */ 49*37da2899SCharles.Forsyth /* */ 50*37da2899SCharles.Forsyth /* loader.current Describes the top of the stack, on which a new */ 51*37da2899SCharles.Forsyth /* glyph can be loaded. */ 52*37da2899SCharles.Forsyth /* */ 53*37da2899SCharles.Forsyth /* Rewind Clears the stack. */ 54*37da2899SCharles.Forsyth /* Prepare Set up `loader.current' for addition of a new glyph */ 55*37da2899SCharles.Forsyth /* image. */ 56*37da2899SCharles.Forsyth /* Add Add the `current' glyph image to the `base' one, */ 57*37da2899SCharles.Forsyth /* and prepare for another one. */ 58*37da2899SCharles.Forsyth /* */ 59*37da2899SCharles.Forsyth /* The glyph loader is now a base object. Each driver used to */ 60*37da2899SCharles.Forsyth /* re-implement it in one way or the other, which wasted code and */ 61*37da2899SCharles.Forsyth /* energy. */ 62*37da2899SCharles.Forsyth /* */ 63*37da2899SCharles.Forsyth /*************************************************************************/ 64*37da2899SCharles.Forsyth 65*37da2899SCharles.Forsyth 66*37da2899SCharles.Forsyth /* create a new glyph loader */ 67*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Error ) FT_GlyphLoader_New(FT_Memory memory,FT_GlyphLoader * aloader)68*37da2899SCharles.Forsyth FT_GlyphLoader_New( FT_Memory memory, 69*37da2899SCharles.Forsyth FT_GlyphLoader *aloader ) 70*37da2899SCharles.Forsyth { 71*37da2899SCharles.Forsyth FT_GlyphLoader loader; 72*37da2899SCharles.Forsyth FT_Error error; 73*37da2899SCharles.Forsyth 74*37da2899SCharles.Forsyth 75*37da2899SCharles.Forsyth if ( !FT_NEW( loader ) ) 76*37da2899SCharles.Forsyth { 77*37da2899SCharles.Forsyth loader->memory = memory; 78*37da2899SCharles.Forsyth *aloader = loader; 79*37da2899SCharles.Forsyth } 80*37da2899SCharles.Forsyth return error; 81*37da2899SCharles.Forsyth } 82*37da2899SCharles.Forsyth 83*37da2899SCharles.Forsyth 84*37da2899SCharles.Forsyth /* rewind the glyph loader - reset counters to 0 */ 85*37da2899SCharles.Forsyth FT_BASE_DEF( void ) FT_GlyphLoader_Rewind(FT_GlyphLoader loader)86*37da2899SCharles.Forsyth FT_GlyphLoader_Rewind( FT_GlyphLoader loader ) 87*37da2899SCharles.Forsyth { 88*37da2899SCharles.Forsyth FT_GlyphLoad base = &loader->base; 89*37da2899SCharles.Forsyth FT_GlyphLoad current = &loader->current; 90*37da2899SCharles.Forsyth 91*37da2899SCharles.Forsyth 92*37da2899SCharles.Forsyth base->outline.n_points = 0; 93*37da2899SCharles.Forsyth base->outline.n_contours = 0; 94*37da2899SCharles.Forsyth base->num_subglyphs = 0; 95*37da2899SCharles.Forsyth 96*37da2899SCharles.Forsyth *current = *base; 97*37da2899SCharles.Forsyth } 98*37da2899SCharles.Forsyth 99*37da2899SCharles.Forsyth 100*37da2899SCharles.Forsyth /* reset the glyph loader, frees all allocated tables */ 101*37da2899SCharles.Forsyth /* and starts from zero */ 102*37da2899SCharles.Forsyth FT_BASE_DEF( void ) FT_GlyphLoader_Reset(FT_GlyphLoader loader)103*37da2899SCharles.Forsyth FT_GlyphLoader_Reset( FT_GlyphLoader loader ) 104*37da2899SCharles.Forsyth { 105*37da2899SCharles.Forsyth FT_Memory memory = loader->memory; 106*37da2899SCharles.Forsyth 107*37da2899SCharles.Forsyth 108*37da2899SCharles.Forsyth FT_FREE( loader->base.outline.points ); 109*37da2899SCharles.Forsyth FT_FREE( loader->base.outline.tags ); 110*37da2899SCharles.Forsyth FT_FREE( loader->base.outline.contours ); 111*37da2899SCharles.Forsyth FT_FREE( loader->base.extra_points ); 112*37da2899SCharles.Forsyth FT_FREE( loader->base.subglyphs ); 113*37da2899SCharles.Forsyth 114*37da2899SCharles.Forsyth loader->max_points = 0; 115*37da2899SCharles.Forsyth loader->max_contours = 0; 116*37da2899SCharles.Forsyth loader->max_subglyphs = 0; 117*37da2899SCharles.Forsyth 118*37da2899SCharles.Forsyth FT_GlyphLoader_Rewind( loader ); 119*37da2899SCharles.Forsyth } 120*37da2899SCharles.Forsyth 121*37da2899SCharles.Forsyth 122*37da2899SCharles.Forsyth /* delete a glyph loader */ 123*37da2899SCharles.Forsyth FT_BASE_DEF( void ) FT_GlyphLoader_Done(FT_GlyphLoader loader)124*37da2899SCharles.Forsyth FT_GlyphLoader_Done( FT_GlyphLoader loader ) 125*37da2899SCharles.Forsyth { 126*37da2899SCharles.Forsyth if ( loader ) 127*37da2899SCharles.Forsyth { 128*37da2899SCharles.Forsyth FT_Memory memory = loader->memory; 129*37da2899SCharles.Forsyth 130*37da2899SCharles.Forsyth 131*37da2899SCharles.Forsyth FT_GlyphLoader_Reset( loader ); 132*37da2899SCharles.Forsyth FT_FREE( loader ); 133*37da2899SCharles.Forsyth } 134*37da2899SCharles.Forsyth } 135*37da2899SCharles.Forsyth 136*37da2899SCharles.Forsyth 137*37da2899SCharles.Forsyth /* re-adjust the `current' outline fields */ 138*37da2899SCharles.Forsyth static void FT_GlyphLoader_Adjust_Points(FT_GlyphLoader loader)139*37da2899SCharles.Forsyth FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader ) 140*37da2899SCharles.Forsyth { 141*37da2899SCharles.Forsyth FT_Outline* base = &loader->base.outline; 142*37da2899SCharles.Forsyth FT_Outline* current = &loader->current.outline; 143*37da2899SCharles.Forsyth 144*37da2899SCharles.Forsyth 145*37da2899SCharles.Forsyth current->points = base->points + base->n_points; 146*37da2899SCharles.Forsyth current->tags = base->tags + base->n_points; 147*37da2899SCharles.Forsyth current->contours = base->contours + base->n_contours; 148*37da2899SCharles.Forsyth 149*37da2899SCharles.Forsyth /* handle extra points table - if any */ 150*37da2899SCharles.Forsyth if ( loader->use_extra ) 151*37da2899SCharles.Forsyth loader->current.extra_points = 152*37da2899SCharles.Forsyth loader->base.extra_points + base->n_points; 153*37da2899SCharles.Forsyth } 154*37da2899SCharles.Forsyth 155*37da2899SCharles.Forsyth 156*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Error ) FT_GlyphLoader_CreateExtra(FT_GlyphLoader loader)157*37da2899SCharles.Forsyth FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader ) 158*37da2899SCharles.Forsyth { 159*37da2899SCharles.Forsyth FT_Error error; 160*37da2899SCharles.Forsyth FT_Memory memory = loader->memory; 161*37da2899SCharles.Forsyth 162*37da2899SCharles.Forsyth 163*37da2899SCharles.Forsyth if ( !FT_NEW_ARRAY( loader->base.extra_points, loader->max_points ) ) 164*37da2899SCharles.Forsyth { 165*37da2899SCharles.Forsyth loader->use_extra = 1; 166*37da2899SCharles.Forsyth FT_GlyphLoader_Adjust_Points( loader ); 167*37da2899SCharles.Forsyth } 168*37da2899SCharles.Forsyth return error; 169*37da2899SCharles.Forsyth } 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth 172*37da2899SCharles.Forsyth /* re-adjust the `current' subglyphs field */ 173*37da2899SCharles.Forsyth static void FT_GlyphLoader_Adjust_Subglyphs(FT_GlyphLoader loader)174*37da2899SCharles.Forsyth FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader ) 175*37da2899SCharles.Forsyth { 176*37da2899SCharles.Forsyth FT_GlyphLoad base = &loader->base; 177*37da2899SCharles.Forsyth FT_GlyphLoad current = &loader->current; 178*37da2899SCharles.Forsyth 179*37da2899SCharles.Forsyth 180*37da2899SCharles.Forsyth current->subglyphs = base->subglyphs + base->num_subglyphs; 181*37da2899SCharles.Forsyth } 182*37da2899SCharles.Forsyth 183*37da2899SCharles.Forsyth 184*37da2899SCharles.Forsyth /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */ 185*37da2899SCharles.Forsyth /* function reallocates its outline tables if necessary. Note that it */ 186*37da2899SCharles.Forsyth /* DOESN'T change the number of points within the loader! */ 187*37da2899SCharles.Forsyth /* */ 188*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Error ) FT_GlyphLoader_CheckPoints(FT_GlyphLoader loader,FT_UInt n_points,FT_UInt n_contours)189*37da2899SCharles.Forsyth FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader, 190*37da2899SCharles.Forsyth FT_UInt n_points, 191*37da2899SCharles.Forsyth FT_UInt n_contours ) 192*37da2899SCharles.Forsyth { 193*37da2899SCharles.Forsyth FT_Memory memory = loader->memory; 194*37da2899SCharles.Forsyth FT_Error error = FT_Err_Ok; 195*37da2899SCharles.Forsyth FT_Outline* base = &loader->base.outline; 196*37da2899SCharles.Forsyth FT_Outline* current = &loader->current.outline; 197*37da2899SCharles.Forsyth FT_Bool adjust = 1; 198*37da2899SCharles.Forsyth 199*37da2899SCharles.Forsyth FT_UInt new_max, old_max; 200*37da2899SCharles.Forsyth 201*37da2899SCharles.Forsyth 202*37da2899SCharles.Forsyth /* check points & tags */ 203*37da2899SCharles.Forsyth new_max = base->n_points + current->n_points + n_points; 204*37da2899SCharles.Forsyth old_max = loader->max_points; 205*37da2899SCharles.Forsyth 206*37da2899SCharles.Forsyth if ( new_max > old_max ) 207*37da2899SCharles.Forsyth { 208*37da2899SCharles.Forsyth new_max = ( new_max + 7 ) & -8; 209*37da2899SCharles.Forsyth 210*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) || 211*37da2899SCharles.Forsyth FT_RENEW_ARRAY( base->tags, old_max, new_max ) ) 212*37da2899SCharles.Forsyth goto Exit; 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth if ( loader->use_extra && 215*37da2899SCharles.Forsyth FT_RENEW_ARRAY( loader->base.extra_points, old_max, new_max ) ) 216*37da2899SCharles.Forsyth goto Exit; 217*37da2899SCharles.Forsyth 218*37da2899SCharles.Forsyth adjust = 1; 219*37da2899SCharles.Forsyth loader->max_points = new_max; 220*37da2899SCharles.Forsyth } 221*37da2899SCharles.Forsyth 222*37da2899SCharles.Forsyth /* check contours */ 223*37da2899SCharles.Forsyth old_max = loader->max_contours; 224*37da2899SCharles.Forsyth new_max = base->n_contours + current->n_contours + 225*37da2899SCharles.Forsyth n_contours; 226*37da2899SCharles.Forsyth if ( new_max > old_max ) 227*37da2899SCharles.Forsyth { 228*37da2899SCharles.Forsyth new_max = ( new_max + 3 ) & -4; 229*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) ) 230*37da2899SCharles.Forsyth goto Exit; 231*37da2899SCharles.Forsyth 232*37da2899SCharles.Forsyth adjust = 1; 233*37da2899SCharles.Forsyth loader->max_contours = new_max; 234*37da2899SCharles.Forsyth } 235*37da2899SCharles.Forsyth 236*37da2899SCharles.Forsyth if ( adjust ) 237*37da2899SCharles.Forsyth FT_GlyphLoader_Adjust_Points( loader ); 238*37da2899SCharles.Forsyth 239*37da2899SCharles.Forsyth Exit: 240*37da2899SCharles.Forsyth return error; 241*37da2899SCharles.Forsyth } 242*37da2899SCharles.Forsyth 243*37da2899SCharles.Forsyth 244*37da2899SCharles.Forsyth /* Ensure that we can add `n_subglyphs' to our glyph. this function */ 245*37da2899SCharles.Forsyth /* reallocates its subglyphs table if necessary. Note that it DOES */ 246*37da2899SCharles.Forsyth /* NOT change the number of subglyphs within the loader! */ 247*37da2899SCharles.Forsyth /* */ 248*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Error ) FT_GlyphLoader_CheckSubGlyphs(FT_GlyphLoader loader,FT_UInt n_subs)249*37da2899SCharles.Forsyth FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader, 250*37da2899SCharles.Forsyth FT_UInt n_subs ) 251*37da2899SCharles.Forsyth { 252*37da2899SCharles.Forsyth FT_Memory memory = loader->memory; 253*37da2899SCharles.Forsyth FT_Error error = FT_Err_Ok; 254*37da2899SCharles.Forsyth FT_UInt new_max, old_max; 255*37da2899SCharles.Forsyth 256*37da2899SCharles.Forsyth FT_GlyphLoad base = &loader->base; 257*37da2899SCharles.Forsyth FT_GlyphLoad current = &loader->current; 258*37da2899SCharles.Forsyth 259*37da2899SCharles.Forsyth 260*37da2899SCharles.Forsyth new_max = base->num_subglyphs + current->num_subglyphs + n_subs; 261*37da2899SCharles.Forsyth old_max = loader->max_subglyphs; 262*37da2899SCharles.Forsyth if ( new_max > old_max ) 263*37da2899SCharles.Forsyth { 264*37da2899SCharles.Forsyth new_max = ( new_max + 1 ) & -2; 265*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) ) 266*37da2899SCharles.Forsyth goto Exit; 267*37da2899SCharles.Forsyth 268*37da2899SCharles.Forsyth loader->max_subglyphs = new_max; 269*37da2899SCharles.Forsyth 270*37da2899SCharles.Forsyth FT_GlyphLoader_Adjust_Subglyphs( loader ); 271*37da2899SCharles.Forsyth } 272*37da2899SCharles.Forsyth 273*37da2899SCharles.Forsyth Exit: 274*37da2899SCharles.Forsyth return error; 275*37da2899SCharles.Forsyth } 276*37da2899SCharles.Forsyth 277*37da2899SCharles.Forsyth 278*37da2899SCharles.Forsyth /* prepare loader for the addition of a new glyph on top of the base one */ 279*37da2899SCharles.Forsyth FT_BASE_DEF( void ) FT_GlyphLoader_Prepare(FT_GlyphLoader loader)280*37da2899SCharles.Forsyth FT_GlyphLoader_Prepare( FT_GlyphLoader loader ) 281*37da2899SCharles.Forsyth { 282*37da2899SCharles.Forsyth FT_GlyphLoad current = &loader->current; 283*37da2899SCharles.Forsyth 284*37da2899SCharles.Forsyth 285*37da2899SCharles.Forsyth current->outline.n_points = 0; 286*37da2899SCharles.Forsyth current->outline.n_contours = 0; 287*37da2899SCharles.Forsyth current->num_subglyphs = 0; 288*37da2899SCharles.Forsyth 289*37da2899SCharles.Forsyth FT_GlyphLoader_Adjust_Points ( loader ); 290*37da2899SCharles.Forsyth FT_GlyphLoader_Adjust_Subglyphs( loader ); 291*37da2899SCharles.Forsyth } 292*37da2899SCharles.Forsyth 293*37da2899SCharles.Forsyth 294*37da2899SCharles.Forsyth /* add current glyph to the base image - and prepare for another */ 295*37da2899SCharles.Forsyth FT_BASE_DEF( void ) FT_GlyphLoader_Add(FT_GlyphLoader loader)296*37da2899SCharles.Forsyth FT_GlyphLoader_Add( FT_GlyphLoader loader ) 297*37da2899SCharles.Forsyth { 298*37da2899SCharles.Forsyth FT_GlyphLoad base = &loader->base; 299*37da2899SCharles.Forsyth FT_GlyphLoad current = &loader->current; 300*37da2899SCharles.Forsyth 301*37da2899SCharles.Forsyth FT_UInt n_curr_contours = current->outline.n_contours; 302*37da2899SCharles.Forsyth FT_UInt n_base_points = base->outline.n_points; 303*37da2899SCharles.Forsyth FT_UInt n; 304*37da2899SCharles.Forsyth 305*37da2899SCharles.Forsyth 306*37da2899SCharles.Forsyth base->outline.n_points = 307*37da2899SCharles.Forsyth (short)( base->outline.n_points + current->outline.n_points ); 308*37da2899SCharles.Forsyth base->outline.n_contours = 309*37da2899SCharles.Forsyth (short)( base->outline.n_contours + current->outline.n_contours ); 310*37da2899SCharles.Forsyth 311*37da2899SCharles.Forsyth base->num_subglyphs += current->num_subglyphs; 312*37da2899SCharles.Forsyth 313*37da2899SCharles.Forsyth /* adjust contours count in newest outline */ 314*37da2899SCharles.Forsyth for ( n = 0; n < n_curr_contours; n++ ) 315*37da2899SCharles.Forsyth current->outline.contours[n] = 316*37da2899SCharles.Forsyth (short)( current->outline.contours[n] + n_base_points ); 317*37da2899SCharles.Forsyth 318*37da2899SCharles.Forsyth /* prepare for another new glyph image */ 319*37da2899SCharles.Forsyth FT_GlyphLoader_Prepare( loader ); 320*37da2899SCharles.Forsyth } 321*37da2899SCharles.Forsyth 322*37da2899SCharles.Forsyth 323*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Error ) FT_GlyphLoader_CopyPoints(FT_GlyphLoader target,FT_GlyphLoader source)324*37da2899SCharles.Forsyth FT_GlyphLoader_CopyPoints( FT_GlyphLoader target, 325*37da2899SCharles.Forsyth FT_GlyphLoader source ) 326*37da2899SCharles.Forsyth { 327*37da2899SCharles.Forsyth FT_Error error; 328*37da2899SCharles.Forsyth FT_UInt num_points = source->base.outline.n_points; 329*37da2899SCharles.Forsyth FT_UInt num_contours = source->base.outline.n_contours; 330*37da2899SCharles.Forsyth 331*37da2899SCharles.Forsyth 332*37da2899SCharles.Forsyth error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours ); 333*37da2899SCharles.Forsyth if ( !error ) 334*37da2899SCharles.Forsyth { 335*37da2899SCharles.Forsyth FT_Outline* out = &target->base.outline; 336*37da2899SCharles.Forsyth FT_Outline* in = &source->base.outline; 337*37da2899SCharles.Forsyth 338*37da2899SCharles.Forsyth 339*37da2899SCharles.Forsyth FT_MEM_COPY( out->points, in->points, 340*37da2899SCharles.Forsyth num_points * sizeof ( FT_Vector ) ); 341*37da2899SCharles.Forsyth FT_MEM_COPY( out->tags, in->tags, 342*37da2899SCharles.Forsyth num_points * sizeof ( char ) ); 343*37da2899SCharles.Forsyth FT_MEM_COPY( out->contours, in->contours, 344*37da2899SCharles.Forsyth num_contours * sizeof ( short ) ); 345*37da2899SCharles.Forsyth 346*37da2899SCharles.Forsyth /* do we need to copy the extra points? */ 347*37da2899SCharles.Forsyth if ( target->use_extra && source->use_extra ) 348*37da2899SCharles.Forsyth FT_MEM_COPY( target->base.extra_points, source->base.extra_points, 349*37da2899SCharles.Forsyth num_points * sizeof ( FT_Vector ) ); 350*37da2899SCharles.Forsyth 351*37da2899SCharles.Forsyth out->n_points = (short)num_points; 352*37da2899SCharles.Forsyth out->n_contours = (short)num_contours; 353*37da2899SCharles.Forsyth 354*37da2899SCharles.Forsyth FT_GlyphLoader_Adjust_Points( target ); 355*37da2899SCharles.Forsyth } 356*37da2899SCharles.Forsyth 357*37da2899SCharles.Forsyth return error; 358*37da2899SCharles.Forsyth } 359*37da2899SCharles.Forsyth 360*37da2899SCharles.Forsyth 361*37da2899SCharles.Forsyth /* END */ 362