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