oleaut32: Fix handle cast warnings on 64-bit.
[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     if (ft_handle)  /* do it only if we have freetype up and running */
2089     {
2090         char *unixname;
2091
2092         if(flags)
2093             FIXME("Ignoring flags %x\n", flags);
2094
2095         if((unixname = wine_get_unix_file_name(file)))
2096         {
2097             EnterCriticalSection( &freetype_cs );
2098             ret = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
2099             LeaveCriticalSection( &freetype_cs );
2100             HeapFree(GetProcessHeap(), 0, unixname);
2101         }
2102         if (!ret && !strchrW(file, '\\')) {
2103             /* Try in %WINDIR%/fonts, needed for Fotobuch Designer */
2104             ret = load_font_from_winfonts_dir(file);
2105             if (!ret) {
2106                 /* Try in datadir/fonts (or builddir/fonts),
2107                  * needed for Magic the Gathering Online
2108                  */
2109                 ret = load_font_from_data_dir(file);
2110             }
2111         }
2112     }
2113    return ret;
2114 }
2115
2116 /*************************************************************
2117  *    WineEngAddFontMemResourceEx
2118  *
2119  */
2120 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
2121 {
2122     if (ft_handle)  /* do it only if we have freetype up and running */
2123     {
2124         PVOID pFontCopy = HeapAlloc(GetProcessHeap(), 0, cbFont);
2125
2126         TRACE("Copying %d bytes of data from %p to %p\n", cbFont, pbFont, pFontCopy);
2127         memcpy(pFontCopy, pbFont, cbFont);
2128
2129         EnterCriticalSection( &freetype_cs );
2130         *pcFonts = AddFontToList(NULL, pFontCopy, cbFont, NULL, NULL, ADDFONT_FORCE_BITMAP);
2131         LeaveCriticalSection( &freetype_cs );
2132
2133         if (*pcFonts == 0)
2134         {
2135             TRACE("AddFontToList failed\n");
2136             HeapFree(GetProcessHeap(), 0, pFontCopy);
2137             return NULL;
2138         }
2139         /* FIXME: is the handle only for use in RemoveFontMemResourceEx or should it be a true handle?
2140          * For now return something unique but quite random
2141          */
2142         TRACE("Returning handle %lx\n", ((INT_PTR)pFontCopy)^0x87654321);
2143         return (HANDLE)(((INT_PTR)pFontCopy)^0x87654321);
2144     }
2145
2146     *pcFonts = 0;
2147     return 0;
2148 }
2149
2150 /*************************************************************
2151  *    WineEngRemoveFontResourceEx
2152  *
2153  */
2154 BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
2155 {
2156     FIXME(":stub\n");
2157     return TRUE;
2158 }
2159
2160 static const struct nls_update_font_list
2161 {
2162     UINT ansi_cp, oem_cp;
2163     const char *oem, *fixed, *system;
2164     const char *courier, *serif, *small, *sserif;
2165     /* these are for font substitutes */
2166     const char *shelldlg, *tmsrmn;
2167     const char *fixed_0, *system_0, *courier_0, *serif_0, *small_0, *sserif_0,
2168                *helv_0, *tmsrmn_0;
2169     const struct subst
2170     {
2171         const char *from, *to;
2172     } arial_0, courier_new_0, times_new_roman_0;
2173 } nls_update_font_list[] =
2174 {
2175     /* Latin 1 (United States) */
2176     { 1252, 437, "vgaoem.fon", "vgafix.fon", "vgasys.fon",
2177       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2178       "Tahoma","Times New Roman",
2179       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2180       { 0 }, { 0 }, { 0 }
2181     },
2182     /* Latin 1 (Multilingual) */
2183     { 1252, 850, "vga850.fon", "vgafix.fon", "vgasys.fon",
2184       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2185       "Tahoma","Times New Roman",  /* FIXME unverified */
2186       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2187       { 0 }, { 0 }, { 0 }
2188     },
2189     /* Eastern Europe */
2190     { 1250, 852, "vga852.fon", "vgafixe.fon", "vgasyse.fon",
2191       "couree.fon", "serifee.fon", "smallee.fon", "sserifee.fon",
2192       "Tahoma","Times New Roman", /* FIXME unverified */
2193       "Fixedsys,238", "System,238",
2194       "Courier New,238", "MS Serif,238", "Small Fonts,238",
2195       "MS Sans Serif,238", "MS Sans Serif,238", "MS Serif,238",
2196       { "Arial CE,0", "Arial,238" },
2197       { "Courier New CE,0", "Courier New,238" },
2198       { "Times New Roman CE,0", "Times New Roman,238" }
2199     },
2200     /* Cyrillic */
2201     { 1251, 866, "vga866.fon", "vgafixr.fon", "vgasysr.fon",
2202       "courer.fon", "serifer.fon", "smaller.fon", "sserifer.fon",
2203       "Tahoma","Times New Roman", /* FIXME unverified */
2204       "Fixedsys,204", "System,204",
2205       "Courier New,204", "MS Serif,204", "Small Fonts,204",
2206       "MS Sans Serif,204", "MS Sans Serif,204", "MS Serif,204",
2207       { "Arial Cyr,0", "Arial,204" },
2208       { "Courier New Cyr,0", "Courier New,204" },
2209       { "Times New Roman Cyr,0", "Times New Roman,204" }
2210     },
2211     /* Greek */
2212     { 1253, 737, "vga869.fon", "vgafixg.fon", "vgasysg.fon",
2213       "coureg.fon", "serifeg.fon", "smalleg.fon", "sserifeg.fon",
2214       "Tahoma","Times New Roman", /* FIXME unverified */
2215       "Fixedsys,161", "System,161",
2216       "Courier New,161", "MS Serif,161", "Small Fonts,161",
2217       "MS Sans Serif,161", "MS Sans Serif,161", "MS Serif,161",
2218       { "Arial Greek,0", "Arial,161" },
2219       { "Courier New Greek,0", "Courier New,161" },
2220       { "Times New Roman Greek,0", "Times New Roman,161" }
2221     },
2222     /* Turkish */
2223     { 1254, 857, "vga857.fon", "vgafixt.fon", "vgasyst.fon",
2224       "couret.fon", "serifet.fon", "smallet.fon", "sserifet.fon",
2225       "Tahoma","Times New Roman", /* FIXME unverified */
2226       "Fixedsys,162", "System,162",
2227       "Courier New,162", "MS Serif,162", "Small Fonts,162",
2228       "MS Sans Serif,162", "MS Sans Serif,162", "MS Serif,162",
2229       { "Arial Tur,0", "Arial,162" },
2230       { "Courier New Tur,0", "Courier New,162" },
2231       { "Times New Roman Tur,0", "Times New Roman,162" }
2232     },
2233     /* Hebrew */
2234     { 1255, 862, "vgaoem.fon", "vgaf1255.fon", "vgas1255.fon",
2235       "coue1255.fon", "sere1255.fon", "smae1255.fon", "ssee1255.fon",
2236       "Tahoma","Times New Roman", /* FIXME unverified */
2237       "Fixedsys,177", "System,177",
2238       "Courier New,177", "MS Serif,177", "Small Fonts,177",
2239       "MS Sans Serif,177", "MS Sans Serif,177", "MS Serif,177",
2240       { 0 }, { 0 }, { 0 }
2241     },
2242     /* Arabic */
2243     { 1256, 720, "vgaoem.fon", "vgaf1256.fon", "vgas1256.fon",
2244       "coue1256.fon", "sere1256.fon", "smae1256.fon", "ssee1256.fon",
2245       "Tahoma","Times New Roman", /* FIXME unverified */
2246       "Fixedsys,178", "System,178",
2247       "Courier New,178", "MS Serif,178", "Small Fonts,178",
2248       "MS Sans Serif,178", "MS Sans Serif,178", "MS Serif,178",
2249       { 0 }, { 0 }, { 0 }
2250     },
2251     /* Baltic */
2252     { 1257, 775, "vga775.fon", "vgaf1257.fon", "vgas1257.fon",
2253       "coue1257.fon", "sere1257.fon", "smae1257.fon", "ssee1257.fon",
2254       "Tahoma","Times New Roman", /* FIXME unverified */
2255       "Fixedsys,186", "System,186",
2256       "Courier New,186", "MS Serif,186", "Small Fonts,186",
2257       "MS Sans Serif,186", "MS Sans Serif,186", "MS Serif,186",
2258       { "Arial Baltic,0", "Arial,186" },
2259       { "Courier New Baltic,0", "Courier New,186" },
2260       { "Times New Roman Baltic,0", "Times New Roman,186" }
2261     },
2262     /* Vietnamese */
2263     { 1258, 1258, "vga850.fon", "vgafix.fon", "vgasys.fon",
2264       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2265       "Tahoma","Times New Roman", /* FIXME unverified */
2266       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2267       { 0 }, { 0 }, { 0 }
2268     },
2269     /* Thai */
2270     { 874, 874, "vga850.fon", "vgaf874.fon", "vgas874.fon",
2271       "coure.fon", "serife.fon", "smalle.fon", "ssee874.fon",
2272       "Tahoma","Times New Roman", /* FIXME unverified */
2273       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2274       { 0 }, { 0 }, { 0 }
2275     },
2276     /* Japanese */
2277     { 932, 932, "vga932.fon", "jvgafix.fon", "jvgasys.fon",
2278       "coure.fon", "serife.fon", "jsmalle.fon", "sserife.fon",
2279       "MS UI Gothic","MS Serif",
2280       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2281       { 0 }, { 0 }, { 0 }
2282     },
2283     /* Chinese Simplified */
2284     { 936, 936, "vga936.fon", "svgafix.fon", "svgasys.fon",
2285       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2286       "SimSun", "NSimSun",
2287       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2288       { 0 }, { 0 }, { 0 }
2289     },
2290     /* Korean */
2291     { 949, 949, "vga949.fon", "hvgafix.fon", "hvgasys.fon",
2292       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2293       "Gulim",  "Batang",
2294       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2295       { 0 }, { 0 }, { 0 }
2296     },
2297     /* Chinese Traditional */
2298     { 950, 950, "vga950.fon", "cvgafix.fon", "cvgasys.fon",
2299       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2300       "PMingLiU",  "MingLiU",
2301       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2302       { 0 }, { 0 }, { 0 }
2303     }
2304 };
2305
2306 static inline BOOL is_dbcs_ansi_cp(UINT ansi_cp)
2307 {
2308     return ( ansi_cp == 932       /* CP932 for Japanese */
2309             || ansi_cp == 936     /* CP936 for Chinese Simplified */
2310             || ansi_cp == 949     /* CP949 for Korean */
2311             || ansi_cp == 950 );  /* CP950 for Chinese Traditional */
2312 }
2313
2314 static inline HKEY create_fonts_NT_registry_key(void)
2315 {
2316     HKEY hkey = 0;
2317
2318     RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key, 0, NULL,
2319                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2320     return hkey;
2321 }
2322
2323 static inline HKEY create_fonts_9x_registry_key(void)
2324 {
2325     HKEY hkey = 0;
2326
2327     RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key, 0, NULL,
2328                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2329     return hkey;
2330 }
2331
2332 static inline HKEY create_config_fonts_registry_key(void)
2333 {
2334     HKEY hkey = 0;
2335
2336     RegCreateKeyExW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, 0, NULL,
2337                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2338     return hkey;
2339 }
2340
2341 static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl)
2342 {
2343     RegSetValueExA(hkey, "Courier", 0, REG_SZ, (const BYTE *)fl->courier, strlen(fl->courier)+1);
2344     RegSetValueExA(hkey, "MS Serif", 0, REG_SZ, (const BYTE *)fl->serif, strlen(fl->serif)+1);
2345     RegSetValueExA(hkey, "MS Sans Serif", 0, REG_SZ, (const BYTE *)fl->sserif, strlen(fl->sserif)+1);
2346     RegSetValueExA(hkey, "Small Fonts", 0, REG_SZ, (const BYTE *)fl->small, strlen(fl->small)+1);
2347 }
2348
2349 static void set_value_key(HKEY hkey, const char *name, const char *value)
2350 {
2351     if (value)
2352         RegSetValueExA(hkey, name, 0, REG_SZ, (const BYTE *)value, strlen(value) + 1);
2353     else if (name)
2354         RegDeleteValueA(hkey, name);
2355 }
2356
2357 static void update_font_info(void)
2358 {
2359     char buf[40], cpbuf[40];
2360     DWORD len, type;
2361     HKEY hkey = 0;
2362     UINT i, ansi_cp = 0, oem_cp = 0;
2363     BOOL done = FALSE;
2364
2365     if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL) != ERROR_SUCCESS)
2366         return;
2367
2368     GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
2369                    (WCHAR *)&ansi_cp, sizeof(ansi_cp)/sizeof(WCHAR));
2370     GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTCODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
2371                    (WCHAR *)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR));
2372     sprintf( cpbuf, "%u,%u", ansi_cp, oem_cp );
2373
2374     /* Setup Default_Fallback usage for DBCS ANSI codepages */
2375     if (is_dbcs_ansi_cp(ansi_cp))
2376         use_default_fallback = TRUE;
2377
2378     len = sizeof(buf);
2379     if (RegQueryValueExA(hkey, "Codepages", 0, &type, (BYTE *)buf, &len) == ERROR_SUCCESS && type == REG_SZ)
2380     {
2381         if (!strcmp( buf, cpbuf ))  /* already set correctly */
2382         {
2383             RegCloseKey(hkey);
2384             return;
2385         }
2386         TRACE("updating registry, codepages changed %s -> %u,%u\n", buf, ansi_cp, oem_cp);
2387     }
2388     else TRACE("updating registry, codepages changed none -> %u,%u\n", ansi_cp, oem_cp);
2389
2390     RegSetValueExA(hkey, "Codepages", 0, REG_SZ, (const BYTE *)cpbuf, strlen(cpbuf)+1);
2391     RegCloseKey(hkey);
2392
2393     for (i = 0; i < sizeof(nls_update_font_list)/sizeof(nls_update_font_list[0]); i++)
2394     {
2395         HKEY hkey;
2396
2397         if (nls_update_font_list[i].ansi_cp == ansi_cp &&
2398             nls_update_font_list[i].oem_cp == oem_cp)
2399         {
2400             hkey = create_config_fonts_registry_key();
2401             RegSetValueExA(hkey, "OEMFONT.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].oem, strlen(nls_update_font_list[i].oem)+1);
2402             RegSetValueExA(hkey, "FIXEDFON.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].fixed, strlen(nls_update_font_list[i].fixed)+1);
2403             RegSetValueExA(hkey, "FONTS.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].system, strlen(nls_update_font_list[i].system)+1);
2404             RegCloseKey(hkey);
2405
2406             hkey = create_fonts_NT_registry_key();
2407             add_font_list(hkey, &nls_update_font_list[i]);
2408             RegCloseKey(hkey);
2409
2410             hkey = create_fonts_9x_registry_key();
2411             add_font_list(hkey, &nls_update_font_list[i]);
2412             RegCloseKey(hkey);
2413
2414             if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
2415             {
2416                 RegSetValueExA(hkey, "MS Shell Dlg", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].shelldlg,
2417                                strlen(nls_update_font_list[i].shelldlg)+1);
2418                 RegSetValueExA(hkey, "Tms Rmn", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].tmsrmn,
2419                                strlen(nls_update_font_list[i].tmsrmn)+1);
2420
2421                 set_value_key(hkey, "Fixedsys,0", nls_update_font_list[i].fixed_0);
2422                 set_value_key(hkey, "System,0", nls_update_font_list[i].system_0);
2423                 set_value_key(hkey, "Courier,0", nls_update_font_list[i].courier_0);
2424                 set_value_key(hkey, "MS Serif,0", nls_update_font_list[i].serif_0);
2425                 set_value_key(hkey, "Small Fonts,0", nls_update_font_list[i].small_0);
2426                 set_value_key(hkey, "MS Sans Serif,0", nls_update_font_list[i].sserif_0);
2427                 set_value_key(hkey, "Helv,0", nls_update_font_list[i].helv_0);
2428                 set_value_key(hkey, "Tms Rmn,0", nls_update_font_list[i].tmsrmn_0);
2429
2430                 set_value_key(hkey, nls_update_font_list[i].arial_0.from, nls_update_font_list[i].arial_0.to);
2431                 set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, nls_update_font_list[i].courier_new_0.to);
2432                 set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, nls_update_font_list[i].times_new_roman_0.to);
2433
2434                 RegCloseKey(hkey);
2435             }
2436             done = TRUE;
2437         }
2438         else
2439         {
2440             /* Delete the FontSubstitutes from other locales */
2441             if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
2442             {
2443                 set_value_key(hkey, nls_update_font_list[i].arial_0.from, NULL);
2444                 set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, NULL);
2445                 set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, NULL);
2446                 RegCloseKey(hkey);
2447             }
2448         }
2449     }
2450     if (!done)
2451         FIXME("there is no font defaults for codepages %u,%u\n", ansi_cp, oem_cp);
2452 }
2453
2454
2455 static BOOL init_freetype(void)
2456 {
2457     ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0);
2458     if(!ft_handle) {
2459         WINE_MESSAGE(
2460       "Wine cannot find the FreeType font library.  To enable Wine to\n"
2461       "use TrueType fonts please install a version of FreeType greater than\n"
2462       "or equal to 2.0.5.\n"
2463       "http://www.freetype.org\n");
2464         return FALSE;
2465     }
2466
2467 #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;}
2468
2469     LOAD_FUNCPTR(FT_Vector_Unit)
2470     LOAD_FUNCPTR(FT_Done_Face)
2471     LOAD_FUNCPTR(FT_Get_Char_Index)
2472     LOAD_FUNCPTR(FT_Get_Module)
2473     LOAD_FUNCPTR(FT_Get_Sfnt_Name)
2474     LOAD_FUNCPTR(FT_Get_Sfnt_Name_Count)
2475     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
2476     LOAD_FUNCPTR(FT_Init_FreeType)
2477     LOAD_FUNCPTR(FT_Load_Glyph)
2478     LOAD_FUNCPTR(FT_Matrix_Multiply)
2479 #ifndef FT_MULFIX_INLINED
2480     LOAD_FUNCPTR(FT_MulFix)
2481 #endif
2482     LOAD_FUNCPTR(FT_New_Face)
2483     LOAD_FUNCPTR(FT_New_Memory_Face)
2484     LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
2485     LOAD_FUNCPTR(FT_Outline_Transform)
2486     LOAD_FUNCPTR(FT_Outline_Translate)
2487     LOAD_FUNCPTR(FT_Select_Charmap)
2488     LOAD_FUNCPTR(FT_Set_Charmap)
2489     LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
2490     LOAD_FUNCPTR(FT_Vector_Transform)
2491     LOAD_FUNCPTR(FT_Render_Glyph)
2492
2493 #undef LOAD_FUNCPTR
2494     /* Don't warn if these ones are missing */
2495     pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0);
2496     pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0);
2497     pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0);
2498     pFT_Get_Next_Char = wine_dlsym(ft_handle, "FT_Get_Next_Char", NULL, 0);
2499     pFT_Get_TrueType_Engine_Type = wine_dlsym(ft_handle, "FT_Get_TrueType_Engine_Type", NULL, 0);
2500 #ifdef HAVE_FREETYPE_FTLCDFIL_H
2501     pFT_Library_SetLcdFilter = wine_dlsym(ft_handle, "FT_Library_SetLcdFilter", NULL, 0);
2502 #endif
2503 #ifdef HAVE_FREETYPE_FTWINFNT_H
2504     pFT_Get_WinFNT_Header = wine_dlsym(ft_handle, "FT_Get_WinFNT_Header", NULL, 0);
2505 #endif
2506       if(!wine_dlsym(ft_handle, "FT_Get_Postscript_Name", NULL, 0) &&
2507          !wine_dlsym(ft_handle, "FT_Sqrt64", NULL, 0)) {
2508         /* try to avoid 2.0.4: >= 2.0.5 has FT_Get_Postscript_Name and
2509            <= 2.0.3 has FT_Sqrt64 */
2510           goto sym_not_found;
2511       }
2512
2513     if(pFT_Init_FreeType(&library) != 0) {
2514         ERR("Can't init FreeType library\n");
2515         wine_dlclose(ft_handle, NULL, 0);
2516         ft_handle = NULL;
2517         return FALSE;
2518     }
2519     FT_Version.major = FT_Version.minor = FT_Version.patch = -1;
2520     if (pFT_Library_Version)
2521         pFT_Library_Version(library,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
2522
2523     if (FT_Version.major<=0)
2524     {
2525         FT_Version.major=2;
2526         FT_Version.minor=0;
2527         FT_Version.patch=5;
2528     }
2529     TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
2530     FT_SimpleVersion = ((FT_Version.major << 16) & 0xff0000) |
2531                        ((FT_Version.minor <<  8) & 0x00ff00) |
2532                        ((FT_Version.patch      ) & 0x0000ff);
2533
2534     return TRUE;
2535
2536 sym_not_found:
2537     WINE_MESSAGE(
2538       "Wine cannot find certain functions that it needs inside the FreeType\n"
2539       "font library.  To enable Wine to use TrueType fonts please upgrade\n"
2540       "FreeType to at least version 2.0.5.\n"
2541       "http://www.freetype.org\n");
2542     wine_dlclose(ft_handle, NULL, 0);
2543     ft_handle = NULL;
2544     return FALSE;
2545 }
2546
2547 /*************************************************************
2548  *    WineEngInit
2549  *
2550  * Initialize FreeType library and create a list of available faces
2551  */
2552 BOOL WineEngInit(void)
2553 {
2554     static const WCHAR dot_fonW[] = {'.','f','o','n','\0'};
2555     static const WCHAR pathW[] = {'P','a','t','h',0};
2556     HKEY hkey;
2557     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
2558     LPVOID data;
2559     WCHAR windowsdir[MAX_PATH];
2560     char *unixname;
2561     HANDLE font_mutex;
2562     const char *data_dir;
2563
2564     TRACE("\n");
2565
2566     /* update locale dependent font info in registry */
2567     update_font_info();
2568
2569     if(!init_freetype()) return FALSE;
2570
2571     if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) {
2572         ERR("Failed to create font mutex\n");
2573         return FALSE;
2574     }
2575     WaitForSingleObject(font_mutex, INFINITE);
2576
2577     delete_external_font_keys();
2578
2579     /* load the system bitmap fonts */
2580     load_system_fonts();
2581
2582     /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
2583     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
2584     strcatW(windowsdir, fontsW);
2585     if((unixname = wine_get_unix_file_name(windowsdir)))
2586     {
2587         ReadFontDir(unixname, FALSE);
2588         HeapFree(GetProcessHeap(), 0, unixname);
2589     }
2590
2591     /* load the system truetype fonts */
2592     data_dir = wine_get_data_dir();
2593     if (!data_dir) data_dir = wine_get_build_dir();
2594     if (data_dir && (unixname = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + sizeof("/fonts/")))) {
2595         strcpy(unixname, data_dir);
2596         strcat(unixname, "/fonts/");
2597         ReadFontDir(unixname, TRUE);
2598         HeapFree(GetProcessHeap(), 0, unixname);
2599     }
2600
2601     /* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
2602        for any fonts not installed in %WINDOWSDIR%\Fonts.  They will have their
2603        full path as the entry.  Also look for any .fon fonts, since ReadFontDir
2604        will skip these. */
2605     if(RegOpenKeyW(HKEY_LOCAL_MACHINE,
2606                    is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
2607                    &hkey) == ERROR_SUCCESS) {
2608         LPWSTR valueW;
2609         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2610                          &valuelen, &datalen, NULL, NULL);
2611
2612         valuelen++; /* returned value doesn't include room for '\0' */
2613         valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
2614         data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
2615         if (valueW && data)
2616         {
2617             dlen = datalen * sizeof(WCHAR);
2618             vlen = valuelen;
2619             while(RegEnumValueW(hkey, i++, valueW, &vlen, NULL, &type, data,
2620                                 &dlen) == ERROR_SUCCESS) {
2621                 if(((LPWSTR)data)[0] && ((LPWSTR)data)[1] == ':')
2622                 {
2623                     if((unixname = wine_get_unix_file_name((LPWSTR)data)))
2624                     {
2625                         AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
2626                         HeapFree(GetProcessHeap(), 0, unixname);
2627                     }
2628                 }
2629                 else if(dlen / 2 >= 6 && !strcmpiW(((LPWSTR)data) + dlen / 2 - 5, dot_fonW))
2630                 {
2631                     WCHAR pathW[MAX_PATH];
2632                     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
2633                     BOOL added = FALSE;
2634
2635                     sprintfW(pathW, fmtW, windowsdir, data);
2636                     if((unixname = wine_get_unix_file_name(pathW)))
2637                     {
2638                         added = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
2639                         HeapFree(GetProcessHeap(), 0, unixname);
2640                     }
2641                     if (!added)
2642                         load_font_from_data_dir(data);
2643                 }
2644                 /* reset dlen and vlen */
2645                 dlen = datalen;
2646                 vlen = valuelen;
2647             }
2648         }
2649         HeapFree(GetProcessHeap(), 0, data);
2650         HeapFree(GetProcessHeap(), 0, valueW);
2651         RegCloseKey(hkey);
2652     }
2653
2654     load_fontconfig_fonts();
2655
2656     /* then look in any directories that we've specified in the config file */
2657     /* @@ Wine registry key: HKCU\Software\Wine\Fonts */
2658     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", &hkey) == ERROR_SUCCESS)
2659     {
2660         DWORD len;
2661         LPWSTR valueW;
2662         LPSTR valueA, ptr;
2663
2664         if (RegQueryValueExW( hkey, pathW, NULL, NULL, NULL, &len ) == ERROR_SUCCESS)
2665         {
2666             len += sizeof(WCHAR);
2667             valueW = HeapAlloc( GetProcessHeap(), 0, len );
2668             if (RegQueryValueExW( hkey, pathW, NULL, NULL, (LPBYTE)valueW, &len ) == ERROR_SUCCESS)
2669             {
2670                 len = WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, NULL, 0, NULL, NULL );
2671                 valueA = HeapAlloc( GetProcessHeap(), 0, len );
2672                 WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, valueA, len, NULL, NULL );
2673                 TRACE( "got font path %s\n", debugstr_a(valueA) );
2674                 ptr = valueA;
2675                 while (ptr)
2676                 {
2677                     LPSTR next = strchr( ptr, ':' );
2678                     if (next) *next++ = 0;
2679                     ReadFontDir( ptr, TRUE );
2680                     ptr = next;
2681                 }
2682                 HeapFree( GetProcessHeap(), 0, valueA );
2683             }
2684             HeapFree( GetProcessHeap(), 0, valueW );
2685         }
2686         RegCloseKey(hkey);
2687     }
2688
2689     DumpFontList();
2690     LoadSubstList();
2691     DumpSubstList();
2692     LoadReplaceList();
2693     update_reg_entries();
2694
2695     init_system_links();
2696     
2697     ReleaseMutex(font_mutex);
2698     return TRUE;
2699 }
2700
2701
2702 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
2703 {
2704     TT_OS2 *pOS2;
2705     TT_HoriHeader *pHori;
2706
2707     LONG ppem;
2708
2709     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
2710     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
2711
2712     if(height == 0) height = 16;
2713
2714     /* Calc. height of EM square:
2715      *
2716      * For +ve lfHeight we have
2717      * lfHeight = (winAscent + winDescent) * ppem / units_per_em
2718      * Re-arranging gives:
2719      * ppem = units_per_em * lfheight / (winAscent + winDescent)
2720      *
2721      * For -ve lfHeight we have
2722      * |lfHeight| = ppem
2723      * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
2724      * with il = winAscent + winDescent - units_per_em]
2725      *
2726      */
2727
2728     if(height > 0) {
2729         if(pOS2->usWinAscent + pOS2->usWinDescent == 0)
2730             ppem = MulDiv(ft_face->units_per_EM, height,
2731                           pHori->Ascender - pHori->Descender);
2732         else
2733             ppem = MulDiv(ft_face->units_per_EM, height,
2734                           pOS2->usWinAscent + pOS2->usWinDescent);
2735     }
2736     else
2737         ppem = -height;
2738
2739     return ppem;
2740 }
2741
2742 static struct font_mapping *map_font_file( const char *name )
2743 {
2744     struct font_mapping *mapping;
2745     struct stat st;
2746     int fd;
2747
2748     if ((fd = open( name, O_RDONLY )) == -1) return NULL;
2749     if (fstat( fd, &st ) == -1) goto error;
2750
2751     LIST_FOR_EACH_ENTRY( mapping, &mappings_list, struct font_mapping, entry )
2752     {
2753         if (mapping->dev == st.st_dev && mapping->ino == st.st_ino)
2754         {
2755             mapping->refcount++;
2756             close( fd );
2757             return mapping;
2758         }
2759     }
2760     if (!(mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(*mapping) )))
2761         goto error;
2762
2763     mapping->data = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
2764     close( fd );
2765
2766     if (mapping->data == MAP_FAILED)
2767     {
2768         HeapFree( GetProcessHeap(), 0, mapping );
2769         return NULL;
2770     }
2771     mapping->refcount = 1;
2772     mapping->dev = st.st_dev;
2773     mapping->ino = st.st_ino;
2774     mapping->size = st.st_size;
2775     list_add_tail( &mappings_list, &mapping->entry );
2776     return mapping;
2777
2778 error:
2779     close( fd );
2780     return NULL;
2781 }
2782
2783 static void unmap_font_file( struct font_mapping *mapping )
2784 {
2785     if (!--mapping->refcount)
2786     {
2787         list_remove( &mapping->entry );
2788         munmap( mapping->data, mapping->size );
2789         HeapFree( GetProcessHeap(), 0, mapping );
2790     }
2791 }
2792
2793 static LONG load_VDMX(GdiFont*, LONG);
2794
2795 static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height)
2796 {
2797     FT_Error err;
2798     FT_Face ft_face;
2799     void *data_ptr;
2800     DWORD data_size;
2801
2802     TRACE("%s/%p, %ld, %d x %d\n", debugstr_a(face->file), face->font_data_ptr, face->face_index, width, height);
2803
2804     if (face->file)
2805     {
2806         if (!(font->mapping = map_font_file( face->file )))
2807         {
2808             WARN("failed to map %s\n", debugstr_a(face->file));
2809             return 0;
2810         }
2811         data_ptr = font->mapping->data;
2812         data_size = font->mapping->size;
2813     }
2814     else
2815     {
2816         data_ptr = face->font_data_ptr;
2817         data_size = face->font_data_size;
2818     }
2819
2820     err = pFT_New_Memory_Face(library, data_ptr, data_size, face->face_index, &ft_face);
2821     if(err) {
2822         ERR("FT_New_Face rets %d\n", err);
2823         return 0;
2824     }
2825
2826     /* set it here, as load_VDMX needs it */
2827     font->ft_face = ft_face;
2828
2829     if(FT_IS_SCALABLE(ft_face)) {
2830         /* load the VDMX table if we have one */
2831         font->ppem = load_VDMX(font, height);
2832         if(font->ppem == 0)
2833             font->ppem = calc_ppem_for_height(ft_face, height);
2834         TRACE("height %d => ppem %d\n", height, font->ppem);
2835
2836         if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0)
2837             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", 0, font->ppem, err);
2838     } else {
2839         font->ppem = height;
2840         if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
2841             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", width, height, err);
2842     }
2843     return ft_face;
2844 }
2845
2846
2847 static int get_nearest_charset(Face *face, int *cp)
2848 {
2849   /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
2850      a single face with the requested charset.  The idea is to check if
2851      the selected font supports the current ANSI codepage, if it does
2852      return the corresponding charset, else return the first charset */
2853
2854     CHARSETINFO csi;
2855     int acp = GetACP(), i;
2856     DWORD fs0;
2857
2858     *cp = acp;
2859     if(TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE))
2860         if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
2861             return csi.ciCharset;
2862
2863     for(i = 0; i < 32; i++) {
2864         fs0 = 1L << i;
2865         if(face->fs.fsCsb[0] & fs0) {
2866             if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG)) {
2867                 *cp = csi.ciACP;
2868                 return csi.ciCharset;
2869             }
2870             else
2871                 FIXME("TCI failing on %x\n", fs0);
2872         }
2873     }
2874
2875     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08x file = %s\n",
2876           face->fs.fsCsb[0], face->file);
2877     *cp = acp;
2878     return DEFAULT_CHARSET;
2879 }
2880
2881 static GdiFont *alloc_font(void)
2882 {
2883     GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
2884     ret->gmsize = 1;
2885     ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM*));
2886     ret->gm[0] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
2887     ret->potm = NULL;
2888     ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
2889     ret->total_kern_pairs = (DWORD)-1;
2890     ret->kern_pairs = NULL;
2891     list_init(&ret->hfontlist);
2892     list_init(&ret->child_fonts);
2893     return ret;
2894 }
2895
2896 static void free_font(GdiFont *font)
2897 {
2898     struct list *cursor, *cursor2;
2899     DWORD i;
2900
2901     LIST_FOR_EACH_SAFE(cursor, cursor2, &font->child_fonts)
2902     {
2903         CHILD_FONT *child = LIST_ENTRY(cursor, CHILD_FONT, entry);
2904         struct list *first_hfont;
2905         HFONTLIST *hfontlist;
2906         list_remove(cursor);
2907         if(child->font)
2908         {
2909             first_hfont = list_head(&child->font->hfontlist);
2910             hfontlist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
2911             DeleteObject(hfontlist->hfont);
2912             HeapFree(GetProcessHeap(), 0, hfontlist);
2913             free_font(child->font);
2914         }
2915         HeapFree(GetProcessHeap(), 0, child);
2916     }
2917
2918     if (font->ft_face) pFT_Done_Face(font->ft_face);
2919     if (font->mapping) unmap_font_file( font->mapping );
2920     HeapFree(GetProcessHeap(), 0, font->kern_pairs);
2921     HeapFree(GetProcessHeap(), 0, font->potm);
2922     HeapFree(GetProcessHeap(), 0, font->name);
2923     for (i = 0; i < font->gmsize; i++)
2924         HeapFree(GetProcessHeap(),0,font->gm[i]);
2925     HeapFree(GetProcessHeap(), 0, font->gm);
2926     HeapFree(GetProcessHeap(), 0, font->GSUB_Table);
2927     HeapFree(GetProcessHeap(), 0, font);
2928 }
2929
2930
2931 /*************************************************************
2932  * load_VDMX
2933  *
2934  * load the vdmx entry for the specified height
2935  */
2936
2937 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
2938           ( ( (FT_ULong)_x4 << 24 ) |     \
2939             ( (FT_ULong)_x3 << 16 ) |     \
2940             ( (FT_ULong)_x2 <<  8 ) |     \
2941               (FT_ULong)_x1         )
2942
2943 #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X')
2944
2945 typedef struct {
2946     BYTE bCharSet;
2947     BYTE xRatio;
2948     BYTE yStartRatio;
2949     BYTE yEndRatio;
2950 } Ratios;
2951
2952 typedef struct {
2953     WORD recs;
2954     BYTE startsz;
2955     BYTE endsz;
2956 } VDMX_group;
2957
2958 static LONG load_VDMX(GdiFont *font, LONG height)
2959 {
2960     WORD hdr[3], tmp;
2961     VDMX_group group;
2962     BYTE devXRatio, devYRatio;
2963     USHORT numRecs, numRatios;
2964     DWORD result, offset = -1;
2965     LONG ppem = 0;
2966     int i;
2967
2968     result = WineEngGetFontData(font, MS_VDMX_TAG, 0, hdr, 6);
2969
2970     if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
2971         return ppem;
2972
2973     /* FIXME: need the real device aspect ratio */
2974     devXRatio = 1;
2975     devYRatio = 1;
2976
2977     numRecs = GET_BE_WORD(hdr[1]);
2978     numRatios = GET_BE_WORD(hdr[2]);
2979
2980     TRACE("numRecs = %d numRatios = %d\n", numRecs, numRatios);
2981     for(i = 0; i < numRatios; i++) {
2982         Ratios ratio;
2983
2984         offset = (3 * 2) + (i * sizeof(Ratios));
2985         WineEngGetFontData(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
2986         offset = -1;
2987
2988         TRACE("Ratios[%d] %d  %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
2989
2990         if((ratio.xRatio == 0 &&
2991             ratio.yStartRatio == 0 &&
2992             ratio.yEndRatio == 0) ||
2993            (devXRatio == ratio.xRatio &&
2994             devYRatio >= ratio.yStartRatio &&
2995             devYRatio <= ratio.yEndRatio))
2996             {
2997                 offset = (3 * 2) + (numRatios * 4) + (i * 2);
2998                 WineEngGetFontData(font, MS_VDMX_TAG, offset, &tmp, 2);
2999                 offset = GET_BE_WORD(tmp);
3000                 break;
3001             }
3002     }
3003
3004     if(offset == -1) {
3005         FIXME("No suitable ratio found\n");
3006         return ppem;
3007     }
3008
3009     if(WineEngGetFontData(font, MS_VDMX_TAG, offset, &group, 4) != GDI_ERROR) {
3010         USHORT recs;
3011         BYTE startsz, endsz;
3012         WORD *vTable;
3013
3014         recs = GET_BE_WORD(group.recs);
3015         startsz = group.startsz;
3016         endsz = group.endsz;
3017
3018         TRACE("recs=%d  startsz=%d  endsz=%d\n", recs, startsz, endsz);
3019
3020         vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6);
3021         result = WineEngGetFontData(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6);
3022         if(result == GDI_ERROR) {
3023             FIXME("Failed to retrieve vTable\n");
3024             goto end;
3025         }
3026
3027         if(height > 0) {
3028             for(i = 0; i < recs; i++) {
3029                 SHORT yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
3030                 SHORT yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
3031                 ppem = GET_BE_WORD(vTable[i * 3]);
3032
3033                 if(yMax + -yMin == height) {
3034                     font->yMax = yMax;
3035                     font->yMin = yMin;
3036                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
3037                     break;
3038                 }
3039                 if(yMax + -yMin > height) {
3040                     if(--i < 0) {
3041                         ppem = 0;
3042                         goto end; /* failed */
3043                     }
3044                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
3045                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
3046                     ppem = GET_BE_WORD(vTable[i * 3]);
3047                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
3048                     break;
3049                 }
3050             }
3051             if(!font->yMax) {
3052                 ppem = 0;
3053                 TRACE("ppem not found for height %d\n", height);
3054             }
3055         } else {
3056             ppem = -height;
3057             if(ppem < startsz || ppem > endsz)
3058                 goto end;
3059
3060             for(i = 0; i < recs; i++) {
3061                 USHORT yPelHeight;
3062                 yPelHeight = GET_BE_WORD(vTable[i * 3]);
3063
3064                 if(yPelHeight > ppem)
3065                     break; /* failed */
3066
3067                 if(yPelHeight == ppem) {
3068                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
3069                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
3070                     TRACE("ppem %d found; yMax=%d  yMin=%d\n", ppem, font->yMax, font->yMin);
3071                     break;
3072                 }
3073             }
3074         }
3075         end:
3076         HeapFree(GetProcessHeap(), 0, vTable);
3077     }
3078
3079     return ppem;
3080 }
3081
3082 static BOOL fontcmp(const GdiFont *font, FONT_DESC *fd)
3083 {
3084     if(font->font_desc.hash != fd->hash) return TRUE;
3085     if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE;
3086     if(memcmp(&font->font_desc.lf, &fd->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
3087     if(!font->font_desc.can_use_bitmap != !fd->can_use_bitmap) return TRUE;
3088     return strcmpiW(font->font_desc.lf.lfFaceName, fd->lf.lfFaceName);
3089 }
3090
3091 static void calc_hash(FONT_DESC *pfd)
3092 {
3093     DWORD hash = 0, *ptr, two_chars;
3094     WORD *pwc;
3095     unsigned int i;
3096
3097     for(i = 0, ptr = (DWORD*)&pfd->matrix; i < sizeof(FMAT2)/sizeof(DWORD); i++, ptr++)
3098         hash ^= *ptr;
3099     for(i = 0, ptr = (DWORD*)&pfd->lf; i < 7; i++, ptr++)
3100         hash ^= *ptr;
3101     for(i = 0, ptr = (DWORD*)pfd->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
3102         two_chars = *ptr;
3103         pwc = (WCHAR *)&two_chars;
3104         if(!*pwc) break;
3105         *pwc = toupperW(*pwc);
3106         pwc++;
3107         *pwc = toupperW(*pwc);
3108         hash ^= two_chars;
3109         if(!*pwc) break;
3110     }
3111     hash ^= !pfd->can_use_bitmap;
3112     pfd->hash = hash;
3113     return;
3114 }
3115
3116 static GdiFont *find_in_cache(HFONT hfont, const LOGFONTW *plf, const FMAT2 *pmat, BOOL can_use_bitmap)
3117 {
3118     GdiFont *ret;
3119     FONT_DESC fd;
3120     HFONTLIST *hflist;
3121     struct list *font_elem_ptr, *hfontlist_elem_ptr;
3122
3123     fd.lf = *plf;
3124     fd.matrix = *pmat;
3125     fd.can_use_bitmap = can_use_bitmap;
3126     calc_hash(&fd);
3127
3128     /* try the child list */
3129     LIST_FOR_EACH(font_elem_ptr, &child_font_list) {
3130         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3131         if(!fontcmp(ret, &fd)) {
3132             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
3133             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
3134                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3135                 if(hflist->hfont == hfont)
3136                     return ret;
3137             }
3138         }
3139     }
3140
3141     /* try the in-use list */
3142     LIST_FOR_EACH(font_elem_ptr, &gdi_font_list) {
3143         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3144         if(!fontcmp(ret, &fd)) {
3145             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
3146             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
3147                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3148                 if(hflist->hfont == hfont)
3149                     return ret;
3150             }
3151             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3152             hflist->hfont = hfont;
3153             list_add_head(&ret->hfontlist, &hflist->entry);
3154             return ret;
3155         }
3156     }
3157  
3158     /* then the unused list */
3159     font_elem_ptr = list_head(&unused_gdi_font_list);
3160     while(font_elem_ptr) {
3161         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3162         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
3163         if(!fontcmp(ret, &fd)) {
3164             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
3165             assert(list_empty(&ret->hfontlist));
3166             TRACE("Found %p in unused list\n", ret);
3167             list_remove(&ret->entry);
3168             list_add_head(&gdi_font_list, &ret->entry);
3169             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3170             hflist->hfont = hfont;
3171             list_add_head(&ret->hfontlist, &hflist->entry);
3172             return ret;
3173         }
3174     }
3175     return NULL;
3176 }
3177
3178 static void add_to_cache(GdiFont *font)
3179 {
3180     static DWORD cache_num = 1;
3181
3182     font->cache_num = cache_num++;
3183     list_add_head(&gdi_font_list, &font->entry);
3184 }
3185
3186 /*************************************************************
3187  * create_child_font_list
3188  */
3189 static BOOL create_child_font_list(GdiFont *font)
3190 {
3191     BOOL ret = FALSE;
3192     SYSTEM_LINKS *font_link;
3193     CHILD_FONT *font_link_entry, *new_child;
3194
3195     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3196     {
3197         if(!strcmpW(font_link->font_name, font->name))
3198         {
3199             TRACE("found entry in system list\n");
3200             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3201             {
3202                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
3203                 new_child->face = font_link_entry->face;
3204                 new_child->font = NULL;
3205                 list_add_tail(&font->child_fonts, &new_child->entry);
3206                 TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
3207             }
3208             ret = TRUE;
3209             break;
3210         }
3211     }
3212     /*
3213      * if not SYMBOL or OEM then we also get all the fonts for Microsoft
3214      * Sans Serif.  This is how asian windows get default fallbacks for fonts
3215      */
3216     if (use_default_fallback && font->charset != SYMBOL_CHARSET &&
3217         font->charset != OEM_CHARSET &&
3218         strcmpW(font->name,szDefaultFallbackLink) != 0)
3219         LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3220         {
3221             if(!strcmpW(font_link->font_name,szDefaultFallbackLink))
3222             {
3223                 TRACE("found entry in default fallback list\n");
3224                 LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3225                 {
3226                     new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
3227                     new_child->face = font_link_entry->face;
3228                     new_child->font = NULL;
3229                     list_add_tail(&font->child_fonts, &new_child->entry);
3230                     TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
3231                 }
3232                 ret = TRUE;
3233                 break;
3234             }
3235         }
3236
3237     return ret;
3238 }
3239
3240 static BOOL select_charmap(FT_Face ft_face, FT_Encoding encoding)
3241 {
3242     FT_Error ft_err = FT_Err_Invalid_CharMap_Handle;
3243
3244     if (pFT_Set_Charmap)
3245     {
3246         FT_Int i;
3247         FT_CharMap cmap0, cmap1, cmap2, cmap3, cmap_def;
3248
3249         cmap0 = cmap1 = cmap2 = cmap3 = cmap_def = NULL;
3250
3251         for (i = 0; i < ft_face->num_charmaps; i++)
3252         {
3253             if (ft_face->charmaps[i]->encoding == encoding)
3254             {
3255                 TRACE("found cmap with platform_id %u, encoding_id %u\n",
3256                        ft_face->charmaps[i]->platform_id, ft_face->charmaps[i]->encoding_id);
3257
3258                 switch (ft_face->charmaps[i]->platform_id)
3259                 {
3260                     default:
3261                         cmap_def = ft_face->charmaps[i];
3262                         break;
3263                     case 0: /* Apple Unicode */
3264                         cmap0 = ft_face->charmaps[i];
3265                         break;
3266                     case 1: /* Macintosh */
3267                         cmap1 = ft_face->charmaps[i];
3268                         break;
3269                     case 2: /* ISO */
3270                         cmap2 = ft_face->charmaps[i];
3271                         break;
3272                     case 3: /* Microsoft */
3273                         cmap3 = ft_face->charmaps[i];
3274                         break;
3275                 }
3276             }
3277
3278             if (cmap3) /* prefer Microsoft cmap table */
3279                 ft_err = pFT_Set_Charmap(ft_face, cmap3);
3280             else if (cmap1)
3281                 ft_err = pFT_Set_Charmap(ft_face, cmap1);
3282             else if (cmap2)
3283                 ft_err = pFT_Set_Charmap(ft_face, cmap2);
3284             else if (cmap0)
3285                 ft_err = pFT_Set_Charmap(ft_face, cmap0);
3286             else if (cmap_def)
3287                 ft_err = pFT_Set_Charmap(ft_face, cmap_def);
3288         }
3289         return ft_err == FT_Err_Ok;
3290     }
3291
3292     return pFT_Select_Charmap(ft_face, encoding) == FT_Err_Ok;
3293 }
3294
3295 /*************************************************************
3296  * WineEngCreateFontInstance
3297  *
3298  */
3299 GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont)
3300 {
3301     GdiFont *ret;
3302     Face *face, *best, *best_bitmap;
3303     Family *family, *last_resort_family;
3304     struct list *family_elem_ptr, *face_elem_ptr;
3305     INT height, width = 0;
3306     unsigned int score = 0, new_score;
3307     signed int diff = 0, newdiff;
3308     BOOL bd, it, can_use_bitmap;
3309     LOGFONTW lf;
3310     CHARSETINFO csi;
3311     HFONTLIST *hflist;
3312     FMAT2 dcmat;
3313     FontSubst *psub = NULL;
3314
3315     if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
3316     lf.lfWidth = abs(lf.lfWidth);
3317
3318     can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
3319
3320     TRACE("%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n",
3321           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
3322           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
3323           lf.lfEscapement);
3324
3325     if(dc->GraphicsMode == GM_ADVANCED)
3326         memcpy(&dcmat, &dc->xformWorld2Vport, sizeof(FMAT2));
3327     else
3328     {
3329         /* Windows 3.1 compatibility mode GM_COMPATIBLE has only limited
3330            font scaling abilities. */
3331         dcmat.eM11 = dcmat.eM22 = fabs(dc->xformWorld2Vport.eM22);
3332         dcmat.eM21 = dcmat.eM12 = 0;
3333     }
3334
3335     /* Try to avoid not necessary glyph transformations */
3336     if (dcmat.eM21 == 0.0 && dcmat.eM12 == 0.0 && dcmat.eM11 == dcmat.eM22)
3337     {
3338         lf.lfHeight *= fabs(dcmat.eM11);
3339         lf.lfWidth *= fabs(dcmat.eM11);
3340         dcmat.eM11 = dcmat.eM22 = 1.0;
3341     }
3342
3343     TRACE("DC transform %f %f %f %f\n", dcmat.eM11, dcmat.eM12,
3344                                         dcmat.eM21, dcmat.eM22);
3345
3346     EnterCriticalSection( &freetype_cs );
3347
3348     /* check the cache first */
3349     if((ret = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap)) != NULL) {
3350         TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
3351         LeaveCriticalSection( &freetype_cs );
3352         return ret;
3353     }
3354
3355     TRACE("not in cache\n");
3356     if(list_empty(&font_list)) /* No fonts installed */
3357     {
3358         TRACE("No fonts installed\n");
3359         LeaveCriticalSection( &freetype_cs );
3360         return NULL;
3361     }
3362     if(!have_installed_roman_font)
3363     {
3364         TRACE("No roman font installed\n");
3365         LeaveCriticalSection( &freetype_cs );
3366         return NULL;
3367     }
3368
3369     ret = alloc_font();
3370
3371     ret->font_desc.matrix = dcmat;
3372     ret->font_desc.lf = lf;
3373     ret->font_desc.can_use_bitmap = can_use_bitmap;
3374     calc_hash(&ret->font_desc);
3375     hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3376     hflist->hfont = hfont;
3377     list_add_head(&ret->hfontlist, &hflist->entry);
3378
3379     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
3380        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
3381        original value lfCharSet.  Note this is a special case for
3382        Symbol and doesn't happen at least for "Wingdings*" */
3383
3384     if(!strcmpiW(lf.lfFaceName, SymbolW))
3385         lf.lfCharSet = SYMBOL_CHARSET;
3386
3387     if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
3388         switch(lf.lfCharSet) {
3389         case DEFAULT_CHARSET:
3390             csi.fs.fsCsb[0] = 0;
3391             break;
3392         default:
3393             FIXME("Untranslated charset %d\n", lf.lfCharSet);
3394             csi.fs.fsCsb[0] = 0;
3395             break;
3396         }
3397     }
3398
3399     family = NULL;
3400     if(lf.lfFaceName[0] != '\0') {
3401         SYSTEM_LINKS *font_link;
3402         CHILD_FONT *font_link_entry;
3403         LPWSTR FaceName = lf.lfFaceName;
3404
3405         /*
3406          * Check for a leading '@' this signals that the font is being
3407          * requested in tategaki mode (vertical writing substitution) but
3408          * does not affect the fontface that is to be selected.
3409          */
3410         if (lf.lfFaceName[0]=='@')
3411             FaceName = &lf.lfFaceName[1];
3412
3413         psub = get_font_subst(&font_subst_list, FaceName, lf.lfCharSet);
3414
3415         if(psub) {
3416             TRACE("substituting %s,%d -> %s,%d\n", debugstr_w(FaceName), lf.lfCharSet,
3417                   debugstr_w(psub->to.name), (psub->to.charset != -1) ? psub->to.charset : lf.lfCharSet);
3418             if (psub->to.charset != -1)
3419                 lf.lfCharSet = psub->to.charset;
3420         }
3421
3422         /* We want a match on name and charset or just name if
3423            charset was DEFAULT_CHARSET.  If the latter then
3424            we fixup the returned charset later in get_nearest_charset
3425            where we'll either use the charset of the current ansi codepage
3426            or if that's unavailable the first charset that the font supports.
3427         */
3428         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3429             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3430             if (!strcmpiW(family->FamilyName, FaceName) ||
3431                 (psub && !strcmpiW(family->FamilyName, psub->to.name)))
3432             {
3433                 LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3434                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
3435                     if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
3436                         if(face->scalable || can_use_bitmap)
3437                             goto found;
3438                 }
3439             }
3440         }
3441
3442         /*
3443          * Try check the SystemLink list first for a replacement font.
3444          * We may find good replacements there.
3445          */
3446         LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3447         {
3448             if(!strcmpiW(font_link->font_name, FaceName) ||
3449                (psub && !strcmpiW(font_link->font_name,psub->to.name)))
3450             {
3451                 TRACE("found entry in system list\n");
3452                 LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3453                 {
3454                     face = font_link_entry->face;
3455                     family = face->family;
3456                     if(csi.fs.fsCsb[0] &
3457                         (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]) || !csi.fs.fsCsb[0])
3458                     {
3459                         if(face->scalable || can_use_bitmap)
3460                             goto found;
3461                     }
3462                 }
3463             }
3464         }
3465     }
3466
3467     psub = NULL; /* substitution is no more relevant */
3468
3469     /* If requested charset was DEFAULT_CHARSET then try using charset
3470        corresponding to the current ansi codepage */
3471     if (!csi.fs.fsCsb[0])
3472     {
3473         INT acp = GetACP();
3474         if(!TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE)) {
3475             FIXME("TCI failed on codepage %d\n", acp);
3476             csi.fs.fsCsb[0] = 0;
3477         } else
3478             lf.lfCharSet = csi.ciCharset;
3479     }
3480
3481     /* Face families are in the top 4 bits of lfPitchAndFamily,
3482        so mask with 0xF0 before testing */
3483
3484     if((lf.lfPitchAndFamily & FIXED_PITCH) ||
3485        (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
3486         strcpyW(lf.lfFaceName, defFixed);
3487     else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
3488         strcpyW(lf.lfFaceName, defSerif);
3489     else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
3490         strcpyW(lf.lfFaceName, defSans);
3491     else
3492         strcpyW(lf.lfFaceName, defSans);
3493     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3494         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3495         if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
3496             LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3497                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
3498                 if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
3499                     if(face->scalable || can_use_bitmap)
3500                         goto found;
3501             }
3502         }
3503     }
3504
3505     last_resort_family = NULL;
3506     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3507         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3508         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3509             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3510             if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) {
3511                 if(face->scalable)
3512                     goto found;
3513                 if(can_use_bitmap && !last_resort_family)
3514                     last_resort_family = family;
3515             }            
3516         }
3517     }
3518
3519     if(last_resort_family) {
3520         family = last_resort_family;
3521         csi.fs.fsCsb[0] = 0;
3522         goto found;
3523     }
3524
3525     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3526         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3527         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3528             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3529             if(face->scalable) {
3530                 csi.fs.fsCsb[0] = 0;
3531                 WARN("just using first face for now\n");
3532                 goto found;
3533             }
3534             if(can_use_bitmap && !last_resort_family)
3535                 last_resort_family = family;
3536         }
3537     }
3538     if(!last_resort_family) {
3539         FIXME("can't find a single appropriate font - bailing\n");
3540         free_font(ret);
3541         LeaveCriticalSection( &freetype_cs );
3542         return NULL;
3543     }
3544
3545     WARN("could only find a bitmap font - this will probably look awful!\n");
3546     family = last_resort_family;
3547     csi.fs.fsCsb[0] = 0;
3548
3549 found:
3550     it = lf.lfItalic ? 1 : 0;
3551     bd = lf.lfWeight > 550 ? 1 : 0;
3552
3553     height = lf.lfHeight;
3554
3555     face = best = best_bitmap = NULL;
3556     LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
3557     {
3558         if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
3559         {
3560             BOOL italic, bold;
3561
3562             italic = (face->ntmFlags & NTM_ITALIC) ? 1 : 0;
3563             bold = (face->ntmFlags & NTM_BOLD) ? 1 : 0;
3564             new_score = (italic ^ it) + (bold ^ bd);
3565             if(!best || new_score <= score)
3566             {
3567                 TRACE("(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n",
3568                       italic, bold, it, bd);
3569                 score = new_score;
3570                 best = face;
3571                 if(best->scalable  && score == 0) break;
3572                 if(!best->scalable)
3573                 {
3574                     if(height > 0)
3575                         newdiff = height - (signed int)(best->size.height);
3576                     else
3577                         newdiff = -height - ((signed int)(best->size.height) - best->size.internal_leading);
3578                     if(!best_bitmap || new_score < score ||
3579                        (diff > 0 && newdiff < diff && newdiff >= 0) || (diff < 0 && newdiff > diff))
3580                     {
3581                         TRACE("%d is better for %d diff was %d\n", best->size.height, height, diff);
3582                         diff = newdiff;
3583                         best_bitmap = best;
3584                         if(score == 0 && diff == 0) break;
3585                     }
3586                 }
3587             }
3588         }
3589     }
3590     if(best)
3591         face = best->scalable ? best : best_bitmap;
3592     ret->fake_italic = (it && !(face->ntmFlags & NTM_ITALIC));
3593     ret->fake_bold = (bd && !(face->ntmFlags & NTM_BOLD));
3594
3595     ret->fs = face->fs;
3596
3597     if(csi.fs.fsCsb[0]) {
3598         ret->charset = lf.lfCharSet;
3599         ret->codepage = csi.ciACP;
3600     }
3601     else
3602         ret->charset = get_nearest_charset(face, &ret->codepage);
3603
3604     TRACE("Chosen: %s %s (%s/%p:%ld)\n", debugstr_w(family->FamilyName),
3605           debugstr_w(face->StyleName), face->file, face->font_data_ptr, face->face_index);
3606
3607     ret->aveWidth = height ? lf.lfWidth : 0;
3608
3609     if(!face->scalable) {
3610         /* Windows uses integer scaling factors for bitmap fonts */
3611         INT scale, scaled_height;
3612
3613         /* FIXME: rotation of bitmap fonts is ignored */
3614         height = abs(GDI_ROUND( (double)height * ret->font_desc.matrix.eM22 ));
3615         if (ret->aveWidth)
3616             ret->aveWidth = (double)ret->aveWidth * ret->font_desc.matrix.eM11;
3617         ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
3618
3619         if (height != 0) height = diff;
3620         height += face->size.height;
3621
3622         scale = (height + face->size.height - 1) / face->size.height;
3623         scaled_height = scale * face->size.height;
3624         /* XP allows not more than 10% deviation */
3625         if (scale > 1 && scaled_height - height > scaled_height / 10) scale--;
3626         ret->scale_y = scale;
3627
3628         width = face->size.x_ppem >> 6;
3629         height = face->size.y_ppem >> 6;
3630     }
3631     else
3632         ret->scale_y = 1.0;
3633     TRACE("font scale y: %f\n", ret->scale_y);
3634
3635     ret->ft_face = OpenFontFace(ret, face, width, height);
3636
3637     if (!ret->ft_face)
3638     {
3639         free_font( ret );
3640         LeaveCriticalSection( &freetype_cs );
3641         return 0;
3642     }
3643
3644     ret->ntmFlags = face->ntmFlags;
3645
3646     if (ret->charset == SYMBOL_CHARSET && 
3647         select_charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) {
3648         /* No ops */
3649     }
3650     else if (select_charmap(ret->ft_face, FT_ENCODING_UNICODE)) {
3651         /* No ops */
3652     }
3653     else {
3654         select_charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN);
3655     }
3656
3657     ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0;
3658     ret->name = psub ? strdupW(psub->from.name) : strdupW(family->FamilyName);
3659     ret->underline = lf.lfUnderline ? 0xff : 0;
3660     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
3661     create_child_font_list(ret);
3662
3663     if (lf.lfFaceName[0]=='@') /* We need to try to load the GSUB table */
3664     {
3665         int length = WineEngGetFontData (ret, GSUB_TAG , 0, NULL, 0);
3666         if (length != GDI_ERROR)
3667         {
3668             ret->GSUB_Table = HeapAlloc(GetProcessHeap(),0,length);
3669             WineEngGetFontData(ret, GSUB_TAG , 0, ret->GSUB_Table, length);
3670             TRACE("Loaded GSUB table of %i bytes\n",length);
3671         }
3672     }
3673
3674     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
3675
3676     add_to_cache(ret);
3677     LeaveCriticalSection( &freetype_cs );
3678     return ret;
3679 }
3680
3681 static void dump_gdi_font_list(void)
3682 {
3683     GdiFont *gdiFont;
3684     struct list *elem_ptr;
3685
3686     TRACE("---------- gdiFont Cache ----------\n");
3687     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
3688         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
3689         TRACE("gdiFont=%p %s %d\n",
3690               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
3691     }
3692
3693     TRACE("---------- Unused gdiFont Cache ----------\n");
3694     LIST_FOR_EACH(elem_ptr, &unused_gdi_font_list) {
3695         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
3696         TRACE("gdiFont=%p %s %d\n",
3697               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
3698     }
3699 }
3700
3701 /*************************************************************
3702  * WineEngDestroyFontInstance
3703  *
3704  * free the gdiFont associated with this handle
3705  *
3706  */
3707 BOOL WineEngDestroyFontInstance(HFONT handle)
3708 {
3709     GdiFont *gdiFont;
3710     HFONTLIST *hflist;
3711     BOOL ret = FALSE;
3712     struct list *font_elem_ptr, *hfontlist_elem_ptr;
3713     int i = 0;
3714
3715     EnterCriticalSection( &freetype_cs );
3716
3717     LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry)
3718     {
3719         struct list *first_hfont = list_head(&gdiFont->hfontlist);
3720         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
3721         if(hflist->hfont == handle)
3722         {
3723             TRACE("removing child font %p from child list\n", gdiFont);
3724             list_remove(&gdiFont->entry);
3725             LeaveCriticalSection( &freetype_cs );
3726             return TRUE;
3727         }
3728     }
3729
3730     TRACE("destroying hfont=%p\n", handle);
3731     if(TRACE_ON(font))
3732         dump_gdi_font_list();
3733
3734     font_elem_ptr = list_head(&gdi_font_list);
3735     while(font_elem_ptr) {
3736         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3737         font_elem_ptr = list_next(&gdi_font_list, font_elem_ptr);
3738
3739         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
3740         while(hfontlist_elem_ptr) {
3741             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3742             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
3743             if(hflist->hfont == handle) {
3744                 list_remove(&hflist->entry);
3745                 HeapFree(GetProcessHeap(), 0, hflist);
3746                 ret = TRUE;
3747             }
3748         }
3749         if(list_empty(&gdiFont->hfontlist)) {
3750             TRACE("Moving to Unused list\n");
3751             list_remove(&gdiFont->entry);
3752             list_add_head(&unused_gdi_font_list, &gdiFont->entry);
3753         }
3754     }
3755
3756
3757     font_elem_ptr = list_head(&unused_gdi_font_list);
3758     while(font_elem_ptr && i++ < UNUSED_CACHE_SIZE)
3759         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
3760     while(font_elem_ptr) {
3761         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3762         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
3763         TRACE("freeing %p\n", gdiFont);
3764         list_remove(&gdiFont->entry);
3765         free_font(gdiFont);
3766     }
3767     LeaveCriticalSection( &freetype_cs );
3768     return ret;
3769 }
3770
3771 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
3772                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
3773 {
3774     GdiFont *font;
3775     LONG width, height;
3776
3777     if (face->cached_enum_data)
3778     {
3779         TRACE("Cached\n");
3780         *pelf = face->cached_enum_data->elf;
3781         *pntm = face->cached_enum_data->ntm;
3782         *ptype = face->cached_enum_data->type;
3783         return;
3784     }
3785
3786     font = alloc_font();
3787
3788     if(face->scalable) {
3789         height = -2048; /* 2048 is the most common em size */
3790         width = 0;
3791     } else {
3792         height = face->size.y_ppem >> 6;
3793         width = face->size.x_ppem >> 6;
3794     }
3795     font->scale_y = 1.0;
3796     
3797     if (!(font->ft_face = OpenFontFace(font, face, width, height)))
3798     {
3799         free_font(font);
3800         return;
3801     }
3802
3803     font->name = strdupW(face->family->FamilyName);
3804     font->ntmFlags = face->ntmFlags;
3805
3806     if (WineEngGetOutlineTextMetrics(font, 0, NULL))
3807     {
3808         memcpy(&pntm->ntmTm, &font->potm->otmTextMetrics, sizeof(TEXTMETRICW));
3809
3810         pntm->ntmTm.ntmSizeEM = font->potm->otmEMSquare;
3811
3812         lstrcpynW(pelf->elfLogFont.lfFaceName,
3813                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFamilyName),
3814                  LF_FACESIZE);
3815         lstrcpynW(pelf->elfFullName,
3816                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFaceName),
3817                  LF_FULLFACESIZE);
3818         lstrcpynW(pelf->elfStyle,
3819                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpStyleName),
3820                  LF_FACESIZE);
3821     }
3822     else
3823     {
3824         WineEngGetTextMetrics(font, (TEXTMETRICW *)&pntm->ntmTm);
3825
3826         pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
3827
3828         lstrcpynW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
3829         lstrcpynW(pelf->elfFullName, face->family->FamilyName, LF_FULLFACESIZE);
3830         lstrcpynW(pelf->elfStyle, face->StyleName, LF_FACESIZE);
3831     }
3832
3833     pntm->ntmTm.ntmFlags = face->ntmFlags;
3834     pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
3835     pntm->ntmTm.ntmAvgWidth = pntm->ntmTm.tmAveCharWidth;
3836     pntm->ntmFontSig = face->fs;
3837
3838     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
3839
3840     pelf->elfLogFont.lfEscapement = 0;
3841     pelf->elfLogFont.lfOrientation = 0;
3842     pelf->elfLogFont.lfHeight = pntm->ntmTm.tmHeight;
3843     pelf->elfLogFont.lfWidth = pntm->ntmTm.tmAveCharWidth;
3844     pelf->elfLogFont.lfWeight = pntm->ntmTm.tmWeight;
3845     pelf->elfLogFont.lfItalic = pntm->ntmTm.tmItalic;
3846     pelf->elfLogFont.lfUnderline = pntm->ntmTm.tmUnderlined;
3847     pelf->elfLogFont.lfStrikeOut = pntm->ntmTm.tmStruckOut;
3848     pelf->elfLogFont.lfCharSet = pntm->ntmTm.tmCharSet;
3849     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
3850     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
3851     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
3852     pelf->elfLogFont.lfPitchAndFamily = (pntm->ntmTm.tmPitchAndFamily & 0xf1) + 1;
3853
3854     *ptype = 0;
3855     if (pntm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE)
3856         *ptype |= TRUETYPE_FONTTYPE;
3857     if (pntm->ntmTm.tmPitchAndFamily & TMPF_DEVICE)
3858         *ptype |= DEVICE_FONTTYPE;
3859     if(!(pntm->ntmTm.tmPitchAndFamily & TMPF_VECTOR))
3860         *ptype |= RASTER_FONTTYPE;
3861
3862     face->cached_enum_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*face->cached_enum_data));
3863     if (face->cached_enum_data)
3864     {
3865         face->cached_enum_data->elf = *pelf;
3866         face->cached_enum_data->ntm = *pntm;
3867         face->cached_enum_data->type = *ptype;
3868     }
3869
3870     free_font(font);
3871 }
3872
3873 /*************************************************************
3874  * WineEngEnumFonts
3875  *
3876  */
3877 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
3878 {
3879     Family *family;
3880     Face *face;
3881     struct list *family_elem_ptr, *face_elem_ptr;
3882     ENUMLOGFONTEXW elf;
3883     NEWTEXTMETRICEXW ntm;
3884     DWORD type;
3885     FONTSIGNATURE fs;
3886     CHARSETINFO csi;
3887     LOGFONTW lf;
3888     int i;
3889
3890     if (!plf)
3891     {
3892         lf.lfCharSet = DEFAULT_CHARSET;
3893         lf.lfPitchAndFamily = 0;
3894         lf.lfFaceName[0] = 0;
3895         plf = &lf;
3896     }
3897
3898     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
3899
3900     EnterCriticalSection( &freetype_cs );
3901     if(plf->lfFaceName[0]) {
3902         FontSubst *psub;
3903         psub = get_font_subst(&font_subst_list, plf->lfFaceName, plf->lfCharSet);
3904
3905         if(psub) {
3906             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
3907                   debugstr_w(psub->to.name));
3908             lf = *plf;
3909             strcpyW(lf.lfFaceName, psub->to.name);
3910             plf = &lf;
3911         }
3912
3913         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3914             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3915             if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
3916                 LIST_FOR_EACH(face_elem_ptr, &family->faces) {
3917                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
3918                     GetEnumStructs(face, &elf, &ntm, &type);
3919                     for(i = 0; i < 32; i++) {
3920                         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
3921                             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
3922                             strcpyW(elf.elfScript, OEM_DOSW);
3923                             i = 32; /* break out of loop */
3924                         } else if(!(face->fs.fsCsb[0] & (1L << i)))
3925                             continue;
3926                         else {
3927                             fs.fsCsb[0] = 1L << i;
3928                             fs.fsCsb[1] = 0;
3929                             if(!TranslateCharsetInfo(fs.fsCsb, &csi,
3930                                                      TCI_SRCFONTSIG))
3931                                 csi.ciCharset = DEFAULT_CHARSET;
3932                             if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
3933                             if(csi.ciCharset != DEFAULT_CHARSET) {
3934                                 elf.elfLogFont.lfCharSet =
3935                                     ntm.ntmTm.tmCharSet = csi.ciCharset;
3936                                 if(ElfScriptsW[i])
3937                                     strcpyW(elf.elfScript, ElfScriptsW[i]);
3938                                 else
3939                                     FIXME("Unknown elfscript for bit %d\n", i);
3940                             }
3941                         }
3942                         TRACE("enuming face %s full %s style %s charset %d type %d script %s it %d weight %d ntmflags %08x\n",
3943                               debugstr_w(elf.elfLogFont.lfFaceName),
3944                               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
3945                               csi.ciCharset, type, debugstr_w(elf.elfScript),
3946                               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
3947                               ntm.ntmTm.ntmFlags);
3948                         /* release section before callback (FIXME) */
3949                         LeaveCriticalSection( &freetype_cs );
3950                         if (!proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam)) return 0;
3951                         EnterCriticalSection( &freetype_cs );
3952                     }
3953                 }
3954             }
3955         }
3956     } else {
3957         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3958             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3959             face_elem_ptr = list_head(&family->faces);
3960             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3961             GetEnumStructs(face, &elf, &ntm, &type);
3962             for(i = 0; i < 32; i++) {
3963                 if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
3964                     elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
3965                     strcpyW(elf.elfScript, OEM_DOSW);
3966                     i = 32; /* break out of loop */
3967                 } else if(!(face->fs.fsCsb[0] & (1L << i)))
3968                     continue;
3969                 else {
3970                     fs.fsCsb[0] = 1L << i;
3971                     fs.fsCsb[1] = 0;
3972                     if(!TranslateCharsetInfo(fs.fsCsb, &csi,
3973                                              TCI_SRCFONTSIG))
3974                         csi.ciCharset = DEFAULT_CHARSET;
3975                     if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
3976                     if(csi.ciCharset != DEFAULT_CHARSET) {
3977                         elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet =
3978                           csi.ciCharset;
3979                           if(ElfScriptsW[i])
3980                               strcpyW(elf.elfScript, ElfScriptsW[i]);
3981                           else
3982                               FIXME("Unknown elfscript for bit %d\n", i);
3983                     }
3984                 }
3985                 TRACE("enuming face %s full %s style %s charset = %d type %d script %s it %d weight %d ntmflags %08x\n",
3986                       debugstr_w(elf.elfLogFont.lfFaceName),
3987                       debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
3988                       csi.ciCharset, type, debugstr_w(elf.elfScript),
3989                       elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
3990                       ntm.ntmTm.ntmFlags);
3991                 /* release section before callback (FIXME) */
3992                 LeaveCriticalSection( &freetype_cs );
3993                 if (!proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam)) return 0;
3994                 EnterCriticalSection( &freetype_cs );
3995             }
3996         }
3997     }
3998     LeaveCriticalSection( &freetype_cs );
3999     return 1;
4000 }
4001
4002 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
4003 {
4004     pt->x.value = vec->x >> 6;
4005     pt->x.fract = (vec->x & 0x3f) << 10;
4006     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
4007     pt->y.value = vec->y >> 6;
4008     pt->y.fract = (vec->y & 0x3f) << 10;
4009     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
4010     return;
4011 }
4012
4013 /***************************************************
4014  * According to the MSDN documentation on WideCharToMultiByte,
4015  * certain codepages cannot set the default_used parameter.
4016  * This returns TRUE if the codepage can set that parameter, false else
4017  * so that calls to WideCharToMultiByte don't fail with ERROR_INVALID_PARAMETER
4018  */
4019 static BOOL codepage_sets_default_used(UINT codepage)
4020 {
4021    switch (codepage)
4022    {
4023        case CP_UTF7:
4024        case CP_UTF8:
4025        case CP_SYMBOL:
4026            return FALSE;
4027        default:
4028            return TRUE;
4029    }
4030 }
4031
4032 /*
4033  * GSUB Table handling functions
4034  */
4035
4036 static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph)
4037 {
4038     const GSUB_CoverageFormat1* cf1;
4039
4040     cf1 = (GSUB_CoverageFormat1*)table;
4041
4042     if (GET_BE_WORD(cf1->CoverageFormat) == 1)
4043     {
4044         int count = GET_BE_WORD(cf1->GlyphCount);
4045         int i;
4046         TRACE("Coverage Format 1, %i glyphs\n",count);
4047         for (i = 0; i < count; i++)
4048             if (glyph == GET_BE_WORD(cf1->GlyphArray[i]))
4049                 return i;
4050         return -1;
4051     }
4052     else if (GET_BE_WORD(cf1->CoverageFormat) == 2)
4053     {
4054         const GSUB_CoverageFormat2* cf2;
4055         int i;
4056         int count;
4057         cf2 = (GSUB_CoverageFormat2*)cf1;
4058
4059         count = GET_BE_WORD(cf2->RangeCount);
4060         TRACE("Coverage Format 2, %i ranges\n",count);
4061         for (i = 0; i < count; i++)
4062         {
4063             if (glyph < GET_BE_WORD(cf2->RangeRecord[i].Start))
4064                 return -1;
4065             if ((glyph >= GET_BE_WORD(cf2->RangeRecord[i].Start)) &&
4066                 (glyph <= GET_BE_WORD(cf2->RangeRecord[i].End)))
4067             {
4068                 return (GET_BE_WORD(cf2->RangeRecord[i].StartCoverageIndex) +
4069                     glyph - GET_BE_WORD(cf2->RangeRecord[i].Start));
4070             }
4071         }
4072         return -1;
4073     }
4074     else
4075         ERR("Unknown CoverageFormat %i\n",GET_BE_WORD(cf1->CoverageFormat));
4076
4077     return -1;
4078 }
4079
4080 static const GSUB_Script* GSUB_get_script_table( const GSUB_Header* header, const char* tag)
4081 {
4082     const GSUB_ScriptList *script;
4083     const GSUB_Script *deflt = NULL;
4084     int i;
4085     script = (GSUB_ScriptList*)((LPBYTE)header + GET_BE_WORD(header->ScriptList));
4086
4087     TRACE("%i scripts in this font\n",GET_BE_WORD(script->ScriptCount));
4088     for (i = 0; i < GET_BE_WORD(script->ScriptCount); i++)
4089     {
4090         const GSUB_Script *scr;
4091         int offset;
4092
4093         offset = GET_BE_WORD(script->ScriptRecord[i].Script);
4094         scr = (GSUB_Script*)((LPBYTE)script + offset);
4095
4096         if (strncmp(script->ScriptRecord[i].ScriptTag, tag,4)==0)
4097             return scr;
4098         if (strncmp(script->ScriptRecord[i].ScriptTag, "dflt",4)==0)
4099             deflt = scr;
4100     }
4101     return deflt;
4102 }
4103
4104 static const GSUB_LangSys* GSUB_get_lang_table( const GSUB_Script* script, const char* tag)
4105 {
4106     int i;
4107     int offset;
4108     const GSUB_LangSys *Lang;
4109
4110     TRACE("Deflang %x, LangCount %i\n",GET_BE_WORD(script->DefaultLangSys), GET_BE_WORD(script->LangSysCount));
4111
4112     for (i = 0; i < GET_BE_WORD(script->LangSysCount) ; i++)
4113     {
4114         offset = GET_BE_WORD(script->LangSysRecord[i].LangSys);
4115         Lang = (GSUB_LangSys*)((LPBYTE)script + offset);
4116
4117         if ( strncmp(script->LangSysRecord[i].LangSysTag,tag,4)==0)
4118             return Lang;
4119     }
4120     offset = GET_BE_WORD(script->DefaultLangSys);
4121     if (offset)
4122     {
4123         Lang = (GSUB_LangSys*)((LPBYTE)script + offset);
4124         return Lang;
4125     }
4126     return NULL;
4127 }
4128
4129 static const GSUB_Feature * GSUB_get_feature(const GSUB_Header *header, const GSUB_LangSys *lang, const char* tag)
4130 {
4131     int i;
4132     const GSUB_FeatureList *feature;
4133     feature = (GSUB_FeatureList*)((LPBYTE)header + GET_BE_WORD(header->FeatureList));
4134
4135     TRACE("%i features\n",GET_BE_WORD(lang->FeatureCount));
4136     for (i = 0; i < GET_BE_WORD(lang->FeatureCount); i++)
4137     {
4138         int index = GET_BE_WORD(lang->FeatureIndex[i]);
4139         if (strncmp(feature->FeatureRecord[index].FeatureTag,tag,4)==0)
4140         {
4141             const GSUB_Feature *feat;
4142             feat = (GSUB_Feature*)((LPBYTE)feature + GET_BE_WORD(feature->FeatureRecord[index].Feature));
4143             return feat;
4144         }
4145     }
4146     return NULL;
4147 }
4148
4149 static FT_UInt GSUB_apply_feature(const GSUB_Header * header, const GSUB_Feature* feature, UINT glyph)
4150 {
4151     int i;
4152     int offset;
4153     const GSUB_LookupList *lookup;
4154     lookup = (GSUB_LookupList*)((LPBYTE)header + GET_BE_WORD(header->LookupList));
4155
4156     TRACE("%i lookups\n", GET_BE_WORD(feature->LookupCount));
4157     for (i = 0; i < GET_BE_WORD(feature->LookupCount); i++)
4158     {
4159         const GSUB_LookupTable *look;
4160         offset = GET_BE_WORD(lookup->Lookup[GET_BE_WORD(feature->LookupListIndex[i])]);
4161         look = (GSUB_LookupTable*)((LPBYTE)lookup + offset);
4162         TRACE("type %i, flag %x, subtables %i\n",GET_BE_WORD(look->LookupType),GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount));
4163         if (GET_BE_WORD(look->LookupType) != 1)
4164             FIXME("We only handle SubType 1\n");
4165         else
4166         {
4167             int j;
4168
4169             for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
4170             {
4171                 const GSUB_SingleSubstFormat1 *ssf1;
4172                 offset = GET_BE_WORD(look->SubTable[j]);
4173                 ssf1 = (GSUB_SingleSubstFormat1*)((LPBYTE)look+offset);
4174                 if (GET_BE_WORD(ssf1->SubstFormat) == 1)
4175                 {
4176                     int offset = GET_BE_WORD(ssf1->Coverage);
4177                     TRACE("  subtype 1, delta %i\n", GET_BE_WORD(ssf1->DeltaGlyphID));
4178                     if (GSUB_is_glyph_covered((LPBYTE)ssf1+offset, glyph) != -1)
4179                     {
4180                         TRACE("  Glyph 0x%x ->",glyph);
4181                         glyph += GET_BE_WORD(ssf1->DeltaGlyphID);
4182                         TRACE(" 0x%x\n",glyph);
4183                     }
4184                 }
4185                 else
4186                 {
4187                     const GSUB_SingleSubstFormat2 *ssf2;
4188                     INT index;
4189                     INT offset;
4190
4191                     ssf2 = (GSUB_SingleSubstFormat2 *)ssf1;
4192                     offset = GET_BE_WORD(ssf1->Coverage);
4193                     TRACE("  subtype 2,  glyph count %i\n", GET_BE_WORD(ssf2->GlyphCount));
4194                     index = GSUB_is_glyph_covered((LPBYTE)ssf2+offset, glyph);
4195                     TRACE("  Coverage index %i\n",index);
4196                     if (index != -1)
4197                     {
4198                         TRACE("    Glyph is 0x%x ->",glyph);
4199                         glyph = GET_BE_WORD(ssf2->Substitute[index]);
4200                         TRACE("0x%x\n",glyph);
4201                     }
4202                 }
4203             }
4204         }
4205     }
4206     return glyph;
4207 }
4208
4209 static const char* get_opentype_script(const GdiFont *font)
4210 {
4211     /*
4212      * I am not sure if this is the correct way to generate our script tag
4213      */
4214
4215     switch (font->charset)
4216     {
4217         case ANSI_CHARSET: return "latn";
4218         case BALTIC_CHARSET: return "latn"; /* ?? */
4219         case CHINESEBIG5_CHARSET: return "hani";
4220         case EASTEUROPE_CHARSET: return "latn"; /* ?? */
4221         case GB2312_CHARSET: return "hani";
4222         case GREEK_CHARSET: return "grek";
4223         case HANGUL_CHARSET: return "hang";
4224         case RUSSIAN_CHARSET: return "cyrl";
4225         case SHIFTJIS_CHARSET: return "kana";
4226         case TURKISH_CHARSET: return "latn"; /* ?? */
4227         case VIETNAMESE_CHARSET: return "latn";
4228         case JOHAB_CHARSET: return "latn"; /* ?? */
4229         case ARABIC_CHARSET: return "arab";
4230         case HEBREW_CHARSET: return "hebr";
4231         case THAI_CHARSET: return "thai";
4232         default: return "latn";
4233     }
4234 }
4235
4236 static FT_UInt get_GSUB_vert_glyph(const GdiFont *font, UINT glyph)
4237 {
4238     const GSUB_Header *header;
4239     const GSUB_Script *script;
4240     const GSUB_LangSys *language;
4241     const GSUB_Feature *feature;
4242
4243     if (!font->GSUB_Table)
4244         return glyph;
4245
4246     header = font->GSUB_Table;
4247
4248     script = GSUB_get_script_table(header, get_opentype_script(font));
4249     if (!script)
4250     {
4251         TRACE("Script not found\n");
4252         return glyph;
4253     }
4254     language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
4255     if (!language)
4256     {
4257         TRACE("Language not found\n");
4258         return glyph;
4259     }
4260     feature  =  GSUB_get_feature(header, language, "vrt2");
4261     if (!feature)
4262         feature  =  GSUB_get_feature(header, language, "vert");
4263     if (!feature)
4264     {
4265         TRACE("vrt2/vert feature not found\n");
4266         return glyph;
4267     }
4268     return GSUB_apply_feature(header, feature, glyph);
4269 }
4270
4271 static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph)
4272 {
4273     FT_UInt glyphId;
4274
4275     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
4276         WCHAR wc = (WCHAR)glyph;
4277         BOOL default_used;
4278         BOOL *default_used_pointer;
4279         FT_UInt ret;
4280         char buf;
4281         default_used_pointer = NULL;
4282         default_used = FALSE;
4283         if (codepage_sets_default_used(font->codepage))
4284             default_used_pointer = &default_used;
4285         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
4286             ret = 0;
4287         else
4288             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
4289         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
4290         return get_GSUB_vert_glyph(font,ret);
4291     }
4292
4293     if(font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL && glyph < 0x100)
4294         glyph = glyph + 0xf000;
4295     glyphId = pFT_Get_Char_Index(font->ft_face, glyph);
4296     return get_GSUB_vert_glyph(font,glyphId);
4297 }
4298
4299 /*************************************************************
4300  * WineEngGetGlyphIndices
4301  *
4302  */
4303 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
4304                                 LPWORD pgi, DWORD flags)
4305 {
4306     int i;
4307     int default_char = -1;
4308
4309     if  (flags & GGI_MARK_NONEXISTING_GLYPHS) default_char = 0xffff;  /* XP would use 0x1f for bitmap fonts */
4310
4311     for(i = 0; i < count; i++)
4312     {
4313         pgi[i] = get_glyph_index(font, lpstr[i]);
4314         if  (pgi[i] == 0)
4315         {
4316             if (default_char == -1)
4317             {
4318                 if (FT_IS_SFNT(font->ft_face))
4319                 {
4320                     TT_OS2 *pOS2 = pFT_Get_Sfnt_Table(font->ft_face, ft_sfnt_os2);
4321                     default_char = (pOS2->usDefaultChar ? get_glyph_index(font, pOS2->usDefaultChar) : 0);
4322                 }
4323                 else
4324                 {
4325                     TEXTMETRICW textm;
4326                     WineEngGetTextMetrics(font, &textm);
4327                     default_char = textm.tmDefaultChar;
4328                 }
4329             }
4330             pgi[i] = default_char;
4331         }
4332     }
4333     return count;
4334 }
4335
4336 static inline BOOL is_identity_FMAT2(const FMAT2 *matrix)
4337 {
4338     static const FMAT2 identity = { 1.0, 0.0, 0.0, 1.0 };
4339     return !memcmp(matrix, &identity, sizeof(FMAT2));
4340 }
4341
4342 static inline BOOL is_identity_MAT2(const MAT2 *matrix)
4343 {
4344     static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
4345     return !memcmp(matrix, &identity, sizeof(MAT2));
4346 }
4347
4348 /*************************************************************
4349  * WineEngGetGlyphOutline
4350  *
4351  * Behaves in exactly the same way as the win32 api GetGlyphOutline
4352  * except that the first parameter is the HWINEENGFONT of the font in
4353  * question rather than an HDC.
4354  *
4355  */
4356 DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
4357                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
4358                              const MAT2* lpmat)
4359 {
4360     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
4361     FT_Face ft_face = incoming_font->ft_face;
4362     GdiFont *font = incoming_font;
4363     FT_UInt glyph_index;
4364     DWORD width, height, pitch, needed = 0;
4365     FT_Bitmap ft_bitmap;
4366     FT_Error err;
4367     INT left, right, top = 0, bottom = 0, adv, lsb, bbx;
4368     FT_Angle angle = 0;
4369     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
4370     double widthRatio = 1.0;
4371     FT_Matrix transMat = identityMat;
4372     FT_Matrix transMatUnrotated;
4373     BOOL needsTransform = FALSE;
4374     BOOL tategaki = (font->GSUB_Table != NULL);
4375     UINT original_index;
4376
4377     TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
4378           buflen, buf, lpmat);
4379
4380     TRACE("font transform %f %f %f %f\n",
4381           font->font_desc.matrix.eM11, font->font_desc.matrix.eM12,
4382           font->font_desc.matrix.eM21, font->font_desc.matrix.eM22);
4383
4384     EnterCriticalSection( &freetype_cs );
4385
4386     if(format & GGO_GLYPH_INDEX) {
4387         glyph_index = get_GSUB_vert_glyph(incoming_font,glyph);
4388         original_index = glyph;
4389         format &= ~GGO_GLYPH_INDEX;
4390     } else {
4391         get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index);
4392         ft_face = font->ft_face;
4393         original_index = glyph_index;
4394     }
4395
4396     if(format & GGO_UNHINTED) {
4397         load_flags |= FT_LOAD_NO_HINTING;
4398         format &= ~GGO_UNHINTED;
4399     }
4400
4401     /* tategaki never appears to happen to lower glyph index */
4402     if (glyph_index < TATEGAKI_LOWER_BOUND )
4403         tategaki = FALSE;
4404
4405     if(original_index >= font->gmsize * GM_BLOCK_SIZE) {
4406         font->gmsize = (original_index / GM_BLOCK_SIZE + 1);
4407         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
4408                                font->gmsize * sizeof(GM*));
4409     } else {
4410         if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL &&
4411             FONT_GM(font,original_index)->init && (!lpmat || is_identity_MAT2(lpmat)))
4412         {
4413             *lpgm = FONT_GM(font,original_index)->gm;
4414             TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
4415                   wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
4416                   lpgm->gmCellIncX, lpgm->gmCellIncY);
4417             LeaveCriticalSection( &freetype_cs );
4418             return 1; /* FIXME */
4419         }
4420     }
4421
4422     if (!font->gm[original_index / GM_BLOCK_SIZE])
4423         font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
4424
4425     /* Scaling factor */
4426     if (font->aveWidth)
4427     {
4428         TEXTMETRICW tm;
4429
4430         WineEngGetTextMetrics(font, &tm);
4431
4432         widthRatio = (double)font->aveWidth;
4433         widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
4434     }
4435     else
4436         widthRatio = font->scale_y;
4437
4438     /* Scaling transform */
4439     if (widthRatio != 1.0 || font->scale_y != 1.0)
4440     {
4441         FT_Matrix scaleMat;
4442         scaleMat.xx = FT_FixedFromFloat(widthRatio);
4443         scaleMat.xy = 0;
4444         scaleMat.yx = 0;
4445         scaleMat.yy = FT_FixedFromFloat(font->scale_y);
4446
4447         pFT_Matrix_Multiply(&scaleMat, &transMat);
4448         needsTransform = TRUE;
4449     }
4450
4451     /* Slant transform */
4452     if (font->fake_italic) {
4453         FT_Matrix slantMat;
4454         
4455         slantMat.xx = (1 << 16);
4456         slantMat.xy = ((1 << 16) >> 2);
4457         slantMat.yx = 0;
4458         slantMat.yy = (1 << 16);
4459         pFT_Matrix_Multiply(&slantMat, &transMat);
4460         needsTransform = TRUE;
4461     }
4462
4463     /* Rotation transform */
4464     transMatUnrotated = transMat;
4465     if(font->orientation && !tategaki) {
4466         FT_Matrix rotationMat;
4467         FT_Vector vecAngle;
4468         angle = FT_FixedFromFloat((double)font->orientation / 10.0);
4469         pFT_Vector_Unit(&vecAngle, angle);
4470         rotationMat.xx = vecAngle.x;
4471         rotationMat.xy = -vecAngle.y;
4472         rotationMat.yx = -rotationMat.xy;
4473         rotationMat.yy = rotationMat.xx;
4474         
4475         pFT_Matrix_Multiply(&rotationMat, &transMat);
4476         needsTransform = TRUE;
4477     }
4478
4479     /* World transform */
4480     if (!is_identity_FMAT2(&font->font_desc.matrix))
4481     {
4482         FT_Matrix worldMat;
4483         worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11);
4484         worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM21);
4485         worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM12);
4486         worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22);
4487         pFT_Matrix_Multiply(&worldMat, &transMat);
4488         pFT_Matrix_Multiply(&worldMat, &transMatUnrotated);
4489         needsTransform = TRUE;
4490     }
4491
4492     /* Extra transformation specified by caller */
4493     if (lpmat && !is_identity_MAT2(lpmat))
4494     {
4495         FT_Matrix extraMat;
4496         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
4497         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
4498         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
4499         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
4500         pFT_Matrix_Multiply(&extraMat, &transMat);
4501         pFT_Matrix_Multiply(&extraMat, &transMatUnrotated);
4502         needsTransform = TRUE;
4503     }
4504
4505     if (needsTransform || (format == GGO_NATIVE || format == GGO_BEZIER ||
4506                            format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
4507                            format == GGO_GRAY8_BITMAP))
4508     {
4509         load_flags |= FT_LOAD_NO_BITMAP;
4510     }
4511
4512     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
4513
4514     if(err) {
4515         WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
4516         LeaveCriticalSection( &freetype_cs );
4517         return GDI_ERROR;
4518     }
4519
4520     left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64;
4521     right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64;
4522
4523     adv = (INT)((ft_face->glyph->metrics.horiAdvance) + 63) >> 6;
4524     lsb = left >> 6;
4525     bbx = (right - left) >> 6;
4526
4527     if(!needsTransform) {
4528         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
4529         bottom = (ft_face->glyph->metrics.horiBearingY -
4530                   ft_face->glyph->metrics.height) & -64;
4531         lpgm->gmCellIncX = adv;
4532         lpgm->gmCellIncY = 0;
4533     } else {
4534         INT xc, yc;
4535         FT_Vector vec;
4536         for(xc = 0; xc < 2; xc++) {
4537             for(yc = 0; yc < 2; yc++) {
4538                 vec.x = (ft_face->glyph->metrics.horiBearingX +
4539                   xc * ft_face->glyph->metrics.width);
4540                 vec.y = ft_face->glyph->metrics.horiBearingY -
4541                   yc * ft_face->glyph->metrics.height;
4542                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
4543                 pFT_Vector_Transform(&vec, &transMat);
4544                 if(xc == 0 && yc == 0) {
4545                     left = right = vec.x;
4546                     top = bottom = vec.y;
4547                 } else {
4548                     if(vec.x < left) left = vec.x;
4549                     else if(vec.x > right) right = vec.x;
4550                     if(vec.y < bottom) bottom = vec.y;
4551                     else if(vec.y > top) top = vec.y;
4552                 }
4553             }
4554         }
4555         left = left & -64;
4556         right = (right + 63) & -64;
4557         bottom = bottom & -64;
4558         top = (top + 63) & -64;
4559
4560         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
4561         vec.x = ft_face->glyph->metrics.horiAdvance;
4562         vec.y = 0;
4563         pFT_Vector_Transform(&vec, &transMat);
4564         lpgm->gmCellIncX = (vec.x+63) >> 6;
4565         lpgm->gmCellIncY = -((vec.y+63) >> 6);
4566
4567         vec.x = ft_face->glyph->metrics.horiAdvance;
4568         vec.y = 0;
4569         pFT_Vector_Transform(&vec, &transMatUnrotated);
4570         adv = (vec.x+63) >> 6;
4571     }
4572     lpgm->gmBlackBoxX = (right - left) >> 6;
4573     lpgm->gmBlackBoxY = (top - bottom) >> 6;
4574     lpgm->gmptGlyphOrigin.x = left >> 6;
4575     lpgm->gmptGlyphOrigin.y = top >> 6;
4576
4577     TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
4578           wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
4579           lpgm->gmCellIncX, lpgm->gmCellIncY);
4580
4581     if ((format == GGO_METRICS || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
4582         (!lpmat || is_identity_MAT2(lpmat))) /* don't cache custom transforms */
4583     {
4584         FONT_GM(font,original_index)->gm = *lpgm;
4585         FONT_GM(font,original_index)->adv = adv;
4586         FONT_GM(font,original_index)->lsb = lsb;
4587         FONT_GM(font,original_index)->bbx = bbx;
4588         FONT_GM(font,original_index)->init = TRUE;
4589     }
4590
4591     if(format == GGO_METRICS)
4592     {
4593         LeaveCriticalSection( &freetype_cs );
4594         return 1; /* FIXME */
4595     }
4596
4597     if(ft_face->glyph->format != ft_glyph_format_outline &&
4598        (needsTransform || format == GGO_NATIVE || format == GGO_BEZIER ||
4599                           format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
4600                           format == GGO_GRAY8_BITMAP))
4601     {
4602         TRACE("loaded a bitmap\n");
4603         LeaveCriticalSection( &freetype_cs );
4604         return GDI_ERROR;
4605     }
4606
4607     switch(format) {
4608     case GGO_BITMAP:
4609         width = lpgm->gmBlackBoxX;
4610         height = lpgm->gmBlackBoxY;
4611         pitch = ((width + 31) >> 5) << 2;
4612         needed = pitch * height;
4613
4614         if(!buf || !buflen) break;
4615
4616         switch(ft_face->glyph->format) {
4617         case ft_glyph_format_bitmap:
4618           {
4619             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
4620             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
4621             INT h = ft_face->glyph->bitmap.rows;
4622             while(h--) {
4623                 memcpy(dst, src, w);
4624                 src += ft_face->glyph->bitmap.pitch;
4625                 dst += pitch;
4626             }
4627             break;
4628           }
4629
4630         case ft_glyph_format_outline:
4631             ft_bitmap.width = width;
4632             ft_bitmap.rows = height;
4633             ft_bitmap.pitch = pitch;
4634             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
4635             ft_bitmap.buffer = buf;
4636
4637             if(needsTransform)
4638                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4639
4640             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4641
4642             /* Note: FreeType will only set 'black' bits for us. */
4643             memset(buf, 0, needed);
4644             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
4645             break;
4646
4647         default:
4648             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
4649             LeaveCriticalSection( &freetype_cs );
4650             return GDI_ERROR;
4651         }
4652         break;
4653
4654     case GGO_GRAY2_BITMAP:
4655     case GGO_GRAY4_BITMAP:
4656     case GGO_GRAY8_BITMAP:
4657     case WINE_GGO_GRAY16_BITMAP:
4658       {
4659         unsigned int mult, row, col;
4660         BYTE *start, *ptr;
4661
4662         width = lpgm->gmBlackBoxX;
4663         height = lpgm->gmBlackBoxY;
4664         pitch = (width + 3) / 4 * 4;
4665         needed = pitch * height;
4666
4667         if(!buf || !buflen) break;
4668
4669         switch(ft_face->glyph->format) {
4670         case ft_glyph_format_bitmap:
4671           {
4672             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
4673             INT h = ft_face->glyph->bitmap.rows;
4674             INT x;
4675             while(h--) {
4676                 for(x = 0; x < pitch; x++)
4677                 {
4678                     if(x < ft_face->glyph->bitmap.width)
4679                         dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0;
4680                     else
4681                         dst[x] = 0;
4682                 }
4683                 src += ft_face->glyph->bitmap.pitch;
4684                 dst += pitch;
4685             }
4686             LeaveCriticalSection( &freetype_cs );
4687             return needed;
4688           }
4689         case ft_glyph_format_outline:
4690           {
4691             ft_bitmap.width = width;
4692             ft_bitmap.rows = height;
4693             ft_bitmap.pitch = pitch;
4694             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
4695             ft_bitmap.buffer = buf;
4696
4697             if(needsTransform)
4698                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4699
4700             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4701
4702             memset(ft_bitmap.buffer, 0, buflen);
4703
4704             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
4705
4706             if(format == GGO_GRAY2_BITMAP)
4707                 mult = 4;
4708             else if(format == GGO_GRAY4_BITMAP)
4709                 mult = 16;
4710             else if(format == GGO_GRAY8_BITMAP)
4711                 mult = 64;
4712             else /* format == WINE_GGO_GRAY16_BITMAP */
4713             {
4714                 LeaveCriticalSection( &freetype_cs );
4715                 return needed;
4716             }
4717             break;
4718           }
4719         default:
4720             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
4721             LeaveCriticalSection( &freetype_cs );
4722             return GDI_ERROR;
4723         }
4724
4725         start = buf;
4726         for(row = 0; row < height; row++) {
4727             ptr = start;
4728             for(col = 0; col < width; col++, ptr++) {
4729                 *ptr = (((int)*ptr) * mult + 128) / 256;
4730             }
4731             start += pitch;
4732         }
4733         break;
4734       }
4735
4736     case WINE_GGO_HRGB_BITMAP:
4737     case WINE_GGO_HBGR_BITMAP:
4738     case WINE_GGO_VRGB_BITMAP:
4739     case WINE_GGO_VBGR_BITMAP:
4740 #ifdef HAVE_FREETYPE_FTLCDFIL_H
4741       {
4742         switch (ft_face->glyph->format)
4743         {
4744         case FT_GLYPH_FORMAT_BITMAP:
4745           {
4746             BYTE *src, *dst;
4747             INT src_pitch, x;
4748
4749             width  = lpgm->gmBlackBoxX;
4750             height = lpgm->gmBlackBoxY;
4751             pitch  = width * 4;
4752             needed = pitch * height;
4753
4754             if (!buf || !buflen) break;
4755
4756             memset(buf, 0, buflen);
4757             dst = buf;
4758             src = ft_face->glyph->bitmap.buffer;
4759             src_pitch = ft_face->glyph->bitmap.pitch;
4760
4761             while ( height-- )
4762             {
4763                 for (x = 0; x < width; x++)
4764                 {
4765                     if ( src[x / 8] & (1 << ( (7 - (x % 8)))) )
4766                         ((unsigned int *)dst)[x] = ~0u;
4767                 }
4768                 src += src_pitch;
4769                 dst += pitch;
4770             }
4771
4772             break;
4773           }
4774
4775         case FT_GLYPH_FORMAT_OUTLINE:
4776           {
4777             unsigned int *dst;
4778             BYTE *src;
4779             INT x, src_pitch, src_width, src_height, rgb_interval, hmul, vmul;
4780             INT x_shift, y_shift;
4781             BOOL rgb;
4782             FT_LcdFilter lcdfilter = FT_LCD_FILTER_DEFAULT;
4783             FT_Render_Mode render_mode =
4784                 (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_HBGR_BITMAP)?
4785                     FT_RENDER_MODE_LCD: FT_RENDER_MODE_LCD_V;
4786
4787             if ( lcdfilter == FT_LCD_FILTER_DEFAULT || lcdfilter == FT_LCD_FILTER_LIGHT )
4788             {
4789                 if ( render_mode == FT_RENDER_MODE_LCD)
4790                 {
4791                     lpgm->gmBlackBoxX += 2;
4792                     lpgm->gmptGlyphOrigin.x -= 1;
4793                 }
4794                 else
4795                 {
4796                     lpgm->gmBlackBoxY += 2;
4797                     lpgm->gmptGlyphOrigin.y += 1;
4798                 }
4799             }
4800
4801             width  = lpgm->gmBlackBoxX;
4802             height = lpgm->gmBlackBoxY;
4803             pitch  = width * 4;
4804             needed = pitch * height;
4805
4806             if (!buf || !buflen) break;
4807
4808             memset(buf, 0, buflen);
4809             dst = (unsigned int *)buf;
4810             rgb = (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_VRGB_BITMAP);
4811
4812             if ( needsTransform )
4813                 pFT_Outline_Transform (&ft_face->glyph->outline, &transMat);
4814
4815             if ( pFT_Library_SetLcdFilter )
4816                 pFT_Library_SetLcdFilter( library, lcdfilter );
4817             pFT_Render_Glyph (ft_face->glyph, render_mode);
4818
4819             src = ft_face->glyph->bitmap.buffer;
4820             src_pitch = ft_face->glyph->bitmap.pitch;
4821             src_width = ft_face->glyph->bitmap.width;
4822             src_height = ft_face->glyph->bitmap.rows;
4823
4824             if ( render_mode == FT_RENDER_MODE_LCD)
4825             {
4826                 rgb_interval = 1;
4827                 hmul = 3;
4828                 vmul = 1;
4829             }
4830             else
4831             {
4832                 rgb_interval = src_pitch;
4833                 hmul = 1;
4834                 vmul = 3;
4835             }
4836
4837             x_shift = ft_face->glyph->bitmap_left - lpgm->gmptGlyphOrigin.x;
4838             if ( x_shift < 0 ) x_shift = 0;
4839             if ( x_shift + (src_width / hmul) > width )
4840                 x_shift = width - (src_width / hmul);
4841
4842             y_shift = lpgm->gmptGlyphOrigin.y - ft_face->glyph->bitmap_top;
4843             if ( y_shift < 0 ) y_shift = 0;
4844             if ( y_shift + (src_height / vmul) > height )
4845                 y_shift = height - (src_height / vmul);
4846
4847             dst += x_shift + y_shift * ( pitch / 4 );
4848             while ( src_height )
4849             {
4850                 for ( x = 0; x < src_width / hmul; x++ )
4851                 {
4852                     if ( rgb )
4853                     {
4854                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 0] << 16) |
4855                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
4856                                  ((unsigned int)src[hmul * x + rgb_interval * 2] <<  0) |
4857                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
4858                     }
4859                     else
4860                     {
4861                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 2] << 16) |
4862                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
4863                                  ((unsigned int)src[hmul * x + rgb_interval * 0] <<  0) |
4864                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
4865                     }
4866                 }
4867                 src += src_pitch * vmul;
4868                 dst += pitch / 4;
4869                 src_height -= vmul;
4870             }
4871
4872             break;
4873           }
4874
4875         default:
4876             FIXME ("loaded glyph format %x\n", ft_face->glyph->format);
4877             LeaveCriticalSection ( &freetype_cs );
4878             return GDI_ERROR;
4879         }
4880
4881         break;
4882       }
4883 #else
4884       LeaveCriticalSection( &freetype_cs );
4885       return GDI_ERROR;
4886 #endif
4887
4888     case GGO_NATIVE:
4889       {
4890         int contour, point = 0, first_pt;
4891         FT_Outline *outline = &ft_face->glyph->outline;
4892         TTPOLYGONHEADER *pph;
4893         TTPOLYCURVE *ppc;
4894         DWORD pph_start, cpfx, type;
4895
4896         if(buflen == 0) buf = NULL;
4897
4898         if (needsTransform && buf) {
4899                 pFT_Outline_Transform(outline, &transMat);
4900         }
4901
4902         for(contour = 0; contour < outline->n_contours; contour++) {
4903             pph_start = needed;
4904             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
4905             first_pt = point;
4906             if(buf) {
4907                 pph->dwType = TT_POLYGON_TYPE;
4908                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
4909             }
4910             needed += sizeof(*pph);
4911             point++;
4912             while(point <= outline->contours[contour]) {
4913                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
4914                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
4915                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
4916                 cpfx = 0;
4917                 do {
4918                     if(buf)
4919                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4920                     cpfx++;
4921                     point++;
4922                 } while(point <= outline->contours[contour] &&
4923                         (outline->tags[point] & FT_Curve_Tag_On) ==
4924                         (outline->tags[point-1] & FT_Curve_Tag_On));
4925                 /* At the end of a contour Windows adds the start point, but
4926                    only for Beziers */
4927                 if(point > outline->contours[contour] &&
4928                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
4929                     if(buf)
4930                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
4931                     cpfx++;
4932                 } else if(point <= outline->contours[contour] &&
4933                           outline->tags[point] & FT_Curve_Tag_On) {
4934                   /* add closing pt for bezier */
4935                     if(buf)
4936                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4937                     cpfx++;
4938                     point++;
4939                 }
4940                 if(buf) {
4941                     ppc->wType = type;
4942                     ppc->cpfx = cpfx;
4943                 }
4944                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
4945             }
4946             if(buf)
4947                 pph->cb = needed - pph_start;
4948         }
4949         break;
4950       }
4951     case GGO_BEZIER:
4952       {
4953         /* Convert the quadratic Beziers to cubic Beziers.
4954            The parametric eqn for a cubic Bezier is, from PLRM:
4955            r(t) = at^3 + bt^2 + ct + r0
4956            with the control points:
4957            r1 = r0 + c/3
4958            r2 = r1 + (c + b)/3
4959            r3 = r0 + c + b + a
4960
4961            A quadratic Beizer has the form:
4962            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
4963
4964            So equating powers of t leads to:
4965            r1 = 2/3 p1 + 1/3 p0
4966            r2 = 2/3 p1 + 1/3 p2
4967            and of course r0 = p0, r3 = p2
4968         */
4969
4970         int contour, point = 0, first_pt;
4971         FT_Outline *outline = &ft_face->glyph->outline;
4972         TTPOLYGONHEADER *pph;
4973         TTPOLYCURVE *ppc;
4974         DWORD pph_start, cpfx, type;
4975         FT_Vector cubic_control[4];
4976         if(buflen == 0) buf = NULL;
4977
4978         if (needsTransform && buf) {
4979                 pFT_Outline_Transform(outline, &transMat);
4980         }
4981
4982         for(contour = 0; contour < outline->n_contours; contour++) {
4983             pph_start = needed;
4984             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
4985             first_pt = point;
4986             if(buf) {
4987                 pph->dwType = TT_POLYGON_TYPE;
4988                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
4989             }
4990             needed += sizeof(*pph);
4991             point++;
4992             while(point <= outline->contours[contour]) {
4993                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
4994                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
4995                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
4996                 cpfx = 0;
4997                 do {
4998                     if(type == TT_PRIM_LINE) {
4999                         if(buf)
5000                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
5001                         cpfx++;
5002                         point++;
5003                     } else {
5004                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
5005                          so cpfx = 3n */
5006
5007                       /* FIXME: Possible optimization in endpoint calculation
5008                          if there are two consecutive curves */
5009                         cubic_control[0] = outline->points[point-1];
5010                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
5011                             cubic_control[0].x += outline->points[point].x + 1;
5012                             cubic_control[0].y += outline->points[point].y + 1;
5013                             cubic_control[0].x >>= 1;
5014                             cubic_control[0].y >>= 1;
5015                         }
5016                         if(point+1 > outline->contours[contour])
5017                             cubic_control[3] = outline->points[first_pt];
5018                         else {
5019                             cubic_control[3] = outline->points[point+1];
5020                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
5021                                 cubic_control[3].x += outline->points[point].x + 1;
5022                                 cubic_control[3].y += outline->points[point].y + 1;
5023                                 cubic_control[3].x >>= 1;
5024                                 cubic_control[3].y >>= 1;
5025                             }
5026                         }
5027                         /* r1 = 1/3 p0 + 2/3 p1
5028                            r2 = 1/3 p2 + 2/3 p1 */
5029                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
5030                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
5031                         cubic_control[2] = cubic_control[1];
5032                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
5033                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
5034                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
5035                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
5036                         if(buf) {
5037                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
5038                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
5039                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
5040                         }
5041                         cpfx += 3;
5042                         point++;
5043                     }
5044                 } while(point <= outline->contours[contour] &&
5045                         (outline->tags[point] & FT_Curve_Tag_On) ==
5046                         (outline->tags[point-1] & FT_Curve_Tag_On));
5047                 /* At the end of a contour Windows adds the start point,
5048                    but only for Beziers and we've already done that.
5049                 */
5050                 if(point <= outline->contours[contour] &&
5051                    outline->tags[point] & FT_Curve_Tag_On) {
5052                   /* This is the closing pt of a bezier, but we've already
5053                      added it, so just inc point and carry on */
5054                     point++;
5055                 }
5056                 if(buf) {
5057                     ppc->wType = type;
5058                     ppc->cpfx = cpfx;
5059                 }
5060                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
5061             }
5062             if(buf)
5063                 pph->cb = needed - pph_start;
5064         }
5065         break;
5066       }
5067
5068     default:
5069         FIXME("Unsupported format %d\n", format);
5070         LeaveCriticalSection( &freetype_cs );
5071         return GDI_ERROR;
5072     }
5073     LeaveCriticalSection( &freetype_cs );
5074     return needed;
5075 }
5076
5077 static BOOL get_bitmap_text_metrics(GdiFont *font)
5078 {
5079     FT_Face ft_face = font->ft_face;
5080 #ifdef HAVE_FREETYPE_FTWINFNT_H
5081     FT_WinFNT_HeaderRec winfnt_header;
5082 #endif
5083     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
5084     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
5085     font->potm->otmSize = size;
5086
5087 #define TM font->potm->otmTextMetrics
5088 #ifdef HAVE_FREETYPE_FTWINFNT_H
5089     if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
5090     {
5091         TM.tmHeight = winfnt_header.pixel_height;
5092         TM.tmAscent = winfnt_header.ascent;
5093         TM.tmDescent = TM.tmHeight - TM.tmAscent;
5094         TM.tmInternalLeading = winfnt_header.internal_leading;
5095         TM.tmExternalLeading = winfnt_header.external_leading;
5096         TM.tmAveCharWidth = winfnt_header.avg_width;
5097         TM.tmMaxCharWidth = winfnt_header.max_width;
5098         TM.tmWeight = winfnt_header.weight;
5099         TM.tmOverhang = 0;
5100         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
5101         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
5102         TM.tmFirstChar = winfnt_header.first_char;
5103         TM.tmLastChar = winfnt_header.last_char;
5104         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
5105         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
5106         TM.tmItalic = winfnt_header.italic;
5107         TM.tmUnderlined = font->underline;
5108         TM.tmStruckOut = font->strikeout;
5109         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
5110         TM.tmCharSet = winfnt_header.charset;
5111     }
5112     else
5113 #endif
5114     {
5115         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
5116         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
5117         TM.tmHeight = TM.tmAscent + TM.tmDescent;
5118         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
5119         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
5120         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
5121         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
5122         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
5123         TM.tmOverhang = 0;
5124         TM.tmDigitizedAspectX = 96; /* FIXME */
5125         TM.tmDigitizedAspectY = 96; /* FIXME */
5126         TM.tmFirstChar = 1;
5127         TM.tmLastChar = 255;
5128         TM.tmDefaultChar = 32;
5129         TM.tmBreakChar = 32;
5130         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
5131         TM.tmUnderlined = font->underline;
5132         TM.tmStruckOut = font->strikeout;
5133         /* NB inverted meaning of TMPF_FIXED_PITCH */
5134         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
5135         TM.tmCharSet = font->charset;
5136     }
5137 #undef TM
5138
5139     return TRUE;
5140 }
5141
5142
5143 static void scale_font_metrics(const GdiFont *font, LPTEXTMETRICW ptm)
5144 {
5145     double scale_x, scale_y;
5146
5147     if (font->aveWidth)
5148     {
5149         scale_x = (double)font->aveWidth;
5150         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5151     }
5152     else
5153         scale_x = font->scale_y;
5154
5155     scale_x *= fabs(font->font_desc.matrix.eM11);
5156     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
5157
5158 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
5159 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
5160
5161     SCALE_Y(ptm->tmHeight);
5162     SCALE_Y(ptm->tmAscent);
5163     SCALE_Y(ptm->tmDescent);
5164     SCALE_Y(ptm->tmInternalLeading);
5165     SCALE_Y(ptm->tmExternalLeading);
5166     SCALE_Y(ptm->tmOverhang);
5167
5168     SCALE_X(ptm->tmAveCharWidth);
5169     SCALE_X(ptm->tmMaxCharWidth);
5170
5171 #undef SCALE_X
5172 #undef SCALE_Y
5173 }
5174
5175 static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *potm)
5176 {
5177     double scale_x, scale_y;
5178
5179     if (font->aveWidth)
5180     {
5181         scale_x = (double)font->aveWidth;
5182         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5183     }
5184     else
5185         scale_x = font->scale_y;
5186
5187     scale_x *= fabs(font->font_desc.matrix.eM11);
5188     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
5189
5190     scale_font_metrics(font, &potm->otmTextMetrics);
5191
5192 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
5193 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
5194
5195     SCALE_Y(potm->otmAscent);
5196     SCALE_Y(potm->otmDescent);
5197     SCALE_Y(potm->otmLineGap);
5198     SCALE_Y(potm->otmsCapEmHeight);
5199     SCALE_Y(potm->otmsXHeight);
5200     SCALE_Y(potm->otmrcFontBox.top);
5201     SCALE_Y(potm->otmrcFontBox.bottom);
5202     SCALE_X(potm->otmrcFontBox.left);
5203     SCALE_X(potm->otmrcFontBox.right);
5204     SCALE_Y(potm->otmMacAscent);
5205     SCALE_Y(potm->otmMacDescent);
5206     SCALE_Y(potm->otmMacLineGap);
5207     SCALE_X(potm->otmptSubscriptSize.x);
5208     SCALE_Y(potm->otmptSubscriptSize.y);
5209     SCALE_X(potm->otmptSubscriptOffset.x);
5210     SCALE_Y(potm->otmptSubscriptOffset.y);
5211     SCALE_X(potm->otmptSuperscriptSize.x);
5212     SCALE_Y(potm->otmptSuperscriptSize.y);
5213     SCALE_X(potm->otmptSuperscriptOffset.x);
5214     SCALE_Y(potm->otmptSuperscriptOffset.y);
5215     SCALE_Y(potm->otmsStrikeoutSize);
5216     SCALE_Y(potm->otmsStrikeoutPosition);
5217     SCALE_Y(potm->otmsUnderscoreSize);
5218     SCALE_Y(potm->otmsUnderscorePosition);
5219
5220 #undef SCALE_X
5221 #undef SCALE_Y
5222 }
5223
5224 /*************************************************************
5225  * WineEngGetTextMetrics
5226  *
5227  */
5228 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
5229 {
5230     EnterCriticalSection( &freetype_cs );
5231     if(!font->potm) {
5232         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
5233             if(!get_bitmap_text_metrics(font))
5234             {
5235                 LeaveCriticalSection( &freetype_cs );
5236                 return FALSE;
5237             }
5238     }
5239     if(!font->potm)
5240     {
5241         LeaveCriticalSection( &freetype_cs );
5242         return FALSE;
5243     }
5244     *ptm = font->potm->otmTextMetrics;
5245     scale_font_metrics(font, ptm);
5246     LeaveCriticalSection( &freetype_cs );
5247     return TRUE;
5248 }
5249
5250
5251 /*************************************************************
5252  * WineEngGetOutlineTextMetrics
5253  *
5254  */
5255 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
5256                                   OUTLINETEXTMETRICW *potm)
5257 {
5258     FT_Face ft_face = font->ft_face;
5259     UINT needed, lenfam, lensty, ret;
5260     TT_OS2 *pOS2;
5261     TT_HoriHeader *pHori;
5262     TT_Postscript *pPost;
5263     FT_Fixed x_scale, y_scale;
5264     WCHAR *family_nameW, *style_nameW;
5265     static const WCHAR spaceW[] = {' ', '\0'};
5266     char *cp;
5267     INT ascent, descent;
5268
5269     TRACE("font=%p\n", font);
5270
5271     if(!FT_IS_SCALABLE(ft_face))
5272         return 0;
5273
5274     EnterCriticalSection( &freetype_cs );
5275
5276     if(font->potm) {
5277         if(cbSize >= font->potm->otmSize)
5278         {
5279             memcpy(potm, font->potm, font->potm->otmSize);
5280             scale_outline_font_metrics(font, potm);
5281         }
5282         LeaveCriticalSection( &freetype_cs );
5283         return font->potm->otmSize;
5284     }
5285
5286
5287     needed = sizeof(*potm);
5288
5289     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
5290     family_nameW = strdupW(font->name);
5291
5292     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
5293       * sizeof(WCHAR);
5294     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
5295     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
5296                         style_nameW, lensty/sizeof(WCHAR));
5297
5298     /* These names should be read from the TT name table */
5299
5300     /* length of otmpFamilyName */
5301     needed += lenfam;
5302
5303     /* length of otmpFaceName */
5304     if ((ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) == 0) {
5305       needed += lenfam; /* just the family name */
5306     } else {
5307       needed += lenfam + lensty; /* family + " " + style */
5308     }
5309
5310     /* length of otmpStyleName */
5311     needed += lensty;
5312
5313     /* length of otmpFullName */
5314     needed += lenfam + lensty;
5315
5316
5317     x_scale = ft_face->size->metrics.x_scale;
5318     y_scale = ft_face->size->metrics.y_scale;
5319
5320     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
5321     if(!pOS2) {
5322         FIXME("Can't find OS/2 table - not TT font?\n");
5323         ret = 0;
5324         goto end;
5325     }
5326
5327     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
5328     if(!pHori) {
5329         FIXME("Can't find HHEA table - not TT font?\n");
5330         ret = 0;
5331         goto end;
5332     }
5333
5334     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
5335
5336     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",
5337           pOS2->usWinAscent, pOS2->usWinDescent,
5338           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
5339           ft_face->ascender, ft_face->descender, ft_face->height,
5340           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
5341           ft_face->bbox.yMax, ft_face->bbox.yMin);
5342
5343     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
5344     font->potm->otmSize = needed;
5345
5346 #define TM font->potm->otmTextMetrics
5347
5348     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
5349         ascent = pHori->Ascender;
5350         descent = -pHori->Descender;
5351     } else {
5352         ascent = pOS2->usWinAscent;
5353         descent = pOS2->usWinDescent;
5354     }
5355
5356     if(font->yMax) {
5357         TM.tmAscent = font->yMax;
5358         TM.tmDescent = -font->yMin;
5359         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
5360     } else {
5361         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
5362         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
5363         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
5364                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
5365     }
5366
5367     TM.tmHeight = TM.tmAscent + TM.tmDescent;
5368
5369     /* MSDN says:
5370      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
5371     */
5372     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
5373                  ((ascent + descent) -
5374                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
5375
5376     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
5377     if (TM.tmAveCharWidth == 0) {
5378         TM.tmAveCharWidth = 1; 
5379     }
5380     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
5381     TM.tmWeight = (font->fake_bold || (ft_face->style_flags & FT_STYLE_FLAG_BOLD)) ? FW_BOLD : FW_REGULAR;
5382     TM.tmOverhang = 0;
5383     TM.tmDigitizedAspectX = 300;
5384     TM.tmDigitizedAspectY = 300;
5385     /* It appears that for fonts with SYMBOL_CHARSET Windows always sets
5386      * symbol range to 0 - f0ff
5387      */
5388     if (font->charset == SYMBOL_CHARSET)
5389     {
5390         TM.tmFirstChar = 0;
5391         TM.tmDefaultChar = pOS2->usDefaultChar ? pOS2->usDefaultChar : 0x1f;
5392     }
5393     else
5394     {
5395         TM.tmFirstChar = pOS2->usFirstCharIndex;
5396         TM.tmDefaultChar = pOS2->usDefaultChar ? pOS2->usDefaultChar : 0xffff;
5397     }
5398     TM.tmLastChar = pOS2->usLastCharIndex;
5399     TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
5400     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
5401     TM.tmUnderlined = font->underline;
5402     TM.tmStruckOut = font->strikeout;
5403
5404     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
5405     if(!FT_IS_FIXED_WIDTH(ft_face) &&
5406        (pOS2->version == 0xFFFFU || 
5407         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
5408         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
5409     else
5410         TM.tmPitchAndFamily = 0;
5411
5412     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
5413     case PAN_FAMILY_SCRIPT:
5414         TM.tmPitchAndFamily |= FF_SCRIPT;
5415         break;
5416     case PAN_FAMILY_DECORATIVE:
5417     case PAN_FAMILY_PICTORIAL:
5418         TM.tmPitchAndFamily |= FF_DECORATIVE;
5419         break;
5420     case PAN_FAMILY_TEXT_DISPLAY:
5421         if(TM.tmPitchAndFamily == 0) /* fixed */
5422             TM.tmPitchAndFamily = FF_MODERN;
5423         else {
5424             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
5425             case PAN_SERIF_NORMAL_SANS:
5426             case PAN_SERIF_OBTUSE_SANS:
5427             case PAN_SERIF_PERP_SANS:
5428                 TM.tmPitchAndFamily |= FF_SWISS;
5429                 break;
5430             default:
5431                 TM.tmPitchAndFamily |= FF_ROMAN;
5432             }
5433         }
5434         break;
5435     default:
5436         TM.tmPitchAndFamily |= FF_DONTCARE;
5437     }
5438
5439     if(FT_IS_SCALABLE(ft_face))
5440         TM.tmPitchAndFamily |= TMPF_VECTOR;
5441
5442     if(FT_IS_SFNT(ft_face))
5443     {
5444         if (font->ntmFlags & NTM_PS_OPENTYPE)
5445             TM.tmPitchAndFamily |= TMPF_DEVICE;
5446         else
5447             TM.tmPitchAndFamily |= TMPF_TRUETYPE;
5448     }
5449
5450     TM.tmCharSet = font->charset;
5451
5452     font->potm->otmFiller = 0;
5453     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
5454     font->potm->otmfsSelection = pOS2->fsSelection;
5455     font->potm->otmfsType = pOS2->fsType;
5456     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
5457     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
5458     font->potm->otmItalicAngle = 0; /* POST table */
5459     font->potm->otmEMSquare = ft_face->units_per_EM;
5460     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
5461     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
5462     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
5463     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
5464     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
5465     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
5466     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
5467     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
5468     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
5469     font->potm->otmMacAscent = TM.tmAscent;
5470     font->potm->otmMacDescent = -TM.tmDescent;
5471     font->potm->otmMacLineGap = font->potm->otmLineGap;
5472     font->potm->otmusMinimumPPEM = 0; /* TT Header */
5473     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
5474     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
5475     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
5476     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
5477     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
5478     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
5479     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
5480     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
5481     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
5482     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
5483     if(!pPost) {
5484         font->potm->otmsUnderscoreSize = 0;
5485         font->potm->otmsUnderscorePosition = 0;
5486     } else {
5487         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
5488         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
5489     }
5490 #undef TM
5491
5492     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
5493     cp = (char*)font->potm + sizeof(*font->potm);
5494     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
5495     strcpyW((WCHAR*)cp, family_nameW);
5496     cp += lenfam;
5497     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
5498     strcpyW((WCHAR*)cp, style_nameW);
5499     cp += lensty;
5500     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
5501     strcpyW((WCHAR*)cp, family_nameW);
5502     if (ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) {
5503         strcatW((WCHAR*)cp, spaceW);
5504         strcatW((WCHAR*)cp, style_nameW);
5505         cp += lenfam + lensty;
5506     } else
5507         cp += lenfam;
5508     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
5509     strcpyW((WCHAR*)cp, family_nameW);
5510     strcatW((WCHAR*)cp, spaceW);
5511     strcatW((WCHAR*)cp, style_nameW);
5512     ret = needed;
5513
5514     if(potm && needed <= cbSize)
5515     {
5516         memcpy(potm, font->potm, font->potm->otmSize);
5517         scale_outline_font_metrics(font, potm);
5518     }
5519
5520 end:
5521     HeapFree(GetProcessHeap(), 0, style_nameW);
5522     HeapFree(GetProcessHeap(), 0, family_nameW);
5523
5524     LeaveCriticalSection( &freetype_cs );
5525     return ret;
5526 }
5527
5528 static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
5529 {
5530     HFONTLIST *hfontlist;
5531     child->font = alloc_font();
5532     child->font->ft_face = OpenFontFace(child->font, child->face, 0, -font->ppem);
5533     if(!child->font->ft_face)
5534     {
5535         free_font(child->font);
5536         child->font = NULL;
5537         return FALSE;
5538     }
5539
5540     child->font->font_desc = font->font_desc;
5541     child->font->ntmFlags = child->face->ntmFlags;
5542     child->font->orientation = font->orientation;
5543     child->font->scale_y = font->scale_y;
5544     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
5545     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
5546     list_add_head(&child->font->hfontlist, &hfontlist->entry);
5547     child->font->base_font = font;
5548     list_add_head(&child_font_list, &child->font->entry);
5549     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
5550     return TRUE;
5551 }
5552
5553 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph)
5554 {
5555     FT_UInt g;
5556     CHILD_FONT *child_font;
5557
5558     if(font->base_font)
5559         font = font->base_font;
5560
5561     *linked_font = font;
5562
5563     if((*glyph = get_glyph_index(font, c)))
5564         return TRUE;
5565
5566     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
5567     {
5568         if(!child_font->font)
5569             if(!load_child_font(font, child_font))
5570                 continue;
5571
5572         if(!child_font->font->ft_face)
5573             continue;
5574         g = get_glyph_index(child_font->font, c);
5575         if(g)
5576         {
5577             *glyph = g;
5578             *linked_font = child_font->font;
5579             return TRUE;
5580         }
5581     }
5582     return FALSE;
5583 }
5584
5585 /*************************************************************
5586  * WineEngGetCharWidth
5587  *
5588  */
5589 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
5590                          LPINT buffer)
5591 {
5592     UINT c;
5593     GLYPHMETRICS gm;
5594     FT_UInt glyph_index;
5595     GdiFont *linked_font;
5596
5597     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
5598
5599     EnterCriticalSection( &freetype_cs );
5600     for(c = firstChar; c <= lastChar; c++) {
5601         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
5602         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
5603                                &gm, 0, NULL, NULL);
5604         buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv;
5605     }
5606     LeaveCriticalSection( &freetype_cs );
5607     return TRUE;
5608 }
5609
5610 /*************************************************************
5611  * WineEngGetCharABCWidths
5612  *
5613  */
5614 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
5615                              LPABC buffer)
5616 {
5617     UINT c;
5618     GLYPHMETRICS gm;
5619     FT_UInt glyph_index;
5620     GdiFont *linked_font;
5621
5622     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
5623
5624     if(!FT_IS_SCALABLE(font->ft_face))
5625         return FALSE;
5626
5627     EnterCriticalSection( &freetype_cs );
5628
5629     for(c = firstChar; c <= lastChar; c++) {
5630         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
5631         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
5632                                &gm, 0, NULL, NULL);
5633         buffer[c - firstChar].abcA = FONT_GM(linked_font,glyph_index)->lsb;
5634         buffer[c - firstChar].abcB = FONT_GM(linked_font,glyph_index)->bbx;
5635         buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb -
5636             FONT_GM(linked_font,glyph_index)->bbx;
5637     }
5638     LeaveCriticalSection( &freetype_cs );
5639     return TRUE;
5640 }
5641
5642 /*************************************************************
5643  * WineEngGetCharABCWidthsI
5644  *
5645  */
5646 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
5647                               LPABC buffer)
5648 {
5649     UINT c;
5650     GLYPHMETRICS gm;
5651     FT_UInt glyph_index;
5652     GdiFont *linked_font;
5653
5654     if(!FT_HAS_HORIZONTAL(font->ft_face))
5655         return FALSE;
5656
5657     EnterCriticalSection( &freetype_cs );
5658
5659     get_glyph_index_linked(font, 'a', &linked_font, &glyph_index);
5660     if (!pgi)
5661         for(c = firstChar; c < firstChar+count; c++) {
5662             WineEngGetGlyphOutline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
5663                                    &gm, 0, NULL, NULL);
5664             buffer[c - firstChar].abcA = FONT_GM(linked_font,c)->lsb;
5665             buffer[c - firstChar].abcB = FONT_GM(linked_font,c)->bbx;
5666             buffer[c - firstChar].abcC = FONT_GM(linked_font,c)->adv - FONT_GM(linked_font,c)->lsb
5667                 - FONT_GM(linked_font,c)->bbx;
5668         }
5669     else
5670         for(c = 0; c < count; c++) {
5671             WineEngGetGlyphOutline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
5672                                    &gm, 0, NULL, NULL);
5673             buffer[c].abcA = FONT_GM(linked_font,pgi[c])->lsb;
5674             buffer[c].abcB = FONT_GM(linked_font,pgi[c])->bbx;
5675             buffer[c].abcC = FONT_GM(linked_font,pgi[c])->adv
5676                 - FONT_GM(linked_font,pgi[c])->lsb - FONT_GM(linked_font,pgi[c])->bbx;
5677         }
5678
5679     LeaveCriticalSection( &freetype_cs );
5680     return TRUE;
5681 }
5682
5683 /*************************************************************
5684  * WineEngGetTextExtentExPoint
5685  *
5686  */
5687 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
5688                                  INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
5689 {
5690     INT idx;
5691     INT nfit = 0, ext;
5692     GLYPHMETRICS gm;
5693     TEXTMETRICW tm;
5694     FT_UInt glyph_index;
5695     GdiFont *linked_font;
5696
5697     TRACE("%p, %s, %d, %d, %p\n", font, debugstr_wn(wstr, count), count,
5698           max_ext, size);
5699
5700     EnterCriticalSection( &freetype_cs );
5701
5702     size->cx = 0;
5703     WineEngGetTextMetrics(font, &tm);
5704     size->cy = tm.tmHeight;
5705
5706     for(idx = 0; idx < count; idx++) {
5707         get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
5708         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
5709                                &gm, 0, NULL, NULL);
5710         size->cx += FONT_GM(linked_font,glyph_index)->adv;
5711         ext = size->cx;
5712         if (! pnfit || ext <= max_ext) {
5713             ++nfit;
5714             if (dxs)
5715                 dxs[idx] = ext;
5716         }
5717     }
5718
5719     if (pnfit)
5720         *pnfit = nfit;
5721
5722     LeaveCriticalSection( &freetype_cs );
5723     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
5724     return TRUE;
5725 }
5726
5727 /*************************************************************
5728  * WineEngGetTextExtentExPointI
5729  *
5730  */
5731 BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count,
5732                                   INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
5733 {
5734     INT idx;
5735     INT nfit = 0, ext;
5736     GLYPHMETRICS gm;
5737     TEXTMETRICW tm;
5738
5739     TRACE("%p, %p, %d, %d, %p\n", font, indices, count, max_ext, size);
5740
5741     EnterCriticalSection( &freetype_cs );
5742
5743     size->cx = 0;
5744     WineEngGetTextMetrics(font, &tm);
5745     size->cy = tm.tmHeight;
5746
5747     for(idx = 0; idx < count; idx++) {
5748         WineEngGetGlyphOutline(font, indices[idx],
5749                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
5750                                NULL);
5751         size->cx += FONT_GM(font,indices[idx])->adv;
5752         ext = size->cx;
5753         if (! pnfit || ext <= max_ext) {
5754             ++nfit;
5755             if (dxs)
5756                 dxs[idx] = ext;
5757         }
5758     }
5759
5760     if (pnfit)
5761         *pnfit = nfit;
5762
5763     LeaveCriticalSection( &freetype_cs );
5764     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
5765     return TRUE;
5766 }
5767
5768 /*************************************************************
5769  * WineEngGetFontData
5770  *
5771  */
5772 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
5773                          DWORD cbData)
5774 {
5775     FT_Face ft_face = font->ft_face;
5776     FT_ULong len;
5777     FT_Error err;
5778
5779     TRACE("font=%p, table=%c%c%c%c, offset=0x%x, buf=%p, cbData=0x%x\n",
5780         font, LOBYTE(LOWORD(table)), HIBYTE(LOWORD(table)),
5781         LOBYTE(HIWORD(table)), HIBYTE(HIWORD(table)), offset, buf, cbData);
5782
5783     if(!FT_IS_SFNT(ft_face))
5784         return GDI_ERROR;
5785
5786     if(!buf || !cbData)
5787         len = 0;
5788     else
5789         len = cbData;
5790
5791     if(table) { /* MS tags differ in endianness from FT ones */
5792         table = table >> 24 | table << 24 |
5793           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
5794     }
5795
5796     /* make sure value of len is the value freetype says it needs */
5797     if(buf && len)
5798     {
5799         FT_ULong needed = 0;
5800         err = load_sfnt_table(ft_face, table, offset, NULL, &needed);
5801         if( !err && needed < len) len = needed;
5802     }
5803     err = load_sfnt_table(ft_face, table, offset, buf, &len);
5804
5805     if(err) {
5806         TRACE("Can't find table %c%c%c%c\n",
5807               /* bytes were reversed */
5808               HIBYTE(HIWORD(table)), LOBYTE(HIWORD(table)),
5809               HIBYTE(LOWORD(table)), LOBYTE(LOWORD(table)));
5810         return GDI_ERROR;
5811     }
5812     return len;
5813 }
5814
5815 /*************************************************************
5816  * WineEngGetTextFace
5817  *
5818  */
5819 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
5820 {
5821     INT n = strlenW(font->name) + 1;
5822     if(str) {
5823         lstrcpynW(str, font->name, count);
5824         return min(count, n);
5825     } else
5826         return n;
5827 }
5828
5829 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
5830 {
5831     if (fs) *fs = font->fs;
5832     return font->charset;
5833 }
5834
5835 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
5836 {
5837     GdiFont *font = dc->gdiFont, *linked_font;
5838     struct list *first_hfont;
5839     BOOL ret;
5840
5841     EnterCriticalSection( &freetype_cs );
5842     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
5843     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
5844     if(font == linked_font)
5845         *new_hfont = dc->hFont;
5846     else
5847     {
5848         first_hfont = list_head(&linked_font->hfontlist);
5849         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
5850     }
5851     LeaveCriticalSection( &freetype_cs );
5852     return ret;
5853 }
5854     
5855 /* Retrieve a list of supported Unicode ranges for a given font.
5856  * Can be called with NULL gs to calculate the buffer size. Returns
5857  * the number of ranges found.
5858  */
5859 static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
5860 {
5861     DWORD num_ranges = 0;
5862
5863     if (face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
5864     {
5865         FT_UInt glyph_code;
5866         FT_ULong char_code, char_code_prev;
5867
5868         glyph_code = 0;
5869         char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
5870
5871         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
5872                face->num_glyphs, glyph_code, char_code);
5873
5874         if (!glyph_code) return 0;
5875
5876         if (gs)
5877         {
5878             gs->ranges[0].wcLow = (USHORT)char_code;
5879             gs->ranges[0].cGlyphs = 0;
5880             gs->cGlyphsSupported = 0;
5881         }
5882
5883         num_ranges = 1;
5884         while (glyph_code)
5885         {
5886             if (char_code < char_code_prev)
5887             {
5888                 ERR("expected increasing char code from FT_Get_Next_Char\n");
5889                 return 0;
5890             }
5891             if (char_code - char_code_prev > 1)
5892             {
5893                 num_ranges++;
5894                 if (gs)
5895                 {
5896                     gs->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
5897                     gs->ranges[num_ranges - 1].cGlyphs = 1;
5898                     gs->cGlyphsSupported++;
5899                 }
5900             }
5901             else if (gs)
5902             {
5903                 gs->ranges[num_ranges - 1].cGlyphs++;
5904                 gs->cGlyphsSupported++;
5905             }
5906             char_code_prev = char_code;
5907             char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
5908         }
5909     }
5910     else
5911         FIXME("encoding %u not supported\n", face->charmap->encoding);
5912
5913     return num_ranges;
5914 }
5915
5916 DWORD WineEngGetFontUnicodeRanges(GdiFont *font, LPGLYPHSET glyphset)
5917 {
5918     DWORD size = 0;
5919     DWORD num_ranges = get_font_unicode_ranges(font->ft_face, glyphset);
5920
5921     size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
5922     if (glyphset)
5923     {
5924         glyphset->cbThis = size;
5925         glyphset->cRanges = num_ranges;
5926     }
5927     return size;
5928 }
5929
5930 /*************************************************************
5931  *     FontIsLinked
5932  */
5933 BOOL WineEngFontIsLinked(GdiFont *font)
5934 {
5935     BOOL ret;
5936     EnterCriticalSection( &freetype_cs );
5937     ret = !list_empty(&font->child_fonts);
5938     LeaveCriticalSection( &freetype_cs );
5939     return ret;
5940 }
5941
5942 static BOOL is_hinting_enabled(void)
5943 {
5944     /* Use the >= 2.2.0 function if available */
5945     if(pFT_Get_TrueType_Engine_Type)
5946     {
5947         FT_TrueTypeEngineType type = pFT_Get_TrueType_Engine_Type(library);
5948         return type == FT_TRUETYPE_ENGINE_TYPE_PATENTED;
5949     }
5950 #ifdef FT_DRIVER_HAS_HINTER
5951     else
5952     {
5953         FT_Module mod;
5954
5955         /* otherwise if we've been compiled with < 2.2.0 headers 
5956            use the internal macro */
5957         mod = pFT_Get_Module(library, "truetype");
5958         if(mod && FT_DRIVER_HAS_HINTER(mod))
5959             return TRUE;
5960     }
5961 #endif
5962
5963     return FALSE;
5964 }
5965
5966 static BOOL is_subpixel_rendering_enabled( void )
5967 {
5968 #ifdef HAVE_FREETYPE_FTLCDFIL_H
5969     return pFT_Library_SetLcdFilter &&
5970            pFT_Library_SetLcdFilter( NULL, 0 ) != FT_Err_Unimplemented_Feature;
5971 #else
5972     return FALSE;
5973 #endif
5974 }
5975
5976 /*************************************************************************
5977  *             GetRasterizerCaps   (GDI32.@)
5978  */
5979 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
5980 {
5981     static int hinting = -1;
5982     static int subpixel = -1;
5983
5984     if(hinting == -1)
5985     {
5986         hinting = is_hinting_enabled();
5987         TRACE("hinting is %senabled\n", hinting ? "" : "NOT ");
5988     }
5989
5990     if ( subpixel == -1 )
5991     {
5992         subpixel = is_subpixel_rendering_enabled();
5993         TRACE("subpixel rendering is %senabled\n", subpixel ? "" : "NOT ");
5994     }
5995
5996     lprs->nSize = sizeof(RASTERIZER_STATUS);
5997     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
5998     if ( subpixel )
5999         lprs->wFlags |= WINE_TT_SUBPIXEL_RENDERING_ENABLED;
6000     lprs->nLanguageID = 0;
6001     return TRUE;
6002 }
6003
6004 /*************************************************************
6005  *     WineEngRealizationInfo
6006  */
6007 BOOL WineEngRealizationInfo(GdiFont *font, realization_info_t *info)
6008 {
6009     FIXME("(%p, %p): stub!\n", font, info);
6010
6011     info->flags = 1;
6012     if(FT_IS_SCALABLE(font->ft_face))
6013         info->flags |= 2;
6014
6015     info->cache_num = font->cache_num;
6016     info->unknown2 = -1;
6017     return TRUE;
6018 }
6019
6020 /*************************************************************************
6021  * Kerning support for TrueType fonts
6022  */
6023 #define MS_KERN_TAG MS_MAKE_TAG('k', 'e', 'r', 'n')
6024
6025 struct TT_kern_table
6026 {
6027     USHORT version;
6028     USHORT nTables;
6029 };
6030
6031 struct TT_kern_subtable
6032 {
6033     USHORT version;
6034     USHORT length;
6035     union
6036     {
6037         USHORT word;
6038         struct
6039         {
6040             USHORT horizontal : 1;
6041             USHORT minimum : 1;
6042             USHORT cross_stream: 1;
6043             USHORT override : 1;
6044             USHORT reserved1 : 4;
6045             USHORT format : 8;
6046         } bits;
6047     } coverage;
6048 };
6049
6050 struct TT_format0_kern_subtable
6051 {
6052     USHORT nPairs;
6053     USHORT searchRange;
6054     USHORT entrySelector;
6055     USHORT rangeShift;
6056 };
6057
6058 struct TT_kern_pair
6059 {
6060     USHORT left;
6061     USHORT right;
6062     short  value;
6063 };
6064
6065 static DWORD parse_format0_kern_subtable(GdiFont *font,
6066                                          const struct TT_format0_kern_subtable *tt_f0_ks,
6067                                          const USHORT *glyph_to_char,
6068                                          KERNINGPAIR *kern_pair, DWORD cPairs)
6069 {
6070     USHORT i, nPairs;
6071     const struct TT_kern_pair *tt_kern_pair;
6072
6073     TRACE("font height %d, units_per_EM %d\n", font->ppem, font->ft_face->units_per_EM);
6074
6075     nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
6076
6077     TRACE("nPairs %u, searchRange %u, entrySelector %u, rangeShift %u\n",
6078            nPairs, GET_BE_WORD(tt_f0_ks->searchRange),
6079            GET_BE_WORD(tt_f0_ks->entrySelector), GET_BE_WORD(tt_f0_ks->rangeShift));
6080
6081     if (!kern_pair || !cPairs)
6082         return nPairs;
6083
6084     tt_kern_pair = (const struct TT_kern_pair *)(tt_f0_ks + 1);
6085
6086     nPairs = min(nPairs, cPairs);
6087
6088     for (i = 0; i < nPairs; i++)
6089     {
6090         kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
6091         kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
6092         /* this algorithm appears to better match what Windows does */
6093         kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
6094         if (kern_pair->iKernAmount < 0)
6095         {
6096             kern_pair->iKernAmount -= font->ft_face->units_per_EM / 2;
6097             kern_pair->iKernAmount -= font->ppem;
6098         }
6099         else if (kern_pair->iKernAmount > 0)
6100         {
6101             kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
6102             kern_pair->iKernAmount += font->ppem;
6103         }
6104         kern_pair->iKernAmount /= font->ft_face->units_per_EM;
6105
6106         TRACE("left %u right %u value %d\n",
6107                kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
6108
6109         kern_pair++;
6110     }
6111     TRACE("copied %u entries\n", nPairs);
6112     return nPairs;
6113 }
6114
6115 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
6116 {
6117     DWORD length;
6118     void *buf;
6119     const struct TT_kern_table *tt_kern_table;
6120     const struct TT_kern_subtable *tt_kern_subtable;
6121     USHORT i, nTables;
6122     USHORT *glyph_to_char;
6123
6124     EnterCriticalSection( &freetype_cs );
6125     if (font->total_kern_pairs != (DWORD)-1)
6126     {
6127         if (cPairs && kern_pair)
6128         {
6129             cPairs = min(cPairs, font->total_kern_pairs);
6130             memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
6131             LeaveCriticalSection( &freetype_cs );
6132             return cPairs;
6133         }
6134         LeaveCriticalSection( &freetype_cs );
6135         return font->total_kern_pairs;
6136     }
6137
6138     font->total_kern_pairs = 0;
6139
6140     length = WineEngGetFontData(font, MS_KERN_TAG, 0, NULL, 0);
6141
6142     if (length == GDI_ERROR)
6143     {
6144         TRACE("no kerning data in the font\n");
6145         LeaveCriticalSection( &freetype_cs );
6146         return 0;
6147     }
6148
6149     buf = HeapAlloc(GetProcessHeap(), 0, length);
6150     if (!buf)
6151     {
6152         WARN("Out of memory\n");
6153         LeaveCriticalSection( &freetype_cs );
6154         return 0;
6155     }
6156
6157     WineEngGetFontData(font, MS_KERN_TAG, 0, buf, length);
6158
6159     /* build a glyph index to char code map */
6160     glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
6161     if (!glyph_to_char)
6162     {
6163         WARN("Out of memory allocating a glyph index to char code map\n");
6164         HeapFree(GetProcessHeap(), 0, buf);
6165         LeaveCriticalSection( &freetype_cs );
6166         return 0;
6167     }
6168
6169     if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
6170     {
6171         FT_UInt glyph_code;
6172         FT_ULong char_code;
6173
6174         glyph_code = 0;
6175         char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
6176
6177         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
6178                font->ft_face->num_glyphs, glyph_code, char_code);
6179
6180         while (glyph_code)
6181         {
6182             /*TRACE("Char %04lX -> Index %u%s\n", char_code, glyph_code, glyph_to_char[glyph_code] ? "  !" : "" );*/
6183
6184             /* FIXME: This doesn't match what Windows does: it does some fancy
6185              * things with duplicate glyph index to char code mappings, while
6186              * we just avoid overriding existing entries.
6187              */
6188             if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
6189                 glyph_to_char[glyph_code] = (USHORT)char_code;
6190
6191             char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
6192         }
6193     }
6194     else
6195     {
6196         ULONG n;
6197
6198         FIXME("encoding %u not supported\n", font->ft_face->charmap->encoding);
6199         for (n = 0; n <= 65535; n++)
6200             glyph_to_char[n] = (USHORT)n;
6201     }
6202
6203     tt_kern_table = buf;
6204     nTables = GET_BE_WORD(tt_kern_table->nTables);
6205     TRACE("version %u, nTables %u\n",
6206            GET_BE_WORD(tt_kern_table->version), nTables);
6207
6208     tt_kern_subtable = (const struct TT_kern_subtable *)(tt_kern_table + 1);
6209
6210     for (i = 0; i < nTables; i++)
6211     {
6212         struct TT_kern_subtable tt_kern_subtable_copy;
6213
6214         tt_kern_subtable_copy.version = GET_BE_WORD(tt_kern_subtable->version);
6215         tt_kern_subtable_copy.length = GET_BE_WORD(tt_kern_subtable->length);
6216         tt_kern_subtable_copy.coverage.word = GET_BE_WORD(tt_kern_subtable->coverage.word);
6217
6218         TRACE("version %u, length %u, coverage %u, subtable format %u\n",
6219                tt_kern_subtable_copy.version, tt_kern_subtable_copy.length,
6220                tt_kern_subtable_copy.coverage.word, tt_kern_subtable_copy.coverage.bits.format);
6221
6222         /* According to the TrueType specification this is the only format
6223          * that will be properly interpreted by Windows and OS/2
6224          */
6225         if (tt_kern_subtable_copy.coverage.bits.format == 0)
6226         {
6227             DWORD new_chunk, old_total = font->total_kern_pairs;
6228
6229             new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
6230                                                     glyph_to_char, NULL, 0);
6231             font->total_kern_pairs += new_chunk;
6232
6233             if (!font->kern_pairs)
6234                 font->kern_pairs = HeapAlloc(GetProcessHeap(), 0,
6235                                              font->total_kern_pairs * sizeof(*font->kern_pairs));
6236             else
6237                 font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs,
6238                                                font->total_kern_pairs * sizeof(*font->kern_pairs));
6239
6240             parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
6241                         glyph_to_char, font->kern_pairs + old_total, new_chunk);
6242         }
6243         else
6244             TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format);
6245
6246         tt_kern_subtable = (const struct TT_kern_subtable *)((const char *)tt_kern_subtable + tt_kern_subtable_copy.length);
6247     }
6248
6249     HeapFree(GetProcessHeap(), 0, glyph_to_char);
6250     HeapFree(GetProcessHeap(), 0, buf);
6251
6252     if (cPairs && kern_pair)
6253     {
6254         cPairs = min(cPairs, font->total_kern_pairs);
6255         memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
6256         LeaveCriticalSection( &freetype_cs );
6257         return cPairs;
6258     }
6259     LeaveCriticalSection( &freetype_cs );
6260     return font->total_kern_pairs;
6261 }
6262
6263 #else /* HAVE_FREETYPE */
6264
6265 /*************************************************************************/
6266
6267 BOOL WineEngInit(void)
6268 {
6269     return FALSE;
6270 }
6271 GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont)
6272 {
6273     return NULL;
6274 }
6275 BOOL WineEngDestroyFontInstance(HFONT hfont)
6276 {
6277     return FALSE;
6278 }
6279
6280 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
6281 {
6282     return 1;
6283 }
6284
6285 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
6286                                 LPWORD pgi, DWORD flags)
6287 {
6288     return GDI_ERROR;
6289 }
6290
6291 DWORD WineEngGetGlyphOutline(GdiFont *font, UINT glyph, UINT format,
6292                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
6293                              const MAT2* lpmat)
6294 {
6295     ERR("called but we don't have FreeType\n");
6296     return GDI_ERROR;
6297 }
6298
6299 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
6300 {
6301     ERR("called but we don't have FreeType\n");
6302     return FALSE;
6303 }
6304
6305 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
6306                                   OUTLINETEXTMETRICW *potm)
6307 {
6308     ERR("called but we don't have FreeType\n");
6309     return 0;
6310 }
6311
6312 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
6313                          LPINT buffer)
6314 {
6315     ERR("called but we don't have FreeType\n");
6316     return FALSE;
6317 }
6318
6319 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
6320                              LPABC buffer)
6321 {
6322     ERR("called but we don't have FreeType\n");
6323     return FALSE;
6324 }
6325
6326 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
6327                               LPABC buffer)
6328 {
6329     ERR("called but we don't have FreeType\n");
6330     return FALSE;
6331 }
6332
6333 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
6334                                  INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
6335 {
6336     ERR("called but we don't have FreeType\n");
6337     return FALSE;
6338 }
6339
6340 BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count,
6341                                   INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
6342 {
6343     ERR("called but we don't have FreeType\n");
6344     return FALSE;
6345 }
6346
6347 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
6348                          DWORD cbData)
6349 {
6350     ERR("called but we don't have FreeType\n");
6351     return GDI_ERROR;
6352 }
6353
6354 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
6355 {
6356     ERR("called but we don't have FreeType\n");
6357     return 0;
6358 }
6359
6360 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
6361 {
6362     FIXME(":stub\n");
6363     return 1;
6364 }
6365
6366 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
6367 {
6368     FIXME(":stub\n");
6369     return TRUE;
6370 }
6371
6372 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
6373 {
6374     FIXME(":stub\n");
6375     return NULL;
6376 }
6377
6378 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
6379 {
6380     FIXME(":stub\n");
6381     return DEFAULT_CHARSET;
6382 }
6383
6384 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
6385 {
6386     return FALSE;
6387 }
6388
6389 DWORD WineEngGetFontUnicodeRanges(GdiFont *font, LPGLYPHSET glyphset)
6390 {
6391     FIXME("(%p, %p): stub\n", font, glyphset);
6392     return 0;
6393 }
6394
6395 BOOL WineEngFontIsLinked(GdiFont *font)
6396 {
6397     return FALSE;
6398 }
6399
6400 /*************************************************************************
6401  *             GetRasterizerCaps   (GDI32.@)
6402  */
6403 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
6404 {
6405     lprs->nSize = sizeof(RASTERIZER_STATUS);
6406     lprs->wFlags = 0;
6407     lprs->nLanguageID = 0;
6408     return TRUE;
6409 }
6410
6411 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
6412 {
6413     ERR("called but we don't have FreeType\n");
6414     return 0;
6415 }
6416
6417 BOOL WineEngRealizationInfo(GdiFont *font, realization_info_t *info)
6418 {
6419     ERR("called but we don't have FreeType\n");
6420     return FALSE;
6421 }
6422
6423 #endif /* HAVE_FREETYPE */