1 /***************************************************************************/
5 /* FreeType font driver for Windows FNT/FON files */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 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_Bad_Argument
;
367 if ( FT_NEW( face
->font
) )
370 if ( FT_STREAM_SEEK( font_offset
+ face_index
* 12 ) ||
371 FT_FRAME_ENTER( 12 ) )
374 face
->font
->offset
= (FT_ULong
)FT_GET_USHORT_LE() << size_shift
;
375 face
->font
->fnt_size
= (FT_ULong
)FT_GET_USHORT_LE() << size_shift
;
381 error
= fnt_font_load( face
->font
, stream
);
383 else if ( ne_header
.magic
== WINFNT_PE_MAGIC
)
385 WinPE32_HeaderRec pe32_header
;
386 WinPE32_SectionRec pe32_section
;
387 WinPE_RsrcDirRec root_dir
, name_dir
, lang_dir
;
388 WinPE_RsrcDirEntryRec dir_entry1
, dir_entry2
, dir_entry3
;
389 WinPE_RsrcDataEntryRec data_entry
;
391 FT_Long root_dir_offset
, name_dir_offset
, lang_dir_offset
;
395 FT_TRACE2(( "PE signature found\n" ));
397 if ( FT_STREAM_SEEK( mz_header
.lfanew
) ||
398 FT_STREAM_READ_FIELDS( winpe32_header_fields
, &pe32_header
) )
401 FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, "
402 "size_of_optional_header %02x\n"
403 "magic32 %02x, rsrc_virtual_address %04lx, "
405 pe32_header
.magic
, pe32_header
.machine
,
406 pe32_header
.number_of_sections
,
407 pe32_header
.size_of_optional_header
,
408 pe32_header
.magic32
, pe32_header
.rsrc_virtual_address
,
409 pe32_header
.rsrc_size
));
411 if ( pe32_header
.magic
!= WINFNT_PE_MAGIC
/* check full signature */ ||
412 pe32_header
.machine
!= 0x014c /* i386 */ ||
413 pe32_header
.size_of_optional_header
!= 0xe0 /* FIXME */ ||
414 pe32_header
.magic32
!= 0x10b )
416 FT_TRACE2(( "this file has an invalid PE header\n" ));
417 error
= FNT_Err_Invalid_File_Format
;
421 face
->root
.num_faces
= 0;
423 for ( i
= 0; i
< pe32_header
.number_of_sections
; i
++ )
425 if ( FT_STREAM_READ_FIELDS( winpe32_section_fields
,
429 FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n",
430 pe32_section
.name
, pe32_section
.virtual_address
,
431 pe32_section
.size_of_raw_data
,
432 pe32_section
.pointer_to_raw_data
));
434 if ( pe32_header
.rsrc_virtual_address
==
435 pe32_section
.virtual_address
)
436 goto Found_rsrc_section
;
439 FT_TRACE2(( "this file doesn't contain any resources\n" ));
440 error
= FNT_Err_Invalid_File_Format
;
444 FT_TRACE2(( "found resources section %.8s\n", pe32_section
.name
));
446 if ( FT_STREAM_SEEK( pe32_section
.pointer_to_raw_data
) ||
447 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields
, &root_dir
) )
450 root_dir_offset
= pe32_section
.pointer_to_raw_data
;
452 for ( i
= 0; i
< root_dir
.number_of_named_entries
+
453 root_dir
.number_of_id_entries
; i
++ )
455 if ( FT_STREAM_SEEK( root_dir_offset
+ 16 + i
* 8 ) ||
456 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields
,
460 if ( !(dir_entry1
.offset
& 0x80000000UL
) /* DataIsDirectory */ )
462 error
= FNT_Err_Invalid_File_Format
;
466 dir_entry1
.offset
&= ~0x80000000UL
;
468 name_dir_offset
= pe32_section
.pointer_to_raw_data
+
471 if ( FT_STREAM_SEEK( pe32_section
.pointer_to_raw_data
+
472 dir_entry1
.offset
) ||
473 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields
, &name_dir
) )
476 for ( j
= 0; j
< name_dir
.number_of_named_entries
+
477 name_dir
.number_of_id_entries
; j
++ )
479 if ( FT_STREAM_SEEK( name_dir_offset
+ 16 + j
* 8 ) ||
480 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields
,
484 if ( !(dir_entry2
.offset
& 0x80000000UL
) /* DataIsDirectory */ )
486 error
= FNT_Err_Invalid_File_Format
;
490 dir_entry2
.offset
&= ~0x80000000UL
;
492 lang_dir_offset
= pe32_section
.pointer_to_raw_data
+
495 if ( FT_STREAM_SEEK( pe32_section
.pointer_to_raw_data
+
496 dir_entry2
.offset
) ||
497 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields
, &lang_dir
) )
500 for ( k
= 0; k
< lang_dir
.number_of_named_entries
+
501 lang_dir
.number_of_id_entries
; k
++ )
503 if ( FT_STREAM_SEEK( lang_dir_offset
+ 16 + k
* 8 ) ||
504 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields
,
508 if ( dir_entry2
.offset
& 0x80000000UL
/* DataIsDirectory */ )
510 error
= FNT_Err_Invalid_File_Format
;
514 if ( dir_entry1
.name
== 8 /* RT_FONT */ )
516 if ( FT_STREAM_SEEK( root_dir_offset
+ dir_entry3
.offset
) ||
517 FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields
,
521 FT_TRACE2(( "found font #%lu, offset %04lx, "
522 "size %04lx, cp %lu\n",
524 pe32_section
.pointer_to_raw_data
+
525 data_entry
.offset_to_data
-
526 pe32_section
.virtual_address
,
527 data_entry
.size
, data_entry
.code_page
));
529 if ( face_index
== face
->root
.num_faces
)
531 if ( FT_NEW( face
->font
) )
534 face
->font
->offset
= pe32_section
.pointer_to_raw_data
+
535 data_entry
.offset_to_data
-
536 pe32_section
.virtual_address
;
537 face
->font
->fnt_size
= data_entry
.size
;
539 error
= fnt_font_load( face
->font
, stream
);
542 FT_TRACE2(( "font #%lu load error %d\n",
543 dir_entry2
.name
, error
));
547 FT_TRACE2(( "font #%lu successfully loaded\n",
551 face
->root
.num_faces
++;
558 if ( !face
->root
.num_faces
)
560 FT_TRACE2(( "this file doesn't contain any RT_FONT resources\n" ));
561 error
= FNT_Err_Invalid_File_Format
;
565 if ( face_index
>= face
->root
.num_faces
)
567 error
= FNT_Err_Bad_Argument
;
574 fnt_font_done( face
);
581 typedef struct FNT_CMapRec_
587 } FNT_CMapRec
, *FNT_CMap
;
591 fnt_cmap_init( FNT_CMap cmap
)
593 FNT_Face face
= (FNT_Face
)FT_CMAP_FACE( cmap
);
594 FNT_Font font
= face
->font
;
597 cmap
->first
= (FT_UInt32
) font
->header
.first_char
;
598 cmap
->count
= (FT_UInt32
)( font
->header
.last_char
- cmap
->first
+ 1 );
605 fnt_cmap_char_index( FNT_CMap cmap
,
606 FT_UInt32 char_code
)
611 char_code
-= cmap
->first
;
612 if ( char_code
< cmap
->count
)
613 gindex
= char_code
+ 1; /* we artificially increase the glyph index; */
614 /* FNT_Load_Glyph reverts to the right one */
620 fnt_cmap_char_next( FNT_CMap cmap
,
621 FT_UInt32
*pchar_code
)
624 FT_UInt32 result
= 0;
625 FT_UInt32 char_code
= *pchar_code
+ 1;
628 if ( char_code
<= cmap
->first
)
630 result
= cmap
->first
;
635 char_code
-= cmap
->first
;
636 if ( char_code
< cmap
->count
)
638 result
= cmap
->first
+ char_code
;
639 gindex
= char_code
+ 1;
643 *pchar_code
= result
;
648 static const FT_CMap_ClassRec fnt_cmap_class_rec
=
650 sizeof ( FNT_CMapRec
),
652 (FT_CMap_InitFunc
) fnt_cmap_init
,
653 (FT_CMap_DoneFunc
) NULL
,
654 (FT_CMap_CharIndexFunc
)fnt_cmap_char_index
,
655 (FT_CMap_CharNextFunc
) fnt_cmap_char_next
658 static FT_CMap_Class
const fnt_cmap_class
= &fnt_cmap_class_rec
;
662 FNT_Face_Done( FNT_Face face
)
666 FT_Memory memory
= FT_FACE_MEMORY( face
);
669 fnt_font_done( face
);
671 FT_FREE( face
->root
.available_sizes
);
672 face
->root
.num_fixed_sizes
= 0;
678 FNT_Face_Init( FT_Stream stream
,
682 FT_Parameter
* params
)
685 FT_Memory memory
= FT_FACE_MEMORY( face
);
687 FT_UNUSED( num_params
);
691 /* try to load font from a DLL */
692 error
= fnt_face_get_dll_font( face
, face_index
);
693 if ( error
== FNT_Err_Unknown_File_Format
)
695 /* this didn't work; try to load a single FNT font */
699 if ( face_index
> 0 )
701 error
= FNT_Err_Bad_Argument
;
705 if ( FT_NEW( face
->font
) )
708 face
->root
.num_faces
= 1;
712 font
->fnt_size
= stream
->size
;
714 error
= fnt_font_load( font
, stream
);
720 /* we now need to fill the root FT_Face fields */
721 /* with relevant information */
723 FT_Face root
= FT_FACE( face
);
724 FNT_Font font
= face
->font
;
725 FT_PtrDist family_size
;
728 root
->face_flags
= FT_FACE_FLAG_FIXED_SIZES
|
729 FT_FACE_FLAG_HORIZONTAL
;
731 if ( font
->header
.avg_width
== font
->header
.max_width
)
732 root
->face_flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
734 if ( font
->header
.italic
)
735 root
->style_flags
|= FT_STYLE_FLAG_ITALIC
;
737 if ( font
->header
.weight
>= 800 )
738 root
->style_flags
|= FT_STYLE_FLAG_BOLD
;
740 /* set up the `fixed_sizes' array */
741 if ( FT_NEW_ARRAY( root
->available_sizes
, 1 ) )
744 root
->num_fixed_sizes
= 1;
747 FT_Bitmap_Size
* bsize
= root
->available_sizes
;
748 FT_UShort x_res
, y_res
;
751 bsize
->width
= font
->header
.avg_width
;
752 bsize
->height
= (FT_Short
)(
753 font
->header
.pixel_height
+ font
->header
.external_leading
);
754 bsize
->size
= font
->header
.nominal_point_size
<< 6;
756 x_res
= font
->header
.horizontal_resolution
;
760 y_res
= font
->header
.vertical_resolution
;
764 bsize
->y_ppem
= FT_MulDiv( bsize
->size
, y_res
, 72 );
765 bsize
->y_ppem
= FT_PIX_ROUND( bsize
->y_ppem
);
770 * the nominal height is larger than the bbox's height
772 * => nominal_point_size contains incorrect value;
773 * use pixel_height as the nominal height
775 if ( bsize
->y_ppem
> font
->header
.pixel_height
<< 6 )
777 FT_TRACE2(( "use pixel_height as the nominal height\n" ));
779 bsize
->y_ppem
= font
->header
.pixel_height
<< 6;
780 bsize
->size
= FT_MulDiv( bsize
->y_ppem
, 72, y_res
);
783 bsize
->x_ppem
= FT_MulDiv( bsize
->size
, x_res
, 72 );
784 bsize
->x_ppem
= FT_PIX_ROUND( bsize
->x_ppem
);
788 FT_CharMapRec charmap
;
791 charmap
.encoding
= FT_ENCODING_NONE
;
792 charmap
.platform_id
= 0;
793 charmap
.encoding_id
= 0;
796 if ( font
->header
.charset
== FT_WinFNT_ID_MAC
)
798 charmap
.encoding
= FT_ENCODING_APPLE_ROMAN
;
799 charmap
.platform_id
= 1;
800 /* charmap.encoding_id = 0; */
803 error
= FT_CMap_New( fnt_cmap_class
,
810 /* Select default charmap */
811 if ( root
->num_charmaps
)
812 root
->charmap
= root
->charmaps
[0];
815 /* setup remaining flags */
817 /* reserve one slot for the .notdef glyph at index 0 */
818 root
->num_glyphs
= font
->header
.last_char
-
819 font
->header
.first_char
+ 1 + 1;
821 if ( font
->header
.face_name_offset
>= font
->header
.file_size
)
823 FT_TRACE2(( "invalid family name offset!\n" ));
824 error
= FNT_Err_Invalid_File_Format
;
827 family_size
= font
->header
.file_size
- font
->header
.face_name_offset
;
828 /* Some broken fonts don't delimit the face name with a final */
829 /* NULL byte -- the frame is erroneously one byte too small. */
830 /* We thus allocate one more byte, setting it explicitly to */
832 if ( FT_ALLOC( font
->family_name
, family_size
+ 1 ) )
835 FT_MEM_COPY( font
->family_name
,
836 font
->fnt_frame
+ font
->header
.face_name_offset
,
839 font
->family_name
[family_size
] = '\0';
841 if ( FT_REALLOC( font
->family_name
,
843 ft_strlen( font
->family_name
) + 1 ) )
846 root
->family_name
= font
->family_name
;
847 root
->style_name
= (char *)"Regular";
849 if ( root
->style_flags
& FT_STYLE_FLAG_BOLD
)
851 if ( root
->style_flags
& FT_STYLE_FLAG_ITALIC
)
852 root
->style_name
= (char *)"Bold Italic";
854 root
->style_name
= (char *)"Bold";
856 else if ( root
->style_flags
& FT_STYLE_FLAG_ITALIC
)
857 root
->style_name
= (char *)"Italic";
862 FNT_Face_Done( face
);
870 FNT_Size_Select( FT_Size size
)
872 FNT_Face face
= (FNT_Face
)size
->face
;
873 FT_WinFNT_Header header
= &face
->font
->header
;
876 FT_Select_Metrics( size
->face
, 0 );
878 size
->metrics
.ascender
= header
->ascent
* 64;
879 size
->metrics
.descender
= -( header
->pixel_height
-
880 header
->ascent
) * 64;
881 size
->metrics
.max_advance
= header
->max_width
* 64;
888 FNT_Size_Request( FT_Size size
,
889 FT_Size_Request req
)
891 FNT_Face face
= (FNT_Face
)size
->face
;
892 FT_WinFNT_Header header
= &face
->font
->header
;
893 FT_Bitmap_Size
* bsize
= size
->face
->available_sizes
;
894 FT_Error error
= FNT_Err_Invalid_Pixel_Size
;
898 height
= FT_REQUEST_HEIGHT( req
);
899 height
= ( height
+ 32 ) >> 6;
903 case FT_SIZE_REQUEST_TYPE_NOMINAL
:
904 if ( height
== ( bsize
->y_ppem
+ 32 ) >> 6 )
908 case FT_SIZE_REQUEST_TYPE_REAL_DIM
:
909 if ( height
== header
->pixel_height
)
914 error
= FNT_Err_Unimplemented_Feature
;
921 return FNT_Size_Select( size
);
926 FNT_Load_Glyph( FT_GlyphSlot slot
,
929 FT_Int32 load_flags
)
931 FNT_Face face
= (FNT_Face
)FT_SIZE_FACE( size
);
932 FNT_Font font
= face
->font
;
933 FT_Error error
= FNT_Err_Ok
;
936 FT_Bitmap
* bitmap
= &slot
->bitmap
;
940 FT_UNUSED( load_flags
);
943 if ( !face
|| !font
||
944 glyph_index
>= (FT_UInt
)( FT_FACE( face
)->num_glyphs
) )
946 error
= FNT_Err_Invalid_Argument
;
950 if ( glyph_index
> 0 )
951 glyph_index
--; /* revert to real index */
953 glyph_index
= font
->header
.default_char
; /* the .notdef glyph */
955 new_format
= FT_BOOL( font
->header
.version
== 0x300 );
956 len
= new_format
? 6 : 4;
958 /* jump to glyph entry */
959 p
= font
->fnt_frame
+ ( new_format
? 148 : 118 ) + len
* glyph_index
;
961 bitmap
->width
= FT_NEXT_SHORT_LE( p
);
964 offset
= FT_NEXT_ULONG_LE( p
);
966 offset
= FT_NEXT_USHORT_LE( p
);
968 if ( offset
>= font
->header
.file_size
)
970 FT_TRACE2(( "invalid FNT offset!\n" ));
971 error
= FNT_Err_Invalid_File_Format
;
975 /* jump to glyph data */
976 p
= font
->fnt_frame
+ /* font->header.bits_offset */ + offset
;
978 /* allocate and build bitmap */
980 FT_Memory memory
= FT_FACE_MEMORY( slot
->face
);
981 FT_Int pitch
= ( bitmap
->width
+ 7 ) >> 3;
986 bitmap
->pitch
= pitch
;
987 bitmap
->rows
= font
->header
.pixel_height
;
988 bitmap
->pixel_mode
= FT_PIXEL_MODE_MONO
;
990 if ( offset
+ pitch
* bitmap
->rows
>= font
->header
.file_size
)
992 FT_TRACE2(( "invalid bitmap width\n" ));
993 error
= FNT_Err_Invalid_File_Format
;
997 /* note: since glyphs are stored in columns and not in rows we */
998 /* can't use ft_glyphslot_set_bitmap */
999 if ( FT_ALLOC_MULT( bitmap
->buffer
, pitch
, bitmap
->rows
) )
1002 column
= (FT_Byte
*)bitmap
->buffer
;
1004 for ( ; pitch
> 0; pitch
--, column
++ )
1006 FT_Byte
* limit
= p
+ bitmap
->rows
;
1009 for ( write
= column
; p
< limit
; p
++, write
+= bitmap
->pitch
)
1014 slot
->internal
->flags
= FT_GLYPH_OWN_BITMAP
;
1015 slot
->bitmap_left
= 0;
1016 slot
->bitmap_top
= font
->header
.ascent
;
1017 slot
->format
= FT_GLYPH_FORMAT_BITMAP
;
1019 /* now set up metrics */
1020 slot
->metrics
.width
= bitmap
->width
<< 6;
1021 slot
->metrics
.height
= bitmap
->rows
<< 6;
1022 slot
->metrics
.horiAdvance
= bitmap
->width
<< 6;
1023 slot
->metrics
.horiBearingX
= 0;
1024 slot
->metrics
.horiBearingY
= slot
->bitmap_top
<< 6;
1026 ft_synthesize_vertical_metrics( &slot
->metrics
,
1027 bitmap
->rows
<< 6 );
1035 winfnt_get_header( FT_Face face
,
1036 FT_WinFNT_HeaderRec
*aheader
)
1038 FNT_Font font
= ((FNT_Face
)face
)->font
;
1041 *aheader
= font
->header
;
1047 static const FT_Service_WinFntRec winfnt_service_rec
=
1057 static const FT_ServiceDescRec winfnt_services
[] =
1059 { FT_SERVICE_ID_XF86_NAME
, FT_XF86_FORMAT_WINFNT
},
1060 { FT_SERVICE_ID_WINFNT
, &winfnt_service_rec
},
1065 static FT_Module_Interface
1066 winfnt_get_service( FT_Driver driver
,
1067 const FT_String
* service_id
)
1069 FT_UNUSED( driver
);
1071 return ft_service_list_lookup( winfnt_services
, service_id
);
1077 FT_CALLBACK_TABLE_DEF
1078 const FT_Driver_ClassRec winfnt_driver_class
=
1081 FT_MODULE_FONT_DRIVER
|
1082 FT_MODULE_DRIVER_NO_OUTLINES
,
1083 sizeof ( FT_DriverRec
),
1091 (FT_Module_Constructor
)0,
1092 (FT_Module_Destructor
) 0,
1093 (FT_Module_Requester
) winfnt_get_service
1096 sizeof( FNT_FaceRec
),
1097 sizeof( FT_SizeRec
),
1098 sizeof( FT_GlyphSlotRec
),
1100 (FT_Face_InitFunc
) FNT_Face_Init
,
1101 (FT_Face_DoneFunc
) FNT_Face_Done
,
1102 (FT_Size_InitFunc
) 0,
1103 (FT_Size_DoneFunc
) 0,
1104 (FT_Slot_InitFunc
) 0,
1105 (FT_Slot_DoneFunc
) 0,
1107 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
1108 ft_stub_set_char_sizes
,
1109 ft_stub_set_pixel_sizes
,
1111 (FT_Slot_LoadFunc
) FNT_Load_Glyph
,
1113 (FT_Face_GetKerningFunc
) 0,
1114 (FT_Face_AttachFunc
) 0,
1115 (FT_Face_GetAdvancesFunc
) 0,
1117 (FT_Size_RequestFunc
) FNT_Size_Request
,
1118 (FT_Size_SelectFunc
) FNT_Size_Select