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