mmdevapi/tests: Add tests for volume control interfaces.
[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     {
4558         /* there is a number of old pre-Unicode "broken" TTFs, which
4559            do have symbols at U+00XX instead of U+f0XX */
4560         if (!(glyphId = pFT_Get_Char_Index(font->ft_face, glyph + 0xf000)))
4561             glyphId = pFT_Get_Char_Index(font->ft_face, glyph);
4562     }
4563     else glyphId = pFT_Get_Char_Index(font->ft_face, glyph);
4564
4565     return get_GSUB_vert_glyph(font,glyphId);
4566 }
4567
4568 /*************************************************************
4569  * WineEngGetGlyphIndices
4570  *
4571  */
4572 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
4573                                 LPWORD pgi, DWORD flags)
4574 {
4575     int i;
4576     int default_char = -1;
4577
4578     if  (flags & GGI_MARK_NONEXISTING_GLYPHS) default_char = 0xffff;  /* XP would use 0x1f for bitmap fonts */
4579
4580     for(i = 0; i < count; i++)
4581     {
4582         pgi[i] = get_glyph_index(font, lpstr[i]);
4583         if  (pgi[i] == 0)
4584         {
4585             if (default_char == -1)
4586             {
4587                 if (FT_IS_SFNT(font->ft_face))
4588                 {
4589                     TT_OS2 *pOS2 = pFT_Get_Sfnt_Table(font->ft_face, ft_sfnt_os2);
4590                     default_char = (pOS2->usDefaultChar ? get_glyph_index(font, pOS2->usDefaultChar) : 0);
4591                 }
4592                 else
4593                 {
4594                     TEXTMETRICW textm;
4595                     WineEngGetTextMetrics(font, &textm);
4596                     default_char = textm.tmDefaultChar;
4597                 }
4598             }
4599             pgi[i] = default_char;
4600         }
4601     }
4602     return count;
4603 }
4604
4605 static inline BOOL is_identity_FMAT2(const FMAT2 *matrix)
4606 {
4607     static const FMAT2 identity = { 1.0, 0.0, 0.0, 1.0 };
4608     return !memcmp(matrix, &identity, sizeof(FMAT2));
4609 }
4610
4611 static inline BOOL is_identity_MAT2(const MAT2 *matrix)
4612 {
4613     static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
4614     return !memcmp(matrix, &identity, sizeof(MAT2));
4615 }
4616
4617 /*************************************************************
4618  * WineEngGetGlyphOutline
4619  *
4620  * Behaves in exactly the same way as the win32 api GetGlyphOutline
4621  * except that the first parameter is the HWINEENGFONT of the font in
4622  * question rather than an HDC.
4623  *
4624  */
4625 DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
4626                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
4627                              const MAT2* lpmat)
4628 {
4629     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
4630     FT_Face ft_face = incoming_font->ft_face;
4631     GdiFont *font = incoming_font;
4632     FT_UInt glyph_index;
4633     DWORD width, height, pitch, needed = 0;
4634     FT_Bitmap ft_bitmap;
4635     FT_Error err;
4636     INT left, right, top = 0, bottom = 0, adv, lsb, bbx;
4637     FT_Angle angle = 0;
4638     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
4639     double widthRatio = 1.0;
4640     FT_Matrix transMat = identityMat;
4641     FT_Matrix transMatUnrotated;
4642     BOOL needsTransform = FALSE;
4643     BOOL tategaki = (font->GSUB_Table != NULL);
4644     UINT original_index;
4645
4646     TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
4647           buflen, buf, lpmat);
4648
4649     TRACE("font transform %f %f %f %f\n",
4650           font->font_desc.matrix.eM11, font->font_desc.matrix.eM12,
4651           font->font_desc.matrix.eM21, font->font_desc.matrix.eM22);
4652
4653     GDI_CheckNotLock();
4654     EnterCriticalSection( &freetype_cs );
4655
4656     if(format & GGO_GLYPH_INDEX) {
4657         glyph_index = get_GSUB_vert_glyph(incoming_font,glyph);
4658         original_index = glyph;
4659         format &= ~GGO_GLYPH_INDEX;
4660     } else {
4661         get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index);
4662         ft_face = font->ft_face;
4663         original_index = glyph_index;
4664     }
4665
4666     if(format & GGO_UNHINTED) {
4667         load_flags |= FT_LOAD_NO_HINTING;
4668         format &= ~GGO_UNHINTED;
4669     }
4670
4671     /* tategaki never appears to happen to lower glyph index */
4672     if (glyph_index < TATEGAKI_LOWER_BOUND )
4673         tategaki = FALSE;
4674
4675     if(original_index >= font->gmsize * GM_BLOCK_SIZE) {
4676         font->gmsize = (original_index / GM_BLOCK_SIZE + 1);
4677         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
4678                                font->gmsize * sizeof(GM*));
4679     } else {
4680         if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL &&
4681             FONT_GM(font,original_index)->init && is_identity_MAT2(lpmat))
4682         {
4683             *lpgm = FONT_GM(font,original_index)->gm;
4684             TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
4685                   wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
4686                   lpgm->gmCellIncX, lpgm->gmCellIncY);
4687             LeaveCriticalSection( &freetype_cs );
4688             return 1; /* FIXME */
4689         }
4690     }
4691
4692     if (!font->gm[original_index / GM_BLOCK_SIZE])
4693         font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
4694
4695     /* Scaling factor */
4696     if (font->aveWidth)
4697     {
4698         TEXTMETRICW tm;
4699
4700         WineEngGetTextMetrics(font, &tm);
4701
4702         widthRatio = (double)font->aveWidth;
4703         widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
4704     }
4705     else
4706         widthRatio = font->scale_y;
4707
4708     /* Scaling transform */
4709     if (widthRatio != 1.0 || font->scale_y != 1.0)
4710     {
4711         FT_Matrix scaleMat;
4712         scaleMat.xx = FT_FixedFromFloat(widthRatio);
4713         scaleMat.xy = 0;
4714         scaleMat.yx = 0;
4715         scaleMat.yy = FT_FixedFromFloat(font->scale_y);
4716
4717         pFT_Matrix_Multiply(&scaleMat, &transMat);
4718         needsTransform = TRUE;
4719     }
4720
4721     /* Slant transform */
4722     if (font->fake_italic) {
4723         FT_Matrix slantMat;
4724         
4725         slantMat.xx = (1 << 16);
4726         slantMat.xy = ((1 << 16) >> 2);
4727         slantMat.yx = 0;
4728         slantMat.yy = (1 << 16);
4729         pFT_Matrix_Multiply(&slantMat, &transMat);
4730         needsTransform = TRUE;
4731     }
4732
4733     /* Rotation transform */
4734     transMatUnrotated = transMat;
4735     if(font->orientation && !tategaki) {
4736         FT_Matrix rotationMat;
4737         FT_Vector vecAngle;
4738         angle = FT_FixedFromFloat((double)font->orientation / 10.0);
4739         pFT_Vector_Unit(&vecAngle, angle);
4740         rotationMat.xx = vecAngle.x;
4741         rotationMat.xy = -vecAngle.y;
4742         rotationMat.yx = -rotationMat.xy;
4743         rotationMat.yy = rotationMat.xx;
4744         
4745         pFT_Matrix_Multiply(&rotationMat, &transMat);
4746         needsTransform = TRUE;
4747     }
4748
4749     /* World transform */
4750     if (!is_identity_FMAT2(&font->font_desc.matrix))
4751     {
4752         FT_Matrix worldMat;
4753         worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11);
4754         worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM12);
4755         worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM21);
4756         worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22);
4757         pFT_Matrix_Multiply(&worldMat, &transMat);
4758         pFT_Matrix_Multiply(&worldMat, &transMatUnrotated);
4759         needsTransform = TRUE;
4760     }
4761
4762     /* Extra transformation specified by caller */
4763     if (!is_identity_MAT2(lpmat))
4764     {
4765         FT_Matrix extraMat;
4766         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
4767         extraMat.xy = FT_FixedFromFIXED(lpmat->eM12);
4768         extraMat.yx = FT_FixedFromFIXED(lpmat->eM21);
4769         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
4770         pFT_Matrix_Multiply(&extraMat, &transMat);
4771         pFT_Matrix_Multiply(&extraMat, &transMatUnrotated);
4772         needsTransform = TRUE;
4773     }
4774
4775     if (needsTransform || (format == GGO_NATIVE || format == GGO_BEZIER ||
4776                            format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
4777                            format == GGO_GRAY8_BITMAP))
4778     {
4779         load_flags |= FT_LOAD_NO_BITMAP;
4780     }
4781
4782     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
4783
4784     if(err) {
4785         WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
4786         LeaveCriticalSection( &freetype_cs );
4787         return GDI_ERROR;
4788     }
4789
4790     if(!needsTransform) {
4791         left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64;
4792         right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64;
4793         adv = (INT)(ft_face->glyph->metrics.horiAdvance + 63) >> 6;
4794
4795         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
4796         bottom = (ft_face->glyph->metrics.horiBearingY -
4797                   ft_face->glyph->metrics.height) & -64;
4798         lpgm->gmCellIncX = adv;
4799         lpgm->gmCellIncY = 0;
4800     } else {
4801         INT xc, yc;
4802         FT_Vector vec;
4803
4804         left = right = 0;
4805
4806         for(xc = 0; xc < 2; xc++) {
4807             for(yc = 0; yc < 2; yc++) {
4808                 vec.x = (ft_face->glyph->metrics.horiBearingX +
4809                   xc * ft_face->glyph->metrics.width);
4810                 vec.y = ft_face->glyph->metrics.horiBearingY -
4811                   yc * ft_face->glyph->metrics.height;
4812                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
4813                 pFT_Vector_Transform(&vec, &transMat);
4814                 if(xc == 0 && yc == 0) {
4815                     left = right = vec.x;
4816                     top = bottom = vec.y;
4817                 } else {
4818                     if(vec.x < left) left = vec.x;
4819                     else if(vec.x > right) right = vec.x;
4820                     if(vec.y < bottom) bottom = vec.y;
4821                     else if(vec.y > top) top = vec.y;
4822                 }
4823             }
4824         }
4825         left = left & -64;
4826         right = (right + 63) & -64;
4827         bottom = bottom & -64;
4828         top = (top + 63) & -64;
4829
4830         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
4831         vec.x = ft_face->glyph->metrics.horiAdvance;
4832         vec.y = 0;
4833         pFT_Vector_Transform(&vec, &transMat);
4834         lpgm->gmCellIncX = (vec.x+63) >> 6;
4835         lpgm->gmCellIncY = -((vec.y+63) >> 6);
4836
4837         vec.x = ft_face->glyph->metrics.horiAdvance;
4838         vec.y = 0;
4839         pFT_Vector_Transform(&vec, &transMatUnrotated);
4840         adv = (vec.x+63) >> 6;
4841     }
4842
4843     lsb = left >> 6;
4844     bbx = (right - left) >> 6;
4845     lpgm->gmBlackBoxX = (right - left) >> 6;
4846     lpgm->gmBlackBoxY = (top - bottom) >> 6;
4847     lpgm->gmptGlyphOrigin.x = left >> 6;
4848     lpgm->gmptGlyphOrigin.y = top >> 6;
4849
4850     TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
4851           wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
4852           lpgm->gmCellIncX, lpgm->gmCellIncY);
4853
4854     if ((format == GGO_METRICS || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
4855         is_identity_MAT2(lpmat)) /* don't cache custom transforms */
4856     {
4857         FONT_GM(font,original_index)->gm = *lpgm;
4858         FONT_GM(font,original_index)->adv = adv;
4859         FONT_GM(font,original_index)->lsb = lsb;
4860         FONT_GM(font,original_index)->bbx = bbx;
4861         FONT_GM(font,original_index)->init = TRUE;
4862     }
4863
4864     if(format == GGO_METRICS)
4865     {
4866         LeaveCriticalSection( &freetype_cs );
4867         return 1; /* FIXME */
4868     }
4869
4870     if(ft_face->glyph->format != ft_glyph_format_outline &&
4871        (format == GGO_NATIVE || format == GGO_BEZIER ||
4872         format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
4873         format == GGO_GRAY8_BITMAP))
4874     {
4875         TRACE("loaded a bitmap\n");
4876         LeaveCriticalSection( &freetype_cs );
4877         return GDI_ERROR;
4878     }
4879
4880     switch(format) {
4881     case GGO_BITMAP:
4882         width = lpgm->gmBlackBoxX;
4883         height = lpgm->gmBlackBoxY;
4884         pitch = ((width + 31) >> 5) << 2;
4885         needed = pitch * height;
4886
4887         if(!buf || !buflen) break;
4888
4889         switch(ft_face->glyph->format) {
4890         case ft_glyph_format_bitmap:
4891           {
4892             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
4893             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
4894             INT h = ft_face->glyph->bitmap.rows;
4895             while(h--) {
4896                 memcpy(dst, src, w);
4897                 src += ft_face->glyph->bitmap.pitch;
4898                 dst += pitch;
4899             }
4900             break;
4901           }
4902
4903         case ft_glyph_format_outline:
4904             ft_bitmap.width = width;
4905             ft_bitmap.rows = height;
4906             ft_bitmap.pitch = pitch;
4907             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
4908             ft_bitmap.buffer = buf;
4909
4910             if(needsTransform)
4911                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4912
4913             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4914
4915             /* Note: FreeType will only set 'black' bits for us. */
4916             memset(buf, 0, needed);
4917             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
4918             break;
4919
4920         default:
4921             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
4922             LeaveCriticalSection( &freetype_cs );
4923             return GDI_ERROR;
4924         }
4925         break;
4926
4927     case GGO_GRAY2_BITMAP:
4928     case GGO_GRAY4_BITMAP:
4929     case GGO_GRAY8_BITMAP:
4930     case WINE_GGO_GRAY16_BITMAP:
4931       {
4932         unsigned int mult, row, col;
4933         BYTE *start, *ptr;
4934
4935         width = lpgm->gmBlackBoxX;
4936         height = lpgm->gmBlackBoxY;
4937         pitch = (width + 3) / 4 * 4;
4938         needed = pitch * height;
4939
4940         if(!buf || !buflen) break;
4941
4942         switch(ft_face->glyph->format) {
4943         case ft_glyph_format_bitmap:
4944           {
4945             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
4946             INT h = ft_face->glyph->bitmap.rows;
4947             INT x;
4948             memset( buf, 0, needed );
4949             while(h--) {
4950                 for(x = 0; x < pitch && x < ft_face->glyph->bitmap.width; x++)
4951                     if (src[x / 8] & (1 << ( (7 - (x % 8))))) dst[x] = 0xff;
4952                 src += ft_face->glyph->bitmap.pitch;
4953                 dst += pitch;
4954             }
4955             LeaveCriticalSection( &freetype_cs );
4956             return needed;
4957           }
4958         case ft_glyph_format_outline:
4959           {
4960             ft_bitmap.width = width;
4961             ft_bitmap.rows = height;
4962             ft_bitmap.pitch = pitch;
4963             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
4964             ft_bitmap.buffer = buf;
4965
4966             if(needsTransform)
4967                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4968
4969             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4970
4971             memset(ft_bitmap.buffer, 0, buflen);
4972
4973             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
4974
4975             if(format == GGO_GRAY2_BITMAP)
4976                 mult = 4;
4977             else if(format == GGO_GRAY4_BITMAP)
4978                 mult = 16;
4979             else if(format == GGO_GRAY8_BITMAP)
4980                 mult = 64;
4981             else /* format == WINE_GGO_GRAY16_BITMAP */
4982             {
4983                 LeaveCriticalSection( &freetype_cs );
4984                 return needed;
4985             }
4986             break;
4987           }
4988         default:
4989             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
4990             LeaveCriticalSection( &freetype_cs );
4991             return GDI_ERROR;
4992         }
4993
4994         start = buf;
4995         for(row = 0; row < height; row++) {
4996             ptr = start;
4997             for(col = 0; col < width; col++, ptr++) {
4998                 *ptr = (((int)*ptr) * mult + 128) / 256;
4999             }
5000             start += pitch;
5001         }
5002         break;
5003       }
5004
5005     case WINE_GGO_HRGB_BITMAP:
5006     case WINE_GGO_HBGR_BITMAP:
5007     case WINE_GGO_VRGB_BITMAP:
5008     case WINE_GGO_VBGR_BITMAP:
5009 #ifdef HAVE_FREETYPE_FTLCDFIL_H
5010       {
5011         switch (ft_face->glyph->format)
5012         {
5013         case FT_GLYPH_FORMAT_BITMAP:
5014           {
5015             BYTE *src, *dst;
5016             INT src_pitch, x;
5017
5018             width  = lpgm->gmBlackBoxX;
5019             height = lpgm->gmBlackBoxY;
5020             pitch  = width * 4;
5021             needed = pitch * height;
5022
5023             if (!buf || !buflen) break;
5024
5025             memset(buf, 0, buflen);
5026             dst = buf;
5027             src = ft_face->glyph->bitmap.buffer;
5028             src_pitch = ft_face->glyph->bitmap.pitch;
5029
5030             height = min( height, ft_face->glyph->bitmap.rows );
5031             while ( height-- )
5032             {
5033                 for (x = 0; x < width && x < ft_face->glyph->bitmap.width; x++)
5034                 {
5035                     if ( src[x / 8] & (1 << ( (7 - (x % 8)))) )
5036                         ((unsigned int *)dst)[x] = ~0u;
5037                 }
5038                 src += src_pitch;
5039                 dst += pitch;
5040             }
5041
5042             break;
5043           }
5044
5045         case FT_GLYPH_FORMAT_OUTLINE:
5046           {
5047             unsigned int *dst;
5048             BYTE *src;
5049             INT x, src_pitch, src_width, src_height, rgb_interval, hmul, vmul;
5050             INT x_shift, y_shift;
5051             BOOL rgb;
5052             FT_LcdFilter lcdfilter = FT_LCD_FILTER_DEFAULT;
5053             FT_Render_Mode render_mode =
5054                 (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_HBGR_BITMAP)?
5055                     FT_RENDER_MODE_LCD: FT_RENDER_MODE_LCD_V;
5056
5057             if ( lcdfilter == FT_LCD_FILTER_DEFAULT || lcdfilter == FT_LCD_FILTER_LIGHT )
5058             {
5059                 if ( render_mode == FT_RENDER_MODE_LCD)
5060                 {
5061                     lpgm->gmBlackBoxX += 2;
5062                     lpgm->gmptGlyphOrigin.x -= 1;
5063                 }
5064                 else
5065                 {
5066                     lpgm->gmBlackBoxY += 2;
5067                     lpgm->gmptGlyphOrigin.y += 1;
5068                 }
5069             }
5070
5071             width  = lpgm->gmBlackBoxX;
5072             height = lpgm->gmBlackBoxY;
5073             pitch  = width * 4;
5074             needed = pitch * height;
5075
5076             if (!buf || !buflen) break;
5077
5078             memset(buf, 0, buflen);
5079             dst = buf;
5080             rgb = (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_VRGB_BITMAP);
5081
5082             if ( needsTransform )
5083                 pFT_Outline_Transform (&ft_face->glyph->outline, &transMat);
5084
5085             if ( pFT_Library_SetLcdFilter )
5086                 pFT_Library_SetLcdFilter( library, lcdfilter );
5087             pFT_Render_Glyph (ft_face->glyph, render_mode);
5088
5089             src = ft_face->glyph->bitmap.buffer;
5090             src_pitch = ft_face->glyph->bitmap.pitch;
5091             src_width = ft_face->glyph->bitmap.width;
5092             src_height = ft_face->glyph->bitmap.rows;
5093
5094             if ( render_mode == FT_RENDER_MODE_LCD)
5095             {
5096                 rgb_interval = 1;
5097                 hmul = 3;
5098                 vmul = 1;
5099             }
5100             else
5101             {
5102                 rgb_interval = src_pitch;
5103                 hmul = 1;
5104                 vmul = 3;
5105             }
5106
5107             x_shift = ft_face->glyph->bitmap_left - lpgm->gmptGlyphOrigin.x;
5108             if ( x_shift < 0 ) x_shift = 0;
5109             if ( x_shift + (src_width / hmul) > width )
5110                 x_shift = width - (src_width / hmul);
5111
5112             y_shift = lpgm->gmptGlyphOrigin.y - ft_face->glyph->bitmap_top;
5113             if ( y_shift < 0 ) y_shift = 0;
5114             if ( y_shift + (src_height / vmul) > height )
5115                 y_shift = height - (src_height / vmul);
5116
5117             dst += x_shift + y_shift * ( pitch / 4 );
5118             while ( src_height )
5119             {
5120                 for ( x = 0; x < src_width / hmul; x++ )
5121                 {
5122                     if ( rgb )
5123                     {
5124                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 0] << 16) |
5125                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
5126                                  ((unsigned int)src[hmul * x + rgb_interval * 2] <<  0) |
5127                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
5128                     }
5129                     else
5130                     {
5131                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 2] << 16) |
5132                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
5133                                  ((unsigned int)src[hmul * x + rgb_interval * 0] <<  0) |
5134                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
5135                     }
5136                 }
5137                 src += src_pitch * vmul;
5138                 dst += pitch / 4;
5139                 src_height -= vmul;
5140             }
5141
5142             break;
5143           }
5144
5145         default:
5146             FIXME ("loaded glyph format %x\n", ft_face->glyph->format);
5147             LeaveCriticalSection ( &freetype_cs );
5148             return GDI_ERROR;
5149         }
5150
5151         break;
5152       }
5153 #else
5154       LeaveCriticalSection( &freetype_cs );
5155       return GDI_ERROR;
5156 #endif
5157
5158     case GGO_NATIVE:
5159       {
5160         int contour, point = 0, first_pt;
5161         FT_Outline *outline = &ft_face->glyph->outline;
5162         TTPOLYGONHEADER *pph;
5163         TTPOLYCURVE *ppc;
5164         DWORD pph_start, cpfx, type;
5165
5166         if(buflen == 0) buf = NULL;
5167
5168         if (needsTransform && buf) {
5169                 pFT_Outline_Transform(outline, &transMat);
5170         }
5171
5172         for(contour = 0; contour < outline->n_contours; contour++) {
5173             pph_start = needed;
5174             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
5175             first_pt = point;
5176             if(buf) {
5177                 pph->dwType = TT_POLYGON_TYPE;
5178                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
5179             }
5180             needed += sizeof(*pph);
5181             point++;
5182             while(point <= outline->contours[contour]) {
5183                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
5184                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
5185                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
5186                 cpfx = 0;
5187                 do {
5188                     if(buf)
5189                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
5190                     cpfx++;
5191                     point++;
5192                 } while(point <= outline->contours[contour] &&
5193                         (outline->tags[point] & FT_Curve_Tag_On) ==
5194                         (outline->tags[point-1] & FT_Curve_Tag_On));
5195                 /* At the end of a contour Windows adds the start point, but
5196                    only for Beziers */
5197                 if(point > outline->contours[contour] &&
5198                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
5199                     if(buf)
5200                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
5201                     cpfx++;
5202                 } else if(point <= outline->contours[contour] &&
5203                           outline->tags[point] & FT_Curve_Tag_On) {
5204                   /* add closing pt for bezier */
5205                     if(buf)
5206                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
5207                     cpfx++;
5208                     point++;
5209                 }
5210                 if(buf) {
5211                     ppc->wType = type;
5212                     ppc->cpfx = cpfx;
5213                 }
5214                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
5215             }
5216             if(buf)
5217                 pph->cb = needed - pph_start;
5218         }
5219         break;
5220       }
5221     case GGO_BEZIER:
5222       {
5223         /* Convert the quadratic Beziers to cubic Beziers.
5224            The parametric eqn for a cubic Bezier is, from PLRM:
5225            r(t) = at^3 + bt^2 + ct + r0
5226            with the control points:
5227            r1 = r0 + c/3
5228            r2 = r1 + (c + b)/3
5229            r3 = r0 + c + b + a
5230
5231            A quadratic Beizer has the form:
5232            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
5233
5234            So equating powers of t leads to:
5235            r1 = 2/3 p1 + 1/3 p0
5236            r2 = 2/3 p1 + 1/3 p2
5237            and of course r0 = p0, r3 = p2
5238         */
5239
5240         int contour, point = 0, first_pt;
5241         FT_Outline *outline = &ft_face->glyph->outline;
5242         TTPOLYGONHEADER *pph;
5243         TTPOLYCURVE *ppc;
5244         DWORD pph_start, cpfx, type;
5245         FT_Vector cubic_control[4];
5246         if(buflen == 0) buf = NULL;
5247
5248         if (needsTransform && buf) {
5249                 pFT_Outline_Transform(outline, &transMat);
5250         }
5251
5252         for(contour = 0; contour < outline->n_contours; contour++) {
5253             pph_start = needed;
5254             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
5255             first_pt = point;
5256             if(buf) {
5257                 pph->dwType = TT_POLYGON_TYPE;
5258                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
5259             }
5260             needed += sizeof(*pph);
5261             point++;
5262             while(point <= outline->contours[contour]) {
5263                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
5264                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
5265                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
5266                 cpfx = 0;
5267                 do {
5268                     if(type == TT_PRIM_LINE) {
5269                         if(buf)
5270                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
5271                         cpfx++;
5272                         point++;
5273                     } else {
5274                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
5275                          so cpfx = 3n */
5276
5277                       /* FIXME: Possible optimization in endpoint calculation
5278                          if there are two consecutive curves */
5279                         cubic_control[0] = outline->points[point-1];
5280                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
5281                             cubic_control[0].x += outline->points[point].x + 1;
5282                             cubic_control[0].y += outline->points[point].y + 1;
5283                             cubic_control[0].x >>= 1;
5284                             cubic_control[0].y >>= 1;
5285                         }
5286                         if(point+1 > outline->contours[contour])
5287                             cubic_control[3] = outline->points[first_pt];
5288                         else {
5289                             cubic_control[3] = outline->points[point+1];
5290                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
5291                                 cubic_control[3].x += outline->points[point].x + 1;
5292                                 cubic_control[3].y += outline->points[point].y + 1;
5293                                 cubic_control[3].x >>= 1;
5294                                 cubic_control[3].y >>= 1;
5295                             }
5296                         }
5297                         /* r1 = 1/3 p0 + 2/3 p1
5298                            r2 = 1/3 p2 + 2/3 p1 */
5299                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
5300                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
5301                         cubic_control[2] = cubic_control[1];
5302                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
5303                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
5304                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
5305                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
5306                         if(buf) {
5307                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
5308                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
5309                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
5310                         }
5311                         cpfx += 3;
5312                         point++;
5313                     }
5314                 } while(point <= outline->contours[contour] &&
5315                         (outline->tags[point] & FT_Curve_Tag_On) ==
5316                         (outline->tags[point-1] & FT_Curve_Tag_On));
5317                 /* At the end of a contour Windows adds the start point,
5318                    but only for Beziers and we've already done that.
5319                 */
5320                 if(point <= outline->contours[contour] &&
5321                    outline->tags[point] & FT_Curve_Tag_On) {
5322                   /* This is the closing pt of a bezier, but we've already
5323                      added it, so just inc point and carry on */
5324                     point++;
5325                 }
5326                 if(buf) {
5327                     ppc->wType = type;
5328                     ppc->cpfx = cpfx;
5329                 }
5330                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
5331             }
5332             if(buf)
5333                 pph->cb = needed - pph_start;
5334         }
5335         break;
5336       }
5337
5338     default:
5339         FIXME("Unsupported format %d\n", format);
5340         LeaveCriticalSection( &freetype_cs );
5341         return GDI_ERROR;
5342     }
5343     LeaveCriticalSection( &freetype_cs );
5344     return needed;
5345 }
5346
5347 static BOOL get_bitmap_text_metrics(GdiFont *font)
5348 {
5349     FT_Face ft_face = font->ft_face;
5350 #ifdef HAVE_FREETYPE_FTWINFNT_H
5351     FT_WinFNT_HeaderRec winfnt_header;
5352 #endif
5353     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
5354     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
5355     font->potm->otmSize = size;
5356
5357 #define TM font->potm->otmTextMetrics
5358 #ifdef HAVE_FREETYPE_FTWINFNT_H
5359     if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
5360     {
5361         TM.tmHeight = winfnt_header.pixel_height;
5362         TM.tmAscent = winfnt_header.ascent;
5363         TM.tmDescent = TM.tmHeight - TM.tmAscent;
5364         TM.tmInternalLeading = winfnt_header.internal_leading;
5365         TM.tmExternalLeading = winfnt_header.external_leading;
5366         TM.tmAveCharWidth = winfnt_header.avg_width;
5367         TM.tmMaxCharWidth = winfnt_header.max_width;
5368         TM.tmWeight = winfnt_header.weight;
5369         TM.tmOverhang = 0;
5370         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
5371         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
5372         TM.tmFirstChar = winfnt_header.first_char;
5373         TM.tmLastChar = winfnt_header.last_char;
5374         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
5375         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
5376         TM.tmItalic = winfnt_header.italic;
5377         TM.tmUnderlined = font->underline;
5378         TM.tmStruckOut = font->strikeout;
5379         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
5380         TM.tmCharSet = winfnt_header.charset;
5381     }
5382     else
5383 #endif
5384     {
5385         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
5386         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
5387         TM.tmHeight = TM.tmAscent + TM.tmDescent;
5388         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
5389         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
5390         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
5391         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
5392         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
5393         TM.tmOverhang = 0;
5394         TM.tmDigitizedAspectX = 96; /* FIXME */
5395         TM.tmDigitizedAspectY = 96; /* FIXME */
5396         TM.tmFirstChar = 1;
5397         TM.tmLastChar = 255;
5398         TM.tmDefaultChar = 32;
5399         TM.tmBreakChar = 32;
5400         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
5401         TM.tmUnderlined = font->underline;
5402         TM.tmStruckOut = font->strikeout;
5403         /* NB inverted meaning of TMPF_FIXED_PITCH */
5404         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
5405         TM.tmCharSet = font->charset;
5406     }
5407 #undef TM
5408
5409     return TRUE;
5410 }
5411
5412
5413 static void scale_font_metrics(const GdiFont *font, LPTEXTMETRICW ptm)
5414 {
5415     double scale_x, scale_y;
5416
5417     if (font->aveWidth)
5418     {
5419         scale_x = (double)font->aveWidth;
5420         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5421     }
5422     else
5423         scale_x = font->scale_y;
5424
5425     scale_x *= fabs(font->font_desc.matrix.eM11);
5426     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
5427
5428 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
5429 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
5430
5431     SCALE_Y(ptm->tmHeight);
5432     SCALE_Y(ptm->tmAscent);
5433     SCALE_Y(ptm->tmDescent);
5434     SCALE_Y(ptm->tmInternalLeading);
5435     SCALE_Y(ptm->tmExternalLeading);
5436     SCALE_Y(ptm->tmOverhang);
5437
5438     SCALE_X(ptm->tmAveCharWidth);
5439     SCALE_X(ptm->tmMaxCharWidth);
5440
5441 #undef SCALE_X
5442 #undef SCALE_Y
5443 }
5444
5445 static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *potm)
5446 {
5447     double scale_x, scale_y;
5448
5449     if (font->aveWidth)
5450     {
5451         scale_x = (double)font->aveWidth;
5452         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5453     }
5454     else
5455         scale_x = font->scale_y;
5456
5457     scale_x *= fabs(font->font_desc.matrix.eM11);
5458     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
5459
5460     scale_font_metrics(font, &potm->otmTextMetrics);
5461
5462 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
5463 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
5464
5465     SCALE_Y(potm->otmAscent);
5466     SCALE_Y(potm->otmDescent);
5467     SCALE_Y(potm->otmLineGap);
5468     SCALE_Y(potm->otmsCapEmHeight);
5469     SCALE_Y(potm->otmsXHeight);
5470     SCALE_Y(potm->otmrcFontBox.top);
5471     SCALE_Y(potm->otmrcFontBox.bottom);
5472     SCALE_X(potm->otmrcFontBox.left);
5473     SCALE_X(potm->otmrcFontBox.right);
5474     SCALE_Y(potm->otmMacAscent);
5475     SCALE_Y(potm->otmMacDescent);
5476     SCALE_Y(potm->otmMacLineGap);
5477     SCALE_X(potm->otmptSubscriptSize.x);
5478     SCALE_Y(potm->otmptSubscriptSize.y);
5479     SCALE_X(potm->otmptSubscriptOffset.x);
5480     SCALE_Y(potm->otmptSubscriptOffset.y);
5481     SCALE_X(potm->otmptSuperscriptSize.x);
5482     SCALE_Y(potm->otmptSuperscriptSize.y);
5483     SCALE_X(potm->otmptSuperscriptOffset.x);
5484     SCALE_Y(potm->otmptSuperscriptOffset.y);
5485     SCALE_Y(potm->otmsStrikeoutSize);
5486     SCALE_Y(potm->otmsStrikeoutPosition);
5487     SCALE_Y(potm->otmsUnderscoreSize);
5488     SCALE_Y(potm->otmsUnderscorePosition);
5489
5490 #undef SCALE_X
5491 #undef SCALE_Y
5492 }
5493
5494 /*************************************************************
5495  * WineEngGetTextMetrics
5496  *
5497  */
5498 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
5499 {
5500     GDI_CheckNotLock();
5501     EnterCriticalSection( &freetype_cs );
5502     if(!font->potm) {
5503         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
5504             if(!get_bitmap_text_metrics(font))
5505             {
5506                 LeaveCriticalSection( &freetype_cs );
5507                 return FALSE;
5508             }
5509
5510         /* Make sure that the font has sane width/height ratio */
5511         if (font->aveWidth)
5512         {
5513             if ((font->aveWidth + font->potm->otmTextMetrics.tmHeight - 1) / font->potm->otmTextMetrics.tmHeight > 100)
5514             {
5515                 WARN("Ignoring too large font->aveWidth %d\n", font->aveWidth);
5516                 font->aveWidth = 0;
5517             }
5518         }
5519     }
5520
5521     *ptm = font->potm->otmTextMetrics;
5522     scale_font_metrics(font, ptm);
5523     LeaveCriticalSection( &freetype_cs );
5524     return TRUE;
5525 }
5526
5527 static BOOL face_has_symbol_charmap(FT_Face ft_face)
5528 {
5529     int i;
5530
5531     for(i = 0; i < ft_face->num_charmaps; i++)
5532     {
5533         if(ft_face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
5534             return TRUE;
5535     }
5536     return FALSE;
5537 }
5538
5539 /*************************************************************
5540  * WineEngGetOutlineTextMetrics
5541  *
5542  */
5543 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
5544                                   OUTLINETEXTMETRICW *potm)
5545 {
5546     FT_Face ft_face = font->ft_face;
5547     UINT needed, lenfam, lensty, ret;
5548     TT_OS2 *pOS2;
5549     TT_HoriHeader *pHori;
5550     TT_Postscript *pPost;
5551     FT_Fixed x_scale, y_scale;
5552     WCHAR *family_nameW, *style_nameW;
5553     static const WCHAR spaceW[] = {' ', '\0'};
5554     char *cp;
5555     INT ascent, descent;
5556
5557     TRACE("font=%p\n", font);
5558
5559     if(!FT_IS_SCALABLE(ft_face))
5560         return 0;
5561
5562     GDI_CheckNotLock();
5563     EnterCriticalSection( &freetype_cs );
5564
5565     if(font->potm) {
5566         if(cbSize >= font->potm->otmSize)
5567         {
5568             memcpy(potm, font->potm, font->potm->otmSize);
5569             scale_outline_font_metrics(font, potm);
5570         }
5571         LeaveCriticalSection( &freetype_cs );
5572         return font->potm->otmSize;
5573     }
5574
5575
5576     needed = sizeof(*potm);
5577
5578     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
5579     family_nameW = strdupW(font->name);
5580
5581     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
5582       * sizeof(WCHAR);
5583     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
5584     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
5585                         style_nameW, lensty/sizeof(WCHAR));
5586
5587     /* These names should be read from the TT name table */
5588
5589     /* length of otmpFamilyName */
5590     needed += lenfam;
5591
5592     /* length of otmpFaceName */
5593     if ((ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) == 0) {
5594       needed += lenfam; /* just the family name */
5595     } else {
5596       needed += lenfam + lensty; /* family + " " + style */
5597     }
5598
5599     /* length of otmpStyleName */
5600     needed += lensty;
5601
5602     /* length of otmpFullName */
5603     needed += lenfam + lensty;
5604
5605
5606     x_scale = ft_face->size->metrics.x_scale;
5607     y_scale = ft_face->size->metrics.y_scale;
5608
5609     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
5610     if(!pOS2) {
5611         FIXME("Can't find OS/2 table - not TT font?\n");
5612         ret = 0;
5613         goto end;
5614     }
5615
5616     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
5617     if(!pHori) {
5618         FIXME("Can't find HHEA table - not TT font?\n");
5619         ret = 0;
5620         goto end;
5621     }
5622
5623     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
5624
5625     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",
5626           pOS2->usWinAscent, pOS2->usWinDescent,
5627           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
5628           ft_face->ascender, ft_face->descender, ft_face->height,
5629           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
5630           ft_face->bbox.yMax, ft_face->bbox.yMin);
5631
5632     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
5633     font->potm->otmSize = needed;
5634
5635 #define TM font->potm->otmTextMetrics
5636
5637     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
5638         ascent = pHori->Ascender;
5639         descent = -pHori->Descender;
5640     } else {
5641         ascent = pOS2->usWinAscent;
5642         descent = pOS2->usWinDescent;
5643     }
5644
5645     if(font->yMax) {
5646         TM.tmAscent = font->yMax;
5647         TM.tmDescent = -font->yMin;
5648         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
5649     } else {
5650         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
5651         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
5652         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
5653                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
5654     }
5655
5656     TM.tmHeight = TM.tmAscent + TM.tmDescent;
5657
5658     /* MSDN says:
5659      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
5660     */
5661     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
5662                  ((ascent + descent) -
5663                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
5664
5665     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
5666     if (TM.tmAveCharWidth == 0) {
5667         TM.tmAveCharWidth = 1; 
5668     }
5669     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
5670     TM.tmWeight = FW_REGULAR;
5671     if (font->fake_bold)
5672         TM.tmWeight = FW_BOLD;
5673     else
5674     {
5675         if (ft_face->style_flags & FT_STYLE_FLAG_BOLD)
5676         {
5677             if (pOS2->usWeightClass > FW_MEDIUM)
5678                 TM.tmWeight = pOS2->usWeightClass;
5679         }
5680         else if (pOS2->usWeightClass <= FW_MEDIUM)
5681             TM.tmWeight = pOS2->usWeightClass;
5682     }
5683     TM.tmOverhang = 0;
5684     TM.tmDigitizedAspectX = 300;
5685     TM.tmDigitizedAspectY = 300;
5686     /* It appears that for fonts with SYMBOL_CHARSET Windows always sets
5687      * symbol range to 0 - f0ff
5688      */
5689
5690     if (face_has_symbol_charmap(ft_face) || (pOS2->usFirstCharIndex >= 0xf000 && pOS2->usFirstCharIndex < 0xf100))
5691     {
5692         TM.tmFirstChar = 0;
5693         switch(GetACP())
5694         {
5695         case 1257: /* Baltic */
5696             TM.tmLastChar = 0xf8fd;
5697             break;
5698         default:
5699             TM.tmLastChar = 0xf0ff;
5700         }
5701         TM.tmBreakChar = 0x20;
5702         TM.tmDefaultChar = 0x1f;
5703     }
5704     else
5705     {
5706         TM.tmFirstChar = pOS2->usFirstCharIndex; /* Should be the first char in the cmap */
5707         TM.tmLastChar = pOS2->usLastCharIndex;   /* Should be min(cmap_last, os2_last) */
5708
5709         if(pOS2->usFirstCharIndex <= 1)
5710             TM.tmBreakChar = pOS2->usFirstCharIndex + 2;
5711         else if (pOS2->usFirstCharIndex > 0xff)
5712             TM.tmBreakChar = 0x20;
5713         else
5714             TM.tmBreakChar = pOS2->usFirstCharIndex;
5715         TM.tmDefaultChar = TM.tmBreakChar - 1;
5716     }
5717     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
5718     TM.tmUnderlined = font->underline;
5719     TM.tmStruckOut = font->strikeout;
5720
5721     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
5722     if(!FT_IS_FIXED_WIDTH(ft_face) &&
5723        (pOS2->version == 0xFFFFU || 
5724         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
5725         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
5726     else
5727         TM.tmPitchAndFamily = 0;
5728
5729     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX])
5730     {
5731     case PAN_FAMILY_SCRIPT:
5732         TM.tmPitchAndFamily |= FF_SCRIPT;
5733         break;
5734
5735     case PAN_FAMILY_DECORATIVE:
5736         TM.tmPitchAndFamily |= FF_DECORATIVE;
5737         break;
5738
5739     case PAN_ANY:
5740     case PAN_NO_FIT:
5741     case PAN_FAMILY_TEXT_DISPLAY:
5742     case PAN_FAMILY_PICTORIAL: /* symbol fonts get treated as if they were text */
5743                                /* which is clearly not what the panose spec says. */
5744     default:
5745         if(TM.tmPitchAndFamily == 0 || /* fixed */
5746            pOS2->panose[PAN_PROPORTION_INDEX] == PAN_PROP_MONOSPACED)
5747             TM.tmPitchAndFamily = FF_MODERN;
5748         else
5749         {
5750             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX])
5751             {
5752             case PAN_ANY:
5753             case PAN_NO_FIT:
5754             default:
5755                 TM.tmPitchAndFamily |= FF_DONTCARE;
5756                 break;
5757
5758             case PAN_SERIF_COVE:
5759             case PAN_SERIF_OBTUSE_COVE:
5760             case PAN_SERIF_SQUARE_COVE:
5761             case PAN_SERIF_OBTUSE_SQUARE_COVE:
5762             case PAN_SERIF_SQUARE:
5763             case PAN_SERIF_THIN:
5764             case PAN_SERIF_BONE:
5765             case PAN_SERIF_EXAGGERATED:
5766             case PAN_SERIF_TRIANGLE:
5767                 TM.tmPitchAndFamily |= FF_ROMAN;
5768                 break;
5769
5770             case PAN_SERIF_NORMAL_SANS:
5771             case PAN_SERIF_OBTUSE_SANS:
5772             case PAN_SERIF_PERP_SANS:
5773             case PAN_SERIF_FLARED:
5774             case PAN_SERIF_ROUNDED:
5775                 TM.tmPitchAndFamily |= FF_SWISS;
5776                 break;
5777             }
5778         }
5779         break;
5780     }
5781
5782     if(FT_IS_SCALABLE(ft_face))
5783         TM.tmPitchAndFamily |= TMPF_VECTOR;
5784
5785     if(FT_IS_SFNT(ft_face))
5786     {
5787         if (font->ntmFlags & NTM_PS_OPENTYPE)
5788             TM.tmPitchAndFamily |= TMPF_DEVICE;
5789         else
5790             TM.tmPitchAndFamily |= TMPF_TRUETYPE;
5791     }
5792
5793     TM.tmCharSet = font->charset;
5794
5795     font->potm->otmFiller = 0;
5796     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
5797     font->potm->otmfsSelection = pOS2->fsSelection;
5798     font->potm->otmfsType = pOS2->fsType;
5799     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
5800     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
5801     font->potm->otmItalicAngle = 0; /* POST table */
5802     font->potm->otmEMSquare = ft_face->units_per_EM;
5803     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
5804     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
5805     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
5806     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
5807     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
5808     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
5809     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
5810     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
5811     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
5812     font->potm->otmMacAscent = TM.tmAscent;
5813     font->potm->otmMacDescent = -TM.tmDescent;
5814     font->potm->otmMacLineGap = font->potm->otmLineGap;
5815     font->potm->otmusMinimumPPEM = 0; /* TT Header */
5816     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
5817     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
5818     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
5819     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
5820     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
5821     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
5822     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
5823     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
5824     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
5825     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
5826     if(!pPost) {
5827         font->potm->otmsUnderscoreSize = 0;
5828         font->potm->otmsUnderscorePosition = 0;
5829     } else {
5830         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
5831         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
5832     }
5833 #undef TM
5834
5835     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
5836     cp = (char*)font->potm + sizeof(*font->potm);
5837     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
5838     strcpyW((WCHAR*)cp, family_nameW);
5839     cp += lenfam;
5840     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
5841     strcpyW((WCHAR*)cp, style_nameW);
5842     cp += lensty;
5843     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
5844     strcpyW((WCHAR*)cp, family_nameW);
5845     if (ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) {
5846         strcatW((WCHAR*)cp, spaceW);
5847         strcatW((WCHAR*)cp, style_nameW);
5848         cp += lenfam + lensty;
5849     } else
5850         cp += lenfam;
5851     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
5852     strcpyW((WCHAR*)cp, family_nameW);
5853     strcatW((WCHAR*)cp, spaceW);
5854     strcatW((WCHAR*)cp, style_nameW);
5855     ret = needed;
5856
5857     if(potm && needed <= cbSize)
5858     {
5859         memcpy(potm, font->potm, font->potm->otmSize);
5860         scale_outline_font_metrics(font, potm);
5861     }
5862
5863 end:
5864     HeapFree(GetProcessHeap(), 0, style_nameW);
5865     HeapFree(GetProcessHeap(), 0, family_nameW);
5866
5867     LeaveCriticalSection( &freetype_cs );
5868     return ret;
5869 }
5870
5871 static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
5872 {
5873     HFONTLIST *hfontlist;
5874     child->font = alloc_font();
5875     child->font->ft_face = OpenFontFace(child->font, child->face, 0, -font->ppem);
5876     if(!child->font->ft_face)
5877     {
5878         free_font(child->font);
5879         child->font = NULL;
5880         return FALSE;
5881     }
5882
5883     child->font->font_desc = font->font_desc;
5884     child->font->ntmFlags = child->face->ntmFlags;
5885     child->font->orientation = font->orientation;
5886     child->font->scale_y = font->scale_y;
5887     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
5888     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
5889     child->font->name = strdupW(child->face->family->FamilyName);
5890     list_add_head(&child->font->hfontlist, &hfontlist->entry);
5891     child->font->base_font = font;
5892     list_add_head(&child_font_list, &child->font->entry);
5893     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
5894     return TRUE;
5895 }
5896
5897 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph)
5898 {
5899     FT_UInt g;
5900     CHILD_FONT *child_font;
5901
5902     if(font->base_font)
5903         font = font->base_font;
5904
5905     *linked_font = font;
5906
5907     if((*glyph = get_glyph_index(font, c)))
5908         return TRUE;
5909
5910     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
5911     {
5912         if(!child_font->font)
5913             if(!load_child_font(font, child_font))
5914                 continue;
5915
5916         if(!child_font->font->ft_face)
5917             continue;
5918         g = get_glyph_index(child_font->font, c);
5919         if(g)
5920         {
5921             *glyph = g;
5922             *linked_font = child_font->font;
5923             return TRUE;
5924         }
5925     }
5926     return FALSE;
5927 }
5928
5929 /*************************************************************
5930  * WineEngGetCharWidth
5931  *
5932  */
5933 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
5934                          LPINT buffer)
5935 {
5936     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
5937     UINT c;
5938     GLYPHMETRICS gm;
5939     FT_UInt glyph_index;
5940     GdiFont *linked_font;
5941
5942     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
5943
5944     GDI_CheckNotLock();
5945     EnterCriticalSection( &freetype_cs );
5946     for(c = firstChar; c <= lastChar; c++) {
5947         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
5948         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
5949                                &gm, 0, NULL, &identity);
5950         buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv;
5951     }
5952     LeaveCriticalSection( &freetype_cs );
5953     return TRUE;
5954 }
5955
5956 /*************************************************************
5957  * WineEngGetCharABCWidths
5958  *
5959  */
5960 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
5961                              LPABC buffer)
5962 {
5963     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
5964     UINT c;
5965     GLYPHMETRICS gm;
5966     FT_UInt glyph_index;
5967     GdiFont *linked_font;
5968
5969     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
5970
5971     if(!FT_IS_SCALABLE(font->ft_face))
5972         return FALSE;
5973
5974     GDI_CheckNotLock();
5975     EnterCriticalSection( &freetype_cs );
5976
5977     for(c = firstChar; c <= lastChar; c++) {
5978         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
5979         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
5980                                &gm, 0, NULL, &identity);
5981         buffer[c - firstChar].abcA = FONT_GM(linked_font,glyph_index)->lsb;
5982         buffer[c - firstChar].abcB = FONT_GM(linked_font,glyph_index)->bbx;
5983         buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb -
5984             FONT_GM(linked_font,glyph_index)->bbx;
5985     }
5986     LeaveCriticalSection( &freetype_cs );
5987     return TRUE;
5988 }
5989
5990 /*************************************************************
5991  * WineEngGetCharABCWidthsFloat
5992  *
5993  */
5994 BOOL WineEngGetCharABCWidthsFloat(GdiFont *font, UINT first, UINT last, LPABCFLOAT buffer)
5995 {
5996     static const MAT2 identity = {{0,1}, {0,0}, {0,0}, {0,1}};
5997     UINT c;
5998     GLYPHMETRICS gm;
5999     FT_UInt glyph_index;
6000     GdiFont *linked_font;
6001
6002     TRACE("%p, %d, %d, %p\n", font, first, last, buffer);
6003
6004     GDI_CheckNotLock();
6005     EnterCriticalSection( &freetype_cs );
6006
6007     for (c = first; c <= last; c++)
6008     {
6009         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
6010         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
6011                                &gm, 0, NULL, &identity);
6012         buffer[c - first].abcfA = FONT_GM(linked_font, glyph_index)->lsb;
6013         buffer[c - first].abcfB = FONT_GM(linked_font, glyph_index)->bbx;
6014         buffer[c - first].abcfC = FONT_GM(linked_font, glyph_index)->adv -
6015                                   FONT_GM(linked_font, glyph_index)->lsb -
6016                                   FONT_GM(linked_font, glyph_index)->bbx;
6017     }
6018     LeaveCriticalSection( &freetype_cs );
6019     return TRUE;
6020 }
6021
6022 /*************************************************************
6023  * WineEngGetCharABCWidthsI
6024  *
6025  */
6026 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
6027                               LPABC buffer)
6028 {
6029     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
6030     UINT c;
6031     GLYPHMETRICS gm;
6032     FT_UInt glyph_index;
6033     GdiFont *linked_font;
6034
6035     if(!FT_HAS_HORIZONTAL(font->ft_face))
6036         return FALSE;
6037
6038     GDI_CheckNotLock();
6039     EnterCriticalSection( &freetype_cs );
6040
6041     get_glyph_index_linked(font, 'a', &linked_font, &glyph_index);
6042     if (!pgi)
6043         for(c = firstChar; c < firstChar+count; c++) {
6044             WineEngGetGlyphOutline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
6045                                    &gm, 0, NULL, &identity);
6046             buffer[c - firstChar].abcA = FONT_GM(linked_font,c)->lsb;
6047             buffer[c - firstChar].abcB = FONT_GM(linked_font,c)->bbx;
6048             buffer[c - firstChar].abcC = FONT_GM(linked_font,c)->adv - FONT_GM(linked_font,c)->lsb
6049                 - FONT_GM(linked_font,c)->bbx;
6050         }
6051     else
6052         for(c = 0; c < count; c++) {
6053             WineEngGetGlyphOutline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
6054                                    &gm, 0, NULL, &identity);
6055             buffer[c].abcA = FONT_GM(linked_font,pgi[c])->lsb;
6056             buffer[c].abcB = FONT_GM(linked_font,pgi[c])->bbx;
6057             buffer[c].abcC = FONT_GM(linked_font,pgi[c])->adv
6058                 - FONT_GM(linked_font,pgi[c])->lsb - FONT_GM(linked_font,pgi[c])->bbx;
6059         }
6060
6061     LeaveCriticalSection( &freetype_cs );
6062     return TRUE;
6063 }
6064
6065 /*************************************************************
6066  * WineEngGetTextExtentExPoint
6067  *
6068  */
6069 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
6070                                  INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
6071 {
6072     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
6073     INT idx;
6074     INT nfit = 0, ext;
6075     GLYPHMETRICS gm;
6076     TEXTMETRICW tm;
6077     FT_UInt glyph_index;
6078     GdiFont *linked_font;
6079
6080     TRACE("%p, %s, %d, %d, %p\n", font, debugstr_wn(wstr, count), count,
6081           max_ext, size);
6082
6083     GDI_CheckNotLock();
6084     EnterCriticalSection( &freetype_cs );
6085
6086     size->cx = 0;
6087     WineEngGetTextMetrics(font, &tm);
6088     size->cy = tm.tmHeight;
6089
6090     for(idx = 0; idx < count; idx++) {
6091         get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
6092         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
6093                                &gm, 0, NULL, &identity);
6094         size->cx += FONT_GM(linked_font,glyph_index)->adv;
6095         ext = size->cx;
6096         if (! pnfit || ext <= max_ext) {
6097             ++nfit;
6098             if (dxs)
6099                 dxs[idx] = ext;
6100         }
6101     }
6102
6103     if (pnfit)
6104         *pnfit = nfit;
6105
6106     LeaveCriticalSection( &freetype_cs );
6107     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
6108     return TRUE;
6109 }
6110
6111 /*************************************************************
6112  * WineEngGetTextExtentExPointI
6113  *
6114  */
6115 BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count,
6116                                   INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
6117 {
6118     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
6119     INT idx;
6120     INT nfit = 0, ext;
6121     GLYPHMETRICS gm;
6122     TEXTMETRICW tm;
6123
6124     TRACE("%p, %p, %d, %d, %p\n", font, indices, count, max_ext, size);
6125
6126     GDI_CheckNotLock();
6127     EnterCriticalSection( &freetype_cs );
6128
6129     size->cx = 0;
6130     WineEngGetTextMetrics(font, &tm);
6131     size->cy = tm.tmHeight;
6132
6133     for(idx = 0; idx < count; idx++) {
6134         WineEngGetGlyphOutline(font, indices[idx],
6135                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
6136                                &identity);
6137         size->cx += FONT_GM(font,indices[idx])->adv;
6138         ext = size->cx;
6139         if (! pnfit || ext <= max_ext) {
6140             ++nfit;
6141             if (dxs)
6142                 dxs[idx] = ext;
6143         }
6144     }
6145
6146     if (pnfit)
6147         *pnfit = nfit;
6148
6149     LeaveCriticalSection( &freetype_cs );
6150     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
6151     return TRUE;
6152 }
6153
6154 /*************************************************************
6155  * WineEngGetFontData
6156  *
6157  */
6158 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
6159                          DWORD cbData)
6160 {
6161     FT_Face ft_face = font->ft_face;
6162     FT_ULong len;
6163     FT_Error err;
6164
6165     TRACE("font=%p, table=%c%c%c%c, offset=0x%x, buf=%p, cbData=0x%x\n",
6166         font, LOBYTE(LOWORD(table)), HIBYTE(LOWORD(table)),
6167         LOBYTE(HIWORD(table)), HIBYTE(HIWORD(table)), offset, buf, cbData);
6168
6169     if(!FT_IS_SFNT(ft_face))
6170         return GDI_ERROR;
6171
6172     if(!buf || !cbData)
6173         len = 0;
6174     else
6175         len = cbData;
6176
6177     if(table) { /* MS tags differ in endianness from FT ones */
6178         table = table >> 24 | table << 24 |
6179           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
6180     }
6181
6182     /* make sure value of len is the value freetype says it needs */
6183     if(buf && len)
6184     {
6185         FT_ULong needed = 0;
6186         err = load_sfnt_table(ft_face, table, offset, NULL, &needed);
6187         if( !err && needed < len) len = needed;
6188     }
6189     err = load_sfnt_table(ft_face, table, offset, buf, &len);
6190
6191     if(err) {
6192         TRACE("Can't find table %c%c%c%c\n",
6193               /* bytes were reversed */
6194               HIBYTE(HIWORD(table)), LOBYTE(HIWORD(table)),
6195               HIBYTE(LOWORD(table)), LOBYTE(LOWORD(table)));
6196         return GDI_ERROR;
6197     }
6198     return len;
6199 }
6200
6201 /*************************************************************
6202  * WineEngGetTextFace
6203  *
6204  */
6205 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
6206 {
6207     INT n = strlenW(font->name) + 1;
6208     if(str) {
6209         lstrcpynW(str, font->name, count);
6210         return min(count, n);
6211     } else
6212         return n;
6213 }
6214
6215 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
6216 {
6217     if (fs) *fs = font->fs;
6218     return font->charset;
6219 }
6220
6221 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
6222 {
6223     GdiFont *font = dc->gdiFont, *linked_font;
6224     struct list *first_hfont;
6225     BOOL ret;
6226
6227     GDI_CheckNotLock();
6228     EnterCriticalSection( &freetype_cs );
6229     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
6230     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
6231     if(font == linked_font)
6232         *new_hfont = dc->hFont;
6233     else
6234     {
6235         first_hfont = list_head(&linked_font->hfontlist);
6236         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
6237     }
6238     LeaveCriticalSection( &freetype_cs );
6239     return ret;
6240 }
6241     
6242 /* Retrieve a list of supported Unicode ranges for a given font.
6243  * Can be called with NULL gs to calculate the buffer size. Returns
6244  * the number of ranges found.
6245  */
6246 static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
6247 {
6248     DWORD num_ranges = 0;
6249
6250     if (face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
6251     {
6252         FT_UInt glyph_code;
6253         FT_ULong char_code, char_code_prev;
6254
6255         glyph_code = 0;
6256         char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
6257
6258         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
6259                face->num_glyphs, glyph_code, char_code);
6260
6261         if (!glyph_code) return 0;
6262
6263         if (gs)
6264         {
6265             gs->ranges[0].wcLow = (USHORT)char_code;
6266             gs->ranges[0].cGlyphs = 0;
6267             gs->cGlyphsSupported = 0;
6268         }
6269
6270         num_ranges = 1;
6271         while (glyph_code)
6272         {
6273             if (char_code < char_code_prev)
6274             {
6275                 ERR("expected increasing char code from FT_Get_Next_Char\n");
6276                 return 0;
6277             }
6278             if (char_code - char_code_prev > 1)
6279             {
6280                 num_ranges++;
6281                 if (gs)
6282                 {
6283                     gs->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
6284                     gs->ranges[num_ranges - 1].cGlyphs = 1;
6285                     gs->cGlyphsSupported++;
6286                 }
6287             }
6288             else if (gs)
6289             {
6290                 gs->ranges[num_ranges - 1].cGlyphs++;
6291                 gs->cGlyphsSupported++;
6292             }
6293             char_code_prev = char_code;
6294             char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
6295         }
6296     }
6297     else
6298         FIXME("encoding %u not supported\n", face->charmap->encoding);
6299
6300     return num_ranges;
6301 }
6302
6303 DWORD WineEngGetFontUnicodeRanges(GdiFont *font, LPGLYPHSET glyphset)
6304 {
6305     DWORD size = 0;
6306     DWORD num_ranges = get_font_unicode_ranges(font->ft_face, glyphset);
6307
6308     size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
6309     if (glyphset)
6310     {
6311         glyphset->cbThis = size;
6312         glyphset->cRanges = num_ranges;
6313         glyphset->flAccel = 0;
6314     }
6315     return size;
6316 }
6317
6318 /*************************************************************
6319  *     FontIsLinked
6320  */
6321 BOOL WineEngFontIsLinked(GdiFont *font)
6322 {
6323     BOOL ret;
6324     GDI_CheckNotLock();
6325     EnterCriticalSection( &freetype_cs );
6326     ret = !list_empty(&font->child_fonts);
6327     LeaveCriticalSection( &freetype_cs );
6328     return ret;
6329 }
6330
6331 static BOOL is_hinting_enabled(void)
6332 {
6333     /* Use the >= 2.2.0 function if available */
6334     if(pFT_Get_TrueType_Engine_Type)
6335     {
6336         FT_TrueTypeEngineType type = pFT_Get_TrueType_Engine_Type(library);
6337         return type == FT_TRUETYPE_ENGINE_TYPE_PATENTED;
6338     }
6339 #ifdef FT_DRIVER_HAS_HINTER
6340     else
6341     {
6342         FT_Module mod;
6343
6344         /* otherwise if we've been compiled with < 2.2.0 headers 
6345            use the internal macro */
6346         mod = pFT_Get_Module(library, "truetype");
6347         if(mod && FT_DRIVER_HAS_HINTER(mod))
6348             return TRUE;
6349     }
6350 #endif
6351
6352     return FALSE;
6353 }
6354
6355 static BOOL is_subpixel_rendering_enabled( void )
6356 {
6357 #ifdef HAVE_FREETYPE_FTLCDFIL_H
6358     return pFT_Library_SetLcdFilter &&
6359            pFT_Library_SetLcdFilter( NULL, 0 ) != FT_Err_Unimplemented_Feature;
6360 #else
6361     return FALSE;
6362 #endif
6363 }
6364
6365 /*************************************************************************
6366  *             GetRasterizerCaps   (GDI32.@)
6367  */
6368 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
6369 {
6370     static int hinting = -1;
6371     static int subpixel = -1;
6372
6373     if(hinting == -1)
6374     {
6375         hinting = is_hinting_enabled();
6376         TRACE("hinting is %senabled\n", hinting ? "" : "NOT ");
6377     }
6378
6379     if ( subpixel == -1 )
6380     {
6381         subpixel = is_subpixel_rendering_enabled();
6382         TRACE("subpixel rendering is %senabled\n", subpixel ? "" : "NOT ");
6383     }
6384
6385     lprs->nSize = sizeof(RASTERIZER_STATUS);
6386     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
6387     if ( subpixel )
6388         lprs->wFlags |= WINE_TT_SUBPIXEL_RENDERING_ENABLED;
6389     lprs->nLanguageID = 0;
6390     return TRUE;
6391 }
6392
6393 /*************************************************************
6394  *     WineEngRealizationInfo
6395  */
6396 BOOL WineEngRealizationInfo(GdiFont *font, realization_info_t *info)
6397 {
6398     FIXME("(%p, %p): stub!\n", font, info);
6399
6400     info->flags = 1;
6401     if(FT_IS_SCALABLE(font->ft_face))
6402         info->flags |= 2;
6403
6404     info->cache_num = font->cache_num;
6405     info->unknown2 = -1;
6406     return TRUE;
6407 }
6408
6409 /*************************************************************************
6410  * Kerning support for TrueType fonts
6411  */
6412 #define MS_KERN_TAG MS_MAKE_TAG('k', 'e', 'r', 'n')
6413
6414 struct TT_kern_table
6415 {
6416     USHORT version;
6417     USHORT nTables;
6418 };
6419
6420 struct TT_kern_subtable
6421 {
6422     USHORT version;
6423     USHORT length;
6424     union
6425     {
6426         USHORT word;
6427         struct
6428         {
6429             USHORT horizontal : 1;
6430             USHORT minimum : 1;
6431             USHORT cross_stream: 1;
6432             USHORT override : 1;
6433             USHORT reserved1 : 4;
6434             USHORT format : 8;
6435         } bits;
6436     } coverage;
6437 };
6438
6439 struct TT_format0_kern_subtable
6440 {
6441     USHORT nPairs;
6442     USHORT searchRange;
6443     USHORT entrySelector;
6444     USHORT rangeShift;
6445 };
6446
6447 struct TT_kern_pair
6448 {
6449     USHORT left;
6450     USHORT right;
6451     short  value;
6452 };
6453
6454 static DWORD parse_format0_kern_subtable(GdiFont *font,
6455                                          const struct TT_format0_kern_subtable *tt_f0_ks,
6456                                          const USHORT *glyph_to_char,
6457                                          KERNINGPAIR *kern_pair, DWORD cPairs)
6458 {
6459     USHORT i, nPairs;
6460     const struct TT_kern_pair *tt_kern_pair;
6461
6462     TRACE("font height %d, units_per_EM %d\n", font->ppem, font->ft_face->units_per_EM);
6463
6464     nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
6465
6466     TRACE("nPairs %u, searchRange %u, entrySelector %u, rangeShift %u\n",
6467            nPairs, GET_BE_WORD(tt_f0_ks->searchRange),
6468            GET_BE_WORD(tt_f0_ks->entrySelector), GET_BE_WORD(tt_f0_ks->rangeShift));
6469
6470     if (!kern_pair || !cPairs)
6471         return nPairs;
6472
6473     tt_kern_pair = (const struct TT_kern_pair *)(tt_f0_ks + 1);
6474
6475     nPairs = min(nPairs, cPairs);
6476
6477     for (i = 0; i < nPairs; i++)
6478     {
6479         kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
6480         kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
6481         /* this algorithm appears to better match what Windows does */
6482         kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
6483         if (kern_pair->iKernAmount < 0)
6484         {
6485             kern_pair->iKernAmount -= font->ft_face->units_per_EM / 2;
6486             kern_pair->iKernAmount -= font->ppem;
6487         }
6488         else if (kern_pair->iKernAmount > 0)
6489         {
6490             kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
6491             kern_pair->iKernAmount += font->ppem;
6492         }
6493         kern_pair->iKernAmount /= font->ft_face->units_per_EM;
6494
6495         TRACE("left %u right %u value %d\n",
6496                kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
6497
6498         kern_pair++;
6499     }
6500     TRACE("copied %u entries\n", nPairs);
6501     return nPairs;
6502 }
6503
6504 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
6505 {
6506     DWORD length;
6507     void *buf;
6508     const struct TT_kern_table *tt_kern_table;
6509     const struct TT_kern_subtable *tt_kern_subtable;
6510     USHORT i, nTables;
6511     USHORT *glyph_to_char;
6512
6513     GDI_CheckNotLock();
6514     EnterCriticalSection( &freetype_cs );
6515     if (font->total_kern_pairs != (DWORD)-1)
6516     {
6517         if (cPairs && kern_pair)
6518         {
6519             cPairs = min(cPairs, font->total_kern_pairs);
6520             memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
6521             LeaveCriticalSection( &freetype_cs );
6522             return cPairs;
6523         }
6524         LeaveCriticalSection( &freetype_cs );
6525         return font->total_kern_pairs;
6526     }
6527
6528     font->total_kern_pairs = 0;
6529
6530     length = WineEngGetFontData(font, MS_KERN_TAG, 0, NULL, 0);
6531
6532     if (length == GDI_ERROR)
6533     {
6534         TRACE("no kerning data in the font\n");
6535         LeaveCriticalSection( &freetype_cs );
6536         return 0;
6537     }
6538
6539     buf = HeapAlloc(GetProcessHeap(), 0, length);
6540     if (!buf)
6541     {
6542         WARN("Out of memory\n");
6543         LeaveCriticalSection( &freetype_cs );
6544         return 0;
6545     }
6546
6547     WineEngGetFontData(font, MS_KERN_TAG, 0, buf, length);
6548
6549     /* build a glyph index to char code map */
6550     glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
6551     if (!glyph_to_char)
6552     {
6553         WARN("Out of memory allocating a glyph index to char code map\n");
6554         HeapFree(GetProcessHeap(), 0, buf);
6555         LeaveCriticalSection( &freetype_cs );
6556         return 0;
6557     }
6558
6559     if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
6560     {
6561         FT_UInt glyph_code;
6562         FT_ULong char_code;
6563
6564         glyph_code = 0;
6565         char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
6566
6567         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
6568                font->ft_face->num_glyphs, glyph_code, char_code);
6569
6570         while (glyph_code)
6571         {
6572             /*TRACE("Char %04lX -> Index %u%s\n", char_code, glyph_code, glyph_to_char[glyph_code] ? "  !" : "" );*/
6573
6574             /* FIXME: This doesn't match what Windows does: it does some fancy
6575              * things with duplicate glyph index to char code mappings, while
6576              * we just avoid overriding existing entries.
6577              */
6578             if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
6579                 glyph_to_char[glyph_code] = (USHORT)char_code;
6580
6581             char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
6582         }
6583     }
6584     else
6585     {
6586         ULONG n;
6587
6588         FIXME("encoding %u not supported\n", font->ft_face->charmap->encoding);
6589         for (n = 0; n <= 65535; n++)
6590             glyph_to_char[n] = (USHORT)n;
6591     }
6592
6593     tt_kern_table = buf;
6594     nTables = GET_BE_WORD(tt_kern_table->nTables);
6595     TRACE("version %u, nTables %u\n",
6596            GET_BE_WORD(tt_kern_table->version), nTables);
6597
6598     tt_kern_subtable = (const struct TT_kern_subtable *)(tt_kern_table + 1);
6599
6600     for (i = 0; i < nTables; i++)
6601     {
6602         struct TT_kern_subtable tt_kern_subtable_copy;
6603
6604         tt_kern_subtable_copy.version = GET_BE_WORD(tt_kern_subtable->version);
6605         tt_kern_subtable_copy.length = GET_BE_WORD(tt_kern_subtable->length);
6606         tt_kern_subtable_copy.coverage.word = GET_BE_WORD(tt_kern_subtable->coverage.word);
6607
6608         TRACE("version %u, length %u, coverage %u, subtable format %u\n",
6609                tt_kern_subtable_copy.version, tt_kern_subtable_copy.length,
6610                tt_kern_subtable_copy.coverage.word, tt_kern_subtable_copy.coverage.bits.format);
6611
6612         /* According to the TrueType specification this is the only format
6613          * that will be properly interpreted by Windows and OS/2
6614          */
6615         if (tt_kern_subtable_copy.coverage.bits.format == 0)
6616         {
6617             DWORD new_chunk, old_total = font->total_kern_pairs;
6618
6619             new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
6620                                                     glyph_to_char, NULL, 0);
6621             font->total_kern_pairs += new_chunk;
6622
6623             if (!font->kern_pairs)
6624                 font->kern_pairs = HeapAlloc(GetProcessHeap(), 0,
6625                                              font->total_kern_pairs * sizeof(*font->kern_pairs));
6626             else
6627                 font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs,
6628                                                font->total_kern_pairs * sizeof(*font->kern_pairs));
6629
6630             parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
6631                         glyph_to_char, font->kern_pairs + old_total, new_chunk);
6632         }
6633         else
6634             TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format);
6635
6636         tt_kern_subtable = (const struct TT_kern_subtable *)((const char *)tt_kern_subtable + tt_kern_subtable_copy.length);
6637     }
6638
6639     HeapFree(GetProcessHeap(), 0, glyph_to_char);
6640     HeapFree(GetProcessHeap(), 0, buf);
6641
6642     if (cPairs && kern_pair)
6643     {
6644         cPairs = min(cPairs, font->total_kern_pairs);
6645         memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
6646         LeaveCriticalSection( &freetype_cs );
6647         return cPairs;
6648     }
6649     LeaveCriticalSection( &freetype_cs );
6650     return font->total_kern_pairs;
6651 }
6652
6653 #else /* HAVE_FREETYPE */
6654
6655 /*************************************************************************/
6656
6657 BOOL WineEngInit(void)
6658 {
6659     return FALSE;
6660 }
6661 GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont)
6662 {
6663     return NULL;
6664 }
6665 BOOL WineEngDestroyFontInstance(HFONT hfont)
6666 {
6667     return FALSE;
6668 }
6669
6670 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
6671 {
6672     return 1;
6673 }
6674
6675 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
6676                                 LPWORD pgi, DWORD flags)
6677 {
6678     return GDI_ERROR;
6679 }
6680
6681 DWORD WineEngGetGlyphOutline(GdiFont *font, UINT glyph, UINT format,
6682                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
6683                              const MAT2* lpmat)
6684 {
6685     ERR("called but we don't have FreeType\n");
6686     return GDI_ERROR;
6687 }
6688
6689 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
6690 {
6691     ERR("called but we don't have FreeType\n");
6692     return FALSE;
6693 }
6694
6695 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
6696                                   OUTLINETEXTMETRICW *potm)
6697 {
6698     ERR("called but we don't have FreeType\n");
6699     return 0;
6700 }
6701
6702 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
6703                          LPINT buffer)
6704 {
6705     ERR("called but we don't have FreeType\n");
6706     return FALSE;
6707 }
6708
6709 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
6710                              LPABC buffer)
6711 {
6712     ERR("called but we don't have FreeType\n");
6713     return FALSE;
6714 }
6715
6716 BOOL WineEngGetCharABCWidthsFloat(GdiFont *font, UINT first, UINT last, LPABCFLOAT buffer)
6717 {
6718     ERR("called but we don't have FreeType\n");
6719     return FALSE;
6720 }
6721
6722 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
6723                               LPABC buffer)
6724 {
6725     ERR("called but we don't have FreeType\n");
6726     return FALSE;
6727 }
6728
6729 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
6730                                  INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
6731 {
6732     ERR("called but we don't have FreeType\n");
6733     return FALSE;
6734 }
6735
6736 BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count,
6737                                   INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
6738 {
6739     ERR("called but we don't have FreeType\n");
6740     return FALSE;
6741 }
6742
6743 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
6744                          DWORD cbData)
6745 {
6746     ERR("called but we don't have FreeType\n");
6747     return GDI_ERROR;
6748 }
6749
6750 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
6751 {
6752     ERR("called but we don't have FreeType\n");
6753     return 0;
6754 }
6755
6756 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
6757 {
6758     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
6759     return 1;
6760 }
6761
6762 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
6763 {
6764     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
6765     return TRUE;
6766 }
6767
6768 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
6769 {
6770     FIXME("(%p, %u, %p, %p): stub\n", pbFont, cbFont, pdv, pcFonts);
6771     return NULL;
6772 }
6773
6774 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
6775 {
6776     FIXME("(%p, %p, %u): stub\n", font, fs, flags);
6777     return DEFAULT_CHARSET;
6778 }
6779
6780 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
6781 {
6782     return FALSE;
6783 }
6784
6785 DWORD WineEngGetFontUnicodeRanges(GdiFont *font, LPGLYPHSET glyphset)
6786 {
6787     FIXME("(%p, %p): stub\n", font, glyphset);
6788     return 0;
6789 }
6790
6791 BOOL WineEngFontIsLinked(GdiFont *font)
6792 {
6793     return FALSE;
6794 }
6795
6796 /*************************************************************************
6797  *             GetRasterizerCaps   (GDI32.@)
6798  */
6799 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
6800 {
6801     lprs->nSize = sizeof(RASTERIZER_STATUS);
6802     lprs->wFlags = 0;
6803     lprs->nLanguageID = 0;
6804     return TRUE;
6805 }
6806
6807 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
6808 {
6809     ERR("called but we don't have FreeType\n");
6810     return 0;
6811 }
6812
6813 BOOL WineEngRealizationInfo(GdiFont *font, realization_info_t *info)
6814 {
6815     ERR("called but we don't have FreeType\n");
6816     return FALSE;
6817 }
6818
6819 #endif /* HAVE_FREETYPE */