gdiplus: Stub GdipCloneImage.
[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 XFORM *pxf, 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     memcpy(&fd.matrix, pxf, sizeof(FMAT2));
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     FontSubst *psub = NULL;
3244
3245     EnterCriticalSection( &freetype_cs );
3246
3247     LIST_FOR_EACH_ENTRY(ret, &child_font_list, struct tagGdiFont, entry)
3248     {
3249         struct list *first_hfont = list_head(&ret->hfontlist);
3250         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
3251         if(hflist->hfont == hfont)
3252         {
3253             LeaveCriticalSection( &freetype_cs );
3254             return ret;
3255         }
3256     }
3257
3258     if (!GetObjectW( hfont, sizeof(lf), &lf ))
3259     {
3260         LeaveCriticalSection( &freetype_cs );
3261         return NULL;
3262     }
3263     lf.lfWidth = abs(lf.lfWidth);
3264
3265     can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
3266
3267     TRACE("%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n",
3268           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
3269           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
3270           lf.lfEscapement);
3271
3272     TRACE("DC transform %f %f %f %f %f %f\n",
3273           dc->xformWorld2Vport.eM11, dc->xformWorld2Vport.eM12,
3274           dc->xformWorld2Vport.eM21, dc->xformWorld2Vport.eM22,
3275           dc->xformWorld2Vport.eDx, dc->xformWorld2Vport.eDy);
3276
3277     /* check the cache first */
3278     if((ret = find_in_cache(hfont, &lf, &dc->xformWorld2Vport, can_use_bitmap)) != NULL) {
3279         TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
3280         LeaveCriticalSection( &freetype_cs );
3281         return ret;
3282     }
3283
3284     TRACE("not in cache\n");
3285     if(list_empty(&font_list)) /* No fonts installed */
3286     {
3287         TRACE("No fonts installed\n");
3288         LeaveCriticalSection( &freetype_cs );
3289         return NULL;
3290     }
3291     if(!have_installed_roman_font)
3292     {
3293         TRACE("No roman font installed\n");
3294         LeaveCriticalSection( &freetype_cs );
3295         return NULL;
3296     }
3297
3298     ret = alloc_font();
3299
3300     memcpy(&ret->font_desc.matrix, &dc->xformWorld2Vport, sizeof(FMAT2));
3301     ret->font_desc.lf = lf;
3302     ret->font_desc.can_use_bitmap = can_use_bitmap;
3303     calc_hash(&ret->font_desc);
3304     hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3305     hflist->hfont = hfont;
3306     list_add_head(&ret->hfontlist, &hflist->entry);
3307
3308     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
3309        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
3310        original value lfCharSet.  Note this is a special case for
3311        Symbol and doesn't happen at least for "Wingdings*" */
3312
3313     if(!strcmpiW(lf.lfFaceName, SymbolW))
3314         lf.lfCharSet = SYMBOL_CHARSET;
3315
3316     if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
3317         switch(lf.lfCharSet) {
3318         case DEFAULT_CHARSET:
3319             csi.fs.fsCsb[0] = 0;
3320             break;
3321         default:
3322             FIXME("Untranslated charset %d\n", lf.lfCharSet);
3323             csi.fs.fsCsb[0] = 0;
3324             break;
3325         }
3326     }
3327
3328     family = NULL;
3329     if(lf.lfFaceName[0] != '\0') {
3330         SYSTEM_LINKS *font_link;
3331         CHILD_FONT *font_link_entry;
3332         LPWSTR FaceName = lf.lfFaceName;
3333
3334         /*
3335          * Check for a leading '@' this signals that the font is being
3336          * requested in tategaki mode (vertical writing substitution) but
3337          * does not affect the fontface that is to be selected.
3338          */
3339         if (lf.lfFaceName[0]=='@')
3340             FaceName = &lf.lfFaceName[1];
3341
3342         psub = get_font_subst(&font_subst_list, FaceName, lf.lfCharSet);
3343
3344         if(psub) {
3345             TRACE("substituting %s,%d -> %s,%d\n", debugstr_w(FaceName), lf.lfCharSet,
3346                   debugstr_w(psub->to.name), (psub->to.charset != -1) ? psub->to.charset : lf.lfCharSet);
3347             if (psub->to.charset != -1)
3348                 lf.lfCharSet = psub->to.charset;
3349         }
3350
3351         /* We want a match on name and charset or just name if
3352            charset was DEFAULT_CHARSET.  If the latter then
3353            we fixup the returned charset later in get_nearest_charset
3354            where we'll either use the charset of the current ansi codepage
3355            or if that's unavailable the first charset that the font supports.
3356         */
3357         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3358             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3359             if (!strcmpiW(family->FamilyName, FaceName) ||
3360                 (psub && !strcmpiW(family->FamilyName, psub->to.name)))
3361             {
3362                 LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3363                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
3364                     if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
3365                         if(face->scalable || can_use_bitmap)
3366                             goto found;
3367                 }
3368             }
3369         }
3370
3371         /*
3372          * Try check the SystemLink list first for a replacement font.
3373          * We may find good replacements there.
3374          */
3375         LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3376         {
3377             if(!strcmpiW(font_link->font_name, FaceName))
3378             {
3379                 TRACE("found entry in system list\n");
3380                 LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3381                 {
3382                     face = font_link_entry->face;
3383                     family = face->family;
3384                     if(csi.fs.fsCsb[0] &
3385                         (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]) || !csi.fs.fsCsb[0])
3386                     {
3387                         if(face->scalable || can_use_bitmap)
3388                             goto found;
3389                     }
3390                 }
3391             }
3392         }
3393     }
3394
3395     psub = NULL; /* substitution is no more relevant */
3396
3397     /* If requested charset was DEFAULT_CHARSET then try using charset
3398        corresponding to the current ansi codepage */
3399     if (!csi.fs.fsCsb[0] || lf.lfWeight == FW_DONTCARE)
3400     {
3401         INT acp = GetACP();
3402         if(!TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE)) {
3403             FIXME("TCI failed on codepage %d\n", acp);
3404             csi.fs.fsCsb[0] = 0;
3405         } else
3406             lf.lfCharSet = csi.ciCharset;
3407     }
3408
3409     /* Face families are in the top 4 bits of lfPitchAndFamily,
3410        so mask with 0xF0 before testing */
3411
3412     if((lf.lfPitchAndFamily & FIXED_PITCH) ||
3413        (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
3414         strcpyW(lf.lfFaceName, defFixed);
3415     else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
3416         strcpyW(lf.lfFaceName, defSerif);
3417     else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
3418         strcpyW(lf.lfFaceName, defSans);
3419     else
3420         strcpyW(lf.lfFaceName, defSans);
3421     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3422         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3423         if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
3424             LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3425                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
3426                 if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
3427                     if(face->scalable || can_use_bitmap)
3428                         goto found;
3429             }
3430         }
3431     }
3432
3433     last_resort_family = NULL;
3434     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3435         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3436         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3437             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3438             if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) {
3439                 if(face->scalable)
3440                     goto found;
3441                 if(can_use_bitmap && !last_resort_family)
3442                     last_resort_family = family;
3443             }            
3444         }
3445     }
3446
3447     if(last_resort_family) {
3448         family = last_resort_family;
3449         csi.fs.fsCsb[0] = 0;
3450         goto found;
3451     }
3452
3453     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3454         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3455         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3456             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3457             if(face->scalable) {
3458                 csi.fs.fsCsb[0] = 0;
3459                 WARN("just using first face for now\n");
3460                 goto found;
3461             }
3462             if(can_use_bitmap && !last_resort_family)
3463                 last_resort_family = family;
3464         }
3465     }
3466     if(!last_resort_family) {
3467         FIXME("can't find a single appropriate font - bailing\n");
3468         free_font(ret);
3469         LeaveCriticalSection( &freetype_cs );
3470         return NULL;
3471     }
3472
3473     WARN("could only find a bitmap font - this will probably look awful!\n");
3474     family = last_resort_family;
3475     csi.fs.fsCsb[0] = 0;
3476
3477 found:
3478     it = lf.lfItalic ? 1 : 0;
3479     bd = lf.lfWeight > 550 ? 1 : 0;
3480
3481     height = lf.lfHeight;
3482
3483     face = best = best_bitmap = NULL;
3484     LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
3485     {
3486         if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
3487         {
3488             BOOL italic, bold;
3489
3490             italic = (face->ntmFlags & NTM_ITALIC) ? 1 : 0;
3491             bold = (face->ntmFlags & NTM_BOLD) ? 1 : 0;
3492             new_score = (italic ^ it) + (bold ^ bd);
3493             if(!best || new_score <= score)
3494             {
3495                 TRACE("(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n",
3496                       italic, bold, it, bd);
3497                 score = new_score;
3498                 best = face;
3499                 if(best->scalable  && score == 0) break;
3500                 if(!best->scalable)
3501                 {
3502                     if(height > 0)
3503                         newdiff = height - (signed int)(best->size.height);
3504                     else
3505                         newdiff = -height - ((signed int)(best->size.height) - best->size.internal_leading);
3506                     if(!best_bitmap || new_score < score ||
3507                        (diff > 0 && newdiff < diff && newdiff >= 0) || (diff < 0 && newdiff > diff))
3508                     {
3509                         TRACE("%d is better for %d diff was %d\n", best->size.height, height, diff);
3510                         diff = newdiff;
3511                         best_bitmap = best;
3512                         if(score == 0 && diff == 0) break;
3513                     }
3514                 }
3515             }
3516         }
3517     }
3518     if(best)
3519         face = best->scalable ? best : best_bitmap;
3520     ret->fake_italic = (it && !(face->ntmFlags & NTM_ITALIC));
3521     ret->fake_bold = (bd && !(face->ntmFlags & NTM_BOLD));
3522
3523     ret->fs = face->fs;
3524
3525     if(csi.fs.fsCsb[0]) {
3526         ret->charset = lf.lfCharSet;
3527         ret->codepage = csi.ciACP;
3528     }
3529     else
3530         ret->charset = get_nearest_charset(face, &ret->codepage);
3531
3532     TRACE("Chosen: %s %s (%s/%p:%ld)\n", debugstr_w(family->FamilyName),
3533           debugstr_w(face->StyleName), face->file, face->font_data_ptr, face->face_index);
3534
3535     ret->aveWidth = height ? lf.lfWidth : 0;
3536
3537     if(!face->scalable) {
3538         /* Windows uses integer scaling factors for bitmap fonts */
3539         INT scale, scaled_height;
3540
3541         if (height != 0) height = diff;
3542         height += face->size.height;
3543
3544         scale = (height + face->size.height - 1) / face->size.height;
3545         scaled_height = scale * face->size.height;
3546         /* XP allows not more than 10% deviation */
3547         if (scale > 1 && scaled_height - height > scaled_height / 10) scale--;
3548         ret->scale_y = scale;
3549
3550         width = face->size.x_ppem >> 6;
3551         height = face->size.y_ppem >> 6;
3552     }
3553     else
3554         ret->scale_y = 1.0;
3555     TRACE("font scale y: %f\n", ret->scale_y);
3556
3557     ret->ft_face = OpenFontFace(ret, face, width, height);
3558
3559     if (!ret->ft_face)
3560     {
3561         free_font( ret );
3562         LeaveCriticalSection( &freetype_cs );
3563         return 0;
3564     }
3565
3566     ret->ntmFlags = face->ntmFlags;
3567
3568     if (ret->charset == SYMBOL_CHARSET && 
3569         select_charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) {
3570         /* No ops */
3571     }
3572     else if (select_charmap(ret->ft_face, FT_ENCODING_UNICODE)) {
3573         /* No ops */
3574     }
3575     else {
3576         select_charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN);
3577     }
3578
3579     ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0;
3580     ret->name = psub ? strdupW(psub->from.name) : strdupW(family->FamilyName);
3581     ret->underline = lf.lfUnderline ? 0xff : 0;
3582     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
3583     create_child_font_list(ret);
3584
3585     if (lf.lfFaceName[0]=='@') /* We need to try to load the GSUB table */
3586     {
3587         int length = WineEngGetFontData (ret, GSUB_TAG , 0, NULL, 0);
3588         if (length != GDI_ERROR)
3589         {
3590             ret->GSUB_Table = HeapAlloc(GetProcessHeap(),0,length);
3591             WineEngGetFontData(ret, GSUB_TAG , 0, ret->GSUB_Table, length);
3592             TRACE("Loaded GSUB table of %i bytes\n",length);
3593         }
3594     }
3595
3596     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
3597
3598     list_add_head(&gdi_font_list, &ret->entry);
3599     LeaveCriticalSection( &freetype_cs );
3600     return ret;
3601 }
3602
3603 static void dump_gdi_font_list(void)
3604 {
3605     GdiFont *gdiFont;
3606     struct list *elem_ptr;
3607
3608     TRACE("---------- gdiFont Cache ----------\n");
3609     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
3610         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
3611         TRACE("gdiFont=%p %s %d\n",
3612               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
3613     }
3614
3615     TRACE("---------- Unused gdiFont Cache ----------\n");
3616     LIST_FOR_EACH(elem_ptr, &unused_gdi_font_list) {
3617         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
3618         TRACE("gdiFont=%p %s %d\n",
3619               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
3620     }
3621 }
3622
3623 /*************************************************************
3624  * WineEngDestroyFontInstance
3625  *
3626  * free the gdiFont associated with this handle
3627  *
3628  */
3629 BOOL WineEngDestroyFontInstance(HFONT handle)
3630 {
3631     GdiFont *gdiFont;
3632     HFONTLIST *hflist;
3633     BOOL ret = FALSE;
3634     struct list *font_elem_ptr, *hfontlist_elem_ptr;
3635     int i = 0;
3636
3637     EnterCriticalSection( &freetype_cs );
3638
3639     LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry)
3640     {
3641         struct list *first_hfont = list_head(&gdiFont->hfontlist);
3642         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
3643         if(hflist->hfont == handle)
3644         {
3645             TRACE("removing child font %p from child list\n", gdiFont);
3646             list_remove(&gdiFont->entry);
3647             LeaveCriticalSection( &freetype_cs );
3648             return TRUE;
3649         }
3650     }
3651
3652     TRACE("destroying hfont=%p\n", handle);
3653     if(TRACE_ON(font))
3654         dump_gdi_font_list();
3655
3656     font_elem_ptr = list_head(&gdi_font_list);
3657     while(font_elem_ptr) {
3658         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3659         font_elem_ptr = list_next(&gdi_font_list, font_elem_ptr);
3660
3661         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
3662         while(hfontlist_elem_ptr) {
3663             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3664             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
3665             if(hflist->hfont == handle) {
3666                 list_remove(&hflist->entry);
3667                 HeapFree(GetProcessHeap(), 0, hflist);
3668                 ret = TRUE;
3669             }
3670         }
3671         if(list_empty(&gdiFont->hfontlist)) {
3672             TRACE("Moving to Unused list\n");
3673             list_remove(&gdiFont->entry);
3674             list_add_head(&unused_gdi_font_list, &gdiFont->entry);
3675         }
3676     }
3677
3678
3679     font_elem_ptr = list_head(&unused_gdi_font_list);
3680     while(font_elem_ptr && i++ < UNUSED_CACHE_SIZE)
3681         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
3682     while(font_elem_ptr) {
3683         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3684         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
3685         TRACE("freeing %p\n", gdiFont);
3686         list_remove(&gdiFont->entry);
3687         free_font(gdiFont);
3688     }
3689     LeaveCriticalSection( &freetype_cs );
3690     return ret;
3691 }
3692
3693 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
3694                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
3695 {
3696     GdiFont *font;
3697     LONG width, height;
3698
3699     if (face->cached_enum_data)
3700     {
3701         TRACE("Cached\n");
3702         *pelf = face->cached_enum_data->elf;
3703         *pntm = face->cached_enum_data->ntm;
3704         *ptype = face->cached_enum_data->type;
3705         return;
3706     }
3707
3708     font = alloc_font();
3709
3710     if(face->scalable) {
3711         height = -2048; /* 2048 is the most common em size */
3712         width = 0;
3713     } else {
3714         height = face->size.y_ppem >> 6;
3715         width = face->size.x_ppem >> 6;
3716     }
3717     font->scale_y = 1.0;
3718     
3719     if (!(font->ft_face = OpenFontFace(font, face, width, height)))
3720     {
3721         free_font(font);
3722         return;
3723     }
3724
3725     font->name = strdupW(face->family->FamilyName);
3726     font->ntmFlags = face->ntmFlags;
3727
3728     if (WineEngGetOutlineTextMetrics(font, 0, NULL))
3729     {
3730         memcpy(&pntm->ntmTm, &font->potm->otmTextMetrics, sizeof(TEXTMETRICW));
3731
3732         pntm->ntmTm.ntmSizeEM = font->potm->otmEMSquare;
3733
3734         lstrcpynW(pelf->elfLogFont.lfFaceName,
3735                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFamilyName),
3736                  LF_FACESIZE);
3737         lstrcpynW(pelf->elfFullName,
3738                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFaceName),
3739                  LF_FULLFACESIZE);
3740         lstrcpynW(pelf->elfStyle,
3741                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpStyleName),
3742                  LF_FACESIZE);
3743     }
3744     else
3745     {
3746         WineEngGetTextMetrics(font, (TEXTMETRICW *)&pntm->ntmTm);
3747
3748         pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
3749
3750         lstrcpynW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
3751         lstrcpynW(pelf->elfFullName, face->family->FamilyName, LF_FULLFACESIZE);
3752         lstrcpynW(pelf->elfStyle, face->StyleName, LF_FACESIZE);
3753     }
3754
3755     pntm->ntmTm.ntmFlags = face->ntmFlags;
3756     pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
3757     pntm->ntmTm.ntmAvgWidth = pntm->ntmTm.tmAveCharWidth;
3758     pntm->ntmFontSig = face->fs;
3759
3760     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
3761
3762     pelf->elfLogFont.lfEscapement = 0;
3763     pelf->elfLogFont.lfOrientation = 0;
3764     pelf->elfLogFont.lfHeight = pntm->ntmTm.tmHeight;
3765     pelf->elfLogFont.lfWidth = pntm->ntmTm.tmAveCharWidth;
3766     pelf->elfLogFont.lfWeight = pntm->ntmTm.tmWeight;
3767     pelf->elfLogFont.lfItalic = pntm->ntmTm.tmItalic;
3768     pelf->elfLogFont.lfUnderline = pntm->ntmTm.tmUnderlined;
3769     pelf->elfLogFont.lfStrikeOut = pntm->ntmTm.tmStruckOut;
3770     pelf->elfLogFont.lfCharSet = pntm->ntmTm.tmCharSet;
3771     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
3772     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
3773     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
3774     pelf->elfLogFont.lfPitchAndFamily = (pntm->ntmTm.tmPitchAndFamily & 0xf1) + 1;
3775
3776     *ptype = 0;
3777     if (pntm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE)
3778         *ptype |= TRUETYPE_FONTTYPE;
3779     if (pntm->ntmTm.tmPitchAndFamily & TMPF_DEVICE)
3780         *ptype |= DEVICE_FONTTYPE;
3781     if(!(pntm->ntmTm.tmPitchAndFamily & TMPF_VECTOR))
3782         *ptype |= RASTER_FONTTYPE;
3783
3784     face->cached_enum_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*face->cached_enum_data));
3785     if (face->cached_enum_data)
3786     {
3787         face->cached_enum_data->elf = *pelf;
3788         face->cached_enum_data->ntm = *pntm;
3789         face->cached_enum_data->type = *ptype;
3790     }
3791
3792     free_font(font);
3793 }
3794
3795 /*************************************************************
3796  * WineEngEnumFonts
3797  *
3798  */
3799 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
3800 {
3801     Family *family;
3802     Face *face;
3803     struct list *family_elem_ptr, *face_elem_ptr;
3804     ENUMLOGFONTEXW elf;
3805     NEWTEXTMETRICEXW ntm;
3806     DWORD type;
3807     FONTSIGNATURE fs;
3808     CHARSETINFO csi;
3809     LOGFONTW lf;
3810     int i;
3811
3812     if (!plf)
3813     {
3814         lf.lfCharSet = DEFAULT_CHARSET;
3815         lf.lfPitchAndFamily = 0;
3816         lf.lfFaceName[0] = 0;
3817         plf = &lf;
3818     }
3819
3820     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
3821
3822     EnterCriticalSection( &freetype_cs );
3823     if(plf->lfFaceName[0]) {
3824         FontSubst *psub;
3825         psub = get_font_subst(&font_subst_list, plf->lfFaceName, plf->lfCharSet);
3826
3827         if(psub) {
3828             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
3829                   debugstr_w(psub->to.name));
3830             lf = *plf;
3831             strcpyW(lf.lfFaceName, psub->to.name);
3832             plf = &lf;
3833         }
3834
3835         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3836             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3837             if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
3838                 LIST_FOR_EACH(face_elem_ptr, &family->faces) {
3839                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
3840                     GetEnumStructs(face, &elf, &ntm, &type);
3841                     for(i = 0; i < 32; i++) {
3842                         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
3843                             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
3844                             strcpyW(elf.elfScript, OEM_DOSW);
3845                             i = 32; /* break out of loop */
3846                         } else if(!(face->fs.fsCsb[0] & (1L << i)))
3847                             continue;
3848                         else {
3849                             fs.fsCsb[0] = 1L << i;
3850                             fs.fsCsb[1] = 0;
3851                             if(!TranslateCharsetInfo(fs.fsCsb, &csi,
3852                                                      TCI_SRCFONTSIG))
3853                                 csi.ciCharset = DEFAULT_CHARSET;
3854                             if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
3855                             if(csi.ciCharset != DEFAULT_CHARSET) {
3856                                 elf.elfLogFont.lfCharSet =
3857                                     ntm.ntmTm.tmCharSet = csi.ciCharset;
3858                                 if(ElfScriptsW[i])
3859                                     strcpyW(elf.elfScript, ElfScriptsW[i]);
3860                                 else
3861                                     FIXME("Unknown elfscript for bit %d\n", i);
3862                             }
3863                         }
3864                         TRACE("enuming face %s full %s style %s charset %d type %d script %s it %d weight %d ntmflags %08x\n",
3865                               debugstr_w(elf.elfLogFont.lfFaceName),
3866                               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
3867                               csi.ciCharset, type, debugstr_w(elf.elfScript),
3868                               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
3869                               ntm.ntmTm.ntmFlags);
3870                         /* release section before callback (FIXME) */
3871                         LeaveCriticalSection( &freetype_cs );
3872                         if (!proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam)) return 0;
3873                         EnterCriticalSection( &freetype_cs );
3874                     }
3875                 }
3876             }
3877         }
3878     } else {
3879         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3880             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3881             face_elem_ptr = list_head(&family->faces);
3882             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3883             GetEnumStructs(face, &elf, &ntm, &type);
3884             for(i = 0; i < 32; i++) {
3885                 if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
3886                     elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
3887                     strcpyW(elf.elfScript, OEM_DOSW);
3888                     i = 32; /* break out of loop */
3889                 } else if(!(face->fs.fsCsb[0] & (1L << i)))
3890                     continue;
3891                 else {
3892                     fs.fsCsb[0] = 1L << i;
3893                     fs.fsCsb[1] = 0;
3894                     if(!TranslateCharsetInfo(fs.fsCsb, &csi,
3895                                              TCI_SRCFONTSIG))
3896                         csi.ciCharset = DEFAULT_CHARSET;
3897                     if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
3898                     if(csi.ciCharset != DEFAULT_CHARSET) {
3899                         elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet =
3900                           csi.ciCharset;
3901                           if(ElfScriptsW[i])
3902                               strcpyW(elf.elfScript, ElfScriptsW[i]);
3903                           else
3904                               FIXME("Unknown elfscript for bit %d\n", i);
3905                     }
3906                 }
3907                 TRACE("enuming face %s full %s style %s charset = %d type %d script %s it %d weight %d ntmflags %08x\n",
3908                       debugstr_w(elf.elfLogFont.lfFaceName),
3909                       debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
3910                       csi.ciCharset, type, debugstr_w(elf.elfScript),
3911                       elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
3912                       ntm.ntmTm.ntmFlags);
3913                 /* release section before callback (FIXME) */
3914                 LeaveCriticalSection( &freetype_cs );
3915                 if (!proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam)) return 0;
3916                 EnterCriticalSection( &freetype_cs );
3917             }
3918         }
3919     }
3920     LeaveCriticalSection( &freetype_cs );
3921     return 1;
3922 }
3923
3924 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
3925 {
3926     pt->x.value = vec->x >> 6;
3927     pt->x.fract = (vec->x & 0x3f) << 10;
3928     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
3929     pt->y.value = vec->y >> 6;
3930     pt->y.fract = (vec->y & 0x3f) << 10;
3931     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
3932     return;
3933 }
3934
3935 /***************************************************
3936  * According to the MSDN documentation on WideCharToMultiByte,
3937  * certain codepages cannot set the default_used parameter.
3938  * This returns TRUE if the codepage can set that parameter, false else
3939  * so that calls to WideCharToMultiByte don't fail with ERROR_INVALID_PARAMETER
3940  */
3941 static BOOL codepage_sets_default_used(UINT codepage)
3942 {
3943    switch (codepage)
3944    {
3945        case CP_UTF7:
3946        case CP_UTF8:
3947        case CP_SYMBOL:
3948            return FALSE;
3949        default:
3950            return TRUE;
3951    }
3952 }
3953
3954 /*
3955  * GSUB Table handling functions
3956  */
3957
3958 static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph)
3959 {
3960     const GSUB_CoverageFormat1* cf1;
3961
3962     cf1 = (GSUB_CoverageFormat1*)table;
3963
3964     if (GET_BE_WORD(cf1->CoverageFormat) == 1)
3965     {
3966         int count = GET_BE_WORD(cf1->GlyphCount);
3967         int i;
3968         TRACE("Coverage Format 1, %i glyphs\n",count);
3969         for (i = 0; i < count; i++)
3970             if (glyph == GET_BE_WORD(cf1->GlyphArray[i]))
3971                 return i;
3972         return -1;
3973     }
3974     else if (GET_BE_WORD(cf1->CoverageFormat) == 2)
3975     {
3976         const GSUB_CoverageFormat2* cf2;
3977         int i;
3978         int count;
3979         cf2 = (GSUB_CoverageFormat2*)cf1;
3980
3981         count = GET_BE_WORD(cf2->RangeCount);
3982         TRACE("Coverage Format 2, %i ranges\n",count);
3983         for (i = 0; i < count; i++)
3984         {
3985             if (glyph < GET_BE_WORD(cf2->RangeRecord[i].Start))
3986                 return -1;
3987             if ((glyph >= GET_BE_WORD(cf2->RangeRecord[i].Start)) &&
3988                 (glyph <= GET_BE_WORD(cf2->RangeRecord[i].End)))
3989             {
3990                 return (GET_BE_WORD(cf2->RangeRecord[i].StartCoverageIndex) +
3991                     glyph - GET_BE_WORD(cf2->RangeRecord[i].Start));
3992             }
3993         }
3994         return -1;
3995     }
3996     else
3997         ERR("Unknown CoverageFormat %i\n",GET_BE_WORD(cf1->CoverageFormat));
3998
3999     return -1;
4000 }
4001
4002 static const GSUB_Script* GSUB_get_script_table( const GSUB_Header* header, const char* tag)
4003 {
4004     const GSUB_ScriptList *script;
4005     const GSUB_Script *deflt = NULL;
4006     int i;
4007     script = (GSUB_ScriptList*)((LPBYTE)header + GET_BE_WORD(header->ScriptList));
4008
4009     TRACE("%i scripts in this font\n",GET_BE_WORD(script->ScriptCount));
4010     for (i = 0; i < GET_BE_WORD(script->ScriptCount); i++)
4011     {
4012         const GSUB_Script *scr;
4013         int offset;
4014
4015         offset = GET_BE_WORD(script->ScriptRecord[i].Script);
4016         scr = (GSUB_Script*)((LPBYTE)script + offset);
4017
4018         if (strncmp(script->ScriptRecord[i].ScriptTag, tag,4)==0)
4019             return scr;
4020         if (strncmp(script->ScriptRecord[i].ScriptTag, "dflt",4)==0)
4021             deflt = scr;
4022     }
4023     return deflt;
4024 }
4025
4026 static const GSUB_LangSys* GSUB_get_lang_table( const GSUB_Script* script, const char* tag)
4027 {
4028     int i;
4029     int offset;
4030     const GSUB_LangSys *Lang;
4031
4032     TRACE("Deflang %x, LangCount %i\n",GET_BE_WORD(script->DefaultLangSys), GET_BE_WORD(script->LangSysCount));
4033
4034     for (i = 0; i < GET_BE_WORD(script->LangSysCount) ; i++)
4035     {
4036         offset = GET_BE_WORD(script->LangSysRecord[i].LangSys);
4037         Lang = (GSUB_LangSys*)((LPBYTE)script + offset);
4038
4039         if ( strncmp(script->LangSysRecord[i].LangSysTag,tag,4)==0)
4040             return Lang;
4041     }
4042     offset = GET_BE_WORD(script->DefaultLangSys);
4043     if (offset)
4044     {
4045         Lang = (GSUB_LangSys*)((LPBYTE)script + offset);
4046         return Lang;
4047     }
4048     return NULL;
4049 }
4050
4051 static const GSUB_Feature * GSUB_get_feature(const GSUB_Header *header, const GSUB_LangSys *lang, const char* tag)
4052 {
4053     int i;
4054     const GSUB_FeatureList *feature;
4055     feature = (GSUB_FeatureList*)((LPBYTE)header + GET_BE_WORD(header->FeatureList));
4056
4057     TRACE("%i features\n",GET_BE_WORD(lang->FeatureCount));
4058     for (i = 0; i < GET_BE_WORD(lang->FeatureCount); i++)
4059     {
4060         int index = GET_BE_WORD(lang->FeatureIndex[i]);
4061         if (strncmp(feature->FeatureRecord[index].FeatureTag,tag,4)==0)
4062         {
4063             const GSUB_Feature *feat;
4064             feat = (GSUB_Feature*)((LPBYTE)feature + GET_BE_WORD(feature->FeatureRecord[index].Feature));
4065             return feat;
4066         }
4067     }
4068     return NULL;
4069 }
4070
4071 static FT_UInt GSUB_apply_feature(const GSUB_Header * header, const GSUB_Feature* feature, UINT glyph)
4072 {
4073     int i;
4074     int offset;
4075     const GSUB_LookupList *lookup;
4076     lookup = (GSUB_LookupList*)((LPBYTE)header + GET_BE_WORD(header->LookupList));
4077
4078     TRACE("%i lookups\n", GET_BE_WORD(feature->LookupCount));
4079     for (i = 0; i < GET_BE_WORD(feature->LookupCount); i++)
4080     {
4081         const GSUB_LookupTable *look;
4082         offset = GET_BE_WORD(lookup->Lookup[GET_BE_WORD(feature->LookupListIndex[i])]);
4083         look = (GSUB_LookupTable*)((LPBYTE)lookup + offset);
4084         TRACE("type %i, flag %x, subtables %i\n",GET_BE_WORD(look->LookupType),GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount));
4085         if (GET_BE_WORD(look->LookupType) != 1)
4086             FIXME("We only handle SubType 1\n");
4087         else
4088         {
4089             int j;
4090
4091             for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
4092             {
4093                 const GSUB_SingleSubstFormat1 *ssf1;
4094                 offset = GET_BE_WORD(look->SubTable[j]);
4095                 ssf1 = (GSUB_SingleSubstFormat1*)((LPBYTE)look+offset);
4096                 if (GET_BE_WORD(ssf1->SubstFormat) == 1)
4097                 {
4098                     int offset = GET_BE_WORD(ssf1->Coverage);
4099                     TRACE("  subtype 1, delta %i\n", GET_BE_WORD(ssf1->DeltaGlyphID));
4100                     if (GSUB_is_glyph_covered((LPBYTE)ssf1+offset, glyph) != -1)
4101                     {
4102                         TRACE("  Glyph 0x%x ->",glyph);
4103                         glyph += GET_BE_WORD(ssf1->DeltaGlyphID);
4104                         TRACE(" 0x%x\n",glyph);
4105                     }
4106                 }
4107                 else
4108                 {
4109                     const GSUB_SingleSubstFormat2 *ssf2;
4110                     INT index;
4111                     INT offset;
4112
4113                     ssf2 = (GSUB_SingleSubstFormat2 *)ssf1;
4114                     offset = GET_BE_WORD(ssf1->Coverage);
4115                     TRACE("  subtype 2,  glyph count %i\n", GET_BE_WORD(ssf2->GlyphCount));
4116                     index = GSUB_is_glyph_covered((LPBYTE)ssf2+offset, glyph);
4117                     TRACE("  Coverage index %i\n",index);
4118                     if (index != -1)
4119                     {
4120                         TRACE("    Glyph is 0x%x ->",glyph);
4121                         glyph = GET_BE_WORD(ssf2->Substitute[index]);
4122                         TRACE("0x%x\n",glyph);
4123                     }
4124                 }
4125             }
4126         }
4127     }
4128     return glyph;
4129 }
4130
4131 static const char* get_opentype_script(const GdiFont *font)
4132 {
4133     /*
4134      * I am not sure if this is the correct way to generate our script tag
4135      */
4136
4137     switch (font->charset)
4138     {
4139         case ANSI_CHARSET: return "latn";
4140         case BALTIC_CHARSET: return "latn"; /* ?? */
4141         case CHINESEBIG5_CHARSET: return "hani";
4142         case EASTEUROPE_CHARSET: return "latn"; /* ?? */
4143         case GB2312_CHARSET: return "hani";
4144         case GREEK_CHARSET: return "grek";
4145         case HANGUL_CHARSET: return "hang";
4146         case RUSSIAN_CHARSET: return "cyrl";
4147         case SHIFTJIS_CHARSET: return "kana";
4148         case TURKISH_CHARSET: return "latn"; /* ?? */
4149         case VIETNAMESE_CHARSET: return "latn";
4150         case JOHAB_CHARSET: return "latn"; /* ?? */
4151         case ARABIC_CHARSET: return "arab";
4152         case HEBREW_CHARSET: return "hebr";
4153         case THAI_CHARSET: return "thai";
4154         default: return "latn";
4155     }
4156 }
4157
4158 static FT_UInt get_GSUB_vert_glyph(const GdiFont *font, UINT glyph)
4159 {
4160     const GSUB_Header *header;
4161     const GSUB_Script *script;
4162     const GSUB_LangSys *language;
4163     const GSUB_Feature *feature;
4164
4165     if (!font->GSUB_Table)
4166         return glyph;
4167
4168     header = font->GSUB_Table;
4169
4170     script = GSUB_get_script_table(header, get_opentype_script(font));
4171     if (!script)
4172     {
4173         TRACE("Script not found\n");
4174         return glyph;
4175     }
4176     language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
4177     if (!language)
4178     {
4179         TRACE("Language not found\n");
4180         return glyph;
4181     }
4182     feature  =  GSUB_get_feature(header, language, "vrt2");
4183     if (!feature)
4184         feature  =  GSUB_get_feature(header, language, "vert");
4185     if (!feature)
4186     {
4187         TRACE("vrt2/vert feature not found\n");
4188         return glyph;
4189     }
4190     return GSUB_apply_feature(header, feature, glyph);
4191 }
4192
4193 static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph)
4194 {
4195     FT_UInt glyphId;
4196
4197     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
4198         WCHAR wc = (WCHAR)glyph;
4199         BOOL default_used;
4200         BOOL *default_used_pointer;
4201         FT_UInt ret;
4202         char buf;
4203         default_used_pointer = NULL;
4204         default_used = FALSE;
4205         if (codepage_sets_default_used(font->codepage))
4206             default_used_pointer = &default_used;
4207         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
4208             ret = 0;
4209         else
4210             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
4211         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
4212         return get_GSUB_vert_glyph(font,ret);
4213     }
4214
4215     if(font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL && glyph < 0x100)
4216         glyph = glyph + 0xf000;
4217     glyphId = pFT_Get_Char_Index(font->ft_face, glyph);
4218     return get_GSUB_vert_glyph(font,glyphId);
4219 }
4220
4221 /*************************************************************
4222  * WineEngGetGlyphIndices
4223  *
4224  */
4225 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
4226                                 LPWORD pgi, DWORD flags)
4227 {
4228     int i;
4229     int default_char = -1;
4230
4231     if  (flags & GGI_MARK_NONEXISTING_GLYPHS) default_char = 0xffff;  /* XP would use 0x1f for bitmap fonts */
4232
4233     for(i = 0; i < count; i++)
4234     {
4235         pgi[i] = get_glyph_index(font, lpstr[i]);
4236         if  (pgi[i] == 0)
4237         {
4238             if (default_char == -1)
4239             {
4240                 if (FT_IS_SFNT(font->ft_face))
4241                 {
4242                     TT_OS2 *pOS2 = pFT_Get_Sfnt_Table(font->ft_face, ft_sfnt_os2);
4243                     default_char = (pOS2->usDefaultChar ? get_glyph_index(font, pOS2->usDefaultChar) : 0);
4244                 }
4245                 else
4246                 {
4247                     TEXTMETRICW textm;
4248                     WineEngGetTextMetrics(font, &textm);
4249                     default_char = textm.tmDefaultChar;
4250                 }
4251             }
4252             pgi[i] = default_char;
4253         }
4254     }
4255     return count;
4256 }
4257
4258 static inline BOOL is_identity_FMAT2(const FMAT2 *matrix)
4259 {
4260     static const FMAT2 identity = { 1.0, 0.0, 0.0, 1.0 };
4261     return !memcmp(matrix, &identity, sizeof(FMAT2));
4262 }
4263
4264 static inline BOOL is_identity_MAT2(const MAT2 *matrix)
4265 {
4266     static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
4267     return !memcmp(matrix, &identity, sizeof(MAT2));
4268 }
4269
4270 /*************************************************************
4271  * WineEngGetGlyphOutline
4272  *
4273  * Behaves in exactly the same way as the win32 api GetGlyphOutline
4274  * except that the first parameter is the HWINEENGFONT of the font in
4275  * question rather than an HDC.
4276  *
4277  */
4278 DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
4279                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
4280                              const MAT2* lpmat)
4281 {
4282     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
4283     FT_Face ft_face = incoming_font->ft_face;
4284     GdiFont *font = incoming_font;
4285     FT_UInt glyph_index;
4286     DWORD width, height, pitch, needed = 0;
4287     FT_Bitmap ft_bitmap;
4288     FT_Error err;
4289     INT left, right, top = 0, bottom = 0, adv, lsb, bbx;
4290     FT_Angle angle = 0;
4291     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
4292     double widthRatio = 1.0;
4293     FT_Matrix transMat = identityMat;
4294     BOOL needsTransform = FALSE;
4295     BOOL tategaki = (font->GSUB_Table != NULL);
4296     UINT original_index;
4297
4298     TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
4299           buflen, buf, lpmat);
4300
4301     TRACE("font transform %f %f %f %f\n",
4302           font->font_desc.matrix.eM11, font->font_desc.matrix.eM12,
4303           font->font_desc.matrix.eM21, font->font_desc.matrix.eM22);
4304
4305     EnterCriticalSection( &freetype_cs );
4306
4307     if(format & GGO_GLYPH_INDEX) {
4308         glyph_index = get_GSUB_vert_glyph(incoming_font,glyph);
4309         original_index = glyph;
4310         format &= ~GGO_GLYPH_INDEX;
4311     } else {
4312         get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index);
4313         ft_face = font->ft_face;
4314         original_index = glyph_index;
4315     }
4316
4317     /* tategaki never appears to happen to lower glyph index */
4318     if (glyph_index < TATEGAKI_LOWER_BOUND )
4319         tategaki = FALSE;
4320
4321     if(original_index >= font->gmsize * GM_BLOCK_SIZE) {
4322         font->gmsize = (original_index / GM_BLOCK_SIZE + 1);
4323         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
4324                                font->gmsize * sizeof(GM*));
4325     } else {
4326         if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL &&
4327             FONT_GM(font,original_index)->init && (!lpmat || is_identity_MAT2(lpmat)))
4328         {
4329             *lpgm = FONT_GM(font,original_index)->gm;
4330             TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
4331                   wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
4332                   lpgm->gmCellIncX, lpgm->gmCellIncY);
4333             LeaveCriticalSection( &freetype_cs );
4334             return 1; /* FIXME */
4335         }
4336     }
4337
4338     if (!font->gm[original_index / GM_BLOCK_SIZE])
4339         font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
4340
4341     if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP && format != WINE_GGO_GRAY16_BITMAP) || lpmat)
4342         load_flags |= FT_LOAD_NO_BITMAP;
4343
4344     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
4345
4346     if(err) {
4347         WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
4348         LeaveCriticalSection( &freetype_cs );
4349         return GDI_ERROR;
4350     }
4351         
4352     /* Scaling factor */
4353     if (font->aveWidth)
4354     {
4355         TEXTMETRICW tm;
4356
4357         WineEngGetTextMetrics(font, &tm);
4358
4359         widthRatio = (double)font->aveWidth;
4360         widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
4361     }
4362     else
4363         widthRatio = font->scale_y;
4364
4365     left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64;
4366     right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64;
4367
4368     adv = (INT)((ft_face->glyph->metrics.horiAdvance) + 63) >> 6;
4369     lsb = left >> 6;
4370     bbx = (right - left) >> 6;
4371
4372     /* Scaling transform */
4373     if (widthRatio != 1.0 || font->scale_y != 1.0)
4374     {
4375         FT_Matrix scaleMat;
4376         scaleMat.xx = FT_FixedFromFloat(widthRatio);
4377         scaleMat.xy = 0;
4378         scaleMat.yx = 0;
4379         scaleMat.yy = FT_FixedFromFloat(font->scale_y);
4380
4381         pFT_Matrix_Multiply(&scaleMat, &transMat);
4382         needsTransform = TRUE;
4383     }
4384
4385     /* Slant transform */
4386     if (font->fake_italic) {
4387         FT_Matrix slantMat;
4388         
4389         slantMat.xx = (1 << 16);
4390         slantMat.xy = ((1 << 16) >> 2);
4391         slantMat.yx = 0;
4392         slantMat.yy = (1 << 16);
4393         pFT_Matrix_Multiply(&slantMat, &transMat);
4394         needsTransform = TRUE;
4395     }
4396
4397     /* Rotation transform */
4398     if(font->orientation && !tategaki) {
4399         FT_Matrix rotationMat;
4400         FT_Vector vecAngle;
4401         angle = FT_FixedFromFloat((double)font->orientation / 10.0);
4402         pFT_Vector_Unit(&vecAngle, angle);
4403         rotationMat.xx = vecAngle.x;
4404         rotationMat.xy = -vecAngle.y;
4405         rotationMat.yx = -rotationMat.xy;
4406         rotationMat.yy = rotationMat.xx;
4407         
4408         pFT_Matrix_Multiply(&rotationMat, &transMat);
4409         needsTransform = TRUE;
4410     }
4411
4412     /* World transform */
4413     if (!is_identity_FMAT2(&font->font_desc.matrix))
4414     {
4415         FT_Matrix worldMat;
4416         worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11);
4417         worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM21);
4418         worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM12);
4419         worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22);
4420         pFT_Matrix_Multiply(&worldMat, &transMat);
4421         needsTransform = TRUE;
4422     }
4423
4424     /* Extra transformation specified by caller */
4425     if (lpmat && !is_identity_MAT2(lpmat))
4426     {
4427         FT_Matrix extraMat;
4428         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
4429         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
4430         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
4431         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
4432         pFT_Matrix_Multiply(&extraMat, &transMat);
4433         needsTransform = TRUE;
4434     }
4435
4436     if(!needsTransform) {
4437         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
4438         bottom = (ft_face->glyph->metrics.horiBearingY -
4439                   ft_face->glyph->metrics.height) & -64;
4440         lpgm->gmCellIncX = adv;
4441         lpgm->gmCellIncY = 0;
4442     } else {
4443         INT xc, yc;
4444         FT_Vector vec;
4445         for(xc = 0; xc < 2; xc++) {
4446             for(yc = 0; yc < 2; yc++) {
4447                 vec.x = (ft_face->glyph->metrics.horiBearingX +
4448                   xc * ft_face->glyph->metrics.width);
4449                 vec.y = ft_face->glyph->metrics.horiBearingY -
4450                   yc * ft_face->glyph->metrics.height;
4451                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
4452                 pFT_Vector_Transform(&vec, &transMat);
4453                 if(xc == 0 && yc == 0) {
4454                     left = right = vec.x;
4455                     top = bottom = vec.y;
4456                 } else {
4457                     if(vec.x < left) left = vec.x;
4458                     else if(vec.x > right) right = vec.x;
4459                     if(vec.y < bottom) bottom = vec.y;
4460                     else if(vec.y > top) top = vec.y;
4461                 }
4462             }
4463         }
4464         left = left & -64;
4465         right = (right + 63) & -64;
4466         bottom = bottom & -64;
4467         top = (top + 63) & -64;
4468
4469         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
4470         vec.x = ft_face->glyph->metrics.horiAdvance;
4471         vec.y = 0;
4472         pFT_Vector_Transform(&vec, &transMat);
4473         adv = lpgm->gmCellIncX = (vec.x+63) >> 6;
4474         lpgm->gmCellIncY = -((vec.y+63) >> 6);
4475     }
4476     lpgm->gmBlackBoxX = (right - left) >> 6;
4477     lpgm->gmBlackBoxY = (top - bottom) >> 6;
4478     lpgm->gmptGlyphOrigin.x = left >> 6;
4479     lpgm->gmptGlyphOrigin.y = top >> 6;
4480
4481     TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
4482           wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
4483           lpgm->gmCellIncX, lpgm->gmCellIncY);
4484
4485     if ((format == GGO_METRICS || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
4486         (!lpmat || is_identity_MAT2(lpmat))) /* don't cache custom transforms */
4487     {
4488         FONT_GM(font,original_index)->gm = *lpgm;
4489         FONT_GM(font,original_index)->adv = adv;
4490         FONT_GM(font,original_index)->lsb = lsb;
4491         FONT_GM(font,original_index)->bbx = bbx;
4492         FONT_GM(font,original_index)->init = TRUE;
4493     }
4494
4495     if(format == GGO_METRICS)
4496     {
4497         LeaveCriticalSection( &freetype_cs );
4498         return 1; /* FIXME */
4499     }
4500
4501     if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP && format != WINE_GGO_GRAY16_BITMAP) {
4502         TRACE("loaded a bitmap\n");
4503         LeaveCriticalSection( &freetype_cs );
4504         return GDI_ERROR;
4505     }
4506
4507     switch(format) {
4508     case GGO_BITMAP:
4509         width = lpgm->gmBlackBoxX;
4510         height = lpgm->gmBlackBoxY;
4511         pitch = ((width + 31) >> 5) << 2;
4512         needed = pitch * height;
4513
4514         if(!buf || !buflen) break;
4515
4516         switch(ft_face->glyph->format) {
4517         case ft_glyph_format_bitmap:
4518           {
4519             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
4520             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
4521             INT h = ft_face->glyph->bitmap.rows;
4522             while(h--) {
4523                 memcpy(dst, src, w);
4524                 src += ft_face->glyph->bitmap.pitch;
4525                 dst += pitch;
4526             }
4527             break;
4528           }
4529
4530         case ft_glyph_format_outline:
4531             ft_bitmap.width = width;
4532             ft_bitmap.rows = height;
4533             ft_bitmap.pitch = pitch;
4534             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
4535             ft_bitmap.buffer = buf;
4536
4537                 if(needsTransform) {
4538                         pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4539             }
4540
4541             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4542
4543             /* Note: FreeType will only set 'black' bits for us. */
4544             memset(buf, 0, needed);
4545             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
4546             break;
4547
4548         default:
4549             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
4550             LeaveCriticalSection( &freetype_cs );
4551             return GDI_ERROR;
4552         }
4553         break;
4554
4555     case GGO_GRAY2_BITMAP:
4556     case GGO_GRAY4_BITMAP:
4557     case GGO_GRAY8_BITMAP:
4558     case WINE_GGO_GRAY16_BITMAP:
4559       {
4560         unsigned int mult, row, col;
4561         BYTE *start, *ptr;
4562
4563         width = lpgm->gmBlackBoxX;
4564         height = lpgm->gmBlackBoxY;
4565         pitch = (width + 3) / 4 * 4;
4566         needed = pitch * height;
4567
4568         if(!buf || !buflen) break;
4569
4570         switch(ft_face->glyph->format) {
4571         case ft_glyph_format_bitmap:
4572           {
4573             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
4574             INT h = ft_face->glyph->bitmap.rows;
4575             INT x;
4576             while(h--) {
4577                 for(x = 0; x < pitch; x++)
4578                 {
4579                     if(x < ft_face->glyph->bitmap.width)
4580                         dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0;
4581                     else
4582                         dst[x] = 0;
4583                 }
4584                 src += ft_face->glyph->bitmap.pitch;
4585                 dst += pitch;
4586             }
4587             LeaveCriticalSection( &freetype_cs );
4588             return needed;
4589           }
4590         case ft_glyph_format_outline:
4591           {
4592             ft_bitmap.width = width;
4593             ft_bitmap.rows = height;
4594             ft_bitmap.pitch = pitch;
4595             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
4596             ft_bitmap.buffer = buf;
4597
4598             if(needsTransform)
4599                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4600
4601             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4602
4603             memset(ft_bitmap.buffer, 0, buflen);
4604
4605             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
4606
4607             if(format == GGO_GRAY2_BITMAP)
4608                 mult = 4;
4609             else if(format == GGO_GRAY4_BITMAP)
4610                 mult = 16;
4611             else if(format == GGO_GRAY8_BITMAP)
4612                 mult = 64;
4613             else /* format == WINE_GGO_GRAY16_BITMAP */
4614             {
4615                 LeaveCriticalSection( &freetype_cs );
4616                 return needed;
4617             }
4618             break;
4619           }
4620         default:
4621             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
4622             LeaveCriticalSection( &freetype_cs );
4623             return GDI_ERROR;
4624         }
4625
4626         start = buf;
4627         for(row = 0; row < height; row++) {
4628             ptr = start;
4629             for(col = 0; col < width; col++, ptr++) {
4630                 *ptr = (((int)*ptr) * mult + 128) / 256;
4631             }
4632             start += pitch;
4633         }
4634         break;
4635       }
4636
4637     case GGO_NATIVE:
4638       {
4639         int contour, point = 0, first_pt;
4640         FT_Outline *outline = &ft_face->glyph->outline;
4641         TTPOLYGONHEADER *pph;
4642         TTPOLYCURVE *ppc;
4643         DWORD pph_start, cpfx, type;
4644
4645         if(buflen == 0) buf = NULL;
4646
4647         if (needsTransform && buf) {
4648                 pFT_Outline_Transform(outline, &transMat);
4649         }
4650
4651         for(contour = 0; contour < outline->n_contours; contour++) {
4652             pph_start = needed;
4653             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
4654             first_pt = point;
4655             if(buf) {
4656                 pph->dwType = TT_POLYGON_TYPE;
4657                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
4658             }
4659             needed += sizeof(*pph);
4660             point++;
4661             while(point <= outline->contours[contour]) {
4662                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
4663                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
4664                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
4665                 cpfx = 0;
4666                 do {
4667                     if(buf)
4668                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4669                     cpfx++;
4670                     point++;
4671                 } while(point <= outline->contours[contour] &&
4672                         (outline->tags[point] & FT_Curve_Tag_On) ==
4673                         (outline->tags[point-1] & FT_Curve_Tag_On));
4674                 /* At the end of a contour Windows adds the start point, but
4675                    only for Beziers */
4676                 if(point > outline->contours[contour] &&
4677                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
4678                     if(buf)
4679                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
4680                     cpfx++;
4681                 } else if(point <= outline->contours[contour] &&
4682                           outline->tags[point] & FT_Curve_Tag_On) {
4683                   /* add closing pt for bezier */
4684                     if(buf)
4685                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4686                     cpfx++;
4687                     point++;
4688                 }
4689                 if(buf) {
4690                     ppc->wType = type;
4691                     ppc->cpfx = cpfx;
4692                 }
4693                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
4694             }
4695             if(buf)
4696                 pph->cb = needed - pph_start;
4697         }
4698         break;
4699       }
4700     case GGO_BEZIER:
4701       {
4702         /* Convert the quadratic Beziers to cubic Beziers.
4703            The parametric eqn for a cubic Bezier is, from PLRM:
4704            r(t) = at^3 + bt^2 + ct + r0
4705            with the control points:
4706            r1 = r0 + c/3
4707            r2 = r1 + (c + b)/3
4708            r3 = r0 + c + b + a
4709
4710            A quadratic Beizer has the form:
4711            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
4712
4713            So equating powers of t leads to:
4714            r1 = 2/3 p1 + 1/3 p0
4715            r2 = 2/3 p1 + 1/3 p2
4716            and of course r0 = p0, r3 = p2
4717         */
4718
4719         int contour, point = 0, first_pt;
4720         FT_Outline *outline = &ft_face->glyph->outline;
4721         TTPOLYGONHEADER *pph;
4722         TTPOLYCURVE *ppc;
4723         DWORD pph_start, cpfx, type;
4724         FT_Vector cubic_control[4];
4725         if(buflen == 0) buf = NULL;
4726
4727         if (needsTransform && buf) {
4728                 pFT_Outline_Transform(outline, &transMat);
4729         }
4730
4731         for(contour = 0; contour < outline->n_contours; contour++) {
4732             pph_start = needed;
4733             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
4734             first_pt = point;
4735             if(buf) {
4736                 pph->dwType = TT_POLYGON_TYPE;
4737                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
4738             }
4739             needed += sizeof(*pph);
4740             point++;
4741             while(point <= outline->contours[contour]) {
4742                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
4743                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
4744                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
4745                 cpfx = 0;
4746                 do {
4747                     if(type == TT_PRIM_LINE) {
4748                         if(buf)
4749                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4750                         cpfx++;
4751                         point++;
4752                     } else {
4753                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
4754                          so cpfx = 3n */
4755
4756                       /* FIXME: Possible optimization in endpoint calculation
4757                          if there are two consecutive curves */
4758                         cubic_control[0] = outline->points[point-1];
4759                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
4760                             cubic_control[0].x += outline->points[point].x + 1;
4761                             cubic_control[0].y += outline->points[point].y + 1;
4762                             cubic_control[0].x >>= 1;
4763                             cubic_control[0].y >>= 1;
4764                         }
4765                         if(point+1 > outline->contours[contour])
4766                             cubic_control[3] = outline->points[first_pt];
4767                         else {
4768                             cubic_control[3] = outline->points[point+1];
4769                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
4770                                 cubic_control[3].x += outline->points[point].x + 1;
4771                                 cubic_control[3].y += outline->points[point].y + 1;
4772                                 cubic_control[3].x >>= 1;
4773                                 cubic_control[3].y >>= 1;
4774                             }
4775                         }
4776                         /* r1 = 1/3 p0 + 2/3 p1
4777                            r2 = 1/3 p2 + 2/3 p1 */
4778                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
4779                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
4780                         cubic_control[2] = cubic_control[1];
4781                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
4782                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
4783                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
4784                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
4785                         if(buf) {
4786                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
4787                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
4788                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
4789                         }
4790                         cpfx += 3;
4791                         point++;
4792                     }
4793                 } while(point <= outline->contours[contour] &&
4794                         (outline->tags[point] & FT_Curve_Tag_On) ==
4795                         (outline->tags[point-1] & FT_Curve_Tag_On));
4796                 /* At the end of a contour Windows adds the start point,
4797                    but only for Beziers and we've already done that.
4798                 */
4799                 if(point <= outline->contours[contour] &&
4800                    outline->tags[point] & FT_Curve_Tag_On) {
4801                   /* This is the closing pt of a bezier, but we've already
4802                      added it, so just inc point and carry on */
4803                     point++;
4804                 }
4805                 if(buf) {
4806                     ppc->wType = type;
4807                     ppc->cpfx = cpfx;
4808                 }
4809                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
4810             }
4811             if(buf)
4812                 pph->cb = needed - pph_start;
4813         }
4814         break;
4815       }
4816
4817     default:
4818         FIXME("Unsupported format %d\n", format);
4819         LeaveCriticalSection( &freetype_cs );
4820         return GDI_ERROR;
4821     }
4822     LeaveCriticalSection( &freetype_cs );
4823     return needed;
4824 }
4825
4826 static BOOL get_bitmap_text_metrics(GdiFont *font)
4827 {
4828     FT_Face ft_face = font->ft_face;
4829 #ifdef HAVE_FREETYPE_FTWINFNT_H
4830     FT_WinFNT_HeaderRec winfnt_header;
4831 #endif
4832     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
4833     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
4834     font->potm->otmSize = size;
4835
4836 #define TM font->potm->otmTextMetrics
4837 #ifdef HAVE_FREETYPE_FTWINFNT_H
4838     if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
4839     {
4840         TM.tmHeight = winfnt_header.pixel_height;
4841         TM.tmAscent = winfnt_header.ascent;
4842         TM.tmDescent = TM.tmHeight - TM.tmAscent;
4843         TM.tmInternalLeading = winfnt_header.internal_leading;
4844         TM.tmExternalLeading = winfnt_header.external_leading;
4845         TM.tmAveCharWidth = winfnt_header.avg_width;
4846         TM.tmMaxCharWidth = winfnt_header.max_width;
4847         TM.tmWeight = winfnt_header.weight;
4848         TM.tmOverhang = 0;
4849         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
4850         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
4851         TM.tmFirstChar = winfnt_header.first_char;
4852         TM.tmLastChar = winfnt_header.last_char;
4853         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
4854         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
4855         TM.tmItalic = winfnt_header.italic;
4856         TM.tmUnderlined = font->underline;
4857         TM.tmStruckOut = font->strikeout;
4858         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
4859         TM.tmCharSet = winfnt_header.charset;
4860     }
4861     else
4862 #endif
4863     {
4864         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
4865         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
4866         TM.tmHeight = TM.tmAscent + TM.tmDescent;
4867         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
4868         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
4869         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
4870         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
4871         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
4872         TM.tmOverhang = 0;
4873         TM.tmDigitizedAspectX = 96; /* FIXME */
4874         TM.tmDigitizedAspectY = 96; /* FIXME */
4875         TM.tmFirstChar = 1;
4876         TM.tmLastChar = 255;
4877         TM.tmDefaultChar = 32;
4878         TM.tmBreakChar = 32;
4879         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
4880         TM.tmUnderlined = font->underline;
4881         TM.tmStruckOut = font->strikeout;
4882         /* NB inverted meaning of TMPF_FIXED_PITCH */
4883         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
4884         TM.tmCharSet = font->charset;
4885     }
4886 #undef TM
4887
4888     return TRUE;
4889 }
4890
4891
4892 static void scale_font_metrics(const GdiFont *font, LPTEXTMETRICW ptm)
4893 {
4894     double scale_x, scale_y;
4895
4896     if (font->aveWidth)
4897     {
4898         scale_x = (double)font->aveWidth;
4899         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
4900     }
4901     else
4902         scale_x = font->scale_y;
4903
4904     scale_x *= fabs(font->font_desc.matrix.eM11);
4905     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
4906
4907 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
4908 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
4909
4910     SCALE_Y(ptm->tmHeight);
4911     SCALE_Y(ptm->tmAscent);
4912     SCALE_Y(ptm->tmDescent);
4913     SCALE_Y(ptm->tmInternalLeading);
4914     SCALE_Y(ptm->tmExternalLeading);
4915     SCALE_Y(ptm->tmOverhang);
4916
4917     SCALE_X(ptm->tmAveCharWidth);
4918     SCALE_X(ptm->tmMaxCharWidth);
4919
4920 #undef SCALE_X
4921 #undef SCALE_Y
4922 }
4923
4924 static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *potm)
4925 {
4926     double scale_x, scale_y;
4927
4928     if (font->aveWidth)
4929     {
4930         scale_x = (double)font->aveWidth;
4931         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
4932     }
4933     else
4934         scale_x = font->scale_y;
4935
4936     scale_x *= fabs(font->font_desc.matrix.eM11);
4937     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
4938
4939     scale_font_metrics(font, &potm->otmTextMetrics);
4940
4941 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
4942 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
4943
4944     SCALE_Y(potm->otmAscent);
4945     SCALE_Y(potm->otmDescent);
4946     SCALE_Y(potm->otmLineGap);
4947     SCALE_Y(potm->otmsCapEmHeight);
4948     SCALE_Y(potm->otmsXHeight);
4949     SCALE_Y(potm->otmrcFontBox.top);
4950     SCALE_Y(potm->otmrcFontBox.bottom);
4951     SCALE_X(potm->otmrcFontBox.left);
4952     SCALE_X(potm->otmrcFontBox.right);
4953     SCALE_Y(potm->otmMacAscent);
4954     SCALE_Y(potm->otmMacDescent);
4955     SCALE_Y(potm->otmMacLineGap);
4956     SCALE_X(potm->otmptSubscriptSize.x);
4957     SCALE_Y(potm->otmptSubscriptSize.y);
4958     SCALE_X(potm->otmptSubscriptOffset.x);
4959     SCALE_Y(potm->otmptSubscriptOffset.y);
4960     SCALE_X(potm->otmptSuperscriptSize.x);
4961     SCALE_Y(potm->otmptSuperscriptSize.y);
4962     SCALE_X(potm->otmptSuperscriptOffset.x);
4963     SCALE_Y(potm->otmptSuperscriptOffset.y);
4964     SCALE_Y(potm->otmsStrikeoutSize);
4965     SCALE_Y(potm->otmsStrikeoutPosition);
4966     SCALE_Y(potm->otmsUnderscoreSize);
4967     SCALE_Y(potm->otmsUnderscorePosition);
4968
4969 #undef SCALE_X
4970 #undef SCALE_Y
4971 }
4972
4973 /*************************************************************
4974  * WineEngGetTextMetrics
4975  *
4976  */
4977 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
4978 {
4979     EnterCriticalSection( &freetype_cs );
4980     if(!font->potm) {
4981         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
4982             if(!get_bitmap_text_metrics(font))
4983             {
4984                 LeaveCriticalSection( &freetype_cs );
4985                 return FALSE;
4986             }
4987     }
4988     if(!font->potm)
4989     {
4990         LeaveCriticalSection( &freetype_cs );
4991         return FALSE;
4992     }
4993     *ptm = font->potm->otmTextMetrics;
4994     scale_font_metrics(font, ptm);
4995     LeaveCriticalSection( &freetype_cs );
4996     return TRUE;
4997 }
4998
4999
5000 /*************************************************************
5001  * WineEngGetOutlineTextMetrics
5002  *
5003  */
5004 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
5005                                   OUTLINETEXTMETRICW *potm)
5006 {
5007     FT_Face ft_face = font->ft_face;
5008     UINT needed, lenfam, lensty, ret;
5009     TT_OS2 *pOS2;
5010     TT_HoriHeader *pHori;
5011     TT_Postscript *pPost;
5012     FT_Fixed x_scale, y_scale;
5013     WCHAR *family_nameW, *style_nameW;
5014     static const WCHAR spaceW[] = {' ', '\0'};
5015     char *cp;
5016     INT ascent, descent;
5017
5018     TRACE("font=%p\n", font);
5019
5020     if(!FT_IS_SCALABLE(ft_face))
5021         return 0;
5022
5023     EnterCriticalSection( &freetype_cs );
5024
5025     if(font->potm) {
5026         if(cbSize >= font->potm->otmSize)
5027         {
5028             memcpy(potm, font->potm, font->potm->otmSize);
5029             scale_outline_font_metrics(font, potm);
5030         }
5031         LeaveCriticalSection( &freetype_cs );
5032         return font->potm->otmSize;
5033     }
5034
5035
5036     needed = sizeof(*potm);
5037
5038     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
5039     family_nameW = strdupW(font->name);
5040
5041     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
5042       * sizeof(WCHAR);
5043     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
5044     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
5045                         style_nameW, lensty/sizeof(WCHAR));
5046
5047     /* These names should be read from the TT name table */
5048
5049     /* length of otmpFamilyName */
5050     needed += lenfam;
5051
5052     /* length of otmpFaceName */
5053     if ((ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) == 0) {
5054       needed += lenfam; /* just the family name */
5055     } else {
5056       needed += lenfam + lensty; /* family + " " + style */
5057     }
5058
5059     /* length of otmpStyleName */
5060     needed += lensty;
5061
5062     /* length of otmpFullName */
5063     needed += lenfam + lensty;
5064
5065
5066     x_scale = ft_face->size->metrics.x_scale;
5067     y_scale = ft_face->size->metrics.y_scale;
5068
5069     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
5070     if(!pOS2) {
5071         FIXME("Can't find OS/2 table - not TT font?\n");
5072         ret = 0;
5073         goto end;
5074     }
5075
5076     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
5077     if(!pHori) {
5078         FIXME("Can't find HHEA table - not TT font?\n");
5079         ret = 0;
5080         goto end;
5081     }
5082
5083     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
5084
5085     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",
5086           pOS2->usWinAscent, pOS2->usWinDescent,
5087           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
5088           ft_face->ascender, ft_face->descender, ft_face->height,
5089           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
5090           ft_face->bbox.yMax, ft_face->bbox.yMin);
5091
5092     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
5093     font->potm->otmSize = needed;
5094
5095 #define TM font->potm->otmTextMetrics
5096
5097     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
5098         ascent = pHori->Ascender;
5099         descent = -pHori->Descender;
5100     } else {
5101         ascent = pOS2->usWinAscent;
5102         descent = pOS2->usWinDescent;
5103     }
5104
5105     if(font->yMax) {
5106         TM.tmAscent = font->yMax;
5107         TM.tmDescent = -font->yMin;
5108         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
5109     } else {
5110         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
5111         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
5112         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
5113                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
5114     }
5115
5116     TM.tmHeight = TM.tmAscent + TM.tmDescent;
5117
5118     /* MSDN says:
5119      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
5120     */
5121     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
5122                  ((ascent + descent) -
5123                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
5124
5125     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
5126     if (TM.tmAveCharWidth == 0) {
5127         TM.tmAveCharWidth = 1; 
5128     }
5129     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
5130     TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
5131     TM.tmOverhang = 0;
5132     TM.tmDigitizedAspectX = 300;
5133     TM.tmDigitizedAspectY = 300;
5134     /* It appears that for fonts with SYMBOL_CHARSET Windows always sets
5135      * symbol range to 0 - f0ff
5136      */
5137     if (font->charset == SYMBOL_CHARSET)
5138     {
5139         TM.tmFirstChar = 0;
5140         TM.tmDefaultChar = pOS2->usDefaultChar ? pOS2->usDefaultChar : 0x1f;
5141     }
5142     else
5143     {
5144         TM.tmFirstChar = pOS2->usFirstCharIndex;
5145         TM.tmDefaultChar = pOS2->usDefaultChar ? pOS2->usDefaultChar : 0xffff;
5146     }
5147     TM.tmLastChar = pOS2->usLastCharIndex;
5148     TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
5149     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
5150     TM.tmUnderlined = font->underline;
5151     TM.tmStruckOut = font->strikeout;
5152
5153     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
5154     if(!FT_IS_FIXED_WIDTH(ft_face) &&
5155        (pOS2->version == 0xFFFFU || 
5156         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
5157         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
5158     else
5159         TM.tmPitchAndFamily = 0;
5160
5161     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
5162     case PAN_FAMILY_SCRIPT:
5163         TM.tmPitchAndFamily |= FF_SCRIPT;
5164         break;
5165     case PAN_FAMILY_DECORATIVE:
5166     case PAN_FAMILY_PICTORIAL:
5167         TM.tmPitchAndFamily |= FF_DECORATIVE;
5168         break;
5169     case PAN_FAMILY_TEXT_DISPLAY:
5170         if(TM.tmPitchAndFamily == 0) /* fixed */
5171             TM.tmPitchAndFamily = FF_MODERN;
5172         else {
5173             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
5174             case PAN_SERIF_NORMAL_SANS:
5175             case PAN_SERIF_OBTUSE_SANS:
5176             case PAN_SERIF_PERP_SANS:
5177                 TM.tmPitchAndFamily |= FF_SWISS;
5178                 break;
5179             default:
5180                 TM.tmPitchAndFamily |= FF_ROMAN;
5181             }
5182         }
5183         break;
5184     default:
5185         TM.tmPitchAndFamily |= FF_DONTCARE;
5186     }
5187
5188     if(FT_IS_SCALABLE(ft_face))
5189         TM.tmPitchAndFamily |= TMPF_VECTOR;
5190
5191     if(FT_IS_SFNT(ft_face))
5192     {
5193         if (font->ntmFlags & NTM_PS_OPENTYPE)
5194             TM.tmPitchAndFamily |= TMPF_DEVICE;
5195         else
5196             TM.tmPitchAndFamily |= TMPF_TRUETYPE;
5197     }
5198
5199     TM.tmCharSet = font->charset;
5200
5201     font->potm->otmFiller = 0;
5202     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
5203     font->potm->otmfsSelection = pOS2->fsSelection;
5204     font->potm->otmfsType = pOS2->fsType;
5205     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
5206     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
5207     font->potm->otmItalicAngle = 0; /* POST table */
5208     font->potm->otmEMSquare = ft_face->units_per_EM;
5209     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
5210     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
5211     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
5212     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
5213     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
5214     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
5215     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
5216     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
5217     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
5218     font->potm->otmMacAscent = TM.tmAscent;
5219     font->potm->otmMacDescent = -TM.tmDescent;
5220     font->potm->otmMacLineGap = font->potm->otmLineGap;
5221     font->potm->otmusMinimumPPEM = 0; /* TT Header */
5222     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
5223     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
5224     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
5225     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
5226     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
5227     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
5228     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
5229     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
5230     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
5231     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
5232     if(!pPost) {
5233         font->potm->otmsUnderscoreSize = 0;
5234         font->potm->otmsUnderscorePosition = 0;
5235     } else {
5236         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
5237         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
5238     }
5239 #undef TM
5240
5241     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
5242     cp = (char*)font->potm + sizeof(*font->potm);
5243     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
5244     strcpyW((WCHAR*)cp, family_nameW);
5245     cp += lenfam;
5246     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
5247     strcpyW((WCHAR*)cp, style_nameW);
5248     cp += lensty;
5249     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
5250     strcpyW((WCHAR*)cp, family_nameW);
5251     if (ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) {
5252         strcatW((WCHAR*)cp, spaceW);
5253         strcatW((WCHAR*)cp, style_nameW);
5254         cp += lenfam + lensty;
5255     } else
5256         cp += lenfam;
5257     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
5258     strcpyW((WCHAR*)cp, family_nameW);
5259     strcatW((WCHAR*)cp, spaceW);
5260     strcatW((WCHAR*)cp, style_nameW);
5261     ret = needed;
5262
5263     if(potm && needed <= cbSize)
5264     {
5265         memcpy(potm, font->potm, font->potm->otmSize);
5266         scale_outline_font_metrics(font, potm);
5267     }
5268
5269 end:
5270     HeapFree(GetProcessHeap(), 0, style_nameW);
5271     HeapFree(GetProcessHeap(), 0, family_nameW);
5272
5273     LeaveCriticalSection( &freetype_cs );
5274     return ret;
5275 }
5276
5277 static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
5278 {
5279     HFONTLIST *hfontlist;
5280     child->font = alloc_font();
5281     child->font->ft_face = OpenFontFace(child->font, child->face, 0, -font->ppem);
5282     if(!child->font->ft_face)
5283     {
5284         free_font(child->font);
5285         child->font = NULL;
5286         return FALSE;
5287     }
5288
5289     child->font->ntmFlags = child->face->ntmFlags;
5290     child->font->orientation = font->orientation;
5291     child->font->scale_y = font->scale_y;
5292     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
5293     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
5294     list_add_head(&child->font->hfontlist, &hfontlist->entry);
5295     child->font->base_font = font;
5296     list_add_head(&child_font_list, &child->font->entry);
5297     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
5298     return TRUE;
5299 }
5300
5301 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph)
5302 {
5303     FT_UInt g;
5304     CHILD_FONT *child_font;
5305
5306     if(font->base_font)
5307         font = font->base_font;
5308
5309     *linked_font = font;
5310
5311     if((*glyph = get_glyph_index(font, c)))
5312         return TRUE;
5313
5314     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
5315     {
5316         if(!child_font->font)
5317             if(!load_child_font(font, child_font))
5318                 continue;
5319
5320         if(!child_font->font->ft_face)
5321             continue;
5322         g = get_glyph_index(child_font->font, c);
5323         if(g)
5324         {
5325             *glyph = g;
5326             *linked_font = child_font->font;
5327             return TRUE;
5328         }
5329     }
5330     return FALSE;
5331 }
5332
5333 /*************************************************************
5334  * WineEngGetCharWidth
5335  *
5336  */
5337 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
5338                          LPINT buffer)
5339 {
5340     UINT c;
5341     GLYPHMETRICS gm;
5342     FT_UInt glyph_index;
5343     GdiFont *linked_font;
5344
5345     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
5346
5347     EnterCriticalSection( &freetype_cs );
5348     for(c = firstChar; c <= lastChar; c++) {
5349         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
5350         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
5351                                &gm, 0, NULL, NULL);
5352         buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv;
5353     }
5354     LeaveCriticalSection( &freetype_cs );
5355     return TRUE;
5356 }
5357
5358 /*************************************************************
5359  * WineEngGetCharABCWidths
5360  *
5361  */
5362 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
5363                              LPABC buffer)
5364 {
5365     UINT c;
5366     GLYPHMETRICS gm;
5367     FT_UInt glyph_index;
5368     GdiFont *linked_font;
5369
5370     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
5371
5372     if(!FT_IS_SCALABLE(font->ft_face))
5373         return FALSE;
5374
5375     EnterCriticalSection( &freetype_cs );
5376
5377     for(c = firstChar; c <= lastChar; c++) {
5378         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
5379         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
5380                                &gm, 0, NULL, NULL);
5381         buffer[c - firstChar].abcA = FONT_GM(linked_font,glyph_index)->lsb;
5382         buffer[c - firstChar].abcB = FONT_GM(linked_font,glyph_index)->bbx;
5383         buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb -
5384             FONT_GM(linked_font,glyph_index)->bbx;
5385     }
5386     LeaveCriticalSection( &freetype_cs );
5387     return TRUE;
5388 }
5389
5390 /*************************************************************
5391  * WineEngGetCharABCWidthsI
5392  *
5393  */
5394 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
5395                               LPABC buffer)
5396 {
5397     UINT c;
5398     GLYPHMETRICS gm;
5399     FT_UInt glyph_index;
5400     GdiFont *linked_font;
5401
5402     if(!FT_HAS_HORIZONTAL(font->ft_face))
5403         return FALSE;
5404
5405     EnterCriticalSection( &freetype_cs );
5406
5407     get_glyph_index_linked(font, 'a', &linked_font, &glyph_index);
5408     if (!pgi)
5409         for(c = firstChar; c < firstChar+count; c++) {
5410             WineEngGetGlyphOutline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
5411                                    &gm, 0, NULL, NULL);
5412             buffer[c - firstChar].abcA = FONT_GM(linked_font,c)->lsb;
5413             buffer[c - firstChar].abcB = FONT_GM(linked_font,c)->bbx;
5414             buffer[c - firstChar].abcC = FONT_GM(linked_font,c)->adv - FONT_GM(linked_font,c)->lsb
5415                 - FONT_GM(linked_font,c)->bbx;
5416         }
5417     else
5418         for(c = 0; c < count; c++) {
5419             WineEngGetGlyphOutline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
5420                                    &gm, 0, NULL, NULL);
5421             buffer[c].abcA = FONT_GM(linked_font,pgi[c])->lsb;
5422             buffer[c].abcB = FONT_GM(linked_font,pgi[c])->bbx;
5423             buffer[c].abcC = FONT_GM(linked_font,pgi[c])->adv
5424                 - FONT_GM(linked_font,pgi[c])->lsb - FONT_GM(linked_font,pgi[c])->bbx;
5425         }
5426
5427     LeaveCriticalSection( &freetype_cs );
5428     return TRUE;
5429 }
5430
5431 /*************************************************************
5432  * WineEngGetTextExtentExPoint
5433  *
5434  */
5435 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
5436                                  INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
5437 {
5438     INT idx;
5439     INT nfit = 0, ext;
5440     GLYPHMETRICS gm;
5441     TEXTMETRICW tm;
5442     FT_UInt glyph_index;
5443     GdiFont *linked_font;
5444
5445     TRACE("%p, %s, %d, %d, %p\n", font, debugstr_wn(wstr, count), count,
5446           max_ext, size);
5447
5448     EnterCriticalSection( &freetype_cs );
5449
5450     size->cx = 0;
5451     WineEngGetTextMetrics(font, &tm);
5452     size->cy = tm.tmHeight;
5453
5454     for(idx = 0; idx < count; idx++) {
5455         get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
5456         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
5457                                &gm, 0, NULL, NULL);
5458         size->cx += FONT_GM(linked_font,glyph_index)->adv;
5459         ext = size->cx;
5460         if (! pnfit || ext <= max_ext) {
5461             ++nfit;
5462             if (dxs)
5463                 dxs[idx] = ext;
5464         }
5465     }
5466
5467     if (pnfit)
5468         *pnfit = nfit;
5469
5470     LeaveCriticalSection( &freetype_cs );
5471     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
5472     return TRUE;
5473 }
5474
5475 /*************************************************************
5476  * WineEngGetTextExtentExPointI
5477  *
5478  */
5479 BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count,
5480                                   INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
5481 {
5482     INT idx;
5483     INT nfit = 0, ext;
5484     GLYPHMETRICS gm;
5485     TEXTMETRICW tm;
5486
5487     TRACE("%p, %p, %d, %d, %p\n", font, indices, count, max_ext, size);
5488
5489     EnterCriticalSection( &freetype_cs );
5490
5491     size->cx = 0;
5492     WineEngGetTextMetrics(font, &tm);
5493     size->cy = tm.tmHeight;
5494
5495     for(idx = 0; idx < count; idx++) {
5496         WineEngGetGlyphOutline(font, indices[idx],
5497                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
5498                                NULL);
5499         size->cx += FONT_GM(font,indices[idx])->adv;
5500         ext = size->cx;
5501         if (! pnfit || ext <= max_ext) {
5502             ++nfit;
5503             if (dxs)
5504                 dxs[idx] = ext;
5505         }
5506     }
5507
5508     if (pnfit)
5509         *pnfit = nfit;
5510
5511     LeaveCriticalSection( &freetype_cs );
5512     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
5513     return TRUE;
5514 }
5515
5516 /*************************************************************
5517  * WineEngGetFontData
5518  *
5519  */
5520 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
5521                          DWORD cbData)
5522 {
5523     FT_Face ft_face = font->ft_face;
5524     FT_ULong len;
5525     FT_Error err;
5526
5527     TRACE("font=%p, table=%c%c%c%c, offset=0x%x, buf=%p, cbData=0x%x\n",
5528         font, LOBYTE(LOWORD(table)), HIBYTE(LOWORD(table)),
5529         LOBYTE(HIWORD(table)), HIBYTE(HIWORD(table)), offset, buf, cbData);
5530
5531     if(!FT_IS_SFNT(ft_face))
5532         return GDI_ERROR;
5533
5534     if(!buf || !cbData)
5535         len = 0;
5536     else
5537         len = cbData;
5538
5539     if(table) { /* MS tags differ in endianness from FT ones */
5540         table = table >> 24 | table << 24 |
5541           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
5542     }
5543
5544     /* make sure value of len is the value freetype says it needs */
5545     if(buf && len)
5546     {
5547         FT_ULong needed = 0;
5548         err = load_sfnt_table(ft_face, table, offset, NULL, &needed);
5549         if( !err && needed < len) len = needed;
5550     }
5551     err = load_sfnt_table(ft_face, table, offset, buf, &len);
5552
5553     if(err) {
5554         TRACE("Can't find table %c%c%c%c\n",
5555               /* bytes were reversed */
5556               HIBYTE(HIWORD(table)), LOBYTE(HIWORD(table)),
5557               HIBYTE(LOWORD(table)), LOBYTE(LOWORD(table)));
5558         return GDI_ERROR;
5559     }
5560     return len;
5561 }
5562
5563 /*************************************************************
5564  * WineEngGetTextFace
5565  *
5566  */
5567 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
5568 {
5569     INT n = strlenW(font->name) + 1;
5570     if(str) {
5571         lstrcpynW(str, font->name, count);
5572         return min(count, n);
5573     } else
5574         return n;
5575 }
5576
5577 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
5578 {
5579     if (fs) *fs = font->fs;
5580     return font->charset;
5581 }
5582
5583 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
5584 {
5585     GdiFont *font = dc->gdiFont, *linked_font;
5586     struct list *first_hfont;
5587     BOOL ret;
5588
5589     EnterCriticalSection( &freetype_cs );
5590     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
5591     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
5592     if(font == linked_font)
5593         *new_hfont = dc->hFont;
5594     else
5595     {
5596         first_hfont = list_head(&linked_font->hfontlist);
5597         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
5598     }
5599     LeaveCriticalSection( &freetype_cs );
5600     return ret;
5601 }
5602     
5603 /* Retrieve a list of supported Unicode ranges for a given font.
5604  * Can be called with NULL gs to calculate the buffer size. Returns
5605  * the number of ranges found.
5606  */
5607 static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
5608 {
5609     DWORD num_ranges = 0;
5610
5611     if (face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
5612     {
5613         FT_UInt glyph_code;
5614         FT_ULong char_code, char_code_prev;
5615
5616         glyph_code = 0;
5617         char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
5618
5619         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
5620                face->num_glyphs, glyph_code, char_code);
5621
5622         if (!glyph_code) return 0;
5623
5624         if (gs)
5625         {
5626             gs->ranges[0].wcLow = (USHORT)char_code;
5627             gs->ranges[0].cGlyphs = 0;
5628             gs->cGlyphsSupported = 0;
5629         }
5630
5631         num_ranges = 1;
5632         while (glyph_code)
5633         {
5634             if (char_code < char_code_prev)
5635             {
5636                 ERR("expected increasing char code from FT_Get_Next_Char\n");
5637                 return 0;
5638             }
5639             if (char_code - char_code_prev > 1)
5640             {
5641                 num_ranges++;
5642                 if (gs)
5643                 {
5644                     gs->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
5645                     gs->ranges[num_ranges - 1].cGlyphs = 1;
5646                     gs->cGlyphsSupported++;
5647                 }
5648             }
5649             else if (gs)
5650             {
5651                 gs->ranges[num_ranges - 1].cGlyphs++;
5652                 gs->cGlyphsSupported++;
5653             }
5654             char_code_prev = char_code;
5655             char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
5656         }
5657     }
5658     else
5659         FIXME("encoding %u not supported\n", face->charmap->encoding);
5660
5661     return num_ranges;
5662 }
5663
5664 DWORD WineEngGetFontUnicodeRanges(GdiFont *font, LPGLYPHSET glyphset)
5665 {
5666     DWORD size = 0;
5667     DWORD num_ranges = get_font_unicode_ranges(font->ft_face, glyphset);
5668
5669     size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
5670     if (glyphset)
5671     {
5672         glyphset->cbThis = size;
5673         glyphset->cRanges = num_ranges;
5674     }
5675     return size;
5676 }
5677
5678 /*************************************************************
5679  *     FontIsLinked
5680  */
5681 BOOL WineEngFontIsLinked(GdiFont *font)
5682 {
5683     BOOL ret;
5684     EnterCriticalSection( &freetype_cs );
5685     ret = !list_empty(&font->child_fonts);
5686     LeaveCriticalSection( &freetype_cs );
5687     return ret;
5688 }
5689
5690 static BOOL is_hinting_enabled(void)
5691 {
5692     /* Use the >= 2.2.0 function if available */
5693     if(pFT_Get_TrueType_Engine_Type)
5694     {
5695         FT_TrueTypeEngineType type = pFT_Get_TrueType_Engine_Type(library);
5696         return type == FT_TRUETYPE_ENGINE_TYPE_PATENTED;
5697     }
5698 #ifdef FT_DRIVER_HAS_HINTER
5699     else
5700     {
5701         FT_Module mod;
5702
5703         /* otherwise if we've been compiled with < 2.2.0 headers 
5704            use the internal macro */
5705         mod = pFT_Get_Module(library, "truetype");
5706         if(mod && FT_DRIVER_HAS_HINTER(mod))
5707             return TRUE;
5708     }
5709 #endif
5710
5711     return FALSE;
5712 }
5713
5714 /*************************************************************************
5715  *             GetRasterizerCaps   (GDI32.@)
5716  */
5717 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
5718 {
5719     static int hinting = -1;
5720
5721     if(hinting == -1)
5722     {
5723         hinting = is_hinting_enabled();
5724         TRACE("hinting is %senabled\n", hinting ? "" : "NOT ");
5725     }
5726
5727     lprs->nSize = sizeof(RASTERIZER_STATUS);
5728     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
5729     lprs->nLanguageID = 0;
5730     return TRUE;
5731 }
5732
5733 /*************************************************************************
5734  * Kerning support for TrueType fonts
5735  */
5736 #define MS_KERN_TAG MS_MAKE_TAG('k', 'e', 'r', 'n')
5737
5738 struct TT_kern_table
5739 {
5740     USHORT version;
5741     USHORT nTables;
5742 };
5743
5744 struct TT_kern_subtable
5745 {
5746     USHORT version;
5747     USHORT length;
5748     union
5749     {
5750         USHORT word;
5751         struct
5752         {
5753             USHORT horizontal : 1;
5754             USHORT minimum : 1;
5755             USHORT cross_stream: 1;
5756             USHORT override : 1;
5757             USHORT reserved1 : 4;
5758             USHORT format : 8;
5759         } bits;
5760     } coverage;
5761 };
5762
5763 struct TT_format0_kern_subtable
5764 {
5765     USHORT nPairs;
5766     USHORT searchRange;
5767     USHORT entrySelector;
5768     USHORT rangeShift;
5769 };
5770
5771 struct TT_kern_pair
5772 {
5773     USHORT left;
5774     USHORT right;
5775     short  value;
5776 };
5777
5778 static DWORD parse_format0_kern_subtable(GdiFont *font,
5779                                          const struct TT_format0_kern_subtable *tt_f0_ks,
5780                                          const USHORT *glyph_to_char,
5781                                          KERNINGPAIR *kern_pair, DWORD cPairs)
5782 {
5783     USHORT i, nPairs;
5784     const struct TT_kern_pair *tt_kern_pair;
5785
5786     TRACE("font height %d, units_per_EM %d\n", font->ppem, font->ft_face->units_per_EM);
5787
5788     nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
5789
5790     TRACE("nPairs %u, searchRange %u, entrySelector %u, rangeShift %u\n",
5791            nPairs, GET_BE_WORD(tt_f0_ks->searchRange),
5792            GET_BE_WORD(tt_f0_ks->entrySelector), GET_BE_WORD(tt_f0_ks->rangeShift));
5793
5794     if (!kern_pair || !cPairs)
5795         return nPairs;
5796
5797     tt_kern_pair = (const struct TT_kern_pair *)(tt_f0_ks + 1);
5798
5799     nPairs = min(nPairs, cPairs);
5800
5801     for (i = 0; i < nPairs; i++)
5802     {
5803         kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
5804         kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
5805         /* this algorithm appears to better match what Windows does */
5806         kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
5807         if (kern_pair->iKernAmount < 0)
5808         {
5809             kern_pair->iKernAmount -= font->ft_face->units_per_EM / 2;
5810             kern_pair->iKernAmount -= font->ppem;
5811         }
5812         else if (kern_pair->iKernAmount > 0)
5813         {
5814             kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
5815             kern_pair->iKernAmount += font->ppem;
5816         }
5817         kern_pair->iKernAmount /= font->ft_face->units_per_EM;
5818
5819         TRACE("left %u right %u value %d\n",
5820                kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
5821
5822         kern_pair++;
5823     }
5824     TRACE("copied %u entries\n", nPairs);
5825     return nPairs;
5826 }
5827
5828 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
5829 {
5830     DWORD length;
5831     void *buf;
5832     const struct TT_kern_table *tt_kern_table;
5833     const struct TT_kern_subtable *tt_kern_subtable;
5834     USHORT i, nTables;
5835     USHORT *glyph_to_char;
5836
5837     EnterCriticalSection( &freetype_cs );
5838     if (font->total_kern_pairs != (DWORD)-1)
5839     {
5840         if (cPairs && kern_pair)
5841         {
5842             cPairs = min(cPairs, font->total_kern_pairs);
5843             memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
5844             LeaveCriticalSection( &freetype_cs );
5845             return cPairs;
5846         }
5847         LeaveCriticalSection( &freetype_cs );
5848         return font->total_kern_pairs;
5849     }
5850
5851     font->total_kern_pairs = 0;
5852
5853     length = WineEngGetFontData(font, MS_KERN_TAG, 0, NULL, 0);
5854
5855     if (length == GDI_ERROR)
5856     {
5857         TRACE("no kerning data in the font\n");
5858         LeaveCriticalSection( &freetype_cs );
5859         return 0;
5860     }
5861
5862     buf = HeapAlloc(GetProcessHeap(), 0, length);
5863     if (!buf)
5864     {
5865         WARN("Out of memory\n");
5866         LeaveCriticalSection( &freetype_cs );
5867         return 0;
5868     }
5869
5870     WineEngGetFontData(font, MS_KERN_TAG, 0, buf, length);
5871
5872     /* build a glyph index to char code map */
5873     glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
5874     if (!glyph_to_char)
5875     {
5876         WARN("Out of memory allocating a glyph index to char code map\n");
5877         HeapFree(GetProcessHeap(), 0, buf);
5878         LeaveCriticalSection( &freetype_cs );
5879         return 0;
5880     }
5881
5882     if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
5883     {
5884         FT_UInt glyph_code;
5885         FT_ULong char_code;
5886
5887         glyph_code = 0;
5888         char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
5889
5890         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
5891                font->ft_face->num_glyphs, glyph_code, char_code);
5892
5893         while (glyph_code)
5894         {
5895             /*TRACE("Char %04lX -> Index %u%s\n", char_code, glyph_code, glyph_to_char[glyph_code] ? "  !" : "" );*/
5896
5897             /* FIXME: This doesn't match what Windows does: it does some fancy
5898              * things with duplicate glyph index to char code mappings, while
5899              * we just avoid overriding existing entries.
5900              */
5901             if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
5902                 glyph_to_char[glyph_code] = (USHORT)char_code;
5903
5904             char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
5905         }
5906     }
5907     else
5908     {
5909         ULONG n;
5910
5911         FIXME("encoding %u not supported\n", font->ft_face->charmap->encoding);
5912         for (n = 0; n <= 65535; n++)
5913             glyph_to_char[n] = (USHORT)n;
5914     }
5915
5916     tt_kern_table = buf;
5917     nTables = GET_BE_WORD(tt_kern_table->nTables);
5918     TRACE("version %u, nTables %u\n",
5919            GET_BE_WORD(tt_kern_table->version), nTables);
5920
5921     tt_kern_subtable = (const struct TT_kern_subtable *)(tt_kern_table + 1);
5922
5923     for (i = 0; i < nTables; i++)
5924     {
5925         struct TT_kern_subtable tt_kern_subtable_copy;
5926
5927         tt_kern_subtable_copy.version = GET_BE_WORD(tt_kern_subtable->version);
5928         tt_kern_subtable_copy.length = GET_BE_WORD(tt_kern_subtable->length);
5929         tt_kern_subtable_copy.coverage.word = GET_BE_WORD(tt_kern_subtable->coverage.word);
5930
5931         TRACE("version %u, length %u, coverage %u, subtable format %u\n",
5932                tt_kern_subtable_copy.version, tt_kern_subtable_copy.length,
5933                tt_kern_subtable_copy.coverage.word, tt_kern_subtable_copy.coverage.bits.format);
5934
5935         /* According to the TrueType specification this is the only format
5936          * that will be properly interpreted by Windows and OS/2
5937          */
5938         if (tt_kern_subtable_copy.coverage.bits.format == 0)
5939         {
5940             DWORD new_chunk, old_total = font->total_kern_pairs;
5941
5942             new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
5943                                                     glyph_to_char, NULL, 0);
5944             font->total_kern_pairs += new_chunk;
5945
5946             if (!font->kern_pairs)
5947                 font->kern_pairs = HeapAlloc(GetProcessHeap(), 0,
5948                                              font->total_kern_pairs * sizeof(*font->kern_pairs));
5949             else
5950                 font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs,
5951                                                font->total_kern_pairs * sizeof(*font->kern_pairs));
5952
5953             parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
5954                         glyph_to_char, font->kern_pairs + old_total, new_chunk);
5955         }
5956         else
5957             TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format);
5958
5959         tt_kern_subtable = (const struct TT_kern_subtable *)((const char *)tt_kern_subtable + tt_kern_subtable_copy.length);
5960     }
5961
5962     HeapFree(GetProcessHeap(), 0, glyph_to_char);
5963     HeapFree(GetProcessHeap(), 0, buf);
5964
5965     if (cPairs && kern_pair)
5966     {
5967         cPairs = min(cPairs, font->total_kern_pairs);
5968         memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
5969         LeaveCriticalSection( &freetype_cs );
5970         return cPairs;
5971     }
5972     LeaveCriticalSection( &freetype_cs );
5973     return font->total_kern_pairs;
5974 }
5975
5976 #else /* HAVE_FREETYPE */
5977
5978 /*************************************************************************/
5979
5980 BOOL WineEngInit(void)
5981 {
5982     return FALSE;
5983 }
5984 GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont)
5985 {
5986     return NULL;
5987 }
5988 BOOL WineEngDestroyFontInstance(HFONT hfont)
5989 {
5990     return FALSE;
5991 }
5992
5993 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
5994 {
5995     return 1;
5996 }
5997
5998 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
5999                                 LPWORD pgi, DWORD flags)
6000 {
6001     return GDI_ERROR;
6002 }
6003
6004 DWORD WineEngGetGlyphOutline(GdiFont *font, UINT glyph, UINT format,
6005                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
6006                              const MAT2* lpmat)
6007 {
6008     ERR("called but we don't have FreeType\n");
6009     return GDI_ERROR;
6010 }
6011
6012 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
6013 {
6014     ERR("called but we don't have FreeType\n");
6015     return FALSE;
6016 }
6017
6018 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
6019                                   OUTLINETEXTMETRICW *potm)
6020 {
6021     ERR("called but we don't have FreeType\n");
6022     return 0;
6023 }
6024
6025 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
6026                          LPINT buffer)
6027 {
6028     ERR("called but we don't have FreeType\n");
6029     return FALSE;
6030 }
6031
6032 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
6033                              LPABC buffer)
6034 {
6035     ERR("called but we don't have FreeType\n");
6036     return FALSE;
6037 }
6038
6039 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
6040                               LPABC buffer)
6041 {
6042     ERR("called but we don't have FreeType\n");
6043     return FALSE;
6044 }
6045
6046 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
6047                                  INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
6048 {
6049     ERR("called but we don't have FreeType\n");
6050     return FALSE;
6051 }
6052
6053 BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count,
6054                                   INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
6055 {
6056     ERR("called but we don't have FreeType\n");
6057     return FALSE;
6058 }
6059
6060 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
6061                          DWORD cbData)
6062 {
6063     ERR("called but we don't have FreeType\n");
6064     return GDI_ERROR;
6065 }
6066
6067 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
6068 {
6069     ERR("called but we don't have FreeType\n");
6070     return 0;
6071 }
6072
6073 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
6074 {
6075     FIXME(":stub\n");
6076     return 1;
6077 }
6078
6079 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
6080 {
6081     FIXME(":stub\n");
6082     return TRUE;
6083 }
6084
6085 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
6086 {
6087     FIXME(":stub\n");
6088     return NULL;
6089 }
6090
6091 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
6092 {
6093     FIXME(":stub\n");
6094     return DEFAULT_CHARSET;
6095 }
6096
6097 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
6098 {
6099     return FALSE;
6100 }
6101
6102 DWORD WineEngGetFontUnicodeRanges(GdiFont *font, LPGLYPHSET glyphset)
6103 {
6104     FIXME("(%p, %p): stub\n", font, glyphset);
6105     return 0;
6106 }
6107
6108 BOOL WineEngFontIsLinked(GdiFont *font)
6109 {
6110     return FALSE;
6111 }
6112
6113 /*************************************************************************
6114  *             GetRasterizerCaps   (GDI32.@)
6115  */
6116 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
6117 {
6118     lprs->nSize = sizeof(RASTERIZER_STATUS);
6119     lprs->wFlags = 0;
6120     lprs->nLanguageID = 0;
6121     return TRUE;
6122 }
6123
6124 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
6125 {
6126     ERR("called but we don't have FreeType\n");
6127     return 0;
6128 }
6129
6130 #endif /* HAVE_FREETYPE */