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