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