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