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