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