ttpload.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ttpload.c                                                              */
00004 /*                                                                         */
00005 /*    TrueType-specific tables loader (body).                              */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 by       */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_DEBUG_H
00021 #include FT_INTERNAL_OBJECTS_H
00022 #include FT_INTERNAL_STREAM_H
00023 #include FT_TRUETYPE_TAGS_H
00024 
00025 #include "ttpload.h"
00026 
00027 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00028 #include "ttgxvar.h"
00029 #endif
00030 
00031 #include "tterrors.h"
00032 
00033 
00034   /*************************************************************************/
00035   /*                                                                       */
00036   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00037   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00038   /* messages during execution.                                            */
00039   /*                                                                       */
00040 #undef  FT_COMPONENT
00041 #define FT_COMPONENT  trace_ttpload
00042 
00043 
00044   /*************************************************************************/
00045   /*                                                                       */
00046   /* <Function>                                                            */
00047   /*    tt_face_load_loca                                                  */
00048   /*                                                                       */
00049   /* <Description>                                                         */
00050   /*    Load the locations table.                                          */
00051   /*                                                                       */
00052   /* <InOut>                                                               */
00053   /*    face   :: A handle to the target face object.                      */
00054   /*                                                                       */
00055   /* <Input>                                                               */
00056   /*    stream :: The input stream.                                        */
00057   /*                                                                       */
00058   /* <Return>                                                              */
00059   /*    FreeType error code.  0 means success.                             */
00060   /*                                                                       */
00061   FT_LOCAL_DEF( FT_Error )
00062   tt_face_load_loca( TT_Face    face,
00063                      FT_Stream  stream )
00064   {
00065     FT_Error  error;
00066     FT_ULong  table_len;
00067     FT_Int    shift;
00068 
00069 
00070     /* we need the size of the `glyf' table for malformed `loca' tables */
00071     error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
00072 
00073     /* it is possible that a font doesn't have a glyf table at all */
00074     /* or its size is zero                                         */
00075     if ( error == TT_Err_Table_Missing )
00076       face->glyf_len = 0;
00077     else if ( error )
00078       goto Exit;
00079 
00080     FT_TRACE2(( "Locations " ));
00081     error = face->goto_table( face, TTAG_loca, stream, &table_len );
00082     if ( error )
00083     {
00084       error = TT_Err_Locations_Missing;
00085       goto Exit;
00086     }
00087 
00088     if ( face->header.Index_To_Loc_Format != 0 )
00089     {
00090       shift = 2;
00091 
00092       if ( table_len >= 0x40000L )
00093       {
00094         FT_TRACE2(( "table too large\n" ));
00095         error = TT_Err_Invalid_Table;
00096         goto Exit;
00097       }
00098       face->num_locations = table_len >> shift;
00099     }
00100     else
00101     {
00102       shift = 1;
00103 
00104       if ( table_len >= 0x20000L )
00105       {
00106         FT_TRACE2(( "table too large\n" ));
00107         error = TT_Err_Invalid_Table;
00108         goto Exit;
00109       }
00110       face->num_locations = table_len >> shift;
00111     }
00112 
00113     if ( face->num_locations != (FT_ULong)face->root.num_glyphs )
00114     {
00115       FT_TRACE2(( "glyph count mismatch!  loca: %d, maxp: %d\n",
00116                   face->num_locations, face->root.num_glyphs ));
00117 
00118       /* we only handle the case where `maxp' gives a larger value */
00119       if ( face->num_locations < (FT_ULong)face->root.num_glyphs )
00120       {
00121         FT_Long   new_loca_len = (FT_Long)face->root.num_glyphs << shift;
00122 
00123         TT_Table  entry = face->dir_tables;
00124         TT_Table  limit = entry + face->num_tables;
00125 
00126         FT_Long   pos  = FT_Stream_Pos( stream );
00127         FT_Long   dist = 0x7FFFFFFFL;
00128 
00129 
00130         /* compute the distance to next table in font file */
00131         for ( ; entry < limit; entry++ )
00132         {
00133           FT_Long  diff = entry->Offset - pos;
00134 
00135 
00136           if ( diff > 0 && diff < dist )
00137             dist = diff;
00138         }
00139 
00140         if ( new_loca_len <= dist )
00141         {
00142           face->num_locations = face->root.num_glyphs;
00143           table_len           = new_loca_len;
00144 
00145           FT_TRACE2(( "adjusting num_locations to %d\n",
00146                       face->num_locations ));
00147         }
00148       }
00149     }
00150 
00151     /*
00152      * Extract the frame.  We don't need to decompress it since
00153      * we are able to parse it directly.
00154      */
00155     if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
00156       goto Exit;
00157 
00158     FT_TRACE2(( "loaded\n" ));
00159 
00160   Exit:
00161     return error;
00162   }
00163 
00164 
00165   FT_LOCAL_DEF( FT_ULong )
00166   tt_face_get_location( TT_Face   face,
00167                         FT_UInt   gindex,
00168                         FT_UInt  *asize )
00169   {
00170     FT_ULong  pos1, pos2;
00171     FT_Byte*  p;
00172     FT_Byte*  p_limit;
00173 
00174 
00175     pos1 = pos2 = 0;
00176 
00177     if ( gindex < face->num_locations )
00178     {
00179       if ( face->header.Index_To_Loc_Format != 0 )
00180       {
00181         p       = face->glyph_locations + gindex * 4;
00182         p_limit = face->glyph_locations + face->num_locations * 4;
00183 
00184         pos1 = FT_NEXT_ULONG( p );
00185         pos2 = pos1;
00186 
00187         if ( p + 4 <= p_limit )
00188           pos2 = FT_NEXT_ULONG( p );
00189       }
00190       else
00191       {
00192         p       = face->glyph_locations + gindex * 2;
00193         p_limit = face->glyph_locations + face->num_locations * 2;
00194 
00195         pos1 = FT_NEXT_USHORT( p );
00196         pos2 = pos1;
00197 
00198         if ( p + 2 <= p_limit )
00199           pos2 = FT_NEXT_USHORT( p );
00200 
00201         pos1 <<= 1;
00202         pos2 <<= 1;
00203       }
00204     }
00205 
00206     /* The `loca' table must be ordered; it refers to the length of */
00207     /* an entry as the difference between the current and the next  */
00208     /* position.  However, there do exist (malformed) fonts which   */
00209     /* don't obey this rule, so we are only able to provide an      */
00210     /* upper bound for the size.                                    */
00211     /*                                                              */
00212     /* We get (intentionally) a wrong, non-zero result in case the  */
00213     /* `glyf' table is missing.                                     */
00214     if ( pos2 >= pos1 )
00215       *asize = (FT_UInt)( pos2 - pos1 );
00216     else
00217       *asize = (FT_UInt)( face->glyf_len - pos1 );
00218 
00219     return pos1;
00220   }
00221 
00222 
00223   FT_LOCAL_DEF( void )
00224   tt_face_done_loca( TT_Face  face )
00225   {
00226     FT_Stream  stream = face->root.stream;
00227 
00228 
00229     FT_FRAME_RELEASE( face->glyph_locations );
00230     face->num_locations = 0;
00231   }
00232 
00233 
00234 
00235   /*************************************************************************/
00236   /*                                                                       */
00237   /* <Function>                                                            */
00238   /*    tt_face_load_cvt                                                   */
00239   /*                                                                       */
00240   /* <Description>                                                         */
00241   /*    Load the control value table into a face object.                   */
00242   /*                                                                       */
00243   /* <InOut>                                                               */
00244   /*    face   :: A handle to the target face object.                      */
00245   /*                                                                       */
00246   /* <Input>                                                               */
00247   /*    stream :: A handle to the input stream.                            */
00248   /*                                                                       */
00249   /* <Return>                                                              */
00250   /*    FreeType error code.  0 means success.                             */
00251   /*                                                                       */
00252   FT_LOCAL_DEF( FT_Error )
00253   tt_face_load_cvt( TT_Face    face,
00254                     FT_Stream  stream )
00255   {
00256 #ifdef TT_USE_BYTECODE_INTERPRETER
00257 
00258     FT_Error   error;
00259     FT_Memory  memory = stream->memory;
00260     FT_ULong   table_len;
00261 
00262 
00263     FT_TRACE2(( "CVT " ));
00264 
00265     error = face->goto_table( face, TTAG_cvt, stream, &table_len );
00266     if ( error )
00267     {
00268       FT_TRACE2(( "is missing\n" ));
00269 
00270       face->cvt_size = 0;
00271       face->cvt      = NULL;
00272       error          = TT_Err_Ok;
00273 
00274       goto Exit;
00275     }
00276 
00277     face->cvt_size = table_len / 2;
00278 
00279     if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
00280       goto Exit;
00281 
00282     if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
00283       goto Exit;
00284 
00285     {
00286       FT_Short*  cur   = face->cvt;
00287       FT_Short*  limit = cur + face->cvt_size;
00288 
00289 
00290       for ( ; cur <  limit; cur++ )
00291         *cur = FT_GET_SHORT();
00292     }
00293 
00294     FT_FRAME_EXIT();
00295     FT_TRACE2(( "loaded\n" ));
00296 
00297 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00298     if ( face->doblend )
00299       error = tt_face_vary_cvt( face, stream );
00300 #endif
00301 
00302   Exit:
00303     return error;
00304 
00305 #else /* !TT_USE_BYTECODE_INTERPRETER */
00306 
00307     FT_UNUSED( face   );
00308     FT_UNUSED( stream );
00309 
00310     return TT_Err_Ok;
00311 
00312 #endif
00313   }
00314 
00315 
00316   /*************************************************************************/
00317   /*                                                                       */
00318   /* <Function>                                                            */
00319   /*    tt_face_load_fpgm                                                  */
00320   /*                                                                       */
00321   /* <Description>                                                         */
00322   /*    Load the font program.                                             */
00323   /*                                                                       */
00324   /* <InOut>                                                               */
00325   /*    face   :: A handle to the target face object.                      */
00326   /*                                                                       */
00327   /* <Input>                                                               */
00328   /*    stream :: A handle to the input stream.                            */
00329   /*                                                                       */
00330   /* <Return>                                                              */
00331   /*    FreeType error code.  0 means success.                             */
00332   /*                                                                       */
00333   FT_LOCAL_DEF( FT_Error )
00334   tt_face_load_fpgm( TT_Face    face,
00335                      FT_Stream  stream )
00336   {
00337 #ifdef TT_USE_BYTECODE_INTERPRETER
00338 
00339     FT_Error  error;
00340     FT_ULong  table_len;
00341 
00342 
00343     FT_TRACE2(( "Font program " ));
00344 
00345     /* The font program is optional */
00346     error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
00347     if ( error )
00348     {
00349       face->font_program      = NULL;
00350       face->font_program_size = 0;
00351       error                   = TT_Err_Ok;
00352 
00353       FT_TRACE2(( "is missing\n" ));
00354     }
00355     else
00356     {
00357       face->font_program_size = table_len;
00358       if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
00359         goto Exit;
00360 
00361       FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
00362     }
00363 
00364   Exit:
00365     return error;
00366 
00367 #else /* !TT_USE_BYTECODE_INTERPRETER */
00368 
00369     FT_UNUSED( face   );
00370     FT_UNUSED( stream );
00371 
00372     return TT_Err_Ok;
00373 
00374 #endif
00375   }
00376 
00377 
00378   /*************************************************************************/
00379   /*                                                                       */
00380   /* <Function>                                                            */
00381   /*    tt_face_load_prep                                                  */
00382   /*                                                                       */
00383   /* <Description>                                                         */
00384   /*    Load the cvt program.                                              */
00385   /*                                                                       */
00386   /* <InOut>                                                               */
00387   /*    face   :: A handle to the target face object.                      */
00388   /*                                                                       */
00389   /* <Input>                                                               */
00390   /*    stream :: A handle to the input stream.                            */
00391   /*                                                                       */
00392   /* <Return>                                                              */
00393   /*    FreeType error code.  0 means success.                             */
00394   /*                                                                       */
00395   FT_LOCAL_DEF( FT_Error )
00396   tt_face_load_prep( TT_Face    face,
00397                      FT_Stream  stream )
00398   {
00399 #ifdef TT_USE_BYTECODE_INTERPRETER
00400 
00401     FT_Error  error;
00402     FT_ULong  table_len;
00403 
00404 
00405     FT_TRACE2(( "Prep program " ));
00406 
00407     error = face->goto_table( face, TTAG_prep, stream, &table_len );
00408     if ( error )
00409     {
00410       face->cvt_program      = NULL;
00411       face->cvt_program_size = 0;
00412       error                  = TT_Err_Ok;
00413 
00414       FT_TRACE2(( "is missing\n" ));
00415     }
00416     else
00417     {
00418       face->cvt_program_size = table_len;
00419       if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
00420         goto Exit;
00421 
00422       FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
00423     }
00424 
00425   Exit:
00426     return error;
00427 
00428 #else /* !TT_USE_BYTECODE_INTERPRETER */
00429 
00430     FT_UNUSED( face   );
00431     FT_UNUSED( stream );
00432 
00433     return TT_Err_Ok;
00434 
00435 #endif
00436   }
00437 
00438 
00439   /*************************************************************************/
00440   /*                                                                       */
00441   /* <Function>                                                            */
00442   /*    tt_face_load_hdmx                                                  */
00443   /*                                                                       */
00444   /* <Description>                                                         */
00445   /*    Load the `hdmx' table into the face object.                        */
00446   /*                                                                       */
00447   /* <Input>                                                               */
00448   /*    face   :: A handle to the target face object.                      */
00449   /*                                                                       */
00450   /*    stream :: A handle to the input stream.                            */
00451   /*                                                                       */
00452   /* <Return>                                                              */
00453   /*    FreeType error code.  0 means success.                             */
00454   /*                                                                       */
00455 
00456   FT_LOCAL_DEF( FT_Error )
00457   tt_face_load_hdmx( TT_Face    face,
00458                      FT_Stream  stream )
00459   {
00460     FT_Error   error;
00461     FT_Memory  memory = stream->memory;
00462     FT_UInt    version, nn, num_records;
00463     FT_ULong   table_size, record_size;
00464     FT_Byte*   p;
00465     FT_Byte*   limit;
00466 
00467 
00468     /* this table is optional */
00469     error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
00470     if ( error || table_size < 8 )
00471       return TT_Err_Ok;
00472 
00473     if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
00474       goto Exit;
00475 
00476     p     = face->hdmx_table;
00477     limit = p + table_size;
00478 
00479     version     = FT_NEXT_USHORT( p );
00480     num_records = FT_NEXT_USHORT( p );
00481     record_size = FT_NEXT_ULONG( p );
00482 
00483     /* The maximum number of bytes in an hdmx device record is the */
00484     /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is   */
00485     /* the reason why `record_size' is a long (which we read as    */
00486     /* unsigned long for convenience).  In practice, two bytes     */
00487     /* sufficient to hold the size value.                          */
00488     /*                                                             */
00489     /* There are at least two fonts, HANNOM-A and HANNOM-B version */
00490     /* 2.0 (2005), which get this wrong: The upper two bytes of    */
00491     /* the size value are set to 0xFF instead of 0x00.  We catch   */
00492     /* and fix this.                                               */
00493 
00494     if ( record_size >= 0xFFFF0000UL )
00495       record_size &= 0xFFFFU;
00496 
00497     /* The limit for `num_records' is a heuristic value. */
00498 
00499     if ( version != 0 || num_records > 255 || record_size > 0x10001L )
00500     {
00501       error = TT_Err_Invalid_File_Format;
00502       goto Fail;
00503     }
00504 
00505     if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
00506       goto Fail;
00507 
00508     for ( nn = 0; nn < num_records; nn++ )
00509     {
00510       if ( p + record_size > limit )
00511         break;
00512 
00513       face->hdmx_record_sizes[nn] = p[0];
00514       p                          += record_size;
00515     }
00516 
00517     face->hdmx_record_count = nn;
00518     face->hdmx_table_size   = table_size;
00519     face->hdmx_record_size  = record_size;
00520 
00521   Exit:
00522     return error;
00523 
00524   Fail:
00525     FT_FRAME_RELEASE( face->hdmx_table );
00526     face->hdmx_table_size = 0;
00527     goto Exit;
00528   }
00529 
00530 
00531   FT_LOCAL_DEF( void )
00532   tt_face_free_hdmx( TT_Face  face )
00533   {
00534     FT_Stream  stream = face->root.stream;
00535     FT_Memory  memory = stream->memory;
00536 
00537 
00538     FT_FREE( face->hdmx_record_sizes );
00539     FT_FRAME_RELEASE( face->hdmx_table );
00540   }
00541 
00542 
00543   /*************************************************************************/
00544   /*                                                                       */
00545   /* Return the advance width table for a given pixel size if it is found  */
00546   /* in the font's `hdmx' table (if any).                                  */
00547   /*                                                                       */
00548   FT_LOCAL_DEF( FT_Byte* )
00549   tt_face_get_device_metrics( TT_Face  face,
00550                               FT_UInt  ppem,
00551                               FT_UInt  gindex )
00552   {
00553     FT_UInt   nn;
00554     FT_Byte*  result      = NULL;
00555     FT_ULong  record_size = face->hdmx_record_size;
00556     FT_Byte*  record      = face->hdmx_table + 8;
00557 
00558 
00559     for ( nn = 0; nn < face->hdmx_record_count; nn++ )
00560       if ( face->hdmx_record_sizes[nn] == ppem )
00561       {
00562         gindex += 2;
00563         if ( gindex < record_size )
00564           result = record + nn * record_size + gindex;
00565         break;
00566       }
00567 
00568     return result;
00569   }
00570 
00571 
00572 /* END */

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