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