Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwinfnt.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
1.7.6.1
|