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