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