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