blob: 210c15a8b0623d990c1650029de52cffcc2f08cc [file] [log] [blame]
David Turnerab9cc272000-07-07 19:46:01 +00001/***************************************************************************/
2/* */
3/* winfnt.c */
4/* */
5/* FreeType font driver for Windows FNT/FON files */
6/* */
7/* Copyright 1996-2000 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
Werner Lemberg415cc7c2000-07-08 22:52:21 +000010/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
David Turnerab9cc272000-07-07 19:46:01 +000012/* 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. */
15/* */
16/***************************************************************************/
17
Werner Lemberg415cc7c2000-07-08 22:52:21 +000018
Werner Lemberg90d99642000-12-09 00:45:38 +000019#include <ft2build.h>
20#include FT_ERRORS_H
21#include FT_INTERNAL_DEBUG_H
22#include FT_INTERNAL_STREAM_H
23#include FT_INTERNAL_OBJECTS_H
24#include FT_INTERNAL_FNT_TYPES_H
25#include FT_SOURCE_FILE(winfonts,winfnt.h)
David Turnerab9cc272000-07-07 19:46:01 +000026
Werner Lemberg415cc7c2000-07-08 22:52:21 +000027
28 /*************************************************************************/
29 /* */
30 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
31 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
32 /* messages during execution. */
33 /* */
David Turnerab9cc272000-07-07 19:46:01 +000034#undef FT_COMPONENT
Werner Lemberg415cc7c2000-07-08 22:52:21 +000035#define FT_COMPONENT trace_winfnt
David Turnerab9cc272000-07-07 19:46:01 +000036
37
38 static
Werner Lemberg415cc7c2000-07-08 22:52:21 +000039 const FT_Frame_Field winmz_header_fields[] =
David Turnerab9cc272000-07-07 19:46:01 +000040 {
Werner Lemberge72c9fe2000-07-31 18:59:02 +000041#undef FT_STRUCTURE
42#define FT_STRUCTURE WinMZ_Header
43
Werner Lemberg415cc7c2000-07-08 22:52:21 +000044 FT_FRAME_START( 64 ),
Werner Lemberg8bb45ec2000-09-29 06:41:56 +000045 FT_FRAME_USHORT_LE ( magic ),
46 FT_FRAME_SKIP_BYTES( 29 * 2 ),
47 FT_FRAME_ULONG_LE ( lfanew ),
Werner Lemberg415cc7c2000-07-08 22:52:21 +000048 FT_FRAME_END
49 };
50
51 static
52 const FT_Frame_Field winne_header_fields[] =
53 {
Werner Lemberge72c9fe2000-07-31 18:59:02 +000054#undef FT_STRUCTURE
55#define FT_STRUCTURE WinNE_Header
56
Werner Lemberg415cc7c2000-07-08 22:52:21 +000057 FT_FRAME_START( 40 ),
Werner Lemberg8bb45ec2000-09-29 06:41:56 +000058 FT_FRAME_USHORT_LE ( magic ),
59 FT_FRAME_SKIP_BYTES( 34 ),
60 FT_FRAME_USHORT_LE ( resource_tab_offset ),
61 FT_FRAME_USHORT_LE ( rname_tab_offset ),
Werner Lemberg415cc7c2000-07-08 22:52:21 +000062 FT_FRAME_END
63 };
64
65 static
66 const FT_Frame_Field winfnt_header_fields[] =
67 {
Werner Lemberge72c9fe2000-07-31 18:59:02 +000068#undef FT_STRUCTURE
69#define FT_STRUCTURE WinFNT_Header
70
Werner Lemberg415cc7c2000-07-08 22:52:21 +000071 FT_FRAME_START( 134 ),
Werner Lemberg8bb45ec2000-09-29 06:41:56 +000072 FT_FRAME_USHORT_LE( version ),
73 FT_FRAME_ULONG_LE ( file_size ),
74 FT_FRAME_BYTES ( copyright, 60 ),
75 FT_FRAME_USHORT_LE( file_type ),
76 FT_FRAME_USHORT_LE( nominal_point_size ),
77 FT_FRAME_USHORT_LE( vertical_resolution ),
78 FT_FRAME_USHORT_LE( horizontal_resolution ),
79 FT_FRAME_USHORT_LE( ascent ),
80 FT_FRAME_USHORT_LE( internal_leading ),
81 FT_FRAME_USHORT_LE( external_leading ),
82 FT_FRAME_BYTE ( italic ),
83 FT_FRAME_BYTE ( underline ),
84 FT_FRAME_BYTE ( strike_out ),
85 FT_FRAME_USHORT_LE( weight ),
86 FT_FRAME_BYTE ( charset ),
87 FT_FRAME_USHORT_LE( pixel_width ),
88 FT_FRAME_USHORT_LE( pixel_height ),
89 FT_FRAME_BYTE ( pitch_and_family ),
90 FT_FRAME_USHORT_LE( avg_width ),
91 FT_FRAME_USHORT_LE( max_width ),
92 FT_FRAME_BYTE ( first_char ),
93 FT_FRAME_BYTE ( last_char ),
94 FT_FRAME_BYTE ( default_char ),
95 FT_FRAME_BYTE ( break_char ),
96 FT_FRAME_USHORT_LE( bytes_per_row ),
97 FT_FRAME_ULONG_LE ( device_offset ),
98 FT_FRAME_ULONG_LE ( face_name_offset ),
99 FT_FRAME_ULONG_LE ( bits_pointer ),
100 FT_FRAME_ULONG_LE ( bits_offset ),
101 FT_FRAME_BYTE ( reserved ),
102 FT_FRAME_ULONG_LE ( flags ),
103 FT_FRAME_USHORT_LE( A_space ),
104 FT_FRAME_USHORT_LE( B_space ),
105 FT_FRAME_USHORT_LE( C_space ),
106 FT_FRAME_USHORT_LE( color_table_offset ),
107 FT_FRAME_BYTES ( reserved, 4 ),
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000108 FT_FRAME_END
109 };
110
111
112 static
113 void fnt_done_font( FT_Stream stream,
114 FNT_Font* font )
115 {
116 if ( font->fnt_frame )
David Turnerab9cc272000-07-07 19:46:01 +0000117 RELEASE_Frame( font->fnt_frame );
Werner Lembergb48a6092000-07-09 19:15:30 +0000118
David Turnerab9cc272000-07-07 19:46:01 +0000119 font->fnt_size = 0;
120 font->fnt_frame = 0;
Werner Lembergb48a6092000-07-09 19:15:30 +0000121 }
David Turnerab9cc272000-07-07 19:46:01 +0000122
123
124 static
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000125 FT_Error fnt_load_font( FT_Stream stream,
126 FNT_Font* font )
David Turnerab9cc272000-07-07 19:46:01 +0000127 {
128 FT_Error error;
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000129 WinFNT_Header* header = &font->header;
Werner Lembergb48a6092000-07-09 19:15:30 +0000130
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000131
David Turnerab9cc272000-07-07 19:46:01 +0000132 /* first of all, read the FNT header */
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000133 if ( FILE_Seek( font->offset ) ||
David Turnerab9cc272000-07-07 19:46:01 +0000134 READ_Fields( winfnt_header_fields, header ) )
135 goto Exit;
136
137 /* check header */
138 if ( header->version != 0x200 &&
139 header->version != 0x300 )
140 {
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000141 FT_TRACE2(( "[not a valid FNT file]\n" ));
David Turnerab9cc272000-07-07 19:46:01 +0000142 error = FT_Err_Unknown_File_Format;
143 goto Exit;
144 }
145
146 if ( header->file_type & 1 )
147 {
Werner Lemberg8bb45ec2000-09-29 06:41:56 +0000148 FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));
David Turnerab9cc272000-07-07 19:46:01 +0000149 error = FT_Err_Unknown_File_Format;
150 goto Exit;
151 }
152
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000153 /* small fixup -- some fonts have the `pixel_width' field set to 0 */
David Turnerab9cc272000-07-07 19:46:01 +0000154 if ( header->pixel_width == 0 )
155 header->pixel_width = header->pixel_height;
156
157 /* this is a FNT file/table, we now extract its frame */
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000158 if ( FILE_Seek( font->offset ) ||
David Turnerab9cc272000-07-07 19:46:01 +0000159 EXTRACT_Frame( header->file_size, font->fnt_frame ) )
160 goto Exit;
161
162 Exit:
163 return error;
Werner Lembergb48a6092000-07-09 19:15:30 +0000164 }
David Turnerab9cc272000-07-07 19:46:01 +0000165
166
David Turnerab9cc272000-07-07 19:46:01 +0000167 static
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000168 void fnt_done_fonts( FNT_Face face )
David Turnerab9cc272000-07-07 19:46:01 +0000169 {
170 FT_Memory memory = FT_FACE(face)->memory;
171 FT_Stream stream = FT_FACE(face)->stream;
172 FNT_Font* cur = face->fonts;
173 FNT_Font* limit = cur + face->num_fonts;
Werner Lembergb48a6092000-07-09 19:15:30 +0000174
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000175
David Turnerab9cc272000-07-07 19:46:01 +0000176 for ( ; cur < limit; cur++ )
177 fnt_done_font( stream, cur );
Werner Lembergb48a6092000-07-09 19:15:30 +0000178
David Turnerab9cc272000-07-07 19:46:01 +0000179 FREE( face->fonts );
180 face->num_fonts = 0;
181 }
182
Werner Lemberg8bb45ec2000-09-29 06:41:56 +0000183
David Turnerab9cc272000-07-07 19:46:01 +0000184 static
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000185 FT_Error fnt_get_dll_fonts( FNT_Face face )
David Turnerab9cc272000-07-07 19:46:01 +0000186 {
187 FT_Error error;
188 FT_Stream stream = FT_FACE(face)->stream;
189 FT_Memory memory = FT_FACE(face)->memory;
190 WinMZ_Header mz_header;
191
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000192
David Turnerab9cc272000-07-07 19:46:01 +0000193 face->fonts = 0;
194 face->num_fonts = 0;
195
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000196 /* does it begin with a MZ header? */
David Turnerab9cc272000-07-07 19:46:01 +0000197 if ( FILE_Seek( 0 ) ||
198 READ_Fields( winmz_header_fields, &mz_header ) )
199 goto Exit;
200
David Turnera90663f2000-07-08 00:41:13 +0000201 error = FT_Err_Unknown_File_Format;
David Turnerab9cc272000-07-07 19:46:01 +0000202 if ( mz_header.magic == WINFNT_MZ_MAGIC )
203 {
204 /* yes, now look for a NE header in the file */
205 WinNE_Header ne_header;
Werner Lembergb48a6092000-07-09 19:15:30 +0000206
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000207
David Turnerab9cc272000-07-07 19:46:01 +0000208 if ( FILE_Seek( mz_header.lfanew ) ||
209 READ_Fields( winne_header_fields, &ne_header ) )
210 goto Exit;
Werner Lembergb48a6092000-07-09 19:15:30 +0000211
David Turnera90663f2000-07-08 00:41:13 +0000212 error = FT_Err_Unknown_File_Format;
David Turnerab9cc272000-07-07 19:46:01 +0000213 if ( ne_header.magic == WINFNT_NE_MAGIC )
214 {
215 /* good, now look in the resource table for each FNT resource */
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000216 FT_ULong res_offset = mz_header.lfanew +
217 ne_header.resource_tab_offset;
Werner Lembergb48a6092000-07-09 19:15:30 +0000218
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000219 FT_UShort size_shift;
220 FT_UShort font_count = 0;
221 FT_ULong font_offset = 0;
Werner Lembergb48a6092000-07-09 19:15:30 +0000222
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000223
David Turnerab9cc272000-07-07 19:46:01 +0000224 if ( FILE_Seek( res_offset ) ||
225 ACCESS_Frame( ne_header.rname_tab_offset -
226 ne_header.resource_tab_offset ) )
227 goto Exit;
Werner Lembergb48a6092000-07-09 19:15:30 +0000228
David Turnerab9cc272000-07-07 19:46:01 +0000229 size_shift = GET_UShortLE();
Werner Lembergb48a6092000-07-09 19:15:30 +0000230
David Turnerab9cc272000-07-07 19:46:01 +0000231 for (;;)
232 {
233 FT_UShort type_id, count;
Werner Lembergb48a6092000-07-09 19:15:30 +0000234
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000235
David Turnerab9cc272000-07-07 19:46:01 +0000236 type_id = GET_UShortLE();
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000237 if ( !type_id )
David Turnerab9cc272000-07-07 19:46:01 +0000238 break;
Werner Lembergb48a6092000-07-09 19:15:30 +0000239
David Turnerab9cc272000-07-07 19:46:01 +0000240 count = GET_UShortLE();
Werner Lembergb48a6092000-07-09 19:15:30 +0000241
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000242 if ( type_id == 0x8008 )
David Turnerab9cc272000-07-07 19:46:01 +0000243 {
244 font_count = count;
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000245 font_offset = FILE_Pos() + 4 + ( stream->cursor - stream->limit );
David Turnerab9cc272000-07-07 19:46:01 +0000246 break;
247 }
Werner Lembergb48a6092000-07-09 19:15:30 +0000248
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000249 stream->cursor += 4 + count * 12;
David Turnerab9cc272000-07-07 19:46:01 +0000250 }
251 FORGET_Frame();
252
253 if ( !font_count || !font_offset )
254 {
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000255 FT_TRACE2(( "this file doesn't contain any FNT resources!\n" ));
David Turnerab9cc272000-07-07 19:46:01 +0000256 error = FT_Err_Unknown_File_Format;
257 goto Exit;
Werner Lembergb48a6092000-07-09 19:15:30 +0000258 }
David Turnerab9cc272000-07-07 19:46:01 +0000259
260 if ( FILE_Seek( font_offset ) ||
Werner Lembergb48a6092000-07-09 19:15:30 +0000261 ALLOC_ARRAY( face->fonts, font_count, FNT_Font ) )
David Turnerab9cc272000-07-07 19:46:01 +0000262 goto Exit;
Werner Lembergb48a6092000-07-09 19:15:30 +0000263
David Turnerab9cc272000-07-07 19:46:01 +0000264 face->num_fonts = font_count;
Werner Lembergb48a6092000-07-09 19:15:30 +0000265
David Turnerab9cc272000-07-07 19:46:01 +0000266 if ( ACCESS_Frame( (FT_Long)font_count * 12 ) )
267 goto Exit;
Werner Lembergb48a6092000-07-09 19:15:30 +0000268
David Turnerab9cc272000-07-07 19:46:01 +0000269 /* now read the offset and position of each FNT font */
270 {
271 FNT_Font* cur = face->fonts;
272 FNT_Font* limit = cur + font_count;
Werner Lembergb48a6092000-07-09 19:15:30 +0000273
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000274
David Turnerab9cc272000-07-07 19:46:01 +0000275 for ( ; cur < limit; cur++ )
276 {
277 cur->offset = (FT_ULong)GET_UShortLE() << size_shift;
278 cur->fnt_size = (FT_ULong)GET_UShortLE() << size_shift;
279 cur->size_shift = size_shift;
280 stream->cursor += 8;
281 }
282 }
283 FORGET_Frame();
Werner Lembergb48a6092000-07-09 19:15:30 +0000284
David Turnerab9cc272000-07-07 19:46:01 +0000285 /* finally, try to load each font there */
286 {
287 FNT_Font* cur = face->fonts;
288 FNT_Font* limit = cur + font_count;
Werner Lembergb48a6092000-07-09 19:15:30 +0000289
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000290
David Turnerab9cc272000-07-07 19:46:01 +0000291 for ( ; cur < limit; cur++ )
292 {
293 error = fnt_load_font( stream, cur );
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000294 if ( error )
295 goto Fail;
David Turnerab9cc272000-07-07 19:46:01 +0000296 }
297 }
298 }
299 }
300
301 Fail:
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000302 if ( error )
David Turnerab9cc272000-07-07 19:46:01 +0000303 fnt_done_fonts( face );
304
305 Exit:
306 return error;
307 }
308
309
David Turnerab9cc272000-07-07 19:46:01 +0000310 static
311 void FNT_Done_Face( FNT_Face face )
312 {
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000313 FT_Memory memory = FT_FACE_MEMORY( face );
Werner Lembergb48a6092000-07-09 19:15:30 +0000314
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000315
316 fnt_done_fonts( face );
Werner Lembergb48a6092000-07-09 19:15:30 +0000317
David Turnerab9cc272000-07-07 19:46:01 +0000318 FREE( face->root.available_sizes );
319 face->root.num_fixed_sizes = 0;
320 }
321
Werner Lembergb48a6092000-07-09 19:15:30 +0000322
David Turnerab9cc272000-07-07 19:46:01 +0000323 static
324 FT_Error FNT_Init_Face( FT_Stream stream,
325 FNT_Face face,
326 FT_Int face_index,
327 FT_Int num_params,
328 FT_Parameter* params )
329 {
330 FT_Error error;
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000331 FT_Memory memory = FT_FACE_MEMORY( face );
Werner Lembergb48a6092000-07-09 19:15:30 +0000332
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000333 FT_UNUSED( num_params );
334 FT_UNUSED( params );
335 FT_UNUSED( face_index );
Werner Lembergb48a6092000-07-09 19:15:30 +0000336
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000337
David Turnerab9cc272000-07-07 19:46:01 +0000338 /* try to load several fonts from a DLL */
339 error = fnt_get_dll_fonts( face );
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000340 if ( error )
David Turnerab9cc272000-07-07 19:46:01 +0000341 {
342 /* this didn't work, now try to load a single FNT font */
David Turnerab9cc272000-07-07 19:46:01 +0000343 FNT_Font* font;
Werner Lembergb48a6092000-07-09 19:15:30 +0000344
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000345 if ( ALLOC( face->fonts, sizeof ( *face->fonts ) ) )
David Turnerab9cc272000-07-07 19:46:01 +0000346 goto Exit;
Werner Lembergb48a6092000-07-09 19:15:30 +0000347
David Turnerab9cc272000-07-07 19:46:01 +0000348 face->num_fonts = 1;
349 font = face->fonts;
Werner Lembergb48a6092000-07-09 19:15:30 +0000350
David Turnerab9cc272000-07-07 19:46:01 +0000351 font->offset = 0;
352 font->fnt_size = stream->size;
Werner Lembergb48a6092000-07-09 19:15:30 +0000353
David Turnerab9cc272000-07-07 19:46:01 +0000354 error = fnt_load_font( stream, font );
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000355 if ( error )
David Turnerab9cc272000-07-07 19:46:01 +0000356 goto Fail;
357 }
358
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000359 /* all right, one or more fonts were loaded; we now need to */
Werner Lembergb48a6092000-07-09 19:15:30 +0000360 /* fill the root FT_Face fields with relevant information */
David Turnerab9cc272000-07-07 19:46:01 +0000361 {
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000362 FT_Face root = FT_FACE( face );
363 FNT_Font* fonts = face->fonts;
364 FNT_Font* limit = fonts + face->num_fonts;
365 FNT_Font* cur;
366
David Turnerab9cc272000-07-07 19:46:01 +0000367
368 root->num_faces = 1;
369 root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
370 FT_FACE_FLAG_HORIZONTAL;
371
372 if ( fonts->header.avg_width == fonts->header.max_width )
373 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
Werner Lembergb48a6092000-07-09 19:15:30 +0000374
David Turnerab9cc272000-07-07 19:46:01 +0000375 if ( fonts->header.italic )
376 root->style_flags |= FT_STYLE_FLAG_ITALIC;
Werner Lembergb48a6092000-07-09 19:15:30 +0000377
David Turnerab9cc272000-07-07 19:46:01 +0000378 if ( fonts->header.weight >= 800 )
379 root->style_flags |= FT_STYLE_FLAG_BOLD;
380
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000381 /* Setup the `fixed_sizes' array */
382 if ( ALLOC_ARRAY( root->available_sizes, face->num_fonts,
383 FT_Bitmap_Size ) )
David Turnerab9cc272000-07-07 19:46:01 +0000384 goto Fail;
385
Werner Lembergb48a6092000-07-09 19:15:30 +0000386 root->num_fixed_sizes = face->num_fonts;
387
David Turnerab9cc272000-07-07 19:46:01 +0000388 {
389 FT_Bitmap_Size* size = root->available_sizes;
Werner Lembergb48a6092000-07-09 19:15:30 +0000390
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000391
David Turnerab9cc272000-07-07 19:46:01 +0000392 for ( cur = fonts; cur < limit; cur++, size++ )
393 {
394 size->width = cur->header.pixel_width;
395 size->height = cur->header.pixel_height;
396 }
397 }
Werner Lembergb48a6092000-07-09 19:15:30 +0000398
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000399 /* Setup the `charmaps' array */
David Turnerab9cc272000-07-07 19:46:01 +0000400 root->charmaps = &face->charmap_handle;
401 root->num_charmaps = 1;
402
403 face->charmap.encoding = ft_encoding_unicode;
404 face->charmap.platform_id = 3;
405 face->charmap.encoding_id = 1;
406 face->charmap.face = root;
Werner Lembergb48a6092000-07-09 19:15:30 +0000407
David Turnerab9cc272000-07-07 19:46:01 +0000408 face->charmap_handle = &face->charmap;
Werner Lembergb48a6092000-07-09 19:15:30 +0000409
David Turnerab9cc272000-07-07 19:46:01 +0000410 root->charmap = face->charmap_handle;
411
Werner Lembergb48a6092000-07-09 19:15:30 +0000412 /* setup remaining flags */
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000413 root->num_glyphs = fonts->header.last_char -
414 fonts->header.first_char + 1;
Werner Lembergb48a6092000-07-09 19:15:30 +0000415
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000416 root->family_name = (FT_String*)fonts->fnt_frame +
417 fonts->header.face_name_offset;
Werner Lembergb1dd3532000-07-31 22:51:00 +0000418 root->style_name = (char *)"Regular";
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000419
420 if ( root->style_flags & FT_STYLE_FLAG_BOLD )
David Turnerab9cc272000-07-07 19:46:01 +0000421 {
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000422 if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
Werner Lembergb1dd3532000-07-31 22:51:00 +0000423 root->style_name = (char *)"Bold Italic";
David Turnerab9cc272000-07-07 19:46:01 +0000424 else
Werner Lembergb1dd3532000-07-31 22:51:00 +0000425 root->style_name = (char *)"Bold";
David Turnerab9cc272000-07-07 19:46:01 +0000426 }
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000427 else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
Werner Lembergb1dd3532000-07-31 22:51:00 +0000428 root->style_name = (char *)"Italic";
David Turnerab9cc272000-07-07 19:46:01 +0000429 }
Werner Lembergb48a6092000-07-09 19:15:30 +0000430
David Turnerab9cc272000-07-07 19:46:01 +0000431 Fail:
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000432 if ( error )
David Turnerab9cc272000-07-07 19:46:01 +0000433 FNT_Done_Face( face );
Werner Lembergb48a6092000-07-09 19:15:30 +0000434
David Turnerab9cc272000-07-07 19:46:01 +0000435 Exit:
436 return error;
Werner Lembergb48a6092000-07-09 19:15:30 +0000437 }
David Turnerab9cc272000-07-07 19:46:01 +0000438
439
David Turnerab9cc272000-07-07 19:46:01 +0000440 static
441 FT_Error FNT_Set_Pixel_Size( FNT_Size size )
442 {
443 /* look up a font corresponding to the current pixel size */
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000444 FNT_Face face = (FNT_Face)FT_SIZE_FACE( size );
David Turnerab9cc272000-07-07 19:46:01 +0000445 FNT_Font* cur = face->fonts;
446 FNT_Font* limit = cur + face->num_fonts;
447
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000448
David Turnerab9cc272000-07-07 19:46:01 +0000449 size->font = 0;
450 for ( ; cur < limit; cur++ )
451 {
452 /* we only compare the character height, as fonts used some strange */
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000453 /* values */
David Turnerab9cc272000-07-07 19:46:01 +0000454 if ( cur->header.pixel_height == size->root.metrics.y_ppem )
455 {
456 size->font = cur;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000457
Werner Lemberg0959a872000-07-18 06:50:03 +0000458 size->root.metrics.ascender = cur->header.ascent * 64;
459 size->root.metrics.descender = ( cur->header.pixel_height -
460 cur->header.ascent ) * 64;
461 size->root.metrics.height = cur->header.pixel_height * 64;
David Turnerab9cc272000-07-07 19:46:01 +0000462 break;
Werner Lembergb48a6092000-07-09 19:15:30 +0000463 }
David Turnerab9cc272000-07-07 19:46:01 +0000464 }
465
Werner Lemberg8bb45ec2000-09-29 06:41:56 +0000466 return ( size->font ? FT_Err_Ok : FT_Err_Invalid_Pixel_Size );
David Turnerab9cc272000-07-07 19:46:01 +0000467 }
468
469
470 static
471 FT_UInt FNT_Get_Char_Index( FT_CharMap charmap,
472 FT_ULong char_code )
473 {
474 FT_UInt result = char_code;
Werner Lembergb48a6092000-07-09 19:15:30 +0000475
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000476
477 if ( charmap )
David Turnerab9cc272000-07-07 19:46:01 +0000478 {
479 FNT_Font* font = ((FNT_Face)charmap->face)->fonts;
480 FT_UInt first = font->header.first_char;
481 FT_UInt count = font->header.last_char - first + 1;
Werner Lembergb48a6092000-07-09 19:15:30 +0000482
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000483
David Turnerab9cc272000-07-07 19:46:01 +0000484 char_code -= first;
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000485 if ( char_code < count )
Werner Lembergd060a752000-07-20 06:57:41 +0000486 result = char_code + 1;
David Turnerab9cc272000-07-07 19:46:01 +0000487 else
David Turnerbca33282000-07-19 20:17:37 +0000488 result = 0;
David Turnerab9cc272000-07-07 19:46:01 +0000489 }
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000490
David Turnerab9cc272000-07-07 19:46:01 +0000491 return result;
492 }
493
494
David Turnerab9cc272000-07-07 19:46:01 +0000495 static
496 FT_Error FNT_Load_Glyph( FT_GlyphSlot slot,
497 FNT_Size size,
498 FT_UInt glyph_index,
499 FT_Int load_flags )
500 {
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000501 FNT_Font* font = size->font;
502 FT_Error error = 0;
503 FT_Byte* p;
504 FT_Int len;
505 FT_Bitmap* bitmap = &slot->bitmap;
506 FT_ULong offset;
507 FT_Bool new_format;
Werner Lembergb48a6092000-07-09 19:15:30 +0000508
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000509 FT_UNUSED( slot );
510 FT_UNUSED( load_flags );
511
Werner Lembergb48a6092000-07-09 19:15:30 +0000512
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000513 if ( !font )
David Turnerab9cc272000-07-07 19:46:01 +0000514 {
515 error = FT_Err_Invalid_Argument;
516 goto Exit;
517 }
518
Werner Lembergd060a752000-07-20 06:57:41 +0000519 if ( glyph_index > 0 )
David Turnerbca33282000-07-19 20:17:37 +0000520 glyph_index--;
521 else
522 glyph_index = font->header.default_char - font->header.first_char;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000523
David Turnerab9cc272000-07-07 19:46:01 +0000524 new_format = font->header.version == 0x300;
525 len = new_format ? 6 : 4;
526
Werner Lembergb48a6092000-07-09 19:15:30 +0000527 /* jump to glyph entry */
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000528 p = font->fnt_frame + 118 + len * glyph_index;
Werner Lembergb48a6092000-07-09 19:15:30 +0000529
David Turnerab9cc272000-07-07 19:46:01 +0000530 bitmap->width = NEXT_ShortLE(p);
Werner Lembergb48a6092000-07-09 19:15:30 +0000531
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000532 if ( new_format )
David Turnerab9cc272000-07-07 19:46:01 +0000533 offset = NEXT_ULongLE(p);
534 else
535 offset = NEXT_UShortLE(p);
Werner Lembergb48a6092000-07-09 19:15:30 +0000536
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000537 /* jump to glyph data */
David Turnerab9cc272000-07-07 19:46:01 +0000538 p = font->fnt_frame + /* font->header.bits_offset */ + offset;
Werner Lembergb48a6092000-07-09 19:15:30 +0000539
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000540 /* allocate and build bitmap */
David Turnerab9cc272000-07-07 19:46:01 +0000541 {
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000542 FT_Memory memory = FT_FACE_MEMORY( slot->face );
543 FT_Int pitch = ( bitmap->width + 7 ) >> 3;
544 FT_Byte* column;
545 FT_Byte* write;
Werner Lembergb48a6092000-07-09 19:15:30 +0000546
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000547
548 bitmap->pitch = pitch;
549 bitmap->rows = font->header.pixel_height;
David Turnerab9cc272000-07-07 19:46:01 +0000550 bitmap->pixel_mode = ft_pixel_mode_mono;
Werner Lembergb48a6092000-07-09 19:15:30 +0000551
David Turnerab9cc272000-07-07 19:46:01 +0000552 if ( ALLOC( bitmap->buffer, pitch * bitmap->rows ) )
553 goto Exit;
Werner Lembergb48a6092000-07-09 19:15:30 +0000554
David Turnerab9cc272000-07-07 19:46:01 +0000555 column = (FT_Byte*)bitmap->buffer;
556
557 for ( ; pitch > 0; pitch--, column++ )
558 {
559 FT_Byte* limit = p + bitmap->rows;
Werner Lembergb48a6092000-07-09 19:15:30 +0000560
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000561
David Turnerab9cc272000-07-07 19:46:01 +0000562 for ( write = column; p < limit; p++, write += bitmap->pitch )
563 write[0] = p[0];
564 }
565 }
Werner Lembergb48a6092000-07-09 19:15:30 +0000566
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000567 slot->flags = ft_glyph_own_bitmap;
568 slot->bitmap_left = 0;
569 slot->bitmap_top = font->header.ascent;
570 slot->format = ft_glyph_format_bitmap;
Werner Lembergb48a6092000-07-09 19:15:30 +0000571
David Turnerab9cc272000-07-07 19:46:01 +0000572 /* now set up metrics */
573 slot->metrics.horiAdvance = bitmap->width << 6;
574 slot->metrics.horiBearingX = 0;
575 slot->metrics.horiBearingY = slot->bitmap_top << 6;
576
577 slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16;
David Turnerd3c8e062000-12-04 22:53:55 +0000578 slot->format = ft_glyph_format_bitmap;
Werner Lembergb48a6092000-07-09 19:15:30 +0000579
David Turnerab9cc272000-07-07 19:46:01 +0000580 Exit:
581 return error;
Werner Lembergb48a6092000-07-09 19:15:30 +0000582 }
David Turnerab9cc272000-07-07 19:46:01 +0000583
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000584
David Turner76a5f622000-11-04 01:55:49 +0000585 FT_CALLBACK_TABLE_DEF
586 const FT_Driver_Class winfnt_driver_class =
David Turnerab9cc272000-07-07 19:46:01 +0000587 {
588 {
589 ft_module_font_driver,
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000590 sizeof ( FT_DriverRec ),
Werner Lembergb48a6092000-07-09 19:15:30 +0000591
David Turnerab9cc272000-07-07 19:46:01 +0000592 "winfonts",
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000593 0x10000L,
594 0x20000L,
Werner Lembergb48a6092000-07-09 19:15:30 +0000595
David Turnerab9cc272000-07-07 19:46:01 +0000596 0,
Werner Lembergb48a6092000-07-09 19:15:30 +0000597
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000598 (FT_Module_Constructor)0,
599 (FT_Module_Destructor) 0,
600 (FT_Module_Requester) 0
David Turnerab9cc272000-07-07 19:46:01 +0000601 },
Werner Lembergb48a6092000-07-09 19:15:30 +0000602
David Turnerab9cc272000-07-07 19:46:01 +0000603 sizeof( FNT_FaceRec ),
604 sizeof( FNT_SizeRec ),
605 sizeof( FT_GlyphSlotRec ),
Werner Lembergb48a6092000-07-09 19:15:30 +0000606
David Turnerab9cc272000-07-07 19:46:01 +0000607 (FTDriver_initFace) FNT_Init_Face,
608 (FTDriver_doneFace) FNT_Done_Face,
609 (FTDriver_initSize) 0,
610 (FTDriver_doneSize) 0,
611 (FTDriver_initGlyphSlot)0,
612 (FTDriver_doneGlyphSlot)0,
613
614 (FTDriver_setCharSizes) FNT_Set_Pixel_Size,
615 (FTDriver_setPixelSizes)FNT_Set_Pixel_Size,
616
617 (FTDriver_loadGlyph) FNT_Load_Glyph,
618 (FTDriver_getCharIndex) FNT_Get_Char_Index,
619
620 (FTDriver_getKerning) 0,
621 (FTDriver_attachFile) 0,
622 (FTDriver_getAdvances) 0
623 };
624
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000625
Werner Lembergab855232000-10-31 22:13:54 +0000626#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
627
628
629 /*************************************************************************/
630 /* */
631 /* <Function> */
632 /* getDriverClass */
633 /* */
634 /* <Description> */
635 /* This function is used when compiling the TrueType driver as a */
636 /* shared library (`.DLL' or `.so'). It will be used by the */
637 /* high-level library of FreeType to retrieve the address of the */
638 /* driver's generic interface. */
639 /* */
640 /* It shouldn't be implemented in a static build, as each driver must */
641 /* have the same function as an exported entry point. */
642 /* */
643 /* <Return> */
644 /* The address of the TrueType's driver generic interface. The */
645 /* format-specific interface can then be retrieved through the method */
646 /* interface->get_format_interface. */
647 /* */
David Turner76a5f622000-11-04 01:55:49 +0000648 FT_EXPORT_DEF( const FT_Driver_Class* ) getDriverClass( void )
Werner Lembergab855232000-10-31 22:13:54 +0000649 {
650 return &winfnt_driver_class;
651 }
652
653
654#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
655
656
Werner Lemberg415cc7c2000-07-08 22:52:21 +0000657/* END */