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