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