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