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