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