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

winfnt.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  winfnt.c                                                               */
00004 /*                                                                         */
00005 /*    FreeType font driver for Windows FNT/FON files                       */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010 by */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*  Copyright 2003 Huw D M Davies for Codeweavers                          */
00010 /*  Copyright 2007 Dmitry Timoshkov for Codeweavers                        */
00011 /*                                                                         */
00012 /*  This file is part of the FreeType project, and may only be used,       */
00013 /*  modified, and distributed under the terms of the FreeType project      */
00014 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00015 /*  this file you indicate that you have read the license and              */
00016 /*  understand and accept it fully.                                        */
00017 /*                                                                         */
00018 /***************************************************************************/
00019 
00020 
00021 #include <ft2build.h>
00022 #include FT_WINFONTS_H
00023 #include FT_INTERNAL_DEBUG_H
00024 #include FT_INTERNAL_STREAM_H
00025 #include FT_INTERNAL_OBJECTS_H
00026 #include FT_TRUETYPE_IDS_H 
00027 
00028 #include "winfnt.h"
00029 #include "fnterrs.h"
00030 #include FT_SERVICE_WINFNT_H
00031 #include FT_SERVICE_XFREE86_NAME_H
00032 
00033   /*************************************************************************/
00034   /*                                                                       */
00035   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00036   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00037   /* messages during execution.                                            */
00038   /*                                                                       */
00039 #undef  FT_COMPONENT
00040 #define FT_COMPONENT  trace_winfnt
00041 
00042 
00043   static const FT_Frame_Field  winmz_header_fields[] =
00044   {
00045 #undef  FT_STRUCTURE
00046 #define FT_STRUCTURE  WinMZ_HeaderRec
00047 
00048     FT_FRAME_START( 64 ),
00049       FT_FRAME_USHORT_LE ( magic ),
00050       FT_FRAME_SKIP_BYTES( 29 * 2 ),
00051       FT_FRAME_ULONG_LE  ( lfanew ),
00052     FT_FRAME_END
00053   };
00054 
00055   static const FT_Frame_Field  winne_header_fields[] =
00056   {
00057 #undef  FT_STRUCTURE
00058 #define FT_STRUCTURE  WinNE_HeaderRec
00059 
00060     FT_FRAME_START( 40 ),
00061       FT_FRAME_USHORT_LE ( magic ),
00062       FT_FRAME_SKIP_BYTES( 34 ),
00063       FT_FRAME_USHORT_LE ( resource_tab_offset ),
00064       FT_FRAME_USHORT_LE ( rname_tab_offset ),
00065     FT_FRAME_END
00066   };
00067 
00068   static const FT_Frame_Field  winpe32_header_fields[] =
00069   {
00070 #undef  FT_STRUCTURE
00071 #define FT_STRUCTURE  WinPE32_HeaderRec
00072 
00073     FT_FRAME_START( 248 ),
00074       FT_FRAME_ULONG_LE  ( magic ),   /* PE00 */
00075       FT_FRAME_USHORT_LE ( machine ), /* 0x014c - i386 */
00076       FT_FRAME_USHORT_LE ( number_of_sections ),
00077       FT_FRAME_SKIP_BYTES( 12 ),
00078       FT_FRAME_USHORT_LE ( size_of_optional_header ),
00079       FT_FRAME_SKIP_BYTES( 2 ),
00080       FT_FRAME_USHORT_LE ( magic32 ), /* 0x10b */
00081       FT_FRAME_SKIP_BYTES( 110 ),
00082       FT_FRAME_ULONG_LE  ( rsrc_virtual_address ),
00083       FT_FRAME_ULONG_LE  ( rsrc_size ),
00084       FT_FRAME_SKIP_BYTES( 104 ),
00085     FT_FRAME_END
00086   };
00087 
00088   static const FT_Frame_Field  winpe32_section_fields[] =
00089   {
00090 #undef  FT_STRUCTURE
00091 #define FT_STRUCTURE  WinPE32_SectionRec
00092 
00093     FT_FRAME_START( 40 ),
00094       FT_FRAME_BYTES     ( name, 8 ),
00095       FT_FRAME_SKIP_BYTES( 4 ),
00096       FT_FRAME_ULONG_LE  ( virtual_address ),
00097       FT_FRAME_ULONG_LE  ( size_of_raw_data ),
00098       FT_FRAME_ULONG_LE  ( pointer_to_raw_data ),
00099       FT_FRAME_SKIP_BYTES( 16 ),
00100     FT_FRAME_END
00101   };
00102 
00103   static const FT_Frame_Field  winpe_rsrc_dir_fields[] =
00104   {
00105 #undef  FT_STRUCTURE
00106 #define FT_STRUCTURE  WinPE_RsrcDirRec
00107 
00108     FT_FRAME_START( 16 ),
00109       FT_FRAME_ULONG_LE ( characteristics ),
00110       FT_FRAME_ULONG_LE ( time_date_stamp ),
00111       FT_FRAME_USHORT_LE( major_version ),
00112       FT_FRAME_USHORT_LE( minor_version ),
00113       FT_FRAME_USHORT_LE( number_of_named_entries ),
00114       FT_FRAME_USHORT_LE( number_of_id_entries ),
00115     FT_FRAME_END
00116   };
00117 
00118   static const FT_Frame_Field  winpe_rsrc_dir_entry_fields[] =
00119   {
00120 #undef  FT_STRUCTURE
00121 #define FT_STRUCTURE  WinPE_RsrcDirEntryRec
00122 
00123     FT_FRAME_START( 8 ),
00124       FT_FRAME_ULONG_LE( name ),
00125       FT_FRAME_ULONG_LE( offset ),
00126     FT_FRAME_END
00127   };
00128 
00129   static const FT_Frame_Field  winpe_rsrc_data_entry_fields[] =
00130   {
00131 #undef  FT_STRUCTURE
00132 #define FT_STRUCTURE  WinPE_RsrcDataEntryRec
00133 
00134     FT_FRAME_START( 16 ),
00135       FT_FRAME_ULONG_LE( offset_to_data ),
00136       FT_FRAME_ULONG_LE( size ),
00137       FT_FRAME_ULONG_LE( code_page ),
00138       FT_FRAME_ULONG_LE( reserved ),
00139     FT_FRAME_END
00140   };
00141 
00142   static const FT_Frame_Field  winfnt_header_fields[] =
00143   {
00144 #undef  FT_STRUCTURE
00145 #define FT_STRUCTURE  FT_WinFNT_HeaderRec
00146 
00147     FT_FRAME_START( 148 ),
00148       FT_FRAME_USHORT_LE( version ),
00149       FT_FRAME_ULONG_LE ( file_size ),
00150       FT_FRAME_BYTES    ( copyright, 60 ),
00151       FT_FRAME_USHORT_LE( file_type ),
00152       FT_FRAME_USHORT_LE( nominal_point_size ),
00153       FT_FRAME_USHORT_LE( vertical_resolution ),
00154       FT_FRAME_USHORT_LE( horizontal_resolution ),
00155       FT_FRAME_USHORT_LE( ascent ),
00156       FT_FRAME_USHORT_LE( internal_leading ),
00157       FT_FRAME_USHORT_LE( external_leading ),
00158       FT_FRAME_BYTE     ( italic ),
00159       FT_FRAME_BYTE     ( underline ),
00160       FT_FRAME_BYTE     ( strike_out ),
00161       FT_FRAME_USHORT_LE( weight ),
00162       FT_FRAME_BYTE     ( charset ),
00163       FT_FRAME_USHORT_LE( pixel_width ),
00164       FT_FRAME_USHORT_LE( pixel_height ),
00165       FT_FRAME_BYTE     ( pitch_and_family ),
00166       FT_FRAME_USHORT_LE( avg_width ),
00167       FT_FRAME_USHORT_LE( max_width ),
00168       FT_FRAME_BYTE     ( first_char ),
00169       FT_FRAME_BYTE     ( last_char ),
00170       FT_FRAME_BYTE     ( default_char ),
00171       FT_FRAME_BYTE     ( break_char ),
00172       FT_FRAME_USHORT_LE( bytes_per_row ),
00173       FT_FRAME_ULONG_LE ( device_offset ),
00174       FT_FRAME_ULONG_LE ( face_name_offset ),
00175       FT_FRAME_ULONG_LE ( bits_pointer ),
00176       FT_FRAME_ULONG_LE ( bits_offset ),
00177       FT_FRAME_BYTE     ( reserved ),
00178       FT_FRAME_ULONG_LE ( flags ),
00179       FT_FRAME_USHORT_LE( A_space ),
00180       FT_FRAME_USHORT_LE( B_space ),
00181       FT_FRAME_USHORT_LE( C_space ),
00182       FT_FRAME_ULONG_LE ( color_table_offset ),
00183       FT_FRAME_BYTES    ( reserved1, 16 ),
00184     FT_FRAME_END
00185   };
00186 
00187 
00188   static void
00189   fnt_font_done( FNT_Face face )
00190   {
00191     FT_Memory  memory = FT_FACE( face )->memory;
00192     FT_Stream  stream = FT_FACE( face )->stream;
00193     FNT_Font   font   = face->font;
00194 
00195 
00196     if ( !font )
00197       return;
00198 
00199     if ( font->fnt_frame )
00200       FT_FRAME_RELEASE( font->fnt_frame );
00201     FT_FREE( font->family_name );
00202 
00203     FT_FREE( font );
00204     face->font = 0;
00205   }
00206 
00207 
00208   static FT_Error
00209   fnt_font_load( FNT_Font   font,
00210                  FT_Stream  stream )
00211   {
00212     FT_Error          error;
00213     FT_WinFNT_Header  header = &font->header;
00214     FT_Bool           new_format;
00215     FT_UInt           size;
00216 
00217 
00218     /* first of all, read the FNT header */
00219     if ( FT_STREAM_SEEK( font->offset )                        ||
00220          FT_STREAM_READ_FIELDS( winfnt_header_fields, header ) )
00221       goto Exit;
00222 
00223     /* check header */
00224     if ( header->version != 0x200 &&
00225          header->version != 0x300 )
00226     {
00227       FT_TRACE2(( "[not a valid FNT file]\n" ));
00228       error = FNT_Err_Unknown_File_Format;
00229       goto Exit;
00230     }
00231 
00232     new_format = FT_BOOL( font->header.version == 0x300 );
00233     size       = new_format ? 148 : 118;
00234 
00235     if ( header->file_size < size )
00236     {
00237       FT_TRACE2(( "[not a valid FNT file]\n" ));
00238       error = FNT_Err_Unknown_File_Format;
00239       goto Exit;
00240     }
00241 
00242     /* Version 2 doesn't have these fields */
00243     if ( header->version == 0x200 )
00244     {
00245       header->flags   = 0;
00246       header->A_space = 0;
00247       header->B_space = 0;
00248       header->C_space = 0;
00249 
00250       header->color_table_offset = 0;
00251     }
00252 
00253     if ( header->file_type & 1 )
00254     {
00255       FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));
00256       error = FNT_Err_Unknown_File_Format;
00257       goto Exit;
00258     }
00259 
00260     /* this is a FNT file/table; extract its frame */
00261     if ( FT_STREAM_SEEK( font->offset )                         ||
00262          FT_FRAME_EXTRACT( header->file_size, font->fnt_frame ) )
00263       goto Exit;
00264 
00265   Exit:
00266     return error;
00267   }
00268 
00269 
00270   static FT_Error
00271   fnt_face_get_dll_font( FNT_Face  face,
00272                          FT_Int    face_index )
00273   {
00274     FT_Error         error;
00275     FT_Stream        stream = FT_FACE( face )->stream;
00276     FT_Memory        memory = FT_FACE( face )->memory;
00277     WinMZ_HeaderRec  mz_header;
00278 
00279 
00280     face->font = 0;
00281 
00282     /* does it begin with an MZ header? */
00283     if ( FT_STREAM_SEEK( 0 )                                      ||
00284          FT_STREAM_READ_FIELDS( winmz_header_fields, &mz_header ) )
00285       goto Exit;
00286 
00287     error = FNT_Err_Unknown_File_Format;
00288     if ( mz_header.magic == WINFNT_MZ_MAGIC )
00289     {
00290       /* yes, now look for an NE header in the file */
00291       WinNE_HeaderRec  ne_header;
00292 
00293 
00294       FT_TRACE2(( "MZ signature found\n" ));
00295 
00296       if ( FT_STREAM_SEEK( mz_header.lfanew )                       ||
00297            FT_STREAM_READ_FIELDS( winne_header_fields, &ne_header ) )
00298         goto Exit;
00299 
00300       error = FNT_Err_Unknown_File_Format;
00301       if ( ne_header.magic == WINFNT_NE_MAGIC )
00302       {
00303         /* good, now look into the resource table for each FNT resource */
00304         FT_ULong   res_offset  = mz_header.lfanew +
00305                                    ne_header.resource_tab_offset;
00306         FT_UShort  size_shift;
00307         FT_UShort  font_count  = 0;
00308         FT_ULong   font_offset = 0;
00309 
00310 
00311         FT_TRACE2(( "NE signature found\n" ));
00312 
00313         if ( FT_STREAM_SEEK( res_offset )                    ||
00314              FT_FRAME_ENTER( ne_header.rname_tab_offset -
00315                              ne_header.resource_tab_offset ) )
00316           goto Exit;
00317 
00318         size_shift = FT_GET_USHORT_LE();
00319 
00320         for (;;)
00321         {
00322           FT_UShort  type_id, count;
00323 
00324 
00325           type_id = FT_GET_USHORT_LE();
00326           if ( !type_id )
00327             break;
00328 
00329           count = FT_GET_USHORT_LE();
00330 
00331           if ( type_id == 0x8008U )
00332           {
00333             font_count  = count;
00334             font_offset = (FT_ULong)( FT_STREAM_POS() + 4 +
00335                                       ( stream->cursor - stream->limit ) );
00336             break;
00337           }
00338 
00339           stream->cursor += 4 + count * 12;
00340         }
00341 
00342         FT_FRAME_EXIT();
00343 
00344         if ( !font_count || !font_offset )
00345         {
00346           FT_TRACE2(( "this file doesn't contain any FNT resources\n" ));
00347           error = FNT_Err_Invalid_File_Format;
00348           goto Exit;
00349         }
00350 
00351         /* loading `winfnt_header_fields' needs at least 118 bytes;    */
00352         /* use this as a rough measure to check the expected font size */
00353         if ( font_count * 118UL > stream->size )
00354         {
00355           FT_TRACE2(( "invalid number of faces\n" ));
00356           error = FNT_Err_Invalid_File_Format;
00357           goto Exit;
00358         }
00359 
00360         face->root.num_faces = font_count;
00361 
00362         if ( face_index >= font_count )
00363         {
00364           error = FNT_Err_Invalid_Argument;
00365           goto Exit;
00366         }
00367         else if ( face_index < 0 )
00368           goto Exit;
00369 
00370         if ( FT_NEW( face->font ) )
00371           goto Exit;
00372 
00373         if ( FT_STREAM_SEEK( font_offset + face_index * 12 ) ||
00374              FT_FRAME_ENTER( 12 )                            )
00375           goto Fail;
00376 
00377         face->font->offset   = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
00378         face->font->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
00379 
00380         stream->cursor += 8;
00381 
00382         FT_FRAME_EXIT();
00383 
00384         error = fnt_font_load( face->font, stream );
00385       }
00386       else if ( ne_header.magic == WINFNT_PE_MAGIC )
00387       {
00388         WinPE32_HeaderRec       pe32_header;
00389         WinPE32_SectionRec      pe32_section;
00390         WinPE_RsrcDirRec        root_dir, name_dir, lang_dir;
00391         WinPE_RsrcDirEntryRec   dir_entry1, dir_entry2, dir_entry3;
00392         WinPE_RsrcDataEntryRec  data_entry;
00393 
00394         FT_Long    root_dir_offset, name_dir_offset, lang_dir_offset;
00395         FT_UShort  i, j, k;
00396 
00397 
00398         FT_TRACE2(( "PE signature found\n" ));
00399 
00400         if ( FT_STREAM_SEEK( mz_header.lfanew )                           ||
00401              FT_STREAM_READ_FIELDS( winpe32_header_fields, &pe32_header ) )
00402           goto Exit;
00403 
00404         FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, "
00405                     "size_of_optional_header %02x\n"
00406                     "magic32 %02x, rsrc_virtual_address %04lx, "
00407                     "rsrc_size %04lx\n",
00408                     pe32_header.magic, pe32_header.machine,
00409                     pe32_header.number_of_sections,
00410                     pe32_header.size_of_optional_header,
00411                     pe32_header.magic32, pe32_header.rsrc_virtual_address,
00412                     pe32_header.rsrc_size ));
00413 
00414         if ( pe32_header.magic != WINFNT_PE_MAGIC /* check full signature */ ||
00415              pe32_header.machine != 0x014c /* i386 */                        ||
00416              pe32_header.size_of_optional_header != 0xe0 /* FIXME */         ||
00417              pe32_header.magic32 != 0x10b                                    )
00418         {
00419           FT_TRACE2(( "this file has an invalid PE header\n" ));
00420           error = FNT_Err_Invalid_File_Format;
00421           goto Exit;
00422         }
00423 
00424         face->root.num_faces = 0;
00425 
00426         for ( i = 0; i < pe32_header.number_of_sections; i++ )
00427         {
00428           if ( FT_STREAM_READ_FIELDS( winpe32_section_fields,
00429                                       &pe32_section ) )
00430             goto Exit;
00431 
00432           FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n",
00433                       pe32_section.name, pe32_section.virtual_address,
00434                       pe32_section.size_of_raw_data,
00435                       pe32_section.pointer_to_raw_data ));
00436 
00437           if ( pe32_header.rsrc_virtual_address ==
00438                  pe32_section.virtual_address )
00439             goto Found_rsrc_section;
00440         }
00441 
00442         FT_TRACE2(( "this file doesn't contain any resources\n" ));
00443         error = FNT_Err_Invalid_File_Format;
00444         goto Exit;
00445 
00446       Found_rsrc_section:
00447         FT_TRACE2(( "found resources section %.8s\n", pe32_section.name ));
00448 
00449         if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data )        ||
00450              FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &root_dir ) )
00451           goto Exit;
00452 
00453         root_dir_offset = pe32_section.pointer_to_raw_data;
00454 
00455         for ( i = 0; i < root_dir.number_of_named_entries +
00456                            root_dir.number_of_id_entries; i++ )
00457         {
00458           if ( FT_STREAM_SEEK( root_dir_offset + 16 + i * 8 )      ||
00459                FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
00460                                       &dir_entry1 )                )
00461             goto Exit;
00462 
00463           if ( !(dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ )
00464           {
00465             error = FNT_Err_Invalid_File_Format;
00466             goto Exit;
00467           }
00468 
00469           dir_entry1.offset &= ~0x80000000UL;
00470 
00471           name_dir_offset = pe32_section.pointer_to_raw_data +
00472                             dir_entry1.offset;
00473 
00474           if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data +
00475                                dir_entry1.offset )                       ||
00476                FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &name_dir ) )
00477             goto Exit;
00478 
00479           for ( j = 0; j < name_dir.number_of_named_entries +
00480                              name_dir.number_of_id_entries; j++ )
00481           {
00482             if ( FT_STREAM_SEEK( name_dir_offset + 16 + j * 8 )      ||
00483                  FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
00484                                         &dir_entry2 )                )
00485               goto Exit;
00486 
00487             if ( !(dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ )
00488             {
00489               error = FNT_Err_Invalid_File_Format;
00490               goto Exit;
00491             }
00492 
00493             dir_entry2.offset &= ~0x80000000UL;
00494 
00495             lang_dir_offset = pe32_section.pointer_to_raw_data +
00496                                 dir_entry2.offset;
00497 
00498             if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data +
00499                                    dir_entry2.offset )                     ||
00500                  FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &lang_dir ) )
00501               goto Exit;
00502 
00503             for ( k = 0; k < lang_dir.number_of_named_entries +
00504                                lang_dir.number_of_id_entries; k++ )
00505             {
00506               if ( FT_STREAM_SEEK( lang_dir_offset + 16 + k * 8 )      ||
00507                    FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
00508                                           &dir_entry3 )                )
00509                 goto Exit;
00510 
00511               if ( dir_entry2.offset & 0x80000000UL /* DataIsDirectory */ )
00512               {
00513                 error = FNT_Err_Invalid_File_Format;
00514                 goto Exit;
00515               }
00516 
00517               if ( dir_entry1.name == 8 /* RT_FONT */ )
00518               {
00519                 if ( FT_STREAM_SEEK( root_dir_offset + dir_entry3.offset ) ||
00520                      FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields,
00521                                             &data_entry )                  )
00522                   goto Exit;
00523 
00524                 FT_TRACE2(( "found font #%lu, offset %04lx, "
00525                             "size %04lx, cp %lu\n",
00526                             dir_entry2.name,
00527                             pe32_section.pointer_to_raw_data +
00528                               data_entry.offset_to_data -
00529                               pe32_section.virtual_address,
00530                             data_entry.size, data_entry.code_page ));
00531 
00532                 if ( face_index == face->root.num_faces )
00533                 {
00534                   if ( FT_NEW( face->font ) )
00535                     goto Exit;
00536 
00537                   face->font->offset   = pe32_section.pointer_to_raw_data +
00538                                            data_entry.offset_to_data -
00539                                            pe32_section.virtual_address;
00540                   face->font->fnt_size = data_entry.size;
00541 
00542                   error = fnt_font_load( face->font, stream );
00543                   if ( error )
00544                   {
00545                     FT_TRACE2(( "font #%lu load error %d\n",
00546                                 dir_entry2.name, error ));
00547                     goto Fail;
00548                   }
00549                   else
00550                     FT_TRACE2(( "font #%lu successfully loaded\n",
00551                                 dir_entry2.name ));
00552                 }
00553 
00554                 face->root.num_faces++;
00555               }
00556             }
00557           }
00558         }
00559       }
00560 
00561       if ( !face->root.num_faces )
00562       {
00563         FT_TRACE2(( "this file doesn't contain any RT_FONT resources\n" ));
00564         error = FNT_Err_Invalid_File_Format;
00565         goto Exit;
00566       }
00567 
00568       if ( face_index >= face->root.num_faces )
00569       {
00570         error = FNT_Err_Invalid_Argument;
00571         goto Exit;
00572       }
00573     }
00574 
00575   Fail:
00576     if ( error )
00577       fnt_font_done( face );
00578 
00579   Exit:
00580     return error;
00581   }
00582 
00583 
00584   typedef struct  FNT_CMapRec_
00585   {
00586     FT_CMapRec  cmap;
00587     FT_UInt32   first;
00588     FT_UInt32   count;
00589 
00590   } FNT_CMapRec, *FNT_CMap;
00591 
00592 
00593   static FT_Error
00594   fnt_cmap_init( FNT_CMap  cmap )
00595   {
00596     FNT_Face  face = (FNT_Face)FT_CMAP_FACE( cmap );
00597     FNT_Font  font = face->font;
00598 
00599 
00600     cmap->first = (FT_UInt32)  font->header.first_char;
00601     cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 );
00602 
00603     return 0;
00604   }
00605 
00606 
00607   static FT_UInt
00608   fnt_cmap_char_index( FNT_CMap   cmap,
00609                        FT_UInt32  char_code )
00610   {
00611     FT_UInt  gindex = 0;
00612 
00613 
00614     char_code -= cmap->first;
00615     if ( char_code < cmap->count )
00616       /* we artificially increase the glyph index; */
00617       /* FNT_Load_Glyph reverts to the right one   */
00618       gindex = (FT_UInt)( char_code + 1 );
00619     return gindex;
00620   }
00621 
00622 
00623   static FT_UInt32
00624   fnt_cmap_char_next( FNT_CMap    cmap,
00625                       FT_UInt32  *pchar_code )
00626   {
00627     FT_UInt    gindex = 0;
00628     FT_UInt32  result = 0;
00629     FT_UInt32  char_code = *pchar_code + 1;
00630 
00631 
00632     if ( char_code <= cmap->first )
00633     {
00634       result = cmap->first;
00635       gindex = 1;
00636     }
00637     else
00638     {
00639       char_code -= cmap->first;
00640       if ( char_code < cmap->count )
00641       {
00642         result = cmap->first + char_code;
00643         gindex = (FT_UInt)( char_code + 1 );
00644       }
00645     }
00646 
00647     *pchar_code = result;
00648     return gindex;
00649   }
00650 
00651 
00652   static const FT_CMap_ClassRec  fnt_cmap_class_rec =
00653   {
00654     sizeof ( FNT_CMapRec ),
00655 
00656     (FT_CMap_InitFunc)     fnt_cmap_init,
00657     (FT_CMap_DoneFunc)     NULL,
00658     (FT_CMap_CharIndexFunc)fnt_cmap_char_index,
00659     (FT_CMap_CharNextFunc) fnt_cmap_char_next,
00660 
00661     NULL, NULL, NULL, NULL, NULL
00662   };
00663 
00664   static FT_CMap_Class const  fnt_cmap_class = &fnt_cmap_class_rec;
00665 
00666 
00667   static void
00668   FNT_Face_Done( FNT_Face  face )
00669   {
00670     FT_Memory  memory;
00671 
00672 
00673     if ( !face )
00674       return;
00675 
00676     memory = FT_FACE_MEMORY( face );
00677 
00678     fnt_font_done( face );
00679 
00680     FT_FREE( face->root.available_sizes );
00681     face->root.num_fixed_sizes = 0;
00682   }
00683 
00684 
00685   static FT_Error
00686   FNT_Face_Init( FT_Stream      stream,
00687                  FNT_Face       face,
00688                  FT_Int         face_index,
00689                  FT_Int         num_params,
00690                  FT_Parameter*  params )
00691   {
00692     FT_Error   error;
00693     FT_Memory  memory = FT_FACE_MEMORY( face );
00694 
00695     FT_UNUSED( num_params );
00696     FT_UNUSED( params );
00697 
00698 
00699     /* try to load font from a DLL */
00700     error = fnt_face_get_dll_font( face, face_index );
00701     if ( !error && face_index < 0 )
00702       goto Exit;
00703 
00704     if ( error == FNT_Err_Unknown_File_Format )
00705     {
00706       /* this didn't work; try to load a single FNT font */
00707       FNT_Font  font;
00708 
00709       if ( FT_NEW( face->font ) )
00710         goto Exit;
00711 
00712       face->root.num_faces = 1;
00713 
00714       font           = face->font;
00715       font->offset   = 0;
00716       font->fnt_size = stream->size;
00717 
00718       error = fnt_font_load( font, stream );
00719 
00720       if ( !error )
00721       {
00722         if ( face_index > 0 )
00723           error = FNT_Err_Invalid_Argument;
00724         else if ( face_index < 0 )
00725           goto Exit;
00726       }
00727     }
00728 
00729     if ( error )
00730       goto Fail;
00731 
00732     /* we now need to fill the root FT_Face fields */
00733     /* with relevant information                   */
00734     {
00735       FT_Face     root = FT_FACE( face );
00736       FNT_Font    font = face->font;
00737       FT_PtrDist  family_size;
00738 
00739 
00740       root->face_index = face_index;
00741 
00742       root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
00743                          FT_FACE_FLAG_HORIZONTAL;
00744 
00745       if ( font->header.avg_width == font->header.max_width )
00746         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
00747 
00748       if ( font->header.italic )
00749         root->style_flags |= FT_STYLE_FLAG_ITALIC;
00750 
00751       if ( font->header.weight >= 800 )
00752         root->style_flags |= FT_STYLE_FLAG_BOLD;
00753 
00754       /* set up the `fixed_sizes' array */
00755       if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
00756         goto Fail;
00757 
00758       root->num_fixed_sizes = 1;
00759 
00760       {
00761         FT_Bitmap_Size*  bsize = root->available_sizes;
00762         FT_UShort        x_res, y_res;
00763 
00764 
00765         bsize->width  = font->header.avg_width;
00766         bsize->height = (FT_Short)(
00767           font->header.pixel_height + font->header.external_leading );
00768         bsize->size   = font->header.nominal_point_size << 6;
00769 
00770         x_res = font->header.horizontal_resolution;
00771         if ( !x_res )
00772           x_res = 72;
00773 
00774         y_res = font->header.vertical_resolution;
00775         if ( !y_res )
00776           y_res = 72;
00777 
00778         bsize->y_ppem = FT_MulDiv( bsize->size, y_res, 72 );
00779         bsize->y_ppem = FT_PIX_ROUND( bsize->y_ppem );
00780 
00781         /*
00782          * this reads:
00783          *
00784          * the nominal height is larger than the bbox's height
00785          *
00786          * => nominal_point_size contains incorrect value;
00787          *    use pixel_height as the nominal height
00788          */
00789         if ( bsize->y_ppem > ( font->header.pixel_height << 6 ) )
00790         {
00791           FT_TRACE2(( "use pixel_height as the nominal height\n" ));
00792 
00793           bsize->y_ppem = font->header.pixel_height << 6;
00794           bsize->size   = FT_MulDiv( bsize->y_ppem, 72, y_res );
00795         }
00796 
00797         bsize->x_ppem = FT_MulDiv( bsize->size, x_res, 72 );
00798         bsize->x_ppem = FT_PIX_ROUND( bsize->x_ppem );
00799       }
00800 
00801       {
00802         FT_CharMapRec  charmap;
00803 
00804 
00805         charmap.encoding    = FT_ENCODING_NONE;
00806         /* initial platform/encoding should indicate unset status? */
00807         charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
00808         charmap.encoding_id = TT_APPLE_ID_DEFAULT;
00809         charmap.face        = root;
00810 
00811         if ( font->header.charset == FT_WinFNT_ID_MAC )
00812         {
00813           charmap.encoding    = FT_ENCODING_APPLE_ROMAN;
00814           charmap.platform_id = TT_PLATFORM_MACINTOSH;
00815 /*        charmap.encoding_id = TT_MAC_ID_ROMAN; */
00816         }
00817 
00818         error = FT_CMap_New( fnt_cmap_class,
00819                              NULL,
00820                              &charmap,
00821                              NULL );
00822         if ( error )
00823           goto Fail;
00824 
00825         /* Select default charmap */
00826         if ( root->num_charmaps )
00827           root->charmap = root->charmaps[0];
00828       }
00829 
00830       /* setup remaining flags */
00831 
00832       /* reserve one slot for the .notdef glyph at index 0 */
00833       root->num_glyphs = font->header.last_char -
00834                          font->header.first_char + 1 + 1;
00835 
00836       if ( font->header.face_name_offset >= font->header.file_size )
00837       {
00838         FT_TRACE2(( "invalid family name offset\n" ));
00839         error = FNT_Err_Invalid_File_Format;
00840         goto Fail;
00841       }
00842       family_size = font->header.file_size - font->header.face_name_offset;
00843       /* Some broken fonts don't delimit the face name with a final */
00844       /* NULL byte -- the frame is erroneously one byte too small.  */
00845       /* We thus allocate one more byte, setting it explicitly to   */
00846       /* zero.                                                      */
00847       if ( FT_ALLOC( font->family_name, family_size + 1 ) )
00848         goto Fail;
00849 
00850       FT_MEM_COPY( font->family_name,
00851                    font->fnt_frame + font->header.face_name_offset,
00852                    family_size );
00853 
00854       font->family_name[family_size] = '\0';
00855 
00856       if ( FT_REALLOC( font->family_name,
00857                        family_size,
00858                        ft_strlen( font->family_name ) + 1 ) )
00859         goto Fail;
00860 
00861       root->family_name = font->family_name;
00862       root->style_name  = (char *)"Regular";
00863 
00864       if ( root->style_flags & FT_STYLE_FLAG_BOLD )
00865       {
00866         if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
00867           root->style_name = (char *)"Bold Italic";
00868         else
00869           root->style_name = (char *)"Bold";
00870       }
00871       else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
00872         root->style_name = (char *)"Italic";
00873     }
00874     goto Exit;
00875 
00876   Fail:
00877     FNT_Face_Done( face );
00878 
00879   Exit:
00880     return error;
00881   }
00882 
00883 
00884   static FT_Error
00885   FNT_Size_Select( FT_Size  size )
00886   {
00887     FNT_Face          face   = (FNT_Face)size->face;
00888     FT_WinFNT_Header  header = &face->font->header;
00889 
00890 
00891     FT_Select_Metrics( size->face, 0 );
00892 
00893     size->metrics.ascender    = header->ascent * 64;
00894     size->metrics.descender   = -( header->pixel_height -
00895                                    header->ascent ) * 64;
00896     size->metrics.max_advance = header->max_width * 64;
00897 
00898     return FNT_Err_Ok;
00899   }
00900 
00901 
00902   static FT_Error
00903   FNT_Size_Request( FT_Size          size,
00904                     FT_Size_Request  req )
00905   {
00906     FNT_Face          face    = (FNT_Face)size->face;
00907     FT_WinFNT_Header  header  = &face->font->header;
00908     FT_Bitmap_Size*   bsize   = size->face->available_sizes;
00909     FT_Error          error   = FNT_Err_Invalid_Pixel_Size;
00910     FT_Long           height;
00911 
00912 
00913     height = FT_REQUEST_HEIGHT( req );
00914     height = ( height + 32 ) >> 6;
00915 
00916     switch ( req->type )
00917     {
00918     case FT_SIZE_REQUEST_TYPE_NOMINAL:
00919       if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
00920         error = FNT_Err_Ok;
00921       break;
00922 
00923     case FT_SIZE_REQUEST_TYPE_REAL_DIM:
00924       if ( height == header->pixel_height )
00925         error = FNT_Err_Ok;
00926       break;
00927 
00928     default:
00929       error = FNT_Err_Unimplemented_Feature;
00930       break;
00931     }
00932 
00933     if ( error )
00934       return error;
00935     else
00936       return FNT_Size_Select( size );
00937   }
00938 
00939 
00940   static FT_Error
00941   FNT_Load_Glyph( FT_GlyphSlot  slot,
00942                   FT_Size       size,
00943                   FT_UInt       glyph_index,
00944                   FT_Int32      load_flags )
00945   {
00946     FNT_Face    face   = (FNT_Face)FT_SIZE_FACE( size );
00947     FNT_Font    font;
00948     FT_Error    error  = FNT_Err_Ok;
00949     FT_Byte*    p;
00950     FT_Int      len;
00951     FT_Bitmap*  bitmap = &slot->bitmap;
00952     FT_ULong    offset;
00953     FT_Bool     new_format;
00954 
00955     FT_UNUSED( load_flags );
00956 
00957 
00958     if ( !face )
00959     {
00960       error = FNT_Err_Invalid_Argument;
00961       goto Exit;
00962     }
00963 
00964     font = face->font;
00965 
00966     if ( !font ||
00967          glyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs ) )
00968     {
00969       error = FNT_Err_Invalid_Argument;
00970       goto Exit;
00971     }
00972 
00973     if ( glyph_index > 0 )
00974       glyph_index--;                           /* revert to real index */
00975     else
00976       glyph_index = font->header.default_char; /* the .notdef glyph */
00977 
00978     new_format = FT_BOOL( font->header.version == 0x300 );
00979     len        = new_format ? 6 : 4;
00980 
00981     /* jump to glyph entry */
00982     p = font->fnt_frame + ( new_format ? 148 : 118 ) + len * glyph_index;
00983 
00984     bitmap->width = FT_NEXT_SHORT_LE( p );
00985 
00986     if ( new_format )
00987       offset = FT_NEXT_ULONG_LE( p );
00988     else
00989       offset = FT_NEXT_USHORT_LE( p );
00990 
00991     if ( offset >= font->header.file_size )
00992     {
00993       FT_TRACE2(( "invalid FNT offset\n" ));
00994       error = FNT_Err_Invalid_File_Format;
00995       goto Exit;
00996     }
00997 
00998     /* jump to glyph data */
00999     p = font->fnt_frame + /* font->header.bits_offset */ + offset;
01000 
01001     /* allocate and build bitmap */
01002     {
01003       FT_Memory  memory = FT_FACE_MEMORY( slot->face );
01004       FT_Int     pitch  = ( bitmap->width + 7 ) >> 3;
01005       FT_Byte*   column;
01006       FT_Byte*   write;
01007 
01008 
01009       bitmap->pitch      = pitch;
01010       bitmap->rows       = font->header.pixel_height;
01011       bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
01012 
01013       if ( offset + pitch * bitmap->rows >= font->header.file_size )
01014       {
01015         FT_TRACE2(( "invalid bitmap width\n" ));
01016         error = FNT_Err_Invalid_File_Format;
01017         goto Exit;
01018       }
01019 
01020       /* note: since glyphs are stored in columns and not in rows we */
01021       /*       can't use ft_glyphslot_set_bitmap                     */
01022       if ( FT_ALLOC_MULT( bitmap->buffer, pitch, bitmap->rows ) )
01023         goto Exit;
01024 
01025       column = (FT_Byte*)bitmap->buffer;
01026 
01027       for ( ; pitch > 0; pitch--, column++ )
01028       {
01029         FT_Byte*  limit = p + bitmap->rows;
01030 
01031 
01032         for ( write = column; p < limit; p++, write += bitmap->pitch )
01033           *write = *p;
01034       }
01035     }
01036 
01037     slot->internal->flags = FT_GLYPH_OWN_BITMAP;
01038     slot->bitmap_left     = 0;
01039     slot->bitmap_top      = font->header.ascent;
01040     slot->format          = FT_GLYPH_FORMAT_BITMAP;
01041 
01042     /* now set up metrics */
01043     slot->metrics.width        = bitmap->width << 6;
01044     slot->metrics.height       = bitmap->rows << 6;
01045     slot->metrics.horiAdvance  = bitmap->width << 6;
01046     slot->metrics.horiBearingX = 0;
01047     slot->metrics.horiBearingY = slot->bitmap_top << 6;
01048 
01049     ft_synthesize_vertical_metrics( &slot->metrics,
01050                                     bitmap->rows << 6 );
01051 
01052   Exit:
01053     return error;
01054   }
01055 
01056 
01057   static FT_Error
01058   winfnt_get_header( FT_Face               face,
01059                      FT_WinFNT_HeaderRec  *aheader )
01060   {
01061     FNT_Font  font = ((FNT_Face)face)->font;
01062 
01063 
01064     *aheader = font->header;
01065 
01066     return 0;
01067   }
01068 
01069 
01070   static const FT_Service_WinFntRec  winfnt_service_rec =
01071   {
01072     winfnt_get_header
01073   };
01074 
01075  /*
01076   *  SERVICE LIST
01077   *
01078   */
01079 
01080   static const FT_ServiceDescRec  winfnt_services[] =
01081   {
01082     { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_WINFNT },
01083     { FT_SERVICE_ID_WINFNT,    &winfnt_service_rec },
01084     { NULL, NULL }
01085   };
01086 
01087 
01088   static FT_Module_Interface
01089   winfnt_get_service( FT_Driver         driver,
01090                       const FT_String*  service_id )
01091   {
01092     FT_UNUSED( driver );
01093 
01094     return ft_service_list_lookup( winfnt_services, service_id );
01095   }
01096 
01097 
01098 
01099 
01100   FT_CALLBACK_TABLE_DEF
01101   const FT_Driver_ClassRec  winfnt_driver_class =
01102   {
01103     {
01104       FT_MODULE_FONT_DRIVER        |
01105       FT_MODULE_DRIVER_NO_OUTLINES,
01106       sizeof ( FT_DriverRec ),
01107 
01108       "winfonts",
01109       0x10000L,
01110       0x20000L,
01111 
01112       0,
01113 
01114       (FT_Module_Constructor)0,
01115       (FT_Module_Destructor) 0,
01116       (FT_Module_Requester)  winfnt_get_service
01117     },
01118 
01119     sizeof( FNT_FaceRec ),
01120     sizeof( FT_SizeRec ),
01121     sizeof( FT_GlyphSlotRec ),
01122 
01123     (FT_Face_InitFunc)        FNT_Face_Init,
01124     (FT_Face_DoneFunc)        FNT_Face_Done,
01125     (FT_Size_InitFunc)        0,
01126     (FT_Size_DoneFunc)        0,
01127     (FT_Slot_InitFunc)        0,
01128     (FT_Slot_DoneFunc)        0,
01129 
01130 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
01131     ft_stub_set_char_sizes,
01132     ft_stub_set_pixel_sizes,
01133 #endif
01134     (FT_Slot_LoadFunc)        FNT_Load_Glyph,
01135 
01136     (FT_Face_GetKerningFunc)  0,
01137     (FT_Face_AttachFunc)      0,
01138     (FT_Face_GetAdvancesFunc) 0,
01139 
01140     (FT_Size_RequestFunc)     FNT_Size_Request,
01141     (FT_Size_SelectFunc)      FNT_Size_Select
01142   };
01143 
01144 
01145 /* END */

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