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