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