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