janitorial: Remove remaining NULL checks before free() (found by Smatch).
[wine] / dlls / gdi / 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 = %08lx %08lx/%08lx %08lx %08lx %08lx\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%08lx", 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     const char *file, *ext;
1190
1191     fc_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0);
1192     if(!fc_handle) {
1193         TRACE("Wine cannot find the fontconfig library (%s).\n",
1194               SONAME_LIBFONTCONFIG);
1195         return;
1196     }
1197 #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;}
1198 LOAD_FUNCPTR(FcConfigGetCurrent);
1199 LOAD_FUNCPTR(FcFontList);
1200 LOAD_FUNCPTR(FcFontSetDestroy);
1201 LOAD_FUNCPTR(FcInit);
1202 LOAD_FUNCPTR(FcObjectSetAdd);
1203 LOAD_FUNCPTR(FcObjectSetCreate);
1204 LOAD_FUNCPTR(FcObjectSetDestroy);
1205 LOAD_FUNCPTR(FcPatternCreate);
1206 LOAD_FUNCPTR(FcPatternDestroy);
1207 LOAD_FUNCPTR(FcPatternGetString);
1208 #undef LOAD_FUNCPTR
1209
1210     if(!pFcInit()) return;
1211     
1212     config = pFcConfigGetCurrent();
1213     pat = pFcPatternCreate();
1214     os = pFcObjectSetCreate();
1215     pFcObjectSetAdd(os, FC_FILE);
1216     fontset = pFcFontList(config, pat, os);
1217     if(!fontset) return;
1218     for(i = 0; i < fontset->nfont; i++) {
1219         if(pFcPatternGetString(fontset->fonts[i], FC_FILE, 0, (FcChar8**)&file) != FcResultMatch)
1220             continue;
1221         TRACE("fontconfig: %s\n", file);
1222
1223         /* We're just interested in OT/TT fonts for now, so this hack just
1224            picks up the standard extensions to save time loading every other
1225            font */
1226         len = strlen( file );
1227         if(len < 4) continue;
1228         ext = &file[ len - 3 ];
1229         if(!strcasecmp(ext, "ttf") || !strcasecmp(ext, "ttc") || !strcasecmp(ext, "otf"))
1230             AddFontFileToList(file, NULL, ADDFONT_EXTERNAL_FONT);
1231     }
1232     pFcFontSetDestroy(fontset);
1233     pFcObjectSetDestroy(os);
1234     pFcPatternDestroy(pat);
1235  sym_not_found:
1236 #endif
1237     return;
1238 }
1239
1240 static BOOL load_font_from_data_dir(LPCWSTR file)
1241 {
1242     BOOL ret = FALSE;
1243     const char *data_dir = wine_get_data_dir();
1244
1245     if (!data_dir) data_dir = wine_get_build_dir();
1246
1247     if (data_dir)
1248     {
1249         INT len;
1250         char *unix_name;
1251
1252         len = WideCharToMultiByte(CP_UNIXCP, 0, file, -1, NULL, 0, NULL, NULL);
1253
1254         unix_name = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + len + sizeof("/fonts/"));
1255
1256         strcpy(unix_name, data_dir);
1257         strcat(unix_name, "/fonts/");
1258
1259         WideCharToMultiByte(CP_UNIXCP, 0, file, -1, unix_name + strlen(unix_name), len, NULL, NULL);
1260
1261         ret = AddFontFileToList(unix_name, NULL, ADDFONT_FORCE_BITMAP);
1262         HeapFree(GetProcessHeap(), 0, unix_name);
1263     }
1264     return ret;
1265 }
1266
1267 static void load_system_fonts(void)
1268 {
1269     HKEY hkey;
1270     WCHAR data[MAX_PATH], windowsdir[MAX_PATH], pathW[MAX_PATH];
1271     const WCHAR * const *value;
1272     DWORD dlen, type;
1273     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
1274     char *unixname;
1275
1276     if(RegOpenKeyW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, &hkey) == ERROR_SUCCESS) {
1277         GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
1278         strcatW(windowsdir, fontsW);
1279         for(value = SystemFontValues; *value; value++) { 
1280             dlen = sizeof(data);
1281             if(RegQueryValueExW(hkey, *value, 0, &type, (void*)data, &dlen) == ERROR_SUCCESS &&
1282                type == REG_SZ) {
1283                 BOOL added = FALSE;
1284
1285                 sprintfW(pathW, fmtW, windowsdir, data);
1286                 if((unixname = wine_get_unix_file_name(pathW))) {
1287                     added = AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1288                     HeapFree(GetProcessHeap(), 0, unixname);
1289                 }
1290                 if (!added)
1291                     load_font_from_data_dir(data);
1292             }
1293         }
1294         RegCloseKey(hkey);
1295     }
1296 }
1297
1298 /*************************************************************
1299  *
1300  * This adds registry entries for any externally loaded fonts
1301  * (fonts from fontconfig or FontDirs).  It also deletes entries
1302  * of no longer existing fonts.
1303  *
1304  */
1305 static void update_reg_entries(void)
1306 {
1307     HKEY winkey = 0, externalkey = 0;
1308     LPWSTR valueW;
1309     LPVOID data;
1310     DWORD dlen, vlen, datalen, valuelen, i, type, len, len_fam;
1311     Family *family;
1312     Face *face;
1313     struct list *family_elem_ptr, *face_elem_ptr;
1314     WCHAR *file;
1315     static const WCHAR TrueType[] = {' ','(','T','r','u','e','T','y','p','e',')','\0'};
1316     static const WCHAR spaceW[] = {' ', '\0'};
1317     char *path;
1318
1319     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
1320                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &winkey, NULL) != ERROR_SUCCESS) {
1321         ERR("Can't create Windows font reg key\n");
1322         goto end;
1323     }
1324     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\ExternalFonts */
1325     if(RegCreateKeyW(HKEY_CURRENT_USER, external_fonts_reg_key, &externalkey) != ERROR_SUCCESS) {
1326         ERR("Can't create external font reg key\n");
1327         goto end;
1328     }
1329
1330     /* Delete all external fonts added last time */
1331
1332     RegQueryInfoKeyW(externalkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1333                      &valuelen, &datalen, NULL, NULL);
1334     valuelen++; /* returned value doesn't include room for '\0' */
1335     valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
1336     data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
1337
1338     dlen = datalen * sizeof(WCHAR);
1339     vlen = valuelen;
1340     i = 0;
1341     while(RegEnumValueW(externalkey, i++, valueW, &vlen, NULL, &type, data,
1342                         &dlen) == ERROR_SUCCESS) {
1343
1344         RegDeleteValueW(winkey, valueW);
1345         /* reset dlen and vlen */
1346         dlen = datalen;
1347         vlen = valuelen;
1348     }
1349     HeapFree(GetProcessHeap(), 0, data);
1350     HeapFree(GetProcessHeap(), 0, valueW);
1351
1352     /* Delete the old external fonts key */
1353     RegCloseKey(externalkey);
1354     externalkey = 0;
1355     RegDeleteKeyW(HKEY_CURRENT_USER, external_fonts_reg_key);
1356
1357     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\ExternalFonts */
1358     if(RegCreateKeyExW(HKEY_CURRENT_USER, external_fonts_reg_key,
1359                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &externalkey, NULL) != ERROR_SUCCESS) {
1360         ERR("Can't create external font reg key\n");
1361         goto end;
1362     }
1363
1364     /* enumerate the fonts and add external ones to the two keys */
1365
1366     LIST_FOR_EACH(family_elem_ptr, &font_list) {
1367         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
1368         len_fam = strlenW(family->FamilyName) + sizeof(TrueType) / sizeof(WCHAR) + 1;
1369         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
1370             face = LIST_ENTRY(face_elem_ptr, Face, entry);
1371             if(!face->external) continue;
1372             len = len_fam;
1373             if(strcmpiW(face->StyleName, RegularW))
1374                 len = len_fam + strlenW(face->StyleName) + 1;
1375             valueW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1376             strcpyW(valueW, family->FamilyName);
1377             if(len != len_fam) {
1378                 strcatW(valueW, spaceW);
1379                 strcatW(valueW, face->StyleName);
1380             }
1381             strcatW(valueW, TrueType);
1382             if((path = strrchr(face->file, '/')) == NULL)
1383                 path = face->file;
1384             else
1385                 path++;
1386             len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
1387
1388             file = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1389             MultiByteToWideChar(CP_ACP, 0, path, -1, file, len);
1390             RegSetValueExW(winkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
1391             RegSetValueExW(externalkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
1392
1393             HeapFree(GetProcessHeap(), 0, file);
1394             HeapFree(GetProcessHeap(), 0, valueW);
1395         }
1396     }
1397  end:
1398     if(externalkey)
1399         RegCloseKey(externalkey);
1400     if(winkey)
1401         RegCloseKey(winkey);
1402     return;
1403 }
1404
1405
1406 /*************************************************************
1407  *    WineEngAddFontResourceEx
1408  *
1409  */
1410 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
1411 {
1412     if (ft_handle)  /* do it only if we have freetype up and running */
1413     {
1414         char *unixname;
1415
1416         if(flags)
1417             FIXME("Ignoring flags %lx\n", flags);
1418
1419         if((unixname = wine_get_unix_file_name(file)))
1420         {
1421             AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1422             HeapFree(GetProcessHeap(), 0, unixname);
1423         }
1424     }
1425     return 1;
1426 }
1427
1428 /*************************************************************
1429  *    WineEngRemoveFontResourceEx
1430  *
1431  */
1432 BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
1433 {
1434     FIXME(":stub\n");
1435     return TRUE;
1436 }
1437
1438 static const struct nls_update_font_list
1439 {
1440     UINT ansi_cp, oem_cp;
1441     const char *oem, *fixed, *system;
1442     const char *courier, *serif, *small, *sserif;
1443 } nls_update_font_list[] =
1444 {
1445     /* Latin 1 (United States) */
1446     { 1252, 437, "vgaoem.fon", "vgafix.fon", "vgasys.fon",
1447       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1448     },
1449     /* Latin 1 (Multilingual) */
1450     { 1252, 850, "vga850.fon", "vgafix.fon", "vgasys.fon",
1451       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1452     },
1453     /* Eastern Europe */
1454     { 1250, 852, "vga852.fon", "vgafixe.fon", "vgasyse.fon",
1455       "couree.fon", "serifee.fon", "smallee.fon", "sserifee.fon",
1456     },
1457     /* Cyrillic */
1458     { 1251, 866, "vga866.fon", "vgafixr.fon", "vgasysr.fon",
1459       "courer.fon", "serifer.fon", "smaller.fon", "sserifer.fon",
1460     },
1461     /* Greek */
1462     { 1253, 737, "vga869.fon", "vgafixg.fon", "vgasysg.fon",
1463       "coureg.fon", "serifeg.fon", "smalleg.fon", "sserifeg.fon",
1464     },
1465     /* Turkish */
1466     { 1254, 857, "vga857.fon", "vgafixt.fon", "vgasyst.fon",
1467       "couret.fon", "serifet.fon", "smallet.fon", "sserifet.fon",
1468     },
1469     /* Hebrew */
1470     { 1255, 862, "vgaoem.fon", "vgaf1255.fon", "vgas1255.fon",
1471       "coue1255.fon", "sere1255.fon", "smae1255.fon", "ssee1255.fon",
1472     },
1473     /* Arabic */
1474     { 1256, 720, "vgaoem.fon", "vgaf1256.fon", "vgas1256.fon",
1475       "coue1256.fon", "sere1256.fon", "smae1256.fon", "ssee1256.fon",
1476     },
1477     /* Baltic */
1478     { 1257, 775, "vga775.fon", "vgaf1257.fon", "vgas1257.fon",
1479       "coue1257.fon", "sere1257.fon", "smae1257.fon", "ssee1257.fon",
1480     },
1481     /* Vietnamese */
1482     { 1258, 1258, "vga850.fon", "vgafix.fon", "vgasys.fon",
1483       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1484     },
1485     /* Thai */
1486     { 874, 874, "vga850.fon", "vgaf874.fon", "vgas874.fon",
1487       "coure.fon", "serife.fon", "smalle.fon", "ssee874.fon",
1488     },
1489     /* Japanese */
1490     { 932, 932, "vga932.fon", "jvgafix.fon", "jvgasys.fon",
1491       "coure.fon", "serife.fon", "jsmalle.fon", "sserife.fon",
1492     },
1493     /* Chinese Simplified */
1494     { 936, 936, "vga936.fon", "svgafix.fon", "svgasys.fon",
1495       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1496     },
1497     /* Korean */
1498     { 949, 949, "vga949.fon", "hvgafix.fon", "hvgasys.fon",
1499       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1500     },
1501     /* Chinese Traditional */
1502     { 950, 950, "vga950.fon", "cvgafix.fon", "cvgasys.fon",
1503       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1504     }
1505 };
1506
1507 inline static HKEY create_fonts_NT_registry_key(void)
1508 {
1509     HKEY hkey = 0;
1510
1511     RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key, 0, NULL,
1512                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
1513     return hkey;
1514 }
1515
1516 inline static HKEY create_fonts_9x_registry_key(void)
1517 {
1518     HKEY hkey = 0;
1519
1520     RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key, 0, NULL,
1521                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
1522     return hkey;
1523 }
1524
1525 inline static HKEY create_config_fonts_registry_key(void)
1526 {
1527     HKEY hkey = 0;
1528
1529     RegCreateKeyExW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, 0, NULL,
1530                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
1531     return hkey;
1532 }
1533
1534 static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl)
1535 {
1536     RegSetValueExA(hkey, "Courier", 0, REG_SZ, (const BYTE *)fl->courier, strlen(fl->courier)+1);
1537     RegSetValueExA(hkey, "MS Serif", 0, REG_SZ, (const BYTE *)fl->serif, strlen(fl->serif)+1);
1538     RegSetValueExA(hkey, "MS Sans Serif", 0, REG_SZ, (const BYTE *)fl->sserif, strlen(fl->sserif)+1);
1539     RegSetValueExA(hkey, "Small Fonts", 0, REG_SZ, (const BYTE *)fl->small, strlen(fl->small)+1);
1540 }
1541
1542 static void update_font_info(void)
1543 {
1544     char buf[80];
1545     DWORD len, type;
1546     HKEY hkey = 0;
1547     UINT i, ansi_cp = 0, oem_cp = 0;
1548     LCID lcid = GetUserDefaultLCID();
1549
1550     if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", &hkey) != ERROR_SUCCESS)
1551         return;
1552
1553     len = sizeof(buf);
1554     if (RegQueryValueExA(hkey, "Locale", 0, &type, (BYTE *)buf, &len) == ERROR_SUCCESS && type == REG_SZ)
1555     {
1556         if (strtoul(buf, NULL, 16 ) == lcid)  /* already set correctly */
1557         {
1558             RegCloseKey(hkey);
1559             return;
1560         }
1561         TRACE("updating registry, locale changed %s -> %08lx\n", debugstr_a(buf), lcid);
1562     }
1563     else TRACE("updating registry, locale changed none -> %08lx\n", lcid);
1564
1565     sprintf(buf, "%08lx", lcid);
1566     RegSetValueExA(hkey, "Locale", 0, REG_SZ, (const BYTE *)buf, strlen(buf)+1);
1567     RegCloseKey(hkey);
1568
1569     GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
1570                    (WCHAR *)&ansi_cp, sizeof(ansi_cp)/sizeof(WCHAR));
1571     GetLocaleInfoW(lcid, LOCALE_IDEFAULTCODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
1572                    (WCHAR *)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR));
1573
1574     for (i = 0; i < sizeof(nls_update_font_list)/sizeof(nls_update_font_list[0]); i++)
1575     {
1576         if (nls_update_font_list[i].ansi_cp == ansi_cp &&
1577             nls_update_font_list[i].oem_cp == oem_cp)
1578         {
1579             HKEY hkey;
1580
1581             hkey = create_config_fonts_registry_key();
1582             RegSetValueExA(hkey, "OEMFONT.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].oem, strlen(nls_update_font_list[i].oem)+1);
1583             RegSetValueExA(hkey, "FIXEDFON.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].fixed, strlen(nls_update_font_list[i].fixed)+1);
1584             RegSetValueExA(hkey, "FONTS.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].system, strlen(nls_update_font_list[i].system)+1);
1585             RegCloseKey(hkey);
1586
1587             hkey = create_fonts_NT_registry_key();
1588             add_font_list(hkey, &nls_update_font_list[i]);
1589             RegCloseKey(hkey);
1590
1591             hkey = create_fonts_9x_registry_key();
1592             add_font_list(hkey, &nls_update_font_list[i]);
1593             RegCloseKey(hkey);
1594
1595             return;
1596         }
1597     }
1598     FIXME("there is no font defaults for lcid %04lx/ansi_cp %u\n", lcid, ansi_cp);
1599 }
1600
1601 /*************************************************************
1602  *    WineEngInit
1603  *
1604  * Initialize FreeType library and create a list of available faces
1605  */
1606 BOOL WineEngInit(void)
1607 {
1608     static const WCHAR dot_fonW[] = {'.','f','o','n','\0'};
1609     static const WCHAR pathW[] = {'P','a','t','h',0};
1610     HKEY hkey;
1611     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
1612     LPVOID data;
1613     WCHAR windowsdir[MAX_PATH];
1614     char *unixname;
1615     HANDLE font_mutex;
1616     const char *data_dir;
1617
1618     TRACE("\n");
1619
1620     /* update locale dependent font info in registry */
1621     update_font_info();
1622
1623     ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0);
1624     if(!ft_handle) {
1625         WINE_MESSAGE(
1626       "Wine cannot find the FreeType font library.  To enable Wine to\n"
1627       "use TrueType fonts please install a version of FreeType greater than\n"
1628       "or equal to 2.0.5.\n"
1629       "http://www.freetype.org\n");
1630         return FALSE;
1631     }
1632
1633 #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;}
1634
1635     LOAD_FUNCPTR(FT_Vector_Unit)
1636     LOAD_FUNCPTR(FT_Done_Face)
1637     LOAD_FUNCPTR(FT_Get_Char_Index)
1638     LOAD_FUNCPTR(FT_Get_Module)
1639     LOAD_FUNCPTR(FT_Get_Sfnt_Name)
1640     LOAD_FUNCPTR(FT_Get_Sfnt_Name_Count)
1641     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
1642     LOAD_FUNCPTR(FT_Init_FreeType)
1643     LOAD_FUNCPTR(FT_Load_Glyph)
1644     LOAD_FUNCPTR(FT_Matrix_Multiply)
1645     LOAD_FUNCPTR(FT_MulFix)
1646     LOAD_FUNCPTR(FT_New_Face)
1647     LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
1648     LOAD_FUNCPTR(FT_Outline_Transform)
1649     LOAD_FUNCPTR(FT_Outline_Translate)
1650     LOAD_FUNCPTR(FT_Select_Charmap)
1651     LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
1652     LOAD_FUNCPTR(FT_Vector_Transform)
1653
1654 #undef LOAD_FUNCPTR
1655     /* Don't warn if this one is missing */
1656     pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0);
1657     pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0);
1658     pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0);
1659     pFT_Get_Next_Char = wine_dlsym(ft_handle, "FT_Get_Next_Char", NULL, 0);
1660     pFT_Get_TrueType_Engine_Type = wine_dlsym(ft_handle, "FT_Get_TrueType_Engine_Type", NULL, 0);
1661 #ifdef HAVE_FREETYPE_FTWINFNT_H
1662     pFT_Get_WinFNT_Header = wine_dlsym(ft_handle, "FT_Get_WinFNT_Header", NULL, 0);
1663 #endif
1664       if(!wine_dlsym(ft_handle, "FT_Get_Postscript_Name", NULL, 0) &&
1665          !wine_dlsym(ft_handle, "FT_Sqrt64", NULL, 0)) {
1666         /* try to avoid 2.0.4: >= 2.0.5 has FT_Get_Postscript_Name and
1667            <= 2.0.3 has FT_Sqrt64 */
1668           goto sym_not_found;
1669       }
1670
1671     if(pFT_Init_FreeType(&library) != 0) {
1672         ERR("Can't init FreeType library\n");
1673         wine_dlclose(ft_handle, NULL, 0);
1674         ft_handle = NULL;
1675         return FALSE;
1676     }
1677     FT_Version.major=FT_Version.minor=FT_Version.patch=-1;
1678     if (pFT_Library_Version)
1679     {
1680         pFT_Library_Version(library,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
1681     }
1682     if (FT_Version.major<=0)
1683     {
1684         FT_Version.major=2;
1685         FT_Version.minor=0;
1686         FT_Version.patch=5;
1687     }
1688     TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
1689     FT_SimpleVersion = ((FT_Version.major << 16) & 0xff0000) |
1690                        ((FT_Version.minor <<  8) & 0x00ff00) |
1691                        ((FT_Version.patch      ) & 0x0000ff);
1692
1693     if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) {
1694         ERR("Failed to create font mutex\n");
1695         return FALSE;
1696     }
1697     WaitForSingleObject(font_mutex, INFINITE);
1698
1699     /* load the system bitmap fonts */
1700     load_system_fonts();
1701
1702     /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
1703     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
1704     strcatW(windowsdir, fontsW);
1705     if((unixname = wine_get_unix_file_name(windowsdir)))
1706     {
1707         ReadFontDir(unixname, FALSE);
1708         HeapFree(GetProcessHeap(), 0, unixname);
1709     }
1710
1711     /* load the system truetype fonts */
1712     data_dir = wine_get_data_dir();
1713     if (data_dir && (unixname = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + sizeof("/fonts/")))) {
1714         strcpy(unixname, data_dir);
1715         strcat(unixname, "/fonts/");
1716         ReadFontDir(unixname, FALSE);
1717         HeapFree(GetProcessHeap(), 0, unixname);
1718     }
1719
1720     /* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
1721        for any fonts not installed in %WINDOWSDIR%\Fonts.  They will have their
1722        full path as the entry.  Also look for any .fon fonts, since ReadFontDir
1723        will skip these. */
1724     if(RegOpenKeyW(HKEY_LOCAL_MACHINE,
1725                    is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
1726                    &hkey) == ERROR_SUCCESS) {
1727         LPWSTR valueW;
1728         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1729                          &valuelen, &datalen, NULL, NULL);
1730
1731         valuelen++; /* returned value doesn't include room for '\0' */
1732         valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
1733         data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
1734         if (valueW && data)
1735         {
1736             dlen = datalen * sizeof(WCHAR);
1737             vlen = valuelen;
1738             while(RegEnumValueW(hkey, i++, valueW, &vlen, NULL, &type, data,
1739                                 &dlen) == ERROR_SUCCESS) {
1740                 if(((LPWSTR)data)[0] && ((LPWSTR)data)[1] == ':')
1741                 {
1742                     if((unixname = wine_get_unix_file_name((LPWSTR)data)))
1743                     {
1744                         AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1745                         HeapFree(GetProcessHeap(), 0, unixname);
1746                     }
1747                 }
1748                 else if(dlen / 2 >= 6 && !strcmpiW(((LPWSTR)data) + dlen / 2 - 5, dot_fonW))
1749                 {
1750                     WCHAR pathW[MAX_PATH];
1751                     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
1752                     BOOL added = FALSE;
1753
1754                     sprintfW(pathW, fmtW, windowsdir, data);
1755                     if((unixname = wine_get_unix_file_name(pathW)))
1756                     {
1757                         added = AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1758                         HeapFree(GetProcessHeap(), 0, unixname);
1759                     }
1760                     if (!added)
1761                         load_font_from_data_dir(data);
1762                 }
1763                 /* reset dlen and vlen */
1764                 dlen = datalen;
1765                 vlen = valuelen;
1766             }
1767         }
1768         HeapFree(GetProcessHeap(), 0, data);
1769         HeapFree(GetProcessHeap(), 0, valueW);
1770         RegCloseKey(hkey);
1771     }
1772
1773     load_fontconfig_fonts();
1774
1775     /* then look in any directories that we've specified in the config file */
1776     /* @@ Wine registry key: HKCU\Software\Wine\Fonts */
1777     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", &hkey) == ERROR_SUCCESS)
1778     {
1779         DWORD len;
1780         LPWSTR valueW;
1781         LPSTR valueA, ptr;
1782
1783         if (RegQueryValueExW( hkey, pathW, NULL, NULL, NULL, &len ) == ERROR_SUCCESS)
1784         {
1785             len += sizeof(WCHAR);
1786             valueW = HeapAlloc( GetProcessHeap(), 0, len );
1787             if (RegQueryValueExW( hkey, pathW, NULL, NULL, (LPBYTE)valueW, &len ) == ERROR_SUCCESS)
1788             {
1789                 len = WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, NULL, 0, NULL, NULL );
1790                 valueA = HeapAlloc( GetProcessHeap(), 0, len );
1791                 WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, valueA, len, NULL, NULL );
1792                 TRACE( "got font path %s\n", debugstr_a(valueA) );
1793                 ptr = valueA;
1794                 while (ptr)
1795                 {
1796                     LPSTR next = strchr( ptr, ':' );
1797                     if (next) *next++ = 0;
1798                     ReadFontDir( ptr, TRUE );
1799                     ptr = next;
1800                 }
1801                 HeapFree( GetProcessHeap(), 0, valueA );
1802             }
1803             HeapFree( GetProcessHeap(), 0, valueW );
1804         }
1805         RegCloseKey(hkey);
1806     }
1807
1808     DumpFontList();
1809     LoadSubstList();
1810     DumpSubstList();
1811     LoadReplaceList();
1812     update_reg_entries();
1813
1814     init_system_links();
1815     
1816     ReleaseMutex(font_mutex);
1817     return TRUE;
1818 sym_not_found:
1819     WINE_MESSAGE(
1820       "Wine cannot find certain functions that it needs inside the FreeType\n"
1821       "font library.  To enable Wine to use TrueType fonts please upgrade\n"
1822       "FreeType to at least version 2.0.5.\n"
1823       "http://www.freetype.org\n");
1824     wine_dlclose(ft_handle, NULL, 0);
1825     ft_handle = NULL;
1826     return FALSE;
1827 }
1828
1829
1830 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
1831 {
1832     TT_OS2 *pOS2;
1833     TT_HoriHeader *pHori;
1834
1835     LONG ppem;
1836
1837     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
1838     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
1839
1840     if(height == 0) height = 16;
1841
1842     /* Calc. height of EM square:
1843      *
1844      * For +ve lfHeight we have
1845      * lfHeight = (winAscent + winDescent) * ppem / units_per_em
1846      * Re-arranging gives:
1847      * ppem = units_per_em * lfheight / (winAscent + winDescent)
1848      *
1849      * For -ve lfHeight we have
1850      * |lfHeight| = ppem
1851      * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
1852      * with il = winAscent + winDescent - units_per_em]
1853      *
1854      */
1855
1856     if(height > 0) {
1857         if(pOS2->usWinAscent + pOS2->usWinDescent == 0)
1858             ppem = ft_face->units_per_EM * height /
1859                 (pHori->Ascender - pHori->Descender);
1860         else
1861             ppem = ft_face->units_per_EM * height /
1862                 (pOS2->usWinAscent + pOS2->usWinDescent);
1863     }
1864     else
1865         ppem = -height;
1866
1867     return ppem;
1868 }
1869
1870 static LONG load_VDMX(GdiFont*, LONG);
1871
1872 static FT_Face OpenFontFile(GdiFont *font, char *file, FT_Long face_index, LONG width, LONG height)
1873 {
1874     FT_Error err;
1875     FT_Face ft_face;
1876
1877     TRACE("%s, %ld, %ld x %ld\n", debugstr_a(file), face_index, width, height);
1878     err = pFT_New_Face(library, file, face_index, &ft_face);
1879     if(err) {
1880         ERR("FT_New_Face rets %d\n", err);
1881         return 0;
1882     }
1883
1884     /* set it here, as load_VDMX needs it */
1885     font->ft_face = ft_face;
1886
1887     if(FT_IS_SCALABLE(ft_face)) {
1888         /* load the VDMX table if we have one */
1889         font->ppem = load_VDMX(font, height);
1890         if(font->ppem == 0)
1891             font->ppem = calc_ppem_for_height(ft_face, height);
1892
1893         if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0)
1894             WARN("FT_Set_Pixel_Sizes %d, %ld rets %x\n", 0, font->ppem, err);
1895     } else {
1896         font->ppem = height;
1897         if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
1898             WARN("FT_Set_Pixel_Sizes %ld, %ld rets %x\n", width, height, err);
1899     }
1900     return ft_face;
1901 }
1902
1903
1904 static int get_nearest_charset(Face *face, int *cp)
1905 {
1906   /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
1907      a single face with the requested charset.  The idea is to check if
1908      the selected font supports the current ANSI codepage, if it does
1909      return the corresponding charset, else return the first charset */
1910
1911     CHARSETINFO csi;
1912     int acp = GetACP(), i;
1913     DWORD fs0;
1914
1915     *cp = acp;
1916     if(TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE))
1917         if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
1918             return csi.ciCharset;
1919
1920     for(i = 0; i < 32; i++) {
1921         fs0 = 1L << i;
1922         if(face->fs.fsCsb[0] & fs0) {
1923             if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG)) {
1924                 *cp = csi.ciACP;
1925                 return csi.ciCharset;
1926             }
1927             else
1928                 FIXME("TCI failing on %lx\n", fs0);
1929         }
1930     }
1931
1932     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08lx file = %s\n",
1933           face->fs.fsCsb[0], face->file);
1934     *cp = acp;
1935     return DEFAULT_CHARSET;
1936 }
1937
1938 static GdiFont *alloc_font(void)
1939 {
1940     GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
1941     ret->gmsize = INIT_GM_SIZE;
1942     ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1943                         ret->gmsize * sizeof(*ret->gm));
1944     ret->potm = NULL;
1945     ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
1946     ret->total_kern_pairs = (DWORD)-1;
1947     ret->kern_pairs = NULL;
1948     list_init(&ret->hfontlist);
1949     list_init(&ret->child_fonts);
1950     return ret;
1951 }
1952
1953 static void free_font(GdiFont *font)
1954 {
1955     struct list *cursor, *cursor2;
1956
1957     LIST_FOR_EACH_SAFE(cursor, cursor2, &font->child_fonts)
1958     {
1959         CHILD_FONT *child = LIST_ENTRY(cursor, CHILD_FONT, entry);
1960         struct list *first_hfont;
1961         HFONTLIST *hfontlist;
1962         list_remove(cursor);
1963         if(child->font)
1964         {
1965             first_hfont = list_head(&child->font->hfontlist);
1966             hfontlist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
1967             DeleteObject(hfontlist->hfont);
1968             HeapFree(GetProcessHeap(), 0, hfontlist);
1969             free_font(child->font);
1970         }
1971         HeapFree(GetProcessHeap(), 0, child->file_name);
1972         HeapFree(GetProcessHeap(), 0, child);
1973     }
1974
1975     if (font->ft_face) pFT_Done_Face(font->ft_face);
1976     HeapFree(GetProcessHeap(), 0, font->kern_pairs);
1977     HeapFree(GetProcessHeap(), 0, font->potm);
1978     HeapFree(GetProcessHeap(), 0, font->name);
1979     HeapFree(GetProcessHeap(), 0, font->gm);
1980     HeapFree(GetProcessHeap(), 0, font);
1981 }
1982
1983
1984 /*************************************************************
1985  * load_VDMX
1986  *
1987  * load the vdmx entry for the specified height
1988  */
1989
1990 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
1991           ( ( (FT_ULong)_x4 << 24 ) |     \
1992             ( (FT_ULong)_x3 << 16 ) |     \
1993             ( (FT_ULong)_x2 <<  8 ) |     \
1994               (FT_ULong)_x1         )
1995
1996 #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X')
1997
1998 typedef struct {
1999     BYTE bCharSet;
2000     BYTE xRatio;
2001     BYTE yStartRatio;
2002     BYTE yEndRatio;
2003 } Ratios;
2004
2005 typedef struct {
2006     WORD recs;
2007     BYTE startsz;
2008     BYTE endsz;
2009 } VDMX_group;
2010
2011 static LONG load_VDMX(GdiFont *font, LONG height)
2012 {
2013     WORD hdr[3], tmp;
2014     VDMX_group group;
2015     BYTE devXRatio, devYRatio;
2016     USHORT numRecs, numRatios;
2017     DWORD result, offset = -1;
2018     LONG ppem = 0;
2019     int i;
2020
2021     /* For documentation on VDMX records, see
2022      * http://www.microsoft.com/OpenType/OTSpec/vdmx.htm
2023      */
2024
2025     result = WineEngGetFontData(font, MS_VDMX_TAG, 0, hdr, 6);
2026
2027     if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
2028         return ppem;
2029
2030     /* FIXME: need the real device aspect ratio */
2031     devXRatio = 1;
2032     devYRatio = 1;
2033
2034     numRecs = GET_BE_WORD(hdr[1]);
2035     numRatios = GET_BE_WORD(hdr[2]);
2036
2037     TRACE("numRecs = %d numRatios = %d\n", numRecs, numRatios);
2038     for(i = 0; i < numRatios; i++) {
2039         Ratios ratio;
2040
2041         offset = (3 * 2) + (i * sizeof(Ratios));
2042         WineEngGetFontData(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
2043         offset = -1;
2044
2045         TRACE("Ratios[%d] %d  %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
2046
2047         if((ratio.xRatio == 0 &&
2048             ratio.yStartRatio == 0 &&
2049             ratio.yEndRatio == 0) ||
2050            (devXRatio == ratio.xRatio &&
2051             devYRatio >= ratio.yStartRatio &&
2052             devYRatio <= ratio.yEndRatio))
2053             {
2054                 offset = (3 * 2) + (numRatios * 4) + (i * 2);
2055                 WineEngGetFontData(font, MS_VDMX_TAG, offset, &tmp, 2);
2056                 offset = GET_BE_WORD(tmp);
2057                 break;
2058             }
2059     }
2060
2061     if(offset == -1) {
2062         FIXME("No suitable ratio found\n");
2063         return ppem;
2064     }
2065
2066     if(WineEngGetFontData(font, MS_VDMX_TAG, offset, &group, 4) != GDI_ERROR) {
2067         USHORT recs;
2068         BYTE startsz, endsz;
2069         WORD *vTable;
2070
2071         recs = GET_BE_WORD(group.recs);
2072         startsz = group.startsz;
2073         endsz = group.endsz;
2074
2075         TRACE("recs=%d  startsz=%d  endsz=%d\n", recs, startsz, endsz);
2076
2077         vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6);
2078         result = WineEngGetFontData(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6);
2079         if(result == GDI_ERROR) {
2080             FIXME("Failed to retrieve vTable\n");
2081             goto end;
2082         }
2083
2084         if(height > 0) {
2085             for(i = 0; i < recs; i++) {
2086                 SHORT yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
2087                 SHORT yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
2088                 ppem = GET_BE_WORD(vTable[i * 3]);
2089
2090                 if(yMax + -yMin == height) {
2091                     font->yMax = yMax;
2092                     font->yMin = yMin;
2093                     TRACE("ppem %ld found; height=%ld  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
2094                     break;
2095                 }
2096                 if(yMax + -yMin > height) {
2097                     if(--i < 0) {
2098                         ppem = 0;
2099                         goto end; /* failed */
2100                     }
2101                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
2102                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
2103                     ppem = GET_BE_WORD(vTable[i * 3]);
2104                     TRACE("ppem %ld found; height=%ld  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
2105                     break;
2106                 }
2107             }
2108             if(!font->yMax) {
2109                 ppem = 0;
2110                 TRACE("ppem not found for height %ld\n", height);
2111             }
2112         } else {
2113             ppem = -height;
2114             if(ppem < startsz || ppem > endsz)
2115                 goto end;
2116
2117             for(i = 0; i < recs; i++) {
2118                 USHORT yPelHeight;
2119                 yPelHeight = GET_BE_WORD(vTable[i * 3]);
2120
2121                 if(yPelHeight > ppem)
2122                     break; /* failed */
2123
2124                 if(yPelHeight == ppem) {
2125                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
2126                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
2127                     TRACE("ppem %ld found; yMax=%d  yMin=%d\n", ppem, font->yMax, font->yMin);
2128                     break;
2129                 }
2130             }
2131         }
2132         end:
2133         HeapFree(GetProcessHeap(), 0, vTable);
2134     }
2135
2136     return ppem;
2137 }
2138
2139 static BOOL fontcmp(GdiFont *font, FONT_DESC *fd)
2140 {
2141     if(font->font_desc.hash != fd->hash) return TRUE;
2142     if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE;
2143     if(memcmp(&font->font_desc.lf, &fd->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
2144     if(!font->font_desc.can_use_bitmap != !fd->can_use_bitmap) return TRUE;
2145     return strcmpiW(font->font_desc.lf.lfFaceName, fd->lf.lfFaceName);
2146 }
2147
2148 static void calc_hash(FONT_DESC *pfd)
2149 {
2150     DWORD hash = 0, *ptr, two_chars;
2151     WORD *pwc;
2152     unsigned int i;
2153
2154     for(i = 0, ptr = (DWORD*)&pfd->matrix; i < sizeof(FMAT2)/sizeof(DWORD); i++, ptr++)
2155         hash ^= *ptr;
2156     for(i = 0, ptr = (DWORD*)&pfd->lf; i < 7; i++, ptr++)
2157         hash ^= *ptr;
2158     for(i = 0, ptr = (DWORD*)&pfd->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
2159         two_chars = *ptr;
2160         pwc = (WCHAR *)&two_chars;
2161         if(!*pwc) break;
2162         *pwc = toupperW(*pwc);
2163         pwc++;
2164         *pwc = toupperW(*pwc);
2165         hash ^= two_chars;
2166         if(!*pwc) break;
2167     }
2168     hash ^= !pfd->can_use_bitmap;
2169     pfd->hash = hash;
2170     return;
2171 }
2172
2173 static GdiFont *find_in_cache(HFONT hfont, LOGFONTW *plf, XFORM *pxf, BOOL can_use_bitmap)
2174 {
2175     GdiFont *ret;
2176     FONT_DESC fd;
2177     HFONTLIST *hflist;
2178     struct list *font_elem_ptr, *hfontlist_elem_ptr;
2179
2180     memcpy(&fd.lf, plf, sizeof(LOGFONTW));
2181     memcpy(&fd.matrix, pxf, sizeof(FMAT2));
2182     fd.can_use_bitmap = can_use_bitmap;
2183     calc_hash(&fd);
2184
2185     /* try the in-use list */
2186     LIST_FOR_EACH(font_elem_ptr, &gdi_font_list) {
2187         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2188         if(!fontcmp(ret, &fd)) {
2189             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
2190             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
2191                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
2192                 if(hflist->hfont == hfont)
2193                     return ret;
2194             }
2195             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
2196             hflist->hfont = hfont;
2197             list_add_head(&ret->hfontlist, &hflist->entry);
2198             return ret;
2199         }
2200     }
2201  
2202     /* then the unused list */
2203     font_elem_ptr = list_head(&unused_gdi_font_list);
2204     while(font_elem_ptr) {
2205         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2206         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
2207         if(!fontcmp(ret, &fd)) {
2208             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
2209             assert(list_empty(&ret->hfontlist));
2210             TRACE("Found %p in unused list\n", ret);
2211             list_remove(&ret->entry);
2212             list_add_head(&gdi_font_list, &ret->entry);
2213             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
2214             hflist->hfont = hfont;
2215             list_add_head(&ret->hfontlist, &hflist->entry);
2216             return ret;
2217         }
2218     }
2219     return NULL;
2220 }
2221
2222     
2223 /*************************************************************
2224  * create_child_font_list
2225  */
2226 static BOOL create_child_font_list(GdiFont *font)
2227 {
2228     BOOL ret = FALSE;
2229     SYSTEM_LINKS *font_link;
2230     CHILD_FONT *font_link_entry, *new_child;
2231
2232     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
2233     {
2234         if(!strcmpW(font_link->font_name, font->name))
2235         {
2236             TRACE("found entry in system list\n");
2237             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
2238             {
2239                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
2240                 new_child->file_name = strdupA(font_link_entry->file_name);
2241                 new_child->index = font_link_entry->index;
2242                 new_child->font = NULL;
2243                 list_add_tail(&font->child_fonts, &new_child->entry);
2244                 TRACE("font %s %d\n", debugstr_a(new_child->file_name), new_child->index); 
2245             }
2246             ret = TRUE;
2247             break;
2248         }
2249     }
2250
2251     return ret;
2252 }
2253
2254 /*************************************************************
2255  * WineEngCreateFontInstance
2256  *
2257  */
2258 GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont)
2259 {
2260     GdiFont *ret;
2261     Face *face, *best, *best_bitmap;
2262     Family *family, *last_resort_family;
2263     struct list *family_elem_ptr, *face_elem_ptr;
2264     INT height, width = 0;
2265     unsigned int score = 0, new_score;
2266     signed int diff = 0, newdiff;
2267     BOOL bd, it, can_use_bitmap;
2268     LOGFONTW lf;
2269     CHARSETINFO csi;
2270     HFONTLIST *hflist;
2271
2272     LIST_FOR_EACH_ENTRY(ret, &child_font_list, struct tagGdiFont, entry)
2273     {
2274         struct list *first_hfont = list_head(&ret->hfontlist);
2275         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
2276         if(hflist->hfont == hfont)
2277             return ret;
2278     }
2279
2280     if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
2281     can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
2282
2283     TRACE("%s, h=%ld, it=%d, weight=%ld, PandF=%02x, charset=%d orient %ld escapement %ld\n",
2284           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
2285           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
2286           lf.lfEscapement);
2287
2288     /* check the cache first */
2289     if((ret = find_in_cache(hfont, &lf, &dc->xformWorld2Vport, can_use_bitmap)) != NULL) {
2290         TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
2291         return ret;
2292     }
2293
2294     TRACE("not in cache\n");
2295     if(list_empty(&font_list)) /* No fonts installed */
2296     {
2297         TRACE("No fonts installed\n");
2298         return NULL;
2299     }
2300     if(!have_installed_roman_font)
2301     {
2302         TRACE("No roman font installed\n");
2303         return NULL;
2304     }
2305
2306     ret = alloc_font();
2307
2308      memcpy(&ret->font_desc.matrix, &dc->xformWorld2Vport, sizeof(FMAT2));
2309      memcpy(&ret->font_desc.lf, &lf, sizeof(LOGFONTW));
2310      ret->font_desc.can_use_bitmap = can_use_bitmap;
2311      calc_hash(&ret->font_desc);
2312      hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
2313      hflist->hfont = hfont;
2314      list_add_head(&ret->hfontlist, &hflist->entry);
2315
2316
2317     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
2318        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
2319        original value lfCharSet.  Note this is a special case for
2320        Symbol and doesn't happen at least for "Wingdings*" */
2321
2322     if(!strcmpiW(lf.lfFaceName, SymbolW))
2323         lf.lfCharSet = SYMBOL_CHARSET;
2324
2325     if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
2326         switch(lf.lfCharSet) {
2327         case DEFAULT_CHARSET:
2328             csi.fs.fsCsb[0] = 0;
2329             break;
2330         default:
2331             FIXME("Untranslated charset %d\n", lf.lfCharSet);
2332             csi.fs.fsCsb[0] = 0;
2333             break;
2334         }
2335     }
2336
2337     family = NULL;
2338     if(lf.lfFaceName[0] != '\0') {
2339         FontSubst *psub;
2340         psub = get_font_subst(&font_subst_list, lf.lfFaceName, lf.lfCharSet);
2341
2342         if(psub) {
2343             TRACE("substituting %s -> %s\n", debugstr_w(lf.lfFaceName),
2344                   debugstr_w(psub->to.name));
2345             strcpyW(lf.lfFaceName, psub->to.name);
2346         }
2347
2348         /* We want a match on name and charset or just name if
2349            charset was DEFAULT_CHARSET.  If the latter then
2350            we fixup the returned charset later in get_nearest_charset
2351            where we'll either use the charset of the current ansi codepage
2352            or if that's unavailable the first charset that the font supports.
2353         */
2354         LIST_FOR_EACH(family_elem_ptr, &font_list) {
2355             family = LIST_ENTRY(family_elem_ptr, Family, entry);
2356             if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
2357                 LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2358                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
2359                     if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
2360                         if(face->scalable || can_use_bitmap)
2361                             goto found;
2362                 }
2363             }
2364         }
2365     }
2366
2367     /* If requested charset was DEFAULT_CHARSET then try using charset
2368        corresponding to the current ansi codepage */
2369     if(!csi.fs.fsCsb[0]) {
2370         INT acp = GetACP();
2371         if(!TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE)) {
2372             FIXME("TCI failed on codepage %d\n", acp);
2373             csi.fs.fsCsb[0] = 0;
2374         } else
2375             lf.lfCharSet = csi.ciCharset;
2376     }
2377
2378     /* Face families are in the top 4 bits of lfPitchAndFamily,
2379        so mask with 0xF0 before testing */
2380
2381     if((lf.lfPitchAndFamily & FIXED_PITCH) ||
2382        (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
2383         strcpyW(lf.lfFaceName, defFixed);
2384     else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
2385         strcpyW(lf.lfFaceName, defSerif);
2386     else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
2387         strcpyW(lf.lfFaceName, defSans);
2388     else
2389         strcpyW(lf.lfFaceName, defSans);
2390     LIST_FOR_EACH(family_elem_ptr, &font_list) {
2391         family = LIST_ENTRY(family_elem_ptr, Family, entry);
2392         if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
2393             LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2394                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
2395                 if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
2396                     if(face->scalable || can_use_bitmap)
2397                         goto found;
2398             }
2399         }
2400     }
2401
2402     last_resort_family = NULL;
2403     LIST_FOR_EACH(family_elem_ptr, &font_list) {
2404         family = LIST_ENTRY(family_elem_ptr, Family, entry);
2405         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2406             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2407             if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) {
2408                 if(face->scalable)
2409                     goto found;
2410                 if(can_use_bitmap && !last_resort_family)
2411                     last_resort_family = family;
2412             }            
2413         }
2414     }
2415
2416     if(last_resort_family) {
2417         family = last_resort_family;
2418         csi.fs.fsCsb[0] = 0;
2419         goto found;
2420     }
2421
2422     LIST_FOR_EACH(family_elem_ptr, &font_list) {
2423         family = LIST_ENTRY(family_elem_ptr, Family, entry);
2424         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2425             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2426             if(face->scalable) {
2427                 csi.fs.fsCsb[0] = 0;
2428                 FIXME("just using first face for now\n");
2429                 goto found;
2430             }
2431             if(can_use_bitmap && !last_resort_family)
2432                 last_resort_family = family;
2433         }
2434     }
2435     if(!last_resort_family) {
2436         FIXME("can't find a single appropriate font - bailing\n");
2437         free_font(ret);
2438         return NULL;
2439     }
2440
2441     WARN("could only find a bitmap font - this will probably look awful!\n");
2442     family = last_resort_family;
2443     csi.fs.fsCsb[0] = 0;
2444
2445 found:
2446     it = lf.lfItalic ? 1 : 0;
2447     bd = lf.lfWeight > 550 ? 1 : 0;
2448
2449     height = GDI_ROUND( (FLOAT)lf.lfHeight * dc->xformWorld2Vport.eM22 );
2450     height = lf.lfHeight < 0 ? -abs(height) : abs(height);
2451
2452     face = best = best_bitmap = NULL;
2453     LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
2454     {
2455         if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
2456         {
2457             new_score = (face->Italic ^ it) + (face->Bold ^ bd);
2458             if(!best || new_score <= score)
2459             {
2460                 TRACE("(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n",
2461                       face->Italic, face->Bold, it, bd);
2462                 score = new_score;
2463                 best = face;
2464                 if(best->scalable  && score == 0) break;
2465                 if(!best->scalable)
2466                 {
2467                     if(height > 0)
2468                         newdiff = height - (signed int)(best->size.height);
2469                     else
2470                         newdiff = -height - ((signed int)(best->size.height) - best->size.internal_leading);
2471                     if(!best_bitmap || new_score < score ||
2472                        (diff > 0 && newdiff < diff && newdiff >= 0) || (diff < 0 && newdiff > diff))
2473                     {
2474                         TRACE("%d is better for %d diff was %d\n", best->size.height, height, diff);
2475                         diff = newdiff;
2476                         best_bitmap = best;
2477                         if(score == 0 && diff == 0) break;
2478                     }
2479                 }
2480             }
2481         }
2482     }
2483     if(best)
2484         face = best->scalable ? best : best_bitmap;
2485     ret->fake_italic = (it && !face->Italic);
2486     ret->fake_bold = (bd && !face->Bold);
2487
2488     memcpy(&ret->fs, &face->fs, sizeof(FONTSIGNATURE));
2489
2490     if(csi.fs.fsCsb[0]) {
2491         ret->charset = lf.lfCharSet;
2492         ret->codepage = csi.ciACP;
2493     }
2494     else
2495         ret->charset = get_nearest_charset(face, &ret->codepage);
2496
2497     TRACE("Chosen: %s %s (%s:%ld)\n", debugstr_w(family->FamilyName),
2498           debugstr_w(face->StyleName), face->file, face->face_index);
2499
2500     if(!face->scalable) {
2501         width = face->size.x_ppem >> 6;
2502         height = face->size.y_ppem >> 6;
2503     }
2504     ret->ft_face = OpenFontFile(ret, face->file, face->face_index, width, height);
2505
2506     if (!ret->ft_face)
2507     {
2508         free_font( ret );
2509         return 0;
2510     }
2511
2512     if (ret->charset == SYMBOL_CHARSET && 
2513         !pFT_Select_Charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) {
2514         /* No ops */
2515     }
2516     else if (!pFT_Select_Charmap(ret->ft_face, FT_ENCODING_UNICODE)) {
2517         /* No ops */
2518     }
2519     else {
2520         pFT_Select_Charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN);
2521     }
2522
2523     ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0;
2524     ret->name = strdupW(family->FamilyName);
2525     ret->underline = lf.lfUnderline ? 0xff : 0;
2526     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
2527     create_child_font_list(ret);
2528
2529     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
2530
2531     ret->aveWidth = FT_IS_SCALABLE(ret->ft_face) ? lf.lfWidth : 0;
2532     list_add_head(&gdi_font_list, &ret->entry);
2533     return ret;
2534 }
2535
2536 static void dump_gdi_font_list(void)
2537 {
2538     GdiFont *gdiFont;
2539     struct list *elem_ptr;
2540
2541     TRACE("---------- gdiFont Cache ----------\n");
2542     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
2543         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
2544         TRACE("gdiFont=%p %s %ld\n",
2545               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
2546     }
2547
2548     TRACE("---------- Unused gdiFont Cache ----------\n");
2549     LIST_FOR_EACH(elem_ptr, &unused_gdi_font_list) {
2550         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
2551         TRACE("gdiFont=%p %s %ld\n",
2552               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
2553     }
2554 }
2555
2556 /*************************************************************
2557  * WineEngDestroyFontInstance
2558  *
2559  * free the gdiFont associated with this handle
2560  *
2561  */
2562 BOOL WineEngDestroyFontInstance(HFONT handle)
2563 {
2564     GdiFont *gdiFont;
2565     HFONTLIST *hflist;
2566     BOOL ret = FALSE;
2567     struct list *font_elem_ptr, *hfontlist_elem_ptr;
2568     int i = 0;
2569
2570     LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry)
2571     {
2572         struct list *first_hfont = list_head(&gdiFont->hfontlist);
2573         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
2574         if(hflist->hfont == handle)
2575         {
2576             TRACE("removing child font %p from child list\n", gdiFont);
2577             list_remove(&gdiFont->entry);
2578             return TRUE;
2579         }
2580     }
2581
2582     TRACE("destroying hfont=%p\n", handle);
2583     if(TRACE_ON(font))
2584         dump_gdi_font_list();
2585
2586     font_elem_ptr = list_head(&gdi_font_list);
2587     while(font_elem_ptr) {
2588         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2589         font_elem_ptr = list_next(&gdi_font_list, font_elem_ptr);
2590
2591         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
2592         while(hfontlist_elem_ptr) {
2593             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
2594             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
2595             if(hflist->hfont == handle) {
2596                 list_remove(&hflist->entry);
2597                 HeapFree(GetProcessHeap(), 0, hflist);
2598                 ret = TRUE;
2599             }
2600         }
2601         if(list_empty(&gdiFont->hfontlist)) {
2602             TRACE("Moving to Unused list\n");
2603             list_remove(&gdiFont->entry);
2604             list_add_head(&unused_gdi_font_list, &gdiFont->entry);
2605         }
2606     }
2607
2608
2609     font_elem_ptr = list_head(&unused_gdi_font_list);
2610     while(font_elem_ptr && i++ < UNUSED_CACHE_SIZE)
2611         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
2612     while(font_elem_ptr) {
2613         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2614         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
2615         TRACE("freeing %p\n", gdiFont);
2616         list_remove(&gdiFont->entry);
2617         free_font(gdiFont);
2618     }
2619     return ret;
2620 }
2621
2622 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
2623                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
2624 {
2625     OUTLINETEXTMETRICW *potm = NULL;
2626     UINT size;
2627     TEXTMETRICW tm, *ptm;
2628     GdiFont *font = alloc_font();
2629     LONG width, height;
2630
2631     if(face->scalable) {
2632         height = 100;
2633         width = 0;
2634     } else {
2635         height = face->size.y_ppem >> 6;
2636         width = face->size.x_ppem >> 6;
2637     }
2638     
2639     if (!(font->ft_face = OpenFontFile(font, face->file, face->face_index, width, height)))
2640     {
2641         free_font(font);
2642         return;
2643     }
2644
2645     font->name = strdupW(face->family->FamilyName);
2646
2647     memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
2648
2649     size = WineEngGetOutlineTextMetrics(font, 0, NULL);
2650     if(size) {
2651         potm = HeapAlloc(GetProcessHeap(), 0, size);
2652         WineEngGetOutlineTextMetrics(font, size, potm);
2653         ptm = (TEXTMETRICW*)&potm->otmTextMetrics;
2654     } else {
2655         WineEngGetTextMetrics(font, &tm);
2656         ptm = &tm;
2657     }
2658         
2659     pntm->ntmTm.tmHeight = pelf->elfLogFont.lfHeight = ptm->tmHeight;
2660     pntm->ntmTm.tmAscent = ptm->tmAscent;
2661     pntm->ntmTm.tmDescent = ptm->tmDescent;
2662     pntm->ntmTm.tmInternalLeading = ptm->tmInternalLeading;
2663     pntm->ntmTm.tmExternalLeading = ptm->tmExternalLeading;
2664     pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWidth = ptm->tmAveCharWidth;
2665     pntm->ntmTm.tmMaxCharWidth = ptm->tmMaxCharWidth;
2666     pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = ptm->tmWeight;
2667     pntm->ntmTm.tmOverhang = ptm->tmOverhang;
2668     pntm->ntmTm.tmDigitizedAspectX = ptm->tmDigitizedAspectX;
2669     pntm->ntmTm.tmDigitizedAspectY = ptm->tmDigitizedAspectY;
2670     pntm->ntmTm.tmFirstChar = ptm->tmFirstChar;
2671     pntm->ntmTm.tmLastChar = ptm->tmLastChar;
2672     pntm->ntmTm.tmDefaultChar = ptm->tmDefaultChar;
2673     pntm->ntmTm.tmBreakChar = ptm->tmBreakChar;
2674     pntm->ntmTm.tmItalic = pelf->elfLogFont.lfItalic = ptm->tmItalic;
2675     pntm->ntmTm.tmUnderlined = pelf->elfLogFont.lfUnderline = ptm->tmUnderlined;
2676     pntm->ntmTm.tmStruckOut = pelf->elfLogFont.lfStrikeOut = ptm->tmStruckOut;
2677     pntm->ntmTm.tmPitchAndFamily = ptm->tmPitchAndFamily;
2678     pelf->elfLogFont.lfPitchAndFamily = (ptm->tmPitchAndFamily & 0xf1) + 1;
2679     pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = ptm->tmCharSet;
2680     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
2681     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
2682     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
2683
2684     *ptype = ptm->tmPitchAndFamily & TMPF_TRUETYPE ? TRUETYPE_FONTTYPE : 0;
2685     if(!(ptm->tmPitchAndFamily & TMPF_VECTOR))
2686         *ptype |= RASTER_FONTTYPE;
2687
2688     pntm->ntmTm.ntmFlags = ptm->tmItalic ? NTM_ITALIC : 0;
2689     if(ptm->tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD;
2690     if(pntm->ntmTm.ntmFlags == 0) pntm->ntmTm.ntmFlags = NTM_REGULAR;
2691
2692     pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
2693     pntm->ntmTm.ntmAvgWidth = pntm->ntmTm.tmAveCharWidth;
2694     memset(&pntm->ntmFontSig, 0, sizeof(FONTSIGNATURE));
2695
2696     if(potm) {
2697         pntm->ntmTm.ntmSizeEM = potm->otmEMSquare;
2698
2699         lstrcpynW(pelf->elfLogFont.lfFaceName,
2700                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFamilyName),
2701                  LF_FACESIZE);
2702         lstrcpynW(pelf->elfFullName,
2703                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFaceName),
2704                  LF_FULLFACESIZE);
2705         lstrcpynW(pelf->elfStyle,
2706                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName),
2707                  LF_FACESIZE);
2708
2709         HeapFree(GetProcessHeap(), 0, potm);
2710     } else {
2711         pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
2712
2713         lstrcpynW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
2714         lstrcpynW(pelf->elfFullName, face->family->FamilyName, LF_FACESIZE);
2715         pelf->elfStyle[0] = '\0';
2716     }
2717
2718     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
2719
2720     free_font(font);
2721 }
2722
2723 /*************************************************************
2724  * WineEngEnumFonts
2725  *
2726  */
2727 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
2728 {
2729     Family *family;
2730     Face *face;
2731     struct list *family_elem_ptr, *face_elem_ptr;
2732     ENUMLOGFONTEXW elf;
2733     NEWTEXTMETRICEXW ntm;
2734     DWORD type, ret = 1;
2735     FONTSIGNATURE fs;
2736     CHARSETINFO csi;
2737     LOGFONTW lf;
2738     int i;
2739
2740     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
2741
2742     if(plf->lfFaceName[0]) {
2743         FontSubst *psub;
2744         psub = get_font_subst(&font_subst_list, plf->lfFaceName, plf->lfCharSet);
2745
2746         if(psub) {
2747             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
2748                   debugstr_w(psub->to.name));
2749             memcpy(&lf, plf, sizeof(lf));
2750             strcpyW(lf.lfFaceName, psub->to.name);
2751             plf = &lf;
2752         }
2753
2754         LIST_FOR_EACH(family_elem_ptr, &font_list) {
2755             family = LIST_ENTRY(family_elem_ptr, Family, entry);
2756             if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
2757                 LIST_FOR_EACH(face_elem_ptr, &family->faces) {
2758                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
2759                     GetEnumStructs(face, &elf, &ntm, &type);
2760                     for(i = 0; i < 32; i++) {
2761                         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
2762                             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
2763                             strcpyW(elf.elfScript, OEM_DOSW);
2764                             i = 32; /* break out of loop */
2765                         } else if(!(face->fs.fsCsb[0] & (1L << i)))
2766                             continue;
2767                         else {
2768                             fs.fsCsb[0] = 1L << i;
2769                             fs.fsCsb[1] = 0;
2770                             if(!TranslateCharsetInfo(fs.fsCsb, &csi,
2771                                                      TCI_SRCFONTSIG))
2772                                 csi.ciCharset = DEFAULT_CHARSET;
2773                             if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
2774                             if(csi.ciCharset != DEFAULT_CHARSET) {
2775                                 elf.elfLogFont.lfCharSet =
2776                                     ntm.ntmTm.tmCharSet = csi.ciCharset;
2777                                 if(ElfScriptsW[i])
2778                                     strcpyW(elf.elfScript, ElfScriptsW[i]);
2779                                 else
2780                                     FIXME("Unknown elfscript for bit %d\n", i);
2781                             }
2782                         }
2783                         TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
2784                               debugstr_w(elf.elfLogFont.lfFaceName),
2785                               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
2786                               csi.ciCharset, type, debugstr_w(elf.elfScript),
2787                               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
2788                               ntm.ntmTm.ntmFlags);
2789                         ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
2790                         if(!ret) goto end;
2791                     }
2792                 }
2793             }
2794         }
2795     } else {
2796         LIST_FOR_EACH(family_elem_ptr, &font_list) {
2797             family = LIST_ENTRY(family_elem_ptr, Family, entry);
2798             face_elem_ptr = list_head(&family->faces);
2799             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2800             GetEnumStructs(face, &elf, &ntm, &type);
2801             for(i = 0; i < 32; i++) {
2802                 if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
2803                     elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
2804                     strcpyW(elf.elfScript, OEM_DOSW);
2805                     i = 32; /* break out of loop */
2806                 } else if(!(face->fs.fsCsb[0] & (1L << i)))
2807                     continue;
2808                 else {
2809                     fs.fsCsb[0] = 1L << i;
2810                     fs.fsCsb[1] = 0;
2811                     if(!TranslateCharsetInfo(fs.fsCsb, &csi,
2812                                              TCI_SRCFONTSIG))
2813                         csi.ciCharset = DEFAULT_CHARSET;
2814                     if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
2815                     if(csi.ciCharset != DEFAULT_CHARSET) {
2816                         elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet =
2817                           csi.ciCharset;
2818                           if(ElfScriptsW[i])
2819                               strcpyW(elf.elfScript, ElfScriptsW[i]);
2820                           else
2821                               FIXME("Unknown elfscript for bit %d\n", i);
2822                     }
2823                 }
2824                 TRACE("enuming face %s full %s style %s charset = %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
2825                       debugstr_w(elf.elfLogFont.lfFaceName),
2826                       debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
2827                       csi.ciCharset, type, debugstr_w(elf.elfScript),
2828                       elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
2829                       ntm.ntmTm.ntmFlags);
2830                 ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
2831                 if(!ret) goto end;
2832             }
2833         }
2834     }
2835 end:
2836     return ret;
2837 }
2838
2839 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
2840 {
2841     pt->x.value = vec->x >> 6;
2842     pt->x.fract = (vec->x & 0x3f) << 10;
2843     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
2844     pt->y.value = vec->y >> 6;
2845     pt->y.fract = (vec->y & 0x3f) << 10;
2846     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
2847     return;
2848 }
2849
2850 /***************************************************
2851  * According to the MSDN documentation on WideCharToMultiByte,
2852  * certain codepages cannot set the default_used parameter.
2853  * This returns TRUE if the codepage can set that parameter, false else
2854  * so that calls to WideCharToMultiByte don't fail with ERROR_INVALID_PARAMETER
2855  */
2856 static BOOL codepage_sets_default_used(UINT codepage)
2857 {
2858    switch (codepage)
2859    {
2860        case CP_UTF7:
2861        case CP_UTF8:
2862        case CP_SYMBOL:
2863            return FALSE;
2864        default:
2865            return TRUE;
2866    }
2867 }
2868
2869 static FT_UInt get_glyph_index(GdiFont *font, UINT glyph)
2870 {
2871     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
2872         WCHAR wc = (WCHAR)glyph;
2873         BOOL default_used;
2874         BOOL *default_used_pointer;
2875         FT_UInt ret;
2876         char buf;
2877         default_used_pointer = NULL;
2878         default_used = FALSE;
2879         if (codepage_sets_default_used(font->codepage))
2880             default_used_pointer = &default_used;
2881         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
2882             ret = 0;
2883         else
2884             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
2885         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
2886         return ret;
2887     }
2888
2889     if(font->charset == SYMBOL_CHARSET && glyph < 0x100)
2890         glyph = glyph + 0xf000;
2891     return pFT_Get_Char_Index(font->ft_face, glyph);
2892 }
2893
2894 /*************************************************************
2895  * WineEngGetGlyphIndices
2896  *
2897  * FIXME: add support for GGI_MARK_NONEXISTING_GLYPHS
2898  */
2899 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
2900                                 LPWORD pgi, DWORD flags)
2901 {
2902     int i;
2903     WCHAR default_char = 0;
2904     TEXTMETRICW textm;
2905
2906     if  (flags & GGI_MARK_NONEXISTING_GLYPHS) default_char = 0x001f;  /* Indicate non existence */
2907
2908     for(i = 0; i < count; i++)
2909     {
2910         pgi[i] = get_glyph_index(font, lpstr[i]);
2911         if  (pgi[i] == 0)
2912         {
2913             if (!default_char)
2914             {
2915                 WineEngGetTextMetrics(font, &textm);
2916                 default_char = textm.tmDefaultChar;
2917             }
2918             pgi[i] = default_char;
2919         }
2920     }
2921     return count;
2922 }
2923
2924 /*************************************************************
2925  * WineEngGetGlyphOutline
2926  *
2927  * Behaves in exactly the same way as the win32 api GetGlyphOutline
2928  * except that the first parameter is the HWINEENGFONT of the font in
2929  * question rather than an HDC.
2930  *
2931  */
2932 DWORD WineEngGetGlyphOutline(GdiFont *font, UINT glyph, UINT format,
2933                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
2934                              const MAT2* lpmat)
2935 {
2936     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
2937     FT_Face ft_face = font->ft_face;
2938     FT_UInt glyph_index;
2939     DWORD width, height, pitch, needed = 0;
2940     FT_Bitmap ft_bitmap;
2941     FT_Error err;
2942     INT left, right, top = 0, bottom = 0;
2943     FT_Angle angle = 0;
2944     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
2945     float widthRatio = 1.0;
2946     FT_Matrix transMat = identityMat;
2947     BOOL needsTransform = FALSE;
2948
2949
2950     TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm,
2951           buflen, buf, lpmat);
2952
2953     if(format & GGO_GLYPH_INDEX) {
2954         glyph_index = glyph;
2955         format &= ~GGO_GLYPH_INDEX;
2956     } else
2957         glyph_index = get_glyph_index(font, glyph);
2958
2959     if(glyph_index >= font->gmsize) {
2960         font->gmsize = (glyph_index / INIT_GM_SIZE + 1) * INIT_GM_SIZE;
2961         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
2962                                font->gmsize * sizeof(*font->gm));
2963     } else {
2964         if(format == GGO_METRICS && font->gm[glyph_index].init) {
2965             memcpy(lpgm, &font->gm[glyph_index].gm, sizeof(*lpgm));
2966             return 1; /* FIXME */
2967         }
2968     }
2969
2970     if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP) || font->aveWidth || lpmat)
2971         load_flags |= FT_LOAD_NO_BITMAP;
2972
2973     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
2974
2975     if(err) {
2976         FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
2977         return GDI_ERROR;
2978     }
2979         
2980     /* Scaling factor */
2981     if (font->aveWidth && font->potm) {
2982         widthRatio = (float)font->aveWidth * font->font_desc.matrix.eM11 / (float) font->potm->otmTextMetrics.tmAveCharWidth;
2983     }
2984
2985     left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
2986     right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
2987
2988     font->gm[glyph_index].adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
2989     font->gm[glyph_index].lsb = left >> 6;
2990     font->gm[glyph_index].bbx = (right - left) >> 6;
2991
2992     /* Scaling transform */
2993     if(font->aveWidth) {
2994         FT_Matrix scaleMat;
2995         scaleMat.xx = FT_FixedFromFloat(widthRatio);
2996         scaleMat.xy = 0;
2997         scaleMat.yx = 0;
2998         scaleMat.yy = (1 << 16);
2999
3000         pFT_Matrix_Multiply(&scaleMat, &transMat);
3001         needsTransform = TRUE;
3002     }
3003
3004     /* Slant transform */
3005     if (font->fake_italic) {
3006         FT_Matrix slantMat;
3007         
3008         slantMat.xx = (1 << 16);
3009         slantMat.xy = ((1 << 16) >> 2);
3010         slantMat.yx = 0;
3011         slantMat.yy = (1 << 16);
3012         pFT_Matrix_Multiply(&slantMat, &transMat);
3013         needsTransform = TRUE;
3014     }
3015
3016     /* Rotation transform */
3017     if(font->orientation) {
3018         FT_Matrix rotationMat;
3019         FT_Vector vecAngle;
3020         angle = FT_FixedFromFloat((float)font->orientation / 10.0);
3021         pFT_Vector_Unit(&vecAngle, angle);
3022         rotationMat.xx = vecAngle.x;
3023         rotationMat.xy = -vecAngle.y;
3024         rotationMat.yx = -rotationMat.xy;
3025         rotationMat.yy = rotationMat.xx;
3026         
3027         pFT_Matrix_Multiply(&rotationMat, &transMat);
3028         needsTransform = TRUE;
3029     }
3030
3031     /* Extra transformation specified by caller */
3032     if (lpmat) {
3033         FT_Matrix extraMat;
3034         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
3035         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
3036         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
3037         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
3038         pFT_Matrix_Multiply(&extraMat, &transMat);
3039         needsTransform = TRUE;
3040     }
3041
3042     if(!needsTransform) {
3043         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
3044         bottom = (ft_face->glyph->metrics.horiBearingY -
3045                   ft_face->glyph->metrics.height) & -64;
3046         lpgm->gmCellIncX = font->gm[glyph_index].adv;
3047         lpgm->gmCellIncY = 0;
3048     } else {
3049         INT xc, yc;
3050         FT_Vector vec;
3051         for(xc = 0; xc < 2; xc++) {
3052             for(yc = 0; yc < 2; yc++) {
3053                 vec.x = (ft_face->glyph->metrics.horiBearingX +
3054                   xc * ft_face->glyph->metrics.width);
3055                 vec.y = ft_face->glyph->metrics.horiBearingY -
3056                   yc * ft_face->glyph->metrics.height;
3057                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
3058                 pFT_Vector_Transform(&vec, &transMat);
3059                 if(xc == 0 && yc == 0) {
3060                     left = right = vec.x;
3061                     top = bottom = vec.y;
3062                 } else {
3063                     if(vec.x < left) left = vec.x;
3064                     else if(vec.x > right) right = vec.x;
3065                     if(vec.y < bottom) bottom = vec.y;
3066                     else if(vec.y > top) top = vec.y;
3067                 }
3068             }
3069         }
3070         left = left & -64;
3071         right = (right + 63) & -64;
3072         bottom = bottom & -64;
3073         top = (top + 63) & -64;
3074
3075         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
3076         vec.x = ft_face->glyph->metrics.horiAdvance;
3077         vec.y = 0;
3078         pFT_Vector_Transform(&vec, &transMat);
3079         lpgm->gmCellIncX = (vec.x+63) >> 6;
3080         lpgm->gmCellIncY = -((vec.y+63) >> 6);
3081     }
3082     lpgm->gmBlackBoxX = (right - left) >> 6;
3083     lpgm->gmBlackBoxY = (top - bottom) >> 6;
3084     lpgm->gmptGlyphOrigin.x = left >> 6;
3085     lpgm->gmptGlyphOrigin.y = top >> 6;
3086
3087     memcpy(&font->gm[glyph_index].gm, lpgm, sizeof(*lpgm));
3088     font->gm[glyph_index].init = TRUE;
3089
3090     if(format == GGO_METRICS)
3091         return 1; /* FIXME */
3092
3093     if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) {
3094         TRACE("loaded a bitmap\n");
3095         return GDI_ERROR;
3096     }
3097
3098     switch(format) {
3099     case GGO_BITMAP:
3100         width = lpgm->gmBlackBoxX;
3101         height = lpgm->gmBlackBoxY;
3102         pitch = ((width + 31) >> 5) << 2;
3103         needed = pitch * height;
3104
3105         if(!buf || !buflen) break;
3106
3107         switch(ft_face->glyph->format) {
3108         case ft_glyph_format_bitmap:
3109           {
3110             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
3111             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
3112             INT h = ft_face->glyph->bitmap.rows;
3113             while(h--) {
3114                 memcpy(dst, src, w);
3115                 src += ft_face->glyph->bitmap.pitch;
3116                 dst += pitch;
3117             }
3118             break;
3119           }
3120
3121         case ft_glyph_format_outline:
3122             ft_bitmap.width = width;
3123             ft_bitmap.rows = height;
3124             ft_bitmap.pitch = pitch;
3125             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
3126             ft_bitmap.buffer = buf;
3127
3128                 if(needsTransform) {
3129                         pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
3130             }
3131
3132             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
3133
3134             /* Note: FreeType will only set 'black' bits for us. */
3135             memset(buf, 0, needed);
3136             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
3137             break;
3138
3139         default:
3140             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
3141             return GDI_ERROR;
3142         }
3143         break;
3144
3145     case GGO_GRAY2_BITMAP:
3146     case GGO_GRAY4_BITMAP:
3147     case GGO_GRAY8_BITMAP:
3148     case WINE_GGO_GRAY16_BITMAP:
3149       {
3150         unsigned int mult, row, col;
3151         BYTE *start, *ptr;
3152
3153         width = lpgm->gmBlackBoxX;
3154         height = lpgm->gmBlackBoxY;
3155         pitch = (width + 3) / 4 * 4;
3156         needed = pitch * height;
3157
3158         if(!buf || !buflen) break;
3159         ft_bitmap.width = width;
3160         ft_bitmap.rows = height;
3161         ft_bitmap.pitch = pitch;
3162         ft_bitmap.pixel_mode = ft_pixel_mode_grays;
3163         ft_bitmap.buffer = buf;
3164
3165         if(needsTransform) {
3166                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
3167         }
3168
3169         pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
3170
3171         memset(ft_bitmap.buffer, 0, buflen);
3172
3173         pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
3174
3175         if(format == GGO_GRAY2_BITMAP)
3176             mult = 4;
3177         else if(format == GGO_GRAY4_BITMAP)
3178             mult = 16;
3179         else if(format == GGO_GRAY8_BITMAP)
3180             mult = 64;
3181         else if(format == WINE_GGO_GRAY16_BITMAP)
3182             break;
3183         else {
3184             assert(0);
3185             break;
3186         }
3187
3188         start = buf;
3189         for(row = 0; row < height; row++) {
3190             ptr = start;
3191             for(col = 0; col < width; col++, ptr++) {
3192                 *ptr = (((int)*ptr) * mult + 128) / 256;
3193             }
3194             start += pitch;
3195         }
3196         break;
3197       }
3198
3199     case GGO_NATIVE:
3200       {
3201         int contour, point = 0, first_pt;
3202         FT_Outline *outline = &ft_face->glyph->outline;
3203         TTPOLYGONHEADER *pph;
3204         TTPOLYCURVE *ppc;
3205         DWORD pph_start, cpfx, type;
3206
3207         if(buflen == 0) buf = NULL;
3208
3209         if (needsTransform && buf) {
3210                 pFT_Outline_Transform(outline, &transMat);
3211         }
3212
3213         for(contour = 0; contour < outline->n_contours; contour++) {
3214             pph_start = needed;
3215             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
3216             first_pt = point;
3217             if(buf) {
3218                 pph->dwType = TT_POLYGON_TYPE;
3219                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3220             }
3221             needed += sizeof(*pph);
3222             point++;
3223             while(point <= outline->contours[contour]) {
3224                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
3225                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3226                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
3227                 cpfx = 0;
3228                 do {
3229                     if(buf)
3230                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3231                     cpfx++;
3232                     point++;
3233                 } while(point <= outline->contours[contour] &&
3234                         (outline->tags[point] & FT_Curve_Tag_On) ==
3235                         (outline->tags[point-1] & FT_Curve_Tag_On));
3236                 /* At the end of a contour Windows adds the start point, but
3237                    only for Beziers */
3238                 if(point > outline->contours[contour] &&
3239                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
3240                     if(buf)
3241                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
3242                     cpfx++;
3243                 } else if(point <= outline->contours[contour] &&
3244                           outline->tags[point] & FT_Curve_Tag_On) {
3245                   /* add closing pt for bezier */
3246                     if(buf)
3247                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3248                     cpfx++;
3249                     point++;
3250                 }
3251                 if(buf) {
3252                     ppc->wType = type;
3253                     ppc->cpfx = cpfx;
3254                 }
3255                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3256             }
3257             if(buf)
3258                 pph->cb = needed - pph_start;
3259         }
3260         break;
3261       }
3262     case GGO_BEZIER:
3263       {
3264         /* Convert the quadratic Beziers to cubic Beziers.
3265            The parametric eqn for a cubic Bezier is, from PLRM:
3266            r(t) = at^3 + bt^2 + ct + r0
3267            with the control points:
3268            r1 = r0 + c/3
3269            r2 = r1 + (c + b)/3
3270            r3 = r0 + c + b + a
3271
3272            A quadratic Beizer has the form:
3273            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
3274
3275            So equating powers of t leads to:
3276            r1 = 2/3 p1 + 1/3 p0
3277            r2 = 2/3 p1 + 1/3 p2
3278            and of course r0 = p0, r3 = p2
3279         */
3280
3281         int contour, point = 0, first_pt;
3282         FT_Outline *outline = &ft_face->glyph->outline;
3283         TTPOLYGONHEADER *pph;
3284         TTPOLYCURVE *ppc;
3285         DWORD pph_start, cpfx, type;
3286         FT_Vector cubic_control[4];
3287         if(buflen == 0) buf = NULL;
3288
3289         if (needsTransform && buf) {
3290                 pFT_Outline_Transform(outline, &transMat);
3291         }
3292
3293         for(contour = 0; contour < outline->n_contours; contour++) {
3294             pph_start = needed;
3295             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
3296             first_pt = point;
3297             if(buf) {
3298                 pph->dwType = TT_POLYGON_TYPE;
3299                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3300             }
3301             needed += sizeof(*pph);
3302             point++;
3303             while(point <= outline->contours[contour]) {
3304                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
3305                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3306                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
3307                 cpfx = 0;
3308                 do {
3309                     if(type == TT_PRIM_LINE) {
3310                         if(buf)
3311                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3312                         cpfx++;
3313                         point++;
3314                     } else {
3315                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
3316                          so cpfx = 3n */
3317
3318                       /* FIXME: Possible optimization in endpoint calculation
3319                          if there are two consecutive curves */
3320                         cubic_control[0] = outline->points[point-1];
3321                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
3322                             cubic_control[0].x += outline->points[point].x + 1;
3323                             cubic_control[0].y += outline->points[point].y + 1;
3324                             cubic_control[0].x >>= 1;
3325                             cubic_control[0].y >>= 1;
3326                         }
3327                         if(point+1 > outline->contours[contour])
3328                             cubic_control[3] = outline->points[first_pt];
3329                         else {
3330                             cubic_control[3] = outline->points[point+1];
3331                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
3332                                 cubic_control[3].x += outline->points[point].x + 1;
3333                                 cubic_control[3].y += outline->points[point].y + 1;
3334                                 cubic_control[3].x >>= 1;
3335                                 cubic_control[3].y >>= 1;
3336                             }
3337                         }
3338                         /* r1 = 1/3 p0 + 2/3 p1
3339                            r2 = 1/3 p2 + 2/3 p1 */
3340                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
3341                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
3342                         cubic_control[2] = cubic_control[1];
3343                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
3344                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
3345                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
3346                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
3347                         if(buf) {
3348                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
3349                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
3350                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
3351                         }
3352                         cpfx += 3;
3353                         point++;
3354                     }
3355                 } while(point <= outline->contours[contour] &&
3356                         (outline->tags[point] & FT_Curve_Tag_On) ==
3357                         (outline->tags[point-1] & FT_Curve_Tag_On));
3358                 /* At the end of a contour Windows adds the start point,
3359                    but only for Beziers and we've already done that.
3360                 */
3361                 if(point <= outline->contours[contour] &&
3362                    outline->tags[point] & FT_Curve_Tag_On) {
3363                   /* This is the closing pt of a bezier, but we've already
3364                      added it, so just inc point and carry on */
3365                     point++;
3366                 }
3367                 if(buf) {
3368                     ppc->wType = type;
3369                     ppc->cpfx = cpfx;
3370                 }
3371                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3372             }
3373             if(buf)
3374                 pph->cb = needed - pph_start;
3375         }
3376         break;
3377       }
3378
3379     default:
3380         FIXME("Unsupported format %d\n", format);
3381         return GDI_ERROR;
3382     }
3383     return needed;
3384 }
3385
3386 static BOOL get_bitmap_text_metrics(GdiFont *font)
3387 {
3388     FT_Face ft_face = font->ft_face;
3389 #ifdef HAVE_FREETYPE_FTWINFNT_H
3390     FT_WinFNT_HeaderRec winfnt_header;
3391 #endif
3392     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
3393     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
3394     font->potm->otmSize = size;
3395
3396 #define TM font->potm->otmTextMetrics
3397 #ifdef HAVE_FREETYPE_FTWINFNT_H
3398     if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
3399     {
3400         TM.tmHeight = winfnt_header.pixel_height;
3401         TM.tmAscent = winfnt_header.ascent;
3402         TM.tmDescent = TM.tmHeight - TM.tmAscent;
3403         TM.tmInternalLeading = winfnt_header.internal_leading;
3404         TM.tmExternalLeading = winfnt_header.external_leading;
3405         TM.tmAveCharWidth = winfnt_header.avg_width;
3406         TM.tmMaxCharWidth = winfnt_header.max_width;
3407         TM.tmWeight = winfnt_header.weight;
3408         TM.tmOverhang = 0;
3409         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
3410         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
3411         TM.tmFirstChar = winfnt_header.first_char;
3412         TM.tmLastChar = winfnt_header.last_char;
3413         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
3414         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
3415         TM.tmItalic = winfnt_header.italic;
3416         TM.tmUnderlined = font->underline;
3417         TM.tmStruckOut = font->strikeout;
3418         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
3419         TM.tmCharSet = winfnt_header.charset;
3420     }
3421     else
3422 #endif
3423     {
3424         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
3425         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
3426         TM.tmHeight = TM.tmAscent + TM.tmDescent;
3427         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
3428         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
3429         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
3430         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
3431         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
3432         TM.tmOverhang = 0;
3433         TM.tmDigitizedAspectX = 96; /* FIXME */
3434         TM.tmDigitizedAspectY = 96; /* FIXME */
3435         TM.tmFirstChar = 1;
3436         TM.tmLastChar = 255;
3437         TM.tmDefaultChar = 32;
3438         TM.tmBreakChar = 32;
3439         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
3440         TM.tmUnderlined = font->underline;
3441         TM.tmStruckOut = font->strikeout;
3442         /* NB inverted meaning of TMPF_FIXED_PITCH */
3443         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
3444         TM.tmCharSet = font->charset;
3445     }
3446 #undef TM
3447
3448     return TRUE;
3449 }
3450
3451 /*************************************************************
3452  * WineEngGetTextMetrics
3453  *
3454  */
3455 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
3456 {
3457     if(!font->potm) {
3458         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
3459             if(!get_bitmap_text_metrics(font))
3460                 return FALSE;
3461     }
3462     if(!font->potm) return FALSE;
3463     memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm));
3464
3465     if (font->aveWidth) {
3466         ptm->tmAveCharWidth = font->aveWidth * font->font_desc.matrix.eM11;
3467     }
3468     return TRUE;
3469 }
3470
3471
3472 /*************************************************************
3473  * WineEngGetOutlineTextMetrics
3474  *
3475  */
3476 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
3477                                   OUTLINETEXTMETRICW *potm)
3478 {
3479     FT_Face ft_face = font->ft_face;
3480     UINT needed, lenfam, lensty, ret;
3481     TT_OS2 *pOS2;
3482     TT_HoriHeader *pHori;
3483     TT_Postscript *pPost;
3484     FT_Fixed x_scale, y_scale;
3485     WCHAR *family_nameW, *style_nameW;
3486     static const WCHAR spaceW[] = {' ', '\0'};
3487     char *cp;
3488     INT ascent, descent;
3489
3490     TRACE("font=%p\n", font);
3491
3492     if(!FT_IS_SCALABLE(ft_face))
3493         return 0;
3494
3495     if(font->potm) {
3496         if(cbSize >= font->potm->otmSize)
3497             memcpy(potm, font->potm, font->potm->otmSize);
3498         return font->potm->otmSize;
3499     }
3500
3501
3502     needed = sizeof(*potm);
3503
3504     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
3505     family_nameW = strdupW(font->name);
3506
3507     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
3508       * sizeof(WCHAR);
3509     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
3510     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
3511                         style_nameW, lensty/sizeof(WCHAR));
3512
3513     /* These names should be read from the TT name table */
3514
3515     /* length of otmpFamilyName */
3516     needed += lenfam;
3517
3518     /* length of otmpFaceName */
3519     if(!strcasecmp(ft_face->style_name, "regular")) {
3520       needed += lenfam; /* just the family name */
3521     } else {
3522       needed += lenfam + lensty; /* family + " " + style */
3523     }
3524
3525     /* length of otmpStyleName */
3526     needed += lensty;
3527
3528     /* length of otmpFullName */
3529     needed += lenfam + lensty;
3530
3531
3532     x_scale = ft_face->size->metrics.x_scale;
3533     y_scale = ft_face->size->metrics.y_scale;
3534
3535     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
3536     if(!pOS2) {
3537         FIXME("Can't find OS/2 table - not TT font?\n");
3538         ret = 0;
3539         goto end;
3540     }
3541
3542     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
3543     if(!pHori) {
3544         FIXME("Can't find HHEA table - not TT font?\n");
3545         ret = 0;
3546         goto end;
3547     }
3548
3549     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
3550
3551     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",
3552           pOS2->usWinAscent, pOS2->usWinDescent,
3553           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
3554           ft_face->ascender, ft_face->descender, ft_face->height,
3555           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
3556           ft_face->bbox.yMax, ft_face->bbox.yMin);
3557
3558     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
3559     font->potm->otmSize = needed;
3560
3561 #define TM font->potm->otmTextMetrics
3562
3563     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
3564         ascent = pHori->Ascender;
3565         descent = -pHori->Descender;
3566     } else {
3567         ascent = pOS2->usWinAscent;
3568         descent = pOS2->usWinDescent;
3569     }
3570
3571     if(font->yMax) {
3572         TM.tmAscent = font->yMax;
3573         TM.tmDescent = -font->yMin;
3574         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
3575     } else {
3576         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
3577         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
3578         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
3579                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
3580     }
3581
3582     TM.tmHeight = TM.tmAscent + TM.tmDescent;
3583
3584     /* MSDN says:
3585      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
3586     */
3587     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
3588                  ((ascent + descent) -
3589                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
3590
3591     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
3592     if (TM.tmAveCharWidth == 0) {
3593         TM.tmAveCharWidth = 1; 
3594     }
3595     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
3596     TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
3597     TM.tmOverhang = 0;
3598     TM.tmDigitizedAspectX = 300;
3599     TM.tmDigitizedAspectY = 300;
3600     TM.tmFirstChar = pOS2->usFirstCharIndex;
3601     TM.tmLastChar = pOS2->usLastCharIndex;
3602     TM.tmDefaultChar = pOS2->usDefaultChar;
3603     TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
3604     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
3605     TM.tmUnderlined = font->underline;
3606     TM.tmStruckOut = font->strikeout;
3607
3608     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
3609     if(!FT_IS_FIXED_WIDTH(ft_face) &&
3610        (pOS2->version == 0xFFFFU || 
3611         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
3612         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
3613     else
3614         TM.tmPitchAndFamily = 0;
3615
3616     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
3617     case PAN_FAMILY_SCRIPT:
3618         TM.tmPitchAndFamily |= FF_SCRIPT;
3619         break;
3620     case PAN_FAMILY_DECORATIVE:
3621     case PAN_FAMILY_PICTORIAL:
3622         TM.tmPitchAndFamily |= FF_DECORATIVE;
3623         break;
3624     case PAN_FAMILY_TEXT_DISPLAY:
3625         if(TM.tmPitchAndFamily == 0) /* fixed */
3626             TM.tmPitchAndFamily = FF_MODERN;
3627         else {
3628             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
3629             case PAN_SERIF_NORMAL_SANS:
3630             case PAN_SERIF_OBTUSE_SANS:
3631             case PAN_SERIF_PERP_SANS:
3632                 TM.tmPitchAndFamily |= FF_SWISS;
3633                 break;
3634             default:
3635                 TM.tmPitchAndFamily |= FF_ROMAN;
3636             }
3637         }
3638         break;
3639     default:
3640         TM.tmPitchAndFamily |= FF_DONTCARE;
3641     }
3642
3643     if(FT_IS_SCALABLE(ft_face))
3644         TM.tmPitchAndFamily |= TMPF_VECTOR;
3645     if(FT_IS_SFNT(ft_face))
3646         TM.tmPitchAndFamily |= TMPF_TRUETYPE;
3647
3648     TM.tmCharSet = font->charset;
3649 #undef TM
3650
3651     font->potm->otmFiller = 0;
3652     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
3653     font->potm->otmfsSelection = pOS2->fsSelection;
3654     font->potm->otmfsType = pOS2->fsType;
3655     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
3656     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
3657     font->potm->otmItalicAngle = 0; /* POST table */
3658     font->potm->otmEMSquare = ft_face->units_per_EM;
3659     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
3660     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
3661     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
3662     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
3663     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
3664     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
3665     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
3666     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
3667     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
3668     font->potm->otmMacAscent = 0; /* where do these come from ? */
3669     font->potm->otmMacDescent = 0;
3670     font->potm->otmMacLineGap = 0;
3671     font->potm->otmusMinimumPPEM = 0; /* TT Header */
3672     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
3673     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
3674     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
3675     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
3676     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
3677     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
3678     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
3679     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
3680     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
3681     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
3682     if(!pPost) {
3683         font->potm->otmsUnderscoreSize = 0;
3684         font->potm->otmsUnderscorePosition = 0;
3685     } else {
3686         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
3687         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
3688     }
3689
3690     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
3691     cp = (char*)font->potm + sizeof(*font->potm);
3692     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
3693     strcpyW((WCHAR*)cp, family_nameW);
3694     cp += lenfam;
3695     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
3696     strcpyW((WCHAR*)cp, style_nameW);
3697     cp += lensty;
3698     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
3699     strcpyW((WCHAR*)cp, family_nameW);
3700     if(strcasecmp(ft_face->style_name, "regular")) {
3701         strcatW((WCHAR*)cp, spaceW);
3702         strcatW((WCHAR*)cp, style_nameW);
3703         cp += lenfam + lensty;
3704     } else
3705         cp += lenfam;
3706     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
3707     strcpyW((WCHAR*)cp, family_nameW);
3708     strcatW((WCHAR*)cp, spaceW);
3709     strcatW((WCHAR*)cp, style_nameW);
3710     ret = needed;
3711
3712     if(potm && needed <= cbSize)
3713         memcpy(potm, font->potm, font->potm->otmSize);
3714
3715 end:
3716     HeapFree(GetProcessHeap(), 0, style_nameW);
3717     HeapFree(GetProcessHeap(), 0, family_nameW);
3718
3719     return ret;
3720 }
3721
3722 static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
3723 {
3724     HFONTLIST *hfontlist;
3725     child->font = alloc_font();
3726     child->font->ft_face = OpenFontFile(child->font, child->file_name, child->index, 0, -font->ppem);
3727     if(!child->font->ft_face)
3728     {
3729         free_font(child->font);
3730         child->font = NULL;
3731         return FALSE;
3732     }
3733
3734     child->font->orientation = font->orientation;
3735     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
3736     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
3737     list_add_head(&child->font->hfontlist, &hfontlist->entry);
3738     child->font->base_font = font;
3739     list_add_head(&child_font_list, &child->font->entry);
3740     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
3741     return TRUE;
3742 }
3743
3744 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph)
3745 {
3746     FT_UInt g;
3747     CHILD_FONT *child_font;
3748
3749     if(font->base_font)
3750         font = font->base_font;
3751
3752     *linked_font = font;
3753
3754     if((*glyph = get_glyph_index(font, c)))
3755         return TRUE;
3756
3757     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
3758     {
3759         if(!child_font->font)
3760             if(!load_child_font(font, child_font))
3761                 continue;
3762
3763         if(!child_font->font->ft_face)
3764             continue;
3765         g = get_glyph_index(child_font->font, c);
3766         if(g)
3767         {
3768             *glyph = g;
3769             *linked_font = child_font->font;
3770             return TRUE;
3771         }
3772     }
3773     return FALSE;
3774 }
3775
3776 /*************************************************************
3777  * WineEngGetCharWidth
3778  *
3779  */
3780 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
3781                          LPINT buffer)
3782 {
3783     UINT c;
3784     GLYPHMETRICS gm;
3785     FT_UInt glyph_index;
3786     GdiFont *linked_font;
3787
3788     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
3789
3790     for(c = firstChar; c <= lastChar; c++) {
3791         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
3792         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3793                                &gm, 0, NULL, NULL);
3794         buffer[c - firstChar] = linked_font->gm[glyph_index].adv;
3795     }
3796     return TRUE;
3797 }
3798
3799 /*************************************************************
3800  * WineEngGetCharABCWidths
3801  *
3802  */
3803 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
3804                              LPABC buffer)
3805 {
3806     UINT c;
3807     GLYPHMETRICS gm;
3808     FT_UInt glyph_index;
3809     GdiFont *linked_font;
3810
3811     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
3812
3813     if(!FT_IS_SCALABLE(font->ft_face))
3814         return FALSE;
3815
3816     for(c = firstChar; c <= lastChar; c++) {
3817         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
3818         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3819                                &gm, 0, NULL, NULL);
3820         buffer[c - firstChar].abcA = linked_font->gm[glyph_index].lsb;
3821         buffer[c - firstChar].abcB = linked_font->gm[glyph_index].bbx;
3822         buffer[c - firstChar].abcC = linked_font->gm[glyph_index].adv - linked_font->gm[glyph_index].lsb -
3823           linked_font->gm[glyph_index].bbx;
3824     }
3825     return TRUE;
3826 }
3827
3828 /*************************************************************
3829  * WineEngGetCharABCWidthsI
3830  *
3831  */
3832 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
3833                               LPABC buffer)
3834 {
3835     UINT c;
3836     GLYPHMETRICS gm;
3837     FT_UInt glyph_index;
3838     GdiFont *linked_font;
3839
3840     if(!FT_IS_SCALABLE(font->ft_face))
3841         return FALSE;
3842
3843     get_glyph_index_linked(font, 'a', &linked_font, &glyph_index);
3844     if (!pgi)
3845         for(c = firstChar; c < firstChar+count; c++) {
3846             WineEngGetGlyphOutline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
3847                                    &gm, 0, NULL, NULL);
3848             buffer[c - firstChar].abcA = linked_font->gm[c].lsb;
3849             buffer[c - firstChar].abcB = linked_font->gm[c].bbx;
3850             buffer[c - firstChar].abcC = linked_font->gm[c].adv - linked_font->gm[c].lsb 
3851                - linked_font->gm[c].bbx;
3852         }
3853     else
3854         for(c = 0; c < count; c++) {
3855             WineEngGetGlyphOutline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
3856                                    &gm, 0, NULL, NULL);
3857             buffer[c].abcA = linked_font->gm[pgi[c]].lsb;
3858             buffer[c].abcB = linked_font->gm[pgi[c]].bbx;
3859             buffer[c].abcC = linked_font->gm[pgi[c]].adv 
3860                - linked_font->gm[pgi[c]].lsb - linked_font->gm[pgi[c]].bbx;
3861         }
3862
3863     return TRUE;
3864 }
3865
3866 /*************************************************************
3867  * WineEngGetTextExtentExPoint
3868  *
3869  */
3870 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
3871                                  INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
3872 {
3873     INT idx;
3874     INT nfit = 0, ext;
3875     GLYPHMETRICS gm;
3876     TEXTMETRICW tm;
3877     FT_UInt glyph_index;
3878     GdiFont *linked_font;
3879
3880     TRACE("%p, %s, %d, %d, %p\n", font, debugstr_wn(wstr, count), count,
3881           max_ext, size);
3882
3883     size->cx = 0;
3884     WineEngGetTextMetrics(font, &tm);
3885     size->cy = tm.tmHeight;
3886
3887     for(idx = 0; idx < count; idx++) {
3888         get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
3889         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
3890                                &gm, 0, NULL, NULL);
3891         size->cx += linked_font->gm[glyph_index].adv;
3892         ext = size->cx;
3893         if (! pnfit || ext <= max_ext) {
3894             ++nfit;
3895             if (dxs)
3896                 dxs[idx] = ext;
3897         }
3898     }
3899
3900     if (pnfit)
3901         *pnfit = nfit;
3902
3903     TRACE("return %ld, %ld, %d\n", size->cx, size->cy, nfit);
3904     return TRUE;
3905 }
3906
3907 /*************************************************************
3908  * WineEngGetTextExtentPointI
3909  *
3910  */
3911 BOOL WineEngGetTextExtentPointI(GdiFont *font, const WORD *indices, INT count,
3912                                 LPSIZE size)
3913 {
3914     INT idx;
3915     GLYPHMETRICS gm;
3916     TEXTMETRICW tm;
3917
3918     TRACE("%p, %p, %d, %p\n", font, indices, count, size);
3919
3920     size->cx = 0;
3921     WineEngGetTextMetrics(font, &tm);
3922     size->cy = tm.tmHeight;
3923
3924     for(idx = 0; idx < count; idx++) {
3925         WineEngGetGlyphOutline(font, indices[idx],
3926                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
3927                                NULL);
3928         size->cx += font->gm[indices[idx]].adv;
3929     }
3930     TRACE("return %ld,%ld\n", size->cx, size->cy);
3931     return TRUE;
3932 }
3933
3934 /*************************************************************
3935  * WineEngGetFontData
3936  *
3937  */
3938 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
3939                          DWORD cbData)
3940 {
3941     FT_Face ft_face = font->ft_face;
3942     FT_ULong len;
3943     FT_Error err;
3944
3945     TRACE("font=%p, table=%08lx, offset=%08lx, buf=%p, cbData=%lx\n",
3946         font, table, offset, buf, cbData);
3947
3948     if(!FT_IS_SFNT(ft_face))
3949         return GDI_ERROR;
3950
3951     if(!buf || !cbData)
3952         len = 0;
3953     else
3954         len = cbData;
3955
3956     if(table) { /* MS tags differ in endidness from FT ones */
3957         table = table >> 24 | table << 24 |
3958           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
3959     }
3960
3961     /* If the FT_Load_Sfnt_Table function is there we'll use it */
3962     if(pFT_Load_Sfnt_Table) {
3963         /* make sure value of len is the value freetype says it needs */ 
3964         if( buf && len) {
3965             FT_ULong needed = 0;
3966             err = pFT_Load_Sfnt_Table(ft_face, table, offset, NULL, &needed);
3967             if( !err && needed < len) len = needed;
3968         }
3969         err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, &len);
3970     }
3971 #ifdef HAVE_FREETYPE_INTERNAL_SFNT_H
3972     else { /* Do it the hard way */
3973         TT_Face tt_face = (TT_Face) ft_face;
3974         SFNT_Interface *sfnt;
3975         if (FT_Version.major==2 && FT_Version.minor==0)
3976         {
3977             /* 2.0.x */
3978             sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
3979         }
3980         else
3981         {
3982             /* A field was added in the middle of the structure in 2.1.x */
3983             sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
3984         }
3985         /* make sure value of len is the value freetype says it needs */ 
3986         if( buf && len) {
3987             FT_ULong needed = 0;
3988             err = sfnt->load_any(tt_face, table, offset, NULL, &needed);
3989             if( !err && needed < len) len = needed;
3990         }
3991         err = sfnt->load_any(tt_face, table, offset, buf, &len);
3992     }
3993 #else
3994     else {
3995         static int msg;
3996         if(!msg) {
3997             MESSAGE("This version of Wine was compiled with freetype headers later than 2.2.0\n"
3998                     "but is being run with a freetype library without the FT_Load_Sfnt_Table function.\n"
3999                     "Please upgrade your freetype library.\n");
4000             msg++;
4001         }
4002         err = FT_Err_Unimplemented_Feature;
4003     }
4004 #endif
4005     if(err) {
4006         TRACE("Can't find table %08lx.\n", table);
4007         return GDI_ERROR;
4008     }
4009     return len;
4010 }
4011
4012 /*************************************************************
4013  * WineEngGetTextFace
4014  *
4015  */
4016 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
4017 {
4018     if(str) {
4019         lstrcpynW(str, font->name, count);
4020         return strlenW(font->name);
4021     } else
4022         return strlenW(font->name) + 1;
4023 }
4024
4025 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
4026 {
4027     if (fs) memcpy(fs, &font->fs, sizeof(FONTSIGNATURE));
4028     return font->charset;
4029 }
4030
4031 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
4032 {
4033     GdiFont *font = dc->gdiFont, *linked_font;
4034     struct list *first_hfont;
4035     BOOL ret;
4036
4037     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
4038     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
4039     if(font == linked_font)
4040         *new_hfont = dc->hFont;
4041     else
4042     {
4043         first_hfont = list_head(&linked_font->hfontlist);
4044         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
4045     }
4046
4047     return ret;
4048 }
4049     
4050
4051 /*************************************************************
4052  *     FontIsLinked
4053  */
4054 BOOL WINAPI FontIsLinked(HDC hdc)
4055 {
4056     DC *dc = DC_GetDCPtr(hdc);
4057     BOOL ret = FALSE;
4058
4059     if(!dc) return FALSE;
4060     if(dc->gdiFont && !list_empty(&dc->gdiFont->child_fonts))
4061         ret = TRUE;
4062     GDI_ReleaseObj(hdc);
4063     TRACE("returning %d\n", ret);
4064     return ret;
4065 }
4066
4067 static BOOL is_hinting_enabled(void)
4068 {
4069     /* Use the >= 2.2.0 function if available */
4070     if(pFT_Get_TrueType_Engine_Type)
4071     {
4072         FT_TrueTypeEngineType type = pFT_Get_TrueType_Engine_Type(library);
4073         return type == FT_TRUETYPE_ENGINE_TYPE_PATENTED;
4074     }
4075 #ifdef FT_DRIVER_HAS_HINTER
4076     else
4077     {
4078         FT_Module mod;
4079
4080         /* otherwise if we've been compiled with < 2.2.0 headers 
4081            use the internal macro */
4082         mod = pFT_Get_Module(library, "truetype");
4083         if(mod && FT_DRIVER_HAS_HINTER(mod))
4084             return TRUE;
4085     }
4086 #endif
4087
4088     return FALSE;
4089 }
4090
4091 /*************************************************************************
4092  *             GetRasterizerCaps   (GDI32.@)
4093  */
4094 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
4095 {
4096     static int hinting = -1;
4097
4098     if(hinting == -1)
4099         hinting = is_hinting_enabled();
4100
4101     lprs->nSize = sizeof(RASTERIZER_STATUS);
4102     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
4103     lprs->nLanguageID = 0;
4104     return TRUE;
4105 }
4106
4107 /*************************************************************************
4108  * Kerning support for TrueType fonts
4109  */
4110 #define MS_KERN_TAG MS_MAKE_TAG('k', 'e', 'r', 'n')
4111
4112 struct TT_kern_table
4113 {
4114     USHORT version;
4115     USHORT nTables;
4116 };
4117
4118 struct TT_kern_subtable
4119 {
4120     USHORT version;
4121     USHORT length;
4122     union
4123     {
4124         USHORT word;
4125         struct
4126         {
4127             USHORT horizontal : 1;
4128             USHORT minimum : 1;
4129             USHORT cross_stream: 1;
4130             USHORT override : 1;
4131             USHORT reserved1 : 4;
4132             USHORT format : 8;
4133         } bits;
4134     } coverage;
4135 };
4136
4137 struct TT_format0_kern_subtable
4138 {
4139     USHORT nPairs;
4140     USHORT searchRange;
4141     USHORT entrySelector;
4142     USHORT rangeShift;
4143 };
4144
4145 struct TT_kern_pair
4146 {
4147     USHORT left;
4148     USHORT right;
4149     short  value;
4150 };
4151
4152 static DWORD parse_format0_kern_subtable(GdiFont *font,
4153                                          const struct TT_format0_kern_subtable *tt_f0_ks,
4154                                          const USHORT *glyph_to_char,
4155                                          KERNINGPAIR *kern_pair, DWORD cPairs)
4156 {
4157     USHORT i, nPairs;
4158     const struct TT_kern_pair *tt_kern_pair;
4159
4160     TRACE("font height %ld, units_per_EM %d\n", font->ppem, font->ft_face->units_per_EM);
4161
4162     nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
4163
4164     TRACE("nPairs %u, searchRange %u, entrySelector %u, rangeShift %u\n",
4165            nPairs, GET_BE_WORD(tt_f0_ks->searchRange),
4166            GET_BE_WORD(tt_f0_ks->entrySelector), GET_BE_WORD(tt_f0_ks->rangeShift));
4167
4168     if (!kern_pair || !cPairs)
4169         return nPairs;
4170
4171     tt_kern_pair = (const struct TT_kern_pair *)(tt_f0_ks + 1);
4172
4173     nPairs = min(nPairs, cPairs);
4174
4175     for (i = 0; i < nPairs; i++)
4176     {
4177         kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
4178         kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
4179         /* this algorithm appears to better match what Windows does */
4180         kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
4181         if (kern_pair->iKernAmount < 0)
4182         {
4183             kern_pair->iKernAmount -= font->ft_face->units_per_EM / 2;
4184             kern_pair->iKernAmount -= font->ppem;
4185         }
4186         else if (kern_pair->iKernAmount > 0)
4187         {
4188             kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
4189             kern_pair->iKernAmount += font->ppem;
4190         }
4191         kern_pair->iKernAmount /= font->ft_face->units_per_EM;
4192
4193         TRACE("left %u right %u value %d\n",
4194                kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
4195
4196         kern_pair++;
4197     }
4198     TRACE("copied %u entries\n", nPairs);
4199     return nPairs;
4200 }
4201
4202 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
4203 {
4204     DWORD length;
4205     void *buf;
4206     const struct TT_kern_table *tt_kern_table;
4207     const struct TT_kern_subtable *tt_kern_subtable;
4208     USHORT i, nTables;
4209     USHORT *glyph_to_char;
4210
4211     if (font->total_kern_pairs != (DWORD)-1)
4212     {
4213         if (cPairs && kern_pair)
4214         {
4215             cPairs = min(cPairs, font->total_kern_pairs);
4216             memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
4217             return cPairs;
4218         }
4219         return font->total_kern_pairs;
4220     }
4221
4222     font->total_kern_pairs = 0;
4223
4224     length = WineEngGetFontData(font, MS_KERN_TAG, 0, NULL, 0);
4225
4226     if (length == GDI_ERROR)
4227     {
4228         TRACE("no kerning data in the font\n");
4229         return 0;
4230     }
4231
4232     buf = HeapAlloc(GetProcessHeap(), 0, length);
4233     if (!buf)
4234     {
4235         WARN("Out of memory\n");
4236         return 0;
4237     }
4238
4239     WineEngGetFontData(font, MS_KERN_TAG, 0, buf, length);
4240
4241     /* build a glyph index to char code map */
4242     glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
4243     if (!glyph_to_char)
4244     {
4245         WARN("Out of memory allocating a glyph index to char code map\n");
4246         HeapFree(GetProcessHeap(), 0, buf);
4247         return 0;
4248     }
4249
4250     if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
4251     {
4252         FT_UInt glyph_code;
4253         FT_ULong char_code;
4254
4255         glyph_code = 0;
4256         char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
4257
4258         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
4259                font->ft_face->num_glyphs, glyph_code, char_code);
4260
4261         while (glyph_code)
4262         {
4263             /*TRACE("Char %04lX -> Index %u%s\n", char_code, glyph_code, glyph_to_char[glyph_code] ? "  !" : "" );*/
4264
4265             /* FIXME: This doesn't match what Windows does: it does some fancy
4266              * things with duplicate glyph index to char code mappings, while
4267              * we just avoid overriding existing entries.
4268              */
4269             if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
4270                 glyph_to_char[glyph_code] = (USHORT)char_code;
4271
4272             char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
4273         }
4274     }
4275     else
4276     {
4277         ULONG n;
4278
4279         FIXME("encoding %u not supported\n", font->ft_face->charmap->encoding);
4280         for (n = 0; n <= 65535; n++)
4281             glyph_to_char[n] = (USHORT)n;
4282     }
4283
4284     tt_kern_table = buf;
4285     nTables = GET_BE_WORD(tt_kern_table->nTables);
4286     TRACE("version %u, nTables %u\n",
4287            GET_BE_WORD(tt_kern_table->version), nTables);
4288
4289     tt_kern_subtable = (const struct TT_kern_subtable *)(tt_kern_table + 1);
4290
4291     for (i = 0; i < nTables; i++)
4292     {
4293         struct TT_kern_subtable tt_kern_subtable_copy;
4294
4295         tt_kern_subtable_copy.version = GET_BE_WORD(tt_kern_subtable->version);
4296         tt_kern_subtable_copy.length = GET_BE_WORD(tt_kern_subtable->length);
4297         tt_kern_subtable_copy.coverage.word = GET_BE_WORD(tt_kern_subtable->coverage.word);
4298
4299         TRACE("version %u, length %u, coverage %u, subtable format %u\n",
4300                tt_kern_subtable_copy.version, tt_kern_subtable_copy.length,
4301                tt_kern_subtable_copy.coverage.word, tt_kern_subtable_copy.coverage.bits.format);
4302
4303         /* According to the TrueType specification this is the only format
4304          * that will be properly interpreted by Windows and OS/2
4305          */
4306         if (tt_kern_subtable_copy.coverage.bits.format == 0)
4307         {
4308             DWORD new_chunk, old_total = font->total_kern_pairs;
4309
4310             new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
4311                                                     glyph_to_char, NULL, 0);
4312             font->total_kern_pairs += new_chunk;
4313
4314             if (!font->kern_pairs)
4315                 font->kern_pairs = HeapAlloc(GetProcessHeap(), 0,
4316                                              font->total_kern_pairs * sizeof(*font->kern_pairs));
4317             else
4318                 font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs,
4319                                                font->total_kern_pairs * sizeof(*font->kern_pairs));
4320
4321             parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
4322                         glyph_to_char, font->kern_pairs + old_total, new_chunk);
4323         }
4324         else
4325             TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format);
4326
4327         tt_kern_subtable = (const struct TT_kern_subtable *)((const char *)tt_kern_subtable + tt_kern_subtable_copy.length);
4328     }
4329
4330     HeapFree(GetProcessHeap(), 0, glyph_to_char);
4331     HeapFree(GetProcessHeap(), 0, buf);
4332
4333     if (cPairs && kern_pair)
4334     {
4335         cPairs = min(cPairs, font->total_kern_pairs);
4336         memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
4337         return cPairs;
4338     }
4339     return font->total_kern_pairs;
4340 }
4341
4342 #else /* HAVE_FREETYPE */
4343
4344 /*************************************************************************/
4345
4346 BOOL WineEngInit(void)
4347 {
4348     return FALSE;
4349 }
4350 GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont)
4351 {
4352     return NULL;
4353 }
4354 BOOL WineEngDestroyFontInstance(HFONT hfont)
4355 {
4356     return FALSE;
4357 }
4358
4359 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
4360 {
4361     return 1;
4362 }
4363
4364 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
4365                                 LPWORD pgi, DWORD flags)
4366 {
4367     return GDI_ERROR;
4368 }
4369
4370 DWORD WineEngGetGlyphOutline(GdiFont *font, UINT glyph, UINT format,
4371                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
4372                              const MAT2* lpmat)
4373 {
4374     ERR("called but we don't have FreeType\n");
4375     return GDI_ERROR;
4376 }
4377
4378 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
4379 {
4380     ERR("called but we don't have FreeType\n");
4381     return FALSE;
4382 }
4383
4384 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
4385                                   OUTLINETEXTMETRICW *potm)
4386 {
4387     ERR("called but we don't have FreeType\n");
4388     return 0;
4389 }
4390
4391 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
4392                          LPINT buffer)
4393 {
4394     ERR("called but we don't have FreeType\n");
4395     return FALSE;
4396 }
4397
4398 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
4399                              LPABC buffer)
4400 {
4401     ERR("called but we don't have FreeType\n");
4402     return FALSE;
4403 }
4404
4405 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
4406                               LPABC buffer)
4407 {
4408     ERR("called but we don't have FreeType\n");
4409     return FALSE;
4410 }
4411
4412 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
4413                                  INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
4414 {
4415     ERR("called but we don't have FreeType\n");
4416     return FALSE;
4417 }
4418
4419 BOOL WineEngGetTextExtentPointI(GdiFont *font, const WORD *indices, INT count,
4420                                 LPSIZE size)
4421 {
4422     ERR("called but we don't have FreeType\n");
4423     return FALSE;
4424 }
4425
4426 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
4427                          DWORD cbData)
4428 {
4429     ERR("called but we don't have FreeType\n");
4430     return GDI_ERROR;
4431 }
4432
4433 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
4434 {
4435     ERR("called but we don't have FreeType\n");
4436     return 0;
4437 }
4438
4439 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
4440 {
4441     FIXME(":stub\n");
4442     return 1;
4443 }
4444
4445 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
4446 {
4447     FIXME(":stub\n");
4448     return TRUE;
4449 }
4450
4451 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
4452 {
4453     FIXME(":stub\n");
4454     return DEFAULT_CHARSET;
4455 }
4456
4457 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
4458 {
4459     return FALSE;
4460 }
4461
4462 BOOL WINAPI FontIsLinked(HDC hdc)
4463 {
4464     return FALSE;
4465 }
4466
4467 /*************************************************************************
4468  *             GetRasterizerCaps   (GDI32.@)
4469  */
4470 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
4471 {
4472     lprs->nSize = sizeof(RASTERIZER_STATUS);
4473     lprs->wFlags = 0;
4474     lprs->nLanguageID = 0;
4475     return TRUE;
4476 }
4477
4478 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
4479 {
4480     ERR("called but we don't have FreeType\n");
4481     return 0;
4482 }
4483
4484 #endif /* HAVE_FREETYPE */