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