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