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