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