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