xref: /inferno-os/libfreetype/winfnt.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  winfnt.c                                                               */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    FreeType font driver for Windows FNT/FON files                       */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 1996-2001, 2002 by                                           */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth #include <ft2build.h>
20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
21*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H
22*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
23*37da2899SCharles.Forsyth #include FT_INTERNAL_FNT_TYPES_H
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth #include "winfnt.h"
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth #include "fnterrs.h"
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth   /*************************************************************************/
31*37da2899SCharles.Forsyth   /*                                                                       */
32*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
33*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
34*37da2899SCharles.Forsyth   /* messages during execution.                                            */
35*37da2899SCharles.Forsyth   /*                                                                       */
36*37da2899SCharles.Forsyth #undef  FT_COMPONENT
37*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_winfnt
38*37da2899SCharles.Forsyth 
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth   static
41*37da2899SCharles.Forsyth   const FT_Frame_Field  winmz_header_fields[] =
42*37da2899SCharles.Forsyth   {
43*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
44*37da2899SCharles.Forsyth #define FT_STRUCTURE  WinMZ_HeaderRec
45*37da2899SCharles.Forsyth 
46*37da2899SCharles.Forsyth     FT_FRAME_START( 64 ),
47*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE ( magic ),
48*37da2899SCharles.Forsyth       FT_FRAME_SKIP_BYTES( 29 * 2 ),
49*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE  ( lfanew ),
50*37da2899SCharles.Forsyth     FT_FRAME_END
51*37da2899SCharles.Forsyth   };
52*37da2899SCharles.Forsyth 
53*37da2899SCharles.Forsyth   static
54*37da2899SCharles.Forsyth   const FT_Frame_Field  winne_header_fields[] =
55*37da2899SCharles.Forsyth   {
56*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
57*37da2899SCharles.Forsyth #define FT_STRUCTURE  WinNE_HeaderRec
58*37da2899SCharles.Forsyth 
59*37da2899SCharles.Forsyth     FT_FRAME_START( 40 ),
60*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE ( magic ),
61*37da2899SCharles.Forsyth       FT_FRAME_SKIP_BYTES( 34 ),
62*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE ( resource_tab_offset ),
63*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE ( rname_tab_offset ),
64*37da2899SCharles.Forsyth     FT_FRAME_END
65*37da2899SCharles.Forsyth   };
66*37da2899SCharles.Forsyth 
67*37da2899SCharles.Forsyth   static
68*37da2899SCharles.Forsyth   const FT_Frame_Field  winfnt_header_fields[] =
69*37da2899SCharles.Forsyth   {
70*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
71*37da2899SCharles.Forsyth #define FT_STRUCTURE  WinFNT_HeaderRec
72*37da2899SCharles.Forsyth 
73*37da2899SCharles.Forsyth     FT_FRAME_START( 134 ),
74*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( version ),
75*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE ( file_size ),
76*37da2899SCharles.Forsyth       FT_FRAME_BYTES    ( copyright, 60 ),
77*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( file_type ),
78*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( nominal_point_size ),
79*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( vertical_resolution ),
80*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( horizontal_resolution ),
81*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( ascent ),
82*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( internal_leading ),
83*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( external_leading ),
84*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( italic ),
85*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( underline ),
86*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( strike_out ),
87*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( weight ),
88*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( charset ),
89*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( pixel_width ),
90*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( pixel_height ),
91*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( pitch_and_family ),
92*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( avg_width ),
93*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( max_width ),
94*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( first_char ),
95*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( last_char ),
96*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( default_char ),
97*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( break_char ),
98*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( bytes_per_row ),
99*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE ( device_offset ),
100*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE ( face_name_offset ),
101*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE ( bits_pointer ),
102*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE ( bits_offset ),
103*37da2899SCharles.Forsyth       FT_FRAME_BYTE     ( reserved ),
104*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE ( flags ),
105*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( A_space ),
106*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( B_space ),
107*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( C_space ),
108*37da2899SCharles.Forsyth       FT_FRAME_USHORT_LE( color_table_offset ),
109*37da2899SCharles.Forsyth       FT_FRAME_BYTES    ( reserved, 4 ),
110*37da2899SCharles.Forsyth     FT_FRAME_END
111*37da2899SCharles.Forsyth   };
112*37da2899SCharles.Forsyth 
113*37da2899SCharles.Forsyth 
114*37da2899SCharles.Forsyth   static void
fnt_font_done(FNT_Font font,FT_Stream stream)115*37da2899SCharles.Forsyth   fnt_font_done( FNT_Font   font,
116*37da2899SCharles.Forsyth                  FT_Stream  stream )
117*37da2899SCharles.Forsyth   {
118*37da2899SCharles.Forsyth     if ( font->fnt_frame )
119*37da2899SCharles.Forsyth       FT_FRAME_RELEASE( font->fnt_frame );
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth     font->fnt_size  = 0;
122*37da2899SCharles.Forsyth     font->fnt_frame = 0;
123*37da2899SCharles.Forsyth   }
124*37da2899SCharles.Forsyth 
125*37da2899SCharles.Forsyth 
126*37da2899SCharles.Forsyth   static FT_Error
fnt_font_load(FNT_Font font,FT_Stream stream)127*37da2899SCharles.Forsyth   fnt_font_load( FNT_Font   font,
128*37da2899SCharles.Forsyth                  FT_Stream  stream )
129*37da2899SCharles.Forsyth   {
130*37da2899SCharles.Forsyth     FT_Error       error;
131*37da2899SCharles.Forsyth     WinFNT_Header  header = &font->header;
132*37da2899SCharles.Forsyth 
133*37da2899SCharles.Forsyth 
134*37da2899SCharles.Forsyth     /* first of all, read the FNT header */
135*37da2899SCharles.Forsyth     if ( FT_STREAM_SEEK( font->offset )                   ||
136*37da2899SCharles.Forsyth          FT_STREAM_READ_FIELDS( winfnt_header_fields, header ) )
137*37da2899SCharles.Forsyth       goto Exit;
138*37da2899SCharles.Forsyth 
139*37da2899SCharles.Forsyth     /* check header */
140*37da2899SCharles.Forsyth     if ( header->version != 0x200 &&
141*37da2899SCharles.Forsyth          header->version != 0x300 )
142*37da2899SCharles.Forsyth     {
143*37da2899SCharles.Forsyth       FT_TRACE2(( "[not a valid FNT file]\n" ));
144*37da2899SCharles.Forsyth       error = FNT_Err_Unknown_File_Format;
145*37da2899SCharles.Forsyth       goto Exit;
146*37da2899SCharles.Forsyth     }
147*37da2899SCharles.Forsyth 
148*37da2899SCharles.Forsyth     if ( header->file_type & 1 )
149*37da2899SCharles.Forsyth     {
150*37da2899SCharles.Forsyth       FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));
151*37da2899SCharles.Forsyth       error = FNT_Err_Unknown_File_Format;
152*37da2899SCharles.Forsyth       goto Exit;
153*37da2899SCharles.Forsyth     }
154*37da2899SCharles.Forsyth 
155*37da2899SCharles.Forsyth     /* small fixup -- some fonts have the `pixel_width' field set to 0 */
156*37da2899SCharles.Forsyth     if ( header->pixel_width == 0 )
157*37da2899SCharles.Forsyth       header->pixel_width = header->pixel_height;
158*37da2899SCharles.Forsyth 
159*37da2899SCharles.Forsyth     /* this is a FNT file/table, we now extract its frame */
160*37da2899SCharles.Forsyth     if ( FT_STREAM_SEEK( font->offset )                         ||
161*37da2899SCharles.Forsyth          FT_FRAME_EXTRACT( header->file_size, font->fnt_frame ) )
162*37da2899SCharles.Forsyth       goto Exit;
163*37da2899SCharles.Forsyth 
164*37da2899SCharles.Forsyth   Exit:
165*37da2899SCharles.Forsyth     return error;
166*37da2899SCharles.Forsyth   }
167*37da2899SCharles.Forsyth 
168*37da2899SCharles.Forsyth 
169*37da2899SCharles.Forsyth   static void
fnt_face_done_fonts(FNT_Face face)170*37da2899SCharles.Forsyth   fnt_face_done_fonts( FNT_Face  face )
171*37da2899SCharles.Forsyth   {
172*37da2899SCharles.Forsyth     FT_Memory  memory = FT_FACE( face )->memory;
173*37da2899SCharles.Forsyth     FT_Stream  stream = FT_FACE( face )->stream;
174*37da2899SCharles.Forsyth     FNT_Font   cur    = face->fonts;
175*37da2899SCharles.Forsyth     FNT_Font   limit  = cur + face->num_fonts;
176*37da2899SCharles.Forsyth 
177*37da2899SCharles.Forsyth 
178*37da2899SCharles.Forsyth     for ( ; cur < limit; cur++ )
179*37da2899SCharles.Forsyth       fnt_font_done( cur, stream );
180*37da2899SCharles.Forsyth 
181*37da2899SCharles.Forsyth     FT_FREE( face->fonts );
182*37da2899SCharles.Forsyth     face->num_fonts = 0;
183*37da2899SCharles.Forsyth   }
184*37da2899SCharles.Forsyth 
185*37da2899SCharles.Forsyth 
186*37da2899SCharles.Forsyth   static FT_Error
fnt_face_get_dll_fonts(FNT_Face face)187*37da2899SCharles.Forsyth   fnt_face_get_dll_fonts( FNT_Face  face )
188*37da2899SCharles.Forsyth   {
189*37da2899SCharles.Forsyth     FT_Error         error;
190*37da2899SCharles.Forsyth     FT_Stream        stream = FT_FACE( face )->stream;
191*37da2899SCharles.Forsyth     FT_Memory        memory = FT_FACE( face )->memory;
192*37da2899SCharles.Forsyth     WinMZ_HeaderRec  mz_header;
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth 
195*37da2899SCharles.Forsyth     face->fonts     = 0;
196*37da2899SCharles.Forsyth     face->num_fonts = 0;
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth     /* does it begin with a MZ header? */
199*37da2899SCharles.Forsyth     if ( FT_STREAM_SEEK( 0 )                                 ||
200*37da2899SCharles.Forsyth          FT_STREAM_READ_FIELDS( winmz_header_fields, &mz_header ) )
201*37da2899SCharles.Forsyth       goto Exit;
202*37da2899SCharles.Forsyth 
203*37da2899SCharles.Forsyth     error = FNT_Err_Unknown_File_Format;
204*37da2899SCharles.Forsyth     if ( mz_header.magic == WINFNT_MZ_MAGIC )
205*37da2899SCharles.Forsyth     {
206*37da2899SCharles.Forsyth       /* yes, now look for a NE header in the file */
207*37da2899SCharles.Forsyth       WinNE_HeaderRec  ne_header;
208*37da2899SCharles.Forsyth 
209*37da2899SCharles.Forsyth 
210*37da2899SCharles.Forsyth       if ( FT_STREAM_SEEK( mz_header.lfanew )                  ||
211*37da2899SCharles.Forsyth            FT_STREAM_READ_FIELDS( winne_header_fields, &ne_header ) )
212*37da2899SCharles.Forsyth         goto Exit;
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth       error = FNT_Err_Unknown_File_Format;
215*37da2899SCharles.Forsyth       if ( ne_header.magic == WINFNT_NE_MAGIC )
216*37da2899SCharles.Forsyth       {
217*37da2899SCharles.Forsyth         /* good, now look in the resource table for each FNT resource */
218*37da2899SCharles.Forsyth         FT_ULong   res_offset = mz_header.lfanew +
219*37da2899SCharles.Forsyth                                 ne_header.resource_tab_offset;
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth         FT_UShort  size_shift;
222*37da2899SCharles.Forsyth         FT_UShort  font_count  = 0;
223*37da2899SCharles.Forsyth         FT_ULong   font_offset = 0;
224*37da2899SCharles.Forsyth 
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth         if ( FT_STREAM_SEEK( res_offset ) ||
227*37da2899SCharles.Forsyth              FT_FRAME_ENTER( ne_header.rname_tab_offset -
228*37da2899SCharles.Forsyth                              ne_header.resource_tab_offset ) )
229*37da2899SCharles.Forsyth           goto Exit;
230*37da2899SCharles.Forsyth 
231*37da2899SCharles.Forsyth         size_shift = FT_GET_USHORT_LE();
232*37da2899SCharles.Forsyth 
233*37da2899SCharles.Forsyth         for (;;)
234*37da2899SCharles.Forsyth         {
235*37da2899SCharles.Forsyth           FT_UShort  type_id, count;
236*37da2899SCharles.Forsyth 
237*37da2899SCharles.Forsyth 
238*37da2899SCharles.Forsyth           type_id = FT_GET_USHORT_LE();
239*37da2899SCharles.Forsyth           if ( !type_id )
240*37da2899SCharles.Forsyth             break;
241*37da2899SCharles.Forsyth 
242*37da2899SCharles.Forsyth           count = FT_GET_USHORT_LE();
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth           if ( type_id == 0x8008 )
245*37da2899SCharles.Forsyth           {
246*37da2899SCharles.Forsyth             font_count  = count;
247*37da2899SCharles.Forsyth             font_offset = (FT_ULong)( FT_STREAM_POS() + 4 +
248*37da2899SCharles.Forsyth                                       ( stream->cursor - stream->limit ) );
249*37da2899SCharles.Forsyth             break;
250*37da2899SCharles.Forsyth           }
251*37da2899SCharles.Forsyth 
252*37da2899SCharles.Forsyth           stream->cursor += 4 + count * 12;
253*37da2899SCharles.Forsyth         }
254*37da2899SCharles.Forsyth         FT_FRAME_EXIT();
255*37da2899SCharles.Forsyth 
256*37da2899SCharles.Forsyth         if ( !font_count || !font_offset )
257*37da2899SCharles.Forsyth         {
258*37da2899SCharles.Forsyth           FT_TRACE2(( "this file doesn't contain any FNT resources!\n" ));
259*37da2899SCharles.Forsyth           error = FNT_Err_Unknown_File_Format;
260*37da2899SCharles.Forsyth           goto Exit;
261*37da2899SCharles.Forsyth         }
262*37da2899SCharles.Forsyth 
263*37da2899SCharles.Forsyth         if ( FT_STREAM_SEEK( font_offset )           ||
264*37da2899SCharles.Forsyth              FT_NEW_ARRAY( face->fonts, font_count ) )
265*37da2899SCharles.Forsyth           goto Exit;
266*37da2899SCharles.Forsyth 
267*37da2899SCharles.Forsyth         face->num_fonts = font_count;
268*37da2899SCharles.Forsyth 
269*37da2899SCharles.Forsyth         if ( FT_FRAME_ENTER( (FT_Long)font_count * 12 ) )
270*37da2899SCharles.Forsyth           goto Exit;
271*37da2899SCharles.Forsyth 
272*37da2899SCharles.Forsyth         /* now read the offset and position of each FNT font */
273*37da2899SCharles.Forsyth         {
274*37da2899SCharles.Forsyth           FNT_Font  cur   = face->fonts;
275*37da2899SCharles.Forsyth           FNT_Font  limit = cur + font_count;
276*37da2899SCharles.Forsyth 
277*37da2899SCharles.Forsyth 
278*37da2899SCharles.Forsyth           for ( ; cur < limit; cur++ )
279*37da2899SCharles.Forsyth           {
280*37da2899SCharles.Forsyth             cur->offset     = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
281*37da2899SCharles.Forsyth             cur->fnt_size   = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
282*37da2899SCharles.Forsyth             cur->size_shift = size_shift;
283*37da2899SCharles.Forsyth             stream->cursor += 8;
284*37da2899SCharles.Forsyth           }
285*37da2899SCharles.Forsyth         }
286*37da2899SCharles.Forsyth         FT_FRAME_EXIT();
287*37da2899SCharles.Forsyth 
288*37da2899SCharles.Forsyth         /* finally, try to load each font there */
289*37da2899SCharles.Forsyth         {
290*37da2899SCharles.Forsyth           FNT_Font  cur   = face->fonts;
291*37da2899SCharles.Forsyth           FNT_Font  limit = cur + font_count;
292*37da2899SCharles.Forsyth 
293*37da2899SCharles.Forsyth 
294*37da2899SCharles.Forsyth           for ( ; cur < limit; cur++ )
295*37da2899SCharles.Forsyth           {
296*37da2899SCharles.Forsyth             error = fnt_font_load( cur, stream );
297*37da2899SCharles.Forsyth             if ( error )
298*37da2899SCharles.Forsyth               goto Fail;
299*37da2899SCharles.Forsyth           }
300*37da2899SCharles.Forsyth         }
301*37da2899SCharles.Forsyth       }
302*37da2899SCharles.Forsyth     }
303*37da2899SCharles.Forsyth 
304*37da2899SCharles.Forsyth   Fail:
305*37da2899SCharles.Forsyth     if ( error )
306*37da2899SCharles.Forsyth       fnt_face_done_fonts( face );
307*37da2899SCharles.Forsyth 
308*37da2899SCharles.Forsyth   Exit:
309*37da2899SCharles.Forsyth     return error;
310*37da2899SCharles.Forsyth   }
311*37da2899SCharles.Forsyth 
312*37da2899SCharles.Forsyth 
313*37da2899SCharles.Forsyth 
314*37da2899SCharles.Forsyth   typedef struct  FNT_CMapRec_
315*37da2899SCharles.Forsyth   {
316*37da2899SCharles.Forsyth     FT_CMapRec  cmap;
317*37da2899SCharles.Forsyth     FT_UInt32   first;
318*37da2899SCharles.Forsyth     FT_UInt32   count;
319*37da2899SCharles.Forsyth 
320*37da2899SCharles.Forsyth   } FNT_CMapRec, *FNT_CMap;
321*37da2899SCharles.Forsyth 
322*37da2899SCharles.Forsyth 
323*37da2899SCharles.Forsyth   static FT_Error
fnt_cmap_init(FNT_CMap cmap)324*37da2899SCharles.Forsyth   fnt_cmap_init( FNT_CMap  cmap )
325*37da2899SCharles.Forsyth   {
326*37da2899SCharles.Forsyth     FNT_Face  face = (FNT_Face)FT_CMAP_FACE( cmap );
327*37da2899SCharles.Forsyth     FNT_Font  font = face->fonts;
328*37da2899SCharles.Forsyth 
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth     cmap->first = (FT_UInt32)  font->header.first_char;
331*37da2899SCharles.Forsyth     cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 );
332*37da2899SCharles.Forsyth 
333*37da2899SCharles.Forsyth     return 0;
334*37da2899SCharles.Forsyth   }
335*37da2899SCharles.Forsyth 
336*37da2899SCharles.Forsyth 
337*37da2899SCharles.Forsyth   static FT_UInt
fnt_cmap_char_index(FNT_CMap cmap,FT_UInt32 char_code)338*37da2899SCharles.Forsyth   fnt_cmap_char_index( FNT_CMap   cmap,
339*37da2899SCharles.Forsyth                        FT_UInt32  char_code )
340*37da2899SCharles.Forsyth   {
341*37da2899SCharles.Forsyth     FT_UInt  gindex = 0;
342*37da2899SCharles.Forsyth 
343*37da2899SCharles.Forsyth 
344*37da2899SCharles.Forsyth     char_code -= cmap->first;
345*37da2899SCharles.Forsyth     if ( char_code < cmap->count )
346*37da2899SCharles.Forsyth       gindex = char_code + 1;
347*37da2899SCharles.Forsyth 
348*37da2899SCharles.Forsyth     return gindex;
349*37da2899SCharles.Forsyth   }
350*37da2899SCharles.Forsyth 
351*37da2899SCharles.Forsyth 
352*37da2899SCharles.Forsyth   static FT_UInt
fnt_cmap_char_next(FNT_CMap cmap,FT_UInt32 * pchar_code)353*37da2899SCharles.Forsyth   fnt_cmap_char_next( FNT_CMap    cmap,
354*37da2899SCharles.Forsyth                       FT_UInt32  *pchar_code )
355*37da2899SCharles.Forsyth   {
356*37da2899SCharles.Forsyth     FT_UInt    gindex = 0;
357*37da2899SCharles.Forsyth     FT_UInt32  result = 0;
358*37da2899SCharles.Forsyth     FT_UInt32  char_code = *pchar_code + 1;
359*37da2899SCharles.Forsyth 
360*37da2899SCharles.Forsyth 
361*37da2899SCharles.Forsyth     if ( char_code <= cmap->first )
362*37da2899SCharles.Forsyth     {
363*37da2899SCharles.Forsyth       result = cmap->first;
364*37da2899SCharles.Forsyth       gindex = 1;
365*37da2899SCharles.Forsyth     }
366*37da2899SCharles.Forsyth     else
367*37da2899SCharles.Forsyth     {
368*37da2899SCharles.Forsyth       char_code -= cmap->first;
369*37da2899SCharles.Forsyth       if ( char_code < cmap->count )
370*37da2899SCharles.Forsyth       {
371*37da2899SCharles.Forsyth         result = cmap->first + char_code;
372*37da2899SCharles.Forsyth         gindex = char_code + 1;
373*37da2899SCharles.Forsyth       }
374*37da2899SCharles.Forsyth     }
375*37da2899SCharles.Forsyth 
376*37da2899SCharles.Forsyth     *pchar_code = result;
377*37da2899SCharles.Forsyth     return gindex;
378*37da2899SCharles.Forsyth   }
379*37da2899SCharles.Forsyth 
380*37da2899SCharles.Forsyth 
381*37da2899SCharles.Forsyth   static FT_CMap_ClassRec  fnt_cmap_class_rec =
382*37da2899SCharles.Forsyth   {
383*37da2899SCharles.Forsyth     sizeof ( FNT_CMapRec ),
384*37da2899SCharles.Forsyth 
385*37da2899SCharles.Forsyth     (FT_CMap_InitFunc)     fnt_cmap_init,
386*37da2899SCharles.Forsyth     (FT_CMap_DoneFunc)     NULL,
387*37da2899SCharles.Forsyth     (FT_CMap_CharIndexFunc)fnt_cmap_char_index,
388*37da2899SCharles.Forsyth     (FT_CMap_CharNextFunc) fnt_cmap_char_next
389*37da2899SCharles.Forsyth   };
390*37da2899SCharles.Forsyth 
391*37da2899SCharles.Forsyth   static FT_CMap_Class  fnt_cmap_class = &fnt_cmap_class_rec;
392*37da2899SCharles.Forsyth 
393*37da2899SCharles.Forsyth 
394*37da2899SCharles.Forsyth 
395*37da2899SCharles.Forsyth   static void
FNT_Face_Done(FNT_Face face)396*37da2899SCharles.Forsyth   FNT_Face_Done( FNT_Face  face )
397*37da2899SCharles.Forsyth   {
398*37da2899SCharles.Forsyth     FT_Memory  memory = FT_FACE_MEMORY( face );
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth 
401*37da2899SCharles.Forsyth     fnt_face_done_fonts( face );
402*37da2899SCharles.Forsyth 
403*37da2899SCharles.Forsyth     FT_FREE( face->root.available_sizes );
404*37da2899SCharles.Forsyth     face->root.num_fixed_sizes = 0;
405*37da2899SCharles.Forsyth   }
406*37da2899SCharles.Forsyth 
407*37da2899SCharles.Forsyth 
408*37da2899SCharles.Forsyth   static FT_Error
FNT_Face_Init(FT_Stream stream,FNT_Face face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)409*37da2899SCharles.Forsyth   FNT_Face_Init( FT_Stream      stream,
410*37da2899SCharles.Forsyth                  FNT_Face       face,
411*37da2899SCharles.Forsyth                  FT_Int         face_index,
412*37da2899SCharles.Forsyth                  FT_Int         num_params,
413*37da2899SCharles.Forsyth                  FT_Parameter*  params )
414*37da2899SCharles.Forsyth   {
415*37da2899SCharles.Forsyth     FT_Error   error;
416*37da2899SCharles.Forsyth     FT_Memory  memory = FT_FACE_MEMORY( face );
417*37da2899SCharles.Forsyth 
418*37da2899SCharles.Forsyth     FT_UNUSED( num_params );
419*37da2899SCharles.Forsyth     FT_UNUSED( params );
420*37da2899SCharles.Forsyth     FT_UNUSED( face_index );
421*37da2899SCharles.Forsyth 
422*37da2899SCharles.Forsyth 
423*37da2899SCharles.Forsyth     /* try to load several fonts from a DLL */
424*37da2899SCharles.Forsyth     error = fnt_face_get_dll_fonts( face );
425*37da2899SCharles.Forsyth     if ( error )
426*37da2899SCharles.Forsyth     {
427*37da2899SCharles.Forsyth       /* this didn't work, now try to load a single FNT font */
428*37da2899SCharles.Forsyth       FNT_Font  font;
429*37da2899SCharles.Forsyth 
430*37da2899SCharles.Forsyth 
431*37da2899SCharles.Forsyth       if ( FT_NEW( face->fonts ) )
432*37da2899SCharles.Forsyth         goto Exit;
433*37da2899SCharles.Forsyth 
434*37da2899SCharles.Forsyth       face->num_fonts = 1;
435*37da2899SCharles.Forsyth       font            = face->fonts;
436*37da2899SCharles.Forsyth 
437*37da2899SCharles.Forsyth       font->offset   = 0;
438*37da2899SCharles.Forsyth       font->fnt_size = stream->size;
439*37da2899SCharles.Forsyth 
440*37da2899SCharles.Forsyth       error = fnt_font_load( font, stream );
441*37da2899SCharles.Forsyth       if ( error )
442*37da2899SCharles.Forsyth         goto Fail;
443*37da2899SCharles.Forsyth     }
444*37da2899SCharles.Forsyth 
445*37da2899SCharles.Forsyth     /* all right, one or more fonts were loaded; we now need to */
446*37da2899SCharles.Forsyth     /* fill the root FT_Face fields with relevant information   */
447*37da2899SCharles.Forsyth     {
448*37da2899SCharles.Forsyth       FT_Face   root  = FT_FACE( face );
449*37da2899SCharles.Forsyth       FNT_Font  fonts = face->fonts;
450*37da2899SCharles.Forsyth       FNT_Font  limit = fonts + face->num_fonts;
451*37da2899SCharles.Forsyth       FNT_Font  cur;
452*37da2899SCharles.Forsyth 
453*37da2899SCharles.Forsyth 
454*37da2899SCharles.Forsyth       root->num_faces  = 1;
455*37da2899SCharles.Forsyth       root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
456*37da2899SCharles.Forsyth                          FT_FACE_FLAG_HORIZONTAL;
457*37da2899SCharles.Forsyth 
458*37da2899SCharles.Forsyth       if ( fonts->header.avg_width == fonts->header.max_width )
459*37da2899SCharles.Forsyth         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
460*37da2899SCharles.Forsyth 
461*37da2899SCharles.Forsyth       if ( fonts->header.italic )
462*37da2899SCharles.Forsyth         root->style_flags |= FT_STYLE_FLAG_ITALIC;
463*37da2899SCharles.Forsyth 
464*37da2899SCharles.Forsyth       if ( fonts->header.weight >= 800 )
465*37da2899SCharles.Forsyth         root->style_flags |= FT_STYLE_FLAG_BOLD;
466*37da2899SCharles.Forsyth 
467*37da2899SCharles.Forsyth       /* Setup the `fixed_sizes' array */
468*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( root->available_sizes, face->num_fonts ) )
469*37da2899SCharles.Forsyth         goto Fail;
470*37da2899SCharles.Forsyth 
471*37da2899SCharles.Forsyth       root->num_fixed_sizes = face->num_fonts;
472*37da2899SCharles.Forsyth 
473*37da2899SCharles.Forsyth       {
474*37da2899SCharles.Forsyth         FT_Bitmap_Size*  size = root->available_sizes;
475*37da2899SCharles.Forsyth 
476*37da2899SCharles.Forsyth 
477*37da2899SCharles.Forsyth         for ( cur = fonts; cur < limit; cur++, size++ )
478*37da2899SCharles.Forsyth         {
479*37da2899SCharles.Forsyth           size->width  = cur->header.pixel_width;
480*37da2899SCharles.Forsyth           size->height = cur->header.pixel_height;
481*37da2899SCharles.Forsyth         }
482*37da2899SCharles.Forsyth       }
483*37da2899SCharles.Forsyth 
484*37da2899SCharles.Forsyth       {
485*37da2899SCharles.Forsyth         FT_CharMapRec  charmap;
486*37da2899SCharles.Forsyth 
487*37da2899SCharles.Forsyth         charmap.encoding    = FT_ENCODING_UNICODE;
488*37da2899SCharles.Forsyth         charmap.platform_id = 3;
489*37da2899SCharles.Forsyth         charmap.encoding_id = 1;
490*37da2899SCharles.Forsyth         charmap.face        = root;
491*37da2899SCharles.Forsyth 
492*37da2899SCharles.Forsyth         error = FT_CMap_New( fnt_cmap_class,
493*37da2899SCharles.Forsyth                              NULL,
494*37da2899SCharles.Forsyth                              &charmap,
495*37da2899SCharles.Forsyth                              NULL );
496*37da2899SCharles.Forsyth         if ( error )
497*37da2899SCharles.Forsyth           goto Fail;
498*37da2899SCharles.Forsyth 
499*37da2899SCharles.Forsyth         /* Select default charmap */
500*37da2899SCharles.Forsyth         if ( root->num_charmaps )
501*37da2899SCharles.Forsyth           root->charmap = root->charmaps[0];
502*37da2899SCharles.Forsyth       }
503*37da2899SCharles.Forsyth 
504*37da2899SCharles.Forsyth       /* setup remaining flags */
505*37da2899SCharles.Forsyth       root->num_glyphs = fonts->header.last_char -
506*37da2899SCharles.Forsyth                          fonts->header.first_char + 1;
507*37da2899SCharles.Forsyth 
508*37da2899SCharles.Forsyth       root->family_name = (FT_String*)fonts->fnt_frame +
509*37da2899SCharles.Forsyth                           fonts->header.face_name_offset;
510*37da2899SCharles.Forsyth       root->style_name  = (char *)"Regular";
511*37da2899SCharles.Forsyth 
512*37da2899SCharles.Forsyth       if ( root->style_flags & FT_STYLE_FLAG_BOLD )
513*37da2899SCharles.Forsyth       {
514*37da2899SCharles.Forsyth         if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
515*37da2899SCharles.Forsyth           root->style_name = (char *)"Bold Italic";
516*37da2899SCharles.Forsyth         else
517*37da2899SCharles.Forsyth           root->style_name = (char *)"Bold";
518*37da2899SCharles.Forsyth       }
519*37da2899SCharles.Forsyth       else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
520*37da2899SCharles.Forsyth         root->style_name = (char *)"Italic";
521*37da2899SCharles.Forsyth     }
522*37da2899SCharles.Forsyth 
523*37da2899SCharles.Forsyth   Fail:
524*37da2899SCharles.Forsyth     if ( error )
525*37da2899SCharles.Forsyth       FNT_Face_Done( face );
526*37da2899SCharles.Forsyth 
527*37da2899SCharles.Forsyth   Exit:
528*37da2899SCharles.Forsyth     return error;
529*37da2899SCharles.Forsyth   }
530*37da2899SCharles.Forsyth 
531*37da2899SCharles.Forsyth 
532*37da2899SCharles.Forsyth   static FT_Error
FNT_Size_Set_Pixels(FNT_Size size)533*37da2899SCharles.Forsyth   FNT_Size_Set_Pixels( FNT_Size  size )
534*37da2899SCharles.Forsyth   {
535*37da2899SCharles.Forsyth     /* look up a font corresponding to the current pixel size */
536*37da2899SCharles.Forsyth     FNT_Face  face  = (FNT_Face)FT_SIZE_FACE( size );
537*37da2899SCharles.Forsyth     FNT_Font  cur   = face->fonts;
538*37da2899SCharles.Forsyth     FNT_Font  limit = cur + face->num_fonts;
539*37da2899SCharles.Forsyth 
540*37da2899SCharles.Forsyth 
541*37da2899SCharles.Forsyth     size->font = 0;
542*37da2899SCharles.Forsyth     for ( ; cur < limit; cur++ )
543*37da2899SCharles.Forsyth     {
544*37da2899SCharles.Forsyth       /* we only compare the character height, as fonts used some strange */
545*37da2899SCharles.Forsyth       /* values                                                           */
546*37da2899SCharles.Forsyth       if ( cur->header.pixel_height == size->root.metrics.y_ppem )
547*37da2899SCharles.Forsyth       {
548*37da2899SCharles.Forsyth         size->font = cur;
549*37da2899SCharles.Forsyth 
550*37da2899SCharles.Forsyth         size->root.metrics.ascender  = cur->header.ascent * 64;
551*37da2899SCharles.Forsyth         size->root.metrics.descender = ( cur->header.pixel_height -
552*37da2899SCharles.Forsyth                                            cur->header.ascent ) * 64;
553*37da2899SCharles.Forsyth         size->root.metrics.height    = cur->header.pixel_height * 64;
554*37da2899SCharles.Forsyth         break;
555*37da2899SCharles.Forsyth       }
556*37da2899SCharles.Forsyth     }
557*37da2899SCharles.Forsyth 
558*37da2899SCharles.Forsyth     return ( size->font ? FNT_Err_Ok : FNT_Err_Invalid_Pixel_Size );
559*37da2899SCharles.Forsyth   }
560*37da2899SCharles.Forsyth 
561*37da2899SCharles.Forsyth 
562*37da2899SCharles.Forsyth   static FT_Error
FNT_Load_Glyph(FT_GlyphSlot slot,FNT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)563*37da2899SCharles.Forsyth   FNT_Load_Glyph( FT_GlyphSlot  slot,
564*37da2899SCharles.Forsyth                   FNT_Size      size,
565*37da2899SCharles.Forsyth                   FT_UInt       glyph_index,
566*37da2899SCharles.Forsyth                   FT_Int32      load_flags )
567*37da2899SCharles.Forsyth   {
568*37da2899SCharles.Forsyth     FNT_Font    font  = size->font;
569*37da2899SCharles.Forsyth     FT_Error    error = 0;
570*37da2899SCharles.Forsyth     FT_Byte*    p;
571*37da2899SCharles.Forsyth     FT_Int      len;
572*37da2899SCharles.Forsyth     FT_Bitmap*  bitmap = &slot->bitmap;
573*37da2899SCharles.Forsyth     FT_ULong    offset;
574*37da2899SCharles.Forsyth     FT_Bool     new_format;
575*37da2899SCharles.Forsyth 
576*37da2899SCharles.Forsyth     FT_UNUSED( slot );
577*37da2899SCharles.Forsyth     FT_UNUSED( load_flags );
578*37da2899SCharles.Forsyth 
579*37da2899SCharles.Forsyth 
580*37da2899SCharles.Forsyth     if ( !font )
581*37da2899SCharles.Forsyth     {
582*37da2899SCharles.Forsyth       error = FNT_Err_Invalid_Argument;
583*37da2899SCharles.Forsyth       goto Exit;
584*37da2899SCharles.Forsyth     }
585*37da2899SCharles.Forsyth 
586*37da2899SCharles.Forsyth     if ( glyph_index > 0 )
587*37da2899SCharles.Forsyth       glyph_index--;
588*37da2899SCharles.Forsyth     else
589*37da2899SCharles.Forsyth       glyph_index = font->header.default_char - font->header.first_char;
590*37da2899SCharles.Forsyth 
591*37da2899SCharles.Forsyth     new_format = FT_BOOL( font->header.version == 0x300 );
592*37da2899SCharles.Forsyth     len        = new_format ? 6 : 4;
593*37da2899SCharles.Forsyth 
594*37da2899SCharles.Forsyth     /* jump to glyph entry */
595*37da2899SCharles.Forsyth     p = font->fnt_frame + 118 + len * glyph_index;
596*37da2899SCharles.Forsyth 
597*37da2899SCharles.Forsyth     bitmap->width = FT_NEXT_SHORT_LE( p );
598*37da2899SCharles.Forsyth 
599*37da2899SCharles.Forsyth     if ( new_format )
600*37da2899SCharles.Forsyth       offset = FT_NEXT_ULONG_LE( p );
601*37da2899SCharles.Forsyth     else
602*37da2899SCharles.Forsyth       offset = FT_NEXT_USHORT_LE( p );
603*37da2899SCharles.Forsyth 
604*37da2899SCharles.Forsyth     /* jump to glyph data */
605*37da2899SCharles.Forsyth     p = font->fnt_frame + /* font->header.bits_offset */ + offset;
606*37da2899SCharles.Forsyth 
607*37da2899SCharles.Forsyth     /* allocate and build bitmap */
608*37da2899SCharles.Forsyth     {
609*37da2899SCharles.Forsyth       FT_Memory  memory = FT_FACE_MEMORY( slot->face );
610*37da2899SCharles.Forsyth       FT_Int     pitch  = ( bitmap->width + 7 ) >> 3;
611*37da2899SCharles.Forsyth       FT_Byte*   column;
612*37da2899SCharles.Forsyth       FT_Byte*   write;
613*37da2899SCharles.Forsyth 
614*37da2899SCharles.Forsyth 
615*37da2899SCharles.Forsyth       bitmap->pitch      = pitch;
616*37da2899SCharles.Forsyth       bitmap->rows       = font->header.pixel_height;
617*37da2899SCharles.Forsyth       bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
618*37da2899SCharles.Forsyth 
619*37da2899SCharles.Forsyth       if ( FT_ALLOC( bitmap->buffer, pitch * bitmap->rows ) )
620*37da2899SCharles.Forsyth         goto Exit;
621*37da2899SCharles.Forsyth 
622*37da2899SCharles.Forsyth       column = (FT_Byte*)bitmap->buffer;
623*37da2899SCharles.Forsyth 
624*37da2899SCharles.Forsyth       for ( ; pitch > 0; pitch--, column++ )
625*37da2899SCharles.Forsyth       {
626*37da2899SCharles.Forsyth         FT_Byte*  limit = p + bitmap->rows;
627*37da2899SCharles.Forsyth 
628*37da2899SCharles.Forsyth 
629*37da2899SCharles.Forsyth         for ( write = column; p < limit; p++, write += bitmap->pitch )
630*37da2899SCharles.Forsyth           write[0] = p[0];
631*37da2899SCharles.Forsyth       }
632*37da2899SCharles.Forsyth     }
633*37da2899SCharles.Forsyth 
634*37da2899SCharles.Forsyth     slot->flags       = FT_GLYPH_OWN_BITMAP;
635*37da2899SCharles.Forsyth     slot->bitmap_left = 0;
636*37da2899SCharles.Forsyth     slot->bitmap_top  = font->header.ascent;
637*37da2899SCharles.Forsyth     slot->format      = FT_GLYPH_FORMAT_BITMAP;
638*37da2899SCharles.Forsyth 
639*37da2899SCharles.Forsyth     /* now set up metrics */
640*37da2899SCharles.Forsyth     slot->metrics.horiAdvance  = bitmap->width << 6;
641*37da2899SCharles.Forsyth     slot->metrics.horiBearingX = 0;
642*37da2899SCharles.Forsyth     slot->metrics.horiBearingY = slot->bitmap_top << 6;
643*37da2899SCharles.Forsyth 
644*37da2899SCharles.Forsyth     slot->linearHoriAdvance    = (FT_Fixed)bitmap->width << 16;
645*37da2899SCharles.Forsyth     slot->format               = FT_GLYPH_FORMAT_BITMAP;
646*37da2899SCharles.Forsyth 
647*37da2899SCharles.Forsyth   Exit:
648*37da2899SCharles.Forsyth     return error;
649*37da2899SCharles.Forsyth   }
650*37da2899SCharles.Forsyth 
651*37da2899SCharles.Forsyth 
652*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
653*37da2899SCharles.Forsyth   const FT_Driver_ClassRec  winfnt_driver_class =
654*37da2899SCharles.Forsyth   {
655*37da2899SCharles.Forsyth     {
656*37da2899SCharles.Forsyth       ft_module_font_driver,
657*37da2899SCharles.Forsyth       sizeof ( FT_DriverRec ),
658*37da2899SCharles.Forsyth 
659*37da2899SCharles.Forsyth       "winfonts",
660*37da2899SCharles.Forsyth       0x10000L,
661*37da2899SCharles.Forsyth       0x20000L,
662*37da2899SCharles.Forsyth 
663*37da2899SCharles.Forsyth       0,
664*37da2899SCharles.Forsyth 
665*37da2899SCharles.Forsyth       (FT_Module_Constructor)0,
666*37da2899SCharles.Forsyth       (FT_Module_Destructor) 0,
667*37da2899SCharles.Forsyth       (FT_Module_Requester)  0
668*37da2899SCharles.Forsyth     },
669*37da2899SCharles.Forsyth 
670*37da2899SCharles.Forsyth     sizeof( FNT_FaceRec ),
671*37da2899SCharles.Forsyth     sizeof( FNT_SizeRec ),
672*37da2899SCharles.Forsyth     sizeof( FT_GlyphSlotRec ),
673*37da2899SCharles.Forsyth 
674*37da2899SCharles.Forsyth     (FT_Face_InitFunc)        FNT_Face_Init,
675*37da2899SCharles.Forsyth     (FT_Face_DoneFunc)        FNT_Face_Done,
676*37da2899SCharles.Forsyth     (FT_Size_InitFunc)        0,
677*37da2899SCharles.Forsyth     (FT_Size_DoneFunc)        0,
678*37da2899SCharles.Forsyth     (FT_Slot_InitFunc)        0,
679*37da2899SCharles.Forsyth     (FT_Slot_DoneFunc)        0,
680*37da2899SCharles.Forsyth 
681*37da2899SCharles.Forsyth     (FT_Size_ResetPointsFunc) FNT_Size_Set_Pixels,
682*37da2899SCharles.Forsyth     (FT_Size_ResetPixelsFunc) FNT_Size_Set_Pixels,
683*37da2899SCharles.Forsyth     (FT_Slot_LoadFunc)        FNT_Load_Glyph,
684*37da2899SCharles.Forsyth 
685*37da2899SCharles.Forsyth     (FT_Face_GetKerningFunc)  0,
686*37da2899SCharles.Forsyth     (FT_Face_AttachFunc)      0,
687*37da2899SCharles.Forsyth     (FT_Face_GetAdvancesFunc) 0
688*37da2899SCharles.Forsyth   };
689*37da2899SCharles.Forsyth 
690*37da2899SCharles.Forsyth 
691*37da2899SCharles.Forsyth /* END */
692