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