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