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