1 /***************************************************************************/
5 /* FreeType font driver for Windows FNT/FON files */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* Copyright 2003 Huw D M Davies for Codeweavers */
10 /* Copyright 2007 Dmitry Timoshkov for Codeweavers */
12 /* This file is part of the FreeType project, and may only be used, */
13 /* modified, and distributed under the terms of the FreeType project */
14 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
15 /* this file you indicate that you have read the license and */
16 /* understand and accept it fully. */
18 /***************************************************************************/
22 #include FT_WINFONTS_H
23 #include FT_INTERNAL_DEBUG_H
24 #include FT_INTERNAL_STREAM_H
25 #include FT_INTERNAL_OBJECTS_H
29 #include FT_SERVICE_WINFNT_H
30 #include FT_SERVICE_XFREE86_NAME_H
32 /*************************************************************************/
34 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
35 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
36 /* messages during execution. */
39 #define FT_COMPONENT trace_winfnt
42 static const FT_Frame_Field winmz_header_fields
[] =
45 #define FT_STRUCTURE WinMZ_HeaderRec
48 FT_FRAME_USHORT_LE ( magic
),
49 FT_FRAME_SKIP_BYTES( 29 * 2 ),
50 FT_FRAME_ULONG_LE ( lfanew
),
54 static const FT_Frame_Field winne_header_fields
[] =
57 #define FT_STRUCTURE WinNE_HeaderRec
60 FT_FRAME_USHORT_LE ( magic
),
61 FT_FRAME_SKIP_BYTES( 34 ),
62 FT_FRAME_USHORT_LE ( resource_tab_offset
),
63 FT_FRAME_USHORT_LE ( rname_tab_offset
),
67 static const FT_Frame_Field winpe32_header_fields
[] =
70 #define FT_STRUCTURE WinPE32_HeaderRec
72 FT_FRAME_START( 248 ),
73 FT_FRAME_ULONG_LE ( magic
), /* PE00 */
74 FT_FRAME_USHORT_LE ( machine
), /* 0x014c - i386 */
75 FT_FRAME_USHORT_LE ( number_of_sections
),
76 FT_FRAME_SKIP_BYTES( 12 ),
77 FT_FRAME_USHORT_LE ( size_of_optional_header
),
78 FT_FRAME_SKIP_BYTES( 2 ),
79 FT_FRAME_USHORT_LE ( magic32
), /* 0x10b */
80 FT_FRAME_SKIP_BYTES( 110 ),
81 FT_FRAME_ULONG_LE ( rsrc_virtual_address
),
82 FT_FRAME_ULONG_LE ( rsrc_size
),
83 FT_FRAME_SKIP_BYTES( 104 ),
87 static const FT_Frame_Field winpe32_section_fields
[] =
90 #define FT_STRUCTURE WinPE32_SectionRec
93 FT_FRAME_BYTES ( name
, 8 ),
94 FT_FRAME_SKIP_BYTES( 4 ),
95 FT_FRAME_ULONG_LE ( virtual_address
),
96 FT_FRAME_ULONG_LE ( size_of_raw_data
),
97 FT_FRAME_ULONG_LE ( pointer_to_raw_data
),
98 FT_FRAME_SKIP_BYTES( 16 ),
102 static const FT_Frame_Field winpe_rsrc_dir_fields
[] =
105 #define FT_STRUCTURE WinPE_RsrcDirRec
107 FT_FRAME_START( 16 ),
108 FT_FRAME_ULONG_LE ( characteristics
),
109 FT_FRAME_ULONG_LE ( time_date_stamp
),
110 FT_FRAME_USHORT_LE( major_version
),
111 FT_FRAME_USHORT_LE( minor_version
),
112 FT_FRAME_USHORT_LE( number_of_named_entries
),
113 FT_FRAME_USHORT_LE( number_of_id_entries
),
117 static const FT_Frame_Field winpe_rsrc_dir_entry_fields
[] =
120 #define FT_STRUCTURE WinPE_RsrcDirEntryRec
123 FT_FRAME_ULONG_LE( name
),
124 FT_FRAME_ULONG_LE( offset
),
128 static const FT_Frame_Field winpe_rsrc_data_entry_fields
[] =
131 #define FT_STRUCTURE WinPE_RsrcDataEntryRec
133 FT_FRAME_START( 16 ),
134 FT_FRAME_ULONG_LE( offset_to_data
),
135 FT_FRAME_ULONG_LE( size
),
136 FT_FRAME_ULONG_LE( code_page
),
137 FT_FRAME_ULONG_LE( reserved
),
141 static const FT_Frame_Field winfnt_header_fields
[] =
144 #define FT_STRUCTURE FT_WinFNT_HeaderRec
146 FT_FRAME_START( 148 ),
147 FT_FRAME_USHORT_LE( version
),
148 FT_FRAME_ULONG_LE ( file_size
),
149 FT_FRAME_BYTES ( copyright
, 60 ),
150 FT_FRAME_USHORT_LE( file_type
),
151 FT_FRAME_USHORT_LE( nominal_point_size
),
152 FT_FRAME_USHORT_LE( vertical_resolution
),
153 FT_FRAME_USHORT_LE( horizontal_resolution
),
154 FT_FRAME_USHORT_LE( ascent
),
155 FT_FRAME_USHORT_LE( internal_leading
),
156 FT_FRAME_USHORT_LE( external_leading
),
157 FT_FRAME_BYTE ( italic
),
158 FT_FRAME_BYTE ( underline
),
159 FT_FRAME_BYTE ( strike_out
),
160 FT_FRAME_USHORT_LE( weight
),
161 FT_FRAME_BYTE ( charset
),
162 FT_FRAME_USHORT_LE( pixel_width
),
163 FT_FRAME_USHORT_LE( pixel_height
),
164 FT_FRAME_BYTE ( pitch_and_family
),
165 FT_FRAME_USHORT_LE( avg_width
),
166 FT_FRAME_USHORT_LE( max_width
),
167 FT_FRAME_BYTE ( first_char
),
168 FT_FRAME_BYTE ( last_char
),
169 FT_FRAME_BYTE ( default_char
),
170 FT_FRAME_BYTE ( break_char
),
171 FT_FRAME_USHORT_LE( bytes_per_row
),
172 FT_FRAME_ULONG_LE ( device_offset
),
173 FT_FRAME_ULONG_LE ( face_name_offset
),
174 FT_FRAME_ULONG_LE ( bits_pointer
),
175 FT_FRAME_ULONG_LE ( bits_offset
),
176 FT_FRAME_BYTE ( reserved
),
177 FT_FRAME_ULONG_LE ( flags
),
178 FT_FRAME_USHORT_LE( A_space
),
179 FT_FRAME_USHORT_LE( B_space
),
180 FT_FRAME_USHORT_LE( C_space
),
181 FT_FRAME_ULONG_LE ( color_table_offset
),
182 FT_FRAME_BYTES ( reserved1
, 16 ),
188 fnt_font_done( FNT_Face face
)
190 FT_Memory memory
= FT_FACE( face
)->memory
;
191 FT_Stream stream
= FT_FACE( face
)->stream
;
192 FNT_Font font
= face
->font
;
198 if ( font
->fnt_frame
)
199 FT_FRAME_RELEASE( font
->fnt_frame
);
200 FT_FREE( font
->family_name
);
208 fnt_font_load( FNT_Font font
,
212 FT_WinFNT_Header header
= &font
->header
;
217 /* first of all, read the FNT header */
218 if ( FT_STREAM_SEEK( font
->offset
) ||
219 FT_STREAM_READ_FIELDS( winfnt_header_fields
, header
) )
223 if ( header
->version
!= 0x200 &&
224 header
->version
!= 0x300 )
226 FT_TRACE2(( "[not a valid FNT file]\n" ));
227 error
= FNT_Err_Unknown_File_Format
;
231 new_format
= FT_BOOL( font
->header
.version
== 0x300 );
232 size
= new_format
? 148 : 118;
234 if ( header
->file_size
< size
)
236 FT_TRACE2(( "[not a valid FNT file]\n" ));
237 error
= FNT_Err_Unknown_File_Format
;
241 /* Version 2 doesn't have these fields */
242 if ( header
->version
== 0x200 )
249 header
->color_table_offset
= 0;
252 if ( header
->file_type
& 1 )
254 FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));
255 error
= FNT_Err_Unknown_File_Format
;
259 /* this is a FNT file/table; extract its frame */
260 if ( FT_STREAM_SEEK( font
->offset
) ||
261 FT_FRAME_EXTRACT( header
->file_size
, font
->fnt_frame
) )
270 fnt_face_get_dll_font( FNT_Face face
,
274 FT_Stream stream
= FT_FACE( face
)->stream
;
275 FT_Memory memory
= FT_FACE( face
)->memory
;
276 WinMZ_HeaderRec mz_header
;
281 /* does it begin with an MZ header? */
282 if ( FT_STREAM_SEEK( 0 ) ||
283 FT_STREAM_READ_FIELDS( winmz_header_fields
, &mz_header
) )
286 error
= FNT_Err_Unknown_File_Format
;
287 if ( mz_header
.magic
== WINFNT_MZ_MAGIC
)
289 /* yes, now look for an NE header in the file */
290 WinNE_HeaderRec ne_header
;
293 FT_TRACE2(( "MZ signature found\n" ));
295 if ( FT_STREAM_SEEK( mz_header
.lfanew
) ||
296 FT_STREAM_READ_FIELDS( winne_header_fields
, &ne_header
) )
299 error
= FNT_Err_Unknown_File_Format
;
300 if ( ne_header
.magic
== WINFNT_NE_MAGIC
)
302 /* good, now look into the resource table for each FNT resource */
303 FT_ULong res_offset
= mz_header
.lfanew
+
304 ne_header
.resource_tab_offset
;
305 FT_UShort size_shift
;
306 FT_UShort font_count
= 0;
307 FT_ULong font_offset
= 0;
310 FT_TRACE2(( "NE signature found\n" ));
312 if ( FT_STREAM_SEEK( res_offset
) ||
313 FT_FRAME_ENTER( ne_header
.rname_tab_offset
-
314 ne_header
.resource_tab_offset
) )
317 size_shift
= FT_GET_USHORT_LE();
321 FT_UShort type_id
, count
;
324 type_id
= FT_GET_USHORT_LE();
328 count
= FT_GET_USHORT_LE();
330 if ( type_id
== 0x8008U
)
333 font_offset
= (FT_ULong
)( FT_STREAM_POS() + 4 +
334 ( stream
->cursor
- stream
->limit
) );
338 stream
->cursor
+= 4 + count
* 12;
343 if ( !font_count
|| !font_offset
)
345 FT_TRACE2(( "this file doesn't contain any FNT resources\n" ));
346 error
= FNT_Err_Invalid_File_Format
;
350 /* loading `winfnt_header_fields' needs at least 118 bytes; */
351 /* use this as a rough measure to check the expected font size */
352 if ( font_count
* 118UL > stream
->size
)
354 FT_TRACE2(( "invalid number of faces\n" ));
355 error
= FNT_Err_Invalid_File_Format
;
359 face
->root
.num_faces
= font_count
;
361 if ( face_index
>= font_count
)
363 error
= FNT_Err_Invalid_Argument
;
366 else if ( face_index
< 0 )
369 if ( FT_NEW( face
->font
) )
372 if ( FT_STREAM_SEEK( font_offset
+ face_index
* 12 ) ||
373 FT_FRAME_ENTER( 12 ) )
376 face
->font
->offset
= (FT_ULong
)FT_GET_USHORT_LE() << size_shift
;
377 face
->font
->fnt_size
= (FT_ULong
)FT_GET_USHORT_LE() << size_shift
;
383 error
= fnt_font_load( face
->font
, stream
);
385 else if ( ne_header
.magic
== WINFNT_PE_MAGIC
)
387 WinPE32_HeaderRec pe32_header
;
388 WinPE32_SectionRec pe32_section
;
389 WinPE_RsrcDirRec root_dir
, name_dir
, lang_dir
;
390 WinPE_RsrcDirEntryRec dir_entry1
, dir_entry2
, dir_entry3
;
391 WinPE_RsrcDataEntryRec data_entry
;
393 FT_Long root_dir_offset
, name_dir_offset
, lang_dir_offset
;
397 FT_TRACE2(( "PE signature found\n" ));
399 if ( FT_STREAM_SEEK( mz_header
.lfanew
) ||
400 FT_STREAM_READ_FIELDS( winpe32_header_fields
, &pe32_header
) )
403 FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, "
404 "size_of_optional_header %02x\n"
405 "magic32 %02x, rsrc_virtual_address %04lx, "
407 pe32_header
.magic
, pe32_header
.machine
,
408 pe32_header
.number_of_sections
,
409 pe32_header
.size_of_optional_header
,
410 pe32_header
.magic32
, pe32_header
.rsrc_virtual_address
,
411 pe32_header
.rsrc_size
));
413 if ( pe32_header
.magic
!= WINFNT_PE_MAGIC
/* check full signature */ ||
414 pe32_header
.machine
!= 0x014c /* i386 */ ||
415 pe32_header
.size_of_optional_header
!= 0xe0 /* FIXME */ ||
416 pe32_header
.magic32
!= 0x10b )
418 FT_TRACE2(( "this file has an invalid PE header\n" ));
419 error
= FNT_Err_Invalid_File_Format
;
423 face
->root
.num_faces
= 0;
425 for ( i
= 0; i
< pe32_header
.number_of_sections
; i
++ )
427 if ( FT_STREAM_READ_FIELDS( winpe32_section_fields
,
431 FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n",
432 pe32_section
.name
, pe32_section
.virtual_address
,
433 pe32_section
.size_of_raw_data
,
434 pe32_section
.pointer_to_raw_data
));
436 if ( pe32_header
.rsrc_virtual_address
==
437 pe32_section
.virtual_address
)
438 goto Found_rsrc_section
;
441 FT_TRACE2(( "this file doesn't contain any resources\n" ));
442 error
= FNT_Err_Invalid_File_Format
;
446 FT_TRACE2(( "found resources section %.8s\n", pe32_section
.name
));
448 if ( FT_STREAM_SEEK( pe32_section
.pointer_to_raw_data
) ||
449 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields
, &root_dir
) )
452 root_dir_offset
= pe32_section
.pointer_to_raw_data
;
454 for ( i
= 0; i
< root_dir
.number_of_named_entries
+
455 root_dir
.number_of_id_entries
; i
++ )
457 if ( FT_STREAM_SEEK( root_dir_offset
+ 16 + i
* 8 ) ||
458 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields
,
462 if ( !(dir_entry1
.offset
& 0x80000000UL
) /* DataIsDirectory */ )
464 error
= FNT_Err_Invalid_File_Format
;
468 dir_entry1
.offset
&= ~0x80000000UL
;
470 name_dir_offset
= pe32_section
.pointer_to_raw_data
+
473 if ( FT_STREAM_SEEK( pe32_section
.pointer_to_raw_data
+
474 dir_entry1
.offset
) ||
475 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields
, &name_dir
) )
478 for ( j
= 0; j
< name_dir
.number_of_named_entries
+
479 name_dir
.number_of_id_entries
; j
++ )
481 if ( FT_STREAM_SEEK( name_dir_offset
+ 16 + j
* 8 ) ||
482 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields
,
486 if ( !(dir_entry2
.offset
& 0x80000000UL
) /* DataIsDirectory */ )
488 error
= FNT_Err_Invalid_File_Format
;
492 dir_entry2
.offset
&= ~0x80000000UL
;
494 lang_dir_offset
= pe32_section
.pointer_to_raw_data
+
497 if ( FT_STREAM_SEEK( pe32_section
.pointer_to_raw_data
+
498 dir_entry2
.offset
) ||
499 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields
, &lang_dir
) )
502 for ( k
= 0; k
< lang_dir
.number_of_named_entries
+
503 lang_dir
.number_of_id_entries
; k
++ )
505 if ( FT_STREAM_SEEK( lang_dir_offset
+ 16 + k
* 8 ) ||
506 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields
,
510 if ( dir_entry2
.offset
& 0x80000000UL
/* DataIsDirectory */ )
512 error
= FNT_Err_Invalid_File_Format
;
516 if ( dir_entry1
.name
== 8 /* RT_FONT */ )
518 if ( FT_STREAM_SEEK( root_dir_offset
+ dir_entry3
.offset
) ||
519 FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields
,
523 FT_TRACE2(( "found font #%lu, offset %04lx, "
524 "size %04lx, cp %lu\n",
526 pe32_section
.pointer_to_raw_data
+
527 data_entry
.offset_to_data
-
528 pe32_section
.virtual_address
,
529 data_entry
.size
, data_entry
.code_page
));
531 if ( face_index
== face
->root
.num_faces
)
533 if ( FT_NEW( face
->font
) )
536 face
->font
->offset
= pe32_section
.pointer_to_raw_data
+
537 data_entry
.offset_to_data
-
538 pe32_section
.virtual_address
;
539 face
->font
->fnt_size
= data_entry
.size
;
541 error
= fnt_font_load( face
->font
, stream
);
544 FT_TRACE2(( "font #%lu load error %d\n",
545 dir_entry2
.name
, error
));
549 FT_TRACE2(( "font #%lu successfully loaded\n",
553 face
->root
.num_faces
++;
560 if ( !face
->root
.num_faces
)
562 FT_TRACE2(( "this file doesn't contain any RT_FONT resources\n" ));
563 error
= FNT_Err_Invalid_File_Format
;
567 if ( face_index
>= face
->root
.num_faces
)
569 error
= FNT_Err_Invalid_Argument
;
576 fnt_font_done( face
);
583 typedef struct FNT_CMapRec_
589 } FNT_CMapRec
, *FNT_CMap
;
593 fnt_cmap_init( FNT_CMap cmap
)
595 FNT_Face face
= (FNT_Face
)FT_CMAP_FACE( cmap
);
596 FNT_Font font
= face
->font
;
599 cmap
->first
= (FT_UInt32
) font
->header
.first_char
;
600 cmap
->count
= (FT_UInt32
)( font
->header
.last_char
- cmap
->first
+ 1 );
607 fnt_cmap_char_index( FNT_CMap cmap
,
608 FT_UInt32 char_code
)
613 char_code
-= cmap
->first
;
614 if ( char_code
< cmap
->count
)
615 /* we artificially increase the glyph index; */
616 /* FNT_Load_Glyph reverts to the right one */
617 gindex
= (FT_UInt
)( char_code
+ 1 );
623 fnt_cmap_char_next( FNT_CMap cmap
,
624 FT_UInt32
*pchar_code
)
627 FT_UInt32 result
= 0;
628 FT_UInt32 char_code
= *pchar_code
+ 1;
631 if ( char_code
<= cmap
->first
)
633 result
= cmap
->first
;
638 char_code
-= cmap
->first
;
639 if ( char_code
< cmap
->count
)
641 result
= cmap
->first
+ char_code
;
642 gindex
= (FT_UInt
)( char_code
+ 1 );
646 *pchar_code
= result
;
651 static const FT_CMap_ClassRec fnt_cmap_class_rec
=
653 sizeof ( FNT_CMapRec
),
655 (FT_CMap_InitFunc
) fnt_cmap_init
,
656 (FT_CMap_DoneFunc
) NULL
,
657 (FT_CMap_CharIndexFunc
)fnt_cmap_char_index
,
658 (FT_CMap_CharNextFunc
) fnt_cmap_char_next
,
660 NULL
, NULL
, NULL
, NULL
, NULL
663 static FT_CMap_Class
const fnt_cmap_class
= &fnt_cmap_class_rec
;
667 FNT_Face_Done( FNT_Face face
)
675 memory
= FT_FACE_MEMORY( face
);
677 fnt_font_done( face
);
679 FT_FREE( face
->root
.available_sizes
);
680 face
->root
.num_fixed_sizes
= 0;
685 FNT_Face_Init( FT_Stream stream
,
689 FT_Parameter
* params
)
692 FT_Memory memory
= FT_FACE_MEMORY( face
);
694 FT_UNUSED( num_params
);
698 /* try to load font from a DLL */
699 error
= fnt_face_get_dll_font( face
, face_index
);
700 if ( !error
&& face_index
< 0 )
703 if ( error
== FNT_Err_Unknown_File_Format
)
705 /* this didn't work; try to load a single FNT font */
708 if ( FT_NEW( face
->font
) )
711 face
->root
.num_faces
= 1;
715 font
->fnt_size
= stream
->size
;
717 error
= fnt_font_load( font
, stream
);
721 if ( face_index
> 0 )
722 error
= FNT_Err_Invalid_Argument
;
723 else if ( face_index
< 0 )
731 /* we now need to fill the root FT_Face fields */
732 /* with relevant information */
734 FT_Face root
= FT_FACE( face
);
735 FNT_Font font
= face
->font
;
736 FT_PtrDist family_size
;
739 root
->face_index
= face_index
;
741 root
->face_flags
= FT_FACE_FLAG_FIXED_SIZES
|
742 FT_FACE_FLAG_HORIZONTAL
;
744 if ( font
->header
.avg_width
== font
->header
.max_width
)
745 root
->face_flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
747 if ( font
->header
.italic
)
748 root
->style_flags
|= FT_STYLE_FLAG_ITALIC
;
750 if ( font
->header
.weight
>= 800 )
751 root
->style_flags
|= FT_STYLE_FLAG_BOLD
;
753 /* set up the `fixed_sizes' array */
754 if ( FT_NEW_ARRAY( root
->available_sizes
, 1 ) )
757 root
->num_fixed_sizes
= 1;
760 FT_Bitmap_Size
* bsize
= root
->available_sizes
;
761 FT_UShort x_res
, y_res
;
764 bsize
->width
= font
->header
.avg_width
;
765 bsize
->height
= (FT_Short
)(
766 font
->header
.pixel_height
+ font
->header
.external_leading
);
767 bsize
->size
= font
->header
.nominal_point_size
<< 6;
769 x_res
= font
->header
.horizontal_resolution
;
773 y_res
= font
->header
.vertical_resolution
;
777 bsize
->y_ppem
= FT_MulDiv( bsize
->size
, y_res
, 72 );
778 bsize
->y_ppem
= FT_PIX_ROUND( bsize
->y_ppem
);
783 * the nominal height is larger than the bbox's height
785 * => nominal_point_size contains incorrect value;
786 * use pixel_height as the nominal height
788 if ( bsize
->y_ppem
> ( font
->header
.pixel_height
<< 6 ) )
790 FT_TRACE2(( "use pixel_height as the nominal height\n" ));
792 bsize
->y_ppem
= font
->header
.pixel_height
<< 6;
793 bsize
->size
= FT_MulDiv( bsize
->y_ppem
, 72, y_res
);
796 bsize
->x_ppem
= FT_MulDiv( bsize
->size
, x_res
, 72 );
797 bsize
->x_ppem
= FT_PIX_ROUND( bsize
->x_ppem
);
801 FT_CharMapRec charmap
;
804 charmap
.encoding
= FT_ENCODING_NONE
;
805 charmap
.platform_id
= 0;
806 charmap
.encoding_id
= 0;
809 if ( font
->header
.charset
== FT_WinFNT_ID_MAC
)
811 charmap
.encoding
= FT_ENCODING_APPLE_ROMAN
;
812 charmap
.platform_id
= 1;
813 /* charmap.encoding_id = 0; */
816 error
= FT_CMap_New( fnt_cmap_class
,
823 /* Select default charmap */
824 if ( root
->num_charmaps
)
825 root
->charmap
= root
->charmaps
[0];
828 /* setup remaining flags */
830 /* reserve one slot for the .notdef glyph at index 0 */
831 root
->num_glyphs
= font
->header
.last_char
-
832 font
->header
.first_char
+ 1 + 1;
834 if ( font
->header
.face_name_offset
>= font
->header
.file_size
)
836 FT_TRACE2(( "invalid family name offset\n" ));
837 error
= FNT_Err_Invalid_File_Format
;
840 family_size
= font
->header
.file_size
- font
->header
.face_name_offset
;
841 /* Some broken fonts don't delimit the face name with a final */
842 /* NULL byte -- the frame is erroneously one byte too small. */
843 /* We thus allocate one more byte, setting it explicitly to */
845 if ( FT_ALLOC( font
->family_name
, family_size
+ 1 ) )
848 FT_MEM_COPY( font
->family_name
,
849 font
->fnt_frame
+ font
->header
.face_name_offset
,
852 font
->family_name
[family_size
] = '\0';
854 if ( FT_REALLOC( font
->family_name
,
856 ft_strlen( font
->family_name
) + 1 ) )
859 root
->family_name
= font
->family_name
;
860 root
->style_name
= (char *)"Regular";
862 if ( root
->style_flags
& FT_STYLE_FLAG_BOLD
)
864 if ( root
->style_flags
& FT_STYLE_FLAG_ITALIC
)
865 root
->style_name
= (char *)"Bold Italic";
867 root
->style_name
= (char *)"Bold";
869 else if ( root
->style_flags
& FT_STYLE_FLAG_ITALIC
)
870 root
->style_name
= (char *)"Italic";
875 FNT_Face_Done( face
);
883 FNT_Size_Select( FT_Size size
)
885 FNT_Face face
= (FNT_Face
)size
->face
;
886 FT_WinFNT_Header header
= &face
->font
->header
;
889 FT_Select_Metrics( size
->face
, 0 );
891 size
->metrics
.ascender
= header
->ascent
* 64;
892 size
->metrics
.descender
= -( header
->pixel_height
-
893 header
->ascent
) * 64;
894 size
->metrics
.max_advance
= header
->max_width
* 64;
901 FNT_Size_Request( FT_Size size
,
902 FT_Size_Request req
)
904 FNT_Face face
= (FNT_Face
)size
->face
;
905 FT_WinFNT_Header header
= &face
->font
->header
;
906 FT_Bitmap_Size
* bsize
= size
->face
->available_sizes
;
907 FT_Error error
= FNT_Err_Invalid_Pixel_Size
;
911 height
= FT_REQUEST_HEIGHT( req
);
912 height
= ( height
+ 32 ) >> 6;
916 case FT_SIZE_REQUEST_TYPE_NOMINAL
:
917 if ( height
== ( ( bsize
->y_ppem
+ 32 ) >> 6 ) )
921 case FT_SIZE_REQUEST_TYPE_REAL_DIM
:
922 if ( height
== header
->pixel_height
)
927 error
= FNT_Err_Unimplemented_Feature
;
934 return FNT_Size_Select( size
);
939 FNT_Load_Glyph( FT_GlyphSlot slot
,
942 FT_Int32 load_flags
)
944 FNT_Face face
= (FNT_Face
)FT_SIZE_FACE( size
);
945 FNT_Font font
= face
->font
;
946 FT_Error error
= FNT_Err_Ok
;
949 FT_Bitmap
* bitmap
= &slot
->bitmap
;
953 FT_UNUSED( load_flags
);
956 if ( !face
|| !font
||
957 glyph_index
>= (FT_UInt
)( FT_FACE( face
)->num_glyphs
) )
959 error
= FNT_Err_Invalid_Argument
;
963 if ( glyph_index
> 0 )
964 glyph_index
--; /* revert to real index */
966 glyph_index
= font
->header
.default_char
; /* the .notdef glyph */
968 new_format
= FT_BOOL( font
->header
.version
== 0x300 );
969 len
= new_format
? 6 : 4;
971 /* jump to glyph entry */
972 p
= font
->fnt_frame
+ ( new_format
? 148 : 118 ) + len
* glyph_index
;
974 bitmap
->width
= FT_NEXT_SHORT_LE( p
);
977 offset
= FT_NEXT_ULONG_LE( p
);
979 offset
= FT_NEXT_USHORT_LE( p
);
981 if ( offset
>= font
->header
.file_size
)
983 FT_TRACE2(( "invalid FNT offset\n" ));
984 error
= FNT_Err_Invalid_File_Format
;
988 /* jump to glyph data */
989 p
= font
->fnt_frame
+ /* font->header.bits_offset */ + offset
;
991 /* allocate and build bitmap */
993 FT_Memory memory
= FT_FACE_MEMORY( slot
->face
);
994 FT_Int pitch
= ( bitmap
->width
+ 7 ) >> 3;
999 bitmap
->pitch
= pitch
;
1000 bitmap
->rows
= font
->header
.pixel_height
;
1001 bitmap
->pixel_mode
= FT_PIXEL_MODE_MONO
;
1003 if ( offset
+ pitch
* bitmap
->rows
>= font
->header
.file_size
)
1005 FT_TRACE2(( "invalid bitmap width\n" ));
1006 error
= FNT_Err_Invalid_File_Format
;
1010 /* note: since glyphs are stored in columns and not in rows we */
1011 /* can't use ft_glyphslot_set_bitmap */
1012 if ( FT_ALLOC_MULT( bitmap
->buffer
, pitch
, bitmap
->rows
) )
1015 column
= (FT_Byte
*)bitmap
->buffer
;
1017 for ( ; pitch
> 0; pitch
--, column
++ )
1019 FT_Byte
* limit
= p
+ bitmap
->rows
;
1022 for ( write
= column
; p
< limit
; p
++, write
+= bitmap
->pitch
)
1027 slot
->internal
->flags
= FT_GLYPH_OWN_BITMAP
;
1028 slot
->bitmap_left
= 0;
1029 slot
->bitmap_top
= font
->header
.ascent
;
1030 slot
->format
= FT_GLYPH_FORMAT_BITMAP
;
1032 /* now set up metrics */
1033 slot
->metrics
.width
= bitmap
->width
<< 6;
1034 slot
->metrics
.height
= bitmap
->rows
<< 6;
1035 slot
->metrics
.horiAdvance
= bitmap
->width
<< 6;
1036 slot
->metrics
.horiBearingX
= 0;
1037 slot
->metrics
.horiBearingY
= slot
->bitmap_top
<< 6;
1039 ft_synthesize_vertical_metrics( &slot
->metrics
,
1040 bitmap
->rows
<< 6 );
1048 winfnt_get_header( FT_Face face
,
1049 FT_WinFNT_HeaderRec
*aheader
)
1051 FNT_Font font
= ((FNT_Face
)face
)->font
;
1054 *aheader
= font
->header
;
1060 static const FT_Service_WinFntRec winfnt_service_rec
=
1070 static const FT_ServiceDescRec winfnt_services
[] =
1072 { FT_SERVICE_ID_XF86_NAME
, FT_XF86_FORMAT_WINFNT
},
1073 { FT_SERVICE_ID_WINFNT
, &winfnt_service_rec
},
1078 static FT_Module_Interface
1079 winfnt_get_service( FT_Driver driver
,
1080 const FT_String
* service_id
)
1082 FT_UNUSED( driver
);
1084 return ft_service_list_lookup( winfnt_services
, service_id
);
1090 FT_CALLBACK_TABLE_DEF
1091 const FT_Driver_ClassRec winfnt_driver_class
=
1094 FT_MODULE_FONT_DRIVER
|
1095 FT_MODULE_DRIVER_NO_OUTLINES
,
1096 sizeof ( FT_DriverRec
),
1104 (FT_Module_Constructor
)0,
1105 (FT_Module_Destructor
) 0,
1106 (FT_Module_Requester
) winfnt_get_service
1109 sizeof( FNT_FaceRec
),
1110 sizeof( FT_SizeRec
),
1111 sizeof( FT_GlyphSlotRec
),
1113 (FT_Face_InitFunc
) FNT_Face_Init
,
1114 (FT_Face_DoneFunc
) FNT_Face_Done
,
1115 (FT_Size_InitFunc
) 0,
1116 (FT_Size_DoneFunc
) 0,
1117 (FT_Slot_InitFunc
) 0,
1118 (FT_Slot_DoneFunc
) 0,
1120 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
1121 ft_stub_set_char_sizes
,
1122 ft_stub_set_pixel_sizes
,
1124 (FT_Slot_LoadFunc
) FNT_Load_Glyph
,
1126 (FT_Face_GetKerningFunc
) 0,
1127 (FT_Face_AttachFunc
) 0,
1128 (FT_Face_GetAdvancesFunc
) 0,
1130 (FT_Size_RequestFunc
) FNT_Size_Request
,
1131 (FT_Size_SelectFunc
) FNT_Size_Select