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