1 /***************************************************************************/
5 /* FreeType font driver for Windows FNT/FON files */
7 /* Copyright 1996-2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
19 #ifdef FT_FLAT_COMPILE
25 #include <winfonts/winfnt.h>
30 #include <freetype/fterrors.h>
31 #include <freetype/internal/ftstream.h>
32 #include <freetype/internal/ftdebug.h>
33 #include <freetype/internal/ftobjs.h>
36 /*************************************************************************/
38 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
39 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
40 /* messages during execution. */
43 #define FT_COMPONENT trace_winfnt
47 const FT_Frame_Field winmz_header_fields
[] =
50 FT_FRAME_USHORT_LE ( WinMZ_Header
, magic
),
51 FT_FRAME_SKIP_BYTES( 29 * 2 ),
52 FT_FRAME_ULONG_LE ( WinMZ_Header
, lfanew
),
57 const FT_Frame_Field winne_header_fields
[] =
60 FT_FRAME_USHORT_LE ( WinNE_Header
, magic
),
61 FT_FRAME_SKIP_BYTES( 34 ),
62 FT_FRAME_USHORT_LE ( WinNE_Header
, resource_tab_offset
),
63 FT_FRAME_USHORT_LE ( WinNE_Header
, rname_tab_offset
),
68 const FT_Frame_Field winfnt_header_fields
[] =
70 FT_FRAME_START( 134 ),
71 FT_FRAME_USHORT_LE( WinFNT_Header
, version
),
72 FT_FRAME_ULONG_LE ( WinFNT_Header
, file_size
),
73 FT_FRAME_BYTES ( WinFNT_Header
, copyright
, 60 ),
74 FT_FRAME_USHORT_LE( WinFNT_Header
, file_type
),
75 FT_FRAME_USHORT_LE( WinFNT_Header
, nominal_point_size
),
76 FT_FRAME_USHORT_LE( WinFNT_Header
, vertical_resolution
),
77 FT_FRAME_USHORT_LE( WinFNT_Header
, horizontal_resolution
),
78 FT_FRAME_USHORT_LE( WinFNT_Header
, ascent
),
79 FT_FRAME_USHORT_LE( WinFNT_Header
, internal_leading
),
80 FT_FRAME_USHORT_LE( WinFNT_Header
, external_leading
),
81 FT_FRAME_BYTE ( WinFNT_Header
, italic
),
82 FT_FRAME_BYTE ( WinFNT_Header
, underline
),
83 FT_FRAME_BYTE ( WinFNT_Header
, strike_out
),
84 FT_FRAME_USHORT_LE( WinFNT_Header
, weight
),
85 FT_FRAME_BYTE ( WinFNT_Header
, charset
),
86 FT_FRAME_USHORT_LE( WinFNT_Header
, pixel_width
),
87 FT_FRAME_USHORT_LE( WinFNT_Header
, pixel_height
),
88 FT_FRAME_BYTE ( WinFNT_Header
, pitch_and_family
),
89 FT_FRAME_USHORT_LE( WinFNT_Header
, avg_width
),
90 FT_FRAME_USHORT_LE( WinFNT_Header
, max_width
),
91 FT_FRAME_BYTE ( WinFNT_Header
, first_char
),
92 FT_FRAME_BYTE ( WinFNT_Header
, last_char
),
93 FT_FRAME_BYTE ( WinFNT_Header
, default_char
),
94 FT_FRAME_BYTE ( WinFNT_Header
, break_char
),
95 FT_FRAME_USHORT_LE( WinFNT_Header
, bytes_per_row
),
96 FT_FRAME_ULONG_LE ( WinFNT_Header
, device_offset
),
97 FT_FRAME_ULONG_LE ( WinFNT_Header
, face_name_offset
),
98 FT_FRAME_ULONG_LE ( WinFNT_Header
, bits_pointer
),
99 FT_FRAME_ULONG_LE ( WinFNT_Header
, bits_offset
),
100 FT_FRAME_BYTE ( WinFNT_Header
, reserved
),
101 FT_FRAME_ULONG_LE ( WinFNT_Header
, flags
),
102 FT_FRAME_USHORT_LE( WinFNT_Header
, A_space
),
103 FT_FRAME_USHORT_LE( WinFNT_Header
, B_space
),
104 FT_FRAME_USHORT_LE( WinFNT_Header
, C_space
),
105 FT_FRAME_USHORT_LE( WinFNT_Header
, color_table_offset
),
106 FT_FRAME_BYTES ( WinFNT_Header
, reserved
, 4 ),
112 void fnt_done_font( FT_Stream stream
,
115 if ( font
->fnt_frame
)
116 RELEASE_Frame( font
->fnt_frame
);
124 FT_Error
fnt_load_font( FT_Stream stream
,
128 WinFNT_Header
* header
= &font
->header
;
131 /* first of all, read the FNT header */
132 if ( FILE_Seek( font
->offset
) ||
133 READ_Fields( winfnt_header_fields
, header
) )
137 if ( header
->version
!= 0x200 &&
138 header
->version
!= 0x300 )
140 FT_TRACE2(( "[not a valid FNT file]\n" ));
141 error
= FT_Err_Unknown_File_Format
;
145 if ( header
->file_type
& 1 )
147 FT_TRACE2(( "can't handle vector FNT fonts\n" ));
148 error
= FT_Err_Unknown_File_Format
;
152 /* small fixup -- some fonts have the `pixel_width' field set to 0 */
153 if ( header
->pixel_width
== 0 )
154 header
->pixel_width
= header
->pixel_height
;
156 /* this is a FNT file/table, we now extract its frame */
157 if ( FILE_Seek( font
->offset
) ||
158 EXTRACT_Frame( header
->file_size
, font
->fnt_frame
) )
167 void fnt_done_fonts( FNT_Face face
)
169 FT_Memory memory
= FT_FACE(face
)->memory
;
170 FT_Stream stream
= FT_FACE(face
)->stream
;
171 FNT_Font
* cur
= face
->fonts
;
172 FNT_Font
* limit
= cur
+ face
->num_fonts
;
175 for ( ; cur
< limit
; cur
++ )
176 fnt_done_font( stream
, cur
);
183 FT_Error
fnt_get_dll_fonts( FNT_Face face
)
186 FT_Stream stream
= FT_FACE(face
)->stream
;
187 FT_Memory memory
= FT_FACE(face
)->memory
;
188 WinMZ_Header mz_header
;
194 /* does it begin with a MZ header? */
195 if ( FILE_Seek( 0 ) ||
196 READ_Fields( winmz_header_fields
, &mz_header
) )
199 error
= FT_Err_Unknown_File_Format
;
200 if ( mz_header
.magic
== WINFNT_MZ_MAGIC
)
202 /* yes, now look for a NE header in the file */
203 WinNE_Header ne_header
;
206 if ( FILE_Seek( mz_header
.lfanew
) ||
207 READ_Fields( winne_header_fields
, &ne_header
) )
210 error
= FT_Err_Unknown_File_Format
;
211 if ( ne_header
.magic
== WINFNT_NE_MAGIC
)
213 /* good, now look in the resource table for each FNT resource */
214 FT_ULong res_offset
= mz_header
.lfanew
+
215 ne_header
.resource_tab_offset
;
217 FT_UShort size_shift
;
218 FT_UShort font_count
= 0;
219 FT_ULong font_offset
= 0;
222 if ( FILE_Seek( res_offset
) ||
223 ACCESS_Frame( ne_header
.rname_tab_offset
-
224 ne_header
.resource_tab_offset
) )
227 size_shift
= GET_UShortLE();
231 FT_UShort type_id
, count
;
234 type_id
= GET_UShortLE();
238 count
= GET_UShortLE();
240 if ( type_id
== 0x8008 )
243 font_offset
= FILE_Pos() + 4 + ( stream
->cursor
- stream
->limit
);
247 stream
->cursor
+= 4 + count
* 12;
251 if ( !font_count
|| !font_offset
)
253 FT_TRACE2(( "this file doesn't contain any FNT resources!\n" ));
254 error
= FT_Err_Unknown_File_Format
;
258 if ( FILE_Seek( font_offset
) ||
259 ALLOC_ARRAY( face
->fonts
, font_count
, FNT_Font
) )
262 face
->num_fonts
= font_count
;
264 if ( ACCESS_Frame( (FT_Long
)font_count
* 12 ) )
267 /* now read the offset and position of each FNT font */
269 FNT_Font
* cur
= face
->fonts
;
270 FNT_Font
* limit
= cur
+ font_count
;
273 for ( ; cur
< limit
; cur
++ )
275 cur
->offset
= (FT_ULong
)GET_UShortLE() << size_shift
;
276 cur
->fnt_size
= (FT_ULong
)GET_UShortLE() << size_shift
;
277 cur
->size_shift
= size_shift
;
283 /* finally, try to load each font there */
285 FNT_Font
* cur
= face
->fonts
;
286 FNT_Font
* limit
= cur
+ font_count
;
289 for ( ; cur
< limit
; cur
++ )
291 error
= fnt_load_font( stream
, cur
);
301 fnt_done_fonts( face
);
309 void FNT_Done_Face( FNT_Face face
)
311 FT_Memory memory
= FT_FACE_MEMORY( face
);
314 fnt_done_fonts( face
);
316 FREE( face
->root
.available_sizes
);
317 face
->root
.num_fixed_sizes
= 0;
322 FT_Error
FNT_Init_Face( FT_Stream stream
,
326 FT_Parameter
* params
)
329 FT_Memory memory
= FT_FACE_MEMORY( face
);
331 FT_UNUSED( num_params
);
333 FT_UNUSED( face_index
);
336 /* try to load several fonts from a DLL */
337 error
= fnt_get_dll_fonts( face
);
340 /* this didn't work, now try to load a single FNT font */
341 FT_Memory memory
= FT_FACE_MEMORY( face
);
344 if ( ALLOC( face
->fonts
, sizeof ( *face
->fonts
) ) )
351 font
->fnt_size
= stream
->size
;
353 error
= fnt_load_font( stream
, font
);
358 /* all right, one or more fonts were loaded; we now need to */
359 /* fill the root FT_Face fields with relevant information */
361 FT_Face root
= FT_FACE( face
);
362 FNT_Font
* fonts
= face
->fonts
;
363 FNT_Font
* limit
= fonts
+ face
->num_fonts
;
368 root
->face_flags
= FT_FACE_FLAG_FIXED_SIZES
|
369 FT_FACE_FLAG_HORIZONTAL
;
371 if ( fonts
->header
.avg_width
== fonts
->header
.max_width
)
372 root
->face_flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
374 if ( fonts
->header
.italic
)
375 root
->style_flags
|= FT_STYLE_FLAG_ITALIC
;
377 if ( fonts
->header
.weight
>= 800 )
378 root
->style_flags
|= FT_STYLE_FLAG_BOLD
;
380 /* Setup the `fixed_sizes' array */
381 if ( ALLOC_ARRAY( root
->available_sizes
, face
->num_fonts
,
385 root
->num_fixed_sizes
= face
->num_fonts
;
388 FT_Bitmap_Size
* size
= root
->available_sizes
;
391 for ( cur
= fonts
; cur
< limit
; cur
++, size
++ )
393 size
->width
= cur
->header
.pixel_width
;
394 size
->height
= cur
->header
.pixel_height
;
398 /* Setup the `charmaps' array */
399 root
->charmaps
= &face
->charmap_handle
;
400 root
->num_charmaps
= 1;
402 face
->charmap
.encoding
= ft_encoding_unicode
;
403 face
->charmap
.platform_id
= 3;
404 face
->charmap
.encoding_id
= 1;
405 face
->charmap
.face
= root
;
407 face
->charmap_handle
= &face
->charmap
;
409 root
->charmap
= face
->charmap_handle
;
411 /* setup remaining flags */
412 root
->num_glyphs
= fonts
->header
.last_char
-
413 fonts
->header
.first_char
+ 1;
415 root
->family_name
= (FT_String
*)fonts
->fnt_frame
+
416 fonts
->header
.face_name_offset
;
417 root
->style_name
= "Regular";
419 if ( root
->style_flags
& FT_STYLE_FLAG_BOLD
)
421 if ( root
->style_flags
& FT_STYLE_FLAG_ITALIC
)
422 root
->style_name
= "Bold Italic";
424 root
->style_name
= "Bold";
426 else if ( root
->style_flags
& FT_STYLE_FLAG_ITALIC
)
427 root
->style_name
= "Italic";
432 FNT_Done_Face( face
);
440 FT_Error
FNT_Set_Pixel_Size( FNT_Size size
)
442 /* look up a font corresponding to the current pixel size */
443 FNT_Face face
= (FNT_Face
)FT_SIZE_FACE( size
);
444 FNT_Font
* cur
= face
->fonts
;
445 FNT_Font
* limit
= cur
+ face
->num_fonts
;
449 for ( ; cur
< limit
; cur
++ )
451 /* we only compare the character height, as fonts used some strange */
453 if ( cur
->header
.pixel_height
== size
->root
.metrics
.y_ppem
)
457 size
->root
.metrics
.ascender
= cur
->header
.ascent
* 64;
458 size
->root
.metrics
.descender
= ( cur
->header
.pixel_height
-
459 cur
->header
.ascent
) * 64;
460 size
->root
.metrics
.height
= cur
->header
.pixel_height
* 64;
465 return ( size
->font
? FT_Err_Ok
: FT_Err_Invalid_Argument
);
470 FT_UInt
FNT_Get_Char_Index( FT_CharMap charmap
,
473 FT_UInt result
= char_code
;
478 FNT_Font
* font
= ((FNT_Face
)charmap
->face
)->fonts
;
479 FT_UInt first
= font
->header
.first_char
;
480 FT_UInt count
= font
->header
.last_char
- first
+ 1;
484 if ( char_code
< count
)
485 result
= char_code
+ 1;
495 FT_Error
FNT_Load_Glyph( FT_GlyphSlot slot
,
500 FNT_Font
* font
= size
->font
;
504 FT_Bitmap
* bitmap
= &slot
->bitmap
;
509 FT_UNUSED( load_flags
);
514 error
= FT_Err_Invalid_Argument
;
518 if ( glyph_index
> 0 )
521 glyph_index
= font
->header
.default_char
- font
->header
.first_char
;
523 new_format
= font
->header
.version
== 0x300;
524 len
= new_format
? 6 : 4;
526 /* jump to glyph entry */
527 p
= font
->fnt_frame
+ 118 + len
* glyph_index
;
529 bitmap
->width
= NEXT_ShortLE(p
);
532 offset
= NEXT_ULongLE(p
);
534 offset
= NEXT_UShortLE(p
);
536 /* jump to glyph data */
537 p
= font
->fnt_frame
+ /* font->header.bits_offset */ + offset
;
539 /* allocate and build bitmap */
541 FT_Memory memory
= FT_FACE_MEMORY( slot
->face
);
542 FT_Int pitch
= ( bitmap
->width
+ 7 ) >> 3;
547 bitmap
->pitch
= pitch
;
548 bitmap
->rows
= font
->header
.pixel_height
;
549 bitmap
->pixel_mode
= ft_pixel_mode_mono
;
551 if ( ALLOC( bitmap
->buffer
, pitch
* bitmap
->rows
) )
554 column
= (FT_Byte
*)bitmap
->buffer
;
556 for ( ; pitch
> 0; pitch
--, column
++ )
558 FT_Byte
* limit
= p
+ bitmap
->rows
;
561 for ( write
= column
; p
< limit
; p
++, write
+= bitmap
->pitch
)
566 slot
->flags
= ft_glyph_own_bitmap
;
567 slot
->bitmap_left
= 0;
568 slot
->bitmap_top
= font
->header
.ascent
;
569 slot
->format
= ft_glyph_format_bitmap
;
571 /* now set up metrics */
572 slot
->metrics
.horiAdvance
= bitmap
->width
<< 6;
573 slot
->metrics
.horiBearingX
= 0;
574 slot
->metrics
.horiBearingY
= slot
->bitmap_top
<< 6;
576 slot
->linearHoriAdvance
= (FT_Fixed
)bitmap
->width
<< 16;
583 const FT_Driver_Class winfnt_driver_class
=
586 ft_module_font_driver
,
587 sizeof ( FT_DriverRec
),
595 (FT_Module_Constructor
)0,
596 (FT_Module_Destructor
) 0,
597 (FT_Module_Requester
) 0
600 sizeof( FNT_FaceRec
),
601 sizeof( FNT_SizeRec
),
602 sizeof( FT_GlyphSlotRec
),
604 (FTDriver_initFace
) FNT_Init_Face
,
605 (FTDriver_doneFace
) FNT_Done_Face
,
606 (FTDriver_initSize
) 0,
607 (FTDriver_doneSize
) 0,
608 (FTDriver_initGlyphSlot
)0,
609 (FTDriver_doneGlyphSlot
)0,
611 (FTDriver_setCharSizes
) FNT_Set_Pixel_Size
,
612 (FTDriver_setPixelSizes
)FNT_Set_Pixel_Size
,
614 (FTDriver_loadGlyph
) FNT_Load_Glyph
,
615 (FTDriver_getCharIndex
) FNT_Get_Char_Index
,
617 (FTDriver_getKerning
) 0,
618 (FTDriver_attachFile
) 0,
619 (FTDriver_getAdvances
) 0