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