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