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