dbghelp: Brought dbghelp.h a bit closer to PSDK definitions.
[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 /***************************************************
2683  * According to the MSDN documentation on WideCharToMultiByte,
2684  * certain codepages cannot set the default_used parameter.
2685  * This returns TRUE if the codepage can set that parameter, false else
2686  * so that calls to WideCharToMultiByte don't fail with ERROR_INVALID_PARAMETER
2687  */
2688 static BOOL codepage_sets_default_used(UINT codepage)
2689 {
2690    switch (codepage)
2691    {
2692        case CP_UTF7:
2693        case CP_UTF8:
2694        case CP_SYMBOL:
2695            return FALSE;
2696        default:
2697            return TRUE;
2698    }
2699 }
2700
2701 static FT_UInt get_glyph_index(GdiFont font, UINT glyph)
2702 {
2703     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
2704         WCHAR wc = (WCHAR)glyph;
2705         BOOL default_used;
2706         BOOL *default_used_pointer;
2707         FT_UInt ret;
2708         char buf;
2709         default_used_pointer = NULL;
2710         default_used = FALSE;
2711         if (codepage_sets_default_used(font->codepage))
2712             default_used_pointer = &default_used;
2713         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
2714             ret = 0;
2715         else
2716             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
2717         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
2718         return ret;
2719     }
2720
2721     if(font->charset == SYMBOL_CHARSET && glyph < 0x100)
2722         glyph = glyph + 0xf000;
2723     return pFT_Get_Char_Index(font->ft_face, glyph);
2724 }
2725
2726 /*************************************************************
2727  * WineEngGetGlyphIndices
2728  *
2729  * FIXME: add support for GGI_MARK_NONEXISTING_GLYPHS
2730  */
2731 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
2732                                 LPWORD pgi, DWORD flags)
2733 {
2734     INT i;
2735
2736     for(i = 0; i < count; i++)
2737         pgi[i] = get_glyph_index(font, lpstr[i]);
2738
2739     return count;
2740 }
2741
2742 /*************************************************************
2743  * WineEngGetGlyphOutline
2744  *
2745  * Behaves in exactly the same way as the win32 api GetGlyphOutline
2746  * except that the first parameter is the HWINEENGFONT of the font in
2747  * question rather than an HDC.
2748  *
2749  */
2750 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
2751                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
2752                              const MAT2* lpmat)
2753 {
2754     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
2755     FT_Face ft_face = font->ft_face;
2756     FT_UInt glyph_index;
2757     DWORD width, height, pitch, needed = 0;
2758     FT_Bitmap ft_bitmap;
2759     FT_Error err;
2760     INT left, right, top = 0, bottom = 0;
2761     FT_Angle angle = 0;
2762     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
2763     float widthRatio = 1.0;
2764     FT_Matrix transMat = identityMat;
2765     BOOL needsTransform = FALSE;
2766
2767
2768     TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm,
2769           buflen, buf, lpmat);
2770
2771     if(format & GGO_GLYPH_INDEX) {
2772         glyph_index = glyph;
2773         format &= ~GGO_GLYPH_INDEX;
2774     } else
2775         glyph_index = get_glyph_index(font, glyph);
2776
2777     if(glyph_index >= font->gmsize) {
2778         font->gmsize = (glyph_index / INIT_GM_SIZE + 1) * INIT_GM_SIZE;
2779         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
2780                                font->gmsize * sizeof(*font->gm));
2781     } else {
2782         if(format == GGO_METRICS && font->gm[glyph_index].init) {
2783             memcpy(lpgm, &font->gm[glyph_index].gm, sizeof(*lpgm));
2784             return 1; /* FIXME */
2785         }
2786     }
2787
2788     if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP) || font->aveWidth || lpmat)
2789         load_flags |= FT_LOAD_NO_BITMAP;
2790
2791     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
2792
2793     if(err) {
2794         FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
2795         return GDI_ERROR;
2796     }
2797         
2798     /* Scaling factor */
2799     if (font->aveWidth && font->potm) {
2800         widthRatio = (float)font->aveWidth * font->font_desc.matrix.eM11 / (float) font->potm->otmTextMetrics.tmAveCharWidth;
2801     }
2802
2803     left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
2804     right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
2805
2806     font->gm[glyph_index].adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
2807     font->gm[glyph_index].lsb = left >> 6;
2808     font->gm[glyph_index].bbx = (right - left) >> 6;
2809
2810     /* Scaling transform */
2811     if(font->aveWidth) {
2812         FT_Matrix scaleMat;
2813         scaleMat.xx = FT_FixedFromFloat(widthRatio);
2814         scaleMat.xy = 0;
2815         scaleMat.yx = 0;
2816         scaleMat.yy = (1 << 16);
2817
2818         pFT_Matrix_Multiply(&scaleMat, &transMat);
2819         needsTransform = TRUE;
2820     }
2821
2822     /* Rotation transform */
2823     if(font->orientation) {
2824         FT_Matrix rotationMat;
2825         FT_Vector vecAngle;
2826         angle = FT_FixedFromFloat((float)font->orientation / 10.0);
2827         pFT_Vector_Unit(&vecAngle, angle);
2828         rotationMat.xx = vecAngle.x;
2829         rotationMat.xy = -vecAngle.y;
2830         rotationMat.yx = -rotationMat.xy;
2831         rotationMat.yy = rotationMat.xx;
2832         
2833         pFT_Matrix_Multiply(&rotationMat, &transMat);
2834         needsTransform = TRUE;
2835     }
2836
2837     /* Extra transformation specified by caller */
2838     if (lpmat) {
2839         FT_Matrix extraMat;
2840         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
2841         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
2842         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
2843         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
2844         pFT_Matrix_Multiply(&extraMat, &transMat);
2845         needsTransform = TRUE;
2846     }
2847
2848     if(!needsTransform) {
2849         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
2850         bottom = (ft_face->glyph->metrics.horiBearingY -
2851                   ft_face->glyph->metrics.height) & -64;
2852         lpgm->gmCellIncX = font->gm[glyph_index].adv;
2853         lpgm->gmCellIncY = 0;
2854     } else {
2855         INT xc, yc;
2856         FT_Vector vec;
2857         for(xc = 0; xc < 2; xc++) {
2858             for(yc = 0; yc < 2; yc++) {
2859                 vec.x = (ft_face->glyph->metrics.horiBearingX +
2860                   xc * ft_face->glyph->metrics.width);
2861                 vec.y = ft_face->glyph->metrics.horiBearingY -
2862                   yc * ft_face->glyph->metrics.height;
2863                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
2864                 pFT_Vector_Transform(&vec, &transMat);
2865                 if(xc == 0 && yc == 0) {
2866                     left = right = vec.x;
2867                     top = bottom = vec.y;
2868                 } else {
2869                     if(vec.x < left) left = vec.x;
2870                     else if(vec.x > right) right = vec.x;
2871                     if(vec.y < bottom) bottom = vec.y;
2872                     else if(vec.y > top) top = vec.y;
2873                 }
2874             }
2875         }
2876         left = left & -64;
2877         right = (right + 63) & -64;
2878         bottom = bottom & -64;
2879         top = (top + 63) & -64;
2880
2881         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
2882         vec.x = ft_face->glyph->metrics.horiAdvance;
2883         vec.y = 0;
2884         pFT_Vector_Transform(&vec, &transMat);
2885         lpgm->gmCellIncX = (vec.x+63) >> 6;
2886         lpgm->gmCellIncY = -((vec.y+63) >> 6);
2887     }
2888     lpgm->gmBlackBoxX = (right - left) >> 6;
2889     lpgm->gmBlackBoxY = (top - bottom) >> 6;
2890     lpgm->gmptGlyphOrigin.x = left >> 6;
2891     lpgm->gmptGlyphOrigin.y = top >> 6;
2892
2893     memcpy(&font->gm[glyph_index].gm, lpgm, sizeof(*lpgm));
2894     font->gm[glyph_index].init = TRUE;
2895
2896     if(format == GGO_METRICS)
2897         return 1; /* FIXME */
2898
2899     if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) {
2900         TRACE("loaded a bitmap\n");
2901         return GDI_ERROR;
2902     }
2903
2904     switch(format) {
2905     case GGO_BITMAP:
2906         width = lpgm->gmBlackBoxX;
2907         height = lpgm->gmBlackBoxY;
2908         pitch = ((width + 31) >> 5) << 2;
2909         needed = pitch * height;
2910
2911         if(!buf || !buflen) break;
2912
2913         switch(ft_face->glyph->format) {
2914         case ft_glyph_format_bitmap:
2915           {
2916             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
2917             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
2918             INT h = ft_face->glyph->bitmap.rows;
2919             while(h--) {
2920                 memcpy(dst, src, w);
2921                 src += ft_face->glyph->bitmap.pitch;
2922                 dst += pitch;
2923             }
2924             break;
2925           }
2926
2927         case ft_glyph_format_outline:
2928             ft_bitmap.width = width;
2929             ft_bitmap.rows = height;
2930             ft_bitmap.pitch = pitch;
2931             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
2932             ft_bitmap.buffer = buf;
2933
2934                 if(needsTransform) {
2935                         pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
2936             }
2937
2938             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
2939
2940             /* Note: FreeType will only set 'black' bits for us. */
2941             memset(buf, 0, needed);
2942             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
2943             break;
2944
2945         default:
2946             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
2947             return GDI_ERROR;
2948         }
2949         break;
2950
2951     case GGO_GRAY2_BITMAP:
2952     case GGO_GRAY4_BITMAP:
2953     case GGO_GRAY8_BITMAP:
2954     case WINE_GGO_GRAY16_BITMAP:
2955       {
2956         unsigned int mult, row, col;
2957         BYTE *start, *ptr;
2958
2959         width = lpgm->gmBlackBoxX;
2960         height = lpgm->gmBlackBoxY;
2961         pitch = (width + 3) / 4 * 4;
2962         needed = pitch * height;
2963
2964         if(!buf || !buflen) break;
2965         ft_bitmap.width = width;
2966         ft_bitmap.rows = height;
2967         ft_bitmap.pitch = pitch;
2968         ft_bitmap.pixel_mode = ft_pixel_mode_grays;
2969         ft_bitmap.buffer = buf;
2970
2971         if(needsTransform) {
2972                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
2973         }
2974
2975         pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
2976
2977         memset(ft_bitmap.buffer, 0, buflen);
2978
2979         pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
2980
2981         if(format == GGO_GRAY2_BITMAP)
2982             mult = 4;
2983         else if(format == GGO_GRAY4_BITMAP)
2984             mult = 16;
2985         else if(format == GGO_GRAY8_BITMAP)
2986             mult = 64;
2987         else if(format == WINE_GGO_GRAY16_BITMAP)
2988             break;
2989         else {
2990             assert(0);
2991             break;
2992         }
2993
2994         start = buf;
2995         for(row = 0; row < height; row++) {
2996             ptr = start;
2997             for(col = 0; col < width; col++, ptr++) {
2998                 *ptr = (((int)*ptr) * mult + 128) / 256;
2999             }
3000             start += pitch;
3001         }
3002         break;
3003       }
3004
3005     case GGO_NATIVE:
3006       {
3007         int contour, point = 0, first_pt;
3008         FT_Outline *outline = &ft_face->glyph->outline;
3009         TTPOLYGONHEADER *pph;
3010         TTPOLYCURVE *ppc;
3011         DWORD pph_start, cpfx, type;
3012
3013         if(buflen == 0) buf = NULL;
3014
3015         if (needsTransform && buf) {
3016                 pFT_Outline_Transform(outline, &transMat);
3017         }
3018
3019         for(contour = 0; contour < outline->n_contours; contour++) {
3020             pph_start = needed;
3021             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
3022             first_pt = point;
3023             if(buf) {
3024                 pph->dwType = TT_POLYGON_TYPE;
3025                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3026             }
3027             needed += sizeof(*pph);
3028             point++;
3029             while(point <= outline->contours[contour]) {
3030                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
3031                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3032                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
3033                 cpfx = 0;
3034                 do {
3035                     if(buf)
3036                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3037                     cpfx++;
3038                     point++;
3039                 } while(point <= outline->contours[contour] &&
3040                         (outline->tags[point] & FT_Curve_Tag_On) ==
3041                         (outline->tags[point-1] & FT_Curve_Tag_On));
3042                 /* At the end of a contour Windows adds the start point, but
3043                    only for Beziers */
3044                 if(point > outline->contours[contour] &&
3045                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
3046                     if(buf)
3047                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
3048                     cpfx++;
3049                 } else if(point <= outline->contours[contour] &&
3050                           outline->tags[point] & FT_Curve_Tag_On) {
3051                   /* add closing pt for bezier */
3052                     if(buf)
3053                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3054                     cpfx++;
3055                     point++;
3056                 }
3057                 if(buf) {
3058                     ppc->wType = type;
3059                     ppc->cpfx = cpfx;
3060                 }
3061                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3062             }
3063             if(buf)
3064                 pph->cb = needed - pph_start;
3065         }
3066         break;
3067       }
3068     case GGO_BEZIER:
3069       {
3070         /* Convert the quadratic Beziers to cubic Beziers.
3071            The parametric eqn for a cubic Bezier is, from PLRM:
3072            r(t) = at^3 + bt^2 + ct + r0
3073            with the control points:
3074            r1 = r0 + c/3
3075            r2 = r1 + (c + b)/3
3076            r3 = r0 + c + b + a
3077
3078            A quadratic Beizer has the form:
3079            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
3080
3081            So equating powers of t leads to:
3082            r1 = 2/3 p1 + 1/3 p0
3083            r2 = 2/3 p1 + 1/3 p2
3084            and of course r0 = p0, r3 = p2
3085         */
3086
3087         int contour, point = 0, first_pt;
3088         FT_Outline *outline = &ft_face->glyph->outline;
3089         TTPOLYGONHEADER *pph;
3090         TTPOLYCURVE *ppc;
3091         DWORD pph_start, cpfx, type;
3092         FT_Vector cubic_control[4];
3093         if(buflen == 0) buf = NULL;
3094
3095         if (needsTransform && buf) {
3096                 pFT_Outline_Transform(outline, &transMat);
3097         }
3098
3099         for(contour = 0; contour < outline->n_contours; contour++) {
3100             pph_start = needed;
3101             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
3102             first_pt = point;
3103             if(buf) {
3104                 pph->dwType = TT_POLYGON_TYPE;
3105                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3106             }
3107             needed += sizeof(*pph);
3108             point++;
3109             while(point <= outline->contours[contour]) {
3110                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
3111                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3112                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
3113                 cpfx = 0;
3114                 do {
3115                     if(type == TT_PRIM_LINE) {
3116                         if(buf)
3117                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3118                         cpfx++;
3119                         point++;
3120                     } else {
3121                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
3122                          so cpfx = 3n */
3123
3124                       /* FIXME: Possible optimization in endpoint calculation
3125                          if there are two consecutive curves */
3126                         cubic_control[0] = outline->points[point-1];
3127                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
3128                             cubic_control[0].x += outline->points[point].x + 1;
3129                             cubic_control[0].y += outline->points[point].y + 1;
3130                             cubic_control[0].x >>= 1;
3131                             cubic_control[0].y >>= 1;
3132                         }
3133                         if(point+1 > outline->contours[contour])
3134                             cubic_control[3] = outline->points[first_pt];
3135                         else {
3136                             cubic_control[3] = outline->points[point+1];
3137                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
3138                                 cubic_control[3].x += outline->points[point].x + 1;
3139                                 cubic_control[3].y += outline->points[point].y + 1;
3140                                 cubic_control[3].x >>= 1;
3141                                 cubic_control[3].y >>= 1;
3142                             }
3143                         }
3144                         /* r1 = 1/3 p0 + 2/3 p1
3145                            r2 = 1/3 p2 + 2/3 p1 */
3146                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
3147                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
3148                         cubic_control[2] = cubic_control[1];
3149                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
3150                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
3151                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
3152                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
3153                         if(buf) {
3154                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
3155                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
3156                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
3157                         }
3158                         cpfx += 3;
3159                         point++;
3160                     }
3161                 } while(point <= outline->contours[contour] &&
3162                         (outline->tags[point] & FT_Curve_Tag_On) ==
3163                         (outline->tags[point-1] & FT_Curve_Tag_On));
3164                 /* At the end of a contour Windows adds the start point,
3165                    but only for Beziers and we've already done that.
3166                 */
3167                 if(point <= outline->contours[contour] &&
3168                    outline->tags[point] & FT_Curve_Tag_On) {
3169                   /* This is the closing pt of a bezier, but we've already
3170                      added it, so just inc point and carry on */
3171                     point++;
3172                 }
3173                 if(buf) {
3174                     ppc->wType = type;
3175                     ppc->cpfx = cpfx;
3176                 }
3177                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3178             }
3179             if(buf)
3180                 pph->cb = needed - pph_start;
3181         }
3182         break;
3183       }
3184
3185     default:
3186         FIXME("Unsupported format %d\n", format);
3187         return GDI_ERROR;
3188     }
3189     return needed;
3190 }
3191
3192 static BOOL get_bitmap_text_metrics(GdiFont font)
3193 {
3194     FT_Face ft_face = font->ft_face;
3195 #ifdef HAVE_FREETYPE_FTWINFNT_H
3196     FT_WinFNT_HeaderRec winfnt_header;
3197 #endif
3198     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
3199     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
3200     font->potm->otmSize = size;
3201
3202 #define TM font->potm->otmTextMetrics
3203 #ifdef HAVE_FREETYPE_FTWINFNT_H
3204     if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
3205     {
3206         TM.tmHeight = winfnt_header.pixel_height;
3207         TM.tmAscent = winfnt_header.ascent;
3208         TM.tmDescent = TM.tmHeight - TM.tmAscent;
3209         TM.tmInternalLeading = winfnt_header.internal_leading;
3210         TM.tmExternalLeading = winfnt_header.external_leading;
3211         TM.tmAveCharWidth = winfnt_header.avg_width;
3212         TM.tmMaxCharWidth = winfnt_header.max_width;
3213         TM.tmWeight = winfnt_header.weight;
3214         TM.tmOverhang = 0;
3215         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
3216         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
3217         TM.tmFirstChar = winfnt_header.first_char;
3218         TM.tmLastChar = winfnt_header.last_char;
3219         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
3220         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
3221         TM.tmItalic = winfnt_header.italic;
3222         TM.tmUnderlined = font->underline;
3223         TM.tmStruckOut = font->strikeout;
3224         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
3225         TM.tmCharSet = winfnt_header.charset;
3226     }
3227     else
3228 #endif
3229     {
3230         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
3231         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
3232         TM.tmHeight = TM.tmAscent + TM.tmDescent;
3233         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
3234         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
3235         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
3236         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
3237         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
3238         TM.tmOverhang = 0;
3239         TM.tmDigitizedAspectX = 96; /* FIXME */
3240         TM.tmDigitizedAspectY = 96; /* FIXME */
3241         TM.tmFirstChar = 1;
3242         TM.tmLastChar = 255;
3243         TM.tmDefaultChar = 32;
3244         TM.tmBreakChar = 32;
3245         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
3246         TM.tmUnderlined = font->underline;
3247         TM.tmStruckOut = font->strikeout;
3248         /* NB inverted meaning of TMPF_FIXED_PITCH */
3249         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
3250         TM.tmCharSet = font->charset;
3251     }
3252 #undef TM
3253
3254     return TRUE;
3255 }
3256
3257 /*************************************************************
3258  * WineEngGetTextMetrics
3259  *
3260  */
3261 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
3262 {
3263     if(!font->potm) {
3264         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
3265             if(!get_bitmap_text_metrics(font))
3266                 return FALSE;
3267     }
3268     if(!font->potm) return FALSE;
3269     memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm));
3270
3271     if (font->aveWidth) {
3272         ptm->tmAveCharWidth = font->aveWidth * font->font_desc.matrix.eM11;
3273     }
3274     return TRUE;
3275 }
3276
3277
3278 /*************************************************************
3279  * WineEngGetOutlineTextMetrics
3280  *
3281  */
3282 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
3283                                   OUTLINETEXTMETRICW *potm)
3284 {
3285     FT_Face ft_face = font->ft_face;
3286     UINT needed, lenfam, lensty, ret;
3287     TT_OS2 *pOS2;
3288     TT_HoriHeader *pHori;
3289     TT_Postscript *pPost;
3290     FT_Fixed x_scale, y_scale;
3291     WCHAR *family_nameW, *style_nameW;
3292     static const WCHAR spaceW[] = {' ', '\0'};
3293     char *cp;
3294     INT ascent, descent;
3295
3296     TRACE("font=%p\n", font);
3297
3298     if(!FT_IS_SCALABLE(ft_face))
3299         return 0;
3300
3301     if(font->potm) {
3302         if(cbSize >= font->potm->otmSize)
3303             memcpy(potm, font->potm, font->potm->otmSize);
3304         return font->potm->otmSize;
3305     }
3306
3307
3308     needed = sizeof(*potm);
3309
3310     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
3311     family_nameW = strdupW(font->name);
3312
3313     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
3314       * sizeof(WCHAR);
3315     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
3316     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
3317                         style_nameW, lensty/sizeof(WCHAR));
3318
3319     /* These names should be read from the TT name table */
3320
3321     /* length of otmpFamilyName */
3322     needed += lenfam;
3323
3324     /* length of otmpFaceName */
3325     if(!strcasecmp(ft_face->style_name, "regular")) {
3326       needed += lenfam; /* just the family name */
3327     } else {
3328       needed += lenfam + lensty; /* family + " " + style */
3329     }
3330
3331     /* length of otmpStyleName */
3332     needed += lensty;
3333
3334     /* length of otmpFullName */
3335     needed += lenfam + lensty;
3336
3337
3338     x_scale = ft_face->size->metrics.x_scale;
3339     y_scale = ft_face->size->metrics.y_scale;
3340
3341     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
3342     if(!pOS2) {
3343         FIXME("Can't find OS/2 table - not TT font?\n");
3344         ret = 0;
3345         goto end;
3346     }
3347
3348     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
3349     if(!pHori) {
3350         FIXME("Can't find HHEA table - not TT font?\n");
3351         ret = 0;
3352         goto end;
3353     }
3354
3355     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
3356
3357     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",
3358           pOS2->usWinAscent, pOS2->usWinDescent,
3359           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
3360           ft_face->ascender, ft_face->descender, ft_face->height,
3361           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
3362           ft_face->bbox.yMax, ft_face->bbox.yMin);
3363
3364     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
3365     font->potm->otmSize = needed;
3366
3367 #define TM font->potm->otmTextMetrics
3368
3369     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
3370         ascent = pHori->Ascender;
3371         descent = -pHori->Descender;
3372     } else {
3373         ascent = pOS2->usWinAscent;
3374         descent = pOS2->usWinDescent;
3375     }
3376
3377     if(font->yMax) {
3378         TM.tmAscent = font->yMax;
3379         TM.tmDescent = -font->yMin;
3380         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
3381     } else {
3382         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
3383         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
3384         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
3385                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
3386     }
3387
3388     TM.tmHeight = TM.tmAscent + TM.tmDescent;
3389
3390     /* MSDN says:
3391      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
3392     */
3393     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
3394                  ((ascent + descent) -
3395                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
3396
3397     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
3398     if (TM.tmAveCharWidth == 0) {
3399         TM.tmAveCharWidth = 1; 
3400     }
3401     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
3402     TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
3403     TM.tmOverhang = 0;
3404     TM.tmDigitizedAspectX = 300;
3405     TM.tmDigitizedAspectY = 300;
3406     TM.tmFirstChar = pOS2->usFirstCharIndex;
3407     TM.tmLastChar = pOS2->usLastCharIndex;
3408     TM.tmDefaultChar = pOS2->usDefaultChar;
3409     TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
3410     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
3411     TM.tmUnderlined = font->underline;
3412     TM.tmStruckOut = font->strikeout;
3413
3414     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
3415     if(!FT_IS_FIXED_WIDTH(ft_face) &&
3416        (pOS2->version == 0xFFFFU || 
3417         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
3418         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
3419     else
3420         TM.tmPitchAndFamily = 0;
3421
3422     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
3423     case PAN_FAMILY_SCRIPT:
3424         TM.tmPitchAndFamily |= FF_SCRIPT;
3425         break;
3426     case PAN_FAMILY_DECORATIVE:
3427     case PAN_FAMILY_PICTORIAL:
3428         TM.tmPitchAndFamily |= FF_DECORATIVE;
3429         break;
3430     case PAN_FAMILY_TEXT_DISPLAY:
3431         if(TM.tmPitchAndFamily == 0) /* fixed */
3432             TM.tmPitchAndFamily = FF_MODERN;
3433         else {
3434             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
3435             case PAN_SERIF_NORMAL_SANS:
3436             case PAN_SERIF_OBTUSE_SANS:
3437             case PAN_SERIF_PERP_SANS:
3438                 TM.tmPitchAndFamily |= FF_SWISS;
3439                 break;
3440             default:
3441                 TM.tmPitchAndFamily |= FF_ROMAN;
3442             }
3443         }
3444         break;
3445     default:
3446         TM.tmPitchAndFamily |= FF_DONTCARE;
3447     }
3448
3449     if(FT_IS_SCALABLE(ft_face))
3450         TM.tmPitchAndFamily |= TMPF_VECTOR;
3451     if(FT_IS_SFNT(ft_face))
3452         TM.tmPitchAndFamily |= TMPF_TRUETYPE;
3453
3454     TM.tmCharSet = font->charset;
3455 #undef TM
3456
3457     font->potm->otmFiller = 0;
3458     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
3459     font->potm->otmfsSelection = pOS2->fsSelection;
3460     font->potm->otmfsType = pOS2->fsType;
3461     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
3462     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
3463     font->potm->otmItalicAngle = 0; /* POST table */
3464     font->potm->otmEMSquare = ft_face->units_per_EM;
3465     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
3466     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
3467     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
3468     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
3469     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
3470     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
3471     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
3472     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
3473     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
3474     font->potm->otmMacAscent = 0; /* where do these come from ? */
3475     font->potm->otmMacDescent = 0;
3476     font->potm->otmMacLineGap = 0;
3477     font->potm->otmusMinimumPPEM = 0; /* TT Header */
3478     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
3479     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
3480     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
3481     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
3482     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
3483     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
3484     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
3485     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
3486     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
3487     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
3488     if(!pPost) {
3489         font->potm->otmsUnderscoreSize = 0;
3490         font->potm->otmsUnderscorePosition = 0;
3491     } else {
3492         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
3493         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
3494     }
3495
3496     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
3497     cp = (char*)font->potm + sizeof(*font->potm);
3498     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
3499     strcpyW((WCHAR*)cp, family_nameW);
3500     cp += lenfam;
3501     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
3502     strcpyW((WCHAR*)cp, style_nameW);
3503     cp += lensty;
3504     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
3505     strcpyW((WCHAR*)cp, family_nameW);
3506     if(strcasecmp(ft_face->style_name, "regular")) {
3507         strcatW((WCHAR*)cp, spaceW);
3508         strcatW((WCHAR*)cp, style_nameW);
3509         cp += lenfam + lensty;
3510     } else
3511         cp += lenfam;
3512     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
3513     strcpyW((WCHAR*)cp, family_nameW);
3514     strcatW((WCHAR*)cp, spaceW);
3515     strcatW((WCHAR*)cp, style_nameW);
3516     ret = needed;
3517
3518     if(potm && needed <= cbSize)
3519         memcpy(potm, font->potm, font->potm->otmSize);
3520
3521 end:
3522     HeapFree(GetProcessHeap(), 0, style_nameW);
3523     HeapFree(GetProcessHeap(), 0, family_nameW);
3524
3525     return ret;
3526 }
3527
3528 static BOOL load_child_font(GdiFont font, CHILD_FONT *child)
3529 {
3530     HFONTLIST *hfontlist;
3531     child->font = alloc_font();
3532     child->font->ft_face = OpenFontFile(child->font, child->file_name, child->index, 0, -font->ppem);
3533     if(!child->font->ft_face)
3534     {
3535         free_font(child->font);
3536         child->font = NULL;
3537         return FALSE;
3538     }
3539
3540     child->font->orientation = font->orientation;
3541     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
3542     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
3543     list_add_head(&child->font->hfontlist, &hfontlist->entry);
3544     child->font->base_font = font;
3545     list_add_head(&child_font_list, &child->font->entry);
3546     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
3547     return TRUE;
3548 }
3549
3550 static BOOL get_glyph_index_linked(GdiFont font, UINT c, GdiFont *linked_font, FT_UInt *glyph)
3551 {
3552     FT_UInt g;
3553     CHILD_FONT *child_font;
3554
3555     if(font->base_font)
3556         font = font->base_font;
3557
3558     *linked_font = font;
3559
3560     if((*glyph = get_glyph_index(font, c)))
3561         return TRUE;
3562
3563     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
3564     {
3565         if(!child_font->font)
3566             if(!load_child_font(font, child_font))
3567                 continue;
3568
3569         if(!child_font->font->ft_face)
3570             continue;
3571         g = get_glyph_index(child_font->font, c);
3572         if(g)
3573         {
3574             *glyph = g;
3575             *linked_font = child_font->font;
3576             return TRUE;
3577         }
3578     }
3579     return FALSE;
3580 }
3581
3582 /*************************************************************
3583  * WineEngGetCharWidth
3584  *
3585  */
3586 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
3587                          LPINT buffer)
3588 {
3589     UINT c;
3590     GLYPHMETRICS gm;
3591     FT_UInt glyph_index;
3592     GdiFont linked_font;
3593
3594     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
3595
3596     for(c = firstChar; c <= lastChar; c++) {
3597         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
3598         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3599                                &gm, 0, NULL, NULL);
3600         buffer[c - firstChar] = linked_font->gm[glyph_index].adv;
3601     }
3602     return TRUE;
3603 }
3604
3605 /*************************************************************
3606  * WineEngGetCharABCWidths
3607  *
3608  */
3609 BOOL WineEngGetCharABCWidths(GdiFont font, UINT firstChar, UINT lastChar,
3610                              LPABC buffer)
3611 {
3612     UINT c;
3613     GLYPHMETRICS gm;
3614     FT_UInt glyph_index;
3615     GdiFont linked_font;
3616
3617     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
3618
3619     if(!FT_IS_SCALABLE(font->ft_face))
3620         return FALSE;
3621
3622     for(c = firstChar; c <= lastChar; c++) {
3623         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
3624         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3625                                &gm, 0, NULL, NULL);
3626         buffer[c - firstChar].abcA = linked_font->gm[glyph_index].lsb;
3627         buffer[c - firstChar].abcB = linked_font->gm[glyph_index].bbx;
3628         buffer[c - firstChar].abcC = linked_font->gm[glyph_index].adv - linked_font->gm[glyph_index].lsb -
3629           linked_font->gm[glyph_index].bbx;
3630     }
3631     return TRUE;
3632 }
3633
3634 /*************************************************************
3635  * WineEngGetTextExtentPoint
3636  *
3637  */
3638 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
3639                                LPSIZE size)
3640 {
3641     INT idx;
3642     GLYPHMETRICS gm;
3643     TEXTMETRICW tm;
3644     FT_UInt glyph_index;
3645     GdiFont linked_font;
3646
3647     TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count,
3648           size);
3649
3650     size->cx = 0;
3651     WineEngGetTextMetrics(font, &tm);
3652     size->cy = tm.tmHeight;
3653
3654     for(idx = 0; idx < count; idx++) {
3655         get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
3656         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3657                                &gm, 0, NULL, NULL);
3658         size->cx += linked_font->gm[glyph_index].adv;
3659     }
3660     TRACE("return %ld,%ld\n", size->cx, size->cy);
3661     return TRUE;
3662 }
3663
3664 /*************************************************************
3665  * WineEngGetTextExtentPointI
3666  *
3667  */
3668 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
3669                                 LPSIZE size)
3670 {
3671     INT idx;
3672     GLYPHMETRICS gm;
3673     TEXTMETRICW tm;
3674
3675     TRACE("%p, %p, %d, %p\n", font, indices, count, size);
3676
3677     size->cx = 0;
3678     WineEngGetTextMetrics(font, &tm);
3679     size->cy = tm.tmHeight;
3680
3681     for(idx = 0; idx < count; idx++) {
3682         WineEngGetGlyphOutline(font, indices[idx],
3683                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
3684                                NULL);
3685         size->cx += font->gm[indices[idx]].adv;
3686     }
3687     TRACE("return %ld,%ld\n", size->cx, size->cy);
3688     return TRUE;
3689 }
3690
3691 /*************************************************************
3692  * WineEngGetFontData
3693  *
3694  */
3695 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
3696                          DWORD cbData)
3697 {
3698     FT_Face ft_face = font->ft_face;
3699     DWORD len;
3700     FT_Error err;
3701
3702     TRACE("font=%p, table=%08lx, offset=%08lx, buf=%p, cbData=%lx\n",
3703         font, table, offset, buf, cbData);
3704
3705     if(!FT_IS_SFNT(ft_face))
3706         return GDI_ERROR;
3707
3708     if(!buf || !cbData)
3709         len = 0;
3710     else
3711         len = cbData;
3712
3713     if(table) { /* MS tags differ in endidness from FT ones */
3714         table = table >> 24 | table << 24 |
3715           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
3716     }
3717
3718     /* If the FT_Load_Sfnt_Table function is there we'll use it */
3719     if(pFT_Load_Sfnt_Table) {
3720         /* make sure value of len is the value freetype says it needs */ 
3721         if( buf && len) {
3722             DWORD needed = 0;
3723             err = pFT_Load_Sfnt_Table(ft_face, table, offset, NULL, &needed);
3724             if( !err && needed < len) len = needed;
3725         }
3726         err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, &len);
3727     } else { /* Do it the hard way */
3728         TT_Face tt_face = (TT_Face) ft_face;
3729         SFNT_Interface *sfnt;
3730         if (FT_Version.major==2 && FT_Version.minor==0)
3731         {
3732             /* 2.0.x */
3733             sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
3734         }
3735         else
3736         {
3737             /* A field was added in the middle of the structure in 2.1.x */
3738             sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
3739         }
3740         /* make sure value of len is the value freetype says it needs */ 
3741         if( buf && len) {
3742             DWORD needed = 0;
3743             err = sfnt->load_any(tt_face, table, offset, NULL, &needed);
3744             if( !err && needed < len) len = needed;
3745         }
3746         err = sfnt->load_any(tt_face, table, offset, buf, &len);
3747     }
3748     if(err) {
3749         TRACE("Can't find table %08lx.\n", table);
3750         return GDI_ERROR;
3751     }
3752     return len;
3753 }
3754
3755 /*************************************************************
3756  * WineEngGetTextFace
3757  *
3758  */
3759 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
3760 {
3761     if(str) {
3762         lstrcpynW(str, font->name, count);
3763         return strlenW(font->name);
3764     } else
3765         return strlenW(font->name) + 1;
3766 }
3767
3768 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
3769 {
3770     if (fs) memcpy(fs, &font->fs, sizeof(FONTSIGNATURE));
3771     return font->charset;
3772 }
3773
3774 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
3775 {
3776     GdiFont font = dc->gdiFont, linked_font;
3777     struct list *first_hfont;
3778     BOOL ret;
3779
3780     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
3781     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
3782     if(font == linked_font)
3783         *new_hfont = dc->hFont;
3784     else
3785     {
3786         first_hfont = list_head(&linked_font->hfontlist);
3787         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
3788     }
3789
3790     return ret;
3791 }
3792     
3793
3794 /*************************************************************
3795  *     FontIsLinked
3796  */
3797 BOOL WINAPI FontIsLinked(HDC hdc)
3798 {
3799     DC *dc = DC_GetDCPtr(hdc);
3800     BOOL ret = FALSE;
3801
3802     if(!dc) return FALSE;
3803     if(dc->gdiFont && !list_empty(&dc->gdiFont->child_fonts))
3804         ret = TRUE;
3805     GDI_ReleaseObj(hdc);
3806     TRACE("returning %d\n", ret);
3807     return ret;
3808 }
3809
3810 static BOOL is_hinting_enabled(void)
3811 {
3812     FT_Module mod = pFT_Get_Module(library, "truetype");
3813     if(mod && FT_DRIVER_HAS_HINTER(mod))
3814         return TRUE;
3815
3816     return FALSE;
3817 }
3818
3819 /*************************************************************************
3820  *             GetRasterizerCaps   (GDI32.@)
3821  */
3822 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
3823 {
3824     static int hinting = -1;
3825
3826     if(hinting == -1)
3827         hinting = is_hinting_enabled();
3828
3829     lprs->nSize = sizeof(RASTERIZER_STATUS);
3830     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
3831     lprs->nLanguageID = 0;
3832     return TRUE;
3833 }
3834
3835
3836 #else /* HAVE_FREETYPE */
3837
3838 BOOL WineEngInit(void)
3839 {
3840     return FALSE;
3841 }
3842 GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
3843 {
3844     return NULL;
3845 }
3846 BOOL WineEngDestroyFontInstance(HFONT hfont)
3847 {
3848     return FALSE;
3849 }
3850
3851 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
3852 {
3853     return 1;
3854 }
3855
3856 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
3857                                 LPWORD pgi, DWORD flags)
3858 {
3859     return GDI_ERROR;
3860 }
3861
3862 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
3863                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
3864                              const MAT2* lpmat)
3865 {
3866     ERR("called but we don't have FreeType\n");
3867     return GDI_ERROR;
3868 }
3869
3870 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
3871 {
3872     ERR("called but we don't have FreeType\n");
3873     return FALSE;
3874 }
3875
3876 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
3877                                   OUTLINETEXTMETRICW *potm)
3878 {
3879     ERR("called but we don't have FreeType\n");
3880     return 0;
3881 }
3882
3883 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
3884                          LPINT buffer)
3885 {
3886     ERR("called but we don't have FreeType\n");
3887     return FALSE;
3888 }
3889
3890 BOOL WineEngGetCharABCWidths(GdiFont font, UINT firstChar, UINT lastChar,
3891                              LPABC buffer)
3892 {
3893     ERR("called but we don't have FreeType\n");
3894     return FALSE;
3895 }
3896
3897 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
3898                                LPSIZE size)
3899 {
3900     ERR("called but we don't have FreeType\n");
3901     return FALSE;
3902 }
3903
3904 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
3905                                 LPSIZE size)
3906 {
3907     ERR("called but we don't have FreeType\n");
3908     return FALSE;
3909 }
3910
3911 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
3912                          DWORD cbData)
3913 {
3914     ERR("called but we don't have FreeType\n");
3915     return GDI_ERROR;
3916 }
3917
3918 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
3919 {
3920     ERR("called but we don't have FreeType\n");
3921     return 0;
3922 }
3923
3924 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
3925 {
3926     FIXME(":stub\n");
3927     return 1;
3928 }
3929
3930 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
3931 {
3932     FIXME(":stub\n");
3933     return TRUE;
3934 }
3935
3936 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
3937 {
3938     FIXME(":stub\n");
3939     return DEFAULT_CHARSET;
3940 }
3941
3942 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
3943 {
3944     return FALSE;
3945 }
3946
3947 BOOL WINAPI FontIsLinked(HDC hdc)
3948 {
3949     return FALSE;
3950 }
3951
3952 /*************************************************************************
3953  *             GetRasterizerCaps   (GDI32.@)
3954  */
3955 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
3956 {
3957     lprs->nSize = sizeof(RASTERIZER_STATUS);
3958     lprs->wFlags = 0;
3959     lprs->nLanguageID = 0;
3960     return TRUE;
3961 }
3962
3963 #endif /* HAVE_FREETYPE */