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