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