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