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

sfobjs.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  sfobjs.c                                                               */
00004 /*                                                                         */
00005 /*    SFNT object management (base).                                       */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 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 "sfobjs.h"
00021 #include "ttload.h"
00022 #include "ttcmap.h"
00023 #include "ttkern.h"
00024 #include FT_INTERNAL_SFNT_H
00025 #include FT_INTERNAL_DEBUG_H
00026 #include FT_TRUETYPE_IDS_H
00027 #include FT_TRUETYPE_TAGS_H
00028 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
00029 #include FT_SFNT_NAMES_H
00030 #include "sferrors.h"
00031 
00032 #ifdef TT_CONFIG_OPTION_BDF
00033 #include "ttbdf.h"
00034 #endif
00035 
00036 
00037   /*************************************************************************/
00038   /*                                                                       */
00039   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00040   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00041   /* messages during execution.                                            */
00042   /*                                                                       */
00043 #undef  FT_COMPONENT
00044 #define FT_COMPONENT  trace_sfobjs
00045 
00046 
00047 
00048   /* convert a UTF-16 name entry to ASCII */
00049   static FT_String*
00050   tt_name_entry_ascii_from_utf16( TT_NameEntry  entry,
00051                                   FT_Memory     memory )
00052   {
00053     FT_String*  string = NULL;
00054     FT_UInt     len, code, n;
00055     FT_Byte*    read   = (FT_Byte*)entry->string;
00056     FT_Error    error;
00057 
00058 
00059     len = (FT_UInt)entry->stringLength / 2;
00060 
00061     if ( FT_NEW_ARRAY( string, len + 1 ) )
00062       return NULL;
00063 
00064     for ( n = 0; n < len; n++ )
00065     {
00066       code = FT_NEXT_USHORT( read );
00067       if ( code < 32 || code > 127 )
00068         code = '?';
00069 
00070       string[n] = (char)code;
00071     }
00072 
00073     string[len] = 0;
00074 
00075     return string;
00076   }
00077 
00078 
00079   /* convert an Apple Roman or symbol name entry to ASCII */
00080   static FT_String*
00081   tt_name_entry_ascii_from_other( TT_NameEntry  entry,
00082                                   FT_Memory     memory )
00083   {
00084     FT_String*  string = NULL;
00085     FT_UInt     len, code, n;
00086     FT_Byte*    read   = (FT_Byte*)entry->string;
00087     FT_Error    error;
00088 
00089 
00090     len = (FT_UInt)entry->stringLength;
00091 
00092     if ( FT_NEW_ARRAY( string, len + 1 ) )
00093       return NULL;
00094 
00095     for ( n = 0; n < len; n++ )
00096     {
00097       code = *read++;
00098       if ( code < 32 || code > 127 )
00099         code = '?';
00100 
00101       string[n] = (char)code;
00102     }
00103 
00104     string[len] = 0;
00105 
00106     return string;
00107   }
00108 
00109 
00110   typedef FT_String*  (*TT_NameEntry_ConvertFunc)( TT_NameEntry  entry,
00111                                                    FT_Memory     memory );
00112 
00113 
00114   /*************************************************************************/
00115   /*                                                                       */
00116   /* <Function>                                                            */
00117   /*    tt_face_get_name                                                   */
00118   /*                                                                       */
00119   /* <Description>                                                         */
00120   /*    Returns a given ENGLISH name record in ASCII.                      */
00121   /*                                                                       */
00122   /* <Input>                                                               */
00123   /*    face   :: A handle to the source face object.                      */
00124   /*                                                                       */
00125   /*    nameid :: The name id of the name record to return.                */
00126   /*                                                                       */
00127   /* <InOut>                                                               */
00128   /*    name   :: The address of a string pointer.  NULL if no name is     */
00129   /*              present.                                                 */
00130   /*                                                                       */
00131   /* <Return>                                                              */
00132   /*    FreeType error code.  0 means success.                             */
00133   /*                                                                       */
00134   static FT_Error
00135   tt_face_get_name( TT_Face      face,
00136                     FT_UShort    nameid,
00137                     FT_String**  name )
00138   {
00139     FT_Memory         memory = face->root.memory;
00140     FT_Error          error  = SFNT_Err_Ok;
00141     FT_String*        result = NULL;
00142     FT_UShort         n;
00143     TT_NameEntryRec*  rec;
00144     FT_Int            found_apple         = -1;
00145     FT_Int            found_apple_roman   = -1;
00146     FT_Int            found_apple_english = -1;
00147     FT_Int            found_win           = -1;
00148     FT_Int            found_unicode       = -1;
00149 
00150     FT_Bool           is_english = 0;
00151 
00152     TT_NameEntry_ConvertFunc  convert;
00153 
00154 
00155     FT_ASSERT( name );
00156 
00157     rec = face->name_table.names;
00158     for ( n = 0; n < face->num_names; n++, rec++ )
00159     {
00160       /* According to the OpenType 1.3 specification, only Microsoft or  */
00161       /* Apple platform IDs might be used in the `name' table.  The      */
00162       /* `Unicode' platform is reserved for the `cmap' table, and the    */
00163       /* `ISO' one is deprecated.                                        */
00164       /*                                                                 */
00165       /* However, the Apple TrueType specification doesn't say the same  */
00166       /* thing and goes to suggest that all Unicode `name' table entries */
00167       /* should be coded in UTF-16 (in big-endian format I suppose).     */
00168       /*                                                                 */
00169       if ( rec->nameID == nameid && rec->stringLength > 0 )
00170       {
00171         switch ( rec->platformID )
00172         {
00173         case TT_PLATFORM_APPLE_UNICODE:
00174         case TT_PLATFORM_ISO:
00175           /* there is `languageID' to check there.  We should use this */
00176           /* field only as a last solution when nothing else is        */
00177           /* available.                                                */
00178           /*                                                           */
00179           found_unicode = n;
00180           break;
00181 
00182         case TT_PLATFORM_MACINTOSH:
00183           /* This is a bit special because some fonts will use either    */
00184           /* an English language id, or a Roman encoding id, to indicate */
00185           /* the English version of its font name.                       */
00186           /*                                                             */
00187           if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
00188             found_apple_english = n;
00189           else if ( rec->encodingID == TT_MAC_ID_ROMAN )
00190             found_apple_roman = n;
00191           break;
00192 
00193         case TT_PLATFORM_MICROSOFT:
00194           /* we only take a non-English name when there is nothing */
00195           /* else available in the font                            */
00196           /*                                                       */
00197           if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
00198           {
00199             switch ( rec->encodingID )
00200             {
00201             case TT_MS_ID_SYMBOL_CS:
00202             case TT_MS_ID_UNICODE_CS:
00203             case TT_MS_ID_UCS_4:
00204               is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
00205               found_win  = n;
00206               break;
00207 
00208             default:
00209               ;
00210             }
00211           }
00212           break;
00213 
00214         default:
00215           ;
00216         }
00217       }
00218     }
00219 
00220     found_apple = found_apple_roman;
00221     if ( found_apple_english >= 0 )
00222       found_apple = found_apple_english;
00223 
00224     /* some fonts contain invalid Unicode or Macintosh formatted entries; */
00225     /* we will thus favor names encoded in Windows formats if available   */
00226     /* (provided it is an English name)                                   */
00227     /*                                                                    */
00228     convert = NULL;
00229     if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )
00230     {
00231       rec = face->name_table.names + found_win;
00232       switch ( rec->encodingID )
00233       {
00234         /* all Unicode strings are encoded using UTF-16BE */
00235       case TT_MS_ID_UNICODE_CS:
00236       case TT_MS_ID_SYMBOL_CS:
00237         convert = tt_name_entry_ascii_from_utf16;
00238         break;
00239 
00240       case TT_MS_ID_UCS_4:
00241         /* Apparently, if this value is found in a name table entry, it is */
00242         /* documented as `full Unicode repertoire'.  Experience with the   */
00243         /* MsGothic font shipped with Windows Vista shows that this really */
00244         /* means UTF-16 encoded names (UCS-4 values are only used within   */
00245         /* charmaps).                                                      */
00246         convert = tt_name_entry_ascii_from_utf16;
00247         break;
00248 
00249       default:
00250         ;
00251       }
00252     }
00253     else if ( found_apple >= 0 )
00254     {
00255       rec     = face->name_table.names + found_apple;
00256       convert = tt_name_entry_ascii_from_other;
00257     }
00258     else if ( found_unicode >= 0 )
00259     {
00260       rec     = face->name_table.names + found_unicode;
00261       convert = tt_name_entry_ascii_from_utf16;
00262     }
00263 
00264     if ( rec && convert )
00265     {
00266       if ( rec->string == NULL )
00267       {
00268         FT_Stream  stream = face->name_table.stream;
00269 
00270 
00271         if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
00272              FT_STREAM_SEEK( rec->stringOffset )              ||
00273              FT_STREAM_READ( rec->string, rec->stringLength ) )
00274         {
00275           FT_FREE( rec->string );
00276           rec->stringLength = 0;
00277           result            = NULL;
00278           goto Exit;
00279         }
00280       }
00281 
00282       result = convert( rec, memory );
00283     }
00284 
00285   Exit:
00286     *name = result;
00287     return error;
00288   }
00289 
00290 
00291   static FT_Encoding
00292   sfnt_find_encoding( int  platform_id,
00293                       int  encoding_id )
00294   {
00295     typedef struct  TEncoding_
00296     {
00297       int          platform_id;
00298       int          encoding_id;
00299       FT_Encoding  encoding;
00300 
00301     } TEncoding;
00302 
00303     static
00304     const TEncoding  tt_encodings[] =
00305     {
00306       { TT_PLATFORM_ISO,           -1,                  FT_ENCODING_UNICODE },
00307 
00308       { TT_PLATFORM_APPLE_UNICODE, -1,                  FT_ENCODING_UNICODE },
00309 
00310       { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     FT_ENCODING_APPLE_ROMAN },
00311 
00312       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SYMBOL_CS,  FT_ENCODING_MS_SYMBOL },
00313       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UCS_4,      FT_ENCODING_UNICODE },
00314       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },
00315       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       FT_ENCODING_SJIS },
00316       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     FT_ENCODING_GB2312 },
00317       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      FT_ENCODING_BIG5 },
00318       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    FT_ENCODING_WANSUNG },
00319       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      FT_ENCODING_JOHAB }
00320     };
00321 
00322     const TEncoding  *cur, *limit;
00323 
00324 
00325     cur   = tt_encodings;
00326     limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
00327 
00328     for ( ; cur < limit; cur++ )
00329     {
00330       if ( cur->platform_id == platform_id )
00331       {
00332         if ( cur->encoding_id == encoding_id ||
00333              cur->encoding_id == -1          )
00334           return cur->encoding;
00335       }
00336     }
00337 
00338     return FT_ENCODING_NONE;
00339   }
00340 
00341 
00342   /* Fill in face->ttc_header.  If the font is not a TTC, it is */
00343   /* synthesized into a TTC with one offset table.              */
00344   static FT_Error
00345   sfnt_open_font( FT_Stream  stream,
00346                   TT_Face    face )
00347   {
00348     FT_Memory  memory = stream->memory;
00349     FT_Error   error;
00350     FT_ULong   tag, offset;
00351 
00352     static const FT_Frame_Field  ttc_header_fields[] =
00353     {
00354 #undef  FT_STRUCTURE
00355 #define FT_STRUCTURE  TTC_HeaderRec
00356 
00357       FT_FRAME_START( 8 ),
00358         FT_FRAME_LONG( version ),
00359         FT_FRAME_LONG( count   ),
00360       FT_FRAME_END
00361     };
00362 
00363 
00364     face->ttc_header.tag     = 0;
00365     face->ttc_header.version = 0;
00366     face->ttc_header.count   = 0;
00367 
00368     offset = FT_STREAM_POS();
00369 
00370     if ( FT_READ_ULONG( tag ) )
00371       return error;
00372 
00373     if ( tag != 0x00010000UL &&
00374          tag != TTAG_ttcf    &&
00375          tag != TTAG_OTTO    &&
00376          tag != TTAG_true    &&
00377          tag != TTAG_typ1    &&
00378          tag != 0x00020000UL )
00379       return SFNT_Err_Unknown_File_Format;
00380 
00381     face->ttc_header.tag = TTAG_ttcf;
00382 
00383     if ( tag == TTAG_ttcf )
00384     {
00385       FT_Int  n;
00386 
00387 
00388       FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
00389 
00390       if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
00391         return error;
00392 
00393       /* now read the offsets of each font in the file */
00394       if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
00395         return error;
00396 
00397       if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
00398         return error;
00399 
00400       for ( n = 0; n < face->ttc_header.count; n++ )
00401         face->ttc_header.offsets[n] = FT_GET_ULONG();
00402 
00403       FT_FRAME_EXIT();
00404     }
00405     else
00406     {
00407       FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
00408 
00409       face->ttc_header.version = 1 << 16;
00410       face->ttc_header.count   = 1;
00411 
00412       if ( FT_NEW( face->ttc_header.offsets ) )
00413         return error;
00414 
00415       face->ttc_header.offsets[0] = offset;
00416     }
00417 
00418     return error;
00419   }
00420 
00421 
00422   FT_LOCAL_DEF( FT_Error )
00423   sfnt_init_face( FT_Stream      stream,
00424                   TT_Face        face,
00425                   FT_Int         face_index,
00426                   FT_Int         num_params,
00427                   FT_Parameter*  params )
00428   {
00429     FT_Error        error;
00430     FT_Library      library = face->root.driver->root.library;
00431     SFNT_Service    sfnt;
00432 
00433 
00434     /* for now, parameters are unused */
00435     FT_UNUSED( num_params );
00436     FT_UNUSED( params );
00437 
00438 
00439     sfnt = (SFNT_Service)face->sfnt;
00440     if ( !sfnt )
00441     {
00442       sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
00443       if ( !sfnt )
00444         return SFNT_Err_Invalid_File_Format;
00445 
00446       face->sfnt       = sfnt;
00447       face->goto_table = sfnt->goto_table;
00448     }
00449 
00450     FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
00451 
00452     error = sfnt_open_font( stream, face );
00453     if ( error )
00454       return error;
00455 
00456     FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
00457 
00458     if ( face_index < 0 )
00459       face_index = 0;
00460 
00461     if ( face_index >= face->ttc_header.count )
00462       return SFNT_Err_Invalid_Argument;
00463 
00464     if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
00465       return error;
00466 
00467     /* check that we have a valid TrueType file */
00468     error = sfnt->load_font_dir( face, stream );
00469     if ( error )
00470       return error;
00471 
00472     face->root.num_faces  = face->ttc_header.count;
00473     face->root.face_index = face_index;
00474 
00475     return error;
00476   }
00477 
00478 
00479 #define LOAD_( x )                                            \
00480   do {                                                        \
00481     FT_TRACE2(( "`" #x "' " ));                               \
00482     FT_TRACE3(( "-->\n" ));                                   \
00483                                                               \
00484     error = sfnt->load_##x( face, stream );                   \
00485                                                               \
00486     FT_TRACE2(( "%s\n", ( !error )                            \
00487                         ? "loaded"                            \
00488                         : ( error == SFNT_Err_Table_Missing ) \
00489                           ? "missing"                         \
00490                           : "failed to load" ));              \
00491     FT_TRACE3(( "\n" ));                                      \
00492   } while ( 0 )
00493 
00494 #define LOADM_( x, vertical )                                 \
00495   do {                                                        \
00496     FT_TRACE2(( "`%s" #x "' ",                                \
00497                 vertical ? "vertical " : "" ));               \
00498     FT_TRACE3(( "-->\n" ));                                   \
00499                                                               \
00500     error = sfnt->load_##x( face, stream, vertical );         \
00501                                                               \
00502     FT_TRACE2(( "%s\n", ( !error )                            \
00503                         ? "loaded"                            \
00504                         : ( error == SFNT_Err_Table_Missing ) \
00505                           ? "missing"                         \
00506                           : "failed to load" ));              \
00507     FT_TRACE3(( "\n" ));                                      \
00508   } while ( 0 )
00509 
00510 #define GET_NAME( id, field )                                 \
00511   do {                                                        \
00512     error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \
00513     if ( error )                                              \
00514       goto Exit;                                              \
00515   } while ( 0 )
00516 
00517 
00518   FT_LOCAL_DEF( FT_Error )
00519   sfnt_load_face( FT_Stream      stream,
00520                   TT_Face        face,
00521                   FT_Int         face_index,
00522                   FT_Int         num_params,
00523                   FT_Parameter*  params )
00524   {
00525     FT_Error      error;
00526 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
00527     FT_Error      psnames_error;
00528 #endif
00529     FT_Bool       has_outline;
00530     FT_Bool       is_apple_sbit;
00531     FT_Bool       ignore_preferred_family = FALSE;
00532     FT_Bool       ignore_preferred_subfamily = FALSE;
00533 
00534     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
00535 
00536     FT_UNUSED( face_index );
00537 
00538     /* Check parameters */
00539     
00540     {
00541       FT_Int  i;
00542 
00543 
00544       for ( i = 0; i < num_params; i++ )
00545       {
00546         if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY )
00547           ignore_preferred_family = TRUE;
00548         else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY )
00549           ignore_preferred_subfamily = TRUE;
00550       }
00551     }
00552 
00553     /* Load tables */
00554 
00555     /* We now support two SFNT-based bitmapped font formats.  They */
00556     /* are recognized easily as they do not include a `glyf'       */
00557     /* table.                                                      */
00558     /*                                                             */
00559     /* The first format comes from Apple, and uses a table named   */
00560     /* `bhed' instead of `head' to store the font header (using    */
00561     /* the same format).  It also doesn't include horizontal and   */
00562     /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
00563     /* missing).                                                   */
00564     /*                                                             */
00565     /* The other format comes from Microsoft, and is used with     */
00566     /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
00567     /* it doesn't contain outlines.                                */
00568     /*                                                             */
00569 
00570     FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));
00571 
00572     /* do we have outlines in there? */
00573 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00574     has_outline   = FT_BOOL( face->root.internal->incremental_interface != 0 ||
00575                              tt_face_lookup_table( face, TTAG_glyf )    != 0 ||
00576                              tt_face_lookup_table( face, TTAG_CFF )     != 0 );
00577 #else
00578     has_outline   = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
00579                              tt_face_lookup_table( face, TTAG_CFF )  != 0 );
00580 #endif
00581 
00582     is_apple_sbit = 0;
00583 
00584     /* if this font doesn't contain outlines, we try to load */
00585     /* a `bhed' table                                        */
00586     if ( !has_outline && sfnt->load_bhed )
00587     {
00588       LOAD_( bhed );
00589       is_apple_sbit = FT_BOOL( !error );
00590     }
00591 
00592     /* load the font header (`head' table) if this isn't an Apple */
00593     /* sbit font file                                             */
00594     if ( !is_apple_sbit )
00595     {
00596       LOAD_( head );
00597       if ( error )
00598         goto Exit;
00599     }
00600 
00601     if ( face->header.Units_Per_EM == 0 )
00602     {
00603       error = SFNT_Err_Invalid_Table;
00604 
00605       goto Exit;
00606     }
00607 
00608     /* the following tables are often not present in embedded TrueType */
00609     /* fonts within PDF documents, so don't check for them.            */
00610     LOAD_( maxp );
00611     LOAD_( cmap );
00612 
00613     /* the following tables are optional in PCL fonts -- */
00614     /* don't check for errors                            */
00615     LOAD_( name );
00616     LOAD_( post );
00617 
00618 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
00619     psnames_error = error;
00620 #endif
00621 
00622     /* do not load the metrics headers and tables if this is an Apple */
00623     /* sbit font file                                                 */
00624     if ( !is_apple_sbit )
00625     {
00626       /* load the `hhea' and `hmtx' tables */
00627       LOADM_( hhea, 0 );
00628       if ( !error )
00629       {
00630         LOADM_( hmtx, 0 );
00631         if ( error == SFNT_Err_Table_Missing )
00632         {
00633           error = SFNT_Err_Hmtx_Table_Missing;
00634 
00635 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00636           /* If this is an incrementally loaded font and there are */
00637           /* overriding metrics, tolerate a missing `hmtx' table.  */
00638           if ( face->root.internal->incremental_interface          &&
00639                face->root.internal->incremental_interface->funcs->
00640                  get_glyph_metrics                                 )
00641           {
00642             face->horizontal.number_Of_HMetrics = 0;
00643             error = SFNT_Err_Ok;
00644           }
00645 #endif
00646         }
00647       }
00648       else if ( error == SFNT_Err_Table_Missing )
00649       {
00650         /* No `hhea' table necessary for SFNT Mac fonts. */
00651         if ( face->format_tag == TTAG_true )
00652         {
00653           FT_TRACE2(( "This is an SFNT Mac font.\n" ));
00654           has_outline = 0;
00655           error = SFNT_Err_Ok;
00656         }
00657         else
00658         {
00659           error = SFNT_Err_Horiz_Header_Missing;
00660 
00661 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00662           /* If this is an incrementally loaded font and there are */
00663           /* overriding metrics, tolerate a missing `hhea' table.  */
00664           if ( face->root.internal->incremental_interface          &&
00665                face->root.internal->incremental_interface->funcs->
00666                  get_glyph_metrics                                 )
00667           {
00668             face->horizontal.number_Of_HMetrics = 0;
00669             error = SFNT_Err_Ok;
00670           }
00671 #endif
00672 
00673         }
00674       }
00675 
00676       if ( error )
00677         goto Exit;
00678 
00679       /* try to load the `vhea' and `vmtx' tables */
00680       LOADM_( hhea, 1 );
00681       if ( !error )
00682       {
00683         LOADM_( hmtx, 1 );
00684         if ( !error )
00685           face->vertical_info = 1;
00686       }
00687 
00688       if ( error && error != SFNT_Err_Table_Missing )
00689         goto Exit;
00690 
00691       LOAD_( os2 );
00692       if ( error )
00693       {
00694         /* we treat the table as missing if there are any errors */
00695         face->os2.version = 0xFFFFU;
00696       }
00697     }
00698 
00699     /* the optional tables */
00700 
00701     /* embedded bitmap support */
00702     if ( sfnt->load_eblc )
00703     {
00704       LOAD_( eblc );
00705       if ( error )
00706       {
00707         /* a font which contains neither bitmaps nor outlines is */
00708         /* still valid (although rather useless in most cases);  */
00709         /* however, you can find such stripped fonts in PDFs     */
00710         if ( error == SFNT_Err_Table_Missing )
00711           error = SFNT_Err_Ok;
00712         else
00713           goto Exit;
00714       }
00715     }
00716 
00717     LOAD_( pclt );
00718     if ( error )
00719     {
00720       if ( error != SFNT_Err_Table_Missing )
00721         goto Exit;
00722 
00723       face->pclt.Version = 0;
00724     }
00725 
00726     /* consider the kerning and gasp tables as optional */
00727     LOAD_( gasp );
00728     LOAD_( kern );
00729 
00730     face->root.num_glyphs = face->max_profile.numGlyphs;
00731 
00732     /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
00733     /* a WWS-only font face.  `WWS' stands for `weight', width', and */
00734     /* `slope', a term used by Microsoft's Windows Presentation      */
00735     /* Foundation (WPF).  This flag has been introduced in version   */
00736     /* 1.5 of the OpenType specification (May 2008).                 */
00737 
00738     face->root.family_name = NULL;
00739     face->root.style_name  = NULL;
00740     if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 )
00741     {
00742       if ( !ignore_preferred_family )
00743         GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
00744       if ( !face->root.family_name )
00745         GET_NAME( FONT_FAMILY, &face->root.family_name );
00746 
00747       if ( !ignore_preferred_subfamily )
00748         GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
00749       if ( !face->root.style_name )
00750         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
00751     }
00752     else
00753     {
00754       GET_NAME( WWS_FAMILY, &face->root.family_name );
00755       if ( !face->root.family_name && !ignore_preferred_family )
00756         GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
00757       if ( !face->root.family_name )
00758         GET_NAME( FONT_FAMILY, &face->root.family_name );
00759 
00760       GET_NAME( WWS_SUBFAMILY, &face->root.style_name );
00761       if ( !face->root.style_name && !ignore_preferred_subfamily )
00762         GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
00763       if ( !face->root.style_name )
00764         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
00765     }
00766 
00767     /* now set up root fields */
00768     {
00769       FT_Face  root  = &face->root;
00770       FT_Long  flags = root->face_flags;
00771 
00772 
00773       /*********************************************************************/
00774       /*                                                                   */
00775       /* Compute face flags.                                               */
00776       /*                                                                   */
00777       if ( has_outline == TRUE )
00778         flags |= FT_FACE_FLAG_SCALABLE;   /* scalable outlines */
00779 
00780       /* The sfnt driver only supports bitmap fonts natively, thus we */
00781       /* don't set FT_FACE_FLAG_HINTER.                               */
00782       flags |= FT_FACE_FLAG_SFNT       |  /* SFNT file format  */
00783                FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
00784 
00785 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
00786       if ( psnames_error == SFNT_Err_Ok               &&
00787            face->postscript.FormatType != 0x00030000L )
00788         flags |= FT_FACE_FLAG_GLYPH_NAMES;
00789 #endif
00790 
00791       /* fixed width font? */
00792       if ( face->postscript.isFixedPitch )
00793         flags |= FT_FACE_FLAG_FIXED_WIDTH;
00794 
00795       /* vertical information? */
00796       if ( face->vertical_info )
00797         flags |= FT_FACE_FLAG_VERTICAL;
00798 
00799       /* kerning available ? */
00800       if ( TT_FACE_HAS_KERNING( face ) )
00801         flags |= FT_FACE_FLAG_KERNING;
00802 
00803 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00804       /* Don't bother to load the tables unless somebody asks for them. */
00805       /* No need to do work which will (probably) not be used.          */
00806       if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
00807            tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
00808            tt_face_lookup_table( face, TTAG_gvar ) != 0 )
00809         flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
00810 #endif
00811 
00812       root->face_flags = flags;
00813 
00814       /*********************************************************************/
00815       /*                                                                   */
00816       /* Compute style flags.                                              */
00817       /*                                                                   */
00818 
00819       flags = 0;
00820       if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
00821       {
00822         /* We have an OS/2 table; use the `fsSelection' field.  Bit 9 */
00823         /* indicates an oblique font face.  This flag has been        */
00824         /* introduced in version 1.5 of the OpenType specification.   */
00825 
00826         if ( face->os2.fsSelection & 512 )       /* bit 9 */
00827           flags |= FT_STYLE_FLAG_ITALIC;
00828         else if ( face->os2.fsSelection & 1 )    /* bit 0 */
00829           flags |= FT_STYLE_FLAG_ITALIC;
00830 
00831         if ( face->os2.fsSelection & 32 )        /* bit 5 */
00832           flags |= FT_STYLE_FLAG_BOLD;
00833       }
00834       else
00835       {
00836         /* this is an old Mac font, use the header field */
00837 
00838         if ( face->header.Mac_Style & 1 )
00839           flags |= FT_STYLE_FLAG_BOLD;
00840 
00841         if ( face->header.Mac_Style & 2 )
00842           flags |= FT_STYLE_FLAG_ITALIC;
00843       }
00844 
00845       root->style_flags = flags;
00846 
00847       /*********************************************************************/
00848       /*                                                                   */
00849       /* Polish the charmaps.                                              */
00850       /*                                                                   */
00851       /*   Try to set the charmap encoding according to the platform &     */
00852       /*   encoding ID of each charmap.                                    */
00853       /*                                                                   */
00854 
00855       tt_face_build_cmaps( face );  /* ignore errors */
00856 
00857 
00858       /* set the encoding fields */
00859       {
00860         FT_Int  m;
00861 
00862 
00863         for ( m = 0; m < root->num_charmaps; m++ )
00864         {
00865           FT_CharMap  charmap = root->charmaps[m];
00866 
00867 
00868           charmap->encoding = sfnt_find_encoding( charmap->platform_id,
00869                                                   charmap->encoding_id );
00870 
00871 #if 0
00872           if ( root->charmap     == NULL &&
00873                charmap->encoding == FT_ENCODING_UNICODE )
00874           {
00875             /* set 'root->charmap' to the first Unicode encoding we find */
00876             root->charmap = charmap;
00877           }
00878 #endif
00879         }
00880       }
00881 
00882 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
00883 
00884       /*
00885        *  Now allocate the root array of FT_Bitmap_Size records and
00886        *  populate them.  Unfortunately, it isn't possible to indicate bit
00887        *  depths in the FT_Bitmap_Size record.  This is a design error.
00888        */
00889       {
00890         FT_UInt  i, count;
00891 
00892 
00893 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
00894         count = face->sbit_num_strikes;
00895 #else
00896         count = (FT_UInt)face->num_sbit_strikes;
00897 #endif
00898 
00899         if ( count > 0 )
00900         {
00901           FT_Memory        memory   = face->root.stream->memory;
00902           FT_UShort        em_size  = face->header.Units_Per_EM;
00903           FT_Short         avgwidth = face->os2.xAvgCharWidth;
00904           FT_Size_Metrics  metrics;
00905 
00906 
00907           if ( em_size == 0 || face->os2.version == 0xFFFFU )
00908           {
00909             avgwidth = 0;
00910             em_size = 1;
00911           }
00912 
00913           if ( FT_NEW_ARRAY( root->available_sizes, count ) )
00914             goto Exit;
00915 
00916           for ( i = 0; i < count; i++ )
00917           {
00918             FT_Bitmap_Size*  bsize = root->available_sizes + i;
00919 
00920 
00921             error = sfnt->load_strike_metrics( face, i, &metrics );
00922             if ( error )
00923               goto Exit;
00924 
00925             bsize->height = (FT_Short)( metrics.height >> 6 );
00926             bsize->width = (FT_Short)(
00927                 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
00928 
00929             bsize->x_ppem = metrics.x_ppem << 6;
00930             bsize->y_ppem = metrics.y_ppem << 6;
00931 
00932             /* assume 72dpi */
00933             bsize->size   = metrics.y_ppem << 6;
00934           }
00935 
00936           root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
00937           root->num_fixed_sizes = (FT_Int)count;
00938         }
00939       }
00940 
00941 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
00942 
00943       /* a font with no bitmaps and no outlines is scalable; */
00944       /* it has only empty glyphs then                       */
00945       if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) )
00946         root->face_flags |= FT_FACE_FLAG_SCALABLE;
00947 
00948 
00949       /*********************************************************************/
00950       /*                                                                   */
00951       /*  Set up metrics.                                                  */
00952       /*                                                                   */
00953       if ( FT_IS_SCALABLE( root ) )
00954       {
00955         /* XXX What about if outline header is missing */
00956         /*     (e.g. sfnt wrapped bitmap)?             */
00957         root->bbox.xMin    = face->header.xMin;
00958         root->bbox.yMin    = face->header.yMin;
00959         root->bbox.xMax    = face->header.xMax;
00960         root->bbox.yMax    = face->header.yMax;
00961         root->units_per_EM = face->header.Units_Per_EM;
00962 
00963 
00964         /* XXX: Computing the ascender/descender/height is very different */
00965         /*      from what the specification tells you.  Apparently, we    */
00966         /*      must be careful because                                   */
00967         /*                                                                */
00968         /*      - not all fonts have an OS/2 table; in this case, we take */
00969         /*        the values in the horizontal header.  However, these    */
00970         /*        values very often are not reliable.                     */
00971         /*                                                                */
00972         /*      - otherwise, the correct typographic values are in the    */
00973         /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
00974         /*                                                                */
00975         /*        However, certain fonts have these fields set to 0.      */
00976         /*        Rather, they have usWinAscent & usWinDescent correctly  */
00977         /*        set (but with different values).                        */
00978         /*                                                                */
00979         /*      As an example, Arial Narrow is implemented through four   */
00980         /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
00981         /*                                                                */
00982         /*      Strangely, all fonts have the same values in their        */
00983         /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
00984         /*                                                                */
00985         /*      On the other hand, they all have different                */
00986         /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
00987         /*      table cannot be used to compute the text height reliably! */
00988         /*                                                                */
00989 
00990         /* The ascender/descender/height are computed from the OS/2 table */
00991         /* when found.  Otherwise, they're taken from the horizontal      */
00992         /* header.                                                        */
00993         /*                                                                */
00994 
00995         root->ascender  = face->horizontal.Ascender;
00996         root->descender = face->horizontal.Descender;
00997 
00998         root->height    = (FT_Short)( root->ascender - root->descender +
00999                                       face->horizontal.Line_Gap );
01000 
01001 #if 0
01002         /* if the line_gap is 0, we add an extra 15% to the text height --  */
01003         /* this computation is based on various versions of Times New Roman */
01004         if ( face->horizontal.Line_Gap == 0 )
01005           root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
01006 #endif /* 0 */
01007 
01008 #if 0
01009         /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
01010         /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
01011         if ( face->os2.version != 0xFFFFU && root->ascender )
01012         {
01013           FT_Int  height;
01014 
01015 
01016           root->ascender  =  face->os2.sTypoAscender;
01017           root->descender = -face->os2.sTypoDescender;
01018 
01019           height = root->ascender + root->descender + face->os2.sTypoLineGap;
01020           if ( height > root->height )
01021             root->height = height;
01022         }
01023 #endif /* 0 */
01024 
01025         root->max_advance_width  = face->horizontal.advance_Width_Max;
01026         root->max_advance_height = (FT_Short)( face->vertical_info
01027                                      ? face->vertical.advance_Height_Max
01028                                      : root->height );
01029 
01030         /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
01031         /* Adjust underline position from top edge to centre of     */
01032         /* stroke to convert TrueType meaning to FreeType meaning.  */
01033         root->underline_position  = face->postscript.underlinePosition -
01034                                     face->postscript.underlineThickness / 2;
01035         root->underline_thickness = face->postscript.underlineThickness;
01036       }
01037 
01038     }
01039 
01040   Exit:
01041     FT_TRACE2(( "sfnt_load_face: done\n" ));
01042 
01043     return error;
01044   }
01045 
01046 
01047 #undef LOAD_
01048 #undef LOADM_
01049 #undef GET_NAME
01050 
01051 
01052   FT_LOCAL_DEF( void )
01053   sfnt_done_face( TT_Face  face )
01054   {
01055     FT_Memory     memory;
01056     SFNT_Service  sfnt;
01057 
01058 
01059     if ( !face )
01060       return;
01061 
01062     memory = face->root.memory;
01063     sfnt   = (SFNT_Service)face->sfnt;
01064 
01065     if ( sfnt )
01066     {
01067       /* destroy the postscript names table if it is loaded */
01068       if ( sfnt->free_psnames )
01069         sfnt->free_psnames( face );
01070 
01071       /* destroy the embedded bitmaps table if it is loaded */
01072       if ( sfnt->free_eblc )
01073         sfnt->free_eblc( face );
01074     }
01075 
01076 #ifdef TT_CONFIG_OPTION_BDF
01077     /* freeing the embedded BDF properties */
01078     tt_face_free_bdf_props( face );
01079 #endif
01080 
01081     /* freeing the kerning table */
01082     tt_face_done_kern( face );
01083 
01084     /* freeing the collection table */
01085     FT_FREE( face->ttc_header.offsets );
01086     face->ttc_header.count = 0;
01087 
01088     /* freeing table directory */
01089     FT_FREE( face->dir_tables );
01090     face->num_tables = 0;
01091 
01092     {
01093       FT_Stream  stream = FT_FACE_STREAM( face );
01094 
01095 
01096       /* simply release the 'cmap' table frame */
01097       FT_FRAME_RELEASE( face->cmap_table );
01098       face->cmap_size = 0;
01099     }
01100 
01101     /* freeing the horizontal metrics */
01102 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
01103     {
01104       FT_Stream  stream = FT_FACE_STREAM( face );
01105 
01106 
01107       FT_FRAME_RELEASE( face->horz_metrics );
01108       FT_FRAME_RELEASE( face->vert_metrics );
01109       face->horz_metrics_size = 0;
01110       face->vert_metrics_size = 0;
01111     }
01112 #else
01113     FT_FREE( face->horizontal.long_metrics );
01114     FT_FREE( face->horizontal.short_metrics );
01115 #endif
01116 
01117     /* freeing the vertical ones, if any */
01118     if ( face->vertical_info )
01119     {
01120       FT_FREE( face->vertical.long_metrics  );
01121       FT_FREE( face->vertical.short_metrics );
01122       face->vertical_info = 0;
01123     }
01124 
01125     /* freeing the gasp table */
01126     FT_FREE( face->gasp.gaspRanges );
01127     face->gasp.numRanges = 0;
01128 
01129     /* freeing the name table */
01130     if ( sfnt )
01131       sfnt->free_name( face );
01132 
01133     /* freeing family and style name */
01134     FT_FREE( face->root.family_name );
01135     FT_FREE( face->root.style_name );
01136 
01137     /* freeing sbit size table */
01138     FT_FREE( face->root.available_sizes );
01139     face->root.num_fixed_sizes = 0;
01140 
01141     FT_FREE( face->postscript_name );
01142 
01143     face->sfnt = 0;
01144   }
01145 
01146 
01147 /* END */

Generated on Sat May 26 2012 04:32:55 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.