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