00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 #include <ft2build.h>
00021 #include FT_INTERNAL_DEBUG_H
00022 #include FT_INTERNAL_CALC_H
00023 #include FT_INTERNAL_STREAM_H
00024 #include FT_INTERNAL_SFNT_H
00025 #include FT_TRUETYPE_TAGS_H
00026 #include FT_OUTLINE_H
00027 
00028 #include "ttgload.h"
00029 #include "ttpload.h"
00030 
00031 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00032 #include "ttgxvar.h"
00033 #endif
00034 
00035 #include "tterrors.h"
00036 
00037 
00038   
00039   
00040   
00041   
00042   
00043   
00044 #undef  FT_COMPONENT
00045 #define FT_COMPONENT  trace_ttgload
00046 
00047 
00048   
00049   
00050   
00051   
00052 #define ARGS_ARE_WORDS             0x0001
00053 #define ARGS_ARE_XY_VALUES         0x0002
00054 #define ROUND_XY_TO_GRID           0x0004
00055 #define WE_HAVE_A_SCALE            0x0008
00056 
00057 #define MORE_COMPONENTS            0x0020
00058 #define WE_HAVE_AN_XY_SCALE        0x0040
00059 #define WE_HAVE_A_2X2              0x0080
00060 #define WE_HAVE_INSTR              0x0100
00061 #define USE_MY_METRICS             0x0200
00062 #define OVERLAP_COMPOUND           0x0400
00063 #define SCALED_COMPONENT_OFFSET    0x0800
00064 #define UNSCALED_COMPONENT_OFFSET  0x1000
00065 
00066 
00067   
00068   
00069   
00070   
00071   
00072   
00073   FT_LOCAL_DEF( void )
00074   TT_Get_HMetrics( TT_Face     face,
00075                    FT_UInt     idx,
00076                    FT_Bool     check,
00077                    FT_Short*   lsb,
00078                    FT_UShort*  aw )
00079   {
00080     ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
00081 
00082     if ( check && face->postscript.isFixedPitch )
00083       *aw = face->horizontal.advance_Width_Max;
00084 
00085     FT_TRACE5(( "  advance width (font units): %d\n", *aw ));
00086     FT_TRACE5(( "  left side bearing (font units): %d\n", *lsb ));
00087   }
00088 
00089 
00090   
00091   
00092   
00093   
00094   
00095   
00096   
00097   
00098   
00099   
00100   
00101   
00102   
00103   FT_LOCAL_DEF( void )
00104   TT_Get_VMetrics( TT_Face     face,
00105                    FT_UInt     idx,
00106                    FT_Bool     check,
00107                    FT_Short*   tsb,
00108                    FT_UShort*  ah )
00109   {
00110     FT_UNUSED( check );
00111 
00112     if ( face->vertical_info )
00113       ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
00114 
00115 #if 1             
00116 
00117     else
00118     {
00119       *tsb = 0;
00120       *ah  = face->root.units_per_EM;
00121     }
00122 
00123 #else      
00124 
00125     else if ( face->os2.version != 0xFFFFU )
00126     {
00127       *tsb = face->os2.sTypoAscender;
00128       *ah  = face->os2.sTypoAscender - face->os2.sTypoDescender;
00129     }
00130     else
00131     {
00132       *tsb = face->horizontal.Ascender;
00133       *ah  = face->horizontal.Ascender - face->horizontal.Descender;
00134     }
00135 
00136 #endif
00137 
00138     FT_TRACE5(( "  advance height (font units): %d\n", *ah ));
00139     FT_TRACE5(( "  top side bearing (font units): %d\n", *tsb ));
00140   }
00141 
00142 
00143   static void
00144   tt_get_metrics( TT_Loader  loader,
00145                   FT_UInt    glyph_index )
00146   {
00147     TT_Face  face = (TT_Face)loader->face;
00148 
00149     FT_Short   left_bearing = 0, top_bearing = 0;
00150     FT_UShort  advance_width = 0, advance_height = 0;
00151 
00152 
00153     TT_Get_HMetrics( face, glyph_index,
00154                      (FT_Bool)!( loader->load_flags &
00155                                  FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
00156                      &left_bearing,
00157                      &advance_width );
00158     TT_Get_VMetrics( face, glyph_index,
00159                      (FT_Bool)!( loader->load_flags &
00160                                  FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
00161                      &top_bearing,
00162                      &advance_height );
00163 
00164 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00165 
00166     
00167     
00168     if ( face->root.internal->incremental_interface                           &&
00169          face->root.internal->incremental_interface->funcs->get_glyph_metrics )
00170     {
00171       FT_Incremental_MetricsRec  metrics;
00172       FT_Error                   error;
00173 
00174 
00175       metrics.bearing_x = left_bearing;
00176       metrics.bearing_y = 0;
00177       metrics.advance   = advance_width;
00178       metrics.advance_v = 0;
00179 
00180       error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
00181                 face->root.internal->incremental_interface->object,
00182                 glyph_index, FALSE, &metrics );
00183       if ( error )
00184         goto Exit;
00185 
00186       left_bearing  = (FT_Short)metrics.bearing_x;
00187       advance_width = (FT_UShort)metrics.advance;
00188 
00189 #if 0
00190 
00191       
00192       metrics.bearing_x = 0;
00193       metrics.bearing_y = top_bearing;
00194       metrics.advance   = advance_height;
00195 
00196       error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
00197                 face->root.internal->incremental_interface->object,
00198                 glyph_index, TRUE, &metrics );
00199       if ( error )
00200         goto Exit;
00201 
00202       top_bearing    = (FT_Short)metrics.bearing_y;
00203       advance_height = (FT_UShort)metrics.advance;
00204 
00205 #endif 
00206 
00207     }
00208 
00209   Exit:
00210 
00211 #endif 
00212 
00213     loader->left_bearing = left_bearing;
00214     loader->advance      = advance_width;
00215     loader->top_bearing  = top_bearing;
00216     loader->vadvance     = advance_height;
00217 
00218     if ( !loader->linear_def )
00219     {
00220       loader->linear_def = 1;
00221       loader->linear     = advance_width;
00222     }
00223   }
00224 
00225 
00226   
00227   
00228   
00229   
00230   static void
00231   translate_array( FT_UInt     n,
00232                    FT_Vector*  coords,
00233                    FT_Pos      delta_x,
00234                    FT_Pos      delta_y )
00235   {
00236     FT_UInt  k;
00237 
00238 
00239     if ( delta_x )
00240       for ( k = 0; k < n; k++ )
00241         coords[k].x += delta_x;
00242 
00243     if ( delta_y )
00244       for ( k = 0; k < n; k++ )
00245         coords[k].y += delta_y;
00246   }
00247 
00248 
00249 #undef  IS_HINTED
00250 #define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
00251 
00252 
00253   
00254   
00255   
00256   
00257   
00258   
00259   
00260 
00261   FT_CALLBACK_DEF( FT_Error )
00262   TT_Access_Glyph_Frame( TT_Loader  loader,
00263                          FT_UInt    glyph_index,
00264                          FT_ULong   offset,
00265                          FT_UInt    byte_count )
00266   {
00267     FT_Error   error;
00268     FT_Stream  stream = loader->stream;
00269 
00270     
00271     FT_UNUSED( glyph_index );
00272 
00273 
00274     FT_TRACE5(( "Glyph %ld\n", glyph_index ));
00275 
00276     
00277     if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
00278       return error;
00279 
00280     loader->cursor = stream->cursor;
00281     loader->limit  = stream->limit;
00282 
00283     return TT_Err_Ok;
00284   }
00285 
00286 
00287   FT_CALLBACK_DEF( void )
00288   TT_Forget_Glyph_Frame( TT_Loader  loader )
00289   {
00290     FT_Stream  stream = loader->stream;
00291 
00292 
00293     FT_FRAME_EXIT();
00294   }
00295 
00296 
00297   FT_CALLBACK_DEF( FT_Error )
00298   TT_Load_Glyph_Header( TT_Loader  loader )
00299   {
00300     FT_Byte*  p     = loader->cursor;
00301     FT_Byte*  limit = loader->limit;
00302 
00303 
00304     if ( p + 10 > limit )
00305       return TT_Err_Invalid_Outline;
00306 
00307     loader->n_contours = FT_NEXT_SHORT( p );
00308 
00309     loader->bbox.xMin = FT_NEXT_SHORT( p );
00310     loader->bbox.yMin = FT_NEXT_SHORT( p );
00311     loader->bbox.xMax = FT_NEXT_SHORT( p );
00312     loader->bbox.yMax = FT_NEXT_SHORT( p );
00313 
00314     FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
00315     FT_TRACE5(( "  xMin: %4d  xMax: %4d\n", loader->bbox.xMin,
00316                                             loader->bbox.xMax ));
00317     FT_TRACE5(( "  yMin: %4d  yMax: %4d\n", loader->bbox.yMin,
00318                                             loader->bbox.yMax ));
00319     loader->cursor = p;
00320 
00321     return TT_Err_Ok;
00322   }
00323 
00324 
00325   FT_CALLBACK_DEF( FT_Error )
00326   TT_Load_Simple_Glyph( TT_Loader  load )
00327   {
00328     FT_Error        error;
00329     FT_Byte*        p          = load->cursor;
00330     FT_Byte*        limit      = load->limit;
00331     FT_GlyphLoader  gloader    = load->gloader;
00332     FT_Int          n_contours = load->n_contours;
00333     FT_Outline*     outline;
00334     TT_Face         face       = (TT_Face)load->face;
00335     FT_UShort       n_ins;
00336     FT_Int          n_points;
00337 
00338     FT_Byte         *flag, *flag_limit;
00339     FT_Byte         c, count;
00340     FT_Vector       *vec, *vec_limit;
00341     FT_Pos          x;
00342     FT_Short        *cont, *cont_limit, prev_cont;
00343     FT_Int          xy_size = 0;
00344 
00345 
00346     
00347     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
00348     if ( error )
00349       goto Fail;
00350 
00351     
00352     cont       = gloader->current.outline.contours;
00353     cont_limit = cont + n_contours;
00354 
00355     
00356     if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
00357       goto Invalid_Outline;
00358 
00359     prev_cont = FT_NEXT_USHORT( p );
00360 
00361     if ( n_contours > 0 )
00362       cont[0] = prev_cont;
00363 
00364     for ( cont++; cont < cont_limit; cont++ )
00365     {
00366       cont[0] = FT_NEXT_USHORT( p );
00367       if ( cont[0] <= prev_cont )
00368       {
00369         
00370         error = FT_Err_Invalid_Table;
00371         goto Fail;
00372       }
00373       prev_cont = cont[0];
00374     }
00375 
00376     n_points = 0;
00377     if ( n_contours > 0 )
00378     {
00379       n_points = cont[-1] + 1;
00380       if ( n_points < 0 )
00381         goto Invalid_Outline;
00382     }
00383 
00384     
00385     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
00386     if ( error )
00387       goto Fail;
00388 
00389     
00390     outline = &gloader->current.outline;
00391 
00392     for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
00393       if ( cont[-1] >= cont[0] )
00394         goto Invalid_Outline;
00395 
00396     
00397     load->glyph->control_len  = 0;
00398     load->glyph->control_data = 0;
00399 
00400     if ( p + 2 > limit )
00401       goto Invalid_Outline;
00402 
00403     n_ins = FT_NEXT_USHORT( p );
00404 
00405     FT_TRACE5(( "  Instructions size: %u\n", n_ins ));
00406 
00407     if ( n_ins > face->max_profile.maxSizeOfInstructions )
00408     {
00409       FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
00410                   n_ins ));
00411       error = TT_Err_Too_Many_Hints;
00412       goto Fail;
00413     }
00414 
00415     if ( ( limit - p ) < n_ins )
00416     {
00417       FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
00418       error = TT_Err_Too_Many_Hints;
00419       goto Fail;
00420     }
00421 
00422 #ifdef TT_USE_BYTECODE_INTERPRETER
00423 
00424     if ( IS_HINTED( load->load_flags ) )
00425     {
00426       load->glyph->control_len  = n_ins;
00427       load->glyph->control_data = load->exec->glyphIns;
00428 
00429       FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
00430     }
00431 
00432 #endif 
00433 
00434     p += n_ins;
00435 
00436     
00437     flag       = (FT_Byte*)outline->tags;
00438     flag_limit = flag + n_points;
00439 
00440     FT_ASSERT( flag != NULL );
00441 
00442     while ( flag < flag_limit )
00443     {
00444       if ( p + 1 > limit )
00445         goto Invalid_Outline;
00446 
00447       *flag++ = c = FT_NEXT_BYTE( p );
00448       if ( c & 8 )
00449       {
00450         if ( p + 1 > limit )
00451           goto Invalid_Outline;
00452 
00453         count = FT_NEXT_BYTE( p );
00454         if ( flag + (FT_Int)count > flag_limit )
00455           goto Invalid_Outline;
00456 
00457         for ( ; count > 0; count-- )
00458           *flag++ = c;
00459       }
00460     }
00461 
00462     
00463 
00464     vec       = outline->points;
00465     vec_limit = vec + n_points;
00466     flag      = (FT_Byte*)outline->tags;
00467     x         = 0;
00468 
00469     if ( p + xy_size > limit )
00470       goto Invalid_Outline;
00471 
00472     for ( ; vec < vec_limit; vec++, flag++ )
00473     {
00474       FT_Pos   y = 0;
00475       FT_Byte  f = *flag;
00476 
00477 
00478       if ( f & 2 )
00479       {
00480         if ( p + 1 > limit )
00481           goto Invalid_Outline;
00482 
00483         y = (FT_Pos)FT_NEXT_BYTE( p );
00484         if ( ( f & 16 ) == 0 )
00485           y = -y;
00486       }
00487       else if ( ( f & 16 ) == 0 )
00488       {
00489         if ( p + 2 > limit )
00490           goto Invalid_Outline;
00491 
00492         y = (FT_Pos)FT_NEXT_SHORT( p );
00493       }
00494 
00495       x     += y;
00496       vec->x = x;
00497       
00498       *flag  = (FT_Byte)( f & ~( 2 | 16 ) );
00499     }
00500 
00501     
00502 
00503     vec       = gloader->current.outline.points;
00504     vec_limit = vec + n_points;
00505     flag      = (FT_Byte*)outline->tags;
00506     x         = 0;
00507 
00508     for ( ; vec < vec_limit; vec++, flag++ )
00509     {
00510       FT_Pos   y = 0;
00511       FT_Byte  f = *flag;
00512 
00513 
00514       if ( f & 4 )
00515       {
00516         if ( p + 1 > limit )
00517           goto Invalid_Outline;
00518 
00519         y = (FT_Pos)FT_NEXT_BYTE( p );
00520         if ( ( f & 32 ) == 0 )
00521           y = -y;
00522       }
00523       else if ( ( f & 32 ) == 0 )
00524       {
00525         if ( p + 2 > limit )
00526           goto Invalid_Outline;
00527 
00528         y = (FT_Pos)FT_NEXT_SHORT( p );
00529       }
00530 
00531       x     += y;
00532       vec->y = x;
00533       
00534       *flag  = (FT_Byte)( f & FT_CURVE_TAG_ON );
00535     }
00536 
00537     outline->n_points   = (FT_UShort)n_points;
00538     outline->n_contours = (FT_Short) n_contours;
00539 
00540     load->cursor = p;
00541 
00542   Fail:
00543     return error;
00544 
00545   Invalid_Outline:
00546     error = TT_Err_Invalid_Outline;
00547     goto Fail;
00548   }
00549 
00550 
00551   FT_CALLBACK_DEF( FT_Error )
00552   TT_Load_Composite_Glyph( TT_Loader  loader )
00553   {
00554     FT_Error        error;
00555     FT_Byte*        p       = loader->cursor;
00556     FT_Byte*        limit   = loader->limit;
00557     FT_GlyphLoader  gloader = loader->gloader;
00558     FT_SubGlyph     subglyph;
00559     FT_UInt         num_subglyphs;
00560 
00561 
00562     num_subglyphs = 0;
00563 
00564     do
00565     {
00566       FT_Fixed  xx, xy, yy, yx;
00567       FT_UInt   count;
00568 
00569 
00570       
00571       error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
00572       if ( error )
00573         goto Fail;
00574 
00575       
00576       if ( p + 4 > limit )
00577         goto Invalid_Composite;
00578 
00579       subglyph = gloader->current.subglyphs + num_subglyphs;
00580 
00581       subglyph->arg1 = subglyph->arg2 = 0;
00582 
00583       subglyph->flags = FT_NEXT_USHORT( p );
00584       subglyph->index = FT_NEXT_USHORT( p );
00585 
00586       
00587       count = 2;
00588       if ( subglyph->flags & ARGS_ARE_WORDS )
00589         count += 2;
00590       if ( subglyph->flags & WE_HAVE_A_SCALE )
00591         count += 2;
00592       else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
00593         count += 4;
00594       else if ( subglyph->flags & WE_HAVE_A_2X2 )
00595         count += 8;
00596 
00597       if ( p + count > limit )
00598         goto Invalid_Composite;
00599 
00600       
00601       if ( subglyph->flags & ARGS_ARE_WORDS )
00602       {
00603         subglyph->arg1 = FT_NEXT_SHORT( p );
00604         subglyph->arg2 = FT_NEXT_SHORT( p );
00605       }
00606       else
00607       {
00608         subglyph->arg1 = FT_NEXT_CHAR( p );
00609         subglyph->arg2 = FT_NEXT_CHAR( p );
00610       }
00611 
00612       
00613       xx = yy = 0x10000L;
00614       xy = yx = 0;
00615 
00616       if ( subglyph->flags & WE_HAVE_A_SCALE )
00617       {
00618         xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00619         yy = xx;
00620       }
00621       else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
00622       {
00623         xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00624         yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00625       }
00626       else if ( subglyph->flags & WE_HAVE_A_2X2 )
00627       {
00628         xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00629         yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00630         xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00631         yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00632       }
00633 
00634       subglyph->transform.xx = xx;
00635       subglyph->transform.xy = xy;
00636       subglyph->transform.yx = yx;
00637       subglyph->transform.yy = yy;
00638 
00639       num_subglyphs++;
00640 
00641     } while ( subglyph->flags & MORE_COMPONENTS );
00642 
00643     gloader->current.num_subglyphs = num_subglyphs;
00644 
00645 #ifdef TT_USE_BYTECODE_INTERPRETER
00646 
00647     {
00648       FT_Stream  stream = loader->stream;
00649 
00650 
00651       
00652       
00653       
00654       
00655       loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
00656                                     p - limit );
00657     }
00658 
00659 #endif
00660 
00661     loader->cursor = p;
00662 
00663   Fail:
00664     return error;
00665 
00666   Invalid_Composite:
00667     error = TT_Err_Invalid_Composite;
00668     goto Fail;
00669   }
00670 
00671 
00672   FT_LOCAL_DEF( void )
00673   TT_Init_Glyph_Loading( TT_Face  face )
00674   {
00675     face->access_glyph_frame   = TT_Access_Glyph_Frame;
00676     face->read_glyph_header    = TT_Load_Glyph_Header;
00677     face->read_simple_glyph    = TT_Load_Simple_Glyph;
00678     face->read_composite_glyph = TT_Load_Composite_Glyph;
00679     face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
00680   }
00681 
00682 
00683   static void
00684   tt_prepare_zone( TT_GlyphZone  zone,
00685                    FT_GlyphLoad  load,
00686                    FT_UInt       start_point,
00687                    FT_UInt       start_contour )
00688   {
00689     zone->n_points    = (FT_UShort)( load->outline.n_points - start_point );
00690     zone->n_contours  = (FT_Short) ( load->outline.n_contours -
00691                                        start_contour );
00692     zone->org         = load->extra_points + start_point;
00693     zone->cur         = load->outline.points + start_point;
00694     zone->orus        = load->extra_points2 + start_point;
00695     zone->tags        = (FT_Byte*)load->outline.tags + start_point;
00696     zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
00697     zone->first_point = (FT_UShort)start_point;
00698   }
00699 
00700 
00701   
00702   
00703   
00704   
00705   
00706   
00707   
00708   
00709   
00710   static FT_Error
00711   TT_Hint_Glyph( TT_Loader  loader,
00712                  FT_Bool    is_composite )
00713   {
00714     TT_GlyphZone  zone = &loader->zone;
00715     FT_Pos        origin;
00716 
00717 #ifdef TT_USE_BYTECODE_INTERPRETER
00718     FT_UInt       n_ins;
00719 #else
00720     FT_UNUSED( is_composite );
00721 #endif
00722 
00723 
00724 #ifdef TT_USE_BYTECODE_INTERPRETER
00725     if ( loader->glyph->control_len > 0xFFFFL )
00726     {
00727       FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));
00728       FT_TRACE1(( "(0x%lx byte) is truncated\n",
00729                  loader->glyph->control_len ));
00730     }
00731     n_ins = (FT_UInt)( loader->glyph->control_len );
00732 #endif
00733 
00734     origin = zone->cur[zone->n_points - 4].x;
00735     origin = FT_PIX_ROUND( origin ) - origin;
00736     if ( origin )
00737       translate_array( zone->n_points, zone->cur, origin, 0 );
00738 
00739 #ifdef TT_USE_BYTECODE_INTERPRETER
00740     
00741     if ( n_ins > 0 )
00742       FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
00743 
00744     
00745     loader->exec->GS = ((TT_Size)loader->size)->GS;
00746 
00747     
00748     
00749     if ( is_composite )
00750     {
00751       loader->exec->metrics.x_scale = 1 << 16;
00752       loader->exec->metrics.y_scale = 1 << 16;
00753 
00754       FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
00755     }
00756     else
00757     {
00758       loader->exec->metrics.x_scale =
00759         ((TT_Size)loader->size)->metrics.x_scale;
00760       loader->exec->metrics.y_scale =
00761         ((TT_Size)loader->size)->metrics.y_scale;
00762     }
00763 #endif
00764 
00765     
00766     zone->cur[zone->n_points - 3].x =
00767       FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
00768     zone->cur[zone->n_points - 1].y =
00769       FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
00770 
00771 #ifdef TT_USE_BYTECODE_INTERPRETER
00772 
00773     if ( n_ins > 0 )
00774     {
00775       FT_Bool   debug;
00776       FT_Error  error;
00777 
00778       FT_GlyphLoader  gloader         = loader->gloader;
00779       FT_Outline      current_outline = gloader->current.outline;
00780 
00781 
00782       error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
00783                                 loader->exec->glyphIns, n_ins );
00784       if ( error )
00785         return error;
00786 
00787       loader->exec->is_composite = is_composite;
00788       loader->exec->pts          = *zone;
00789 
00790       debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
00791                        ((TT_Size)loader->size)->debug             );
00792 
00793       error = TT_Run_Context( loader->exec, debug );
00794       if ( error && loader->exec->pedantic_hinting )
00795         return error;
00796 
00797       
00798       current_outline.tags[0] |=
00799         ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
00800     }
00801 
00802 #endif
00803 
00804     
00805     if ( !loader->preserve_pps )
00806     {
00807       loader->pp1 = zone->cur[zone->n_points - 4];
00808       loader->pp2 = zone->cur[zone->n_points - 3];
00809       loader->pp3 = zone->cur[zone->n_points - 2];
00810       loader->pp4 = zone->cur[zone->n_points - 1];
00811     }
00812 
00813     return TT_Err_Ok;
00814   }
00815 
00816 
00817   
00818   
00819   
00820   
00821   
00822   
00823   
00824   
00825   
00826   
00827   static FT_Error
00828   TT_Process_Simple_Glyph( TT_Loader  loader )
00829   {
00830     FT_GlyphLoader  gloader = loader->gloader;
00831     FT_Error        error   = TT_Err_Ok;
00832     FT_Outline*     outline;
00833     FT_Int          n_points;
00834 
00835 
00836     outline  = &gloader->current.outline;
00837     n_points = outline->n_points;
00838 
00839     
00840 
00841     outline->points[n_points    ] = loader->pp1;
00842     outline->points[n_points + 1] = loader->pp2;
00843     outline->points[n_points + 2] = loader->pp3;
00844     outline->points[n_points + 3] = loader->pp4;
00845 
00846     outline->tags[n_points    ] = 0;
00847     outline->tags[n_points + 1] = 0;
00848     outline->tags[n_points + 2] = 0;
00849     outline->tags[n_points + 3] = 0;
00850 
00851     n_points += 4;
00852 
00853 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00854 
00855     if ( ((TT_Face)loader->face)->doblend )
00856     {
00857       
00858       FT_Vector*  deltas;
00859       FT_Memory   memory = loader->face->memory;
00860       FT_Int      i;
00861 
00862 
00863       error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
00864                                         loader->glyph_index,
00865                                         &deltas,
00866                                         n_points );
00867       if ( error )
00868         return error;
00869 
00870       for ( i = 0; i < n_points; ++i )
00871       {
00872         outline->points[i].x += deltas[i].x;
00873         outline->points[i].y += deltas[i].y;
00874       }
00875 
00876       FT_FREE( deltas );
00877     }
00878 
00879 #endif 
00880 
00881     if ( IS_HINTED( loader->load_flags ) )
00882     {
00883       tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
00884 
00885       FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
00886                      loader->zone.n_points + 4 );
00887     }
00888 
00889     
00890     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
00891     {
00892       FT_Vector*  vec     = outline->points;
00893       FT_Vector*  limit   = outline->points + n_points;
00894       FT_Fixed    x_scale = ((TT_Size)loader->size)->metrics.x_scale;
00895       FT_Fixed    y_scale = ((TT_Size)loader->size)->metrics.y_scale;
00896 
00897 
00898       for ( ; vec < limit; vec++ )
00899       {
00900         vec->x = FT_MulFix( vec->x, x_scale );
00901         vec->y = FT_MulFix( vec->y, y_scale );
00902       }
00903 
00904       loader->pp1 = outline->points[n_points - 4];
00905       loader->pp2 = outline->points[n_points - 3];
00906       loader->pp3 = outline->points[n_points - 2];
00907       loader->pp4 = outline->points[n_points - 1];
00908     }
00909 
00910     if ( IS_HINTED( loader->load_flags ) )
00911     {
00912       loader->zone.n_points += 4;
00913 
00914       error = TT_Hint_Glyph( loader, 0 );
00915     }
00916 
00917     return error;
00918   }
00919 
00920 
00921   
00922   
00923   
00924   
00925   
00926   
00927   
00928   
00929   
00930   static FT_Error
00931   TT_Process_Composite_Component( TT_Loader    loader,
00932                                   FT_SubGlyph  subglyph,
00933                                   FT_UInt      start_point,
00934                                   FT_UInt      num_base_points )
00935   {
00936     FT_GlyphLoader  gloader    = loader->gloader;
00937     FT_Vector*      base_vec   = gloader->base.outline.points;
00938     FT_UInt         num_points = gloader->base.outline.n_points;
00939     FT_Bool         have_scale;
00940     FT_Pos          x, y;
00941 
00942 
00943     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
00944                                               WE_HAVE_AN_XY_SCALE |
00945                                               WE_HAVE_A_2X2       ) );
00946 
00947     
00948     if ( have_scale )
00949     {
00950       FT_UInt  i;
00951 
00952 
00953       for ( i = num_base_points; i < num_points; i++ )
00954         FT_Vector_Transform( base_vec + i, &subglyph->transform );
00955     }
00956 
00957     
00958     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
00959     {
00960       FT_UInt     k = subglyph->arg1;
00961       FT_UInt     l = subglyph->arg2;
00962       FT_Vector*  p1;
00963       FT_Vector*  p2;
00964 
00965 
00966       
00967       
00968 
00969       
00970       k += start_point;
00971       l += num_base_points;
00972       if ( k >= num_base_points ||
00973            l >= num_points      )
00974         return TT_Err_Invalid_Composite;
00975 
00976       p1 = gloader->base.outline.points + k;
00977       p2 = gloader->base.outline.points + l;
00978 
00979       x = p1->x - p2->x;
00980       y = p1->y - p2->y;
00981     }
00982     else
00983     {
00984       x = subglyph->arg1;
00985       y = subglyph->arg2;
00986 
00987       if ( !x && !y )
00988         return TT_Err_Ok;
00989 
00990   
00991   
00992   
00993 
00994       if ( have_scale &&
00995 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
00996            !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
00997 #else
00998             ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
00999 #endif
01000       {
01001 
01002 #if 0
01003 
01004   
01005   
01006   
01007   
01008         int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
01009                                             : -subglyph->transform.xx;
01010         int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
01011                                             : -subglyph->transform.yx;
01012         int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
01013                                             : -subglyph->transform.xy;
01014         int  d = subglyph->transform.yy > 0 ? subglyph->transform.yy
01015                                             : -subglyph->transform.yy;
01016         int  m = a > b ? a : b;
01017         int  n = c > d ? c : d;
01018 
01019 
01020         if ( a - b <= 33 && a - b >= -33 )
01021           m *= 2;
01022         if ( c - d <= 33 && c - d >= -33 )
01023           n *= 2;
01024         x = FT_MulFix( x, m );
01025         y = FT_MulFix( y, n );
01026 
01027 #else 
01028 
01029   
01030   
01031   
01032   
01033         FT_Fixed  mac_xscale = FT_SqrtFixed(
01034                                  (FT_Int32)FT_MulFix( subglyph->transform.xx,
01035                                                       subglyph->transform.xx ) +
01036                                  (FT_Int32)FT_MulFix( subglyph->transform.xy,
01037                                                       subglyph->transform.xy ) );
01038         FT_Fixed  mac_yscale = FT_SqrtFixed(
01039                                  (FT_Int32)FT_MulFix( subglyph->transform.yy,
01040                                                       subglyph->transform.yy ) +
01041                                  (FT_Int32)FT_MulFix( subglyph->transform.yx,
01042                                                       subglyph->transform.yx ) );
01043 
01044 
01045         x = FT_MulFix( x, mac_xscale );
01046         y = FT_MulFix( y, mac_yscale );
01047 
01048 #endif 
01049 
01050       }
01051 
01052       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
01053       {
01054         FT_Fixed  x_scale = ((TT_Size)loader->size)->metrics.x_scale;
01055         FT_Fixed  y_scale = ((TT_Size)loader->size)->metrics.y_scale;
01056 
01057 
01058         x = FT_MulFix( x, x_scale );
01059         y = FT_MulFix( y, y_scale );
01060 
01061         if ( subglyph->flags & ROUND_XY_TO_GRID )
01062         {
01063           x = FT_PIX_ROUND( x );
01064           y = FT_PIX_ROUND( y );
01065         }
01066       }
01067     }
01068 
01069     if ( x || y )
01070       translate_array( num_points - num_base_points,
01071                        base_vec + num_base_points,
01072                        x, y );
01073 
01074     return TT_Err_Ok;
01075   }
01076 
01077 
01078   
01079   
01080   
01081   
01082   
01083   
01084   
01085   
01086   
01087   
01088   static FT_Error
01089   TT_Process_Composite_Glyph( TT_Loader  loader,
01090                               FT_UInt    start_point,
01091                               FT_UInt    start_contour )
01092   {
01093     FT_Error     error;
01094     FT_Outline*  outline;
01095     FT_UInt      i;
01096 
01097 
01098     outline = &loader->gloader->base.outline;
01099 
01100     
01101     error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
01102                                          outline->n_points + 4,
01103                                          0 );
01104     if ( error )
01105       return error;
01106 
01107     outline->points[outline->n_points    ] = loader->pp1;
01108     outline->points[outline->n_points + 1] = loader->pp2;
01109     outline->points[outline->n_points + 2] = loader->pp3;
01110     outline->points[outline->n_points + 3] = loader->pp4;
01111 
01112     outline->tags[outline->n_points    ] = 0;
01113     outline->tags[outline->n_points + 1] = 0;
01114     outline->tags[outline->n_points + 2] = 0;
01115     outline->tags[outline->n_points + 3] = 0;
01116 
01117 #ifdef TT_USE_BYTECODE_INTERPRETER
01118 
01119     {
01120       FT_Stream  stream = loader->stream;
01121       FT_UShort  n_ins;
01122 
01123 
01124       
01125       
01126       if ( FT_STREAM_SEEK( loader->ins_pos ) ||
01127            FT_READ_USHORT( n_ins )           )
01128         return error;
01129 
01130       FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
01131 
01132       
01133       if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions )
01134       {
01135         FT_TRACE0(( "TT_Process_Composite_Glyph: too many instructions (%d)\n",
01136                     n_ins ));
01137 
01138         return TT_Err_Too_Many_Hints;
01139       }
01140       else if ( n_ins == 0 )
01141         return TT_Err_Ok;
01142 
01143       if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
01144         return error;
01145 
01146       loader->glyph->control_data = loader->exec->glyphIns;
01147       loader->glyph->control_len  = n_ins;
01148     }
01149 
01150 #endif
01151 
01152     tt_prepare_zone( &loader->zone, &loader->gloader->base,
01153                      start_point, start_contour );
01154 
01155     
01156     
01157     for ( i = start_point; i < loader->zone.n_points; i++ )
01158       loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
01159 
01160     loader->zone.n_points += 4;
01161 
01162     return TT_Hint_Glyph( loader, 1 );
01163   }
01164 
01165 
01166   
01167   
01168   
01169 #define TT_LOADER_SET_PP( loader )                                          \
01170           do {                                                              \
01171             (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
01172             (loader)->pp1.y = 0;                                            \
01173             (loader)->pp2.x = (loader)->pp1.x + (loader)->advance;          \
01174             (loader)->pp2.y = 0;                                            \
01175             (loader)->pp3.x = 0;                                            \
01176             (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax;  \
01177             (loader)->pp4.x = 0;                                            \
01178             (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
01179           } while ( 0 )
01180 
01181 
01182   
01183   
01184   
01185   
01186   
01187   
01188   
01189   
01190   
01191   static FT_Error
01192   load_truetype_glyph( TT_Loader  loader,
01193                        FT_UInt    glyph_index,
01194                        FT_UInt    recurse_count,
01195                        FT_Bool    header_only )
01196   {
01197     FT_Error        error        = TT_Err_Ok;
01198     FT_Fixed        x_scale, y_scale;
01199     FT_ULong        offset;
01200     TT_Face         face         = (TT_Face)loader->face;
01201     FT_GlyphLoader  gloader      = loader->gloader;
01202     FT_Bool         opened_frame = 0;
01203 
01204 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
01205     FT_Vector*      deltas       = NULL;
01206 #endif
01207 
01208 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01209     FT_StreamRec    inc_stream;
01210     FT_Data         glyph_data;
01211     FT_Bool         glyph_data_loaded = 0;
01212 #endif
01213 
01214 
01215     
01216     
01217     if ( recurse_count > 1                                   &&
01218          recurse_count > face->max_profile.maxComponentDepth )
01219     {
01220       error = TT_Err_Invalid_Composite;
01221       goto Exit;
01222     }
01223 
01224     
01225     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
01226     {
01227       error = TT_Err_Invalid_Glyph_Index;
01228       goto Exit;
01229     }
01230 
01231     loader->glyph_index = glyph_index;
01232 
01233     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01234     {
01235       x_scale = ((TT_Size)loader->size)->metrics.x_scale;
01236       y_scale = ((TT_Size)loader->size)->metrics.y_scale;
01237     }
01238     else
01239     {
01240       x_scale = 0x10000L;
01241       y_scale = 0x10000L;
01242     }
01243 
01244     tt_get_metrics( loader, glyph_index );
01245 
01246     
01247     
01248     
01249 
01250 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01251 
01252     
01253     
01254     
01255     if ( face->root.internal->incremental_interface )
01256     {
01257       error = face->root.internal->incremental_interface->funcs->get_glyph_data(
01258                 face->root.internal->incremental_interface->object,
01259                 glyph_index, &glyph_data );
01260       if ( error )
01261         goto Exit;
01262 
01263       glyph_data_loaded = 1;
01264       offset            = 0;
01265       loader->byte_len  = glyph_data.length;
01266 
01267       FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
01268       FT_Stream_OpenMemory( &inc_stream,
01269                             glyph_data.pointer, glyph_data.length );
01270 
01271       loader->stream = &inc_stream;
01272     }
01273     else
01274 
01275 #endif 
01276 
01277       offset = tt_face_get_location( face, glyph_index,
01278                                      (FT_UInt*)&loader->byte_len );
01279 
01280     if ( loader->byte_len > 0 )
01281     {
01282 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01283       
01284       if ( !loader->glyf_offset                        &&
01285            !face->root.internal->incremental_interface )
01286 #else
01287       if ( !loader->glyf_offset )
01288 #endif 
01289       {
01290         FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
01291         error = TT_Err_Invalid_Table;
01292         goto Exit;
01293       }
01294 
01295       error = face->access_glyph_frame( loader, glyph_index,
01296                                         loader->glyf_offset + offset,
01297                                         loader->byte_len );
01298       if ( error )
01299         goto Exit;
01300 
01301       opened_frame = 1;
01302 
01303       
01304       error = face->read_glyph_header( loader );
01305       if ( error || header_only )
01306         goto Exit;
01307     }
01308 
01309     if ( loader->byte_len == 0 || loader->n_contours == 0 )
01310     {
01311       loader->bbox.xMin = 0;
01312       loader->bbox.xMax = 0;
01313       loader->bbox.yMin = 0;
01314       loader->bbox.yMax = 0;
01315 
01316       if ( header_only )
01317         goto Exit;
01318 
01319       TT_LOADER_SET_PP( loader );
01320 
01321 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
01322 
01323       if ( ((TT_Face)(loader->face))->doblend )
01324       {
01325         
01326         FT_Memory  memory = loader->face->memory;
01327 
01328 
01329         error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
01330                                           glyph_index, &deltas, 4 );
01331         if ( error )
01332           goto Exit;
01333 
01334         loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
01335         loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
01336         loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
01337         loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
01338 
01339         FT_FREE( deltas );
01340       }
01341 
01342 #endif
01343 
01344       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01345       {
01346         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
01347         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
01348         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
01349         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
01350       }
01351 
01352       error = TT_Err_Ok;
01353       goto Exit;
01354     }
01355 
01356     TT_LOADER_SET_PP( loader );
01357 
01358     
01359     
01360     
01361 
01362     
01363 
01364     if ( loader->n_contours > 0 )
01365     {
01366       error = face->read_simple_glyph( loader );
01367       if ( error )
01368         goto Exit;
01369 
01370       
01371       face->forget_glyph_frame( loader );
01372       opened_frame = 0;
01373 
01374       error = TT_Process_Simple_Glyph( loader );
01375       if ( error )
01376         goto Exit;
01377 
01378       FT_GlyphLoader_Add( gloader );
01379     }
01380 
01381     
01382     
01383     
01384 
01385     
01386     else if ( loader->n_contours == -1 )
01387     {
01388       FT_UInt   start_point;
01389       FT_UInt   start_contour;
01390       FT_ULong  ins_pos;  
01391 
01392 
01393       start_point   = gloader->base.outline.n_points;
01394       start_contour = gloader->base.outline.n_contours;
01395 
01396       
01397       error = face->read_composite_glyph( loader );
01398       if ( error )
01399         goto Exit;
01400 
01401       
01402       ins_pos = loader->ins_pos;
01403 
01404       
01405       face->forget_glyph_frame( loader );
01406       opened_frame = 0;
01407 
01408 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
01409 
01410       if ( face->doblend )
01411       {
01412         FT_Int       i, limit;
01413         FT_SubGlyph  subglyph;
01414         FT_Memory    memory = face->root.memory;
01415 
01416 
01417         
01418         
01419 
01420         if ( ( error = TT_Vary_Get_Glyph_Deltas(
01421                          face,
01422                          glyph_index,
01423                          &deltas,
01424                          gloader->current.num_subglyphs + 4 )) != 0 )
01425           goto Exit;
01426 
01427         subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
01428         limit    = gloader->current.num_subglyphs;
01429 
01430         for ( i = 0; i < limit; ++i, ++subglyph )
01431         {
01432           if ( subglyph->flags & ARGS_ARE_XY_VALUES )
01433           {
01434             
01435             
01436             
01437             subglyph->arg1 += (FT_Int16)deltas[i].x;
01438             subglyph->arg2 += (FT_Int16)deltas[i].y;
01439           }
01440         }
01441 
01442         loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
01443         loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
01444         loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
01445         loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
01446 
01447         FT_FREE( deltas );
01448       }
01449 
01450 #endif 
01451 
01452       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01453       {
01454         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
01455         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
01456         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
01457         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
01458       }
01459 
01460       
01461       
01462       
01463       if ( loader->load_flags & FT_LOAD_NO_RECURSE )
01464       {
01465         FT_GlyphLoader_Add( gloader );
01466         loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
01467 
01468         goto Exit;
01469       }
01470 
01471       
01472       
01473       
01474 
01475       {
01476         FT_UInt      n, num_base_points;
01477         FT_SubGlyph  subglyph       = 0;
01478 
01479         FT_UInt      num_points     = start_point;
01480         FT_UInt      num_subglyphs  = gloader->current.num_subglyphs;
01481         FT_UInt      num_base_subgs = gloader->base.num_subglyphs;
01482 
01483         FT_Stream    old_stream     = loader->stream;
01484 
01485 
01486         FT_GlyphLoader_Add( gloader );
01487 
01488         
01489         for ( n = 0; n < num_subglyphs; n++ )
01490         {
01491           FT_Vector  pp[4];
01492 
01493 
01494           
01495           
01496           
01497           
01498           subglyph = gloader->base.subglyphs + num_base_subgs + n;
01499 
01500           pp[0] = loader->pp1;
01501           pp[1] = loader->pp2;
01502           pp[2] = loader->pp3;
01503           pp[3] = loader->pp4;
01504 
01505           num_base_points = gloader->base.outline.n_points;
01506 
01507           error = load_truetype_glyph( loader, subglyph->index,
01508                                        recurse_count + 1, FALSE );
01509           if ( error )
01510             goto Exit;
01511 
01512           
01513           subglyph = gloader->base.subglyphs + num_base_subgs + n;
01514 
01515           if ( !( subglyph->flags & USE_MY_METRICS ) )
01516           {
01517             loader->pp1 = pp[0];
01518             loader->pp2 = pp[1];
01519             loader->pp3 = pp[2];
01520             loader->pp4 = pp[3];
01521           }
01522 
01523           num_points = gloader->base.outline.n_points;
01524 
01525           if ( num_points == num_base_points )
01526             continue;
01527 
01528           
01529           
01530           
01531           
01532           
01533           
01534           TT_Process_Composite_Component( loader, subglyph, start_point,
01535                                           num_base_points );
01536         }
01537 
01538         loader->stream = old_stream;
01539 
01540         
01541         loader->ins_pos = ins_pos;
01542         if ( IS_HINTED( loader->load_flags ) &&
01543 
01544 #ifdef TT_USE_BYTECODE_INTERPRETER
01545 
01546              subglyph->flags & WE_HAVE_INSTR &&
01547 
01548 #endif
01549 
01550              num_points > start_point )
01551           TT_Process_Composite_Glyph( loader, start_point, start_contour );
01552 
01553       }
01554     }
01555     else
01556     {
01557       
01558       error = TT_Err_Invalid_Outline;
01559       goto Exit;
01560     }
01561 
01562     
01563     
01564     
01565 
01566   Exit:
01567 
01568     if ( opened_frame )
01569       face->forget_glyph_frame( loader );
01570 
01571 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01572 
01573     if ( glyph_data_loaded )
01574       face->root.internal->incremental_interface->funcs->free_glyph_data(
01575         face->root.internal->incremental_interface->object,
01576         &glyph_data );
01577 
01578 #endif
01579 
01580     return error;
01581   }
01582 
01583 
01584   static FT_Error
01585   compute_glyph_metrics( TT_Loader  loader,
01586                          FT_UInt    glyph_index )
01587   {
01588     FT_BBox       bbox;
01589     TT_Face       face = (TT_Face)loader->face;
01590     FT_Fixed      y_scale;
01591     TT_GlyphSlot  glyph = loader->glyph;
01592     TT_Size       size = (TT_Size)loader->size;
01593 
01594 
01595     y_scale = 0x10000L;
01596     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01597       y_scale = size->root.metrics.y_scale;
01598 
01599     if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
01600       FT_Outline_Get_CBox( &glyph->outline, &bbox );
01601     else
01602       bbox = loader->bbox;
01603 
01604     
01605     
01606     {
01607       FT_Pos  advance = loader->linear;
01608 
01609 
01610       
01611       
01612       
01613       
01614       
01615       if ( face->postscript.isFixedPitch                                     &&
01616            ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
01617         advance = face->horizontal.advance_Width_Max;
01618 
01619       
01620       
01621       glyph->linearHoriAdvance = advance;
01622     }
01623 
01624     glyph->metrics.horiBearingX = bbox.xMin;
01625     glyph->metrics.horiBearingY = bbox.yMax;
01626     glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
01627 
01628     
01629     if ( !face->postscript.isFixedPitch  &&
01630          IS_HINTED( loader->load_flags ) )
01631     {
01632       FT_Byte*  widthp;
01633 
01634 
01635       widthp = tt_face_get_device_metrics( face,
01636                                            size->root.metrics.x_ppem,
01637                                            glyph_index );
01638 
01639       if ( widthp )
01640         glyph->metrics.horiAdvance = *widthp << 6;
01641     }
01642 
01643     
01644     glyph->metrics.width  = bbox.xMax - bbox.xMin;
01645     glyph->metrics.height = bbox.yMax - bbox.yMin;
01646 
01647     
01648     
01649     
01650     {
01651       FT_Pos  top;      
01652       FT_Pos  advance;  
01653 
01654 
01655       
01656       if ( face->vertical_info                   &&
01657            face->vertical.number_Of_VMetrics > 0 )
01658       {
01659         top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
01660                                    y_scale );
01661 
01662         if ( loader->pp3.y <= loader->pp4.y )
01663           advance = 0;
01664         else
01665           advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
01666                                           y_scale );
01667       }
01668       else
01669       {
01670         FT_Pos  height;
01671 
01672 
01673         
01674         
01675 
01676         
01677         
01678         
01679         
01680 
01681         height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
01682                                       y_scale );
01683         if ( face->os2.version != 0xFFFFU )
01684           advance = (FT_Pos)( face->os2.sTypoAscender -
01685                               face->os2.sTypoDescender );
01686         else
01687           advance = (FT_Pos)( face->horizontal.Ascender -
01688                               face->horizontal.Descender );
01689 
01690         top = ( advance - height ) / 2;
01691       }
01692 
01693 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01694       {
01695         FT_Incremental_InterfaceRec*  incr;
01696         FT_Incremental_MetricsRec     metrics;
01697         FT_Error                      error;
01698 
01699 
01700         incr = face->root.internal->incremental_interface;
01701 
01702         
01703         
01704         if ( incr && incr->funcs->get_glyph_metrics )
01705         {
01706           metrics.bearing_x = 0;
01707           metrics.bearing_y = top;
01708           metrics.advance   = advance;
01709 
01710           error = incr->funcs->get_glyph_metrics( incr->object,
01711                                                   glyph_index,
01712                                                   TRUE,
01713                                                   &metrics );
01714           if ( error )
01715             return error;
01716 
01717           top     = metrics.bearing_y;
01718           advance = metrics.advance;
01719         }
01720       }
01721 
01722       
01723 
01724 #endif 
01725 
01726       glyph->linearVertAdvance = advance;
01727 
01728       
01729       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
01730       {
01731         top     = FT_MulFix( top,     y_scale );
01732         advance = FT_MulFix( advance, y_scale );
01733       }
01734 
01735       
01736       
01737       
01738       glyph->metrics.vertBearingX = glyph->metrics.horiBearingX -
01739                                       glyph->metrics.horiAdvance / 2;
01740       glyph->metrics.vertBearingY = top;
01741       glyph->metrics.vertAdvance  = advance;
01742     }
01743 
01744     return 0;
01745   }
01746 
01747 
01748 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
01749 
01750   static FT_Error
01751   load_sbit_image( TT_Size       size,
01752                    TT_GlyphSlot  glyph,
01753                    FT_UInt       glyph_index,
01754                    FT_Int32      load_flags )
01755   {
01756     TT_Face             face;
01757     SFNT_Service        sfnt;
01758     FT_Stream           stream;
01759     FT_Error            error;
01760     TT_SBit_MetricsRec  metrics;
01761 
01762 
01763     face   = (TT_Face)glyph->face;
01764     sfnt   = (SFNT_Service)face->sfnt;
01765     stream = face->root.stream;
01766 
01767     error = sfnt->load_sbit_image( face,
01768                                    size->strike_index,
01769                                    glyph_index,
01770                                    (FT_Int)load_flags,
01771                                    stream,
01772                                    &glyph->bitmap,
01773                                    &metrics );
01774     if ( !error )
01775     {
01776       glyph->outline.n_points   = 0;
01777       glyph->outline.n_contours = 0;
01778 
01779       glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
01780       glyph->metrics.height = (FT_Pos)metrics.height << 6;
01781 
01782       glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
01783       glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
01784       glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
01785 
01786       glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
01787       glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
01788       glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
01789 
01790       glyph->format = FT_GLYPH_FORMAT_BITMAP;
01791 
01792       if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
01793       {
01794         glyph->bitmap_left = metrics.vertBearingX;
01795         glyph->bitmap_top  = metrics.vertBearingY;
01796       }
01797       else
01798       {
01799         glyph->bitmap_left = metrics.horiBearingX;
01800         glyph->bitmap_top  = metrics.horiBearingY;
01801       }
01802     }
01803 
01804     return error;
01805   }
01806 
01807 #endif 
01808 
01809 
01810   static FT_Error
01811   tt_loader_init( TT_Loader     loader,
01812                   TT_Size       size,
01813                   TT_GlyphSlot  glyph,
01814                   FT_Int32      load_flags,
01815                   FT_Bool       glyf_table_only )
01816   {
01817     TT_Face    face;
01818     FT_Stream  stream;
01819 
01820 
01821     face   = (TT_Face)glyph->face;
01822     stream = face->root.stream;
01823 
01824     FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
01825 
01826 #ifdef TT_USE_BYTECODE_INTERPRETER
01827 
01828     
01829     if ( IS_HINTED( load_flags ) && !glyf_table_only )
01830     {
01831       TT_ExecContext  exec;
01832       FT_Bool         grayscale;
01833 
01834 
01835       if ( !size->cvt_ready )
01836       {
01837         FT_Error  error = tt_size_ready_bytecode( size );
01838         if ( error )
01839           return error;
01840       }
01841 
01842       
01843       exec = size->debug ? size->context
01844                          : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
01845       if ( !exec )
01846         return TT_Err_Could_Not_Find_Context;
01847 
01848       grayscale =
01849         FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
01850 
01851       TT_Load_Context( exec, face, size );
01852 
01853       
01854       
01855       if ( grayscale != exec->grayscale )
01856       {
01857         FT_UInt  i;
01858 
01859 
01860         exec->grayscale = grayscale;
01861 
01862         for ( i = 0; i < size->cvt_size; i++ )
01863           size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
01864         tt_size_run_prep( size );
01865       }
01866 
01867       
01868       if ( exec->GS.instruct_control & 1 )
01869         load_flags |= FT_LOAD_NO_HINTING;
01870 
01871       
01872       if ( exec->GS.instruct_control & 2 )
01873         exec->GS = tt_default_graphics_state;
01874 
01875       exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
01876       loader->exec = exec;
01877       loader->instructions = exec->glyphIns;
01878     }
01879 
01880 #endif 
01881 
01882     
01883     
01884     
01885 
01886 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01887 
01888     if ( face->root.internal->incremental_interface )
01889       loader->glyf_offset = 0;
01890     else
01891 
01892 #endif
01893 
01894     {
01895       FT_Error  error = face->goto_table( face, TTAG_glyf, stream, 0 );
01896 
01897 
01898       if ( error == TT_Err_Table_Missing )
01899         loader->glyf_offset = 0;
01900       else if ( error )
01901       {
01902         FT_ERROR(( "tt_loader_init: could not access glyph table\n" ));
01903         return error;
01904       }
01905       else
01906         loader->glyf_offset = FT_STREAM_POS();
01907     }
01908 
01909     
01910     if ( !glyf_table_only )
01911     {
01912       FT_GlyphLoader  gloader = glyph->internal->loader;
01913 
01914 
01915       FT_GlyphLoader_Rewind( gloader );
01916       loader->gloader = gloader;
01917     }
01918 
01919     loader->load_flags = load_flags;
01920 
01921     loader->face   = (FT_Face)face;
01922     loader->size   = (FT_Size)size;
01923     loader->glyph  = (FT_GlyphSlot)glyph;
01924     loader->stream = stream;
01925 
01926     return TT_Err_Ok;
01927   }
01928 
01929 
01930   
01931   
01932   
01933   
01934   
01935   
01936   
01937   
01938   
01939   
01940   
01941   
01942   
01943   
01944   
01945   
01946   
01947   
01948   
01949   
01950   
01951   
01952   
01953   
01954   
01955   
01956   
01957   FT_LOCAL_DEF( FT_Error )
01958   TT_Load_Glyph( TT_Size       size,
01959                  TT_GlyphSlot  glyph,
01960                  FT_UInt       glyph_index,
01961                  FT_Int32      load_flags )
01962   {
01963     TT_Face       face;
01964     FT_Error      error;
01965     TT_LoaderRec  loader;
01966 
01967 
01968     face   = (TT_Face)glyph->face;
01969     error  = TT_Err_Ok;
01970 
01971 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
01972 
01973     
01974     
01975     
01976     
01977     if ( size->strike_index != 0xFFFFFFFFUL      &&
01978          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
01979     {
01980       error = load_sbit_image( size, glyph, glyph_index, load_flags );
01981       if ( !error )
01982       {
01983         FT_Face  root = &face->root;
01984 
01985 
01986         if ( FT_IS_SCALABLE( root ) )
01987         {
01988           
01989           (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
01990           (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
01991           glyph->linearHoriAdvance = loader.linear;
01992           glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
01993                                        loader.vadvance;
01994           if ( face->postscript.isFixedPitch                             &&
01995                ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
01996             glyph->linearHoriAdvance = face->horizontal.advance_Width_Max;
01997         }
01998 
01999         return TT_Err_Ok;
02000       }
02001     }
02002 
02003 #endif 
02004 
02005     
02006     if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
02007       return TT_Err_Invalid_Size_Handle;
02008 
02009     if ( load_flags & FT_LOAD_SBITS_ONLY )
02010       return TT_Err_Invalid_Argument;
02011 
02012     error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
02013     if ( error )
02014       return error;
02015 
02016     glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
02017     glyph->num_subglyphs = 0;
02018     glyph->outline.flags = 0;
02019 
02020     
02021     error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
02022     if ( !error )
02023     {
02024       if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
02025       {
02026         glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
02027         glyph->subglyphs     = loader.gloader->base.subglyphs;
02028       }
02029       else
02030       {
02031         glyph->outline        = loader.gloader->base.outline;
02032         glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
02033 
02034         
02035         
02036         if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x )
02037           FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
02038       }
02039 
02040 #ifdef TT_USE_BYTECODE_INTERPRETER
02041 
02042       if ( IS_HINTED( load_flags ) )
02043       {
02044         if ( loader.exec->GS.scan_control )
02045         {
02046           
02047           switch ( loader.exec->GS.scan_type )
02048           {
02049           case 0: 
02050             glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
02051             break;
02052           case 1: 
02053             
02054             break;
02055           case 4: 
02056             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
02057                                     FT_OUTLINE_INCLUDE_STUBS;
02058             break;
02059           case 5: 
02060             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
02061             break;
02062 
02063           default: 
02064             glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
02065             break;
02066           }
02067         }
02068         else
02069           glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
02070       }
02071 
02072 #endif 
02073 
02074       compute_glyph_metrics( &loader, glyph_index );
02075     }
02076 
02077     
02078     
02079     
02080     
02081     if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
02082          size->root.metrics.y_ppem < 24     )
02083       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
02084 
02085     return error;
02086   }
02087 
02088 
02089