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