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