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