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