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