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