ttgload.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ttgload.c                                                              */
00004 /*                                                                         */
00005 /*    TrueType Glyph Loader (body).                                        */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
00008 /*            2010 by                                                      */
00009 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00010 /*                                                                         */
00011 /*  This file is part of the FreeType project, and may only be used,       */
00012 /*  modified, and distributed under the terms of the FreeType project      */
00013 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00014 /*  this file you indicate that you have read the license and              */
00015 /*  understand and accept it fully.                                        */
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   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00041   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00042   /* messages during execution.                                            */
00043   /*                                                                       */
00044 #undef  FT_COMPONENT
00045 #define FT_COMPONENT  trace_ttgload
00046 
00047 
00048   /*************************************************************************/
00049   /*                                                                       */
00050   /* Composite font flags.                                                 */
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 /* reserved                        0x0010 */
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   /* Returns the horizontal metrics in font units for a given glyph.  If   */
00070   /* `check' is true, take care of monospaced fonts by returning the       */
00071   /* advance width maximum.                                                */
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   /* Returns the vertical metrics in font units for a given glyph.         */
00093   /* Greg Hitchcock from Microsoft told us that if there were no `vmtx'    */
00094   /* table, typoAscender/Descender from the `OS/2' table would be used     */
00095   /* instead, and if there were no `OS/2' table, use ascender/descender    */
00096   /* from the `hhea' table.  But that is not what Microsoft's rasterizer   */
00097   /* apparently does: It uses the ppem value as the advance height, and    */
00098   /* sets the top side bearing to be zero.                                 */
00099   /*                                                                       */
00100   /* The monospace `check' is probably not meaningful here, but we leave   */
00101   /* it in for a consistent interface.                                     */
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             /* Empirically determined, at variance with what MS said */
00116 
00117     else
00118     {
00119       *tsb = 0;
00120       *ah  = face->root.units_per_EM;
00121     }
00122 
00123 #else      /* This is what MS said to do.  It isn't what they do, however. */
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     /* If this is an incrementally loaded font check whether there are */
00167     /* overriding metrics for this glyph.                              */
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       /* GWW: Do I do the same for vertical metrics? */
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 /* 0 */
00206 
00207     }
00208 
00209   Exit:
00210 
00211 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
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   /* Translates an array of coordinates.                                   */
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   /* The following functions are used by default with TrueType fonts.      */
00256   /* However, they can be replaced by alternatives if we need to support   */
00257   /* TrueType-compressed formats (like MicroType) in the future.           */
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     /* for non-debug mode */
00271     FT_UNUSED( glyph_index );
00272 
00273 
00274     FT_TRACE5(( "Glyph %ld\n", glyph_index ));
00275 
00276     /* the following line sets the `error' variable through macros! */
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     /* check that we can add the contours to the glyph */
00347     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
00348     if ( error )
00349       goto Fail;
00350 
00351     /* reading the contours' endpoints & number of points */
00352     cont       = gloader->current.outline.contours;
00353     cont_limit = cont + n_contours;
00354 
00355     /* check space for contours array + instructions count */
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         /* unordered contours: this is invalid */
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     /* note that we will add four phantom points later */
00385     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
00386     if ( error )
00387       goto Fail;
00388 
00389     /* we'd better check the contours table right now */
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     /* reading the bytecode instructions */
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 /* TT_USE_BYTECODE_INTERPRETER */
00433 
00434     p += n_ins;
00435 
00436     /* reading the point tags */
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     /* reading the X coordinates */
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       /* the cast is for stupid compilers */
00498       *flag  = (FT_Byte)( f & ~( 2 | 16 ) );
00499     }
00500 
00501     /* reading the Y coordinates */
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       /* the cast is for stupid compilers */
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       /* check that we can load a new subglyph */
00571       error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
00572       if ( error )
00573         goto Fail;
00574 
00575       /* check space */
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       /* check space */
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       /* read arguments */
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       /* read transform */
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       /* we must undo the FT_FRAME_ENTER in order to point */
00652       /* to the composite instructions, if we find some.   */
00653       /* We will process them later.                       */
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   /* <Function>                                                            */
00704   /*    TT_Hint_Glyph                                                      */
00705   /*                                                                       */
00706   /* <Description>                                                         */
00707   /*    Hint the glyph using the zone prepared by the caller.  Note that   */
00708   /*    the zone is supposed to include four phantom points.               */
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     /* save original point position in org */
00741     if ( n_ins > 0 )
00742       FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
00743 
00744     /* Reset graphics state. */
00745     loader->exec->GS = ((TT_Size)loader->size)->GS;
00746 
00747     /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
00748     /*      completely refer to the (already) hinted subglyphs.     */
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     /* round pp2 and pp4 */
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       /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
00798       current_outline.tags[0] |=
00799         ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
00800     }
00801 
00802 #endif
00803 
00804     /* save glyph phantom points */
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   /* <Function>                                                            */
00820   /*    TT_Process_Simple_Glyph                                            */
00821   /*                                                                       */
00822   /* <Description>                                                         */
00823   /*    Once a simple glyph has been loaded, it needs to be processed.     */
00824   /*    Usually, this means scaling and hinting through bytecode           */
00825   /*    interpretation.                                                    */
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     /* set phantom points */
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       /* Deltas apply to the unscaled data. */
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 /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
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     /* scale the glyph */
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   /* <Function>                                                            */
00924   /*    TT_Process_Composite_Component                                     */
00925   /*                                                                       */
00926   /* <Description>                                                         */
00927   /*    Once a composite component has been loaded, it needs to be         */
00928   /*    processed.  Usually, this means transforming and translating.      */
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     /* perform the transform required for this subglyph */
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     /* get offset */
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       /* match l-th point of the newly loaded component to the k-th point */
00967       /* of the previously loaded components.                             */
00968 
00969       /* change to the point numbers used by our outline */
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   /* Use a default value dependent on                                     */
00991   /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old TT */
00992   /* fonts which don't set the xxx_COMPONENT_OFFSET bit.                  */
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   /* This algorithm is what Apple documents.  But it doesn't work.         */
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 /* 0 */
01028 
01029   /*************************************************************************/
01030   /*                                                                       */
01031   /* This algorithm is a guess and works much better than the above.       */
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 /* 0 */
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   /* <Function>                                                            */
01081   /*    TT_Process_Composite_Glyph                                         */
01082   /*                                                                       */
01083   /* <Description>                                                         */
01084   /*    This is slightly different from TT_Process_Simple_Glyph, in that   */
01085   /*    its sole purpose is to hint the glyph.  Thus this function is      */
01086   /*    only available when bytecode interpreter is enabled.               */
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     /* make room for phantom points */
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       /* TT_Load_Composite_Glyph only gives us the offset of instructions */
01125       /* so we read them here                                             */
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       /* check it */
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     /* Some points are likely touched during execution of  */
01156     /* instructions on components.  So let's untouch them. */
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   /* Calculate the four phantom points.                     */
01167   /* The first two stand for horizontal origin and advance. */
01168   /* The last two stand for vertical origin and advance.    */
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   /* <Function>                                                            */
01185   /*    load_truetype_glyph                                                */
01186   /*                                                                       */
01187   /* <Description>                                                         */
01188   /*    Loads a given truetype glyph.  Handles composites and uses a       */
01189   /*    TT_Loader object.                                                  */
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     /* some fonts have an incorrect value of `maxComponentDepth', */
01216     /* thus we allow depth 1 to catch the majority of them        */
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     /* check glyph index */
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     /* Set `offset' to the start of the glyph relative to the start of */
01247     /* the `glyf' table, and `byte_len' to the length of the glyph in  */
01248     /* bytes.                                                          */
01249 
01250 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01251 
01252     /* If we are loading glyph data via the incremental interface, set */
01253     /* the loader stream to a memory stream reading the data returned  */
01254     /* by the interface.                                               */
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 /* FT_CONFIG_OPTION_INCREMENTAL */
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       /* for the incremental interface, `glyf_offset' is always zero */
01284       if ( !loader->glyf_offset                        &&
01285            !face->root.internal->incremental_interface )
01286 #else
01287       if ( !loader->glyf_offset )
01288 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
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       /* read glyph header first */
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         /* this must be done before scaling */
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     /* if it is a simple glyph, load it */
01363 
01364     if ( loader->n_contours > 0 )
01365     {
01366       error = face->read_simple_glyph( loader );
01367       if ( error )
01368         goto Exit;
01369 
01370       /* all data have been read */
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     /* otherwise, load a composite! */
01386     else if ( loader->n_contours == -1 )
01387     {
01388       FT_UInt   start_point;
01389       FT_UInt   start_contour;
01390       FT_ULong  ins_pos;  /* position of composite instructions, if any */
01391 
01392 
01393       start_point   = gloader->base.outline.n_points;
01394       start_contour = gloader->base.outline.n_contours;
01395 
01396       /* for each subglyph, read composite header */
01397       error = face->read_composite_glyph( loader );
01398       if ( error )
01399         goto Exit;
01400 
01401       /* store the offset of instructions */
01402       ins_pos = loader->ins_pos;
01403 
01404       /* all data we need are read */
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         /* this provides additional offsets */
01418         /* for each component's translation */
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             /* XXX: overflow check for subglyph->{arg1,arg2}.   */
01435             /* deltas[i].{x,y} must be within signed 16-bit,    */
01436             /* but the restriction of summed delta is not clear */
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 /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
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       /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
01461       /* `as is' in the glyph slot (the client application will be     */
01462       /* responsible for interpreting these data)...                   */
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         /* read each subglyph independently */
01489         for ( n = 0; n < num_subglyphs; n++ )
01490         {
01491           FT_Vector  pp[4];
01492 
01493 
01494           /* Each time we call load_truetype_glyph in this loop, the   */
01495           /* value of `gloader.base.subglyphs' can change due to table */
01496           /* reallocations.  We thus need to recompute the subglyph    */
01497           /* pointer on each iteration.                                */
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           /* restore subglyph pointer */
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           /* gloader->base.outline consists of three parts:               */
01529           /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
01530           /*                                                              */
01531           /* (1): exists from the beginning                               */
01532           /* (2): components that have been loaded so far                 */
01533           /* (3): the newly loaded component                              */
01534           TT_Process_Composite_Component( loader, subglyph, start_point,
01535                                           num_base_points );
01536         }
01537 
01538         loader->stream = old_stream;
01539 
01540         /* process the glyph */
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       /* invalid composite count (negative but not -1) */
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     /* get the device-independent horizontal advance; it is scaled later */
01605     /* by the base layer.                                                */
01606     {
01607       FT_Pos  advance = loader->linear;
01608 
01609 
01610       /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
01611       /* correctly support DynaLab fonts, which have an incorrect       */
01612       /* `advance_Width_Max' field!  It is used, to my knowledge,       */
01613       /* exclusively in the X-TrueType font server.                     */
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       /* we need to return the advance in font units in linearHoriAdvance, */
01620       /* it will be scaled later by the base layer.                        */
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     /* adjust advance width to the value contained in the hdmx table */
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     /* set glyph dimensions */
01644     glyph->metrics.width  = bbox.xMax - bbox.xMin;
01645     glyph->metrics.height = bbox.yMax - bbox.yMin;
01646 
01647     /* Now take care of vertical metrics.  In the case where there is */
01648     /* no vertical information within the font (relatively common),   */
01649     /* create some metrics manually                                   */
01650     {
01651       FT_Pos  top;      /* scaled vertical top side bearing  */
01652       FT_Pos  advance;  /* scaled vertical advance height    */
01653 
01654 
01655       /* Get the unscaled top bearing and advance height. */
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         /* XXX Compute top side bearing and advance height in  */
01674         /*     Get_VMetrics instead of here.                   */
01675 
01676         /* NOTE: The OS/2 values are the only `portable' ones, */
01677         /*       which is why we use them, if there is an OS/2 */
01678         /*       table in the font.  Otherwise, we use the     */
01679         /*       values defined in the horizontal header.      */
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         /* If this is an incrementally loaded font see if there are */
01703         /* overriding metrics for this glyph.                       */
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       /* GWW: Do vertical metrics get loaded incrementally too? */
01723 
01724 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
01725 
01726       glyph->linearVertAdvance = advance;
01727 
01728       /* scale the metrics */
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       /* XXX: for now, we have no better algorithm for the lsb, but it */
01736       /*      should work fine.                                        */
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 /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
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     /* load execution context */
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       /* query new execution context */
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       /* a change from mono to grayscale rendering (and vice versa) */
01854       /* requires a re-execution of the CVT program                 */
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       /* see whether the cvt program has disabled hinting */
01868       if ( exec->GS.instruct_control & 1 )
01869         load_flags |= FT_LOAD_NO_HINTING;
01870 
01871       /* load default graphics state -- if needed */
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 /* TT_USE_BYTECODE_INTERPRETER */
01881 
01882     /* seek to the beginning of the glyph table -- for Type 42 fonts     */
01883     /* the table might be accessed from a Postscript stream or something */
01884     /* else...                                                           */
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     /* get face's glyph loader */
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   /* <Function>                                                            */
01933   /*    TT_Load_Glyph                                                      */
01934   /*                                                                       */
01935   /* <Description>                                                         */
01936   /*    A function used to load a single glyph within a given glyph slot,  */
01937   /*    for a given size.                                                  */
01938   /*                                                                       */
01939   /* <Input>                                                               */
01940   /*    glyph       :: A handle to a target slot object where the glyph    */
01941   /*                   will be loaded.                                     */
01942   /*                                                                       */
01943   /*    size        :: A handle to the source face size at which the glyph */
01944   /*                   must be scaled/loaded.                              */
01945   /*                                                                       */
01946   /*    glyph_index :: The index of the glyph in the font file.            */
01947   /*                                                                       */
01948   /*    load_flags  :: A flag indicating what to load for this glyph.  The */
01949   /*                   FT_LOAD_XXX constants can be used to control the    */
01950   /*                   glyph loading process (e.g., whether the outline    */
01951   /*                   should be scaled, whether to load bitmaps or not,   */
01952   /*                   whether to hint the outline, etc).                  */
01953   /*                                                                       */
01954   /* <Return>                                                              */
01955   /*    FreeType error code.  0 means success.                             */
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     /* try to load embedded bitmap if any              */
01974     /*                                                 */
01975     /* XXX: The convention should be emphasized in     */
01976     /*      the documents because it can be confusing. */
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           /* for the bbox we need the header only */
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 /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
02004 
02005     /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
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     /* main loading loop */
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         /* In case bit 1 of the `flags' field in the `head' table isn't */
02035         /* set, translate array so that (0,0) is the glyph's origin.    */
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           /* convert scan conversion mode to FT_OUTLINE_XXX flags */
02047           switch ( loader.exec->GS.scan_type )
02048           {
02049           case 0: /* simple drop-outs including stubs */
02050             glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
02051             break;
02052           case 1: /* simple drop-outs excluding stubs */
02053             /* nothing; it's the default rendering mode */
02054             break;
02055           case 4: /* smart drop-outs including stubs */
02056             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
02057                                     FT_OUTLINE_INCLUDE_STUBS;
02058             break;
02059           case 5: /* smart drop-outs excluding stubs  */
02060             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
02061             break;
02062 
02063           default: /* no drop-out control */
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 /* TT_USE_BYTECODE_INTERPRETER */
02073 
02074       compute_glyph_metrics( &loader, glyph_index );
02075     }
02076 
02077     /* Set the `high precision' bit flag.                           */
02078     /* This is _critical_ to get correct output for monochrome      */
02079     /* TrueType glyphs at all sizes using the bytecode interpreter. */
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 /* END */

Generated on Tue Jul 5 14:13:53 2011 for ROOT_528-00b_version by  doxygen 1.5.1