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