1 /***************************************************************************/
5 /* FreeType font driver for Windows FNT/FON files */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010 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
26 #include FT_TRUETYPE_IDS_H
30 #include FT_SERVICE_WINFNT_H
31 #include FT_SERVICE_XFREE86_NAME_H
33 /*************************************************************************/
35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
37 /* messages during execution. */
40 #define FT_COMPONENT trace_winfnt
43 static const FT_Frame_Field winmz_header_fields
[] =
46 #define FT_STRUCTURE WinMZ_HeaderRec
49 FT_FRAME_USHORT_LE ( magic
),
50 FT_FRAME_SKIP_BYTES( 29 * 2 ),
51 FT_FRAME_ULONG_LE ( lfanew
),
55 static const FT_Frame_Field winne_header_fields
[] =
58 #define FT_STRUCTURE WinNE_HeaderRec
61 FT_FRAME_USHORT_LE ( magic
),
62 FT_FRAME_SKIP_BYTES( 34 ),
63 FT_FRAME_USHORT_LE ( resource_tab_offset
),
64 FT_FRAME_USHORT_LE ( rname_tab_offset
),
68 static const FT_Frame_Field winpe32_header_fields
[] =
71 #define FT_STRUCTURE WinPE32_HeaderRec
73 FT_FRAME_START( 248 ),
74 FT_FRAME_ULONG_LE ( magic
), /* PE00 */
75 FT_FRAME_USHORT_LE ( machine
), /* 0x014c - i386 */
76 FT_FRAME_USHORT_LE ( number_of_sections
),
77 FT_FRAME_SKIP_BYTES( 12 ),
78 FT_FRAME_USHORT_LE ( size_of_optional_header
),
79 FT_FRAME_SKIP_BYTES( 2 ),
80 FT_FRAME_USHORT_LE ( magic32
), /* 0x10b */
81 FT_FRAME_SKIP_BYTES( 110 ),
82 FT_FRAME_ULONG_LE ( rsrc_virtual_address
),
83 FT_FRAME_ULONG_LE ( rsrc_size
),
84 FT_FRAME_SKIP_BYTES( 104 ),
88 static const FT_Frame_Field winpe32_section_fields
[] =
91 #define FT_STRUCTURE WinPE32_SectionRec
94 FT_FRAME_BYTES ( name
, 8 ),
95 FT_FRAME_SKIP_BYTES( 4 ),
96 FT_FRAME_ULONG_LE ( virtual_address
),
97 FT_FRAME_ULONG_LE ( size_of_raw_data
),
98 FT_FRAME_ULONG_LE ( pointer_to_raw_data
),
99 FT_FRAME_SKIP_BYTES( 16 ),
103 static const FT_Frame_Field winpe_rsrc_dir_fields
[] =
106 #define FT_STRUCTURE WinPE_RsrcDirRec
108 FT_FRAME_START( 16 ),
109 FT_FRAME_ULONG_LE ( characteristics
),
110 FT_FRAME_ULONG_LE ( time_date_stamp
),
111 FT_FRAME_USHORT_LE( major_version
),
112 FT_FRAME_USHORT_LE( minor_version
),
113 FT_FRAME_USHORT_LE( number_of_named_entries
),
114 FT_FRAME_USHORT_LE( number_of_id_entries
),
118 static const FT_Frame_Field winpe_rsrc_dir_entry_fields
[] =
121 #define FT_STRUCTURE WinPE_RsrcDirEntryRec
124 FT_FRAME_ULONG_LE( name
),
125 FT_FRAME_ULONG_LE( offset
),
129 static const FT_Frame_Field winpe_rsrc_data_entry_fields
[] =
132 #define FT_STRUCTURE WinPE_RsrcDataEntryRec
134 FT_FRAME_START( 16 ),
135 FT_FRAME_ULONG_LE( offset_to_data
),
136 FT_FRAME_ULONG_LE( size
),
137 FT_FRAME_ULONG_LE( code_page
),
138 FT_FRAME_ULONG_LE( reserved
),
142 static const FT_Frame_Field winfnt_header_fields
[] =
145 #define FT_STRUCTURE FT_WinFNT_HeaderRec
147 FT_FRAME_START( 148 ),
148 FT_FRAME_USHORT_LE( version
),
149 FT_FRAME_ULONG_LE ( file_size
),
150 FT_FRAME_BYTES ( copyright
, 60 ),
151 FT_FRAME_USHORT_LE( file_type
),
152 FT_FRAME_USHORT_LE( nominal_point_size
),
153 FT_FRAME_USHORT_LE( vertical_resolution
),
154 FT_FRAME_USHORT_LE( horizontal_resolution
),
155 FT_FRAME_USHORT_LE( ascent
),
156 FT_FRAME_USHORT_LE( internal_leading
),
157 FT_FRAME_USHORT_LE( external_leading
),
158 FT_FRAME_BYTE ( italic
),
159 FT_FRAME_BYTE ( underline
),
160 FT_FRAME_BYTE ( strike_out
),
161 FT_FRAME_USHORT_LE( weight
),
162 FT_FRAME_BYTE ( charset
),
163 FT_FRAME_USHORT_LE( pixel_width
),
164 FT_FRAME_USHORT_LE( pixel_height
),
165 FT_FRAME_BYTE ( pitch_and_family
),
166 FT_FRAME_USHORT_LE( avg_width
),
167 FT_FRAME_USHORT_LE( max_width
),
168 FT_FRAME_BYTE ( first_char
),
169 FT_FRAME_BYTE ( last_char
),
170 FT_FRAME_BYTE ( default_char
),
171 FT_FRAME_BYTE ( break_char
),
172 FT_FRAME_USHORT_LE( bytes_per_row
),
173 FT_FRAME_ULONG_LE ( device_offset
),
174 FT_FRAME_ULONG_LE ( face_name_offset
),
175 FT_FRAME_ULONG_LE ( bits_pointer
),
176 FT_FRAME_ULONG_LE ( bits_offset
),
177 FT_FRAME_BYTE ( reserved
),
178 FT_FRAME_ULONG_LE ( flags
),
179 FT_FRAME_USHORT_LE( A_space
),
180 FT_FRAME_USHORT_LE( B_space
),
181 FT_FRAME_USHORT_LE( C_space
),
182 FT_FRAME_ULONG_LE ( color_table_offset
),
183 FT_FRAME_BYTES ( reserved1
, 16 ),
189 fnt_font_done( FNT_Face face
)
191 FT_Memory memory
= FT_FACE( face
)->memory
;
192 FT_Stream stream
= FT_FACE( face
)->stream
;
193 FNT_Font font
= face
->font
;
199 if ( font
->fnt_frame
)
200 FT_FRAME_RELEASE( font
->fnt_frame
);
201 FT_FREE( font
->family_name
);
209 fnt_font_load( FNT_Font font
,
213 FT_WinFNT_Header header
= &font
->header
;
218 /* first of all, read the FNT header */
219 if ( FT_STREAM_SEEK( font
->offset
) ||
220 FT_STREAM_READ_FIELDS( winfnt_header_fields
, header
) )
224 if ( header
->version
!= 0x200 &&
225 header
->version
!= 0x300 )
227 FT_TRACE2(( "[not a valid FNT file]\n" ));
228 error
= FNT_Err_Unknown_File_Format
;
232 new_format
= FT_BOOL( font
->header
.version
== 0x300 );
233 size
= new_format
? 148 : 118;
235 if ( header
->file_size
< size
)
237 FT_TRACE2(( "[not a valid FNT file]\n" ));
238 error
= FNT_Err_Unknown_File_Format
;
242 /* Version 2 doesn't have these fields */
243 if ( header
->version
== 0x200 )
250 header
->color_table_offset
= 0;
253 if ( header
->file_type
& 1 )
255 FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));
256 error
= FNT_Err_Unknown_File_Format
;
260 /* this is a FNT file/table; extract its frame */
261 if ( FT_STREAM_SEEK( font
->offset
) ||
262 FT_FRAME_EXTRACT( header
->file_size
, font
->fnt_frame
) )
271 fnt_face_get_dll_font( FNT_Face face
,
275 FT_Stream stream
= FT_FACE( face
)->stream
;
276 FT_Memory memory
= FT_FACE( face
)->memory
;
277 WinMZ_HeaderRec mz_header
;
282 /* does it begin with an MZ header? */
283 if ( FT_STREAM_SEEK( 0 ) ||
284 FT_STREAM_READ_FIELDS( winmz_header_fields
, &mz_header
) )
287 error
= FNT_Err_Unknown_File_Format
;
288 if ( mz_header
.magic
== WINFNT_MZ_MAGIC
)
290 /* yes, now look for an NE header in the file */
291 WinNE_HeaderRec ne_header
;
294 FT_TRACE2(( "MZ signature found\n" ));
296 if ( FT_STREAM_SEEK( mz_header
.lfanew
) ||
297 FT_STREAM_READ_FIELDS( winne_header_fields
, &ne_header
) )
300 error
= FNT_Err_Unknown_File_Format
;
301 if ( ne_header
.magic
== WINFNT_NE_MAGIC
)
303 /* good, now look into the resource table for each FNT resource */
304 FT_ULong res_offset
= mz_header
.lfanew
+
305 ne_header
.resource_tab_offset
;
306 FT_UShort size_shift
;
307 FT_UShort font_count
= 0;
308 FT_ULong font_offset
= 0;
311 FT_TRACE2(( "NE signature found\n" ));
313 if ( FT_STREAM_SEEK( res_offset
) ||
314 FT_FRAME_ENTER( ne_header
.rname_tab_offset
-
315 ne_header
.resource_tab_offset
) )
318 size_shift
= FT_GET_USHORT_LE();
322 FT_UShort type_id
, count
;
325 type_id
= FT_GET_USHORT_LE();
329 count
= FT_GET_USHORT_LE();
331 if ( type_id
== 0x8008U
)
334 font_offset
= (FT_ULong
)( FT_STREAM_POS() + 4 +
335 ( stream
->cursor
- stream
->limit
) );
339 stream
->cursor
+= 4 + count
* 12;
344 if ( !font_count
|| !font_offset
)
346 FT_TRACE2(( "this file doesn't contain any FNT resources\n" ));
347 error
= FNT_Err_Invalid_File_Format
;
351 /* loading `winfnt_header_fields' needs at least 118 bytes; */
352 /* use this as a rough measure to check the expected font size */
353 if ( font_count
* 118UL > stream
->size
)
355 FT_TRACE2(( "invalid number of faces\n" ));
356 error
= FNT_Err_Invalid_File_Format
;
360 face
->root
.num_faces
= font_count
;
362 if ( face_index
>= font_count
)
364 error
= FNT_Err_Invalid_Argument
;
367 else if ( face_index
< 0 )
370 if ( FT_NEW( face
->font
) )
373 if ( FT_STREAM_SEEK( font_offset
+ face_index
* 12 ) ||
374 FT_FRAME_ENTER( 12 ) )
377 face
->font
->offset
= (FT_ULong
)FT_GET_USHORT_LE() << size_shift
;
378 face
->font
->fnt_size
= (FT_ULong
)FT_GET_USHORT_LE() << size_shift
;
384 error
= fnt_font_load( face
->font
, stream
);
386 else if ( ne_header
.magic
== WINFNT_PE_MAGIC
)
388 WinPE32_HeaderRec pe32_header
;
389 WinPE32_SectionRec pe32_section
;
390 WinPE_RsrcDirRec root_dir
, name_dir
, lang_dir
;
391 WinPE_RsrcDirEntryRec dir_entry1
, dir_entry2
, dir_entry3
;
392 WinPE_RsrcDataEntryRec data_entry
;
394 FT_Long root_dir_offset
, name_dir_offset
, lang_dir_offset
;
398 FT_TRACE2(( "PE signature found\n" ));
400 if ( FT_STREAM_SEEK( mz_header
.lfanew
) ||
401 FT_STREAM_READ_FIELDS( winpe32_header_fields
, &pe32_header
) )
404 FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, "
405 "size_of_optional_header %02x\n"
406 "magic32 %02x, rsrc_virtual_address %04lx, "
408 pe32_header
.magic
, pe32_header
.machine
,
409 pe32_header
.number_of_sections
,
410 pe32_header
.size_of_optional_header
,
411 pe32_header
.magic32
, pe32_header
.rsrc_virtual_address
,
412 pe32_header
.rsrc_size
));
414 if ( pe32_header
.magic
!= WINFNT_PE_MAGIC
/* check full signature */ ||
415 pe32_header
.machine
!= 0x014c /* i386 */ ||
416 pe32_header
.size_of_optional_header
!= 0xe0 /* FIXME */ ||
417 pe32_header
.magic32
!= 0x10b )
419 FT_TRACE2(( "this file has an invalid PE header\n" ));
420 error
= FNT_Err_Invalid_File_Format
;
424 face
->root
.num_faces
= 0;
426 for ( i
= 0; i
< pe32_header
.number_of_sections
; i
++ )
428 if ( FT_STREAM_READ_FIELDS( winpe32_section_fields
,
432 FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n",
433 pe32_section
.name
, pe32_section
.virtual_address
,
434 pe32_section
.size_of_raw_data
,
435 pe32_section
.pointer_to_raw_data
));
437 if ( pe32_header
.rsrc_virtual_address
==
438 pe32_section
.virtual_address
)
439 goto Found_rsrc_section
;
442 FT_TRACE2(( "this file doesn't contain any resources\n" ));
443 error
= FNT_Err_Invalid_File_Format
;
447 FT_TRACE2(( "found resources section %.8s\n", pe32_section
.name
));
449 if ( FT_STREAM_SEEK( pe32_section
.pointer_to_raw_data
) ||
450 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields
, &root_dir
) )
453 root_dir_offset
= pe32_section
.pointer_to_raw_data
;
455 for ( i
= 0; i
< root_dir
.number_of_named_entries
+
456 root_dir
.number_of_id_entries
; i
++ )
458 if ( FT_STREAM_SEEK( root_dir_offset
+ 16 + i
* 8 ) ||
459 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields
,
463 if ( !(dir_entry1
.offset
& 0x80000000UL
) /* DataIsDirectory */ )
465 error
= FNT_Err_Invalid_File_Format
;
469 dir_entry1
.offset
&= ~0x80000000UL
;
471 name_dir_offset
= pe32_section
.pointer_to_raw_data
+
474 if ( FT_STREAM_SEEK( pe32_section
.pointer_to_raw_data
+
475 dir_entry1
.offset
) ||
476 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields
, &name_dir
) )
479 for ( j
= 0; j
< name_dir
.number_of_named_entries
+
480 name_dir
.number_of_id_entries
; j
++ )
482 if ( FT_STREAM_SEEK( name_dir_offset
+ 16 + j
* 8 ) ||
483 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields
,
487 if ( !(dir_entry2
.offset
& 0x80000000UL
) /* DataIsDirectory */ )
489 error
= FNT_Err_Invalid_File_Format
;
493 dir_entry2
.offset
&= ~0x80000000UL
;
495 lang_dir_offset
= pe32_section
.pointer_to_raw_data
+
498 if ( FT_STREAM_SEEK( pe32_section
.pointer_to_raw_data
+
499 dir_entry2
.offset
) ||
500 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields
, &lang_dir
) )
503 for ( k
= 0; k
< lang_dir
.number_of_named_entries
+
504 lang_dir
.number_of_id_entries
; k
++ )
506 if ( FT_STREAM_SEEK( lang_dir_offset
+ 16 + k
* 8 ) ||
507 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields
,
511 if ( dir_entry2
.offset
& 0x80000000UL
/* DataIsDirectory */ )
513 error
= FNT_Err_Invalid_File_Format
;
517 if ( dir_entry1
.name
== 8 /* RT_FONT */ )
519 if ( FT_STREAM_SEEK( root_dir_offset
+ dir_entry3
.offset
) ||
520 FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields
,
524 FT_TRACE2(( "found font #%lu, offset %04lx, "
525 "size %04lx, cp %lu\n",
527 pe32_section
.pointer_to_raw_data
+
528 data_entry
.offset_to_data
-
529 pe32_section
.virtual_address
,
530 data_entry
.size
, data_entry
.code_page
));
532 if ( face_index
== face
->root
.num_faces
)
534 if ( FT_NEW( face
->font
) )
537 face
->font
->offset
= pe32_section
.pointer_to_raw_data
+
538 data_entry
.offset_to_data
-
539 pe32_section
.virtual_address
;
540 face
->font
->fnt_size
= data_entry
.size
;
542 error
= fnt_font_load( face
->font
, stream
);
545 FT_TRACE2(( "font #%lu load error %d\n",
546 dir_entry2
.name
, error
));
550 FT_TRACE2(( "font #%lu successfully loaded\n",
554 face
->root
.num_faces
++;
561 if ( !face
->root
.num_faces
)
563 FT_TRACE2(( "this file doesn't contain any RT_FONT resources\n" ));
564 error
= FNT_Err_Invalid_File_Format
;
568 if ( face_index
>= face
->root
.num_faces
)
570 error
= FNT_Err_Invalid_Argument
;
577 fnt_font_done( face
);
584 typedef struct FNT_CMapRec_
590 } FNT_CMapRec
, *FNT_CMap
;
594 fnt_cmap_init( FNT_CMap cmap
)
596 FNT_Face face
= (FNT_Face
)FT_CMAP_FACE( cmap
);
597 FNT_Font font
= face
->font
;
600 cmap
->first
= (FT_UInt32
) font
->header
.first_char
;
601 cmap
->count
= (FT_UInt32
)( font
->header
.last_char
- cmap
->first
+ 1 );
608 fnt_cmap_char_index( FNT_CMap cmap
,
609 FT_UInt32 char_code
)
614 char_code
-= cmap
->first
;
615 if ( char_code
< cmap
->count
)
616 /* we artificially increase the glyph index; */
617 /* FNT_Load_Glyph reverts to the right one */
618 gindex
= (FT_UInt
)( char_code
+ 1 );
624 fnt_cmap_char_next( FNT_CMap cmap
,
625 FT_UInt32
*pchar_code
)
628 FT_UInt32 result
= 0;
629 FT_UInt32 char_code
= *pchar_code
+ 1;
632 if ( char_code
<= cmap
->first
)
634 result
= cmap
->first
;
639 char_code
-= cmap
->first
;
640 if ( char_code
< cmap
->count
)
642 result
= cmap
->first
+ char_code
;
643 gindex
= (FT_UInt
)( char_code
+ 1 );
647 *pchar_code
= result
;
652 static const FT_CMap_ClassRec fnt_cmap_class_rec
=
654 sizeof ( FNT_CMapRec
),
656 (FT_CMap_InitFunc
) fnt_cmap_init
,
657 (FT_CMap_DoneFunc
) NULL
,
658 (FT_CMap_CharIndexFunc
)fnt_cmap_char_index
,
659 (FT_CMap_CharNextFunc
) fnt_cmap_char_next
,
661 NULL
, NULL
, NULL
, NULL
, NULL
664 static FT_CMap_Class
const fnt_cmap_class
= &fnt_cmap_class_rec
;
668 FNT_Face_Done( FNT_Face face
)
676 memory
= FT_FACE_MEMORY( face
);
678 fnt_font_done( face
);
680 FT_FREE( face
->root
.available_sizes
);
681 face
->root
.num_fixed_sizes
= 0;
686 FNT_Face_Init( FT_Stream stream
,
690 FT_Parameter
* params
)
693 FT_Memory memory
= FT_FACE_MEMORY( face
);
695 FT_UNUSED( num_params
);
699 /* try to load font from a DLL */
700 error
= fnt_face_get_dll_font( face
, face_index
);
701 if ( !error
&& face_index
< 0 )
704 if ( error
== FNT_Err_Unknown_File_Format
)
706 /* this didn't work; try to load a single FNT font */
709 if ( FT_NEW( face
->font
) )
712 face
->root
.num_faces
= 1;
716 font
->fnt_size
= stream
->size
;
718 error
= fnt_font_load( font
, stream
);
722 if ( face_index
> 0 )
723 error
= FNT_Err_Invalid_Argument
;
724 else if ( face_index
< 0 )
732 /* we now need to fill the root FT_Face fields */
733 /* with relevant information */
735 FT_Face root
= FT_FACE( face
);
736 FNT_Font font
= face
->font
;
737 FT_PtrDist family_size
;
740 root
->face_index
= face_index
;
742 root
->face_flags
= FT_FACE_FLAG_FIXED_SIZES
|
743 FT_FACE_FLAG_HORIZONTAL
;
745 if ( font
->header
.avg_width
== font
->header
.max_width
)
746 root
->face_flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
748 if ( font
->header
.italic
)
749 root
->style_flags
|= FT_STYLE_FLAG_ITALIC
;
751 if ( font
->header
.weight
>= 800 )
752 root
->style_flags
|= FT_STYLE_FLAG_BOLD
;
754 /* set up the `fixed_sizes' array */
755 if ( FT_NEW_ARRAY( root
->available_sizes
, 1 ) )
758 root
->num_fixed_sizes
= 1;
761 FT_Bitmap_Size
* bsize
= root
->available_sizes
;
762 FT_UShort x_res
, y_res
;
765 bsize
->width
= font
->header
.avg_width
;
766 bsize
->height
= (FT_Short
)(
767 font
->header
.pixel_height
+ font
->header
.external_leading
);
768 bsize
->size
= font
->header
.nominal_point_size
<< 6;
770 x_res
= font
->header
.horizontal_resolution
;
774 y_res
= font
->header
.vertical_resolution
;
778 bsize
->y_ppem
= FT_MulDiv( bsize
->size
, y_res
, 72 );
779 bsize
->y_ppem
= FT_PIX_ROUND( bsize
->y_ppem
);
784 * the nominal height is larger than the bbox's height
786 * => nominal_point_size contains incorrect value;
787 * use pixel_height as the nominal height
789 if ( bsize
->y_ppem
> ( font
->header
.pixel_height
<< 6 ) )
791 FT_TRACE2(( "use pixel_height as the nominal height\n" ));
793 bsize
->y_ppem
= font
->header
.pixel_height
<< 6;
794 bsize
->size
= FT_MulDiv( bsize
->y_ppem
, 72, y_res
);
797 bsize
->x_ppem
= FT_MulDiv( bsize
->size
, x_res
, 72 );
798 bsize
->x_ppem
= FT_PIX_ROUND( bsize
->x_ppem
);
802 FT_CharMapRec charmap
;
805 charmap
.encoding
= FT_ENCODING_NONE
;
806 /* initial platform/encoding should indicate unset status? */
807 charmap
.platform_id
= TT_PLATFORM_APPLE_UNICODE
;
808 charmap
.encoding_id
= TT_APPLE_ID_DEFAULT
;
811 if ( font
->header
.charset
== FT_WinFNT_ID_MAC
)
813 charmap
.encoding
= FT_ENCODING_APPLE_ROMAN
;
814 charmap
.platform_id
= TT_PLATFORM_MACINTOSH
;
815 /* charmap.encoding_id = TT_MAC_ID_ROMAN; */
818 error
= FT_CMap_New( fnt_cmap_class
,
825 /* Select default charmap */
826 if ( root
->num_charmaps
)
827 root
->charmap
= root
->charmaps
[0];
830 /* setup remaining flags */
832 /* reserve one slot for the .notdef glyph at index 0 */
833 root
->num_glyphs
= font
->header
.last_char
-
834 font
->header
.first_char
+ 1 + 1;
836 if ( font
->header
.face_name_offset
>= font
->header
.file_size
)
838 FT_TRACE2(( "invalid family name offset\n" ));
839 error
= FNT_Err_Invalid_File_Format
;
842 family_size
= font
->header
.file_size
- font
->header
.face_name_offset
;
843 /* Some broken fonts don't delimit the face name with a final */
844 /* NULL byte -- the frame is erroneously one byte too small. */
845 /* We thus allocate one more byte, setting it explicitly to */
847 if ( FT_ALLOC( font
->family_name
, family_size
+ 1 ) )
850 FT_MEM_COPY( font
->family_name
,
851 font
->fnt_frame
+ font
->header
.face_name_offset
,
854 font
->family_name
[family_size
] = '\0';
856 if ( FT_REALLOC( font
->family_name
,
858 ft_strlen( font
->family_name
) + 1 ) )
861 root
->family_name
= font
->family_name
;
862 root
->style_name
= (char *)"Regular";
864 if ( root
->style_flags
& FT_STYLE_FLAG_BOLD
)
866 if ( root
->style_flags
& FT_STYLE_FLAG_ITALIC
)
867 root
->style_name
= (char *)"Bold Italic";
869 root
->style_name
= (char *)"Bold";
871 else if ( root
->style_flags
& FT_STYLE_FLAG_ITALIC
)
872 root
->style_name
= (char *)"Italic";
877 FNT_Face_Done( face
);
885 FNT_Size_Select( FT_Size size
)
887 FNT_Face face
= (FNT_Face
)size
->face
;
888 FT_WinFNT_Header header
= &face
->font
->header
;
891 FT_Select_Metrics( size
->face
, 0 );
893 size
->metrics
.ascender
= header
->ascent
* 64;
894 size
->metrics
.descender
= -( header
->pixel_height
-
895 header
->ascent
) * 64;
896 size
->metrics
.max_advance
= header
->max_width
* 64;
903 FNT_Size_Request( FT_Size size
,
904 FT_Size_Request req
)
906 FNT_Face face
= (FNT_Face
)size
->face
;
907 FT_WinFNT_Header header
= &face
->font
->header
;
908 FT_Bitmap_Size
* bsize
= size
->face
->available_sizes
;
909 FT_Error error
= FNT_Err_Invalid_Pixel_Size
;
913 height
= FT_REQUEST_HEIGHT( req
);
914 height
= ( height
+ 32 ) >> 6;
918 case FT_SIZE_REQUEST_TYPE_NOMINAL
:
919 if ( height
== ( ( bsize
->y_ppem
+ 32 ) >> 6 ) )
923 case FT_SIZE_REQUEST_TYPE_REAL_DIM
:
924 if ( height
== header
->pixel_height
)
929 error
= FNT_Err_Unimplemented_Feature
;
936 return FNT_Size_Select( size
);
941 FNT_Load_Glyph( FT_GlyphSlot slot
,
944 FT_Int32 load_flags
)
946 FNT_Face face
= (FNT_Face
)FT_SIZE_FACE( size
);
948 FT_Error error
= FNT_Err_Ok
;
951 FT_Bitmap
* bitmap
= &slot
->bitmap
;
955 FT_UNUSED( load_flags
);
960 error
= FNT_Err_Invalid_Argument
;
967 glyph_index
>= (FT_UInt
)( FT_FACE( face
)->num_glyphs
) )
969 error
= FNT_Err_Invalid_Argument
;
973 if ( glyph_index
> 0 )
974 glyph_index
--; /* revert to real index */
976 glyph_index
= font
->header
.default_char
; /* the .notdef glyph */
978 new_format
= FT_BOOL( font
->header
.version
== 0x300 );
979 len
= new_format
? 6 : 4;
981 /* jump to glyph entry */
982 p
= font
->fnt_frame
+ ( new_format
? 148 : 118 ) + len
* glyph_index
;
984 bitmap
->width
= FT_NEXT_SHORT_LE( p
);
987 offset
= FT_NEXT_ULONG_LE( p
);
989 offset
= FT_NEXT_USHORT_LE( p
);
991 if ( offset
>= font
->header
.file_size
)
993 FT_TRACE2(( "invalid FNT offset\n" ));
994 error
= FNT_Err_Invalid_File_Format
;
998 /* jump to glyph data */
999 p
= font
->fnt_frame
+ /* font->header.bits_offset */ + offset
;
1001 /* allocate and build bitmap */
1003 FT_Memory memory
= FT_FACE_MEMORY( slot
->face
);
1004 FT_Int pitch
= ( bitmap
->width
+ 7 ) >> 3;
1009 bitmap
->pitch
= pitch
;
1010 bitmap
->rows
= font
->header
.pixel_height
;
1011 bitmap
->pixel_mode
= FT_PIXEL_MODE_MONO
;
1013 if ( offset
+ pitch
* bitmap
->rows
>= font
->header
.file_size
)
1015 FT_TRACE2(( "invalid bitmap width\n" ));
1016 error
= FNT_Err_Invalid_File_Format
;
1020 /* note: since glyphs are stored in columns and not in rows we */
1021 /* can't use ft_glyphslot_set_bitmap */
1022 if ( FT_ALLOC_MULT( bitmap
->buffer
, pitch
, bitmap
->rows
) )
1025 column
= (FT_Byte
*)bitmap
->buffer
;
1027 for ( ; pitch
> 0; pitch
--, column
++ )
1029 FT_Byte
* limit
= p
+ bitmap
->rows
;
1032 for ( write
= column
; p
< limit
; p
++, write
+= bitmap
->pitch
)
1037 slot
->internal
->flags
= FT_GLYPH_OWN_BITMAP
;
1038 slot
->bitmap_left
= 0;
1039 slot
->bitmap_top
= font
->header
.ascent
;
1040 slot
->format
= FT_GLYPH_FORMAT_BITMAP
;
1042 /* now set up metrics */
1043 slot
->metrics
.width
= bitmap
->width
<< 6;
1044 slot
->metrics
.height
= bitmap
->rows
<< 6;
1045 slot
->metrics
.horiAdvance
= bitmap
->width
<< 6;
1046 slot
->metrics
.horiBearingX
= 0;
1047 slot
->metrics
.horiBearingY
= slot
->bitmap_top
<< 6;
1049 ft_synthesize_vertical_metrics( &slot
->metrics
,
1050 bitmap
->rows
<< 6 );
1058 winfnt_get_header( FT_Face face
,
1059 FT_WinFNT_HeaderRec
*aheader
)
1061 FNT_Font font
= ((FNT_Face
)face
)->font
;
1064 *aheader
= font
->header
;
1070 static const FT_Service_WinFntRec winfnt_service_rec
=
1080 static const FT_ServiceDescRec winfnt_services
[] =
1082 { FT_SERVICE_ID_XF86_NAME
, FT_XF86_FORMAT_WINFNT
},
1083 { FT_SERVICE_ID_WINFNT
, &winfnt_service_rec
},
1088 static FT_Module_Interface
1089 winfnt_get_service( FT_Driver driver
,
1090 const FT_String
* service_id
)
1092 FT_UNUSED( driver
);
1094 return ft_service_list_lookup( winfnt_services
, service_id
);
1100 FT_CALLBACK_TABLE_DEF
1101 const FT_Driver_ClassRec winfnt_driver_class
=
1104 FT_MODULE_FONT_DRIVER
|
1105 FT_MODULE_DRIVER_NO_OUTLINES
,
1106 sizeof ( FT_DriverRec
),
1114 (FT_Module_Constructor
)0,
1115 (FT_Module_Destructor
) 0,
1116 (FT_Module_Requester
) winfnt_get_service
1119 sizeof( FNT_FaceRec
),
1120 sizeof( FT_SizeRec
),
1121 sizeof( FT_GlyphSlotRec
),
1123 (FT_Face_InitFunc
) FNT_Face_Init
,
1124 (FT_Face_DoneFunc
) FNT_Face_Done
,
1125 (FT_Size_InitFunc
) 0,
1126 (FT_Size_DoneFunc
) 0,
1127 (FT_Slot_InitFunc
) 0,
1128 (FT_Slot_DoneFunc
) 0,
1130 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
1131 ft_stub_set_char_sizes
,
1132 ft_stub_set_pixel_sizes
,
1134 (FT_Slot_LoadFunc
) FNT_Load_Glyph
,
1136 (FT_Face_GetKerningFunc
) 0,
1137 (FT_Face_AttachFunc
) 0,
1138 (FT_Face_GetAdvancesFunc
) 0,
1140 (FT_Size_RequestFunc
) FNT_Size_Request
,
1141 (FT_Size_SelectFunc
) FNT_Size_Select