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