Add a Wine specific flag to GetRasterizeCaps that reports whether
[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;
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     LIST_FOR_EACH(family_elem_ptr, &font_list) {
2216         family = LIST_ENTRY(family_elem_ptr, Family, entry);
2217         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2218             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2219             if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
2220                 if(face->scalable || can_use_bitmap)
2221                     goto found;
2222         }
2223     }
2224
2225     
2226     LIST_FOR_EACH(family_elem_ptr, &font_list) {
2227         family = LIST_ENTRY(family_elem_ptr, Family, entry);
2228         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2229             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2230             if(face->scalable || can_use_bitmap) {
2231                 csi.fs.fsCsb[0] = 0;
2232                 FIXME("just using first face for now\n");
2233                 goto found;
2234             }
2235         }
2236     }
2237     FIXME("can't find a single appropriate font - bailing\n");
2238     free_font(ret);
2239     return NULL;
2240
2241 found:
2242     it = lf.lfItalic ? 1 : 0;
2243     bd = lf.lfWeight > 550 ? 1 : 0;
2244
2245     height = GDI_ROUND( (FLOAT)lf.lfHeight * dc->xformWorld2Vport.eM22 );
2246     height = lf.lfHeight < 0 ? -abs(height) : abs(height);
2247
2248     face = best = NULL;
2249     LIST_FOR_EACH(face_elem_ptr, &family->faces) {
2250         face = LIST_ENTRY(face_elem_ptr, Face, entry);
2251         if(!(face->Italic ^ it) && !(face->Bold ^ bd) &&
2252            ((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])) {
2253             if(face->scalable)
2254                 break;
2255             if(height > 0)
2256                 newdiff = height - (signed int)(face->size.y_ppem >> 6);
2257             else
2258                 newdiff = -height - ((signed int)(face->size.y_ppem >> 6) - face->size.internal_leading);
2259             if(!best || (diff > 0 && newdiff < diff && newdiff >= 0) ||
2260                (diff < 0 && newdiff > diff)) {
2261                 TRACE("%ld is better for %d diff was %d\n", face->size.y_ppem >> 6, height, diff);
2262                 diff = newdiff;
2263                 best = face;
2264                 if(diff == 0)
2265                     break;
2266             }
2267         }
2268         face = NULL;
2269     }
2270     if(!face && best)
2271         face = best;
2272     else if(!face) {
2273         best = NULL;
2274         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
2275             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2276             if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0]) {
2277                 if(face->scalable)
2278                     break;
2279                 if(height > 0)
2280                     newdiff = height - (signed int)(face->size.y_ppem >> 6);
2281                 else
2282                     newdiff = -height - ((signed int)(face->size.y_ppem >> 6) - face->size.internal_leading);
2283                 if(!best || (diff > 0 && newdiff < diff && newdiff >= 0) ||
2284                    (diff < 0 && newdiff > diff)) {
2285                     TRACE("%ld is better for %d diff was %d\n", face->size.y_ppem >> 6, height, diff);
2286                     diff = newdiff;
2287                     best = face;
2288                     if(diff == 0)
2289                         break;
2290                 }
2291             }
2292             face = NULL;
2293         }
2294         if(!face && best)
2295             face = best;
2296         if(it && !face->Italic) ret->fake_italic = TRUE;
2297         if(bd && !face->Bold) ret->fake_bold = TRUE;
2298     }
2299
2300     memcpy(&ret->fs, &face->fs, sizeof(FONTSIGNATURE));
2301
2302     if(csi.fs.fsCsb[0]) {
2303         ret->charset = lf.lfCharSet;
2304         ret->codepage = csi.ciACP;
2305     }
2306     else
2307         ret->charset = get_nearest_charset(face, &ret->codepage);
2308
2309     TRACE("Chosen: %s %s (%s:%ld)\n", debugstr_w(family->FamilyName),
2310           debugstr_w(face->StyleName), face->file, face->face_index);
2311
2312     if(!face->scalable) {
2313         width = face->size.x_ppem >> 6;
2314         height = face->size.y_ppem >> 6;
2315     }
2316     ret->ft_face = OpenFontFile(ret, face->file, face->face_index, width, height);
2317
2318     if (!ret->ft_face)
2319     {
2320         free_font( ret );
2321         return 0;
2322     }
2323
2324     if (ret->charset == SYMBOL_CHARSET && 
2325         !pFT_Select_Charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) {
2326         /* No ops */
2327     }
2328     else if (!pFT_Select_Charmap(ret->ft_face, FT_ENCODING_UNICODE)) {
2329         /* No ops */
2330     }
2331     else {
2332         pFT_Select_Charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN);
2333     }
2334
2335     ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0;
2336     ret->name = strdupW(family->FamilyName);
2337     ret->underline = lf.lfUnderline ? 0xff : 0;
2338     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
2339     create_child_font_list(ret);
2340
2341     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
2342
2343     ret->aveWidth = FT_IS_SCALABLE(ret->ft_face) ? lf.lfWidth : 0;
2344     list_add_head(&gdi_font_list, &ret->entry);
2345     return ret;
2346 }
2347
2348 static void dump_gdi_font_list(void)
2349 {
2350     GdiFont gdiFont;
2351     struct list *elem_ptr;
2352
2353     TRACE("---------- gdiFont Cache ----------\n");
2354     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
2355         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
2356         TRACE("gdiFont=%p %s %ld\n",
2357               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
2358     }
2359
2360     TRACE("---------- Unused gdiFont Cache ----------\n");
2361     LIST_FOR_EACH(elem_ptr, &unused_gdi_font_list) {
2362         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
2363         TRACE("gdiFont=%p %s %ld\n",
2364               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
2365     }
2366 }
2367
2368 /*************************************************************
2369  * WineEngDestroyFontInstance
2370  *
2371  * free the gdiFont associated with this handle
2372  *
2373  */
2374 BOOL WineEngDestroyFontInstance(HFONT handle)
2375 {
2376     GdiFont gdiFont;
2377     HFONTLIST *hflist;
2378     BOOL ret = FALSE;
2379     struct list *font_elem_ptr, *hfontlist_elem_ptr;
2380     int i = 0;
2381
2382     LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry)
2383     {
2384         struct list *first_hfont = list_head(&gdiFont->hfontlist);
2385         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
2386         if(hflist->hfont == handle)
2387         {
2388             TRACE("removing child font %p from child list\n", gdiFont);
2389             list_remove(&gdiFont->entry);
2390             return TRUE;
2391         }
2392     }
2393
2394     TRACE("destroying hfont=%p\n", handle);
2395     if(TRACE_ON(font))
2396         dump_gdi_font_list();
2397
2398     font_elem_ptr = list_head(&gdi_font_list);
2399     while(font_elem_ptr) {
2400         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2401         font_elem_ptr = list_next(&gdi_font_list, font_elem_ptr);
2402
2403         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
2404         while(hfontlist_elem_ptr) {
2405             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
2406             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
2407             if(hflist->hfont == handle) {
2408                 list_remove(&hflist->entry);
2409                 HeapFree(GetProcessHeap(), 0, hflist);
2410                 ret = TRUE;
2411             }
2412         }
2413         if(list_empty(&gdiFont->hfontlist)) {
2414             TRACE("Moving to Unused list\n");
2415             list_remove(&gdiFont->entry);
2416             list_add_head(&unused_gdi_font_list, &gdiFont->entry);
2417         }
2418     }
2419
2420
2421     font_elem_ptr = list_head(&unused_gdi_font_list);
2422     while(font_elem_ptr && i++ < UNUSED_CACHE_SIZE)
2423         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
2424     while(font_elem_ptr) {
2425         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2426         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
2427         TRACE("freeing %p\n", gdiFont);
2428         list_remove(&gdiFont->entry);
2429         free_font(gdiFont);
2430     }
2431     return ret;
2432 }
2433
2434 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
2435                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
2436 {
2437     OUTLINETEXTMETRICW *potm = NULL;
2438     UINT size;
2439     TEXTMETRICW tm, *ptm;
2440     GdiFont font = alloc_font();
2441     LONG width, height;
2442
2443     if(face->scalable) {
2444         height = 100;
2445         width = 0;
2446     } else {
2447         height = face->size.y_ppem >> 6;
2448         width = face->size.x_ppem >> 6;
2449     }
2450     
2451     if (!(font->ft_face = OpenFontFile(font, face->file, face->face_index, width, height)))
2452     {
2453         free_font(font);
2454         return;
2455     }
2456
2457     font->name = strdupW(face->family->FamilyName);
2458
2459     memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
2460
2461     size = WineEngGetOutlineTextMetrics(font, 0, NULL);
2462     if(size) {
2463         potm = HeapAlloc(GetProcessHeap(), 0, size);
2464         WineEngGetOutlineTextMetrics(font, size, potm);
2465         ptm = (TEXTMETRICW*)&potm->otmTextMetrics;
2466     } else {
2467         WineEngGetTextMetrics(font, &tm);
2468         ptm = &tm;
2469     }
2470         
2471     pntm->ntmTm.tmHeight = pelf->elfLogFont.lfHeight = ptm->tmHeight;
2472     pntm->ntmTm.tmAscent = ptm->tmAscent;
2473     pntm->ntmTm.tmDescent = ptm->tmDescent;
2474     pntm->ntmTm.tmInternalLeading = ptm->tmInternalLeading;
2475     pntm->ntmTm.tmExternalLeading = ptm->tmExternalLeading;
2476     pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWidth = ptm->tmAveCharWidth;
2477     pntm->ntmTm.tmMaxCharWidth = ptm->tmMaxCharWidth;
2478     pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = ptm->tmWeight;
2479     pntm->ntmTm.tmOverhang = ptm->tmOverhang;
2480     pntm->ntmTm.tmDigitizedAspectX = ptm->tmDigitizedAspectX;
2481     pntm->ntmTm.tmDigitizedAspectY = ptm->tmDigitizedAspectY;
2482     pntm->ntmTm.tmFirstChar = ptm->tmFirstChar;
2483     pntm->ntmTm.tmLastChar = ptm->tmLastChar;
2484     pntm->ntmTm.tmDefaultChar = ptm->tmDefaultChar;
2485     pntm->ntmTm.tmBreakChar = ptm->tmBreakChar;
2486     pntm->ntmTm.tmItalic = pelf->elfLogFont.lfItalic = ptm->tmItalic;
2487     pntm->ntmTm.tmUnderlined = pelf->elfLogFont.lfUnderline = ptm->tmUnderlined;
2488     pntm->ntmTm.tmStruckOut = pelf->elfLogFont.lfStrikeOut = ptm->tmStruckOut;
2489     pntm->ntmTm.tmPitchAndFamily = ptm->tmPitchAndFamily;
2490     pelf->elfLogFont.lfPitchAndFamily = (ptm->tmPitchAndFamily & 0xf1) + 1;
2491     pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = ptm->tmCharSet;
2492     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
2493     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
2494     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
2495
2496     *ptype = ptm->tmPitchAndFamily & TMPF_TRUETYPE ? TRUETYPE_FONTTYPE : 0;
2497     if(!(ptm->tmPitchAndFamily & TMPF_VECTOR))
2498         *ptype |= RASTER_FONTTYPE;
2499
2500     pntm->ntmTm.ntmFlags = ptm->tmItalic ? NTM_ITALIC : 0;
2501     if(ptm->tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD;
2502     if(pntm->ntmTm.ntmFlags == 0) pntm->ntmTm.ntmFlags = NTM_REGULAR;
2503
2504     pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
2505     pntm->ntmTm.ntmAvgWidth = pntm->ntmTm.tmAveCharWidth;
2506     memset(&pntm->ntmFontSig, 0, sizeof(FONTSIGNATURE));
2507
2508     if(potm) {
2509         pntm->ntmTm.ntmSizeEM = potm->otmEMSquare;
2510
2511         lstrcpynW(pelf->elfLogFont.lfFaceName,
2512                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFamilyName),
2513                  LF_FACESIZE);
2514         lstrcpynW(pelf->elfFullName,
2515                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFaceName),
2516                  LF_FULLFACESIZE);
2517         lstrcpynW(pelf->elfStyle,
2518                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName),
2519                  LF_FACESIZE);
2520
2521         HeapFree(GetProcessHeap(), 0, potm);
2522     } else {
2523         pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
2524
2525         lstrcpynW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
2526         lstrcpynW(pelf->elfFullName, face->family->FamilyName, LF_FACESIZE);
2527         pelf->elfStyle[0] = '\0';
2528     }
2529
2530     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
2531
2532     free_font(font);
2533 }
2534
2535 /*************************************************************
2536  * WineEngEnumFonts
2537  *
2538  */
2539 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
2540 {
2541     Family *family;
2542     Face *face;
2543     struct list *family_elem_ptr, *face_elem_ptr;
2544     ENUMLOGFONTEXW elf;
2545     NEWTEXTMETRICEXW ntm;
2546     DWORD type, ret = 1;
2547     FONTSIGNATURE fs;
2548     CHARSETINFO csi;
2549     LOGFONTW lf;
2550     int i;
2551
2552     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
2553
2554     if(plf->lfFaceName[0]) {
2555         FontSubst *psub;
2556         for(psub = substlist; psub; psub = psub->next)
2557             if(!strcmpiW(plf->lfFaceName, psub->from.name) &&
2558                (psub->from.charset == -1 ||
2559                 psub->from.charset == plf->lfCharSet))
2560                 break;
2561         if(psub) {
2562             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
2563                   debugstr_w(psub->to.name));
2564             memcpy(&lf, plf, sizeof(lf));
2565             strcpyW(lf.lfFaceName, psub->to.name);
2566             plf = &lf;
2567         }
2568
2569         LIST_FOR_EACH(family_elem_ptr, &font_list) {
2570             family = LIST_ENTRY(family_elem_ptr, Family, entry);
2571             if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
2572                 LIST_FOR_EACH(face_elem_ptr, &family->faces) {
2573                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
2574                     GetEnumStructs(face, &elf, &ntm, &type);
2575                     for(i = 0; i < 32; i++) {
2576                         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
2577                             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
2578                             strcpyW(elf.elfScript, OEM_DOSW);
2579                             i = 32; /* break out of loop */
2580                         } else if(!(face->fs.fsCsb[0] & (1L << i)))
2581                             continue;
2582                         else {
2583                             fs.fsCsb[0] = 1L << i;
2584                             fs.fsCsb[1] = 0;
2585                             if(!TranslateCharsetInfo(fs.fsCsb, &csi,
2586                                                      TCI_SRCFONTSIG))
2587                                 csi.ciCharset = DEFAULT_CHARSET;
2588                             if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
2589                             if(csi.ciCharset != DEFAULT_CHARSET) {
2590                                 elf.elfLogFont.lfCharSet =
2591                                     ntm.ntmTm.tmCharSet = csi.ciCharset;
2592                                 if(ElfScriptsW[i])
2593                                     strcpyW(elf.elfScript, ElfScriptsW[i]);
2594                                 else
2595                                     FIXME("Unknown elfscript for bit %d\n", i);
2596                             }
2597                         }
2598                         TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
2599                               debugstr_w(elf.elfLogFont.lfFaceName),
2600                               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
2601                               csi.ciCharset, type, debugstr_w(elf.elfScript),
2602                               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
2603                               ntm.ntmTm.ntmFlags);
2604                         ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
2605                         if(!ret) goto end;
2606                     }
2607                 }
2608             }
2609         }
2610     } else {
2611         LIST_FOR_EACH(family_elem_ptr, &font_list) {
2612             family = LIST_ENTRY(family_elem_ptr, Family, entry);
2613             face_elem_ptr = list_head(&family->faces);
2614             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2615             GetEnumStructs(face, &elf, &ntm, &type);
2616             for(i = 0; i < 32; i++) {
2617                 if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
2618                     elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
2619                     strcpyW(elf.elfScript, OEM_DOSW);
2620                     i = 32; /* break out of loop */
2621                 } else if(!(face->fs.fsCsb[0] & (1L << i)))
2622                     continue;
2623                 else {
2624                     fs.fsCsb[0] = 1L << i;
2625                     fs.fsCsb[1] = 0;
2626                     if(!TranslateCharsetInfo(fs.fsCsb, &csi,
2627                                              TCI_SRCFONTSIG))
2628                         csi.ciCharset = DEFAULT_CHARSET;
2629                     if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
2630                     if(csi.ciCharset != DEFAULT_CHARSET) {
2631                         elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet =
2632                           csi.ciCharset;
2633                           if(ElfScriptsW[i])
2634                               strcpyW(elf.elfScript, ElfScriptsW[i]);
2635                           else
2636                               FIXME("Unknown elfscript for bit %d\n", i);
2637                     }
2638                 }
2639                 TRACE("enuming face %s full %s style %s charset = %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
2640                       debugstr_w(elf.elfLogFont.lfFaceName),
2641                       debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
2642                       csi.ciCharset, type, debugstr_w(elf.elfScript),
2643                       elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
2644                       ntm.ntmTm.ntmFlags);
2645                 ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
2646                 if(!ret) goto end;
2647             }
2648         }
2649     }
2650 end:
2651     return ret;
2652 }
2653
2654 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
2655 {
2656     pt->x.value = vec->x >> 6;
2657     pt->x.fract = (vec->x & 0x3f) << 10;
2658     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
2659     pt->y.value = vec->y >> 6;
2660     pt->y.fract = (vec->y & 0x3f) << 10;
2661     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
2662     return;
2663 }
2664
2665 static FT_UInt get_glyph_index(GdiFont font, UINT glyph)
2666 {
2667     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
2668         WCHAR wc = (WCHAR)glyph;
2669         BOOL default_used;
2670         FT_UInt ret;
2671         char buf;
2672         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, &default_used) || default_used)
2673             ret = 0;
2674         else
2675             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
2676         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
2677         return ret;
2678     }
2679
2680     if(font->charset == SYMBOL_CHARSET && glyph < 0x100)
2681         glyph = glyph + 0xf000;
2682     return pFT_Get_Char_Index(font->ft_face, glyph);
2683 }
2684
2685 /*************************************************************
2686  * WineEngGetGlyphIndices
2687  *
2688  * FIXME: add support for GGI_MARK_NONEXISTING_GLYPHS
2689  */
2690 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
2691                                 LPWORD pgi, DWORD flags)
2692 {
2693     INT i;
2694
2695     for(i = 0; i < count; i++)
2696         pgi[i] = get_glyph_index(font, lpstr[i]);
2697
2698     return count;
2699 }
2700
2701 /*************************************************************
2702  * WineEngGetGlyphOutline
2703  *
2704  * Behaves in exactly the same way as the win32 api GetGlyphOutline
2705  * except that the first parameter is the HWINEENGFONT of the font in
2706  * question rather than an HDC.
2707  *
2708  */
2709 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
2710                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
2711                              const MAT2* lpmat)
2712 {
2713     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
2714     FT_Face ft_face = font->ft_face;
2715     FT_UInt glyph_index;
2716     DWORD width, height, pitch, needed = 0;
2717     FT_Bitmap ft_bitmap;
2718     FT_Error err;
2719     INT left, right, top = 0, bottom = 0;
2720     FT_Angle angle = 0;
2721     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
2722     float widthRatio = 1.0;
2723     FT_Matrix transMat = identityMat;
2724     BOOL needsTransform = FALSE;
2725
2726
2727     TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm,
2728           buflen, buf, lpmat);
2729
2730     if(format & GGO_GLYPH_INDEX) {
2731         glyph_index = glyph;
2732         format &= ~GGO_GLYPH_INDEX;
2733     } else
2734         glyph_index = get_glyph_index(font, glyph);
2735
2736     if(glyph_index >= font->gmsize) {
2737         font->gmsize = (glyph_index / INIT_GM_SIZE + 1) * INIT_GM_SIZE;
2738         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
2739                                font->gmsize * sizeof(*font->gm));
2740     } else {
2741         if(format == GGO_METRICS && font->gm[glyph_index].init) {
2742             memcpy(lpgm, &font->gm[glyph_index].gm, sizeof(*lpgm));
2743             return 1; /* FIXME */
2744         }
2745     }
2746
2747     if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP) || font->aveWidth || lpmat)
2748         load_flags |= FT_LOAD_NO_BITMAP;
2749
2750     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
2751
2752     if(err) {
2753         FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
2754         return GDI_ERROR;
2755     }
2756         
2757     /* Scaling factor */
2758     if (font->aveWidth && font->potm) {
2759         widthRatio = (float)font->aveWidth * font->font_desc.matrix.eM11 / (float) font->potm->otmTextMetrics.tmAveCharWidth;
2760     }
2761
2762     left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
2763     right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
2764
2765     font->gm[glyph_index].adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
2766     font->gm[glyph_index].lsb = left >> 6;
2767     font->gm[glyph_index].bbx = (right - left) >> 6;
2768
2769     /* Scaling transform */
2770     if(font->aveWidth) {
2771         FT_Matrix scaleMat;
2772         scaleMat.xx = FT_FixedFromFloat(widthRatio);
2773         scaleMat.xy = 0;
2774         scaleMat.yx = 0;
2775         scaleMat.yy = (1 << 16);
2776
2777         pFT_Matrix_Multiply(&scaleMat, &transMat);
2778         needsTransform = TRUE;
2779     }
2780
2781     /* Rotation transform */
2782     if(font->orientation) {
2783         FT_Matrix rotationMat;
2784         FT_Vector vecAngle;
2785         angle = FT_FixedFromFloat((float)font->orientation / 10.0);
2786         pFT_Vector_Unit(&vecAngle, angle);
2787         rotationMat.xx = vecAngle.x;
2788         rotationMat.xy = -vecAngle.y;
2789         rotationMat.yx = -rotationMat.xy;
2790         rotationMat.yy = rotationMat.xx;
2791         
2792         pFT_Matrix_Multiply(&rotationMat, &transMat);
2793         needsTransform = TRUE;
2794     }
2795
2796     /* Extra transformation specified by caller */
2797     if (lpmat) {
2798         FT_Matrix extraMat;
2799         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
2800         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
2801         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
2802         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
2803         pFT_Matrix_Multiply(&extraMat, &transMat);
2804         needsTransform = TRUE;
2805     }
2806
2807     if(!needsTransform) {
2808         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
2809         bottom = (ft_face->glyph->metrics.horiBearingY -
2810                   ft_face->glyph->metrics.height) & -64;
2811         lpgm->gmCellIncX = font->gm[glyph_index].adv;
2812         lpgm->gmCellIncY = 0;
2813     } else {
2814         INT xc, yc;
2815         FT_Vector vec;
2816         for(xc = 0; xc < 2; xc++) {
2817             for(yc = 0; yc < 2; yc++) {
2818                 vec.x = (ft_face->glyph->metrics.horiBearingX +
2819                   xc * ft_face->glyph->metrics.width);
2820                 vec.y = ft_face->glyph->metrics.horiBearingY -
2821                   yc * ft_face->glyph->metrics.height;
2822                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
2823                 pFT_Vector_Transform(&vec, &transMat);
2824                 if(xc == 0 && yc == 0) {
2825                     left = right = vec.x;
2826                     top = bottom = vec.y;
2827                 } else {
2828                     if(vec.x < left) left = vec.x;
2829                     else if(vec.x > right) right = vec.x;
2830                     if(vec.y < bottom) bottom = vec.y;
2831                     else if(vec.y > top) top = vec.y;
2832                 }
2833             }
2834         }
2835         left = left & -64;
2836         right = (right + 63) & -64;
2837         bottom = bottom & -64;
2838         top = (top + 63) & -64;
2839
2840         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
2841         vec.x = ft_face->glyph->metrics.horiAdvance;
2842         vec.y = 0;
2843         pFT_Vector_Transform(&vec, &transMat);
2844         lpgm->gmCellIncX = (vec.x+63) >> 6;
2845         lpgm->gmCellIncY = -((vec.y+63) >> 6);
2846     }
2847     lpgm->gmBlackBoxX = (right - left) >> 6;
2848     lpgm->gmBlackBoxY = (top - bottom) >> 6;
2849     lpgm->gmptGlyphOrigin.x = left >> 6;
2850     lpgm->gmptGlyphOrigin.y = top >> 6;
2851
2852     memcpy(&font->gm[glyph_index].gm, lpgm, sizeof(*lpgm));
2853     font->gm[glyph_index].init = TRUE;
2854
2855     if(format == GGO_METRICS)
2856         return 1; /* FIXME */
2857
2858     if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) {
2859         TRACE("loaded a bitmap\n");
2860         return GDI_ERROR;
2861     }
2862
2863     switch(format) {
2864     case GGO_BITMAP:
2865         width = lpgm->gmBlackBoxX;
2866         height = lpgm->gmBlackBoxY;
2867         pitch = ((width + 31) >> 5) << 2;
2868         needed = pitch * height;
2869
2870         if(!buf || !buflen) break;
2871
2872         switch(ft_face->glyph->format) {
2873         case ft_glyph_format_bitmap:
2874           {
2875             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
2876             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
2877             INT h = ft_face->glyph->bitmap.rows;
2878             while(h--) {
2879                 memcpy(dst, src, w);
2880                 src += ft_face->glyph->bitmap.pitch;
2881                 dst += pitch;
2882             }
2883             break;
2884           }
2885
2886         case ft_glyph_format_outline:
2887             ft_bitmap.width = width;
2888             ft_bitmap.rows = height;
2889             ft_bitmap.pitch = pitch;
2890             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
2891             ft_bitmap.buffer = buf;
2892
2893                 if(needsTransform) {
2894                         pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
2895             }
2896
2897             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
2898
2899             /* Note: FreeType will only set 'black' bits for us. */
2900             memset(buf, 0, needed);
2901             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
2902             break;
2903
2904         default:
2905             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
2906             return GDI_ERROR;
2907         }
2908         break;
2909
2910     case GGO_GRAY2_BITMAP:
2911     case GGO_GRAY4_BITMAP:
2912     case GGO_GRAY8_BITMAP:
2913     case WINE_GGO_GRAY16_BITMAP:
2914       {
2915         unsigned int mult, row, col;
2916         BYTE *start, *ptr;
2917
2918         width = lpgm->gmBlackBoxX;
2919         height = lpgm->gmBlackBoxY;
2920         pitch = (width + 3) / 4 * 4;
2921         needed = pitch * height;
2922
2923         if(!buf || !buflen) break;
2924         ft_bitmap.width = width;
2925         ft_bitmap.rows = height;
2926         ft_bitmap.pitch = pitch;
2927         ft_bitmap.pixel_mode = ft_pixel_mode_grays;
2928         ft_bitmap.buffer = buf;
2929
2930         if(needsTransform) {
2931                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
2932         }
2933
2934         pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
2935
2936         memset(ft_bitmap.buffer, 0, buflen);
2937
2938         pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
2939
2940         if(format == GGO_GRAY2_BITMAP)
2941             mult = 4;
2942         else if(format == GGO_GRAY4_BITMAP)
2943             mult = 16;
2944         else if(format == GGO_GRAY8_BITMAP)
2945             mult = 64;
2946         else if(format == WINE_GGO_GRAY16_BITMAP)
2947             break;
2948         else {
2949             assert(0);
2950             break;
2951         }
2952
2953         start = buf;
2954         for(row = 0; row < height; row++) {
2955             ptr = start;
2956             for(col = 0; col < width; col++, ptr++) {
2957                 *ptr = (((int)*ptr) * mult + 128) / 256;
2958             }
2959             start += pitch;
2960         }
2961         break;
2962       }
2963
2964     case GGO_NATIVE:
2965       {
2966         int contour, point = 0, first_pt;
2967         FT_Outline *outline = &ft_face->glyph->outline;
2968         TTPOLYGONHEADER *pph;
2969         TTPOLYCURVE *ppc;
2970         DWORD pph_start, cpfx, type;
2971
2972         if(buflen == 0) buf = NULL;
2973
2974         if (needsTransform && buf) {
2975                 pFT_Outline_Transform(outline, &transMat);
2976         }
2977
2978         for(contour = 0; contour < outline->n_contours; contour++) {
2979             pph_start = needed;
2980             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
2981             first_pt = point;
2982             if(buf) {
2983                 pph->dwType = TT_POLYGON_TYPE;
2984                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
2985             }
2986             needed += sizeof(*pph);
2987             point++;
2988             while(point <= outline->contours[contour]) {
2989                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
2990                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
2991                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
2992                 cpfx = 0;
2993                 do {
2994                     if(buf)
2995                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
2996                     cpfx++;
2997                     point++;
2998                 } while(point <= outline->contours[contour] &&
2999                         (outline->tags[point] & FT_Curve_Tag_On) ==
3000                         (outline->tags[point-1] & FT_Curve_Tag_On));
3001                 /* At the end of a contour Windows adds the start point, but
3002                    only for Beziers */
3003                 if(point > outline->contours[contour] &&
3004                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
3005                     if(buf)
3006                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
3007                     cpfx++;
3008                 } else if(point <= outline->contours[contour] &&
3009                           outline->tags[point] & FT_Curve_Tag_On) {
3010                   /* add closing pt for bezier */
3011                     if(buf)
3012                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3013                     cpfx++;
3014                     point++;
3015                 }
3016                 if(buf) {
3017                     ppc->wType = type;
3018                     ppc->cpfx = cpfx;
3019                 }
3020                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3021             }
3022             if(buf)
3023                 pph->cb = needed - pph_start;
3024         }
3025         break;
3026       }
3027     case GGO_BEZIER:
3028       {
3029         /* Convert the quadratic Beziers to cubic Beziers.
3030            The parametric eqn for a cubic Bezier is, from PLRM:
3031            r(t) = at^3 + bt^2 + ct + r0
3032            with the control points:
3033            r1 = r0 + c/3
3034            r2 = r1 + (c + b)/3
3035            r3 = r0 + c + b + a
3036
3037            A quadratic Beizer has the form:
3038            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
3039
3040            So equating powers of t leads to:
3041            r1 = 2/3 p1 + 1/3 p0
3042            r2 = 2/3 p1 + 1/3 p2
3043            and of course r0 = p0, r3 = p2
3044         */
3045
3046         int contour, point = 0, first_pt;
3047         FT_Outline *outline = &ft_face->glyph->outline;
3048         TTPOLYGONHEADER *pph;
3049         TTPOLYCURVE *ppc;
3050         DWORD pph_start, cpfx, type;
3051         FT_Vector cubic_control[4];
3052         if(buflen == 0) buf = NULL;
3053
3054         if (needsTransform && buf) {
3055                 pFT_Outline_Transform(outline, &transMat);
3056         }
3057
3058         for(contour = 0; contour < outline->n_contours; contour++) {
3059             pph_start = needed;
3060             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
3061             first_pt = point;
3062             if(buf) {
3063                 pph->dwType = TT_POLYGON_TYPE;
3064                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3065             }
3066             needed += sizeof(*pph);
3067             point++;
3068             while(point <= outline->contours[contour]) {
3069                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
3070                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3071                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
3072                 cpfx = 0;
3073                 do {
3074                     if(type == TT_PRIM_LINE) {
3075                         if(buf)
3076                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3077                         cpfx++;
3078                         point++;
3079                     } else {
3080                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
3081                          so cpfx = 3n */
3082
3083                       /* FIXME: Possible optimization in endpoint calculation
3084                          if there are two consecutive curves */
3085                         cubic_control[0] = outline->points[point-1];
3086                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
3087                             cubic_control[0].x += outline->points[point].x + 1;
3088                             cubic_control[0].y += outline->points[point].y + 1;
3089                             cubic_control[0].x >>= 1;
3090                             cubic_control[0].y >>= 1;
3091                         }
3092                         if(point+1 > outline->contours[contour])
3093                             cubic_control[3] = outline->points[first_pt];
3094                         else {
3095                             cubic_control[3] = outline->points[point+1];
3096                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
3097                                 cubic_control[3].x += outline->points[point].x + 1;
3098                                 cubic_control[3].y += outline->points[point].y + 1;
3099                                 cubic_control[3].x >>= 1;
3100                                 cubic_control[3].y >>= 1;
3101                             }
3102                         }
3103                         /* r1 = 1/3 p0 + 2/3 p1
3104                            r2 = 1/3 p2 + 2/3 p1 */
3105                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
3106                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
3107                         cubic_control[2] = cubic_control[1];
3108                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
3109                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
3110                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
3111                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
3112                         if(buf) {
3113                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
3114                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
3115                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
3116                         }
3117                         cpfx += 3;
3118                         point++;
3119                     }
3120                 } while(point <= outline->contours[contour] &&
3121                         (outline->tags[point] & FT_Curve_Tag_On) ==
3122                         (outline->tags[point-1] & FT_Curve_Tag_On));
3123                 /* At the end of a contour Windows adds the start point,
3124                    but only for Beziers and we've already done that.
3125                 */
3126                 if(point <= outline->contours[contour] &&
3127                    outline->tags[point] & FT_Curve_Tag_On) {
3128                   /* This is the closing pt of a bezier, but we've already
3129                      added it, so just inc point and carry on */
3130                     point++;
3131                 }
3132                 if(buf) {
3133                     ppc->wType = type;
3134                     ppc->cpfx = cpfx;
3135                 }
3136                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3137             }
3138             if(buf)
3139                 pph->cb = needed - pph_start;
3140         }
3141         break;
3142       }
3143
3144     default:
3145         FIXME("Unsupported format %d\n", format);
3146         return GDI_ERROR;
3147     }
3148     return needed;
3149 }
3150
3151 static BOOL get_bitmap_text_metrics(GdiFont font)
3152 {
3153     FT_Face ft_face = font->ft_face;
3154 #ifdef HAVE_FREETYPE_FTWINFNT_H
3155     FT_WinFNT_HeaderRec winfnt_header;
3156 #endif
3157     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
3158     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
3159     font->potm->otmSize = size;
3160
3161 #define TM font->potm->otmTextMetrics
3162 #ifdef HAVE_FREETYPE_FTWINFNT_H
3163     if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
3164     {
3165         TM.tmHeight = winfnt_header.pixel_height;
3166         TM.tmAscent = winfnt_header.ascent;
3167         TM.tmDescent = TM.tmHeight - TM.tmAscent;
3168         TM.tmInternalLeading = winfnt_header.internal_leading;
3169         TM.tmExternalLeading = winfnt_header.external_leading;
3170         TM.tmAveCharWidth = winfnt_header.avg_width;
3171         TM.tmMaxCharWidth = winfnt_header.max_width;
3172         TM.tmWeight = winfnt_header.weight;
3173         TM.tmOverhang = 0;
3174         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
3175         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
3176         TM.tmFirstChar = winfnt_header.first_char;
3177         TM.tmLastChar = winfnt_header.last_char;
3178         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
3179         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
3180         TM.tmItalic = winfnt_header.italic;
3181         TM.tmUnderlined = font->underline;
3182         TM.tmStruckOut = font->strikeout;
3183         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
3184         TM.tmCharSet = winfnt_header.charset;
3185     }
3186     else
3187 #endif
3188     {
3189         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
3190         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
3191         TM.tmHeight = TM.tmAscent + TM.tmDescent;
3192         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
3193         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
3194         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
3195         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
3196         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
3197         TM.tmOverhang = 0;
3198         TM.tmDigitizedAspectX = 96; /* FIXME */
3199         TM.tmDigitizedAspectY = 96; /* FIXME */
3200         TM.tmFirstChar = 1;
3201         TM.tmLastChar = 255;
3202         TM.tmDefaultChar = 32;
3203         TM.tmBreakChar = 32;
3204         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
3205         TM.tmUnderlined = font->underline;
3206         TM.tmStruckOut = font->strikeout;
3207         /* NB inverted meaning of TMPF_FIXED_PITCH */
3208         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
3209         TM.tmCharSet = font->charset;
3210     }
3211 #undef TM
3212
3213     return TRUE;
3214 }
3215
3216 /*************************************************************
3217  * WineEngGetTextMetrics
3218  *
3219  */
3220 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
3221 {
3222     if(!font->potm) {
3223         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
3224             if(!get_bitmap_text_metrics(font))
3225                 return FALSE;
3226     }
3227     if(!font->potm) return FALSE;
3228     memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm));
3229
3230     if (font->aveWidth) {
3231         ptm->tmAveCharWidth = font->aveWidth * font->font_desc.matrix.eM11;
3232     }
3233     return TRUE;
3234 }
3235
3236
3237 /*************************************************************
3238  * WineEngGetOutlineTextMetrics
3239  *
3240  */
3241 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
3242                                   OUTLINETEXTMETRICW *potm)
3243 {
3244     FT_Face ft_face = font->ft_face;
3245     UINT needed, lenfam, lensty, ret;
3246     TT_OS2 *pOS2;
3247     TT_HoriHeader *pHori;
3248     TT_Postscript *pPost;
3249     FT_Fixed x_scale, y_scale;
3250     WCHAR *family_nameW, *style_nameW;
3251     static const WCHAR spaceW[] = {' ', '\0'};
3252     char *cp;
3253     INT ascent, descent;
3254
3255     TRACE("font=%p\n", font);
3256
3257     if(!FT_IS_SCALABLE(ft_face))
3258         return 0;
3259
3260     if(font->potm) {
3261         if(cbSize >= font->potm->otmSize)
3262             memcpy(potm, font->potm, font->potm->otmSize);
3263         return font->potm->otmSize;
3264     }
3265
3266
3267     needed = sizeof(*potm);
3268
3269     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
3270     family_nameW = strdupW(font->name);
3271
3272     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
3273       * sizeof(WCHAR);
3274     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
3275     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
3276                         style_nameW, lensty/sizeof(WCHAR));
3277
3278     /* These names should be read from the TT name table */
3279
3280     /* length of otmpFamilyName */
3281     needed += lenfam;
3282
3283     /* length of otmpFaceName */
3284     if(!strcasecmp(ft_face->style_name, "regular")) {
3285       needed += lenfam; /* just the family name */
3286     } else {
3287       needed += lenfam + lensty; /* family + " " + style */
3288     }
3289
3290     /* length of otmpStyleName */
3291     needed += lensty;
3292
3293     /* length of otmpFullName */
3294     needed += lenfam + lensty;
3295
3296
3297     x_scale = ft_face->size->metrics.x_scale;
3298     y_scale = ft_face->size->metrics.y_scale;
3299
3300     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
3301     if(!pOS2) {
3302         FIXME("Can't find OS/2 table - not TT font?\n");
3303         ret = 0;
3304         goto end;
3305     }
3306
3307     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
3308     if(!pHori) {
3309         FIXME("Can't find HHEA table - not TT font?\n");
3310         ret = 0;
3311         goto end;
3312     }
3313
3314     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
3315
3316     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",
3317           pOS2->usWinAscent, pOS2->usWinDescent,
3318           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
3319           ft_face->ascender, ft_face->descender, ft_face->height,
3320           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
3321           ft_face->bbox.yMax, ft_face->bbox.yMin);
3322
3323     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
3324     font->potm->otmSize = needed;
3325
3326 #define TM font->potm->otmTextMetrics
3327
3328     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
3329         ascent = pHori->Ascender;
3330         descent = -pHori->Descender;
3331     } else {
3332         ascent = pOS2->usWinAscent;
3333         descent = pOS2->usWinDescent;
3334     }
3335
3336     if(font->yMax) {
3337         TM.tmAscent = font->yMax;
3338         TM.tmDescent = -font->yMin;
3339         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
3340     } else {
3341         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
3342         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
3343         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
3344                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
3345     }
3346
3347     TM.tmHeight = TM.tmAscent + TM.tmDescent;
3348
3349     /* MSDN says:
3350      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
3351     */
3352     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
3353                  ((ascent + descent) -
3354                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
3355
3356     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
3357     if (TM.tmAveCharWidth == 0) {
3358         TM.tmAveCharWidth = 1; 
3359     }
3360     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
3361     TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
3362     TM.tmOverhang = 0;
3363     TM.tmDigitizedAspectX = 300;
3364     TM.tmDigitizedAspectY = 300;
3365     TM.tmFirstChar = pOS2->usFirstCharIndex;
3366     TM.tmLastChar = pOS2->usLastCharIndex;
3367     TM.tmDefaultChar = pOS2->usDefaultChar;
3368     TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
3369     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
3370     TM.tmUnderlined = font->underline;
3371     TM.tmStruckOut = font->strikeout;
3372
3373     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
3374     if(!FT_IS_FIXED_WIDTH(ft_face) &&
3375        (pOS2->version == 0xFFFFU || 
3376         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
3377         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
3378     else
3379         TM.tmPitchAndFamily = 0;
3380
3381     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
3382     case PAN_FAMILY_SCRIPT:
3383         TM.tmPitchAndFamily |= FF_SCRIPT;
3384         break;
3385     case PAN_FAMILY_DECORATIVE:
3386     case PAN_FAMILY_PICTORIAL:
3387         TM.tmPitchAndFamily |= FF_DECORATIVE;
3388         break;
3389     case PAN_FAMILY_TEXT_DISPLAY:
3390         if(TM.tmPitchAndFamily == 0) /* fixed */
3391             TM.tmPitchAndFamily = FF_MODERN;
3392         else {
3393             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
3394             case PAN_SERIF_NORMAL_SANS:
3395             case PAN_SERIF_OBTUSE_SANS:
3396             case PAN_SERIF_PERP_SANS:
3397                 TM.tmPitchAndFamily |= FF_SWISS;
3398                 break;
3399             default:
3400                 TM.tmPitchAndFamily |= FF_ROMAN;
3401             }
3402         }
3403         break;
3404     default:
3405         TM.tmPitchAndFamily |= FF_DONTCARE;
3406     }
3407
3408     if(FT_IS_SCALABLE(ft_face))
3409         TM.tmPitchAndFamily |= TMPF_VECTOR;
3410     if(FT_IS_SFNT(ft_face))
3411         TM.tmPitchAndFamily |= TMPF_TRUETYPE;
3412
3413     TM.tmCharSet = font->charset;
3414 #undef TM
3415
3416     font->potm->otmFiller = 0;
3417     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
3418     font->potm->otmfsSelection = pOS2->fsSelection;
3419     font->potm->otmfsType = pOS2->fsType;
3420     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
3421     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
3422     font->potm->otmItalicAngle = 0; /* POST table */
3423     font->potm->otmEMSquare = ft_face->units_per_EM;
3424     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
3425     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
3426     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
3427     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
3428     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
3429     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
3430     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
3431     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
3432     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
3433     font->potm->otmMacAscent = 0; /* where do these come from ? */
3434     font->potm->otmMacDescent = 0;
3435     font->potm->otmMacLineGap = 0;
3436     font->potm->otmusMinimumPPEM = 0; /* TT Header */
3437     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
3438     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
3439     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
3440     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
3441     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
3442     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
3443     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
3444     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
3445     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
3446     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
3447     if(!pPost) {
3448         font->potm->otmsUnderscoreSize = 0;
3449         font->potm->otmsUnderscorePosition = 0;
3450     } else {
3451         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
3452         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
3453     }
3454
3455     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
3456     cp = (char*)font->potm + sizeof(*font->potm);
3457     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
3458     strcpyW((WCHAR*)cp, family_nameW);
3459     cp += lenfam;
3460     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
3461     strcpyW((WCHAR*)cp, style_nameW);
3462     cp += lensty;
3463     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
3464     strcpyW((WCHAR*)cp, family_nameW);
3465     if(strcasecmp(ft_face->style_name, "regular")) {
3466         strcatW((WCHAR*)cp, spaceW);
3467         strcatW((WCHAR*)cp, style_nameW);
3468         cp += lenfam + lensty;
3469     } else
3470         cp += lenfam;
3471     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
3472     strcpyW((WCHAR*)cp, family_nameW);
3473     strcatW((WCHAR*)cp, spaceW);
3474     strcatW((WCHAR*)cp, style_nameW);
3475     ret = needed;
3476
3477     if(potm && needed <= cbSize)
3478         memcpy(potm, font->potm, font->potm->otmSize);
3479
3480 end:
3481     HeapFree(GetProcessHeap(), 0, style_nameW);
3482     HeapFree(GetProcessHeap(), 0, family_nameW);
3483
3484     return ret;
3485 }
3486
3487 static BOOL load_child_font(GdiFont font, CHILD_FONT *child)
3488 {
3489     HFONTLIST *hfontlist;
3490     child->font = alloc_font();
3491     child->font->ft_face = OpenFontFile(child->font, child->file_name, child->index, 0, -font->ppem);
3492     if(!child->font->ft_face)
3493     {
3494         free_font(child->font);
3495         child->font = NULL;
3496         return FALSE;
3497     }
3498
3499     child->font->orientation = font->orientation;
3500     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
3501     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
3502     list_add_head(&child->font->hfontlist, &hfontlist->entry);
3503     child->font->base_font = font;
3504     list_add_head(&child_font_list, &child->font->entry);
3505     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
3506     return TRUE;
3507 }
3508
3509 static BOOL get_glyph_index_linked(GdiFont font, UINT c, GdiFont *linked_font, FT_UInt *glyph)
3510 {
3511     FT_UInt g;
3512     CHILD_FONT *child_font;
3513
3514     if(font->base_font)
3515         font = font->base_font;
3516
3517     *linked_font = font;
3518
3519     if((*glyph = get_glyph_index(font, c)))
3520         return TRUE;
3521
3522     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
3523     {
3524         if(!child_font->font)
3525             if(!load_child_font(font, child_font))
3526                 continue;
3527
3528         if(!child_font->font->ft_face)
3529             continue;
3530         g = get_glyph_index(child_font->font, c);
3531         if(g)
3532         {
3533             *glyph = g;
3534             *linked_font = child_font->font;
3535             return TRUE;
3536         }
3537     }
3538     return FALSE;
3539 }
3540
3541 /*************************************************************
3542  * WineEngGetCharWidth
3543  *
3544  */
3545 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
3546                          LPINT buffer)
3547 {
3548     UINT c;
3549     GLYPHMETRICS gm;
3550     FT_UInt glyph_index;
3551     GdiFont linked_font;
3552
3553     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
3554
3555     for(c = firstChar; c <= lastChar; c++) {
3556         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
3557         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3558                                &gm, 0, NULL, NULL);
3559         buffer[c - firstChar] = linked_font->gm[glyph_index].adv;
3560     }
3561     return TRUE;
3562 }
3563
3564 /*************************************************************
3565  * WineEngGetCharABCWidths
3566  *
3567  */
3568 BOOL WineEngGetCharABCWidths(GdiFont font, UINT firstChar, UINT lastChar,
3569                              LPABC buffer)
3570 {
3571     UINT c;
3572     GLYPHMETRICS gm;
3573     FT_UInt glyph_index;
3574     GdiFont linked_font;
3575
3576     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
3577
3578     if(!FT_IS_SCALABLE(font->ft_face))
3579         return FALSE;
3580
3581     for(c = firstChar; c <= lastChar; c++) {
3582         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
3583         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3584                                &gm, 0, NULL, NULL);
3585         buffer[c - firstChar].abcA = linked_font->gm[glyph_index].lsb;
3586         buffer[c - firstChar].abcB = linked_font->gm[glyph_index].bbx;
3587         buffer[c - firstChar].abcC = linked_font->gm[glyph_index].adv - linked_font->gm[glyph_index].lsb -
3588           linked_font->gm[glyph_index].bbx;
3589     }
3590     return TRUE;
3591 }
3592
3593 /*************************************************************
3594  * WineEngGetTextExtentPoint
3595  *
3596  */
3597 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
3598                                LPSIZE size)
3599 {
3600     INT idx;
3601     GLYPHMETRICS gm;
3602     TEXTMETRICW tm;
3603     FT_UInt glyph_index;
3604     GdiFont linked_font;
3605
3606     TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count,
3607           size);
3608
3609     size->cx = 0;
3610     WineEngGetTextMetrics(font, &tm);
3611     size->cy = tm.tmHeight;
3612
3613     for(idx = 0; idx < count; idx++) {
3614         get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
3615         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3616                                &gm, 0, NULL, NULL);
3617         size->cx += linked_font->gm[glyph_index].adv;
3618     }
3619     TRACE("return %ld,%ld\n", size->cx, size->cy);
3620     return TRUE;
3621 }
3622
3623 /*************************************************************
3624  * WineEngGetTextExtentPointI
3625  *
3626  */
3627 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
3628                                 LPSIZE size)
3629 {
3630     INT idx;
3631     GLYPHMETRICS gm;
3632     TEXTMETRICW tm;
3633
3634     TRACE("%p, %p, %d, %p\n", font, indices, count, size);
3635
3636     size->cx = 0;
3637     WineEngGetTextMetrics(font, &tm);
3638     size->cy = tm.tmHeight;
3639
3640     for(idx = 0; idx < count; idx++) {
3641         WineEngGetGlyphOutline(font, indices[idx],
3642                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
3643                                NULL);
3644         size->cx += font->gm[indices[idx]].adv;
3645     }
3646     TRACE("return %ld,%ld\n", size->cx, size->cy);
3647     return TRUE;
3648 }
3649
3650 /*************************************************************
3651  * WineEngGetFontData
3652  *
3653  */
3654 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
3655                          DWORD cbData)
3656 {
3657     FT_Face ft_face = font->ft_face;
3658     DWORD len;
3659     FT_Error err;
3660
3661     TRACE("font=%p, table=%08lx, offset=%08lx, buf=%p, cbData=%lx\n",
3662         font, table, offset, buf, cbData);
3663
3664     if(!FT_IS_SFNT(ft_face))
3665         return GDI_ERROR;
3666
3667     if(!buf || !cbData)
3668         len = 0;
3669     else
3670         len = cbData;
3671
3672     if(table) { /* MS tags differ in endidness from FT ones */
3673         table = table >> 24 | table << 24 |
3674           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
3675     }
3676
3677     /* If the FT_Load_Sfnt_Table function is there we'll use it */
3678     if(pFT_Load_Sfnt_Table)
3679         err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, &len);
3680     else { /* Do it the hard way */
3681         TT_Face tt_face = (TT_Face) ft_face;
3682         SFNT_Interface *sfnt;
3683         if (FT_Version.major==2 && FT_Version.minor==0)
3684         {
3685             /* 2.0.x */
3686             sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
3687         }
3688         else
3689         {
3690             /* A field was added in the middle of the structure in 2.1.x */
3691             sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
3692         }
3693         err = sfnt->load_any(tt_face, table, offset, buf, &len);
3694     }
3695     if(err) {
3696         TRACE("Can't find table %08lx.\n", table);
3697         return GDI_ERROR;
3698     }
3699     return len;
3700 }
3701
3702 /*************************************************************
3703  * WineEngGetTextFace
3704  *
3705  */
3706 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
3707 {
3708     if(str) {
3709         lstrcpynW(str, font->name, count);
3710         return strlenW(font->name);
3711     } else
3712         return strlenW(font->name) + 1;
3713 }
3714
3715 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
3716 {
3717     if (fs) memcpy(fs, &font->fs, sizeof(FONTSIGNATURE));
3718     return font->charset;
3719 }
3720
3721 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
3722 {
3723     GdiFont font = dc->gdiFont, linked_font;
3724     struct list *first_hfont;
3725     BOOL ret;
3726
3727     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
3728     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
3729     if(font == linked_font)
3730         *new_hfont = dc->hFont;
3731     else
3732     {
3733         first_hfont = list_head(&linked_font->hfontlist);
3734         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
3735     }
3736
3737     return ret;
3738 }
3739     
3740
3741 /*************************************************************
3742  *     FontIsLinked
3743  */
3744 BOOL WINAPI FontIsLinked(HDC hdc)
3745 {
3746     DC *dc = DC_GetDCPtr(hdc);
3747     BOOL ret = FALSE;
3748
3749     if(!dc) return FALSE;
3750     if(dc->gdiFont && !list_empty(&dc->gdiFont->child_fonts))
3751         ret = TRUE;
3752     GDI_ReleaseObj(hdc);
3753     TRACE("returning %d\n", ret);
3754     return ret;
3755 }
3756
3757 static BOOL is_hinting_enabled(void)
3758 {
3759     FT_Module mod = pFT_Get_Module(library, "truetype");
3760     if(mod && FT_DRIVER_HAS_HINTER(mod))
3761         return TRUE;
3762
3763     return FALSE;
3764 }
3765
3766 /*************************************************************************
3767  *             GetRasterizerCaps   (GDI32.@)
3768  */
3769 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
3770 {
3771     static int hinting = -1;
3772
3773     if(hinting == -1)
3774         hinting = is_hinting_enabled();
3775
3776     lprs->nSize = sizeof(RASTERIZER_STATUS);
3777     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
3778     lprs->nLanguageID = 0;
3779     return TRUE;
3780 }
3781
3782
3783 #else /* HAVE_FREETYPE */
3784
3785 BOOL WineEngInit(void)
3786 {
3787     return FALSE;
3788 }
3789 GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
3790 {
3791     return NULL;
3792 }
3793 BOOL WineEngDestroyFontInstance(HFONT hfont)
3794 {
3795     return FALSE;
3796 }
3797
3798 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
3799 {
3800     return 1;
3801 }
3802
3803 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
3804                                 LPWORD pgi, DWORD flags)
3805 {
3806     return GDI_ERROR;
3807 }
3808
3809 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
3810                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
3811                              const MAT2* lpmat)
3812 {
3813     ERR("called but we don't have FreeType\n");
3814     return GDI_ERROR;
3815 }
3816
3817 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
3818 {
3819     ERR("called but we don't have FreeType\n");
3820     return FALSE;
3821 }
3822
3823 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
3824                                   OUTLINETEXTMETRICW *potm)
3825 {
3826     ERR("called but we don't have FreeType\n");
3827     return 0;
3828 }
3829
3830 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
3831                          LPINT buffer)
3832 {
3833     ERR("called but we don't have FreeType\n");
3834     return FALSE;
3835 }
3836
3837 BOOL WineEngGetCharABCWidths(GdiFont font, UINT firstChar, UINT lastChar,
3838                              LPABC buffer)
3839 {
3840     ERR("called but we don't have FreeType\n");
3841     return FALSE;
3842 }
3843
3844 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
3845                                LPSIZE size)
3846 {
3847     ERR("called but we don't have FreeType\n");
3848     return FALSE;
3849 }
3850
3851 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
3852                                 LPSIZE size)
3853 {
3854     ERR("called but we don't have FreeType\n");
3855     return FALSE;
3856 }
3857
3858 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
3859                          DWORD cbData)
3860 {
3861     ERR("called but we don't have FreeType\n");
3862     return GDI_ERROR;
3863 }
3864
3865 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
3866 {
3867     ERR("called but we don't have FreeType\n");
3868     return 0;
3869 }
3870
3871 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
3872 {
3873     FIXME(":stub\n");
3874     return 1;
3875 }
3876
3877 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
3878 {
3879     FIXME(":stub\n");
3880     return TRUE;
3881 }
3882
3883 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
3884 {
3885     FIXME(":stub\n");
3886     return DEFAULT_CHARSET;
3887 }
3888
3889 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
3890 {
3891     return FALSE;
3892 }
3893
3894 BOOL WINAPI FontIsLinked(HDC hdc)
3895 {
3896     return FALSE;
3897 }
3898
3899 /*************************************************************************
3900  *             GetRasterizerCaps   (GDI32.@)
3901  */
3902 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
3903 {
3904     lprs->nSize = sizeof(RASTERIZER_STATUS);
3905     lprs->wFlags = 0;
3906     lprs->nLanguageID = 0;
3907     return TRUE;
3908 }
3909
3910 #endif /* HAVE_FREETYPE */