ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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     loader->left_bearing = left_bearing;
00165     loader->advance      = advance_width;
00166     loader->top_bearing  = top_bearing;
00167     loader->vadvance     = advance_height;
00168 
00169     if ( !loader->linear_def )
00170     {
00171       loader->linear_def = 1;
00172       loader->linear     = advance_width;
00173     }
00174   }
00175 
00176 
00177 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00178 
00179   static void
00180   tt_get_metrics_incr_overrides( TT_Loader  loader,
00181                                  FT_UInt    glyph_index )
00182   {
00183     TT_Face  face = (TT_Face)loader->face;
00184 
00185     FT_Short   left_bearing = 0, top_bearing = 0;
00186     FT_UShort  advance_width = 0, advance_height = 0;
00187 
00188 
00189     /* If this is an incrementally loaded font check whether there are */
00190     /* overriding metrics for this glyph.                              */
00191     if ( face->root.internal->incremental_interface                           &&
00192          face->root.internal->incremental_interface->funcs->get_glyph_metrics )
00193     {
00194       FT_Incremental_MetricsRec  metrics;
00195       FT_Error                   error;
00196 
00197 
00198       metrics.bearing_x = loader->left_bearing;
00199       metrics.bearing_y = 0;
00200       metrics.advance   = loader->advance;
00201       metrics.advance_v = 0;
00202 
00203       error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
00204                 face->root.internal->incremental_interface->object,
00205                 glyph_index, FALSE, &metrics );
00206       if ( error )
00207         goto Exit;
00208 
00209       left_bearing  = (FT_Short)metrics.bearing_x;
00210       advance_width = (FT_UShort)metrics.advance;
00211 
00212 #if 0
00213 
00214       /* GWW: Do I do the same for vertical metrics? */
00215       metrics.bearing_x = 0;
00216       metrics.bearing_y = loader->top_bearing;
00217       metrics.advance   = loader->vadvance;
00218 
00219       error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
00220                 face->root.internal->incremental_interface->object,
00221                 glyph_index, TRUE, &metrics );
00222       if ( error )
00223         goto Exit;
00224 
00225       top_bearing    = (FT_Short)metrics.bearing_y;
00226       advance_height = (FT_UShort)metrics.advance;
00227 
00228 #endif /* 0 */
00229 
00230       loader->left_bearing = left_bearing;
00231       loader->advance      = advance_width;
00232       loader->top_bearing  = top_bearing;
00233       loader->vadvance     = advance_height;
00234 
00235       if ( !loader->linear_def )
00236       {
00237         loader->linear_def = 1;
00238         loader->linear     = advance_width;
00239       }
00240     }
00241 
00242   Exit:
00243     return;
00244   }
00245 
00246 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
00247 
00248 
00249   /*************************************************************************/
00250   /*                                                                       */
00251   /* Translates an array of coordinates.                                   */
00252   /*                                                                       */
00253   static void
00254   translate_array( FT_UInt     n,
00255                    FT_Vector*  coords,
00256                    FT_Pos      delta_x,
00257                    FT_Pos      delta_y )
00258   {
00259     FT_UInt  k;
00260 
00261 
00262     if ( delta_x )
00263       for ( k = 0; k < n; k++ )
00264         coords[k].x += delta_x;
00265 
00266     if ( delta_y )
00267       for ( k = 0; k < n; k++ )
00268         coords[k].y += delta_y;
00269   }
00270 
00271 
00272 #undef  IS_HINTED
00273 #define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
00274 
00275 
00276   /*************************************************************************/
00277   /*                                                                       */
00278   /* The following functions are used by default with TrueType fonts.      */
00279   /* However, they can be replaced by alternatives if we need to support   */
00280   /* TrueType-compressed formats (like MicroType) in the future.           */
00281   /*                                                                       */
00282   /*************************************************************************/
00283 
00284   FT_CALLBACK_DEF( FT_Error )
00285   TT_Access_Glyph_Frame( TT_Loader  loader,
00286                          FT_UInt    glyph_index,
00287                          FT_ULong   offset,
00288                          FT_UInt    byte_count )
00289   {
00290     FT_Error   error;
00291     FT_Stream  stream = loader->stream;
00292 
00293     /* for non-debug mode */
00294     FT_UNUSED( glyph_index );
00295 
00296 
00297     FT_TRACE4(( "Glyph %ld\n", glyph_index ));
00298 
00299     /* the following line sets the `error' variable through macros! */
00300     if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
00301       return error;
00302 
00303     loader->cursor = stream->cursor;
00304     loader->limit  = stream->limit;
00305 
00306     return TT_Err_Ok;
00307   }
00308 
00309 
00310   FT_CALLBACK_DEF( void )
00311   TT_Forget_Glyph_Frame( TT_Loader  loader )
00312   {
00313     FT_Stream  stream = loader->stream;
00314 
00315 
00316     FT_FRAME_EXIT();
00317   }
00318 
00319 
00320   FT_CALLBACK_DEF( FT_Error )
00321   TT_Load_Glyph_Header( TT_Loader  loader )
00322   {
00323     FT_Byte*  p     = loader->cursor;
00324     FT_Byte*  limit = loader->limit;
00325 
00326 
00327     if ( p + 10 > limit )
00328       return TT_Err_Invalid_Outline;
00329 
00330     loader->n_contours = FT_NEXT_SHORT( p );
00331 
00332     loader->bbox.xMin = FT_NEXT_SHORT( p );
00333     loader->bbox.yMin = FT_NEXT_SHORT( p );
00334     loader->bbox.xMax = FT_NEXT_SHORT( p );
00335     loader->bbox.yMax = FT_NEXT_SHORT( p );
00336 
00337     FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
00338     FT_TRACE5(( "  xMin: %4d  xMax: %4d\n", loader->bbox.xMin,
00339                                             loader->bbox.xMax ));
00340     FT_TRACE5(( "  yMin: %4d  yMax: %4d\n", loader->bbox.yMin,
00341                                             loader->bbox.yMax ));
00342     loader->cursor = p;
00343 
00344     return TT_Err_Ok;
00345   }
00346 
00347 
00348   FT_CALLBACK_DEF( FT_Error )
00349   TT_Load_Simple_Glyph( TT_Loader  load )
00350   {
00351     FT_Error        error;
00352     FT_Byte*        p          = load->cursor;
00353     FT_Byte*        limit      = load->limit;
00354     FT_GlyphLoader  gloader    = load->gloader;
00355     FT_Int          n_contours = load->n_contours;
00356     FT_Outline*     outline;
00357     TT_Face         face       = (TT_Face)load->face;
00358     FT_UShort       n_ins;
00359     FT_Int          n_points;
00360 
00361     FT_Byte         *flag, *flag_limit;
00362     FT_Byte         c, count;
00363     FT_Vector       *vec, *vec_limit;
00364     FT_Pos          x;
00365     FT_Short        *cont, *cont_limit, prev_cont;
00366     FT_Int          xy_size = 0;
00367 
00368 
00369     /* check that we can add the contours to the glyph */
00370     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
00371     if ( error )
00372       goto Fail;
00373 
00374     /* reading the contours' endpoints & number of points */
00375     cont       = gloader->current.outline.contours;
00376     cont_limit = cont + n_contours;
00377 
00378     /* check space for contours array + instructions count */
00379     if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
00380       goto Invalid_Outline;
00381 
00382     prev_cont = FT_NEXT_USHORT( p );
00383 
00384     if ( n_contours > 0 )
00385       cont[0] = prev_cont;
00386 
00387     for ( cont++; cont < cont_limit; cont++ )
00388     {
00389       cont[0] = FT_NEXT_USHORT( p );
00390       if ( cont[0] <= prev_cont )
00391       {
00392         /* unordered contours: this is invalid */
00393         error = TT_Err_Invalid_Table;
00394         goto Fail;
00395       }
00396       prev_cont = cont[0];
00397     }
00398 
00399     n_points = 0;
00400     if ( n_contours > 0 )
00401     {
00402       n_points = cont[-1] + 1;
00403       if ( n_points < 0 )
00404         goto Invalid_Outline;
00405     }
00406 
00407     /* note that we will add four phantom points later */
00408     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
00409     if ( error )
00410       goto Fail;
00411 
00412     /* we'd better check the contours table right now */
00413     outline = &gloader->current.outline;
00414 
00415     for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
00416       if ( cont[-1] >= cont[0] )
00417         goto Invalid_Outline;
00418 
00419     /* reading the bytecode instructions */
00420     load->glyph->control_len  = 0;
00421     load->glyph->control_data = 0;
00422 
00423     if ( p + 2 > limit )
00424       goto Invalid_Outline;
00425 
00426     n_ins = FT_NEXT_USHORT( p );
00427 
00428     FT_TRACE5(( "  Instructions size: %u\n", n_ins ));
00429 
00430     if ( n_ins > face->max_profile.maxSizeOfInstructions )
00431     {
00432       FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
00433                   n_ins ));
00434       error = TT_Err_Too_Many_Hints;
00435       goto Fail;
00436     }
00437 
00438     if ( ( limit - p ) < n_ins )
00439     {
00440       FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
00441       error = TT_Err_Too_Many_Hints;
00442       goto Fail;
00443     }
00444 
00445 #ifdef TT_USE_BYTECODE_INTERPRETER
00446 
00447     if ( IS_HINTED( load->load_flags ) )
00448     {
00449       load->glyph->control_len  = n_ins;
00450       load->glyph->control_data = load->exec->glyphIns;
00451 
00452       FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
00453     }
00454 
00455 #endif /* TT_USE_BYTECODE_INTERPRETER */
00456 
00457     p += n_ins;
00458 
00459     /* reading the point tags */
00460     flag       = (FT_Byte*)outline->tags;
00461     flag_limit = flag + n_points;
00462 
00463     FT_ASSERT( flag != NULL );
00464 
00465     while ( flag < flag_limit )
00466     {
00467       if ( p + 1 > limit )
00468         goto Invalid_Outline;
00469 
00470       *flag++ = c = FT_NEXT_BYTE( p );
00471       if ( c & 8 )
00472       {
00473         if ( p + 1 > limit )
00474           goto Invalid_Outline;
00475 
00476         count = FT_NEXT_BYTE( p );
00477         if ( flag + (FT_Int)count > flag_limit )
00478           goto Invalid_Outline;
00479 
00480         for ( ; count > 0; count-- )
00481           *flag++ = c;
00482       }
00483     }
00484 
00485     /* reading the X coordinates */
00486 
00487     vec       = outline->points;
00488     vec_limit = vec + n_points;
00489     flag      = (FT_Byte*)outline->tags;
00490     x         = 0;
00491 
00492     if ( p + xy_size > limit )
00493       goto Invalid_Outline;
00494 
00495     for ( ; vec < vec_limit; vec++, flag++ )
00496     {
00497       FT_Pos   y = 0;
00498       FT_Byte  f = *flag;
00499 
00500 
00501       if ( f & 2 )
00502       {
00503         if ( p + 1 > limit )
00504           goto Invalid_Outline;
00505 
00506         y = (FT_Pos)FT_NEXT_BYTE( p );
00507         if ( ( f & 16 ) == 0 )
00508           y = -y;
00509       }
00510       else if ( ( f & 16 ) == 0 )
00511       {
00512         if ( p + 2 > limit )
00513           goto Invalid_Outline;
00514 
00515         y = (FT_Pos)FT_NEXT_SHORT( p );
00516       }
00517 
00518       x     += y;
00519       vec->x = x;
00520       /* the cast is for stupid compilers */
00521       *flag  = (FT_Byte)( f & ~( 2 | 16 ) );
00522     }
00523 
00524     /* reading the Y coordinates */
00525 
00526     vec       = gloader->current.outline.points;
00527     vec_limit = vec + n_points;
00528     flag      = (FT_Byte*)outline->tags;
00529     x         = 0;
00530 
00531     for ( ; vec < vec_limit; vec++, flag++ )
00532     {
00533       FT_Pos   y = 0;
00534       FT_Byte  f = *flag;
00535 
00536 
00537       if ( f & 4 )
00538       {
00539         if ( p + 1 > limit )
00540           goto Invalid_Outline;
00541 
00542         y = (FT_Pos)FT_NEXT_BYTE( p );
00543         if ( ( f & 32 ) == 0 )
00544           y = -y;
00545       }
00546       else if ( ( f & 32 ) == 0 )
00547       {
00548         if ( p + 2 > limit )
00549           goto Invalid_Outline;
00550 
00551         y = (FT_Pos)FT_NEXT_SHORT( p );
00552       }
00553 
00554       x     += y;
00555       vec->y = x;
00556       /* the cast is for stupid compilers */
00557       *flag  = (FT_Byte)( f & FT_CURVE_TAG_ON );
00558     }
00559 
00560     outline->n_points   = (FT_UShort)n_points;
00561     outline->n_contours = (FT_Short) n_contours;
00562 
00563     load->cursor = p;
00564 
00565   Fail:
00566     return error;
00567 
00568   Invalid_Outline:
00569     error = TT_Err_Invalid_Outline;
00570     goto Fail;
00571   }
00572 
00573 
00574   FT_CALLBACK_DEF( FT_Error )
00575   TT_Load_Composite_Glyph( TT_Loader  loader )
00576   {
00577     FT_Error        error;
00578     FT_Byte*        p       = loader->cursor;
00579     FT_Byte*        limit   = loader->limit;
00580     FT_GlyphLoader  gloader = loader->gloader;
00581     FT_SubGlyph     subglyph;
00582     FT_UInt         num_subglyphs;
00583 
00584 
00585     num_subglyphs = 0;
00586 
00587     do
00588     {
00589       FT_Fixed  xx, xy, yy, yx;
00590       FT_UInt   count;
00591 
00592 
00593       /* check that we can load a new subglyph */
00594       error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
00595       if ( error )
00596         goto Fail;
00597 
00598       /* check space */
00599       if ( p + 4 > limit )
00600         goto Invalid_Composite;
00601 
00602       subglyph = gloader->current.subglyphs + num_subglyphs;
00603 
00604       subglyph->arg1 = subglyph->arg2 = 0;
00605 
00606       subglyph->flags = FT_NEXT_USHORT( p );
00607       subglyph->index = FT_NEXT_USHORT( p );
00608 
00609       /* check space */
00610       count = 2;
00611       if ( subglyph->flags & ARGS_ARE_WORDS )
00612         count += 2;
00613       if ( subglyph->flags & WE_HAVE_A_SCALE )
00614         count += 2;
00615       else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
00616         count += 4;
00617       else if ( subglyph->flags & WE_HAVE_A_2X2 )
00618         count += 8;
00619 
00620       if ( p + count > limit )
00621         goto Invalid_Composite;
00622 
00623       /* read arguments */
00624       if ( subglyph->flags & ARGS_ARE_WORDS )
00625       {
00626         subglyph->arg1 = FT_NEXT_SHORT( p );
00627         subglyph->arg2 = FT_NEXT_SHORT( p );
00628       }
00629       else
00630       {
00631         subglyph->arg1 = FT_NEXT_CHAR( p );
00632         subglyph->arg2 = FT_NEXT_CHAR( p );
00633       }
00634 
00635       /* read transform */
00636       xx = yy = 0x10000L;
00637       xy = yx = 0;
00638 
00639       if ( subglyph->flags & WE_HAVE_A_SCALE )
00640       {
00641         xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00642         yy = xx;
00643       }
00644       else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
00645       {
00646         xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00647         yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00648       }
00649       else if ( subglyph->flags & WE_HAVE_A_2X2 )
00650       {
00651         xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00652         yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00653         xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00654         yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00655       }
00656 
00657       subglyph->transform.xx = xx;
00658       subglyph->transform.xy = xy;
00659       subglyph->transform.yx = yx;
00660       subglyph->transform.yy = yy;
00661 
00662       num_subglyphs++;
00663 
00664     } while ( subglyph->flags & MORE_COMPONENTS );
00665 
00666     gloader->current.num_subglyphs = num_subglyphs;
00667 
00668 #ifdef TT_USE_BYTECODE_INTERPRETER
00669 
00670     {
00671       FT_Stream  stream = loader->stream;
00672 
00673 
00674       /* we must undo the FT_FRAME_ENTER in order to point */
00675       /* to the composite instructions, if we find some.   */
00676       /* We will process them later.                       */
00677       /*                                                   */
00678       loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
00679                                     p - limit );
00680     }
00681 
00682 #endif
00683 
00684     loader->cursor = p;
00685 
00686   Fail:
00687     return error;
00688 
00689   Invalid_Composite:
00690     error = TT_Err_Invalid_Composite;
00691     goto Fail;
00692   }
00693 
00694 
00695   FT_LOCAL_DEF( void )
00696   TT_Init_Glyph_Loading( TT_Face  face )
00697   {
00698     face->access_glyph_frame   = TT_Access_Glyph_Frame;
00699     face->read_glyph_header    = TT_Load_Glyph_Header;
00700     face->read_simple_glyph    = TT_Load_Simple_Glyph;
00701     face->read_composite_glyph = TT_Load_Composite_Glyph;
00702     face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
00703   }
00704 
00705 
00706   static void
00707   tt_prepare_zone( TT_GlyphZone  zone,
00708                    FT_GlyphLoad  load,
00709                    FT_UInt       start_point,
00710                    FT_UInt       start_contour )
00711   {
00712     zone->n_points    = (FT_UShort)( load->outline.n_points - start_point );
00713     zone->n_contours  = (FT_Short) ( load->outline.n_contours -
00714                                        start_contour );
00715     zone->org         = load->extra_points + start_point;
00716     zone->cur         = load->outline.points + start_point;
00717     zone->orus        = load->extra_points2 + start_point;
00718     zone->tags        = (FT_Byte*)load->outline.tags + start_point;
00719     zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
00720     zone->first_point = (FT_UShort)start_point;
00721   }
00722 
00723 
00724   /*************************************************************************/
00725   /*                                                                       */
00726   /* <Function>                                                            */
00727   /*    TT_Hint_Glyph                                                      */
00728   /*                                                                       */
00729   /* <Description>                                                         */
00730   /*    Hint the glyph using the zone prepared by the caller.  Note that   */
00731   /*    the zone is supposed to include four phantom points.               */
00732   /*                                                                       */
00733   static FT_Error
00734   TT_Hint_Glyph( TT_Loader  loader,
00735                  FT_Bool    is_composite )
00736   {
00737     TT_GlyphZone  zone = &loader->zone;
00738     FT_Pos        origin;
00739 
00740 #ifdef TT_USE_BYTECODE_INTERPRETER
00741     FT_UInt       n_ins;
00742 #else
00743     FT_UNUSED( is_composite );
00744 #endif
00745 
00746 
00747 #ifdef TT_USE_BYTECODE_INTERPRETER
00748     if ( loader->glyph->control_len > 0xFFFFL )
00749     {
00750       FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));
00751       FT_TRACE1(( "(0x%lx byte) is truncated\n",
00752                  loader->glyph->control_len ));
00753     }
00754     n_ins = (FT_UInt)( loader->glyph->control_len );
00755 #endif
00756 
00757     origin = zone->cur[zone->n_points - 4].x;
00758     origin = FT_PIX_ROUND( origin ) - origin;
00759     if ( origin )
00760       translate_array( zone->n_points, zone->cur, origin, 0 );
00761 
00762 #ifdef TT_USE_BYTECODE_INTERPRETER
00763     /* save original point position in org */
00764     if ( n_ins > 0 )
00765       FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
00766 
00767     /* Reset graphics state. */
00768     loader->exec->GS = ((TT_Size)loader->size)->GS;
00769 
00770     /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
00771     /*      completely refer to the (already) hinted subglyphs.     */
00772     if ( is_composite )
00773     {
00774       loader->exec->metrics.x_scale = 1 << 16;
00775       loader->exec->metrics.y_scale = 1 << 16;
00776 
00777       FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
00778     }
00779     else
00780     {
00781       loader->exec->metrics.x_scale =
00782         ((TT_Size)loader->size)->metrics.x_scale;
00783       loader->exec->metrics.y_scale =
00784         ((TT_Size)loader->size)->metrics.y_scale;
00785     }
00786 #endif
00787 
00788     /* round pp2 and pp4 */
00789     zone->cur[zone->n_points - 3].x =
00790       FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
00791     zone->cur[zone->n_points - 1].y =
00792       FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
00793 
00794 #ifdef TT_USE_BYTECODE_INTERPRETER
00795 
00796     if ( n_ins > 0 )
00797     {
00798       FT_Bool   debug;
00799       FT_Error  error;
00800 
00801       FT_GlyphLoader  gloader         = loader->gloader;
00802       FT_Outline      current_outline = gloader->current.outline;
00803 
00804 
00805       error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
00806                                 loader->exec->glyphIns, n_ins );
00807       if ( error )
00808         return error;
00809 
00810       loader->exec->is_composite = is_composite;
00811       loader->exec->pts          = *zone;
00812 
00813       debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
00814                        ((TT_Size)loader->size)->debug             );
00815 
00816       error = TT_Run_Context( loader->exec, debug );
00817       if ( error && loader->exec->pedantic_hinting )
00818         return error;
00819 
00820       /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
00821       current_outline.tags[0] |=
00822         ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
00823     }
00824 
00825 #endif
00826 
00827     /* save glyph phantom points */
00828     if ( !loader->preserve_pps )
00829     {
00830       loader->pp1 = zone->cur[zone->n_points - 4];
00831       loader->pp2 = zone->cur[zone->n_points - 3];
00832       loader->pp3 = zone->cur[zone->n_points - 2];
00833       loader->pp4 = zone->cur[zone->n_points - 1];
00834     }
00835 
00836     return TT_Err_Ok;
00837   }
00838 
00839 
00840   /*************************************************************************/
00841   /*                                                                       */
00842   /* <Function>                                                            */
00843   /*    TT_Process_Simple_Glyph                                            */
00844   /*                                                                       */
00845   /* <Description>                                                         */
00846   /*    Once a simple glyph has been loaded, it needs to be processed.     */
00847   /*    Usually, this means scaling and hinting through bytecode           */
00848   /*    interpretation.                                                    */
00849   /*                                                                       */
00850   static FT_Error
00851   TT_Process_Simple_Glyph( TT_Loader  loader )
00852   {
00853     FT_GlyphLoader  gloader = loader->gloader;
00854     FT_Error        error   = TT_Err_Ok;
00855     FT_Outline*     outline;
00856     FT_Int          n_points;
00857 
00858 
00859     outline  = &gloader->current.outline;
00860     n_points = outline->n_points;
00861 
00862     /* set phantom points */
00863 
00864     outline->points[n_points    ] = loader->pp1;
00865     outline->points[n_points + 1] = loader->pp2;
00866     outline->points[n_points + 2] = loader->pp3;
00867     outline->points[n_points + 3] = loader->pp4;
00868 
00869     outline->tags[n_points    ] = 0;
00870     outline->tags[n_points + 1] = 0;
00871     outline->tags[n_points + 2] = 0;
00872     outline->tags[n_points + 3] = 0;
00873 
00874     n_points += 4;
00875 
00876 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00877 
00878     if ( ((TT_Face)loader->face)->doblend )
00879     {
00880       /* Deltas apply to the unscaled data. */
00881       FT_Vector*  deltas;
00882       FT_Memory   memory = loader->face->memory;
00883       FT_Int      i;
00884 
00885 
00886       error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
00887                                         loader->glyph_index,
00888                                         &deltas,
00889                                         n_points );
00890       if ( error )
00891         return error;
00892 
00893       for ( i = 0; i < n_points; ++i )
00894       {
00895         outline->points[i].x += deltas[i].x;
00896         outline->points[i].y += deltas[i].y;
00897       }
00898 
00899       FT_FREE( deltas );
00900     }
00901 
00902 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
00903 
00904     if ( IS_HINTED( loader->load_flags ) )
00905     {
00906       tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
00907 
00908       FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
00909                      loader->zone.n_points + 4 );
00910     }
00911 
00912     /* scale the glyph */
00913     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
00914     {
00915       FT_Vector*  vec     = outline->points;
00916       FT_Vector*  limit   = outline->points + n_points;
00917       FT_Fixed    x_scale = ((TT_Size)loader->size)->metrics.x_scale;
00918       FT_Fixed    y_scale = ((TT_Size)loader->size)->metrics.y_scale;
00919 
00920 
00921       for ( ; vec < limit; vec++ )
00922       {
00923         vec->x = FT_MulFix( vec->x, x_scale );
00924         vec->y = FT_MulFix( vec->y, y_scale );
00925       }
00926 
00927       loader->pp1 = outline->points[n_points - 4];
00928       loader->pp2 = outline->points[n_points - 3];
00929       loader->pp3 = outline->points[n_points - 2];
00930       loader->pp4 = outline->points[n_points - 1];
00931     }
00932 
00933     if ( IS_HINTED( loader->load_flags ) )
00934     {
00935       loader->zone.n_points += 4;
00936 
00937       error = TT_Hint_Glyph( loader, 0 );
00938     }
00939 
00940     return error;
00941   }
00942 
00943 
00944   /*************************************************************************/
00945   /*                                                                       */
00946   /* <Function>                                                            */
00947   /*    TT_Process_Composite_Component                                     */
00948   /*                                                                       */
00949   /* <Description>                                                         */
00950   /*    Once a composite component has been loaded, it needs to be         */
00951   /*    processed.  Usually, this means transforming and translating.      */
00952   /*                                                                       */
00953   static FT_Error
00954   TT_Process_Composite_Component( TT_Loader    loader,
00955                                   FT_SubGlyph  subglyph,
00956                                   FT_UInt      start_point,
00957                                   FT_UInt      num_base_points )
00958   {
00959     FT_GlyphLoader  gloader    = loader->gloader;
00960     FT_Vector*      base_vec   = gloader->base.outline.points;
00961     FT_UInt         num_points = gloader->base.outline.n_points;
00962     FT_Bool         have_scale;
00963     FT_Pos          x, y;
00964 
00965 
00966     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
00967                                               WE_HAVE_AN_XY_SCALE |
00968                                               WE_HAVE_A_2X2       ) );
00969 
00970     /* perform the transform required for this subglyph */
00971     if ( have_scale )
00972     {
00973       FT_UInt  i;
00974 
00975 
00976       for ( i = num_base_points; i < num_points; i++ )
00977         FT_Vector_Transform( base_vec + i, &subglyph->transform );
00978     }
00979 
00980     /* get offset */
00981     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
00982     {
00983       FT_UInt     k = subglyph->arg1;
00984       FT_UInt     l = subglyph->arg2;
00985       FT_Vector*  p1;
00986       FT_Vector*  p2;
00987 
00988 
00989       /* match l-th point of the newly loaded component to the k-th point */
00990       /* of the previously loaded components.                             */
00991 
00992       /* change to the point numbers used by our outline */
00993       k += start_point;
00994       l += num_base_points;
00995       if ( k >= num_base_points ||
00996            l >= num_points      )
00997         return TT_Err_Invalid_Composite;
00998 
00999       p1 = gloader->base.outline.points + k;
01000       p2 = gloader->base.outline.points + l;
01001 
01002       x = p1->x - p2->x;
01003       y = p1->y - p2->y;
01004     }
01005     else
01006     {
01007       x = subglyph->arg1;
01008       y = subglyph->arg2;
01009 
01010       if ( !x && !y )
01011         return TT_Err_Ok;
01012 
01013   /* Use a default value dependent on                                     */
01014   /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old TT */
01015   /* fonts which don't set the xxx_COMPONENT_OFFSET bit.                  */
01016 
01017       if ( have_scale &&
01018 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
01019            !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
01020 #else
01021             ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
01022 #endif
01023       {
01024 
01025 #if 0
01026 
01027   /*************************************************************************/
01028   /*                                                                       */
01029   /* This algorithm is what Apple documents.  But it doesn't work.         */
01030   /*                                                                       */
01031         int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
01032                                             : -subglyph->transform.xx;
01033         int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
01034                                             : -subglyph->transform.yx;
01035         int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
01036                                             : -subglyph->transform.xy;
01037         int  d = subglyph->transform.yy > 0 ? subglyph->transform.yy
01038                                             : -subglyph->transform.yy;
01039         int  m = a > b ? a : b;
01040         int  n = c > d ? c : d;
01041 
01042 
01043         if ( a - b <= 33 && a - b >= -33 )
01044           m *= 2;
01045         if ( c - d <= 33 && c - d >= -33 )
01046           n *= 2;
01047         x = FT_MulFix( x, m );
01048         y = FT_MulFix( y, n );
01049 
01050 #else /* 0 */
01051 
01052   /*************************************************************************/
01053   /*                                                                       */
01054   /* This algorithm is a guess and works much better than the above.       */
01055   /*                                                                       */
01056         FT_Fixed  mac_xscale = FT_SqrtFixed(
01057                                  (FT_Int32)FT_MulFix( subglyph->transform.xx,
01058                                                       subglyph->transform.xx ) +
01059                                  (FT_Int32)FT_MulFix( subglyph->transform.xy,
01060                                                       subglyph->transform.xy ) );
01061         FT_Fixed  mac_yscale = FT_SqrtFixed(
01062                                  (FT_Int32)FT_MulFix( subglyph->transform.yy,
01063                                                       subglyph->transform.yy ) +
01064                                  (FT_Int32)FT_MulFix( subglyph->transform.yx,
01065                                                       subglyph->transform.yx ) );
01066 
01067 
01068         x = FT_MulFix( x, mac_xscale );
01069         y = FT_MulFix( y, mac_yscale );
01070 
01071 #endif /* 0 */
01072 
01073       }
01074 
01075       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
01076       {
01077         FT_Fixed  x_scale = ((TT_Size)loader->size)->metrics.x_scale;
01078         FT_Fixed  y_scale = ((TT_Size)loader->size)->metrics.y_scale;
01079 
01080 
01081         x = FT_MulFix( x, x_scale );
01082         y = FT_MulFix( y, y_scale );
01083 
01084         if ( subglyph->flags & ROUND_XY_TO_GRID )
01085         {
01086           x = FT_PIX_ROUND( x );
01087           y = FT_PIX_ROUND( y );
01088         }
01089       }
01090     }
01091 
01092     if ( x || y )
01093       translate_array( num_points - num_base_points,
01094                        base_vec + num_base_points,
01095                        x, y );
01096 
01097     return TT_Err_Ok;
01098   }
01099 
01100 
01101   /*************************************************************************/
01102   /*                                                                       */
01103   /* <Function>                                                            */
01104   /*    TT_Process_Composite_Glyph                                         */
01105   /*                                                                       */
01106   /* <Description>                                                         */
01107   /*    This is slightly different from TT_Process_Simple_Glyph, in that   */
01108   /*    its sole purpose is to hint the glyph.  Thus this function is      */
01109   /*    only available when bytecode interpreter is enabled.               */
01110   /*                                                                       */
01111   static FT_Error
01112   TT_Process_Composite_Glyph( TT_Loader  loader,
01113                               FT_UInt    start_point,
01114                               FT_UInt    start_contour )
01115   {
01116     FT_Error     error;
01117     FT_Outline*  outline;
01118     FT_UInt      i;
01119 
01120 
01121     outline = &loader->gloader->base.outline;
01122 
01123     /* make room for phantom points */
01124     error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
01125                                          outline->n_points + 4,
01126                                          0 );
01127     if ( error )
01128       return error;
01129 
01130     outline->points[outline->n_points    ] = loader->pp1;
01131     outline->points[outline->n_points + 1] = loader->pp2;
01132     outline->points[outline->n_points + 2] = loader->pp3;
01133     outline->points[outline->n_points + 3] = loader->pp4;
01134 
01135     outline->tags[outline->n_points    ] = 0;
01136     outline->tags[outline->n_points + 1] = 0;
01137     outline->tags[outline->n_points + 2] = 0;
01138     outline->tags[outline->n_points + 3] = 0;
01139 
01140 #ifdef TT_USE_BYTECODE_INTERPRETER
01141 
01142     {
01143       FT_Stream  stream = loader->stream;
01144       FT_UShort  n_ins, max_ins;
01145       FT_ULong   tmp;
01146 
01147 
01148       /* TT_Load_Composite_Glyph only gives us the offset of instructions */
01149       /* so we read them here                                             */
01150       if ( FT_STREAM_SEEK( loader->ins_pos ) ||
01151            FT_READ_USHORT( n_ins )           )
01152         return error;
01153 
01154       FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
01155 
01156       /* check it */
01157       max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions;
01158       if ( n_ins > max_ins )
01159       {
01160         /* acroread ignores this field, so we only do a rough safety check */
01161         if ( (FT_Int)n_ins > loader->byte_len )
01162         {
01163           FT_TRACE1(( "TT_Process_Composite_Glyph: "
01164                       "too many instructions (%d) for glyph with length %d\n",
01165                       n_ins, loader->byte_len ));
01166           return TT_Err_Too_Many_Hints;
01167         }
01168 
01169         tmp = loader->exec->glyphSize;
01170         error = Update_Max( loader->exec->memory,
01171                             &tmp,
01172                             sizeof ( FT_Byte ),
01173                             (void*)&loader->exec->glyphIns,
01174                             n_ins );
01175         loader->exec->glyphSize = (FT_UShort)tmp;
01176         if ( error )
01177           return error;
01178       }
01179       else if ( n_ins == 0 )
01180         return TT_Err_Ok;
01181 
01182       if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
01183         return error;
01184 
01185       loader->glyph->control_data = loader->exec->glyphIns;
01186       loader->glyph->control_len  = n_ins;
01187     }
01188 
01189 #endif
01190 
01191     tt_prepare_zone( &loader->zone, &loader->gloader->base,
01192                      start_point, start_contour );
01193 
01194     /* Some points are likely touched during execution of  */
01195     /* instructions on components.  So let's untouch them. */
01196     for ( i = start_point; i < loader->zone.n_points; i++ )
01197       loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
01198 
01199     loader->zone.n_points += 4;
01200 
01201     return TT_Hint_Glyph( loader, 1 );
01202   }
01203 
01204 
01205   /* Calculate the four phantom points.                     */
01206   /* The first two stand for horizontal origin and advance. */
01207   /* The last two stand for vertical origin and advance.    */
01208 #define TT_LOADER_SET_PP( loader )                                          \
01209           do {                                                              \
01210             (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
01211             (loader)->pp1.y = 0;                                            \
01212             (loader)->pp2.x = (loader)->pp1.x + (loader)->advance;          \
01213             (loader)->pp2.y = 0;                                            \
01214             (loader)->pp3.x = 0;                                            \
01215             (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax;  \
01216             (loader)->pp4.x = 0;                                            \
01217             (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
01218           } while ( 0 )
01219 
01220 
01221   /*************************************************************************/
01222   /*                                                                       */
01223   /* <Function>                                                            */
01224   /*    load_truetype_glyph                                                */
01225   /*                                                                       */
01226   /* <Description>                                                         */
01227   /*    Loads a given truetype glyph.  Handles composites and uses a       */
01228   /*    TT_Loader object.                                                  */
01229   /*                                                                       */
01230   static FT_Error
01231   load_truetype_glyph( TT_Loader  loader,
01232                        FT_UInt    glyph_index,
01233                        FT_UInt    recurse_count,
01234                        FT_Bool    header_only )
01235   {
01236     FT_Error        error        = TT_Err_Ok;
01237     FT_Fixed        x_scale, y_scale;
01238     FT_ULong        offset;
01239     TT_Face         face         = (TT_Face)loader->face;
01240     FT_GlyphLoader  gloader      = loader->gloader;
01241     FT_Bool         opened_frame = 0;
01242 
01243 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
01244     FT_Vector*      deltas       = NULL;
01245 #endif
01246 
01247 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01248     FT_StreamRec    inc_stream;
01249     FT_Data         glyph_data;
01250     FT_Bool         glyph_data_loaded = 0;
01251 #endif
01252 
01253 
01254     /* some fonts have an incorrect value of `maxComponentDepth', */
01255     /* thus we allow depth 1 to catch the majority of them        */
01256     if ( recurse_count > 1                                   &&
01257          recurse_count > face->max_profile.maxComponentDepth )
01258     {
01259       error = TT_Err_Invalid_Composite;
01260       goto Exit;
01261     }
01262 
01263     /* check glyph index */
01264     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
01265     {
01266       error = TT_Err_Invalid_Glyph_Index;
01267       goto Exit;
01268     }
01269 
01270     loader->glyph_index = glyph_index;
01271 
01272     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01273     {
01274       x_scale = ((TT_Size)loader->size)->metrics.x_scale;
01275       y_scale = ((TT_Size)loader->size)->metrics.y_scale;
01276     }
01277     else
01278     {
01279       x_scale = 0x10000L;
01280       y_scale = 0x10000L;
01281     }
01282 
01283     tt_get_metrics( loader, glyph_index );
01284 
01285     /* Set `offset' to the start of the glyph relative to the start of */
01286     /* the `glyf' table, and `byte_len' to the length of the glyph in  */
01287     /* bytes.                                                          */
01288 
01289 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01290 
01291     /* If we are loading glyph data via the incremental interface, set */
01292     /* the loader stream to a memory stream reading the data returned  */
01293     /* by the interface.                                               */
01294     if ( face->root.internal->incremental_interface )
01295     {
01296       error = face->root.internal->incremental_interface->funcs->get_glyph_data(
01297                 face->root.internal->incremental_interface->object,
01298                 glyph_index, &glyph_data );
01299       if ( error )
01300         goto Exit;
01301 
01302       glyph_data_loaded = 1;
01303       offset            = 0;
01304       loader->byte_len  = glyph_data.length;
01305 
01306       FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
01307       FT_Stream_OpenMemory( &inc_stream,
01308                             glyph_data.pointer, glyph_data.length );
01309 
01310       loader->stream = &inc_stream;
01311     }
01312     else
01313 
01314 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
01315 
01316       offset = tt_face_get_location( face, glyph_index,
01317                                      (FT_UInt*)&loader->byte_len );
01318 
01319     if ( loader->byte_len > 0 )
01320     {
01321 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01322       /* for the incremental interface, `glyf_offset' is always zero */
01323       if ( !loader->glyf_offset                        &&
01324            !face->root.internal->incremental_interface )
01325 #else
01326       if ( !loader->glyf_offset )
01327 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
01328       {
01329         FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
01330         error = TT_Err_Invalid_Table;
01331         goto Exit;
01332       }
01333 
01334       error = face->access_glyph_frame( loader, glyph_index,
01335                                         loader->glyf_offset + offset,
01336                                         loader->byte_len );
01337       if ( error )
01338         goto Exit;
01339 
01340       opened_frame = 1;
01341 
01342       /* read glyph header first */
01343       error = face->read_glyph_header( loader );
01344       if ( error || header_only )
01345         goto Exit;
01346     }
01347 
01348     if ( loader->byte_len == 0 || loader->n_contours == 0 )
01349     {
01350       loader->bbox.xMin = 0;
01351       loader->bbox.xMax = 0;
01352       loader->bbox.yMin = 0;
01353       loader->bbox.yMax = 0;
01354 
01355       if ( header_only )
01356         goto Exit;
01357 
01358       /* must initialize points before (possibly) overriding */
01359       /* glyph metrics from the incremental interface        */
01360       TT_LOADER_SET_PP( loader );
01361 
01362 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01363       tt_get_metrics_incr_overrides( loader, glyph_index );
01364 #endif
01365 
01366 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
01367 
01368       if ( ((TT_Face)(loader->face))->doblend )
01369       {
01370         /* this must be done before scaling */
01371         FT_Memory  memory = loader->face->memory;
01372 
01373 
01374         error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
01375                                           glyph_index, &deltas, 4 );
01376         if ( error )
01377           goto Exit;
01378 
01379         loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
01380         loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
01381         loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
01382         loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
01383 
01384         FT_FREE( deltas );
01385       }
01386 
01387 #endif
01388 
01389       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01390       {
01391         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
01392         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
01393         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
01394         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
01395       }
01396 
01397       error = TT_Err_Ok;
01398       goto Exit;
01399     }
01400 
01401     /* must initialize points before (possibly) overriding */
01402     /* glyph metrics from the incremental interface        */
01403     TT_LOADER_SET_PP( loader );
01404 
01405 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01406     tt_get_metrics_incr_overrides( loader, glyph_index );
01407 #endif
01408 
01409     /***********************************************************************/
01410     /***********************************************************************/
01411     /***********************************************************************/
01412 
01413     /* if it is a simple glyph, load it */
01414 
01415     if ( loader->n_contours > 0 )
01416     {
01417       error = face->read_simple_glyph( loader );
01418       if ( error )
01419         goto Exit;
01420 
01421       /* all data have been read */
01422       face->forget_glyph_frame( loader );
01423       opened_frame = 0;
01424 
01425       error = TT_Process_Simple_Glyph( loader );
01426       if ( error )
01427         goto Exit;
01428 
01429       FT_GlyphLoader_Add( gloader );
01430     }
01431 
01432     /***********************************************************************/
01433     /***********************************************************************/
01434     /***********************************************************************/
01435 
01436     /* otherwise, load a composite! */
01437     else if ( loader->n_contours == -1 )
01438     {
01439       FT_UInt   start_point;
01440       FT_UInt   start_contour;
01441       FT_ULong  ins_pos;  /* position of composite instructions, if any */
01442 
01443 
01444       start_point   = gloader->base.outline.n_points;
01445       start_contour = gloader->base.outline.n_contours;
01446 
01447       /* for each subglyph, read composite header */
01448       error = face->read_composite_glyph( loader );
01449       if ( error )
01450         goto Exit;
01451 
01452       /* store the offset of instructions */
01453       ins_pos = loader->ins_pos;
01454 
01455       /* all data we need are read */
01456       face->forget_glyph_frame( loader );
01457       opened_frame = 0;
01458 
01459 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
01460 
01461       if ( face->doblend )
01462       {
01463         FT_Int       i, limit;
01464         FT_SubGlyph  subglyph;
01465         FT_Memory    memory = face->root.memory;
01466 
01467 
01468         /* this provides additional offsets */
01469         /* for each component's translation */
01470 
01471         if ( ( error = TT_Vary_Get_Glyph_Deltas(
01472                          face,
01473                          glyph_index,
01474                          &deltas,
01475                          gloader->current.num_subglyphs + 4 )) != 0 )
01476           goto Exit;
01477 
01478         subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
01479         limit    = gloader->current.num_subglyphs;
01480 
01481         for ( i = 0; i < limit; ++i, ++subglyph )
01482         {
01483           if ( subglyph->flags & ARGS_ARE_XY_VALUES )
01484           {
01485             /* XXX: overflow check for subglyph->{arg1,arg2}.   */
01486             /* deltas[i].{x,y} must be within signed 16-bit,    */
01487             /* but the restriction of summed delta is not clear */
01488             subglyph->arg1 += (FT_Int16)deltas[i].x;
01489             subglyph->arg2 += (FT_Int16)deltas[i].y;
01490           }
01491         }
01492 
01493         loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
01494         loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
01495         loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
01496         loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
01497 
01498         FT_FREE( deltas );
01499       }
01500 
01501 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
01502 
01503       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01504       {
01505         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
01506         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
01507         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
01508         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
01509       }
01510 
01511       /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
01512       /* `as is' in the glyph slot (the client application will be     */
01513       /* responsible for interpreting these data)...                   */
01514       if ( loader->load_flags & FT_LOAD_NO_RECURSE )
01515       {
01516         FT_GlyphLoader_Add( gloader );
01517         loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
01518 
01519         goto Exit;
01520       }
01521 
01522       /*********************************************************************/
01523       /*********************************************************************/
01524       /*********************************************************************/
01525 
01526       {
01527         FT_UInt      n, num_base_points;
01528         FT_SubGlyph  subglyph       = 0;
01529 
01530         FT_UInt      num_points     = start_point;
01531         FT_UInt      num_subglyphs  = gloader->current.num_subglyphs;
01532         FT_UInt      num_base_subgs = gloader->base.num_subglyphs;
01533 
01534         FT_Stream    old_stream     = loader->stream;
01535         FT_Int       old_byte_len   = loader->byte_len;
01536 
01537 
01538         FT_GlyphLoader_Add( gloader );
01539 
01540         /* read each subglyph independently */
01541         for ( n = 0; n < num_subglyphs; n++ )
01542         {
01543           FT_Vector  pp[4];
01544 
01545 
01546           /* Each time we call load_truetype_glyph in this loop, the   */
01547           /* value of `gloader.base.subglyphs' can change due to table */
01548           /* reallocations.  We thus need to recompute the subglyph    */
01549           /* pointer on each iteration.                                */
01550           subglyph = gloader->base.subglyphs + num_base_subgs + n;
01551 
01552           pp[0] = loader->pp1;
01553           pp[1] = loader->pp2;
01554           pp[2] = loader->pp3;
01555           pp[3] = loader->pp4;
01556 
01557           num_base_points = gloader->base.outline.n_points;
01558 
01559           error = load_truetype_glyph( loader, subglyph->index,
01560                                        recurse_count + 1, FALSE );
01561           if ( error )
01562             goto Exit;
01563 
01564           /* restore subglyph pointer */
01565           subglyph = gloader->base.subglyphs + num_base_subgs + n;
01566 
01567           if ( !( subglyph->flags & USE_MY_METRICS ) )
01568           {
01569             loader->pp1 = pp[0];
01570             loader->pp2 = pp[1];
01571             loader->pp3 = pp[2];
01572             loader->pp4 = pp[3];
01573           }
01574 
01575           num_points = gloader->base.outline.n_points;
01576 
01577           if ( num_points == num_base_points )
01578             continue;
01579 
01580           /* gloader->base.outline consists of three parts:               */
01581           /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
01582           /*                                                              */
01583           /* (1): exists from the beginning                               */
01584           /* (2): components that have been loaded so far                 */
01585           /* (3): the newly loaded component                              */
01586           TT_Process_Composite_Component( loader, subglyph, start_point,
01587                                           num_base_points );
01588         }
01589 
01590         loader->stream   = old_stream;
01591         loader->byte_len = old_byte_len;
01592 
01593         /* process the glyph */
01594         loader->ins_pos = ins_pos;
01595         if ( IS_HINTED( loader->load_flags ) &&
01596 
01597 #ifdef TT_USE_BYTECODE_INTERPRETER
01598 
01599              subglyph->flags & WE_HAVE_INSTR &&
01600 
01601 #endif
01602 
01603              num_points > start_point )
01604           TT_Process_Composite_Glyph( loader, start_point, start_contour );
01605 
01606       }
01607     }
01608     else
01609     {
01610       /* invalid composite count (negative but not -1) */
01611       error = TT_Err_Invalid_Outline;
01612       goto Exit;
01613     }
01614 
01615     /***********************************************************************/
01616     /***********************************************************************/
01617     /***********************************************************************/
01618 
01619   Exit:
01620 
01621     if ( opened_frame )
01622       face->forget_glyph_frame( loader );
01623 
01624 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01625 
01626     if ( glyph_data_loaded )
01627       face->root.internal->incremental_interface->funcs->free_glyph_data(
01628         face->root.internal->incremental_interface->object,
01629         &glyph_data );
01630 
01631 #endif
01632 
01633     return error;
01634   }
01635 
01636 
01637   static FT_Error
01638   compute_glyph_metrics( TT_Loader  loader,
01639                          FT_UInt    glyph_index )
01640   {
01641     FT_BBox       bbox;
01642     TT_Face       face = (TT_Face)loader->face;
01643     FT_Fixed      y_scale;
01644     TT_GlyphSlot  glyph = loader->glyph;
01645     TT_Size       size = (TT_Size)loader->size;
01646 
01647 
01648     y_scale = 0x10000L;
01649     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01650       y_scale = size->root.metrics.y_scale;
01651 
01652     if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
01653       FT_Outline_Get_CBox( &glyph->outline, &bbox );
01654     else
01655       bbox = loader->bbox;
01656 
01657     /* get the device-independent horizontal advance; it is scaled later */
01658     /* by the base layer.                                                */
01659     {
01660       FT_Pos  advance = loader->linear;
01661 
01662 
01663       /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
01664       /* correctly support DynaLab fonts, which have an incorrect       */
01665       /* `advance_Width_Max' field!  It is used, to my knowledge,       */
01666       /* exclusively in the X-TrueType font server.                     */
01667       /*                                                                */
01668       if ( face->postscript.isFixedPitch                                     &&
01669            ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
01670         advance = face->horizontal.advance_Width_Max;
01671 
01672       /* we need to return the advance in font units in linearHoriAdvance, */
01673       /* it will be scaled later by the base layer.                        */
01674       glyph->linearHoriAdvance = advance;
01675     }
01676 
01677     glyph->metrics.horiBearingX = bbox.xMin;
01678     glyph->metrics.horiBearingY = bbox.yMax;
01679     glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
01680 
01681     /* adjust advance width to the value contained in the hdmx table */
01682     if ( !face->postscript.isFixedPitch  &&
01683          IS_HINTED( loader->load_flags ) )
01684     {
01685       FT_Byte*  widthp;
01686 
01687 
01688       widthp = tt_face_get_device_metrics( face,
01689                                            size->root.metrics.x_ppem,
01690                                            glyph_index );
01691 
01692       if ( widthp )
01693         glyph->metrics.horiAdvance = *widthp << 6;
01694     }
01695 
01696     /* set glyph dimensions */
01697     glyph->metrics.width  = bbox.xMax - bbox.xMin;
01698     glyph->metrics.height = bbox.yMax - bbox.yMin;
01699 
01700     /* Now take care of vertical metrics.  In the case where there is */
01701     /* no vertical information within the font (relatively common),   */
01702     /* create some metrics manually                                   */
01703     {
01704       FT_Pos  top;      /* scaled vertical top side bearing  */
01705       FT_Pos  advance;  /* scaled vertical advance height    */
01706 
01707 
01708       /* Get the unscaled top bearing and advance height. */
01709       if ( face->vertical_info                   &&
01710            face->vertical.number_Of_VMetrics > 0 )
01711       {
01712         top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
01713                                    y_scale );
01714 
01715         if ( loader->pp3.y <= loader->pp4.y )
01716           advance = 0;
01717         else
01718           advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
01719                                           y_scale );
01720       }
01721       else
01722       {
01723         FT_Pos  height;
01724 
01725 
01726         /* XXX Compute top side bearing and advance height in  */
01727         /*     Get_VMetrics instead of here.                   */
01728 
01729         /* NOTE: The OS/2 values are the only `portable' ones, */
01730         /*       which is why we use them, if there is an OS/2 */
01731         /*       table in the font.  Otherwise, we use the     */
01732         /*       values defined in the horizontal header.      */
01733 
01734         height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
01735                                       y_scale );
01736         if ( face->os2.version != 0xFFFFU )
01737           advance = (FT_Pos)( face->os2.sTypoAscender -
01738                               face->os2.sTypoDescender );
01739         else
01740           advance = (FT_Pos)( face->horizontal.Ascender -
01741                               face->horizontal.Descender );
01742 
01743         top = ( advance - height ) / 2;
01744       }
01745 
01746 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01747       {
01748         FT_Incremental_InterfaceRec*  incr;
01749         FT_Incremental_MetricsRec     metrics;
01750         FT_Error                      error;
01751 
01752 
01753         incr = face->root.internal->incremental_interface;
01754 
01755         /* If this is an incrementally loaded font see if there are */
01756         /* overriding metrics for this glyph.                       */
01757         if ( incr && incr->funcs->get_glyph_metrics )
01758         {
01759           metrics.bearing_x = 0;
01760           metrics.bearing_y = top;
01761           metrics.advance   = advance;
01762 
01763           error = incr->funcs->get_glyph_metrics( incr->object,
01764                                                   glyph_index,
01765                                                   TRUE,
01766                                                   &metrics );
01767           if ( error )
01768             return error;
01769 
01770           top     = metrics.bearing_y;
01771           advance = metrics.advance;
01772         }
01773       }
01774 
01775       /* GWW: Do vertical metrics get loaded incrementally too? */
01776 
01777 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
01778 
01779       glyph->linearVertAdvance = advance;
01780 
01781       /* scale the metrics */
01782       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
01783       {
01784         top     = FT_MulFix( top,     y_scale );
01785         advance = FT_MulFix( advance, y_scale );
01786       }
01787 
01788       /* XXX: for now, we have no better algorithm for the lsb, but it */
01789       /*      should work fine.                                        */
01790       /*                                                               */
01791       glyph->metrics.vertBearingX = glyph->metrics.horiBearingX -
01792                                       glyph->metrics.horiAdvance / 2;
01793       glyph->metrics.vertBearingY = top;
01794       glyph->metrics.vertAdvance  = advance;
01795     }
01796 
01797     return 0;
01798   }
01799 
01800 
01801 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
01802 
01803   static FT_Error
01804   load_sbit_image( TT_Size       size,
01805                    TT_GlyphSlot  glyph,
01806                    FT_UInt       glyph_index,
01807                    FT_Int32      load_flags )
01808   {
01809     TT_Face             face;
01810     SFNT_Service        sfnt;
01811     FT_Stream           stream;
01812     FT_Error            error;
01813     TT_SBit_MetricsRec  metrics;
01814 
01815 
01816     face   = (TT_Face)glyph->face;
01817     sfnt   = (SFNT_Service)face->sfnt;
01818     stream = face->root.stream;
01819 
01820     error = sfnt->load_sbit_image( face,
01821                                    size->strike_index,
01822                                    glyph_index,
01823                                    (FT_Int)load_flags,
01824                                    stream,
01825                                    &glyph->bitmap,
01826                                    &metrics );
01827     if ( !error )
01828     {
01829       glyph->outline.n_points   = 0;
01830       glyph->outline.n_contours = 0;
01831 
01832       glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
01833       glyph->metrics.height = (FT_Pos)metrics.height << 6;
01834 
01835       glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
01836       glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
01837       glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
01838 
01839       glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
01840       glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
01841       glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
01842 
01843       glyph->format = FT_GLYPH_FORMAT_BITMAP;
01844 
01845       if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
01846       {
01847         glyph->bitmap_left = metrics.vertBearingX;
01848         glyph->bitmap_top  = metrics.vertBearingY;
01849       }
01850       else
01851       {
01852         glyph->bitmap_left = metrics.horiBearingX;
01853         glyph->bitmap_top  = metrics.horiBearingY;
01854       }
01855     }
01856 
01857     return error;
01858   }
01859 
01860 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
01861 
01862 
01863   static FT_Error
01864   tt_loader_init( TT_Loader     loader,
01865                   TT_Size       size,
01866                   TT_GlyphSlot  glyph,
01867                   FT_Int32      load_flags,
01868                   FT_Bool       glyf_table_only )
01869   {
01870     TT_Face    face;
01871     FT_Stream  stream;
01872 
01873 
01874     face   = (TT_Face)glyph->face;
01875     stream = face->root.stream;
01876 
01877     FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
01878 
01879 #ifdef TT_USE_BYTECODE_INTERPRETER
01880 
01881     /* load execution context */
01882     if ( IS_HINTED( load_flags ) && !glyf_table_only )
01883     {
01884       TT_ExecContext  exec;
01885       FT_Bool         grayscale;
01886 
01887 
01888       if ( !size->cvt_ready )
01889       {
01890         FT_Error  error = tt_size_ready_bytecode( size );
01891         if ( error )
01892           return error;
01893       }
01894 
01895       /* query new execution context */
01896       exec = size->debug ? size->context
01897                          : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
01898       if ( !exec )
01899         return TT_Err_Could_Not_Find_Context;
01900 
01901       grayscale =
01902         FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
01903 
01904       TT_Load_Context( exec, face, size );
01905 
01906       /* a change from mono to grayscale rendering (and vice versa) */
01907       /* requires a re-execution of the CVT program                 */
01908       if ( grayscale != exec->grayscale )
01909       {
01910         FT_UInt  i;
01911 
01912 
01913         FT_TRACE4(( "tt_loader_init: grayscale change,"
01914                     " re-executing `prep' table\n" ));
01915 
01916         exec->grayscale = grayscale;
01917 
01918         for ( i = 0; i < size->cvt_size; i++ )
01919           size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
01920         tt_size_run_prep( size );
01921       }
01922 
01923       /* see whether the cvt program has disabled hinting */
01924       if ( exec->GS.instruct_control & 1 )
01925         load_flags |= FT_LOAD_NO_HINTING;
01926 
01927       /* load default graphics state -- if needed */
01928       if ( exec->GS.instruct_control & 2 )
01929         exec->GS = tt_default_graphics_state;
01930 
01931       exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
01932       loader->exec = exec;
01933       loader->instructions = exec->glyphIns;
01934     }
01935 
01936 #endif /* TT_USE_BYTECODE_INTERPRETER */
01937 
01938     /* seek to the beginning of the glyph table -- for Type 42 fonts     */
01939     /* the table might be accessed from a Postscript stream or something */
01940     /* else...                                                           */
01941 
01942 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01943 
01944     if ( face->root.internal->incremental_interface )
01945       loader->glyf_offset = 0;
01946     else
01947 
01948 #endif
01949 
01950     {
01951       FT_Error  error = face->goto_table( face, TTAG_glyf, stream, 0 );
01952 
01953 
01954       if ( error == TT_Err_Table_Missing )
01955         loader->glyf_offset = 0;
01956       else if ( error )
01957       {
01958         FT_ERROR(( "tt_loader_init: could not access glyph table\n" ));
01959         return error;
01960       }
01961       else
01962         loader->glyf_offset = FT_STREAM_POS();
01963     }
01964 
01965     /* get face's glyph loader */
01966     if ( !glyf_table_only )
01967     {
01968       FT_GlyphLoader  gloader = glyph->internal->loader;
01969 
01970 
01971       FT_GlyphLoader_Rewind( gloader );
01972       loader->gloader = gloader;
01973     }
01974 
01975     loader->load_flags = load_flags;
01976 
01977     loader->face   = (FT_Face)face;
01978     loader->size   = (FT_Size)size;
01979     loader->glyph  = (FT_GlyphSlot)glyph;
01980     loader->stream = stream;
01981 
01982     return TT_Err_Ok;
01983   }
01984 
01985 
01986   /*************************************************************************/
01987   /*                                                                       */
01988   /* <Function>                                                            */
01989   /*    TT_Load_Glyph                                                      */
01990   /*                                                                       */
01991   /* <Description>                                                         */
01992   /*    A function used to load a single glyph within a given glyph slot,  */
01993   /*    for a given size.                                                  */
01994   /*                                                                       */
01995   /* <Input>                                                               */
01996   /*    glyph       :: A handle to a target slot object where the glyph    */
01997   /*                   will be loaded.                                     */
01998   /*                                                                       */
01999   /*    size        :: A handle to the source face size at which the glyph */
02000   /*                   must be scaled/loaded.                              */
02001   /*                                                                       */
02002   /*    glyph_index :: The index of the glyph in the font file.            */
02003   /*                                                                       */
02004   /*    load_flags  :: A flag indicating what to load for this glyph.  The */
02005   /*                   FT_LOAD_XXX constants can be used to control the    */
02006   /*                   glyph loading process (e.g., whether the outline    */
02007   /*                   should be scaled, whether to load bitmaps or not,   */
02008   /*                   whether to hint the outline, etc).                  */
02009   /*                                                                       */
02010   /* <Return>                                                              */
02011   /*    FreeType error code.  0 means success.                             */
02012   /*                                                                       */
02013   FT_LOCAL_DEF( FT_Error )
02014   TT_Load_Glyph( TT_Size       size,
02015                  TT_GlyphSlot  glyph,
02016                  FT_UInt       glyph_index,
02017                  FT_Int32      load_flags )
02018   {
02019     TT_Face       face;
02020     FT_Error      error;
02021     TT_LoaderRec  loader;
02022 
02023 
02024     face   = (TT_Face)glyph->face;
02025     error  = TT_Err_Ok;
02026 
02027 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
02028 
02029     /* try to load embedded bitmap if any              */
02030     /*                                                 */
02031     /* XXX: The convention should be emphasized in     */
02032     /*      the documents because it can be confusing. */
02033     if ( size->strike_index != 0xFFFFFFFFUL      &&
02034          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
02035     {
02036       error = load_sbit_image( size, glyph, glyph_index, load_flags );
02037       if ( !error )
02038       {
02039         FT_Face  root = &face->root;
02040 
02041 
02042         if ( FT_IS_SCALABLE( root ) )
02043         {
02044           /* for the bbox we need the header only */
02045           (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
02046           (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
02047           glyph->linearHoriAdvance = loader.linear;
02048           glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
02049                                        loader.vadvance;
02050           if ( face->postscript.isFixedPitch                             &&
02051                ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
02052             glyph->linearHoriAdvance = face->horizontal.advance_Width_Max;
02053         }
02054 
02055         return TT_Err_Ok;
02056       }
02057     }
02058 
02059 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
02060 
02061     /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
02062     if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
02063       return TT_Err_Invalid_Size_Handle;
02064 
02065     if ( load_flags & FT_LOAD_SBITS_ONLY )
02066       return TT_Err_Invalid_Argument;
02067 
02068     error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
02069     if ( error )
02070       return error;
02071 
02072     glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
02073     glyph->num_subglyphs = 0;
02074     glyph->outline.flags = 0;
02075 
02076     /* main loading loop */
02077     error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
02078     if ( !error )
02079     {
02080       if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
02081       {
02082         glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
02083         glyph->subglyphs     = loader.gloader->base.subglyphs;
02084       }
02085       else
02086       {
02087         glyph->outline        = loader.gloader->base.outline;
02088         glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
02089 
02090         /* Translate array so that (0,0) is the glyph's origin.  Note  */
02091         /* that this behaviour is independent on the value of bit 1 of */
02092         /* the `flags' field in the `head' table -- at least major     */
02093         /* applications like Acroread indicate that.                   */
02094         if ( loader.pp1.x )
02095           FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
02096       }
02097 
02098 #ifdef TT_USE_BYTECODE_INTERPRETER
02099 
02100       if ( IS_HINTED( load_flags ) )
02101       {
02102         if ( loader.exec->GS.scan_control )
02103         {
02104           /* convert scan conversion mode to FT_OUTLINE_XXX flags */
02105           switch ( loader.exec->GS.scan_type )
02106           {
02107           case 0: /* simple drop-outs including stubs */
02108             glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
02109             break;
02110           case 1: /* simple drop-outs excluding stubs */
02111             /* nothing; it's the default rendering mode */
02112             break;
02113           case 4: /* smart drop-outs including stubs */
02114             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
02115                                     FT_OUTLINE_INCLUDE_STUBS;
02116             break;
02117           case 5: /* smart drop-outs excluding stubs  */
02118             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
02119             break;
02120 
02121           default: /* no drop-out control */
02122             glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
02123             break;
02124           }
02125         }
02126         else
02127           glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
02128       }
02129 
02130 #endif /* TT_USE_BYTECODE_INTERPRETER */
02131 
02132       compute_glyph_metrics( &loader, glyph_index );
02133     }
02134 
02135     /* Set the `high precision' bit flag.                           */
02136     /* This is _critical_ to get correct output for monochrome      */
02137     /* TrueType glyphs at all sizes using the bytecode interpreter. */
02138     /*                                                              */
02139     if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
02140          size->root.metrics.y_ppem < 24     )
02141       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
02142 
02143     return error;
02144   }
02145 
02146 
02147 /* END */

Generated on Mon May 28 2012 04:33:52 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.