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