secur32: Update ntlm_auth version detection to detect new samba4 version numbers.
[wine] / dlls / gdi / freetype.c
1 /*
2  * FreeType font engine interface
3  *
4  * Copyright 2001 Huw D M Davies for CodeWeavers.
5  *
6  * This file contains the WineEng* functions.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #ifdef HAVE_SYS_STAT_H
29 # include <sys/stat.h>
30 #endif
31 #include <string.h>
32 #include <dirent.h>
33 #include <stdio.h>
34 #include <assert.h>
35
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winerror.h"
39 #include "winreg.h"
40 #include "wingdi.h"
41 #include "gdi.h"
42 #include "gdi_private.h"
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
45 #include "wine/list.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(font);
48
49 #ifdef HAVE_FREETYPE
50
51 #ifdef HAVE_FT2BUILD_H
52 #include <ft2build.h>
53 #endif
54 #ifdef HAVE_FREETYPE_FREETYPE_H
55 #include <freetype/freetype.h>
56 #endif
57 #ifdef HAVE_FREETYPE_FTGLYPH_H
58 #include <freetype/ftglyph.h>
59 #endif
60 #ifdef HAVE_FREETYPE_TTTABLES_H
61 #include <freetype/tttables.h>
62 #endif
63 #ifdef HAVE_FREETYPE_FTSNAMES_H
64 #include <freetype/ftsnames.h>
65 #else
66 # ifdef HAVE_FREETYPE_FTNAMES_H
67 # include <freetype/ftnames.h>
68 # endif
69 #endif
70 #ifdef HAVE_FREETYPE_TTNAMEID_H
71 #include <freetype/ttnameid.h>
72 #endif
73 #ifdef HAVE_FREETYPE_FTOUTLN_H
74 #include <freetype/ftoutln.h>
75 #endif
76 #ifdef HAVE_FREETYPE_INTERNAL_SFNT_H
77 #include <freetype/internal/sfnt.h>
78 #endif
79 #ifdef HAVE_FREETYPE_FTTRIGON_H
80 #include <freetype/fttrigon.h>
81 #endif
82 #ifdef HAVE_FREETYPE_FTWINFNT_H
83 #include <freetype/ftwinfnt.h>
84 #endif
85 #ifdef HAVE_FREETYPE_FTMODAPI_H
86 #include <freetype/ftmodapi.h>
87 #endif
88
89 #ifndef SONAME_LIBFREETYPE
90 #define SONAME_LIBFREETYPE "libfreetype.so"
91 #endif
92
93 #ifndef HAVE_FT_TRUETYPEENGINETYPE
94 typedef enum
95 {
96     FT_TRUETYPE_ENGINE_TYPE_NONE = 0,
97     FT_TRUETYPE_ENGINE_TYPE_UNPATENTED,
98     FT_TRUETYPE_ENGINE_TYPE_PATENTED
99 } FT_TrueTypeEngineType;
100 #endif
101
102 static FT_Library library = 0;
103 typedef struct
104 {
105     FT_Int major;
106     FT_Int minor;
107     FT_Int patch;
108 } FT_Version_t;
109 static FT_Version_t FT_Version;
110 static DWORD FT_SimpleVersion;
111
112 static void *ft_handle = NULL;
113
114 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
115 MAKE_FUNCPTR(FT_Vector_Unit);
116 MAKE_FUNCPTR(FT_Done_Face);
117 MAKE_FUNCPTR(FT_Get_Char_Index);
118 MAKE_FUNCPTR(FT_Get_Module);
119 MAKE_FUNCPTR(FT_Get_Sfnt_Table);
120 MAKE_FUNCPTR(FT_Init_FreeType);
121 MAKE_FUNCPTR(FT_Load_Glyph);
122 MAKE_FUNCPTR(FT_Matrix_Multiply);
123 MAKE_FUNCPTR(FT_MulFix);
124 MAKE_FUNCPTR(FT_New_Face);
125 MAKE_FUNCPTR(FT_Outline_Get_Bitmap);
126 MAKE_FUNCPTR(FT_Outline_Transform);
127 MAKE_FUNCPTR(FT_Outline_Translate);
128 MAKE_FUNCPTR(FT_Select_Charmap);
129 MAKE_FUNCPTR(FT_Set_Pixel_Sizes);
130 MAKE_FUNCPTR(FT_Vector_Transform);
131 static void (*pFT_Library_Version)(FT_Library,FT_Int*,FT_Int*,FT_Int*);
132 static FT_Error (*pFT_Load_Sfnt_Table)(FT_Face,FT_ULong,FT_Long,FT_Byte*,FT_ULong*);
133 static FT_ULong (*pFT_Get_First_Char)(FT_Face,FT_UInt*);
134 static FT_TrueTypeEngineType (*pFT_Get_TrueType_Engine_Type)(FT_Library);
135 #ifdef HAVE_FREETYPE_FTWINFNT_H
136 MAKE_FUNCPTR(FT_Get_WinFNT_Header);
137 #endif
138
139 #ifdef HAVE_FONTCONFIG_FONTCONFIG_H
140 #include <fontconfig/fontconfig.h>
141 MAKE_FUNCPTR(FcConfigGetCurrent);
142 MAKE_FUNCPTR(FcFontList);
143 MAKE_FUNCPTR(FcFontSetDestroy);
144 MAKE_FUNCPTR(FcInit);
145 MAKE_FUNCPTR(FcObjectSetAdd);
146 MAKE_FUNCPTR(FcObjectSetCreate);
147 MAKE_FUNCPTR(FcObjectSetDestroy);
148 MAKE_FUNCPTR(FcPatternCreate);
149 MAKE_FUNCPTR(FcPatternDestroy);
150 MAKE_FUNCPTR(FcPatternGet);
151 #ifndef SONAME_LIBFONTCONFIG
152 #define SONAME_LIBFONTCONFIG "libfontconfig.so"
153 #endif
154 #endif
155
156 #undef MAKE_FUNCPTR
157
158 #ifndef ft_encoding_none
159 #define FT_ENCODING_NONE ft_encoding_none
160 #endif
161 #ifndef ft_encoding_ms_symbol
162 #define FT_ENCODING_MS_SYMBOL ft_encoding_symbol
163 #endif
164 #ifndef ft_encoding_unicode
165 #define FT_ENCODING_UNICODE ft_encoding_unicode
166 #endif
167 #ifndef ft_encoding_apple_roman
168 #define FT_ENCODING_APPLE_ROMAN ft_encoding_apple_roman
169 #endif
170
171 #define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
172
173 /* This is bascially a copy of FT_Bitmap_Size with an extra element added */
174 typedef struct {
175     FT_Short height;
176     FT_Short width;
177     FT_Pos size;
178     FT_Pos x_ppem;
179     FT_Pos y_ppem;
180     FT_Short internal_leading;
181 } Bitmap_Size;
182
183 /* FT_Bitmap_Size gained 3 new elements between FreeType 2.1.4 and 2.1.5
184    So to let this compile on older versions of FreeType we'll define the
185    new structure here. */
186 typedef struct {
187     FT_Short height, width;
188     FT_Pos size, x_ppem, y_ppem;
189 } My_FT_Bitmap_Size;
190
191 typedef struct tagFace {
192     struct list entry;
193     WCHAR *StyleName;
194     char *file;
195     FT_Long face_index;
196     BOOL Italic;
197     BOOL Bold;
198     FONTSIGNATURE fs;
199     FONTSIGNATURE fs_links;
200     FT_Fixed font_version;
201     BOOL scalable;
202     Bitmap_Size size;     /* set if face is a bitmap */
203     BOOL external; /* TRUE if we should manually add this font to the registry */
204     struct tagFamily *family;
205 } Face;
206
207 typedef struct tagFamily {
208     struct list entry;
209     WCHAR *FamilyName;
210     struct list faces;
211 } Family;
212
213 typedef struct {
214     GLYPHMETRICS gm;
215     INT adv; /* These three hold to widths of the unrotated chars */
216     INT lsb;
217     INT bbx;
218     BOOL init;
219 } GM;
220
221 typedef struct {
222     FLOAT eM11, eM12;
223     FLOAT eM21, eM22;
224 } FMAT2;
225
226 typedef struct {
227     DWORD hash;
228     LOGFONTW lf;
229     FMAT2 matrix;
230 } FONT_DESC;
231
232 typedef struct tagHFONTLIST {
233     struct list entry;
234     HFONT hfont;
235 } HFONTLIST;
236
237 typedef struct {
238     struct list entry;
239     char *file_name;
240     INT index;
241     GdiFont font;
242 } CHILD_FONT;
243
244 struct tagGdiFont {
245     struct list entry;
246     FT_Face ft_face;
247     LPWSTR name;
248     int charset;
249     int codepage;
250     BOOL fake_italic;
251     BOOL fake_bold;
252     BYTE underline;
253     BYTE strikeout;
254     INT orientation;
255     GM *gm;
256     DWORD gmsize;
257     struct list hfontlist;
258     FONT_DESC font_desc;
259     LONG aveWidth;
260     SHORT yMax;
261     SHORT yMin;
262     OUTLINETEXTMETRICW *potm;
263     FONTSIGNATURE fs;
264     GdiFont base_font;
265     struct list child_fonts;
266     LONG ppem;
267 };
268
269 typedef struct {
270     struct list entry;
271     WCHAR *font_name;
272     struct list links;
273 } SYSTEM_LINKS;
274
275 #define INIT_GM_SIZE 128
276
277 static struct list gdi_font_list = LIST_INIT(gdi_font_list);
278 static struct list unused_gdi_font_list = LIST_INIT(unused_gdi_font_list);
279 #define UNUSED_CACHE_SIZE 10
280 static struct list child_font_list = LIST_INIT(child_font_list);
281 static struct list system_links = LIST_INIT(system_links);
282
283 static struct list font_list = LIST_INIT(font_list);
284
285 static const WCHAR defSerif[] = {'T','i','m','e','s',' ','N','e','w',' ',
286                            'R','o','m','a','n','\0'};
287 static const WCHAR defSans[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
288 static const WCHAR defFixed[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'};
289
290 static const WCHAR defSystem[] = {'S','y','s','t','e','m','\0'};
291 static const WCHAR SystemW[] = {'S','y','s','t','e','m','\0'};
292 static const WCHAR MSSansSerifW[] = {'M','S',' ','S','a','n','s',' ',
293                                'S','e','r','i','f','\0'};
294 static const WCHAR HelvW[] = {'H','e','l','v','\0'};
295 static const WCHAR RegularW[] = {'R','e','g','u','l','a','r','\0'};
296
297 static const WCHAR fontsW[] = {'\\','F','o','n','t','s','\0'};
298 static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
299                                            'W','i','n','d','o','w','s','\\',
300                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
301                                            'F','o','n','t','s','\0'};
302
303 static const WCHAR winnt_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
304                                            'W','i','n','d','o','w','s',' ','N','T','\\',
305                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
306                                            'F','o','n','t','s','\0'};
307
308 static const WCHAR system_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
309 static const WCHAR FixedSys_Value[] = {'F','I','X','E','D','F','O','N','.','F','O','N','\0'};
310 static const WCHAR System_Value[] = {'F','O','N','T','S','.','F','O','N','\0'};
311 static const WCHAR OEMFont_Value[] = {'O','E','M','F','O','N','T','.','F','O','N','\0'};
312
313 static const WCHAR *SystemFontValues[4] = {
314     System_Value,
315     OEMFont_Value,
316     FixedSys_Value,
317     NULL
318 };
319
320 static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
321                                                'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'};
322
323 static const WCHAR ArabicW[] = {'A','r','a','b','i','c','\0'};
324 static const WCHAR BalticW[] = {'B','a','l','t','i','c','\0'};
325 static const WCHAR CHINESE_BIG5W[] = {'C','H','I','N','E','S','E','_','B','I','G','5','\0'};
326 static const WCHAR CHINESE_GB2312W[] = {'C','H','I','N','E','S','E','_','G','B','2','3','1','2','\0'};
327 static const WCHAR Central_EuropeanW[] = {'C','e','n','t','r','a','l',' ',
328                                     'E','u','r','o','p','e','a','n','\0'};
329 static const WCHAR CyrillicW[] = {'C','y','r','i','l','l','i','c','\0'};
330 static const WCHAR GreekW[] = {'G','r','e','e','k','\0'};
331 static const WCHAR HangulW[] = {'H','a','n','g','u','l','\0'};
332 static const WCHAR Hangul_Johab_W[] = {'H','a','n','g','u','l','(','J','o','h','a','b',')','\0'};
333 static const WCHAR HebrewW[] = {'H','e','b','r','e','w','\0'};
334 static const WCHAR JapaneseW[] = {'J','a','p','a','n','e','s','e','\0'};
335 static const WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
336 static const WCHAR ThaiW[] = {'T','h','a','i','\0'};
337 static const WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'};
338 static const WCHAR VietnameseW[] = {'V','i','e','t','n','a','m','e','s','e','\0'};
339 static const WCHAR WesternW[] = {'W','e','s','t','e','r','n','\0'};
340 static const WCHAR OEM_DOSW[] = {'O','E','M','/','D','O','S','\0'};
341
342 static const WCHAR *ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits */
343     WesternW, /*00*/
344     Central_EuropeanW,
345     CyrillicW,
346     GreekW,
347     TurkishW,
348     HebrewW,
349     ArabicW,
350     BalticW,
351     VietnameseW, /*08*/
352     NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/
353     ThaiW,
354     JapaneseW,
355     CHINESE_GB2312W,
356     HangulW,
357     CHINESE_BIG5W,
358     Hangul_Johab_W,
359     NULL, NULL, /*23*/
360     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
361     SymbolW /*31*/
362 };
363
364 typedef struct {
365   WCHAR *name;
366   INT charset;
367 } NameCs;
368
369 typedef struct tagFontSubst {
370   NameCs from;
371   NameCs to;
372   struct tagFontSubst *next;
373 } FontSubst;
374
375 static FontSubst *substlist = NULL;
376 static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail if this is still FALSE */
377
378 static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'};
379
380
381 /****************************************
382  *   Notes on .fon files
383  *
384  * The fonts System, FixedSys and Terminal are special.  There are typically multiple
385  * versions installed for different resolutions and codepages.  Windows stores which one to use
386  * in HKEY_CURRENT_CONFIG\\Software\\Fonts.
387  *    Key            Meaning
388  *  FIXEDFON.FON    FixedSys
389  *  FONTS.FON       System
390  *  OEMFONT.FON     Terminal
391  *  LogPixels       Current dpi set by the display control panel applet
392  *                  (HKLM\\Software\\Microsft\\Windows NT\\CurrentVersion\\FontDPI
393  *                  also has a LogPixels value that appears to mirror this)
394  *
395  * On my system these values have data: vgafix.fon, vgasys.fon, vga850.fon and 96 respectively
396  * (vgaoem.fon would be your oemfont.fon if you have a US setup).
397  * If the resolution is changed to be >= 109dpi then the fonts goto 8514fix, 8514sys and 8514oem
398  * (not sure what's happening to the oem codepage here). 109 is nicely halfway between 96 and 120dpi,
399  * so that makes sense.
400  *
401  * Additionally Windows also loads the fonts listed in the [386enh] section of system.ini (this doesn't appear
402  * to be mapped into the registry on Windows 2000 at least).
403  * I have
404  * woafont=app850.fon
405  * ega80woa.fon=ega80850.fon
406  * ega40woa.fon=ega40850.fon
407  * cga80woa.fon=cga80850.fon
408  * cga40woa.fon=cga40850.fon
409  */
410
411
412 static inline BOOL is_win9x(void)
413 {
414     return GetVersion() & 0x80000000;
415 }
416 /* 
417    This function builds an FT_Fixed from a float. It puts the integer part
418    in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed.
419    It fails if the integer part of the float number is greater than SHORT_MAX.
420 */
421 static inline FT_Fixed FT_FixedFromFloat(float f)
422 {
423         short value = f;
424         unsigned short fract = (f - value) * 0xFFFF;
425         return (FT_Fixed)((long)value << 16 | (unsigned long)fract);
426 }
427
428 /* 
429    This function builds an FT_Fixed from a FIXED. It simply put f.value 
430    in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
431 */
432 static inline FT_Fixed FT_FixedFromFIXED(FIXED f)
433 {
434         return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
435 }
436
437 #define ADDFONT_EXTERNAL_FONT 0x01
438 #define ADDFONT_FORCE_BITMAP  0x02
439 static BOOL AddFontFileToList(const char *file, char *fake_family, DWORD flags)
440 {
441     FT_Face ft_face;
442     TT_OS2 *pOS2;
443     TT_Header *pHeader = NULL;
444     WCHAR *FamilyW, *StyleW;
445     DWORD len;
446     Family *family;
447     Face *face;
448     struct list *family_elem_ptr, *face_elem_ptr;
449     FT_Error err;
450     FT_Long face_index = 0, num_faces;
451 #ifdef HAVE_FREETYPE_FTWINFNT_H
452     FT_WinFNT_HeaderRec winfnt_header;
453 #endif
454     int i, bitmap_num, internal_leading;
455     FONTSIGNATURE fs;
456
457     do {
458         char *family_name = fake_family;
459
460         TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
461         if((err = pFT_New_Face(library, file, face_index, &ft_face)) != 0) {
462             WARN("Unable to load font file %s err = %x\n", debugstr_a(file), err);
463             return FALSE;
464         }
465
466         if(!FT_IS_SFNT(ft_face) && (FT_IS_SCALABLE(ft_face) || !(flags & ADDFONT_FORCE_BITMAP))) { /* for now we'll accept TT/OT or bitmap fonts*/
467             WARN("Ignoring font %s\n", debugstr_a(file));
468             pFT_Done_Face(ft_face);
469             return FALSE;
470         }
471
472         /* There are too many bugs in FreeType < 2.1.9 for bitmap font support */
473         if(!FT_IS_SCALABLE(ft_face) && FT_SimpleVersion < ((2 << 16) | (1 << 8) | (9 << 0))) {
474             WARN("FreeType version < 2.1.9, skipping bitmap font %s\n", debugstr_a(file));
475             pFT_Done_Face(ft_face);
476             return FALSE;
477         }
478
479         if(FT_IS_SFNT(ft_face) && (!pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2) ||
480            !pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea) ||
481            !(pHeader = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_head)))) {
482             TRACE("Font file %s lacks either an OS2, HHEA or HEAD table.\n"
483                   "Skipping this font.\n", debugstr_a(file));
484             pFT_Done_Face(ft_face);
485             return FALSE;
486         }
487
488         if(!ft_face->family_name || !ft_face->style_name) {
489             TRACE("Font file %s lacks either a family or style name\n", debugstr_a(file));
490             pFT_Done_Face(ft_face);
491             return FALSE;
492         }
493
494         if(!family_name)
495             family_name = ft_face->family_name;
496
497         bitmap_num = 0;
498         do {
499             My_FT_Bitmap_Size *size = NULL;
500
501             if(!FT_IS_SCALABLE(ft_face))
502                 size = (My_FT_Bitmap_Size *)ft_face->available_sizes + bitmap_num;
503
504             len = MultiByteToWideChar(CP_ACP, 0, family_name, -1, NULL, 0);
505             FamilyW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
506             MultiByteToWideChar(CP_ACP, 0, family_name, -1, FamilyW, len);
507
508             family = NULL;
509             LIST_FOR_EACH(family_elem_ptr, &font_list) {
510                 family = LIST_ENTRY(family_elem_ptr, Family, entry);
511                 if(!strcmpW(family->FamilyName, FamilyW))
512                     break;
513                 family = NULL;
514             }
515             if(!family) {
516                 family = HeapAlloc(GetProcessHeap(), 0, sizeof(*family));
517                 family->FamilyName = FamilyW;
518                 list_init(&family->faces);
519                 list_add_tail(&font_list, &family->entry);
520             } else {
521                 HeapFree(GetProcessHeap(), 0, FamilyW);
522             }
523
524             len = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0);
525             StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
526             MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
527
528             internal_leading = 0;
529             memset(&fs, 0, sizeof(fs));
530
531             pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
532             if(pOS2) {
533                 fs.fsCsb[0] = pOS2->ulCodePageRange1;
534                 fs.fsCsb[1] = pOS2->ulCodePageRange2;
535                 fs.fsUsb[0] = pOS2->ulUnicodeRange1;
536                 fs.fsUsb[1] = pOS2->ulUnicodeRange2;
537                 fs.fsUsb[2] = pOS2->ulUnicodeRange3;
538                 fs.fsUsb[3] = pOS2->ulUnicodeRange4;
539                 if(pOS2->version == 0) {
540                     FT_UInt dummy;
541
542                     if(!pFT_Get_First_Char || (pFT_Get_First_Char( ft_face, &dummy ) < 0x100))
543                         fs.fsCsb[0] |= 1;
544                     else
545                         fs.fsCsb[0] |= 1L << 31;
546                 }
547             }
548 #ifdef HAVE_FREETYPE_FTWINFNT_H
549             else if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header)) {
550                 CHARSETINFO csi;
551                 TRACE("pix_h %d charset %d dpi %dx%d pt %d\n", winfnt_header.pixel_height, winfnt_header.charset,
552                       winfnt_header.vertical_resolution,winfnt_header.horizontal_resolution, winfnt_header.nominal_point_size);
553                 if(TranslateCharsetInfo((DWORD*)(UINT)winfnt_header.charset, &csi, TCI_SRCCHARSET))
554                     memcpy(&fs, &csi.fs, sizeof(csi.fs));
555                 internal_leading = winfnt_header.internal_leading;
556             }
557 #endif
558
559             face_elem_ptr = list_head(&family->faces);
560             while(face_elem_ptr) {
561                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
562                 face_elem_ptr = list_next(&family->faces, face_elem_ptr);
563                 if(!strcmpW(face->StyleName, StyleW) &&
564                    (FT_IS_SCALABLE(ft_face) || ((size->y_ppem == face->size.y_ppem) && !memcmp(&fs, &face->fs, sizeof(fs)) ))) {
565                     TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
566                           debugstr_w(family->FamilyName), debugstr_w(StyleW),
567                           face->font_version,  pHeader ? pHeader->Font_Revision : 0);
568
569                     if(fake_family) {
570                         TRACE("This font is a replacement but the original really exists, so we'll skip the replacement\n");
571                         HeapFree(GetProcessHeap(), 0, StyleW);
572                         pFT_Done_Face(ft_face);
573                         return FALSE;
574                     }
575                     if(!pHeader || pHeader->Font_Revision <= face->font_version) {
576                         TRACE("Original font is newer so skipping this one\n");
577                         HeapFree(GetProcessHeap(), 0, StyleW);
578                         pFT_Done_Face(ft_face);
579                         return FALSE;
580                     } else {
581                         TRACE("Replacing original with this one\n");
582                         list_remove(&face->entry);
583                         HeapFree(GetProcessHeap(), 0, face->file);
584                         HeapFree(GetProcessHeap(), 0, face->StyleName);
585                         HeapFree(GetProcessHeap(), 0, face);
586                         break;
587                     }
588                 }
589             }
590             face = HeapAlloc(GetProcessHeap(), 0, sizeof(*face));
591             list_add_tail(&family->faces, &face->entry);
592             face->StyleName = StyleW;
593             face->file = HeapAlloc(GetProcessHeap(),0,strlen(file)+1);
594             strcpy(face->file, file);
595             face->face_index = face_index;
596             face->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
597             face->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0;
598             face->font_version = pHeader ? pHeader->Font_Revision : 0;
599             face->family = family;
600             face->external = (flags & ADDFONT_EXTERNAL_FONT) ? TRUE : FALSE;
601             memcpy(&face->fs, &fs, sizeof(face->fs));
602             memset(&face->fs_links, 0, sizeof(face->fs_links));
603
604             if(FT_IS_SCALABLE(ft_face)) {
605                 memset(&face->size, 0, sizeof(face->size));
606                 face->scalable = TRUE;
607             } else {
608                 TRACE("Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld\n",
609                       size->height, size->width, size->size >> 6,
610                       size->x_ppem >> 6, size->y_ppem >> 6);
611                 face->size.height = size->height;
612                 face->size.width = size->width;
613                 face->size.size = size->size;
614                 face->size.x_ppem = size->x_ppem;
615                 face->size.y_ppem = size->y_ppem;
616                 face->size.internal_leading = internal_leading;
617                 face->scalable = FALSE;
618             }
619
620             TRACE("fsCsb = %08lx %08lx/%08lx %08lx %08lx %08lx\n",
621                   face->fs.fsCsb[0], face->fs.fsCsb[1],
622                   face->fs.fsUsb[0], face->fs.fsUsb[1],
623                   face->fs.fsUsb[2], face->fs.fsUsb[3]);
624
625
626             if(face->fs.fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */
627                 for(i = 0; i < ft_face->num_charmaps; i++) {
628                     switch(ft_face->charmaps[i]->encoding) {
629                     case FT_ENCODING_UNICODE:
630                     case FT_ENCODING_APPLE_ROMAN:
631                         face->fs.fsCsb[0] |= 1;
632                         break;
633                     case FT_ENCODING_MS_SYMBOL:
634                         face->fs.fsCsb[0] |= 1L << 31;
635                         break;
636                     default:
637                         break;
638                     }
639                 }
640             }
641
642             if(face->fs.fsCsb[0] & ~(1L << 31))
643                 have_installed_roman_font = TRUE;
644         } while(!FT_IS_SCALABLE(ft_face) && ++bitmap_num < ft_face->num_fixed_sizes);
645
646         num_faces = ft_face->num_faces;
647         pFT_Done_Face(ft_face);
648         TRACE("Added font %s %s\n", debugstr_w(family->FamilyName),
649               debugstr_w(StyleW));
650     } while(num_faces > ++face_index);
651     return TRUE;
652 }
653
654 static void DumpFontList(void)
655 {
656     Family *family;
657     Face *face;
658     struct list *family_elem_ptr, *face_elem_ptr;
659
660     LIST_FOR_EACH(family_elem_ptr, &font_list) {
661         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
662         TRACE("Family: %s\n", debugstr_w(family->FamilyName));
663         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
664             face = LIST_ENTRY(face_elem_ptr, Face, entry);
665             TRACE("\t%s\t%08lx", debugstr_w(face->StyleName), face->fs.fsCsb[0]);
666             if(!face->scalable)
667                 TRACE(" %ld", face->size.y_ppem >> 6);
668             TRACE("\n");
669         }
670     }
671     return;
672 }
673
674 static Face *find_face_from_filename(const WCHAR *name)
675 {
676     Family *family;
677     Face *face;
678     char *file;
679     DWORD len = WideCharToMultiByte(CP_UNIXCP, 0, name, -1, NULL, 0, NULL, NULL);
680     char *nameA = HeapAlloc(GetProcessHeap(), 0, len);
681     Face *ret = NULL;
682
683     WideCharToMultiByte(CP_UNIXCP, 0, name, -1, nameA, len, NULL, NULL);
684     TRACE("looking for %s\n", debugstr_a(nameA));
685
686     LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
687     {
688         LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
689         {
690             file = strrchr(face->file, '/');
691             if(!file)
692                 file = face->file;
693             else
694                 file++;
695             if(!strcmp(file, nameA))
696                 ret = face;
697             break;
698         }
699     }
700     HeapFree(GetProcessHeap(), 0, nameA);
701     return ret;
702 }
703
704 static Family *find_family_from_name(const WCHAR *name)
705 {
706     Family *family;
707
708     LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
709     {
710         if(!strcmpiW(family->FamilyName, name))
711             return family;
712     }
713
714     return NULL;
715 }
716     
717 static void DumpSubstList(void)
718 {
719     FontSubst *psub;
720
721     for(psub = substlist; psub; psub = psub->next)
722         if(psub->from.charset != -1 || psub->to.charset != -1)
723             TRACE("%s:%d -> %s:%d\n", debugstr_w(psub->from.name),
724               psub->from.charset, debugstr_w(psub->to.name), psub->to.charset);
725         else
726             TRACE("%s -> %s\n", debugstr_w(psub->from.name),
727                   debugstr_w(psub->to.name));
728     return;
729 }
730
731 static LPWSTR strdupW(LPCWSTR p)
732 {
733     LPWSTR ret;
734     DWORD len = (strlenW(p) + 1) * sizeof(WCHAR);
735     ret = HeapAlloc(GetProcessHeap(), 0, len);
736     memcpy(ret, p, len);
737     return ret;
738 }
739
740 static LPSTR strdupA(LPCSTR p)
741 {
742     LPSTR ret;
743     DWORD len = (strlen(p) + 1);
744     ret = HeapAlloc(GetProcessHeap(), 0, len);
745     memcpy(ret, p, len);
746     return ret;
747 }
748
749 static void split_subst_info(NameCs *nc, LPSTR str)
750 {
751     CHAR *p = strrchr(str, ',');
752     DWORD len;
753
754     nc->charset = -1;
755     if(p && *(p+1)) {
756         nc->charset = strtol(p+1, NULL, 10);
757         *p = '\0';
758     }
759     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
760     nc->name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
761     MultiByteToWideChar(CP_ACP, 0, str, -1, nc->name, len);
762 }
763
764 static void LoadSubstList(void)
765 {
766     FontSubst *psub, **ppsub;
767     HKEY hkey;
768     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
769     LPSTR value;
770     LPVOID data;
771
772     if(substlist) {
773         for(psub = substlist; psub;) {
774             FontSubst *ptmp;
775             HeapFree(GetProcessHeap(), 0, psub->to.name);
776             HeapFree(GetProcessHeap(), 0, psub->from.name);
777             ptmp = psub;
778             psub = psub->next;
779             HeapFree(GetProcessHeap(), 0, ptmp);
780         }
781         substlist = NULL;
782     }
783
784     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
785                    "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes",
786                    &hkey) == ERROR_SUCCESS) {
787
788         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
789                          &valuelen, &datalen, NULL, NULL);
790
791         valuelen++; /* returned value doesn't include room for '\0' */
792         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
793         data = HeapAlloc(GetProcessHeap(), 0, datalen);
794
795         dlen = datalen;
796         vlen = valuelen;
797         ppsub = &substlist;
798         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
799                             &dlen) == ERROR_SUCCESS) {
800             TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
801
802             *ppsub = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppsub));
803             (*ppsub)->next = NULL;
804             split_subst_info(&((*ppsub)->from), value);
805             split_subst_info(&((*ppsub)->to), data);
806
807             /* Win 2000 doesn't allow mapping between different charsets
808                or mapping of DEFAULT_CHARSET */
809             if(((*ppsub)->to.charset != (*ppsub)->from.charset) ||
810                (*ppsub)->to.charset == DEFAULT_CHARSET) {
811                 HeapFree(GetProcessHeap(), 0, (*ppsub)->to.name);
812                 HeapFree(GetProcessHeap(), 0, (*ppsub)->from.name);
813                 HeapFree(GetProcessHeap(), 0, *ppsub);
814                 *ppsub = NULL;
815             } else {
816                 ppsub = &((*ppsub)->next);
817             }
818             /* reset dlen and vlen */
819             dlen = datalen;
820             vlen = valuelen;
821         }
822         HeapFree(GetProcessHeap(), 0, data);
823         HeapFree(GetProcessHeap(), 0, value);
824         RegCloseKey(hkey);
825     }
826 }
827
828 /***********************************************************
829  * The replacement list is a way to map an entire font
830  * family onto another family.  For example adding
831  *
832  * [HKCU\Software\Wine\Fonts\Replacements]
833  * "Wingdings"="Winedings"
834  *
835  * would enumerate the Winedings font both as Winedings and
836  * Wingdings.  However if a real Wingdings font is present the
837  * replacement does not take place.
838  * 
839  */
840 static void LoadReplaceList(void)
841 {
842     HKEY hkey;
843     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
844     LPSTR value;
845     LPVOID data;
846     Family *family;
847     Face *face;
848     struct list *family_elem_ptr, *face_elem_ptr;
849     WCHAR old_nameW[200];
850
851     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\Replacements */
852     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts\\Replacements", &hkey) == ERROR_SUCCESS)
853     {
854         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
855                          &valuelen, &datalen, NULL, NULL);
856
857         valuelen++; /* returned value doesn't include room for '\0' */
858         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
859         data = HeapAlloc(GetProcessHeap(), 0, datalen);
860
861         dlen = datalen;
862         vlen = valuelen;
863         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
864                             &dlen) == ERROR_SUCCESS) {
865             TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
866             /* "NewName"="Oldname" */
867             if(!MultiByteToWideChar(CP_ACP, 0, data, -1, old_nameW, sizeof(old_nameW)/sizeof(WCHAR)))
868                 break;
869
870             /* Find the old family and hence all of the font files
871                in that family */
872             LIST_FOR_EACH(family_elem_ptr, &font_list) {
873                 family = LIST_ENTRY(family_elem_ptr, Family, entry); 
874                 if(!strcmpiW(family->FamilyName, old_nameW)) {                
875                     LIST_FOR_EACH(face_elem_ptr, &family->faces) {
876                         face = LIST_ENTRY(face_elem_ptr, Face, entry);
877                         TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName),
878                               debugstr_w(face->StyleName), value);
879                         /* Now add a new entry with the new family name */
880                         AddFontFileToList(face->file, value, ADDFONT_FORCE_BITMAP | (face->external ? ADDFONT_EXTERNAL_FONT : 0));
881                     }
882                     break;
883                 }
884             }
885             /* reset dlen and vlen */
886             dlen = datalen;
887             vlen = valuelen;
888         }
889         HeapFree(GetProcessHeap(), 0, data);
890         HeapFree(GetProcessHeap(), 0, value);
891         RegCloseKey(hkey);
892     }
893 }
894
895 /*************************************************************
896  * init_system_links
897  */
898 static BOOL init_system_links(void)
899 {
900     static const WCHAR system_link[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
901                                         'W','i','n','d','o','w','s',' ','N','T','\\',
902                                         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','F','o','n','t','L','i','n','k','\\',
903                                         'S','y','s','t','e','m','L','i','n','k',0};
904     HKEY hkey;
905     BOOL ret = FALSE;
906     DWORD type, max_val, max_data, val_len, data_len, index;
907     WCHAR *value, *data;
908     WCHAR *entry, *next;
909     SYSTEM_LINKS *font_link, *system_font_link;
910     CHILD_FONT *child_font;
911     static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
912     static const WCHAR tahoma_ttf[] = {'t','a','h','o','m','a','.','t','t','f',0};
913     static const WCHAR System[] = {'S','y','s','t','e','m',0};
914     FONTSIGNATURE fs;
915     Family *family;
916     Face *face;
917
918     if(RegOpenKeyW(HKEY_LOCAL_MACHINE, system_link, &hkey) == ERROR_SUCCESS)
919     {
920         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &max_val, &max_data, NULL, NULL);
921         value = HeapAlloc(GetProcessHeap(), 0, (max_val + 1) * sizeof(WCHAR));
922         data = HeapAlloc(GetProcessHeap(), 0, max_data);
923         val_len = max_val + 1;
924         data_len = max_data;
925         index = 0;
926         while(RegEnumValueW(hkey, index++, value, &val_len, NULL, &type, (LPBYTE)data, &data_len) == ERROR_SUCCESS)
927         {
928             TRACE("%s:\n", debugstr_w(value));
929
930             memset(&fs, 0, sizeof(fs));
931             font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_link));
932             font_link->font_name = strdupW(value);
933             list_init(&font_link->links);
934             for(entry = data; (char*)entry < (char*)data + data_len && *entry != 0; entry = next)
935             {
936                 WCHAR *face_name;
937                 INT index;
938                 CHILD_FONT *child_font;
939
940                 TRACE("\t%s\n", debugstr_w(entry));
941
942                 next = entry + strlenW(entry) + 1;
943                 
944                 face_name = strchrW(entry, ',');
945                 if(!face_name)
946                     index = 0;
947                 else
948                 {
949                     FIXME("don't yet handle ttc's correctly in linking.  Assuming index 0\n");
950                     *face_name++ = 0;
951                     while(isspaceW(*face_name))
952                         face_name++;
953
954                     index = 0;
955                 }
956                 face = find_face_from_filename(entry);
957                 if(!face)
958                 {
959                     TRACE("Unable to find file %s\n", debugstr_w(entry));
960                     continue;
961                 }
962
963                 child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
964                 child_font->file_name = strdupA(face->file);
965                 child_font->index = index;
966                 child_font->font = NULL;
967                 fs.fsCsb[0] |= face->fs.fsCsb[0];
968                 fs.fsCsb[1] |= face->fs.fsCsb[1];
969                 list_add_tail(&font_link->links, &child_font->entry);
970             }
971             family = find_family_from_name(font_link->font_name);
972             if(family)
973             {
974                 LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
975                 {
976                     memcpy(&face->fs_links, &fs, sizeof(fs));
977                 }
978             }
979             list_add_tail(&system_links, &font_link->entry);
980             val_len = max_val + 1;
981             data_len = max_data;
982         }
983
984         HeapFree(GetProcessHeap(), 0, value);
985         HeapFree(GetProcessHeap(), 0, data);
986         RegCloseKey(hkey);
987     }
988
989     /* Explicitly add an entry for the system font, this links to Tahoma and any links
990        that Tahoma has */
991
992     system_font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*system_font_link));
993     system_font_link->font_name = strdupW(System);
994     list_init(&system_font_link->links);    
995
996     face = find_face_from_filename(tahoma_ttf);
997     if(face)
998     {
999         child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
1000         child_font->file_name = strdupA(face->file);
1001         child_font->index = 0;
1002         child_font->font = NULL;
1003         list_add_tail(&system_font_link->links, &child_font->entry);
1004     }
1005     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
1006     {
1007         if(!strcmpiW(font_link->font_name, Tahoma))
1008         {
1009             CHILD_FONT *font_link_entry;
1010             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
1011             {
1012                 CHILD_FONT *new_child;
1013                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
1014                 new_child->file_name = strdupA(font_link_entry->file_name);
1015                 new_child->index = font_link_entry->index;
1016                 new_child->font = NULL;
1017                 list_add_tail(&system_font_link->links, &new_child->entry);
1018             }
1019             break;
1020         }
1021     }
1022     list_add_tail(&system_links, &system_font_link->entry);
1023     return ret;
1024 }
1025
1026 static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
1027 {
1028     DIR *dir;
1029     struct dirent *dent;
1030     char path[MAX_PATH];
1031
1032     TRACE("Loading fonts from %s\n", debugstr_a(dirname));
1033
1034     dir = opendir(dirname);
1035     if(!dir) {
1036         ERR("Can't open directory %s\n", debugstr_a(dirname));
1037         return FALSE;
1038     }
1039     while((dent = readdir(dir)) != NULL) {
1040         struct stat statbuf;
1041
1042         if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
1043             continue;
1044
1045         TRACE("Found %s in %s\n", debugstr_a(dent->d_name), debugstr_a(dirname));
1046
1047         sprintf(path, "%s/%s", dirname, dent->d_name);
1048
1049         if(stat(path, &statbuf) == -1)
1050         {
1051             WARN("Can't stat %s\n", debugstr_a(path));
1052             continue;
1053         }
1054         if(S_ISDIR(statbuf.st_mode))
1055             ReadFontDir(path, external_fonts);
1056         else
1057             AddFontFileToList(path, NULL, external_fonts ? ADDFONT_EXTERNAL_FONT : 0);
1058     }
1059     closedir(dir);
1060     return TRUE;
1061 }
1062
1063 static void load_fontconfig_fonts(void)
1064 {
1065 #ifdef HAVE_FONTCONFIG_FONTCONFIG_H
1066     void *fc_handle = NULL;
1067     FcConfig *config;
1068     FcPattern *pat;
1069     FcObjectSet *os;
1070     FcFontSet *fontset;
1071     FcValue v;
1072     int i, len;
1073     const char *file, *ext;
1074
1075     fc_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0);
1076     if(!fc_handle) {
1077         TRACE("Wine cannot find the fontconfig library (%s).\n",
1078               SONAME_LIBFONTCONFIG);
1079         return;
1080     }
1081 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(fc_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
1082 LOAD_FUNCPTR(FcConfigGetCurrent);
1083 LOAD_FUNCPTR(FcFontList);
1084 LOAD_FUNCPTR(FcFontSetDestroy);
1085 LOAD_FUNCPTR(FcInit);
1086 LOAD_FUNCPTR(FcObjectSetAdd);
1087 LOAD_FUNCPTR(FcObjectSetCreate);
1088 LOAD_FUNCPTR(FcObjectSetDestroy);
1089 LOAD_FUNCPTR(FcPatternCreate);
1090 LOAD_FUNCPTR(FcPatternDestroy);
1091 LOAD_FUNCPTR(FcPatternGet);
1092 #undef LOAD_FUNCPTR
1093
1094     if(!pFcInit()) return;
1095     
1096     config = pFcConfigGetCurrent();
1097     pat = pFcPatternCreate();
1098     os = pFcObjectSetCreate();
1099     pFcObjectSetAdd(os, FC_FILE);
1100     fontset = pFcFontList(config, pat, os);
1101     if(!fontset) return;
1102     for(i = 0; i < fontset->nfont; i++) {
1103         if(pFcPatternGet(fontset->fonts[i], FC_FILE, 0, &v) != FcResultMatch)
1104             continue;
1105         if(v.type != FcTypeString) continue;
1106         file = (LPCSTR) v.u.s;
1107         TRACE("fontconfig: %s\n", file);
1108
1109         /* We're just interested in OT/TT fonts for now, so this hack just
1110            picks up the standard extensions to save time loading every other
1111            font */
1112         len = strlen( file );
1113         if(len < 4) continue;
1114         ext = &file[ len - 3 ];
1115         if(!strcasecmp(ext, "ttf") || !strcasecmp(ext, "ttc") || !strcasecmp(ext, "otf"))
1116             AddFontFileToList(file, NULL, ADDFONT_EXTERNAL_FONT);
1117     }
1118     pFcFontSetDestroy(fontset);
1119     pFcObjectSetDestroy(os);
1120     pFcPatternDestroy(pat);
1121  sym_not_found:
1122 #endif
1123     return;
1124 }
1125
1126 static BOOL load_font_from_data_dir(LPCWSTR file)
1127 {
1128     BOOL ret = FALSE;
1129     const char *data_dir = wine_get_data_dir();
1130
1131     if (data_dir)
1132     {
1133         INT len;
1134         char *unix_name;
1135
1136         len = WideCharToMultiByte(CP_UNIXCP, 0, file, -1, NULL, 0, NULL, NULL);
1137
1138         unix_name = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + len + sizeof("/fonts/"));
1139
1140         strcpy(unix_name, data_dir);
1141         strcat(unix_name, "/fonts/");
1142
1143         WideCharToMultiByte(CP_UNIXCP, 0, file, -1, unix_name + strlen(unix_name), len, NULL, NULL);
1144
1145         ret = AddFontFileToList(unix_name, NULL, ADDFONT_FORCE_BITMAP);
1146         HeapFree(GetProcessHeap(), 0, unix_name);
1147     }
1148     return ret;
1149 }
1150
1151 static void load_system_fonts(void)
1152 {
1153     HKEY hkey;
1154     WCHAR data[MAX_PATH], windowsdir[MAX_PATH], pathW[MAX_PATH];
1155     const WCHAR **value;
1156     DWORD dlen, type;
1157     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
1158     char *unixname;
1159
1160     if(RegOpenKeyW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, &hkey) == ERROR_SUCCESS) {
1161         GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
1162         strcatW(windowsdir, fontsW);
1163         for(value = SystemFontValues; *value; value++) { 
1164             dlen = sizeof(data);
1165             if(RegQueryValueExW(hkey, *value, 0, &type, (void*)data, &dlen) == ERROR_SUCCESS &&
1166                type == REG_SZ) {
1167                 BOOL added = FALSE;
1168
1169                 sprintfW(pathW, fmtW, windowsdir, data);
1170                 if((unixname = wine_get_unix_file_name(pathW))) {
1171                     added = AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1172                     HeapFree(GetProcessHeap(), 0, unixname);
1173                 }
1174                 if (!added)
1175                     load_font_from_data_dir(data);
1176             }
1177         }
1178         RegCloseKey(hkey);
1179     }
1180 }
1181
1182 /*************************************************************
1183  *
1184  * This adds registry entries for any externally loaded fonts
1185  * (fonts from fontconfig or FontDirs).  It also deletes entries
1186  * of no longer existing fonts.
1187  *
1188  */
1189 static void update_reg_entries(void)
1190 {
1191     HKEY winkey = 0, externalkey = 0;
1192     LPWSTR valueW;
1193     LPVOID data;
1194     DWORD dlen, vlen, datalen, valuelen, i, type, len, len_fam;
1195     Family *family;
1196     Face *face;
1197     struct list *family_elem_ptr, *face_elem_ptr;
1198     WCHAR *file;
1199     static const WCHAR TrueType[] = {' ','(','T','r','u','e','T','y','p','e',')','\0'};
1200     static const WCHAR spaceW[] = {' ', '\0'};
1201     char *path;
1202
1203     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
1204                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &winkey, NULL) != ERROR_SUCCESS) {
1205         ERR("Can't create Windows font reg key\n");
1206         goto end;
1207     }
1208     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\ExternalFonts */
1209     if(RegCreateKeyW(HKEY_CURRENT_USER, external_fonts_reg_key, &externalkey) != ERROR_SUCCESS) {
1210         ERR("Can't create external font reg key\n");
1211         goto end;
1212     }
1213
1214     /* Delete all external fonts added last time */
1215
1216     RegQueryInfoKeyW(externalkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1217                      &valuelen, &datalen, NULL, NULL);
1218     valuelen++; /* returned value doesn't include room for '\0' */
1219     valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
1220     data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
1221
1222     dlen = datalen * sizeof(WCHAR);
1223     vlen = valuelen;
1224     i = 0;
1225     while(RegEnumValueW(externalkey, i++, valueW, &vlen, NULL, &type, data,
1226                         &dlen) == ERROR_SUCCESS) {
1227
1228         RegDeleteValueW(winkey, valueW);
1229         /* reset dlen and vlen */
1230         dlen = datalen;
1231         vlen = valuelen;
1232     }
1233     HeapFree(GetProcessHeap(), 0, data);
1234     HeapFree(GetProcessHeap(), 0, valueW);
1235
1236     /* Delete the old external fonts key */
1237     RegCloseKey(externalkey);
1238     externalkey = 0;
1239     RegDeleteKeyW(HKEY_CURRENT_USER, external_fonts_reg_key);
1240
1241     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\ExternalFonts */
1242     if(RegCreateKeyExW(HKEY_CURRENT_USER, external_fonts_reg_key,
1243                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &externalkey, NULL) != ERROR_SUCCESS) {
1244         ERR("Can't create external font reg key\n");
1245         goto end;
1246     }
1247
1248     /* enumerate the fonts and add external ones to the two keys */
1249
1250     LIST_FOR_EACH(family_elem_ptr, &font_list) {
1251         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
1252         len_fam = strlenW(family->FamilyName) + sizeof(TrueType) / sizeof(WCHAR) + 1;
1253         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
1254             face = LIST_ENTRY(face_elem_ptr, Face, entry);
1255             if(!face->external) continue;
1256             len = len_fam;
1257             if(strcmpiW(face->StyleName, RegularW))
1258                 len = len_fam + strlenW(face->StyleName) + 1;
1259             valueW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1260             strcpyW(valueW, family->FamilyName);
1261             if(len != len_fam) {
1262                 strcatW(valueW, spaceW);
1263                 strcatW(valueW, face->StyleName);
1264             }
1265             strcatW(valueW, TrueType);
1266             if((path = strrchr(face->file, '/')) == NULL)
1267                 path = face->file;
1268             else
1269                 path++;
1270             len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
1271
1272             file = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1273             MultiByteToWideChar(CP_ACP, 0, path, -1, file, len);
1274             RegSetValueExW(winkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
1275             RegSetValueExW(externalkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
1276
1277             HeapFree(GetProcessHeap(), 0, file);
1278             HeapFree(GetProcessHeap(), 0, valueW);
1279         }
1280     }
1281  end:
1282     if(externalkey)
1283         RegCloseKey(externalkey);
1284     if(winkey)
1285         RegCloseKey(winkey);
1286     return;
1287 }
1288
1289
1290 /*************************************************************
1291  *    WineEngAddFontResourceEx
1292  *
1293  */
1294 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
1295 {
1296     if (ft_handle)  /* do it only if we have freetype up and running */
1297     {
1298         char *unixname;
1299
1300         if(flags)
1301             FIXME("Ignoring flags %lx\n", flags);
1302
1303         if((unixname = wine_get_unix_file_name(file)))
1304         {
1305             AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1306             HeapFree(GetProcessHeap(), 0, unixname);
1307         }
1308     }
1309     return 1;
1310 }
1311
1312 /*************************************************************
1313  *    WineEngRemoveFontResourceEx
1314  *
1315  */
1316 BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
1317 {
1318     FIXME(":stub\n");
1319     return TRUE;
1320 }
1321
1322 static const struct nls_update_font_list
1323 {
1324     UINT ansi_cp, oem_cp;
1325     const char *oem, *fixed, *system;
1326     const char *courier, *serif, *small, *sserif;
1327 } nls_update_font_list[] =
1328 {
1329     /* Latin 1 (United States) */
1330     { 1252, 437, "vgaoem.fon", "vgafix.fon", "vgasys.fon",
1331       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1332     },
1333     /* Latin 1 (Multilingual) */
1334     { 1252, 850, "vga850.fon", "vgafix.fon", "vgasys.fon",
1335       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1336     },
1337     /* Eastern Europe */
1338     { 1250, 852, "vga852.fon", "vgafixe.fon", "vgasyse.fon",
1339       "couree.fon", "serifee.fon", "smallee.fon", "sserifee.fon",
1340     },
1341     /* Cyrillic */
1342     { 1251, 866, "vga866.fon", "vgafixr.fon", "vgasysr.fon",
1343       "courer.fon", "serifer.fon", "smaller.fon", "sserifer.fon",
1344     },
1345     /* Greek */
1346     { 1253, 737, "vga869.fon", "vgafixg.fon", "vgasysg.fon",
1347       "coureg.fon", "serifeg.fon", "smalleg.fon", "sserifeg.fon",
1348     },
1349     /* Turkish */
1350     { 1254, 857, "vga857.fon", "vgafixt.fon", "vgasyst.fon",
1351       "couret.fon", "serifet.fon", "smallet.fon", "sserifet.fon",
1352     },
1353     /* Hebrew */
1354     { 1255, 862, "vgaoem.fon", "vgaf1255.fon", "vgas1255.fon",
1355       "coue1255.fon", "sere1255.fon", "smae1255.fon", "ssee1255.fon",
1356     },
1357     /* Arabic */
1358     { 1256, 720, "vgaoem.fon", "vgaf1256.fon", "vgas1256.fon",
1359       "coue1256.fon", "sere1256.fon", "smae1256.fon", "ssee1256.fon",
1360     },
1361     /* Baltic */
1362     { 1257, 775, "vga775.fon", "vgaf1257.fon", "vgas1257.fon",
1363       "coue1257.fon", "sere1257.fon", "smae1257.fon", "ssee1257.fon",
1364     },
1365     /* Vietnamese */
1366     { 1258, 1258, "vga850.fon", "vgafix.fon", "vgasys.fon",
1367       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1368     },
1369     /* Thai */
1370     { 874, 874, "vga850.fon", "vgaf874.fon", "vgas874.fon",
1371       "coure.fon", "serife.fon", "smalle.fon", "ssee874.fon",
1372     },
1373     /* Japanese */
1374     { 932, 932, "vga932.fon", "jvgafix.fon", "jvgasys.fon",
1375       "coure.fon", "serife.fon", "jsmalle.fon", "sserife.fon",
1376     },
1377     /* Chinese Simplified */
1378     { 936, 936, "vga936.fon", "svgafix.fon", "svgasys.fon",
1379       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1380     },
1381     /* Korean */
1382     { 949, 949, "vga949.fon", "hvgafix.fon", "hvgasys.fon",
1383       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1384     },
1385     /* Chinese Traditional */
1386     { 950, 950, "vga950.fon", "cvgafix.fon", "cvgasys.fon",
1387       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1388     }
1389 };
1390
1391 inline static HKEY create_fonts_NT_registry_key(void)
1392 {
1393     HKEY hkey = 0;
1394
1395     RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key, 0, NULL,
1396                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
1397     return hkey;
1398 }
1399
1400 inline static HKEY create_fonts_9x_registry_key(void)
1401 {
1402     HKEY hkey = 0;
1403
1404     RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key, 0, NULL,
1405                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
1406     return hkey;
1407 }
1408
1409 inline static HKEY create_config_fonts_registry_key(void)
1410 {
1411     HKEY hkey = 0;
1412
1413     RegCreateKeyExW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, 0, NULL,
1414                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
1415     return hkey;
1416 }
1417
1418 static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl)
1419 {
1420     RegSetValueExA(hkey, "Courier", 0, REG_SZ, (const BYTE *)fl->courier, strlen(fl->courier)+1);
1421     RegSetValueExA(hkey, "MS Serif", 0, REG_SZ, (const BYTE *)fl->serif, strlen(fl->serif)+1);
1422     RegSetValueExA(hkey, "MS Sans Serif", 0, REG_SZ, (const BYTE *)fl->sserif, strlen(fl->sserif)+1);
1423     RegSetValueExA(hkey, "Small Fonts", 0, REG_SZ, (const BYTE *)fl->small, strlen(fl->small)+1);
1424 }
1425
1426 static void update_font_info(void)
1427 {
1428     char buf[80];
1429     DWORD len, type;
1430     HKEY hkey = 0;
1431     UINT i, ansi_cp = 0, oem_cp = 0;
1432     LCID lcid = GetUserDefaultLCID();
1433
1434     if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", &hkey) != ERROR_SUCCESS)
1435         return;
1436
1437     len = sizeof(buf);
1438     if (RegQueryValueExA(hkey, "Locale", 0, &type, (BYTE *)buf, &len) == ERROR_SUCCESS && type == REG_SZ)
1439     {
1440         if (strtoul(buf, NULL, 16 ) == lcid)  /* already set correctly */
1441         {
1442             RegCloseKey(hkey);
1443             return;
1444         }
1445         TRACE("updating registry, locale changed %s -> %08lx\n", debugstr_a(buf), lcid);
1446     }
1447     else TRACE("updating registry, locale changed none -> %08lx\n", lcid);
1448
1449     sprintf(buf, "%08lx", lcid);
1450     RegSetValueExA(hkey, "Locale", 0, REG_SZ, (const BYTE *)buf, strlen(buf)+1);
1451     RegCloseKey(hkey);
1452
1453     GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
1454                    (WCHAR *)&ansi_cp, sizeof(ansi_cp)/sizeof(WCHAR));
1455     GetLocaleInfoW(lcid, LOCALE_IDEFAULTCODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
1456                    (WCHAR *)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR));
1457
1458     for (i = 0; i < sizeof(nls_update_font_list)/sizeof(nls_update_font_list[0]); i++)
1459     {
1460         if (nls_update_font_list[i].ansi_cp == ansi_cp &&
1461             nls_update_font_list[i].oem_cp == oem_cp)
1462         {
1463             HKEY hkey;
1464
1465             hkey = create_config_fonts_registry_key();
1466             RegSetValueExA(hkey, "OEMFONT.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].oem, strlen(nls_update_font_list[i].oem)+1);
1467             RegSetValueExA(hkey, "FIXED.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].fixed, strlen(nls_update_font_list[i].fixed)+1);
1468             RegSetValueExA(hkey, "FONTS.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].system, strlen(nls_update_font_list[i].system)+1);
1469             RegCloseKey(hkey);
1470
1471             hkey = create_fonts_NT_registry_key();
1472             add_font_list(hkey, &nls_update_font_list[i]);
1473             RegCloseKey(hkey);
1474
1475             hkey = create_fonts_9x_registry_key();
1476             add_font_list(hkey, &nls_update_font_list[i]);
1477             RegCloseKey(hkey);
1478
1479             return;
1480         }
1481     }
1482     FIXME("there is no font defaults for lcid %04lx/ansi_cp %u", lcid, ansi_cp);
1483 }
1484
1485 /*************************************************************
1486  *    WineEngInit
1487  *
1488  * Initialize FreeType library and create a list of available faces
1489  */
1490 BOOL WineEngInit(void)
1491 {
1492     static const WCHAR dot_fonW[] = {'.','f','o','n','\0'};
1493     static const WCHAR pathW[] = {'P','a','t','h',0};
1494     HKEY hkey;
1495     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
1496     LPVOID data;
1497     WCHAR windowsdir[MAX_PATH];
1498     char *unixname;
1499     HANDLE font_mutex;
1500
1501     TRACE("\n");
1502
1503     /* update locale dependent font info in registry */
1504     update_font_info();
1505
1506     ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0);
1507     if(!ft_handle) {
1508         WINE_MESSAGE(
1509       "Wine cannot find the FreeType font library.  To enable Wine to\n"
1510       "use TrueType fonts please install a version of FreeType greater than\n"
1511       "or equal to 2.0.5.\n"
1512       "http://www.freetype.org\n");
1513         return FALSE;
1514     }
1515
1516 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(ft_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
1517
1518     LOAD_FUNCPTR(FT_Vector_Unit)
1519     LOAD_FUNCPTR(FT_Done_Face)
1520     LOAD_FUNCPTR(FT_Get_Char_Index)
1521     LOAD_FUNCPTR(FT_Get_Module)
1522     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
1523     LOAD_FUNCPTR(FT_Init_FreeType)
1524     LOAD_FUNCPTR(FT_Load_Glyph)
1525     LOAD_FUNCPTR(FT_Matrix_Multiply)
1526     LOAD_FUNCPTR(FT_MulFix)
1527     LOAD_FUNCPTR(FT_New_Face)
1528     LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
1529     LOAD_FUNCPTR(FT_Outline_Transform)
1530     LOAD_FUNCPTR(FT_Outline_Translate)
1531     LOAD_FUNCPTR(FT_Select_Charmap)
1532     LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
1533     LOAD_FUNCPTR(FT_Vector_Transform)
1534
1535 #undef LOAD_FUNCPTR
1536     /* Don't warn if this one is missing */
1537     pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0);
1538     pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0);
1539     pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0);
1540     pFT_Get_TrueType_Engine_Type = wine_dlsym(ft_handle, "FT_Get_TrueType_Engine_Type", NULL, 0);
1541 #ifdef HAVE_FREETYPE_FTWINFNT_H
1542     pFT_Get_WinFNT_Header = wine_dlsym(ft_handle, "FT_Get_WinFNT_Header", NULL, 0);
1543 #endif
1544       if(!wine_dlsym(ft_handle, "FT_Get_Postscript_Name", NULL, 0) &&
1545          !wine_dlsym(ft_handle, "FT_Sqrt64", NULL, 0)) {
1546         /* try to avoid 2.0.4: >= 2.0.5 has FT_Get_Postscript_Name and
1547            <= 2.0.3 has FT_Sqrt64 */
1548           goto sym_not_found;
1549       }
1550
1551     if(pFT_Init_FreeType(&library) != 0) {
1552         ERR("Can't init FreeType library\n");
1553         wine_dlclose(ft_handle, NULL, 0);
1554         ft_handle = NULL;
1555         return FALSE;
1556     }
1557     FT_Version.major=FT_Version.minor=FT_Version.patch=-1;
1558     if (pFT_Library_Version)
1559     {
1560         pFT_Library_Version(library,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
1561     }
1562     if (FT_Version.major<=0)
1563     {
1564         FT_Version.major=2;
1565         FT_Version.minor=0;
1566         FT_Version.patch=5;
1567     }
1568     TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
1569     FT_SimpleVersion = ((FT_Version.major << 16) & 0xff0000) |
1570                        ((FT_Version.minor <<  8) & 0x00ff00) |
1571                        ((FT_Version.patch      ) & 0x0000ff);
1572
1573     if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) {
1574         ERR("Failed to create font mutex\n");
1575         return FALSE;
1576     }
1577     WaitForSingleObject(font_mutex, INFINITE);
1578
1579     /* load the system fonts */
1580     load_system_fonts();
1581
1582     /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
1583     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
1584     strcatW(windowsdir, fontsW);
1585     if((unixname = wine_get_unix_file_name(windowsdir)))
1586     {
1587         ReadFontDir(unixname, FALSE);
1588         HeapFree(GetProcessHeap(), 0, unixname);
1589     }
1590
1591     /* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
1592        for any fonts not installed in %WINDOWSDIR%\Fonts.  They will have their
1593        full path as the entry.  Also look for any .fon fonts, since ReadFontDir
1594        will skip these. */
1595     if(RegOpenKeyW(HKEY_LOCAL_MACHINE,
1596                    is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
1597                    &hkey) == ERROR_SUCCESS) {
1598         LPWSTR valueW;
1599         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1600                          &valuelen, &datalen, NULL, NULL);
1601
1602         valuelen++; /* returned value doesn't include room for '\0' */
1603         valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
1604         data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
1605         if (valueW && data)
1606         {
1607             dlen = datalen * sizeof(WCHAR);
1608             vlen = valuelen;
1609             while(RegEnumValueW(hkey, i++, valueW, &vlen, NULL, &type, data,
1610                                 &dlen) == ERROR_SUCCESS) {
1611                 if(((LPWSTR)data)[0] && ((LPWSTR)data)[1] == ':')
1612                 {
1613                     if((unixname = wine_get_unix_file_name((LPWSTR)data)))
1614                     {
1615                         AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1616                         HeapFree(GetProcessHeap(), 0, unixname);
1617                     }
1618                 }
1619                 else if(dlen / 2 >= 6 && !strcmpiW(((LPWSTR)data) + dlen / 2 - 5, dot_fonW))
1620                 {
1621                     WCHAR pathW[MAX_PATH];
1622                     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
1623                     BOOL added = FALSE;
1624
1625                     sprintfW(pathW, fmtW, windowsdir, data);
1626                     if((unixname = wine_get_unix_file_name(pathW)))
1627                     {
1628                         added = AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1629                         HeapFree(GetProcessHeap(), 0, unixname);
1630                     }
1631                     if (!added)
1632                         load_font_from_data_dir(data);
1633                 }
1634                 /* reset dlen and vlen */
1635                 dlen = datalen;
1636                 vlen = valuelen;
1637             }
1638         }
1639         HeapFree(GetProcessHeap(), 0, data);
1640         HeapFree(GetProcessHeap(), 0, valueW);
1641         RegCloseKey(hkey);
1642     }
1643
1644     load_fontconfig_fonts();
1645
1646     /* then look in any directories that we've specified in the config file */
1647     /* @@ Wine registry key: HKCU\Software\Wine\Fonts */
1648     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", &hkey) == ERROR_SUCCESS)
1649     {
1650         DWORD len;
1651         LPWSTR valueW;
1652         LPSTR valueA, ptr;
1653
1654         if (RegQueryValueExW( hkey, pathW, NULL, NULL, NULL, &len ) == ERROR_SUCCESS)
1655         {
1656             len += sizeof(WCHAR);
1657             valueW = HeapAlloc( GetProcessHeap(), 0, len );
1658             if (RegQueryValueExW( hkey, pathW, NULL, NULL, (LPBYTE)valueW, &len ) == ERROR_SUCCESS)
1659             {
1660                 len = WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, NULL, 0, NULL, NULL );
1661                 valueA = HeapAlloc( GetProcessHeap(), 0, len );
1662                 WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, valueA, len, NULL, NULL );
1663                 TRACE( "got font path %s\n", debugstr_a(valueA) );
1664                 ptr = valueA;
1665                 while (ptr)
1666                 {
1667                     LPSTR next = strchr( ptr, ':' );
1668                     if (next) *next++ = 0;
1669                     ReadFontDir( ptr, TRUE );
1670                     ptr = next;
1671                 }
1672                 HeapFree( GetProcessHeap(), 0, valueA );
1673             }
1674             HeapFree( GetProcessHeap(), 0, valueW );
1675         }
1676         RegCloseKey(hkey);
1677     }
1678
1679     DumpFontList();
1680     LoadSubstList();
1681     DumpSubstList();
1682     LoadReplaceList();
1683     update_reg_entries();
1684
1685     init_system_links();
1686     
1687     ReleaseMutex(font_mutex);
1688     return TRUE;
1689 sym_not_found:
1690     WINE_MESSAGE(
1691       "Wine cannot find certain functions that it needs inside the FreeType\n"
1692       "font library.  To enable Wine to use TrueType fonts please upgrade\n"
1693       "FreeType to at least version 2.0.5.\n"
1694       "http://www.freetype.org\n");
1695     wine_dlclose(ft_handle, NULL, 0);
1696     ft_handle = NULL;
1697     return FALSE;
1698 }
1699
1700
1701 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
1702 {
1703     TT_OS2 *pOS2;
1704     TT_HoriHeader *pHori;
1705
1706     LONG ppem;
1707
1708     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
1709     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
1710
1711     if(height == 0) height = 16;
1712
1713     /* Calc. height of EM square:
1714      *
1715      * For +ve lfHeight we have
1716      * lfHeight = (winAscent + winDescent) * ppem / units_per_em
1717      * Re-arranging gives:
1718      * ppem = units_per_em * lfheight / (winAscent + winDescent)
1719      *
1720      * For -ve lfHeight we have
1721      * |lfHeight| = ppem
1722      * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
1723      * with il = winAscent + winDescent - units_per_em]
1724      *
1725      */
1726
1727     if(height > 0) {
1728         if(pOS2->usWinAscent + pOS2->usWinDescent == 0)
1729             ppem = ft_face->units_per_EM * height /
1730                 (pHori->Ascender - pHori->Descender);
1731         else
1732             ppem = ft_face->units_per_EM * height /
1733                 (pOS2->usWinAscent + pOS2->usWinDescent);
1734     }
1735     else
1736         ppem = -height;
1737
1738     return ppem;
1739 }
1740
1741 static LONG load_VDMX(GdiFont, LONG);
1742
1743 static FT_Face OpenFontFile(GdiFont font, char *file, FT_Long face_index, LONG width, LONG height)
1744 {
1745     FT_Error err;
1746     FT_Face ft_face;
1747
1748     TRACE("%s, %ld, %ld x %ld\n", debugstr_a(file), face_index, width, height);
1749     err = pFT_New_Face(library, file, face_index, &ft_face);
1750     if(err) {
1751         ERR("FT_New_Face rets %d\n", err);
1752         return 0;
1753     }
1754
1755     /* set it here, as load_VDMX needs it */
1756     font->ft_face = ft_face;
1757
1758     if(FT_IS_SCALABLE(ft_face)) {
1759         /* load the VDMX table if we have one */
1760         font->ppem = load_VDMX(font, height);
1761         if(font->ppem == 0)
1762             font->ppem = calc_ppem_for_height(ft_face, height);
1763
1764         if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0)
1765             WARN("FT_Set_Pixel_Sizes %d, %ld rets %x\n", 0, font->ppem, err);
1766     } else {
1767         font->ppem = height;
1768         if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
1769             WARN("FT_Set_Pixel_Sizes %ld, %ld rets %x\n", width, height, err);
1770     }
1771     return ft_face;
1772 }
1773
1774
1775 static int get_nearest_charset(Face *face, int *cp)
1776 {
1777   /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
1778      a single face with the requested charset.  The idea is to check if
1779      the selected font supports the current ANSI codepage, if it does
1780      return the corresponding charset, else return the first charset */
1781
1782     CHARSETINFO csi;
1783     int acp = GetACP(), i;
1784     DWORD fs0;
1785
1786     *cp = acp;
1787     if(TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE))
1788         if(csi.fs.fsCsb[0] & face->fs.fsCsb[0])
1789             return csi.ciCharset;
1790
1791     for(i = 0; i < 32; i++) {
1792         fs0 = 1L << i;
1793         if(face->fs.fsCsb[0] & fs0) {
1794             if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG)) {
1795                 *cp = csi.ciACP;
1796                 return csi.ciCharset;
1797             }
1798             else
1799                 FIXME("TCI failing on %lx\n", fs0);
1800         }
1801     }
1802
1803     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08lx file = %s\n",
1804           face->fs.fsCsb[0], face->file);
1805     *cp = acp;
1806     return DEFAULT_CHARSET;
1807 }
1808
1809 static GdiFont alloc_font(void)
1810 {
1811     GdiFont ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
1812     ret->gmsize = INIT_GM_SIZE;
1813     ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1814                         ret->gmsize * sizeof(*ret->gm));
1815     ret->potm = NULL;
1816     ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
1817     list_init(&ret->hfontlist);
1818     list_init(&ret->child_fonts);
1819     return ret;
1820 }
1821
1822 static void free_font(GdiFont font)
1823 {
1824     struct list *cursor, *cursor2;
1825
1826     LIST_FOR_EACH_SAFE(cursor, cursor2, &font->child_fonts)
1827     {
1828         CHILD_FONT *child = LIST_ENTRY(cursor, CHILD_FONT, entry);
1829         struct list *first_hfont;
1830         HFONTLIST *hfontlist;
1831         list_remove(cursor);
1832         if(child->font)
1833         {
1834             first_hfont = list_head(&child->font->hfontlist);
1835             hfontlist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
1836             DeleteObject(hfontlist->hfont);
1837             HeapFree(GetProcessHeap(), 0, hfontlist);
1838             free_font(child->font);
1839         }
1840         HeapFree(GetProcessHeap(), 0, child->file_name);
1841         HeapFree(GetProcessHeap(), 0, child);
1842     }
1843
1844     if (font->ft_face) pFT_Done_Face(font->ft_face);
1845     HeapFree(GetProcessHeap(), 0, font->potm);
1846     HeapFree(GetProcessHeap(), 0, font->name);
1847     HeapFree(GetProcessHeap(), 0, font->gm);
1848     HeapFree(GetProcessHeap(), 0, font);
1849 }
1850
1851
1852 /*************************************************************
1853  * load_VDMX
1854  *
1855  * load the vdmx entry for the specified height
1856  */
1857
1858 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
1859           ( ( (FT_ULong)_x4 << 24 ) |     \
1860             ( (FT_ULong)_x3 << 16 ) |     \
1861             ( (FT_ULong)_x2 <<  8 ) |     \
1862               (FT_ULong)_x1         )
1863
1864 #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X')
1865
1866 typedef struct {
1867     BYTE bCharSet;
1868     BYTE xRatio;
1869     BYTE yStartRatio;
1870     BYTE yEndRatio;
1871 } Ratios;
1872
1873
1874 static LONG load_VDMX(GdiFont font, LONG height)
1875 {
1876     BYTE hdr[6], tmp[2], group[4];
1877     BYTE devXRatio, devYRatio;
1878     USHORT numRecs, numRatios;
1879     DWORD result, offset = -1;
1880     LONG ppem = 0;
1881     int i;
1882
1883     /* For documentation on VDMX records, see
1884      * http://www.microsoft.com/OpenType/OTSpec/vdmx.htm
1885      */
1886
1887     result = WineEngGetFontData(font, MS_VDMX_TAG, 0, hdr, 6);
1888
1889     if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
1890         return ppem;
1891
1892     /* FIXME: need the real device aspect ratio */
1893     devXRatio = 1;
1894     devYRatio = 1;
1895
1896     numRecs = GET_BE_WORD(&hdr[2]);
1897     numRatios = GET_BE_WORD(&hdr[4]);
1898
1899     TRACE("numRecs = %d numRatios = %d\n", numRecs, numRatios);
1900     for(i = 0; i < numRatios; i++) {
1901         Ratios ratio;
1902
1903         offset = (3 * 2) + (i * sizeof(Ratios));
1904         WineEngGetFontData(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
1905         offset = -1;
1906
1907         TRACE("Ratios[%d] %d  %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
1908
1909         if((ratio.xRatio == 0 &&
1910             ratio.yStartRatio == 0 &&
1911             ratio.yEndRatio == 0) ||
1912            (devXRatio == ratio.xRatio &&
1913             devYRatio >= ratio.yStartRatio &&
1914             devYRatio <= ratio.yEndRatio))
1915             {
1916                 offset = (3 * 2) + (numRatios * 4) + (i * 2);
1917                 WineEngGetFontData(font, MS_VDMX_TAG, offset, tmp, 2);
1918                 offset = GET_BE_WORD(tmp);
1919                 break;
1920             }
1921     }
1922
1923     if(offset == -1) {
1924         FIXME("No suitable ratio found\n");
1925         return ppem;
1926     }
1927
1928     if(WineEngGetFontData(font, MS_VDMX_TAG, offset, group, 4) != GDI_ERROR) {
1929         USHORT recs;
1930         BYTE startsz, endsz;
1931         BYTE *vTable;
1932
1933         recs = GET_BE_WORD(group);
1934         startsz = group[2];
1935         endsz = group[3];
1936
1937         TRACE("recs=%d  startsz=%d  endsz=%d\n", recs, startsz, endsz);
1938
1939         vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6);
1940         result = WineEngGetFontData(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6);
1941         if(result == GDI_ERROR) {
1942             FIXME("Failed to retrieve vTable\n");
1943             goto end;
1944         }
1945
1946         if(height > 0) {
1947             for(i = 0; i < recs; i++) {
1948                 SHORT yMax = GET_BE_WORD(&vTable[(i * 6) + 2]);
1949                 SHORT yMin = GET_BE_WORD(&vTable[(i * 6) + 4]);
1950                 ppem = GET_BE_WORD(&vTable[i * 6]);
1951
1952                 if(yMax + -yMin == height) {
1953                     font->yMax = yMax;
1954                     font->yMin = yMin;
1955                     TRACE("ppem %ld found; height=%ld  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
1956                     break;
1957                 }
1958                 if(yMax + -yMin > height) {
1959                     if(--i < 0) {
1960                         ppem = 0;
1961                         goto end; /* failed */
1962                     }
1963                     font->yMax = GET_BE_WORD(&vTable[(i * 6) + 2]);
1964                     font->yMin = GET_BE_WORD(&vTable[(i * 6) + 4]);
1965                     TRACE("ppem %ld found; height=%ld  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
1966                     break;
1967                 }
1968             }
1969             if(!font->yMax) {
1970                 ppem = 0;
1971                 TRACE("ppem not found for height %ld\n", height);
1972             }
1973         } else {
1974             ppem = -height;
1975             if(ppem < startsz || ppem > endsz)
1976                 goto end;
1977
1978             for(i = 0; i < recs; i++) {
1979                 USHORT yPelHeight;
1980                 yPelHeight = GET_BE_WORD(&vTable[i * 6]);
1981
1982                 if(yPelHeight > ppem)
1983                     break; /* failed */
1984
1985                 if(yPelHeight == ppem) {
1986                     font->yMax = GET_BE_WORD(&vTable[(i * 6) + 2]);
1987                     font->yMin = GET_BE_WORD(&vTable[(i * 6) + 4]);
1988                     TRACE("ppem %ld found; yMax=%d  yMin=%d\n", ppem, font->yMax, font->yMin);
1989                     break;
1990                 }
1991             }
1992         }
1993         end:
1994         HeapFree(GetProcessHeap(), 0, vTable);
1995     }
1996
1997     return ppem;
1998 }
1999
2000 static BOOL fontcmp(GdiFont font, FONT_DESC *fd)
2001 {
2002     if(font->font_desc.hash != fd->hash) return TRUE;
2003     if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE;
2004     if(memcmp(&font->font_desc.lf, &fd->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
2005     return strcmpiW(font->font_desc.lf.lfFaceName, fd->lf.lfFaceName);
2006 }
2007
2008 static void calc_hash(FONT_DESC *pfd)
2009 {
2010     DWORD hash = 0, *ptr, two_chars;
2011     WORD *pwc;
2012     unsigned int i;
2013
2014     for(i = 0, ptr = (DWORD*)&pfd->matrix; i < sizeof(FMAT2)/sizeof(DWORD); i++, ptr++)
2015         hash ^= *ptr;
2016     for(i = 0, ptr = (DWORD*)&pfd->lf; i < 7; i++, ptr++)
2017         hash ^= *ptr;
2018     for(i = 0, ptr = (DWORD*)&pfd->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
2019         two_chars = *ptr;
2020         pwc = (WCHAR *)&two_chars;
2021         if(!*pwc) break;
2022         *pwc = toupperW(*pwc);
2023         pwc++;
2024         *pwc = toupperW(*pwc);
2025         hash ^= two_chars;
2026         if(!*pwc) break;
2027     }
2028     pfd->hash = hash;
2029     return;
2030 }
2031
2032 static GdiFont find_in_cache(HFONT hfont, LOGFONTW *plf, XFORM *pxf, BOOL can_use_bitmap)
2033 {
2034     GdiFont ret;
2035     FONT_DESC fd;
2036     HFONTLIST *hflist;
2037     struct list *font_elem_ptr, *hfontlist_elem_ptr;
2038
2039     memcpy(&fd.lf, plf, sizeof(LOGFONTW));
2040     memcpy(&fd.matrix, pxf, sizeof(FMAT2));
2041     calc_hash(&fd);
2042
2043     /* try the in-use list */
2044     LIST_FOR_EACH(font_elem_ptr, &gdi_font_list) {
2045         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2046         if(!fontcmp(ret, &fd)) {
2047             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
2048             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
2049                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
2050                 if(hflist->hfont == hfont)
2051                     return ret;
2052             }
2053             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
2054             hflist->hfont = hfont;
2055             list_add_head(&ret->hfontlist, &hflist->entry);
2056             return ret;
2057         }
2058     }
2059  
2060     /* then the unused list */
2061     font_elem_ptr = list_head(&unused_gdi_font_list);
2062     while(font_elem_ptr) {
2063         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2064         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
2065         if(!fontcmp(ret, &fd)) {
2066             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
2067             assert(list_empty(&ret->hfontlist));
2068             TRACE("Found %p in unused list\n", ret);
2069             list_remove(&ret->entry);
2070             list_add_head(&gdi_font_list, &ret->entry);
2071             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
2072             hflist->hfont = hfont;
2073             list_add_head(&ret->hfontlist, &hflist->entry);
2074             return ret;
2075         }
2076     }
2077     return NULL;
2078 }
2079
2080     
2081 /*************************************************************
2082  * create_child_font_list
2083  */
2084 static BOOL create_child_font_list(GdiFont font)
2085 {
2086     BOOL ret = FALSE;
2087     SYSTEM_LINKS *font_link;
2088     CHILD_FONT *font_link_entry, *new_child;
2089
2090     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
2091     {
2092         if(!strcmpW(font_link->font_name, font->name))
2093         {
2094             TRACE("found entry in system list\n");
2095             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
2096             {
2097                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
2098                 new_child->file_name = strdupA(font_link_entry->file_name);
2099                 new_child->index = font_link_entry->index;
2100                 new_child->font = NULL;
2101                 list_add_tail(&font->child_fonts, &new_child->entry);
2102                 TRACE("font %s %d\n", debugstr_a(new_child->file_name), new_child->index); 
2103             }
2104             ret = TRUE;
2105             break;
2106         }
2107     }
2108
2109     return ret;
2110 }
2111
2112 /*************************************************************
2113  * WineEngCreateFontInstance
2114  *
2115  */
2116 GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
2117 {
2118     GdiFont ret;
2119     Face *face, *best;
2120     Family *family, *last_resort_family;
2121     struct list *family_elem_ptr, *face_elem_ptr;
2122     INT height, width = 0;
2123     signed int diff = 0, newdiff;
2124     BOOL bd, it, can_use_bitmap;
2125     LOGFONTW lf;
2126     CHARSETINFO csi;
2127     HFONTLIST *hflist;
2128
2129     LIST_FOR_EACH_ENTRY(ret, &child_font_list, struct tagGdiFont, entry)
2130     {
2131         struct list *first_hfont = list_head(&ret->hfontlist);
2132         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
2133         if(hflist->hfont == hfont)
2134             return ret;
2135     }
2136
2137     if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
2138     can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
2139
2140     TRACE("%s, h=%ld, it=%d, weight=%ld, PandF=%02x, charset=%d orient %ld escapement %ld\n",
2141           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
2142           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
2143           lf.lfEscapement);
2144
2145     /* check the cache first */
2146     if((ret = find_in_cache(hfont, &lf, &dc->xformWorld2Vport, can_use_bitmap)) != NULL) {
2147         TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
2148         return ret;
2149     }
2150
2151     TRACE("not in cache\n");
2152     if(list_empty(&font_list)) /* No fonts installed */
2153     {
2154         TRACE("No fonts installed\n");
2155         return NULL;
2156     }
2157     if(!have_installed_roman_font)
2158     {
2159         TRACE("No roman font installed\n");
2160         return NULL;
2161     }
2162
2163     ret = alloc_font();
2164
2165      memcpy(&ret->font_desc.matrix, &dc->xformWorld2Vport, sizeof(FMAT2));
2166      memcpy(&ret->font_desc.lf, &lf, sizeof(LOGFONTW));
2167      calc_hash(&ret->font_desc);
2168      hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
2169      hflist->hfont = hfont;
2170      list_add_head(&ret->hfontlist, &hflist->entry);
2171
2172
2173     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
2174        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
2175        original value lfCharSet.  Note this is a special case for
2176        Symbol and doesn't happen at least for "Wingdings*" */
2177
2178     if(!strcmpiW(lf.lfFaceName, SymbolW))
2179         lf.lfCharSet = SYMBOL_CHARSET;
2180
2181     if(!TranslateCharsetInfo((DWORD*)(INT)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
2182         switch(lf.lfCharSet) {
2183         case DEFAULT_CHARSET:
2184             csi.fs.fsCsb[0] = 0;
2185             break;
2186         default:
2187             FIXME("Untranslated charset %d\n", lf.lfCharSet);
2188             csi.fs.fsCsb[0] = 0;
2189             break;
2190         }
2191     }
2192
2193     family = NULL;
2194     if(lf.lfFaceName[0] != '\0') {
2195         FontSubst *psub;
2196         for(psub = substlist; psub; psub = psub->next)
2197             if(!strcmpiW(lf.lfFaceName, psub->from.name) &&
2198                (psub->from.charset == -1 ||
2199                 psub->from.charset == lf.lfCharSet))
2200               break;
2201         if(psub) {
2202             TRACE("substituting %s -> %s\n", debugstr_w(lf.lfFaceName),
2203                   debugstr_w(psub->to.name));
2204             strcpyW(lf.lfFaceName, psub->to.name);
2205         }
2206
2207         /* We want a match on name and charset or just name if
2208            charset was DEFAULT_CHARSET.  If the latter then
2209            we fixup the returned charset later in get_nearest_charset
2210            where we'll either use the charset of the current ansi codepage
2211            or if that's unavailable the first charset that the font supports.
2212         */
2213         LIST_FOR_EACH(family_elem_ptr, &font_list) {
2214             family = LIST_ENTRY(family_elem_ptr, Family, entry);
2215             if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
2216                 LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2217                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
2218                     if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
2219                         if(face->scalable || can_use_bitmap)
2220                             goto found;
2221                 }
2222             }
2223         }
2224     }
2225
2226     /* If requested charset was DEFAULT_CHARSET then try using charset
2227        corresponding to the current ansi codepage */
2228     if(!csi.fs.fsCsb[0]) {
2229         INT acp = GetACP();
2230         if(!TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE)) {
2231             FIXME("TCI failed on codepage %d\n", acp);
2232             csi.fs.fsCsb[0] = 0;
2233         } else
2234             lf.lfCharSet = csi.ciCharset;
2235     }
2236
2237     /* Face families are in the top 4 bits of lfPitchAndFamily,
2238        so mask with 0xF0 before testing */
2239
2240     if((lf.lfPitchAndFamily & FIXED_PITCH) ||
2241        (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
2242         strcpyW(lf.lfFaceName, defFixed);
2243     else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
2244         strcpyW(lf.lfFaceName, defSerif);
2245     else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
2246         strcpyW(lf.lfFaceName, defSans);
2247     else
2248         strcpyW(lf.lfFaceName, defSans);
2249     LIST_FOR_EACH(family_elem_ptr, &font_list) {
2250         family = LIST_ENTRY(family_elem_ptr, Family, entry);
2251         if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
2252             LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2253                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
2254                 if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
2255                     if(face->scalable || can_use_bitmap)
2256                         goto found;
2257             }
2258         }
2259     }
2260
2261     last_resort_family = NULL;
2262     LIST_FOR_EACH(family_elem_ptr, &font_list) {
2263         family = LIST_ENTRY(family_elem_ptr, Family, entry);
2264         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2265             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2266             if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) {
2267                 if(face->scalable)
2268                     goto found;
2269                 if(can_use_bitmap && !last_resort_family)
2270                     last_resort_family = family;
2271             }            
2272         }
2273     }
2274
2275     if(last_resort_family) {
2276         family = last_resort_family;
2277         csi.fs.fsCsb[0] = 0;
2278         goto found;
2279     }
2280
2281     LIST_FOR_EACH(family_elem_ptr, &font_list) {
2282         family = LIST_ENTRY(family_elem_ptr, Family, entry);
2283         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2284             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2285             if(face->scalable) {
2286                 csi.fs.fsCsb[0] = 0;
2287                 FIXME("just using first face for now\n");
2288                 goto found;
2289             }
2290             if(can_use_bitmap && !last_resort_family)
2291                 last_resort_family = family;
2292         }
2293     }
2294     if(!last_resort_family) {
2295         FIXME("can't find a single appropriate font - bailing\n");
2296         free_font(ret);
2297         return NULL;
2298     }
2299
2300     WARN("could only find a bitmap font - this will probably look awful!\n");
2301     family = last_resort_family;
2302     csi.fs.fsCsb[0] = 0;
2303
2304 found:
2305     it = lf.lfItalic ? 1 : 0;
2306     bd = lf.lfWeight > 550 ? 1 : 0;
2307
2308     height = GDI_ROUND( (FLOAT)lf.lfHeight * dc->xformWorld2Vport.eM22 );
2309     height = lf.lfHeight < 0 ? -abs(height) : abs(height);
2310
2311     face = best = NULL;
2312     LIST_FOR_EACH(face_elem_ptr, &family->faces) {
2313         face = LIST_ENTRY(face_elem_ptr, Face, entry);
2314         if(!(face->Italic ^ it) && !(face->Bold ^ bd) &&
2315            ((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])) {
2316             if(face->scalable)
2317                 break;
2318             if(height > 0)
2319                 newdiff = height - (signed int)(face->size.y_ppem >> 6);
2320             else
2321                 newdiff = -height - ((signed int)(face->size.y_ppem >> 6) - face->size.internal_leading);
2322             if(!best || (diff > 0 && newdiff < diff && newdiff >= 0) ||
2323                (diff < 0 && newdiff > diff)) {
2324                 TRACE("%ld is better for %d diff was %d\n", face->size.y_ppem >> 6, height, diff);
2325                 diff = newdiff;
2326                 best = face;
2327                 if(diff == 0)
2328                     break;
2329             }
2330         }
2331         face = NULL;
2332     }
2333     if(!face && best)
2334         face = best;
2335     else if(!face) {
2336         best = NULL;
2337         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
2338             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2339             if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0]) {
2340                 if(face->scalable)
2341                     break;
2342                 if(height > 0)
2343                     newdiff = height - (signed int)(face->size.y_ppem >> 6);
2344                 else
2345                     newdiff = -height - ((signed int)(face->size.y_ppem >> 6) - face->size.internal_leading);
2346                 if(!best || (diff > 0 && newdiff < diff && newdiff >= 0) ||
2347                    (diff < 0 && newdiff > diff)) {
2348                     TRACE("%ld is better for %d diff was %d\n", face->size.y_ppem >> 6, height, diff);
2349                     diff = newdiff;
2350                     best = face;
2351                     if(diff == 0)
2352                         break;
2353                 }
2354             }
2355             face = NULL;
2356         }
2357         if(!face && best)
2358             face = best;
2359         if(it && !face->Italic) ret->fake_italic = TRUE;
2360         if(bd && !face->Bold) ret->fake_bold = TRUE;
2361     }
2362
2363     memcpy(&ret->fs, &face->fs, sizeof(FONTSIGNATURE));
2364
2365     if(csi.fs.fsCsb[0]) {
2366         ret->charset = lf.lfCharSet;
2367         ret->codepage = csi.ciACP;
2368     }
2369     else
2370         ret->charset = get_nearest_charset(face, &ret->codepage);
2371
2372     TRACE("Chosen: %s %s (%s:%ld)\n", debugstr_w(family->FamilyName),
2373           debugstr_w(face->StyleName), face->file, face->face_index);
2374
2375     if(!face->scalable) {
2376         width = face->size.x_ppem >> 6;
2377         height = face->size.y_ppem >> 6;
2378     }
2379     ret->ft_face = OpenFontFile(ret, face->file, face->face_index, width, height);
2380
2381     if (!ret->ft_face)
2382     {
2383         free_font( ret );
2384         return 0;
2385     }
2386
2387     if (ret->charset == SYMBOL_CHARSET && 
2388         !pFT_Select_Charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) {
2389         /* No ops */
2390     }
2391     else if (!pFT_Select_Charmap(ret->ft_face, FT_ENCODING_UNICODE)) {
2392         /* No ops */
2393     }
2394     else {
2395         pFT_Select_Charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN);
2396     }
2397
2398     ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0;
2399     ret->name = strdupW(family->FamilyName);
2400     ret->underline = lf.lfUnderline ? 0xff : 0;
2401     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
2402     create_child_font_list(ret);
2403
2404     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
2405
2406     ret->aveWidth = FT_IS_SCALABLE(ret->ft_face) ? lf.lfWidth : 0;
2407     list_add_head(&gdi_font_list, &ret->entry);
2408     return ret;
2409 }
2410
2411 static void dump_gdi_font_list(void)
2412 {
2413     GdiFont gdiFont;
2414     struct list *elem_ptr;
2415
2416     TRACE("---------- gdiFont Cache ----------\n");
2417     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
2418         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
2419         TRACE("gdiFont=%p %s %ld\n",
2420               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
2421     }
2422
2423     TRACE("---------- Unused gdiFont Cache ----------\n");
2424     LIST_FOR_EACH(elem_ptr, &unused_gdi_font_list) {
2425         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
2426         TRACE("gdiFont=%p %s %ld\n",
2427               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
2428     }
2429 }
2430
2431 /*************************************************************
2432  * WineEngDestroyFontInstance
2433  *
2434  * free the gdiFont associated with this handle
2435  *
2436  */
2437 BOOL WineEngDestroyFontInstance(HFONT handle)
2438 {
2439     GdiFont gdiFont;
2440     HFONTLIST *hflist;
2441     BOOL ret = FALSE;
2442     struct list *font_elem_ptr, *hfontlist_elem_ptr;
2443     int i = 0;
2444
2445     LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry)
2446     {
2447         struct list *first_hfont = list_head(&gdiFont->hfontlist);
2448         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
2449         if(hflist->hfont == handle)
2450         {
2451             TRACE("removing child font %p from child list\n", gdiFont);
2452             list_remove(&gdiFont->entry);
2453             return TRUE;
2454         }
2455     }
2456
2457     TRACE("destroying hfont=%p\n", handle);
2458     if(TRACE_ON(font))
2459         dump_gdi_font_list();
2460
2461     font_elem_ptr = list_head(&gdi_font_list);
2462     while(font_elem_ptr) {
2463         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2464         font_elem_ptr = list_next(&gdi_font_list, font_elem_ptr);
2465
2466         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
2467         while(hfontlist_elem_ptr) {
2468             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
2469             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
2470             if(hflist->hfont == handle) {
2471                 list_remove(&hflist->entry);
2472                 HeapFree(GetProcessHeap(), 0, hflist);
2473                 ret = TRUE;
2474             }
2475         }
2476         if(list_empty(&gdiFont->hfontlist)) {
2477             TRACE("Moving to Unused list\n");
2478             list_remove(&gdiFont->entry);
2479             list_add_head(&unused_gdi_font_list, &gdiFont->entry);
2480         }
2481     }
2482
2483
2484     font_elem_ptr = list_head(&unused_gdi_font_list);
2485     while(font_elem_ptr && i++ < UNUSED_CACHE_SIZE)
2486         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
2487     while(font_elem_ptr) {
2488         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2489         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
2490         TRACE("freeing %p\n", gdiFont);
2491         list_remove(&gdiFont->entry);
2492         free_font(gdiFont);
2493     }
2494     return ret;
2495 }
2496
2497 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
2498                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
2499 {
2500     OUTLINETEXTMETRICW *potm = NULL;
2501     UINT size;
2502     TEXTMETRICW tm, *ptm;
2503     GdiFont font = alloc_font();
2504     LONG width, height;
2505
2506     if(face->scalable) {
2507         height = 100;
2508         width = 0;
2509     } else {
2510         height = face->size.y_ppem >> 6;
2511         width = face->size.x_ppem >> 6;
2512     }
2513     
2514     if (!(font->ft_face = OpenFontFile(font, face->file, face->face_index, width, height)))
2515     {
2516         free_font(font);
2517         return;
2518     }
2519
2520     font->name = strdupW(face->family->FamilyName);
2521
2522     memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
2523
2524     size = WineEngGetOutlineTextMetrics(font, 0, NULL);
2525     if(size) {
2526         potm = HeapAlloc(GetProcessHeap(), 0, size);
2527         WineEngGetOutlineTextMetrics(font, size, potm);
2528         ptm = (TEXTMETRICW*)&potm->otmTextMetrics;
2529     } else {
2530         WineEngGetTextMetrics(font, &tm);
2531         ptm = &tm;
2532     }
2533         
2534     pntm->ntmTm.tmHeight = pelf->elfLogFont.lfHeight = ptm->tmHeight;
2535     pntm->ntmTm.tmAscent = ptm->tmAscent;
2536     pntm->ntmTm.tmDescent = ptm->tmDescent;
2537     pntm->ntmTm.tmInternalLeading = ptm->tmInternalLeading;
2538     pntm->ntmTm.tmExternalLeading = ptm->tmExternalLeading;
2539     pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWidth = ptm->tmAveCharWidth;
2540     pntm->ntmTm.tmMaxCharWidth = ptm->tmMaxCharWidth;
2541     pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = ptm->tmWeight;
2542     pntm->ntmTm.tmOverhang = ptm->tmOverhang;
2543     pntm->ntmTm.tmDigitizedAspectX = ptm->tmDigitizedAspectX;
2544     pntm->ntmTm.tmDigitizedAspectY = ptm->tmDigitizedAspectY;
2545     pntm->ntmTm.tmFirstChar = ptm->tmFirstChar;
2546     pntm->ntmTm.tmLastChar = ptm->tmLastChar;
2547     pntm->ntmTm.tmDefaultChar = ptm->tmDefaultChar;
2548     pntm->ntmTm.tmBreakChar = ptm->tmBreakChar;
2549     pntm->ntmTm.tmItalic = pelf->elfLogFont.lfItalic = ptm->tmItalic;
2550     pntm->ntmTm.tmUnderlined = pelf->elfLogFont.lfUnderline = ptm->tmUnderlined;
2551     pntm->ntmTm.tmStruckOut = pelf->elfLogFont.lfStrikeOut = ptm->tmStruckOut;
2552     pntm->ntmTm.tmPitchAndFamily = ptm->tmPitchAndFamily;
2553     pelf->elfLogFont.lfPitchAndFamily = (ptm->tmPitchAndFamily & 0xf1) + 1;
2554     pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = ptm->tmCharSet;
2555     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
2556     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
2557     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
2558
2559     *ptype = ptm->tmPitchAndFamily & TMPF_TRUETYPE ? TRUETYPE_FONTTYPE : 0;
2560     if(!(ptm->tmPitchAndFamily & TMPF_VECTOR))
2561         *ptype |= RASTER_FONTTYPE;
2562
2563     pntm->ntmTm.ntmFlags = ptm->tmItalic ? NTM_ITALIC : 0;
2564     if(ptm->tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD;
2565     if(pntm->ntmTm.ntmFlags == 0) pntm->ntmTm.ntmFlags = NTM_REGULAR;
2566
2567     pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
2568     pntm->ntmTm.ntmAvgWidth = pntm->ntmTm.tmAveCharWidth;
2569     memset(&pntm->ntmFontSig, 0, sizeof(FONTSIGNATURE));
2570
2571     if(potm) {
2572         pntm->ntmTm.ntmSizeEM = potm->otmEMSquare;
2573
2574         lstrcpynW(pelf->elfLogFont.lfFaceName,
2575                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFamilyName),
2576                  LF_FACESIZE);
2577         lstrcpynW(pelf->elfFullName,
2578                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFaceName),
2579                  LF_FULLFACESIZE);
2580         lstrcpynW(pelf->elfStyle,
2581                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName),
2582                  LF_FACESIZE);
2583
2584         HeapFree(GetProcessHeap(), 0, potm);
2585     } else {
2586         pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
2587
2588         lstrcpynW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
2589         lstrcpynW(pelf->elfFullName, face->family->FamilyName, LF_FACESIZE);
2590         pelf->elfStyle[0] = '\0';
2591     }
2592
2593     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
2594
2595     free_font(font);
2596 }
2597
2598 /*************************************************************
2599  * WineEngEnumFonts
2600  *
2601  */
2602 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
2603 {
2604     Family *family;
2605     Face *face;
2606     struct list *family_elem_ptr, *face_elem_ptr;
2607     ENUMLOGFONTEXW elf;
2608     NEWTEXTMETRICEXW ntm;
2609     DWORD type, ret = 1;
2610     FONTSIGNATURE fs;
2611     CHARSETINFO csi;
2612     LOGFONTW lf;
2613     int i;
2614
2615     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
2616
2617     if(plf->lfFaceName[0]) {
2618         FontSubst *psub;
2619         for(psub = substlist; psub; psub = psub->next)
2620             if(!strcmpiW(plf->lfFaceName, psub->from.name) &&
2621                (psub->from.charset == -1 ||
2622                 psub->from.charset == plf->lfCharSet))
2623                 break;
2624         if(psub) {
2625             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
2626                   debugstr_w(psub->to.name));
2627             memcpy(&lf, plf, sizeof(lf));
2628             strcpyW(lf.lfFaceName, psub->to.name);
2629             plf = &lf;
2630         }
2631
2632         LIST_FOR_EACH(family_elem_ptr, &font_list) {
2633             family = LIST_ENTRY(family_elem_ptr, Family, entry);
2634             if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
2635                 LIST_FOR_EACH(face_elem_ptr, &family->faces) {
2636                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
2637                     GetEnumStructs(face, &elf, &ntm, &type);
2638                     for(i = 0; i < 32; i++) {
2639                         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
2640                             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
2641                             strcpyW(elf.elfScript, OEM_DOSW);
2642                             i = 32; /* break out of loop */
2643                         } else if(!(face->fs.fsCsb[0] & (1L << i)))
2644                             continue;
2645                         else {
2646                             fs.fsCsb[0] = 1L << i;
2647                             fs.fsCsb[1] = 0;
2648                             if(!TranslateCharsetInfo(fs.fsCsb, &csi,
2649                                                      TCI_SRCFONTSIG))
2650                                 csi.ciCharset = DEFAULT_CHARSET;
2651                             if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
2652                             if(csi.ciCharset != DEFAULT_CHARSET) {
2653                                 elf.elfLogFont.lfCharSet =
2654                                     ntm.ntmTm.tmCharSet = csi.ciCharset;
2655                                 if(ElfScriptsW[i])
2656                                     strcpyW(elf.elfScript, ElfScriptsW[i]);
2657                                 else
2658                                     FIXME("Unknown elfscript for bit %d\n", i);
2659                             }
2660                         }
2661                         TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
2662                               debugstr_w(elf.elfLogFont.lfFaceName),
2663                               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
2664                               csi.ciCharset, type, debugstr_w(elf.elfScript),
2665                               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
2666                               ntm.ntmTm.ntmFlags);
2667                         ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
2668                         if(!ret) goto end;
2669                     }
2670                 }
2671             }
2672         }
2673     } else {
2674         LIST_FOR_EACH(family_elem_ptr, &font_list) {
2675             family = LIST_ENTRY(family_elem_ptr, Family, entry);
2676             face_elem_ptr = list_head(&family->faces);
2677             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2678             GetEnumStructs(face, &elf, &ntm, &type);
2679             for(i = 0; i < 32; i++) {
2680                 if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
2681                     elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
2682                     strcpyW(elf.elfScript, OEM_DOSW);
2683                     i = 32; /* break out of loop */
2684                 } else if(!(face->fs.fsCsb[0] & (1L << i)))
2685                     continue;
2686                 else {
2687                     fs.fsCsb[0] = 1L << i;
2688                     fs.fsCsb[1] = 0;
2689                     if(!TranslateCharsetInfo(fs.fsCsb, &csi,
2690                                              TCI_SRCFONTSIG))
2691                         csi.ciCharset = DEFAULT_CHARSET;
2692                     if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
2693                     if(csi.ciCharset != DEFAULT_CHARSET) {
2694                         elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet =
2695                           csi.ciCharset;
2696                           if(ElfScriptsW[i])
2697                               strcpyW(elf.elfScript, ElfScriptsW[i]);
2698                           else
2699                               FIXME("Unknown elfscript for bit %d\n", i);
2700                     }
2701                 }
2702                 TRACE("enuming face %s full %s style %s charset = %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
2703                       debugstr_w(elf.elfLogFont.lfFaceName),
2704                       debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
2705                       csi.ciCharset, type, debugstr_w(elf.elfScript),
2706                       elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
2707                       ntm.ntmTm.ntmFlags);
2708                 ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
2709                 if(!ret) goto end;
2710             }
2711         }
2712     }
2713 end:
2714     return ret;
2715 }
2716
2717 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
2718 {
2719     pt->x.value = vec->x >> 6;
2720     pt->x.fract = (vec->x & 0x3f) << 10;
2721     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
2722     pt->y.value = vec->y >> 6;
2723     pt->y.fract = (vec->y & 0x3f) << 10;
2724     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
2725     return;
2726 }
2727
2728 /***************************************************
2729  * According to the MSDN documentation on WideCharToMultiByte,
2730  * certain codepages cannot set the default_used parameter.
2731  * This returns TRUE if the codepage can set that parameter, false else
2732  * so that calls to WideCharToMultiByte don't fail with ERROR_INVALID_PARAMETER
2733  */
2734 static BOOL codepage_sets_default_used(UINT codepage)
2735 {
2736    switch (codepage)
2737    {
2738        case CP_UTF7:
2739        case CP_UTF8:
2740        case CP_SYMBOL:
2741            return FALSE;
2742        default:
2743            return TRUE;
2744    }
2745 }
2746
2747 static FT_UInt get_glyph_index(GdiFont font, UINT glyph)
2748 {
2749     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
2750         WCHAR wc = (WCHAR)glyph;
2751         BOOL default_used;
2752         BOOL *default_used_pointer;
2753         FT_UInt ret;
2754         char buf;
2755         default_used_pointer = NULL;
2756         default_used = FALSE;
2757         if (codepage_sets_default_used(font->codepage))
2758             default_used_pointer = &default_used;
2759         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
2760             ret = 0;
2761         else
2762             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
2763         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
2764         return ret;
2765     }
2766
2767     if(font->charset == SYMBOL_CHARSET && glyph < 0x100)
2768         glyph = glyph + 0xf000;
2769     return pFT_Get_Char_Index(font->ft_face, glyph);
2770 }
2771
2772 /*************************************************************
2773  * WineEngGetGlyphIndices
2774  *
2775  * FIXME: add support for GGI_MARK_NONEXISTING_GLYPHS
2776  */
2777 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
2778                                 LPWORD pgi, DWORD flags)
2779 {
2780     INT i;
2781
2782     for(i = 0; i < count; i++)
2783         pgi[i] = get_glyph_index(font, lpstr[i]);
2784
2785     return count;
2786 }
2787
2788 /*************************************************************
2789  * WineEngGetGlyphOutline
2790  *
2791  * Behaves in exactly the same way as the win32 api GetGlyphOutline
2792  * except that the first parameter is the HWINEENGFONT of the font in
2793  * question rather than an HDC.
2794  *
2795  */
2796 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
2797                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
2798                              const MAT2* lpmat)
2799 {
2800     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
2801     FT_Face ft_face = font->ft_face;
2802     FT_UInt glyph_index;
2803     DWORD width, height, pitch, needed = 0;
2804     FT_Bitmap ft_bitmap;
2805     FT_Error err;
2806     INT left, right, top = 0, bottom = 0;
2807     FT_Angle angle = 0;
2808     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
2809     float widthRatio = 1.0;
2810     FT_Matrix transMat = identityMat;
2811     BOOL needsTransform = FALSE;
2812
2813
2814     TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm,
2815           buflen, buf, lpmat);
2816
2817     if(format & GGO_GLYPH_INDEX) {
2818         glyph_index = glyph;
2819         format &= ~GGO_GLYPH_INDEX;
2820     } else
2821         glyph_index = get_glyph_index(font, glyph);
2822
2823     if(glyph_index >= font->gmsize) {
2824         font->gmsize = (glyph_index / INIT_GM_SIZE + 1) * INIT_GM_SIZE;
2825         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
2826                                font->gmsize * sizeof(*font->gm));
2827     } else {
2828         if(format == GGO_METRICS && font->gm[glyph_index].init) {
2829             memcpy(lpgm, &font->gm[glyph_index].gm, sizeof(*lpgm));
2830             return 1; /* FIXME */
2831         }
2832     }
2833
2834     if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP) || font->aveWidth || lpmat)
2835         load_flags |= FT_LOAD_NO_BITMAP;
2836
2837     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
2838
2839     if(err) {
2840         FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
2841         return GDI_ERROR;
2842     }
2843         
2844     /* Scaling factor */
2845     if (font->aveWidth && font->potm) {
2846         widthRatio = (float)font->aveWidth * font->font_desc.matrix.eM11 / (float) font->potm->otmTextMetrics.tmAveCharWidth;
2847     }
2848
2849     left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
2850     right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
2851
2852     font->gm[glyph_index].adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
2853     font->gm[glyph_index].lsb = left >> 6;
2854     font->gm[glyph_index].bbx = (right - left) >> 6;
2855
2856     /* Scaling transform */
2857     if(font->aveWidth) {
2858         FT_Matrix scaleMat;
2859         scaleMat.xx = FT_FixedFromFloat(widthRatio);
2860         scaleMat.xy = 0;
2861         scaleMat.yx = 0;
2862         scaleMat.yy = (1 << 16);
2863
2864         pFT_Matrix_Multiply(&scaleMat, &transMat);
2865         needsTransform = TRUE;
2866     }
2867
2868     /* Slant transform */
2869     if (font->fake_italic) {
2870         FT_Matrix slantMat;
2871         
2872         slantMat.xx = (1 << 16);
2873         slantMat.xy = ((1 << 16) >> 2);
2874         slantMat.yx = 0;
2875         slantMat.yy = (1 << 16);
2876         pFT_Matrix_Multiply(&slantMat, &transMat);
2877         needsTransform = TRUE;
2878     }
2879
2880     /* Rotation transform */
2881     if(font->orientation) {
2882         FT_Matrix rotationMat;
2883         FT_Vector vecAngle;
2884         angle = FT_FixedFromFloat((float)font->orientation / 10.0);
2885         pFT_Vector_Unit(&vecAngle, angle);
2886         rotationMat.xx = vecAngle.x;
2887         rotationMat.xy = -vecAngle.y;
2888         rotationMat.yx = -rotationMat.xy;
2889         rotationMat.yy = rotationMat.xx;
2890         
2891         pFT_Matrix_Multiply(&rotationMat, &transMat);
2892         needsTransform = TRUE;
2893     }
2894
2895     /* Extra transformation specified by caller */
2896     if (lpmat) {
2897         FT_Matrix extraMat;
2898         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
2899         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
2900         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
2901         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
2902         pFT_Matrix_Multiply(&extraMat, &transMat);
2903         needsTransform = TRUE;
2904     }
2905
2906     if(!needsTransform) {
2907         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
2908         bottom = (ft_face->glyph->metrics.horiBearingY -
2909                   ft_face->glyph->metrics.height) & -64;
2910         lpgm->gmCellIncX = font->gm[glyph_index].adv;
2911         lpgm->gmCellIncY = 0;
2912     } else {
2913         INT xc, yc;
2914         FT_Vector vec;
2915         for(xc = 0; xc < 2; xc++) {
2916             for(yc = 0; yc < 2; yc++) {
2917                 vec.x = (ft_face->glyph->metrics.horiBearingX +
2918                   xc * ft_face->glyph->metrics.width);
2919                 vec.y = ft_face->glyph->metrics.horiBearingY -
2920                   yc * ft_face->glyph->metrics.height;
2921                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
2922                 pFT_Vector_Transform(&vec, &transMat);
2923                 if(xc == 0 && yc == 0) {
2924                     left = right = vec.x;
2925                     top = bottom = vec.y;
2926                 } else {
2927                     if(vec.x < left) left = vec.x;
2928                     else if(vec.x > right) right = vec.x;
2929                     if(vec.y < bottom) bottom = vec.y;
2930                     else if(vec.y > top) top = vec.y;
2931                 }
2932             }
2933         }
2934         left = left & -64;
2935         right = (right + 63) & -64;
2936         bottom = bottom & -64;
2937         top = (top + 63) & -64;
2938
2939         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
2940         vec.x = ft_face->glyph->metrics.horiAdvance;
2941         vec.y = 0;
2942         pFT_Vector_Transform(&vec, &transMat);
2943         lpgm->gmCellIncX = (vec.x+63) >> 6;
2944         lpgm->gmCellIncY = -((vec.y+63) >> 6);
2945     }
2946     lpgm->gmBlackBoxX = (right - left) >> 6;
2947     lpgm->gmBlackBoxY = (top - bottom) >> 6;
2948     lpgm->gmptGlyphOrigin.x = left >> 6;
2949     lpgm->gmptGlyphOrigin.y = top >> 6;
2950
2951     memcpy(&font->gm[glyph_index].gm, lpgm, sizeof(*lpgm));
2952     font->gm[glyph_index].init = TRUE;
2953
2954     if(format == GGO_METRICS)
2955         return 1; /* FIXME */
2956
2957     if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) {
2958         TRACE("loaded a bitmap\n");
2959         return GDI_ERROR;
2960     }
2961
2962     switch(format) {
2963     case GGO_BITMAP:
2964         width = lpgm->gmBlackBoxX;
2965         height = lpgm->gmBlackBoxY;
2966         pitch = ((width + 31) >> 5) << 2;
2967         needed = pitch * height;
2968
2969         if(!buf || !buflen) break;
2970
2971         switch(ft_face->glyph->format) {
2972         case ft_glyph_format_bitmap:
2973           {
2974             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
2975             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
2976             INT h = ft_face->glyph->bitmap.rows;
2977             while(h--) {
2978                 memcpy(dst, src, w);
2979                 src += ft_face->glyph->bitmap.pitch;
2980                 dst += pitch;
2981             }
2982             break;
2983           }
2984
2985         case ft_glyph_format_outline:
2986             ft_bitmap.width = width;
2987             ft_bitmap.rows = height;
2988             ft_bitmap.pitch = pitch;
2989             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
2990             ft_bitmap.buffer = buf;
2991
2992                 if(needsTransform) {
2993                         pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
2994             }
2995
2996             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
2997
2998             /* Note: FreeType will only set 'black' bits for us. */
2999             memset(buf, 0, needed);
3000             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
3001             break;
3002
3003         default:
3004             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
3005             return GDI_ERROR;
3006         }
3007         break;
3008
3009     case GGO_GRAY2_BITMAP:
3010     case GGO_GRAY4_BITMAP:
3011     case GGO_GRAY8_BITMAP:
3012     case WINE_GGO_GRAY16_BITMAP:
3013       {
3014         unsigned int mult, row, col;
3015         BYTE *start, *ptr;
3016
3017         width = lpgm->gmBlackBoxX;
3018         height = lpgm->gmBlackBoxY;
3019         pitch = (width + 3) / 4 * 4;
3020         needed = pitch * height;
3021
3022         if(!buf || !buflen) break;
3023         ft_bitmap.width = width;
3024         ft_bitmap.rows = height;
3025         ft_bitmap.pitch = pitch;
3026         ft_bitmap.pixel_mode = ft_pixel_mode_grays;
3027         ft_bitmap.buffer = buf;
3028
3029         if(needsTransform) {
3030                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
3031         }
3032
3033         pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
3034
3035         memset(ft_bitmap.buffer, 0, buflen);
3036
3037         pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
3038
3039         if(format == GGO_GRAY2_BITMAP)
3040             mult = 4;
3041         else if(format == GGO_GRAY4_BITMAP)
3042             mult = 16;
3043         else if(format == GGO_GRAY8_BITMAP)
3044             mult = 64;
3045         else if(format == WINE_GGO_GRAY16_BITMAP)
3046             break;
3047         else {
3048             assert(0);
3049             break;
3050         }
3051
3052         start = buf;
3053         for(row = 0; row < height; row++) {
3054             ptr = start;
3055             for(col = 0; col < width; col++, ptr++) {
3056                 *ptr = (((int)*ptr) * mult + 128) / 256;
3057             }
3058             start += pitch;
3059         }
3060         break;
3061       }
3062
3063     case GGO_NATIVE:
3064       {
3065         int contour, point = 0, first_pt;
3066         FT_Outline *outline = &ft_face->glyph->outline;
3067         TTPOLYGONHEADER *pph;
3068         TTPOLYCURVE *ppc;
3069         DWORD pph_start, cpfx, type;
3070
3071         if(buflen == 0) buf = NULL;
3072
3073         if (needsTransform && buf) {
3074                 pFT_Outline_Transform(outline, &transMat);
3075         }
3076
3077         for(contour = 0; contour < outline->n_contours; contour++) {
3078             pph_start = needed;
3079             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
3080             first_pt = point;
3081             if(buf) {
3082                 pph->dwType = TT_POLYGON_TYPE;
3083                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3084             }
3085             needed += sizeof(*pph);
3086             point++;
3087             while(point <= outline->contours[contour]) {
3088                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
3089                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3090                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
3091                 cpfx = 0;
3092                 do {
3093                     if(buf)
3094                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3095                     cpfx++;
3096                     point++;
3097                 } while(point <= outline->contours[contour] &&
3098                         (outline->tags[point] & FT_Curve_Tag_On) ==
3099                         (outline->tags[point-1] & FT_Curve_Tag_On));
3100                 /* At the end of a contour Windows adds the start point, but
3101                    only for Beziers */
3102                 if(point > outline->contours[contour] &&
3103                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
3104                     if(buf)
3105                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
3106                     cpfx++;
3107                 } else if(point <= outline->contours[contour] &&
3108                           outline->tags[point] & FT_Curve_Tag_On) {
3109                   /* add closing pt for bezier */
3110                     if(buf)
3111                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3112                     cpfx++;
3113                     point++;
3114                 }
3115                 if(buf) {
3116                     ppc->wType = type;
3117                     ppc->cpfx = cpfx;
3118                 }
3119                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3120             }
3121             if(buf)
3122                 pph->cb = needed - pph_start;
3123         }
3124         break;
3125       }
3126     case GGO_BEZIER:
3127       {
3128         /* Convert the quadratic Beziers to cubic Beziers.
3129            The parametric eqn for a cubic Bezier is, from PLRM:
3130            r(t) = at^3 + bt^2 + ct + r0
3131            with the control points:
3132            r1 = r0 + c/3
3133            r2 = r1 + (c + b)/3
3134            r3 = r0 + c + b + a
3135
3136            A quadratic Beizer has the form:
3137            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
3138
3139            So equating powers of t leads to:
3140            r1 = 2/3 p1 + 1/3 p0
3141            r2 = 2/3 p1 + 1/3 p2
3142            and of course r0 = p0, r3 = p2
3143         */
3144
3145         int contour, point = 0, first_pt;
3146         FT_Outline *outline = &ft_face->glyph->outline;
3147         TTPOLYGONHEADER *pph;
3148         TTPOLYCURVE *ppc;
3149         DWORD pph_start, cpfx, type;
3150         FT_Vector cubic_control[4];
3151         if(buflen == 0) buf = NULL;
3152
3153         if (needsTransform && buf) {
3154                 pFT_Outline_Transform(outline, &transMat);
3155         }
3156
3157         for(contour = 0; contour < outline->n_contours; contour++) {
3158             pph_start = needed;
3159             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
3160             first_pt = point;
3161             if(buf) {
3162                 pph->dwType = TT_POLYGON_TYPE;
3163                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3164             }
3165             needed += sizeof(*pph);
3166             point++;
3167             while(point <= outline->contours[contour]) {
3168                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
3169                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3170                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
3171                 cpfx = 0;
3172                 do {
3173                     if(type == TT_PRIM_LINE) {
3174                         if(buf)
3175                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3176                         cpfx++;
3177                         point++;
3178                     } else {
3179                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
3180                          so cpfx = 3n */
3181
3182                       /* FIXME: Possible optimization in endpoint calculation
3183                          if there are two consecutive curves */
3184                         cubic_control[0] = outline->points[point-1];
3185                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
3186                             cubic_control[0].x += outline->points[point].x + 1;
3187                             cubic_control[0].y += outline->points[point].y + 1;
3188                             cubic_control[0].x >>= 1;
3189                             cubic_control[0].y >>= 1;
3190                         }
3191                         if(point+1 > outline->contours[contour])
3192                             cubic_control[3] = outline->points[first_pt];
3193                         else {
3194                             cubic_control[3] = outline->points[point+1];
3195                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
3196                                 cubic_control[3].x += outline->points[point].x + 1;
3197                                 cubic_control[3].y += outline->points[point].y + 1;
3198                                 cubic_control[3].x >>= 1;
3199                                 cubic_control[3].y >>= 1;
3200                             }
3201                         }
3202                         /* r1 = 1/3 p0 + 2/3 p1
3203                            r2 = 1/3 p2 + 2/3 p1 */
3204                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
3205                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
3206                         cubic_control[2] = cubic_control[1];
3207                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
3208                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
3209                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
3210                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
3211                         if(buf) {
3212                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
3213                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
3214                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
3215                         }
3216                         cpfx += 3;
3217                         point++;
3218                     }
3219                 } while(point <= outline->contours[contour] &&
3220                         (outline->tags[point] & FT_Curve_Tag_On) ==
3221                         (outline->tags[point-1] & FT_Curve_Tag_On));
3222                 /* At the end of a contour Windows adds the start point,
3223                    but only for Beziers and we've already done that.
3224                 */
3225                 if(point <= outline->contours[contour] &&
3226                    outline->tags[point] & FT_Curve_Tag_On) {
3227                   /* This is the closing pt of a bezier, but we've already
3228                      added it, so just inc point and carry on */
3229                     point++;
3230                 }
3231                 if(buf) {
3232                     ppc->wType = type;
3233                     ppc->cpfx = cpfx;
3234                 }
3235                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3236             }
3237             if(buf)
3238                 pph->cb = needed - pph_start;
3239         }
3240         break;
3241       }
3242
3243     default:
3244         FIXME("Unsupported format %d\n", format);
3245         return GDI_ERROR;
3246     }
3247     return needed;
3248 }
3249
3250 static BOOL get_bitmap_text_metrics(GdiFont font)
3251 {
3252     FT_Face ft_face = font->ft_face;
3253 #ifdef HAVE_FREETYPE_FTWINFNT_H
3254     FT_WinFNT_HeaderRec winfnt_header;
3255 #endif
3256     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
3257     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
3258     font->potm->otmSize = size;
3259
3260 #define TM font->potm->otmTextMetrics
3261 #ifdef HAVE_FREETYPE_FTWINFNT_H
3262     if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
3263     {
3264         TM.tmHeight = winfnt_header.pixel_height;
3265         TM.tmAscent = winfnt_header.ascent;
3266         TM.tmDescent = TM.tmHeight - TM.tmAscent;
3267         TM.tmInternalLeading = winfnt_header.internal_leading;
3268         TM.tmExternalLeading = winfnt_header.external_leading;
3269         TM.tmAveCharWidth = winfnt_header.avg_width;
3270         TM.tmMaxCharWidth = winfnt_header.max_width;
3271         TM.tmWeight = winfnt_header.weight;
3272         TM.tmOverhang = 0;
3273         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
3274         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
3275         TM.tmFirstChar = winfnt_header.first_char;
3276         TM.tmLastChar = winfnt_header.last_char;
3277         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
3278         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
3279         TM.tmItalic = winfnt_header.italic;
3280         TM.tmUnderlined = font->underline;
3281         TM.tmStruckOut = font->strikeout;
3282         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
3283         TM.tmCharSet = winfnt_header.charset;
3284     }
3285     else
3286 #endif
3287     {
3288         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
3289         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
3290         TM.tmHeight = TM.tmAscent + TM.tmDescent;
3291         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
3292         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
3293         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
3294         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
3295         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
3296         TM.tmOverhang = 0;
3297         TM.tmDigitizedAspectX = 96; /* FIXME */
3298         TM.tmDigitizedAspectY = 96; /* FIXME */
3299         TM.tmFirstChar = 1;
3300         TM.tmLastChar = 255;
3301         TM.tmDefaultChar = 32;
3302         TM.tmBreakChar = 32;
3303         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
3304         TM.tmUnderlined = font->underline;
3305         TM.tmStruckOut = font->strikeout;
3306         /* NB inverted meaning of TMPF_FIXED_PITCH */
3307         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
3308         TM.tmCharSet = font->charset;
3309     }
3310 #undef TM
3311
3312     return TRUE;
3313 }
3314
3315 /*************************************************************
3316  * WineEngGetTextMetrics
3317  *
3318  */
3319 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
3320 {
3321     if(!font->potm) {
3322         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
3323             if(!get_bitmap_text_metrics(font))
3324                 return FALSE;
3325     }
3326     if(!font->potm) return FALSE;
3327     memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm));
3328
3329     if (font->aveWidth) {
3330         ptm->tmAveCharWidth = font->aveWidth * font->font_desc.matrix.eM11;
3331     }
3332     return TRUE;
3333 }
3334
3335
3336 /*************************************************************
3337  * WineEngGetOutlineTextMetrics
3338  *
3339  */
3340 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
3341                                   OUTLINETEXTMETRICW *potm)
3342 {
3343     FT_Face ft_face = font->ft_face;
3344     UINT needed, lenfam, lensty, ret;
3345     TT_OS2 *pOS2;
3346     TT_HoriHeader *pHori;
3347     TT_Postscript *pPost;
3348     FT_Fixed x_scale, y_scale;
3349     WCHAR *family_nameW, *style_nameW;
3350     static const WCHAR spaceW[] = {' ', '\0'};
3351     char *cp;
3352     INT ascent, descent;
3353
3354     TRACE("font=%p\n", font);
3355
3356     if(!FT_IS_SCALABLE(ft_face))
3357         return 0;
3358
3359     if(font->potm) {
3360         if(cbSize >= font->potm->otmSize)
3361             memcpy(potm, font->potm, font->potm->otmSize);
3362         return font->potm->otmSize;
3363     }
3364
3365
3366     needed = sizeof(*potm);
3367
3368     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
3369     family_nameW = strdupW(font->name);
3370
3371     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
3372       * sizeof(WCHAR);
3373     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
3374     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
3375                         style_nameW, lensty/sizeof(WCHAR));
3376
3377     /* These names should be read from the TT name table */
3378
3379     /* length of otmpFamilyName */
3380     needed += lenfam;
3381
3382     /* length of otmpFaceName */
3383     if(!strcasecmp(ft_face->style_name, "regular")) {
3384       needed += lenfam; /* just the family name */
3385     } else {
3386       needed += lenfam + lensty; /* family + " " + style */
3387     }
3388
3389     /* length of otmpStyleName */
3390     needed += lensty;
3391
3392     /* length of otmpFullName */
3393     needed += lenfam + lensty;
3394
3395
3396     x_scale = ft_face->size->metrics.x_scale;
3397     y_scale = ft_face->size->metrics.y_scale;
3398
3399     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
3400     if(!pOS2) {
3401         FIXME("Can't find OS/2 table - not TT font?\n");
3402         ret = 0;
3403         goto end;
3404     }
3405
3406     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
3407     if(!pHori) {
3408         FIXME("Can't find HHEA table - not TT font?\n");
3409         ret = 0;
3410         goto end;
3411     }
3412
3413     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
3414
3415     TRACE("OS/2 winA = %d winD = %d typoA = %d typoD = %d typoLG = %d FT_Face a = %d, d = %d, h = %d: HORZ a = %d, d = %d lg = %d maxY = %ld minY = %ld\n",
3416           pOS2->usWinAscent, pOS2->usWinDescent,
3417           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
3418           ft_face->ascender, ft_face->descender, ft_face->height,
3419           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
3420           ft_face->bbox.yMax, ft_face->bbox.yMin);
3421
3422     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
3423     font->potm->otmSize = needed;
3424
3425 #define TM font->potm->otmTextMetrics
3426
3427     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
3428         ascent = pHori->Ascender;
3429         descent = -pHori->Descender;
3430     } else {
3431         ascent = pOS2->usWinAscent;
3432         descent = pOS2->usWinDescent;
3433     }
3434
3435     if(font->yMax) {
3436         TM.tmAscent = font->yMax;
3437         TM.tmDescent = -font->yMin;
3438         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
3439     } else {
3440         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
3441         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
3442         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
3443                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
3444     }
3445
3446     TM.tmHeight = TM.tmAscent + TM.tmDescent;
3447
3448     /* MSDN says:
3449      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
3450     */
3451     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
3452                  ((ascent + descent) -
3453                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
3454
3455     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
3456     if (TM.tmAveCharWidth == 0) {
3457         TM.tmAveCharWidth = 1; 
3458     }
3459     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
3460     TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
3461     TM.tmOverhang = 0;
3462     TM.tmDigitizedAspectX = 300;
3463     TM.tmDigitizedAspectY = 300;
3464     TM.tmFirstChar = pOS2->usFirstCharIndex;
3465     TM.tmLastChar = pOS2->usLastCharIndex;
3466     TM.tmDefaultChar = pOS2->usDefaultChar;
3467     TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
3468     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
3469     TM.tmUnderlined = font->underline;
3470     TM.tmStruckOut = font->strikeout;
3471
3472     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
3473     if(!FT_IS_FIXED_WIDTH(ft_face) &&
3474        (pOS2->version == 0xFFFFU || 
3475         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
3476         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
3477     else
3478         TM.tmPitchAndFamily = 0;
3479
3480     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
3481     case PAN_FAMILY_SCRIPT:
3482         TM.tmPitchAndFamily |= FF_SCRIPT;
3483         break;
3484     case PAN_FAMILY_DECORATIVE:
3485     case PAN_FAMILY_PICTORIAL:
3486         TM.tmPitchAndFamily |= FF_DECORATIVE;
3487         break;
3488     case PAN_FAMILY_TEXT_DISPLAY:
3489         if(TM.tmPitchAndFamily == 0) /* fixed */
3490             TM.tmPitchAndFamily = FF_MODERN;
3491         else {
3492             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
3493             case PAN_SERIF_NORMAL_SANS:
3494             case PAN_SERIF_OBTUSE_SANS:
3495             case PAN_SERIF_PERP_SANS:
3496                 TM.tmPitchAndFamily |= FF_SWISS;
3497                 break;
3498             default:
3499                 TM.tmPitchAndFamily |= FF_ROMAN;
3500             }
3501         }
3502         break;
3503     default:
3504         TM.tmPitchAndFamily |= FF_DONTCARE;
3505     }
3506
3507     if(FT_IS_SCALABLE(ft_face))
3508         TM.tmPitchAndFamily |= TMPF_VECTOR;
3509     if(FT_IS_SFNT(ft_face))
3510         TM.tmPitchAndFamily |= TMPF_TRUETYPE;
3511
3512     TM.tmCharSet = font->charset;
3513 #undef TM
3514
3515     font->potm->otmFiller = 0;
3516     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
3517     font->potm->otmfsSelection = pOS2->fsSelection;
3518     font->potm->otmfsType = pOS2->fsType;
3519     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
3520     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
3521     font->potm->otmItalicAngle = 0; /* POST table */
3522     font->potm->otmEMSquare = ft_face->units_per_EM;
3523     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
3524     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
3525     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
3526     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
3527     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
3528     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
3529     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
3530     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
3531     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
3532     font->potm->otmMacAscent = 0; /* where do these come from ? */
3533     font->potm->otmMacDescent = 0;
3534     font->potm->otmMacLineGap = 0;
3535     font->potm->otmusMinimumPPEM = 0; /* TT Header */
3536     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
3537     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
3538     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
3539     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
3540     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
3541     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
3542     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
3543     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
3544     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
3545     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
3546     if(!pPost) {
3547         font->potm->otmsUnderscoreSize = 0;
3548         font->potm->otmsUnderscorePosition = 0;
3549     } else {
3550         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
3551         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
3552     }
3553
3554     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
3555     cp = (char*)font->potm + sizeof(*font->potm);
3556     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
3557     strcpyW((WCHAR*)cp, family_nameW);
3558     cp += lenfam;
3559     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
3560     strcpyW((WCHAR*)cp, style_nameW);
3561     cp += lensty;
3562     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
3563     strcpyW((WCHAR*)cp, family_nameW);
3564     if(strcasecmp(ft_face->style_name, "regular")) {
3565         strcatW((WCHAR*)cp, spaceW);
3566         strcatW((WCHAR*)cp, style_nameW);
3567         cp += lenfam + lensty;
3568     } else
3569         cp += lenfam;
3570     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
3571     strcpyW((WCHAR*)cp, family_nameW);
3572     strcatW((WCHAR*)cp, spaceW);
3573     strcatW((WCHAR*)cp, style_nameW);
3574     ret = needed;
3575
3576     if(potm && needed <= cbSize)
3577         memcpy(potm, font->potm, font->potm->otmSize);
3578
3579 end:
3580     HeapFree(GetProcessHeap(), 0, style_nameW);
3581     HeapFree(GetProcessHeap(), 0, family_nameW);
3582
3583     return ret;
3584 }
3585
3586 static BOOL load_child_font(GdiFont font, CHILD_FONT *child)
3587 {
3588     HFONTLIST *hfontlist;
3589     child->font = alloc_font();
3590     child->font->ft_face = OpenFontFile(child->font, child->file_name, child->index, 0, -font->ppem);
3591     if(!child->font->ft_face)
3592     {
3593         free_font(child->font);
3594         child->font = NULL;
3595         return FALSE;
3596     }
3597
3598     child->font->orientation = font->orientation;
3599     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
3600     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
3601     list_add_head(&child->font->hfontlist, &hfontlist->entry);
3602     child->font->base_font = font;
3603     list_add_head(&child_font_list, &child->font->entry);
3604     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
3605     return TRUE;
3606 }
3607
3608 static BOOL get_glyph_index_linked(GdiFont font, UINT c, GdiFont *linked_font, FT_UInt *glyph)
3609 {
3610     FT_UInt g;
3611     CHILD_FONT *child_font;
3612
3613     if(font->base_font)
3614         font = font->base_font;
3615
3616     *linked_font = font;
3617
3618     if((*glyph = get_glyph_index(font, c)))
3619         return TRUE;
3620
3621     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
3622     {
3623         if(!child_font->font)
3624             if(!load_child_font(font, child_font))
3625                 continue;
3626
3627         if(!child_font->font->ft_face)
3628             continue;
3629         g = get_glyph_index(child_font->font, c);
3630         if(g)
3631         {
3632             *glyph = g;
3633             *linked_font = child_font->font;
3634             return TRUE;
3635         }
3636     }
3637     return FALSE;
3638 }
3639
3640 /*************************************************************
3641  * WineEngGetCharWidth
3642  *
3643  */
3644 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
3645                          LPINT buffer)
3646 {
3647     UINT c;
3648     GLYPHMETRICS gm;
3649     FT_UInt glyph_index;
3650     GdiFont linked_font;
3651
3652     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
3653
3654     for(c = firstChar; c <= lastChar; c++) {
3655         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
3656         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3657                                &gm, 0, NULL, NULL);
3658         buffer[c - firstChar] = linked_font->gm[glyph_index].adv;
3659     }
3660     return TRUE;
3661 }
3662
3663 /*************************************************************
3664  * WineEngGetCharABCWidths
3665  *
3666  */
3667 BOOL WineEngGetCharABCWidths(GdiFont font, UINT firstChar, UINT lastChar,
3668                              LPABC buffer)
3669 {
3670     UINT c;
3671     GLYPHMETRICS gm;
3672     FT_UInt glyph_index;
3673     GdiFont linked_font;
3674
3675     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
3676
3677     if(!FT_IS_SCALABLE(font->ft_face))
3678         return FALSE;
3679
3680     for(c = firstChar; c <= lastChar; c++) {
3681         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
3682         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3683                                &gm, 0, NULL, NULL);
3684         buffer[c - firstChar].abcA = linked_font->gm[glyph_index].lsb;
3685         buffer[c - firstChar].abcB = linked_font->gm[glyph_index].bbx;
3686         buffer[c - firstChar].abcC = linked_font->gm[glyph_index].adv - linked_font->gm[glyph_index].lsb -
3687           linked_font->gm[glyph_index].bbx;
3688     }
3689     return TRUE;
3690 }
3691
3692 /*************************************************************
3693  * WineEngGetTextExtentPoint
3694  *
3695  */
3696 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
3697                                LPSIZE size)
3698 {
3699     INT idx;
3700     GLYPHMETRICS gm;
3701     TEXTMETRICW tm;
3702     FT_UInt glyph_index;
3703     GdiFont linked_font;
3704
3705     TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count,
3706           size);
3707
3708     size->cx = 0;
3709     WineEngGetTextMetrics(font, &tm);
3710     size->cy = tm.tmHeight;
3711
3712     for(idx = 0; idx < count; idx++) {
3713         get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
3714         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3715                                &gm, 0, NULL, NULL);
3716         size->cx += linked_font->gm[glyph_index].adv;
3717     }
3718     TRACE("return %ld,%ld\n", size->cx, size->cy);
3719     return TRUE;
3720 }
3721
3722 /*************************************************************
3723  * WineEngGetTextExtentPointI
3724  *
3725  */
3726 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
3727                                 LPSIZE size)
3728 {
3729     INT idx;
3730     GLYPHMETRICS gm;
3731     TEXTMETRICW tm;
3732
3733     TRACE("%p, %p, %d, %p\n", font, indices, count, size);
3734
3735     size->cx = 0;
3736     WineEngGetTextMetrics(font, &tm);
3737     size->cy = tm.tmHeight;
3738
3739     for(idx = 0; idx < count; idx++) {
3740         WineEngGetGlyphOutline(font, indices[idx],
3741                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
3742                                NULL);
3743         size->cx += font->gm[indices[idx]].adv;
3744     }
3745     TRACE("return %ld,%ld\n", size->cx, size->cy);
3746     return TRUE;
3747 }
3748
3749 /*************************************************************
3750  * WineEngGetFontData
3751  *
3752  */
3753 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
3754                          DWORD cbData)
3755 {
3756     FT_Face ft_face = font->ft_face;
3757     DWORD len;
3758     FT_Error err;
3759
3760     TRACE("font=%p, table=%08lx, offset=%08lx, buf=%p, cbData=%lx\n",
3761         font, table, offset, buf, cbData);
3762
3763     if(!FT_IS_SFNT(ft_face))
3764         return GDI_ERROR;
3765
3766     if(!buf || !cbData)
3767         len = 0;
3768     else
3769         len = cbData;
3770
3771     if(table) { /* MS tags differ in endidness from FT ones */
3772         table = table >> 24 | table << 24 |
3773           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
3774     }
3775
3776     /* If the FT_Load_Sfnt_Table function is there we'll use it */
3777     if(pFT_Load_Sfnt_Table) {
3778         /* make sure value of len is the value freetype says it needs */ 
3779         if( buf && len) {
3780             DWORD needed = 0;
3781             err = pFT_Load_Sfnt_Table(ft_face, table, offset, NULL, &needed);
3782             if( !err && needed < len) len = needed;
3783         }
3784         err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, &len);
3785     }
3786 #ifdef HAVE_FREETYPE_INTERNAL_SFNT_H
3787     else { /* Do it the hard way */
3788         TT_Face tt_face = (TT_Face) ft_face;
3789         SFNT_Interface *sfnt;
3790         if (FT_Version.major==2 && FT_Version.minor==0)
3791         {
3792             /* 2.0.x */
3793             sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
3794         }
3795         else
3796         {
3797             /* A field was added in the middle of the structure in 2.1.x */
3798             sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
3799         }
3800         /* make sure value of len is the value freetype says it needs */ 
3801         if( buf && len) {
3802             DWORD needed = 0;
3803             err = sfnt->load_any(tt_face, table, offset, NULL, &needed);
3804             if( !err && needed < len) len = needed;
3805         }
3806         err = sfnt->load_any(tt_face, table, offset, buf, &len);
3807     }
3808 #else
3809     else {
3810         static int msg;
3811         if(!msg) {
3812             MESSAGE("This version of Wine was compiled with freetype headers later than 2.2.0\n"
3813                     "but is being run with a freetype library without the FT_Load_Sfnt_Table function.\n"
3814                     "Please upgrade your freetype library.\n");
3815             msg++;
3816         }
3817         err = FT_Err_Unimplemented_Feature;
3818     }
3819 #endif
3820     if(err) {
3821         TRACE("Can't find table %08lx.\n", table);
3822         return GDI_ERROR;
3823     }
3824     return len;
3825 }
3826
3827 /*************************************************************
3828  * WineEngGetTextFace
3829  *
3830  */
3831 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
3832 {
3833     if(str) {
3834         lstrcpynW(str, font->name, count);
3835         return strlenW(font->name);
3836     } else
3837         return strlenW(font->name) + 1;
3838 }
3839
3840 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
3841 {
3842     if (fs) memcpy(fs, &font->fs, sizeof(FONTSIGNATURE));
3843     return font->charset;
3844 }
3845
3846 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
3847 {
3848     GdiFont font = dc->gdiFont, linked_font;
3849     struct list *first_hfont;
3850     BOOL ret;
3851
3852     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
3853     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
3854     if(font == linked_font)
3855         *new_hfont = dc->hFont;
3856     else
3857     {
3858         first_hfont = list_head(&linked_font->hfontlist);
3859         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
3860     }
3861
3862     return ret;
3863 }
3864     
3865
3866 /*************************************************************
3867  *     FontIsLinked
3868  */
3869 BOOL WINAPI FontIsLinked(HDC hdc)
3870 {
3871     DC *dc = DC_GetDCPtr(hdc);
3872     BOOL ret = FALSE;
3873
3874     if(!dc) return FALSE;
3875     if(dc->gdiFont && !list_empty(&dc->gdiFont->child_fonts))
3876         ret = TRUE;
3877     GDI_ReleaseObj(hdc);
3878     TRACE("returning %d\n", ret);
3879     return ret;
3880 }
3881
3882 static BOOL is_hinting_enabled(void)
3883 {
3884     FT_Module mod;
3885
3886     /* Use the >= 2.2.0 function if available */
3887     if(pFT_Get_TrueType_Engine_Type)
3888     {
3889         FT_TrueTypeEngineType type = pFT_Get_TrueType_Engine_Type(library);
3890         return type == FT_TRUETYPE_ENGINE_TYPE_PATENTED;
3891     }
3892
3893     /* otherwise if we've been compiled with < 2.2.0 headers 
3894        use the internal macro */
3895 #ifdef FT_DRIVER_HAS_HINTER
3896     mod = pFT_Get_Module(library, "truetype");
3897     if(mod && FT_DRIVER_HAS_HINTER(mod))
3898         return TRUE;
3899 #endif
3900
3901     return FALSE;
3902 }
3903
3904 /*************************************************************************
3905  *             GetRasterizerCaps   (GDI32.@)
3906  */
3907 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
3908 {
3909     static int hinting = -1;
3910
3911     if(hinting == -1)
3912         hinting = is_hinting_enabled();
3913
3914     lprs->nSize = sizeof(RASTERIZER_STATUS);
3915     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
3916     lprs->nLanguageID = 0;
3917     return TRUE;
3918 }
3919
3920
3921 #else /* HAVE_FREETYPE */
3922
3923 BOOL WineEngInit(void)
3924 {
3925     return FALSE;
3926 }
3927 GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
3928 {
3929     return NULL;
3930 }
3931 BOOL WineEngDestroyFontInstance(HFONT hfont)
3932 {
3933     return FALSE;
3934 }
3935
3936 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
3937 {
3938     return 1;
3939 }
3940
3941 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
3942                                 LPWORD pgi, DWORD flags)
3943 {
3944     return GDI_ERROR;
3945 }
3946
3947 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
3948                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
3949                              const MAT2* lpmat)
3950 {
3951     ERR("called but we don't have FreeType\n");
3952     return GDI_ERROR;
3953 }
3954
3955 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
3956 {
3957     ERR("called but we don't have FreeType\n");
3958     return FALSE;
3959 }
3960
3961 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
3962                                   OUTLINETEXTMETRICW *potm)
3963 {
3964     ERR("called but we don't have FreeType\n");
3965     return 0;
3966 }
3967
3968 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
3969                          LPINT buffer)
3970 {
3971     ERR("called but we don't have FreeType\n");
3972     return FALSE;
3973 }
3974
3975 BOOL WineEngGetCharABCWidths(GdiFont font, UINT firstChar, UINT lastChar,
3976                              LPABC buffer)
3977 {
3978     ERR("called but we don't have FreeType\n");
3979     return FALSE;
3980 }
3981
3982 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
3983                                LPSIZE size)
3984 {
3985     ERR("called but we don't have FreeType\n");
3986     return FALSE;
3987 }
3988
3989 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
3990                                 LPSIZE size)
3991 {
3992     ERR("called but we don't have FreeType\n");
3993     return FALSE;
3994 }
3995
3996 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
3997                          DWORD cbData)
3998 {
3999     ERR("called but we don't have FreeType\n");
4000     return GDI_ERROR;
4001 }
4002
4003 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
4004 {
4005     ERR("called but we don't have FreeType\n");
4006     return 0;
4007 }
4008
4009 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
4010 {
4011     FIXME(":stub\n");
4012     return 1;
4013 }
4014
4015 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
4016 {
4017     FIXME(":stub\n");
4018     return TRUE;
4019 }
4020
4021 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
4022 {
4023     FIXME(":stub\n");
4024     return DEFAULT_CHARSET;
4025 }
4026
4027 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
4028 {
4029     return FALSE;
4030 }
4031
4032 BOOL WINAPI FontIsLinked(HDC hdc)
4033 {
4034     return FALSE;
4035 }
4036
4037 /*************************************************************************
4038  *             GetRasterizerCaps   (GDI32.@)
4039  */
4040 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
4041 {
4042     lprs->nSize = sizeof(RASTERIZER_STATUS);
4043     lprs->wFlags = 0;
4044     lprs->nLanguageID = 0;
4045     return TRUE;
4046 }
4047
4048 #endif /* HAVE_FREETYPE */