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