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