gdi32: Always start a new stroke when the path ends with a closed figure.
[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                     const char* home;
3119                     LPSTR next = strchr( ptr, ':' );
3120                     if (next) *next++ = 0;
3121                     if (ptr[0] == '~' && ptr[1] == '/' && (home = getenv( "HOME" )) &&
3122                         (unixname = HeapAlloc( GetProcessHeap(), 0, strlen(ptr) + strlen(home) )))
3123                     {
3124                         strcpy( unixname, home );
3125                         strcat( unixname, ptr + 1 );
3126                         ReadFontDir( unixname, TRUE );
3127                         HeapFree( GetProcessHeap(), 0, unixname );
3128                     }
3129                     else
3130                         ReadFontDir( ptr, TRUE );
3131                     ptr = next;
3132                 }
3133                 HeapFree( GetProcessHeap(), 0, valueA );
3134             }
3135             HeapFree( GetProcessHeap(), 0, valueW );
3136         }
3137         RegCloseKey(hkey);
3138     }
3139 }
3140
3141 static BOOL move_to_front(const WCHAR *name)
3142 {
3143     Family *family, *cursor2;
3144     LIST_FOR_EACH_ENTRY_SAFE(family, cursor2, &font_list, Family, entry)
3145     {
3146         if(!strcmpiW(family->FamilyName, name))
3147         {
3148             list_remove(&family->entry);
3149             list_add_head(&font_list, &family->entry);
3150             return TRUE;
3151         }
3152     }
3153     return FALSE;
3154 }
3155
3156 static BOOL set_default(const WCHAR **name_list)
3157 {
3158     while (*name_list)
3159     {
3160         if (move_to_front(*name_list)) return TRUE;
3161         name_list++;
3162     }
3163
3164     return FALSE;
3165 }
3166
3167 static void reorder_font_list(void)
3168 {
3169     set_default( default_serif_list );
3170     set_default( default_fixed_list );
3171     set_default( default_sans_list );
3172 }
3173
3174 /*************************************************************
3175  *    WineEngInit
3176  *
3177  * Initialize FreeType library and create a list of available faces
3178  */
3179 BOOL WineEngInit(void)
3180 {
3181     HKEY hkey_font_cache;
3182     DWORD disposition;
3183     HANDLE font_mutex;
3184
3185     /* update locale dependent font info in registry */
3186     update_font_info();
3187
3188     if(!init_freetype()) return FALSE;
3189
3190     if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL)
3191     {
3192         ERR("Failed to create font mutex\n");
3193         return FALSE;
3194     }
3195     WaitForSingleObject(font_mutex, INFINITE);
3196
3197     create_font_cache_key(&hkey_font_cache, &disposition);
3198
3199     if(disposition == REG_CREATED_NEW_KEY)
3200         init_font_list();
3201     else
3202         load_font_list_from_cache(hkey_font_cache);
3203
3204     RegCloseKey(hkey_font_cache);
3205
3206     reorder_font_list();
3207
3208     DumpFontList();
3209     LoadSubstList();
3210     DumpSubstList();
3211     LoadReplaceList();
3212
3213     if(disposition == REG_CREATED_NEW_KEY)
3214         update_reg_entries();
3215
3216     update_system_links();
3217     init_system_links();
3218     
3219     ReleaseMutex(font_mutex);
3220     return TRUE;
3221 }
3222
3223
3224 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
3225 {
3226     TT_OS2 *pOS2;
3227     TT_HoriHeader *pHori;
3228
3229     LONG ppem;
3230
3231     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
3232     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
3233
3234     if(height == 0) height = 16;
3235
3236     /* Calc. height of EM square:
3237      *
3238      * For +ve lfHeight we have
3239      * lfHeight = (winAscent + winDescent) * ppem / units_per_em
3240      * Re-arranging gives:
3241      * ppem = units_per_em * lfheight / (winAscent + winDescent)
3242      *
3243      * For -ve lfHeight we have
3244      * |lfHeight| = ppem
3245      * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
3246      * with il = winAscent + winDescent - units_per_em]
3247      *
3248      */
3249
3250     if(height > 0) {
3251         if(pOS2->usWinAscent + pOS2->usWinDescent == 0)
3252             ppem = MulDiv(ft_face->units_per_EM, height,
3253                           pHori->Ascender - pHori->Descender);
3254         else
3255             ppem = MulDiv(ft_face->units_per_EM, height,
3256                           pOS2->usWinAscent + pOS2->usWinDescent);
3257     }
3258     else
3259         ppem = -height;
3260
3261     return ppem;
3262 }
3263
3264 static struct font_mapping *map_font_file( const char *name )
3265 {
3266     struct font_mapping *mapping;
3267     struct stat st;
3268     int fd;
3269
3270     if ((fd = open( name, O_RDONLY )) == -1) return NULL;
3271     if (fstat( fd, &st ) == -1) goto error;
3272
3273     LIST_FOR_EACH_ENTRY( mapping, &mappings_list, struct font_mapping, entry )
3274     {
3275         if (mapping->dev == st.st_dev && mapping->ino == st.st_ino)
3276         {
3277             mapping->refcount++;
3278             close( fd );
3279             return mapping;
3280         }
3281     }
3282     if (!(mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(*mapping) )))
3283         goto error;
3284
3285     mapping->data = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
3286     close( fd );
3287
3288     if (mapping->data == MAP_FAILED)
3289     {
3290         HeapFree( GetProcessHeap(), 0, mapping );
3291         return NULL;
3292     }
3293     mapping->refcount = 1;
3294     mapping->dev = st.st_dev;
3295     mapping->ino = st.st_ino;
3296     mapping->size = st.st_size;
3297     list_add_tail( &mappings_list, &mapping->entry );
3298     return mapping;
3299
3300 error:
3301     close( fd );
3302     return NULL;
3303 }
3304
3305 static void unmap_font_file( struct font_mapping *mapping )
3306 {
3307     if (!--mapping->refcount)
3308     {
3309         list_remove( &mapping->entry );
3310         munmap( mapping->data, mapping->size );
3311         HeapFree( GetProcessHeap(), 0, mapping );
3312     }
3313 }
3314
3315 static LONG load_VDMX(GdiFont*, LONG);
3316
3317 static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height)
3318 {
3319     FT_Error err;
3320     FT_Face ft_face;
3321     void *data_ptr;
3322     DWORD data_size;
3323
3324     TRACE("%s/%p, %ld, %d x %d\n", debugstr_a(face->file), face->font_data_ptr, face->face_index, width, height);
3325
3326     if (face->file)
3327     {
3328         if (!(font->mapping = map_font_file( face->file )))
3329         {
3330             WARN("failed to map %s\n", debugstr_a(face->file));
3331             return 0;
3332         }
3333         data_ptr = font->mapping->data;
3334         data_size = font->mapping->size;
3335     }
3336     else
3337     {
3338         data_ptr = face->font_data_ptr;
3339         data_size = face->font_data_size;
3340     }
3341
3342     err = pFT_New_Memory_Face(library, data_ptr, data_size, face->face_index, &ft_face);
3343     if(err) {
3344         ERR("FT_New_Face rets %d\n", err);
3345         return 0;
3346     }
3347
3348     /* set it here, as load_VDMX needs it */
3349     font->ft_face = ft_face;
3350
3351     if(FT_IS_SCALABLE(ft_face)) {
3352         /* load the VDMX table if we have one */
3353         font->ppem = load_VDMX(font, height);
3354         if(font->ppem == 0)
3355             font->ppem = calc_ppem_for_height(ft_face, height);
3356         TRACE("height %d => ppem %d\n", height, font->ppem);
3357
3358         if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0)
3359             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", 0, font->ppem, err);
3360     } else {
3361         font->ppem = height;
3362         if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
3363             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", width, height, err);
3364     }
3365     return ft_face;
3366 }
3367
3368
3369 static int get_nearest_charset(Face *face, int *cp)
3370 {
3371   /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
3372      a single face with the requested charset.  The idea is to check if
3373      the selected font supports the current ANSI codepage, if it does
3374      return the corresponding charset, else return the first charset */
3375
3376     CHARSETINFO csi;
3377     int acp = GetACP(), i;
3378     DWORD fs0;
3379
3380     *cp = acp;
3381     if(TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE))
3382         if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
3383             return csi.ciCharset;
3384
3385     for(i = 0; i < 32; i++) {
3386         fs0 = 1L << i;
3387         if(face->fs.fsCsb[0] & fs0) {
3388             if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG)) {
3389                 *cp = csi.ciACP;
3390                 return csi.ciCharset;
3391             }
3392             else
3393                 FIXME("TCI failing on %x\n", fs0);
3394         }
3395     }
3396
3397     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08x file = %s\n",
3398           face->fs.fsCsb[0], face->file);
3399     *cp = acp;
3400     return DEFAULT_CHARSET;
3401 }
3402
3403 static GdiFont *alloc_font(void)
3404 {
3405     GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
3406     ret->gmsize = 1;
3407     ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM*));
3408     ret->gm[0] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
3409     ret->potm = NULL;
3410     ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
3411     ret->total_kern_pairs = (DWORD)-1;
3412     ret->kern_pairs = NULL;
3413     list_init(&ret->hfontlist);
3414     list_init(&ret->child_fonts);
3415     return ret;
3416 }
3417
3418 static void free_font(GdiFont *font)
3419 {
3420     struct list *cursor, *cursor2;
3421     DWORD i;
3422
3423     LIST_FOR_EACH_SAFE(cursor, cursor2, &font->child_fonts)
3424     {
3425         CHILD_FONT *child = LIST_ENTRY(cursor, CHILD_FONT, entry);
3426         list_remove(cursor);
3427         if(child->font)
3428             free_font(child->font);
3429         HeapFree(GetProcessHeap(), 0, child);
3430     }
3431
3432     LIST_FOR_EACH_SAFE(cursor, cursor2, &font->hfontlist)
3433     {
3434         HFONTLIST *hfontlist = LIST_ENTRY(cursor, HFONTLIST, entry);
3435         DeleteObject(hfontlist->hfont);
3436         list_remove(&hfontlist->entry);
3437         HeapFree(GetProcessHeap(), 0, hfontlist);
3438     }
3439
3440     if (font->ft_face) pFT_Done_Face(font->ft_face);
3441     if (font->mapping) unmap_font_file( font->mapping );
3442     HeapFree(GetProcessHeap(), 0, font->kern_pairs);
3443     HeapFree(GetProcessHeap(), 0, font->potm);
3444     HeapFree(GetProcessHeap(), 0, font->name);
3445     for (i = 0; i < font->gmsize; i++)
3446         HeapFree(GetProcessHeap(),0,font->gm[i]);
3447     HeapFree(GetProcessHeap(), 0, font->gm);
3448     HeapFree(GetProcessHeap(), 0, font->GSUB_Table);
3449     HeapFree(GetProcessHeap(), 0, font);
3450 }
3451
3452
3453 static DWORD get_font_data( GdiFont *font, DWORD table, DWORD offset, LPVOID buf, DWORD cbData)
3454 {
3455     FT_Face ft_face = font->ft_face;
3456     FT_ULong len;
3457     FT_Error err;
3458
3459     if (!FT_IS_SFNT(ft_face)) return GDI_ERROR;
3460
3461     if(!buf)
3462         len = 0;
3463     else
3464         len = cbData;
3465
3466     table = RtlUlongByteSwap( table );  /* MS tags differ in endianness from FT ones */
3467
3468     /* make sure value of len is the value freetype says it needs */
3469     if (buf && len)
3470     {
3471         FT_ULong needed = 0;
3472         err = pFT_Load_Sfnt_Table(ft_face, table, offset, NULL, &needed);
3473         if( !err && needed < len) len = needed;
3474     }
3475     err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, &len);
3476     if (err)
3477     {
3478         TRACE("Can't find table %c%c%c%c\n",
3479               /* bytes were reversed */
3480               HIBYTE(HIWORD(table)), LOBYTE(HIWORD(table)),
3481               HIBYTE(LOWORD(table)), LOBYTE(LOWORD(table)));
3482         return GDI_ERROR;
3483     }
3484     return len;
3485 }
3486
3487 /*************************************************************
3488  * load_VDMX
3489  *
3490  * load the vdmx entry for the specified height
3491  */
3492
3493 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
3494           ( ( (FT_ULong)_x4 << 24 ) |     \
3495             ( (FT_ULong)_x3 << 16 ) |     \
3496             ( (FT_ULong)_x2 <<  8 ) |     \
3497               (FT_ULong)_x1         )
3498
3499 #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X')
3500
3501 typedef struct {
3502     BYTE bCharSet;
3503     BYTE xRatio;
3504     BYTE yStartRatio;
3505     BYTE yEndRatio;
3506 } Ratios;
3507
3508 typedef struct {
3509     WORD recs;
3510     BYTE startsz;
3511     BYTE endsz;
3512 } VDMX_group;
3513
3514 static LONG load_VDMX(GdiFont *font, LONG height)
3515 {
3516     WORD hdr[3], tmp;
3517     VDMX_group group;
3518     BYTE devXRatio, devYRatio;
3519     USHORT numRecs, numRatios;
3520     DWORD result, offset = -1;
3521     LONG ppem = 0;
3522     int i;
3523
3524     result = get_font_data(font, MS_VDMX_TAG, 0, hdr, 6);
3525
3526     if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
3527         return ppem;
3528
3529     /* FIXME: need the real device aspect ratio */
3530     devXRatio = 1;
3531     devYRatio = 1;
3532
3533     numRecs = GET_BE_WORD(hdr[1]);
3534     numRatios = GET_BE_WORD(hdr[2]);
3535
3536     TRACE("numRecs = %d numRatios = %d\n", numRecs, numRatios);
3537     for(i = 0; i < numRatios; i++) {
3538         Ratios ratio;
3539
3540         offset = (3 * 2) + (i * sizeof(Ratios));
3541         get_font_data(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
3542         offset = -1;
3543
3544         TRACE("Ratios[%d] %d  %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
3545
3546         if((ratio.xRatio == 0 &&
3547             ratio.yStartRatio == 0 &&
3548             ratio.yEndRatio == 0) ||
3549            (devXRatio == ratio.xRatio &&
3550             devYRatio >= ratio.yStartRatio &&
3551             devYRatio <= ratio.yEndRatio))
3552             {
3553                 offset = (3 * 2) + (numRatios * 4) + (i * 2);
3554                 get_font_data(font, MS_VDMX_TAG, offset, &tmp, 2);
3555                 offset = GET_BE_WORD(tmp);
3556                 break;
3557             }
3558     }
3559
3560     if(offset == -1) {
3561         FIXME("No suitable ratio found\n");
3562         return ppem;
3563     }
3564
3565     if(get_font_data(font, MS_VDMX_TAG, offset, &group, 4) != GDI_ERROR) {
3566         USHORT recs;
3567         BYTE startsz, endsz;
3568         WORD *vTable;
3569
3570         recs = GET_BE_WORD(group.recs);
3571         startsz = group.startsz;
3572         endsz = group.endsz;
3573
3574         TRACE("recs=%d  startsz=%d  endsz=%d\n", recs, startsz, endsz);
3575
3576         vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6);
3577         result = get_font_data(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6);
3578         if(result == GDI_ERROR) {
3579             FIXME("Failed to retrieve vTable\n");
3580             goto end;
3581         }
3582
3583         if(height > 0) {
3584             for(i = 0; i < recs; i++) {
3585                 SHORT yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
3586                 SHORT yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
3587                 ppem = GET_BE_WORD(vTable[i * 3]);
3588
3589                 if(yMax + -yMin == height) {
3590                     font->yMax = yMax;
3591                     font->yMin = yMin;
3592                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
3593                     break;
3594                 }
3595                 if(yMax + -yMin > height) {
3596                     if(--i < 0) {
3597                         ppem = 0;
3598                         goto end; /* failed */
3599                     }
3600                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
3601                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
3602                     ppem = GET_BE_WORD(vTable[i * 3]);
3603                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
3604                     break;
3605                 }
3606             }
3607             if(!font->yMax) {
3608                 ppem = 0;
3609                 TRACE("ppem not found for height %d\n", height);
3610             }
3611         }
3612         end:
3613         HeapFree(GetProcessHeap(), 0, vTable);
3614     }
3615
3616     return ppem;
3617 }
3618
3619 static BOOL fontcmp(const GdiFont *font, FONT_DESC *fd)
3620 {
3621     if(font->font_desc.hash != fd->hash) return TRUE;
3622     if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE;
3623     if(memcmp(&font->font_desc.lf, &fd->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
3624     if(!font->font_desc.can_use_bitmap != !fd->can_use_bitmap) return TRUE;
3625     return strcmpiW(font->font_desc.lf.lfFaceName, fd->lf.lfFaceName);
3626 }
3627
3628 static void calc_hash(FONT_DESC *pfd)
3629 {
3630     DWORD hash = 0, *ptr, two_chars;
3631     WORD *pwc;
3632     unsigned int i;
3633
3634     for(i = 0, ptr = (DWORD*)&pfd->matrix; i < sizeof(FMAT2)/sizeof(DWORD); i++, ptr++)
3635         hash ^= *ptr;
3636     for(i = 0, ptr = (DWORD*)&pfd->lf; i < 7; i++, ptr++)
3637         hash ^= *ptr;
3638     for(i = 0, ptr = (DWORD*)pfd->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
3639         two_chars = *ptr;
3640         pwc = (WCHAR *)&two_chars;
3641         if(!*pwc) break;
3642         *pwc = toupperW(*pwc);
3643         pwc++;
3644         *pwc = toupperW(*pwc);
3645         hash ^= two_chars;
3646         if(!*pwc) break;
3647     }
3648     hash ^= !pfd->can_use_bitmap;
3649     pfd->hash = hash;
3650     return;
3651 }
3652
3653 static GdiFont *find_in_cache(HFONT hfont, const LOGFONTW *plf, const FMAT2 *pmat, BOOL can_use_bitmap)
3654 {
3655     GdiFont *ret;
3656     FONT_DESC fd;
3657     HFONTLIST *hflist;
3658     struct list *font_elem_ptr, *hfontlist_elem_ptr;
3659
3660     fd.lf = *plf;
3661     fd.matrix = *pmat;
3662     fd.can_use_bitmap = can_use_bitmap;
3663     calc_hash(&fd);
3664
3665     /* try the child list */
3666     LIST_FOR_EACH(font_elem_ptr, &child_font_list) {
3667         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3668         if(!fontcmp(ret, &fd)) {
3669             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
3670             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
3671                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3672                 if(hflist->hfont == hfont)
3673                     return ret;
3674             }
3675         }
3676     }
3677
3678     /* try the in-use list */
3679     LIST_FOR_EACH(font_elem_ptr, &gdi_font_list) {
3680         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3681         if(!fontcmp(ret, &fd)) {
3682             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
3683             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
3684                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3685                 if(hflist->hfont == hfont)
3686                     return ret;
3687             }
3688             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3689             hflist->hfont = hfont;
3690             list_add_head(&ret->hfontlist, &hflist->entry);
3691             return ret;
3692         }
3693     }
3694  
3695     /* then the unused list */
3696     font_elem_ptr = list_head(&unused_gdi_font_list);
3697     while(font_elem_ptr) {
3698         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3699         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
3700         if(!fontcmp(ret, &fd)) {
3701             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
3702             assert(list_empty(&ret->hfontlist));
3703             TRACE("Found %p in unused list\n", ret);
3704             list_remove(&ret->entry);
3705             list_add_head(&gdi_font_list, &ret->entry);
3706             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3707             hflist->hfont = hfont;
3708             list_add_head(&ret->hfontlist, &hflist->entry);
3709             return ret;
3710         }
3711     }
3712     return NULL;
3713 }
3714
3715 static void add_to_cache(GdiFont *font)
3716 {
3717     static DWORD cache_num = 1;
3718
3719     font->cache_num = cache_num++;
3720     list_add_head(&gdi_font_list, &font->entry);
3721 }
3722
3723 /*************************************************************
3724  * create_child_font_list
3725  */
3726 static BOOL create_child_font_list(GdiFont *font)
3727 {
3728     BOOL ret = FALSE;
3729     SYSTEM_LINKS *font_link;
3730     CHILD_FONT *font_link_entry, *new_child;
3731     FontSubst *psub;
3732     WCHAR* font_name;
3733
3734     psub = get_font_subst(&font_subst_list, font->name, -1);
3735     font_name = psub ? psub->to.name : font->name;
3736     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3737     {
3738         if(!strcmpiW(font_link->font_name, font_name))
3739         {
3740             TRACE("found entry in system list\n");
3741             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3742             {
3743                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
3744                 new_child->face = font_link_entry->face;
3745                 new_child->font = NULL;
3746                 list_add_tail(&font->child_fonts, &new_child->entry);
3747                 TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
3748             }
3749             ret = TRUE;
3750             break;
3751         }
3752     }
3753     /*
3754      * if not SYMBOL or OEM then we also get all the fonts for Microsoft
3755      * Sans Serif.  This is how asian windows get default fallbacks for fonts
3756      */
3757     if (use_default_fallback && font->charset != SYMBOL_CHARSET &&
3758         font->charset != OEM_CHARSET &&
3759         strcmpiW(font_name,szDefaultFallbackLink) != 0)
3760         LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3761         {
3762             if(!strcmpiW(font_link->font_name,szDefaultFallbackLink))
3763             {
3764                 TRACE("found entry in default fallback list\n");
3765                 LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3766                 {
3767                     new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
3768                     new_child->face = font_link_entry->face;
3769                     new_child->font = NULL;
3770                     list_add_tail(&font->child_fonts, &new_child->entry);
3771                     TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
3772                 }
3773                 ret = TRUE;
3774                 break;
3775             }
3776         }
3777
3778     return ret;
3779 }
3780
3781 static BOOL select_charmap(FT_Face ft_face, FT_Encoding encoding)
3782 {
3783     FT_Error ft_err = FT_Err_Invalid_CharMap_Handle;
3784
3785     if (pFT_Set_Charmap)
3786     {
3787         FT_Int i;
3788         FT_CharMap cmap0, cmap1, cmap2, cmap3, cmap_def;
3789
3790         cmap0 = cmap1 = cmap2 = cmap3 = cmap_def = NULL;
3791
3792         for (i = 0; i < ft_face->num_charmaps; i++)
3793         {
3794             if (ft_face->charmaps[i]->encoding == encoding)
3795             {
3796                 TRACE("found cmap with platform_id %u, encoding_id %u\n",
3797                        ft_face->charmaps[i]->platform_id, ft_face->charmaps[i]->encoding_id);
3798
3799                 switch (ft_face->charmaps[i]->platform_id)
3800                 {
3801                     default:
3802                         cmap_def = ft_face->charmaps[i];
3803                         break;
3804                     case 0: /* Apple Unicode */
3805                         cmap0 = ft_face->charmaps[i];
3806                         break;
3807                     case 1: /* Macintosh */
3808                         cmap1 = ft_face->charmaps[i];
3809                         break;
3810                     case 2: /* ISO */
3811                         cmap2 = ft_face->charmaps[i];
3812                         break;
3813                     case 3: /* Microsoft */
3814                         cmap3 = ft_face->charmaps[i];
3815                         break;
3816                 }
3817             }
3818
3819             if (cmap3) /* prefer Microsoft cmap table */
3820                 ft_err = pFT_Set_Charmap(ft_face, cmap3);
3821             else if (cmap1)
3822                 ft_err = pFT_Set_Charmap(ft_face, cmap1);
3823             else if (cmap2)
3824                 ft_err = pFT_Set_Charmap(ft_face, cmap2);
3825             else if (cmap0)
3826                 ft_err = pFT_Set_Charmap(ft_face, cmap0);
3827             else if (cmap_def)
3828                 ft_err = pFT_Set_Charmap(ft_face, cmap_def);
3829         }
3830         return ft_err == FT_Err_Ok;
3831     }
3832
3833     return pFT_Select_Charmap(ft_face, encoding) == FT_Err_Ok;
3834 }
3835
3836
3837 /*************************************************************
3838  * freetype_CreateDC
3839  */
3840 static BOOL freetype_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device,
3841                                LPCWSTR output, const DEVMODEW *devmode )
3842 {
3843     struct freetype_physdev *physdev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physdev) );
3844
3845     if (!physdev) return FALSE;
3846     push_dc_driver( dev, &physdev->dev, &freetype_funcs );
3847     return TRUE;
3848 }
3849
3850
3851 /*************************************************************
3852  * freetype_DeleteDC
3853  */
3854 static BOOL freetype_DeleteDC( PHYSDEV dev )
3855 {
3856     struct freetype_physdev *physdev = get_freetype_dev( dev );
3857     HeapFree( GetProcessHeap(), 0, physdev );
3858     return TRUE;
3859 }
3860
3861
3862 /*************************************************************
3863  * freetype_SelectFont
3864  */
3865 static HFONT freetype_SelectFont( PHYSDEV dev, HFONT hfont )
3866 {
3867     struct freetype_physdev *physdev = get_freetype_dev( dev );
3868     GdiFont *ret;
3869     Face *face, *best, *best_bitmap;
3870     Family *family, *last_resort_family;
3871     struct list *family_elem_ptr, *face_elem_ptr;
3872     INT height, width = 0;
3873     unsigned int score = 0, new_score;
3874     signed int diff = 0, newdiff;
3875     BOOL bd, it, can_use_bitmap;
3876     LOGFONTW lf;
3877     CHARSETINFO csi;
3878     HFONTLIST *hflist;
3879     FMAT2 dcmat;
3880     FontSubst *psub = NULL;
3881     DC *dc = get_dc_ptr( dev->hdc );
3882
3883     if (!hfont)  /* notification that the font has been changed by another driver */
3884     {
3885         dc->gdiFont = NULL;
3886         physdev->font = NULL;
3887         release_dc_ptr( dc );
3888         return 0;
3889     }
3890
3891     GetObjectW( hfont, sizeof(lf), &lf );
3892     lf.lfWidth = abs(lf.lfWidth);
3893
3894     can_use_bitmap = GetDeviceCaps(dev->hdc, TEXTCAPS) & TC_RA_ABLE;
3895
3896     TRACE("%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n",
3897           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
3898           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
3899           lf.lfEscapement);
3900
3901     if(dc->GraphicsMode == GM_ADVANCED)
3902         memcpy(&dcmat, &dc->xformWorld2Vport, sizeof(FMAT2));
3903     else
3904     {
3905         /* Windows 3.1 compatibility mode GM_COMPATIBLE has only limited
3906            font scaling abilities. */
3907         dcmat.eM11 = dcmat.eM22 = dc->vport2WorldValid ? fabs(dc->xformWorld2Vport.eM22) : 1.0;
3908         dcmat.eM21 = dcmat.eM12 = 0;
3909     }
3910
3911     /* Try to avoid not necessary glyph transformations */
3912     if (dcmat.eM21 == 0.0 && dcmat.eM12 == 0.0 && dcmat.eM11 == dcmat.eM22)
3913     {
3914         lf.lfHeight *= fabs(dcmat.eM11);
3915         lf.lfWidth *= fabs(dcmat.eM11);
3916         dcmat.eM11 = dcmat.eM22 = 1.0;
3917     }
3918
3919     TRACE("DC transform %f %f %f %f\n", dcmat.eM11, dcmat.eM12,
3920                                         dcmat.eM21, dcmat.eM22);
3921
3922     GDI_CheckNotLock();
3923     EnterCriticalSection( &freetype_cs );
3924
3925     /* check the cache first */
3926     if((ret = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap)) != NULL) {
3927         TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
3928         goto done;
3929     }
3930
3931     if(list_empty(&font_list)) /* No fonts installed */
3932     {
3933         TRACE("No fonts installed\n");
3934         goto done;
3935     }
3936
3937     TRACE("not in cache\n");
3938     ret = alloc_font();
3939
3940     ret->font_desc.matrix = dcmat;
3941     ret->font_desc.lf = lf;
3942     ret->font_desc.can_use_bitmap = can_use_bitmap;
3943     calc_hash(&ret->font_desc);
3944     hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3945     hflist->hfont = hfont;
3946     list_add_head(&ret->hfontlist, &hflist->entry);
3947
3948     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
3949        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
3950        original value lfCharSet.  Note this is a special case for
3951        Symbol and doesn't happen at least for "Wingdings*" */
3952
3953     if(!strcmpiW(lf.lfFaceName, SymbolW))
3954         lf.lfCharSet = SYMBOL_CHARSET;
3955
3956     if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
3957         switch(lf.lfCharSet) {
3958         case DEFAULT_CHARSET:
3959             csi.fs.fsCsb[0] = 0;
3960             break;
3961         default:
3962             FIXME("Untranslated charset %d\n", lf.lfCharSet);
3963             csi.fs.fsCsb[0] = 0;
3964             break;
3965         }
3966     }
3967
3968     family = NULL;
3969     if(lf.lfFaceName[0] != '\0') {
3970         SYSTEM_LINKS *font_link;
3971         CHILD_FONT *font_link_entry;
3972         LPWSTR FaceName = lf.lfFaceName;
3973
3974         /*
3975          * Check for a leading '@' this signals that the font is being
3976          * requested in tategaki mode (vertical writing substitution) but
3977          * does not affect the fontface that is to be selected.
3978          */
3979         if (lf.lfFaceName[0]=='@')
3980             FaceName = &lf.lfFaceName[1];
3981
3982         psub = get_font_subst(&font_subst_list, FaceName, lf.lfCharSet);
3983
3984         if(psub) {
3985             TRACE("substituting %s,%d -> %s,%d\n", debugstr_w(FaceName), lf.lfCharSet,
3986                   debugstr_w(psub->to.name), (psub->to.charset != -1) ? psub->to.charset : lf.lfCharSet);
3987             if (psub->to.charset != -1)
3988                 lf.lfCharSet = psub->to.charset;
3989         }
3990
3991         /* We want a match on name and charset or just name if
3992            charset was DEFAULT_CHARSET.  If the latter then
3993            we fixup the returned charset later in get_nearest_charset
3994            where we'll either use the charset of the current ansi codepage
3995            or if that's unavailable the first charset that the font supports.
3996         */
3997         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3998             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3999             if (!strcmpiW(family->FamilyName, FaceName) ||
4000                 (psub && !strcmpiW(family->FamilyName, psub->to.name)))
4001             {
4002                 LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
4003                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
4004                     if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
4005                         if(face->scalable || can_use_bitmap)
4006                             goto found;
4007                 }
4008             }
4009         }
4010
4011         /* Search by full face name. */
4012         LIST_FOR_EACH(family_elem_ptr, &font_list) {
4013             family = LIST_ENTRY(family_elem_ptr, Family, entry);
4014             LIST_FOR_EACH(face_elem_ptr, &family->faces) {
4015                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
4016                 if(face->FullName && !strcmpiW(face->FullName, FaceName) &&
4017                    ((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0]))
4018                 {
4019                     if(face->scalable || can_use_bitmap)
4020                         goto found_face;
4021                 }
4022             }
4023         }
4024
4025         /*
4026          * Try check the SystemLink list first for a replacement font.
4027          * We may find good replacements there.
4028          */
4029         LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
4030         {
4031             if(!strcmpiW(font_link->font_name, FaceName) ||
4032                (psub && !strcmpiW(font_link->font_name,psub->to.name)))
4033             {
4034                 TRACE("found entry in system list\n");
4035                 LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
4036                 {
4037                     face = font_link_entry->face;
4038                     family = face->family;
4039                     if(csi.fs.fsCsb[0] &
4040                         (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]) || !csi.fs.fsCsb[0])
4041                     {
4042                         if(face->scalable || can_use_bitmap)
4043                             goto found;
4044                     }
4045                 }
4046             }
4047         }
4048     }
4049
4050     psub = NULL; /* substitution is no more relevant */
4051
4052     /* If requested charset was DEFAULT_CHARSET then try using charset
4053        corresponding to the current ansi codepage */
4054     if (!csi.fs.fsCsb[0])
4055     {
4056         INT acp = GetACP();
4057         if(!TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE)) {
4058             FIXME("TCI failed on codepage %d\n", acp);
4059             csi.fs.fsCsb[0] = 0;
4060         } else
4061             lf.lfCharSet = csi.ciCharset;
4062     }
4063
4064     /* Face families are in the top 4 bits of lfPitchAndFamily,
4065        so mask with 0xF0 before testing */
4066
4067     if((lf.lfPitchAndFamily & FIXED_PITCH) ||
4068        (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
4069         strcpyW(lf.lfFaceName, defFixed);
4070     else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
4071         strcpyW(lf.lfFaceName, defSerif);
4072     else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
4073         strcpyW(lf.lfFaceName, defSans);
4074     else
4075         strcpyW(lf.lfFaceName, defSans);
4076     LIST_FOR_EACH(family_elem_ptr, &font_list) {
4077         family = LIST_ENTRY(family_elem_ptr, Family, entry);
4078         if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
4079             LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
4080                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
4081                 if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
4082                     if(face->scalable || can_use_bitmap)
4083                         goto found;
4084             }
4085         }
4086     }
4087
4088     last_resort_family = NULL;
4089     LIST_FOR_EACH(family_elem_ptr, &font_list) {
4090         family = LIST_ENTRY(family_elem_ptr, Family, entry);
4091         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
4092             face = LIST_ENTRY(face_elem_ptr, Face, entry);
4093             if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) {
4094                 if(face->scalable)
4095                     goto found;
4096                 if(can_use_bitmap && !last_resort_family)
4097                     last_resort_family = family;
4098             }            
4099         }
4100     }
4101
4102     if(last_resort_family) {
4103         family = last_resort_family;
4104         csi.fs.fsCsb[0] = 0;
4105         goto found;
4106     }
4107
4108     LIST_FOR_EACH(family_elem_ptr, &font_list) {
4109         family = LIST_ENTRY(family_elem_ptr, Family, entry);
4110         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
4111             face = LIST_ENTRY(face_elem_ptr, Face, entry);
4112             if(face->scalable) {
4113                 csi.fs.fsCsb[0] = 0;
4114                 WARN("just using first face for now\n");
4115                 goto found;
4116             }
4117             if(can_use_bitmap && !last_resort_family)
4118                 last_resort_family = family;
4119         }
4120     }
4121     if(!last_resort_family) {
4122         FIXME("can't find a single appropriate font - bailing\n");
4123         free_font(ret);
4124         ret = NULL;
4125         goto done;
4126     }
4127
4128     WARN("could only find a bitmap font - this will probably look awful!\n");
4129     family = last_resort_family;
4130     csi.fs.fsCsb[0] = 0;
4131
4132 found:
4133     it = lf.lfItalic ? 1 : 0;
4134     bd = lf.lfWeight > 550 ? 1 : 0;
4135
4136     height = lf.lfHeight;
4137
4138     face = best = best_bitmap = NULL;
4139     LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
4140     {
4141         if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
4142         {
4143             BOOL italic, bold;
4144
4145             italic = (face->ntmFlags & NTM_ITALIC) ? 1 : 0;
4146             bold = (face->ntmFlags & NTM_BOLD) ? 1 : 0;
4147             new_score = (italic ^ it) + (bold ^ bd);
4148             if(!best || new_score <= score)
4149             {
4150                 TRACE("(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n",
4151                       italic, bold, it, bd);
4152                 score = new_score;
4153                 best = face;
4154                 if(best->scalable  && score == 0) break;
4155                 if(!best->scalable)
4156                 {
4157                     if(height > 0)
4158                         newdiff = height - (signed int)(best->size.height);
4159                     else
4160                         newdiff = -height - ((signed int)(best->size.height) - best->size.internal_leading);
4161                     if(!best_bitmap || new_score < score ||
4162                        (diff > 0 && newdiff < diff && newdiff >= 0) || (diff < 0 && newdiff > diff))
4163                     {
4164                         TRACE("%d is better for %d diff was %d\n", best->size.height, height, diff);
4165                         diff = newdiff;
4166                         best_bitmap = best;
4167                         if(score == 0 && diff == 0) break;
4168                     }
4169                 }
4170             }
4171         }
4172     }
4173     if(best)
4174         face = best->scalable ? best : best_bitmap;
4175     ret->fake_italic = (it && !(face->ntmFlags & NTM_ITALIC));
4176     ret->fake_bold = (bd && !(face->ntmFlags & NTM_BOLD));
4177
4178 found_face:
4179     height = lf.lfHeight;
4180
4181     ret->fs = face->fs;
4182
4183     if(csi.fs.fsCsb[0]) {
4184         ret->charset = lf.lfCharSet;
4185         ret->codepage = csi.ciACP;
4186     }
4187     else
4188         ret->charset = get_nearest_charset(face, &ret->codepage);
4189
4190     TRACE("Chosen: %s %s (%s/%p:%ld)\n", debugstr_w(family->FamilyName),
4191           debugstr_w(face->StyleName), face->file, face->font_data_ptr, face->face_index);
4192
4193     ret->aveWidth = height ? lf.lfWidth : 0;
4194
4195     if(!face->scalable) {
4196         /* Windows uses integer scaling factors for bitmap fonts */
4197         INT scale, scaled_height;
4198         GdiFont *cachedfont;
4199
4200         /* FIXME: rotation of bitmap fonts is ignored */
4201         height = abs(GDI_ROUND( (double)height * ret->font_desc.matrix.eM22 ));
4202         if (ret->aveWidth)
4203             ret->aveWidth = (double)ret->aveWidth * ret->font_desc.matrix.eM11;
4204         ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
4205         dcmat.eM11 = dcmat.eM22 = 1.0;
4206         /* As we changed the matrix, we need to search the cache for the font again,
4207          * otherwise we might explode the cache. */
4208         if((cachedfont = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap)) != NULL) {
4209             TRACE("Found cached font after non-scalable matrix rescale!\n");
4210             free_font( ret );
4211             ret = cachedfont;
4212             goto done;
4213         }
4214         calc_hash(&ret->font_desc);
4215
4216         if (height != 0) height = diff;
4217         height += face->size.height;
4218
4219         scale = (height + face->size.height - 1) / face->size.height;
4220         scaled_height = scale * face->size.height;
4221         /* Only jump to the next height if the difference <= 25% original height */
4222         if (scale > 2 && scaled_height - height > face->size.height / 4) scale--;
4223         /* The jump between unscaled and doubled is delayed by 1 */
4224         else if (scale == 2 && scaled_height - height > (face->size.height / 4 - 1)) scale--;
4225         ret->scale_y = scale;
4226
4227         width = face->size.x_ppem >> 6;
4228         height = face->size.y_ppem >> 6;
4229     }
4230     else
4231         ret->scale_y = 1.0;
4232     TRACE("font scale y: %f\n", ret->scale_y);
4233
4234     ret->ft_face = OpenFontFace(ret, face, width, height);
4235
4236     if (!ret->ft_face)
4237     {
4238         free_font( ret );
4239         ret = NULL;
4240         goto done;
4241     }
4242
4243     ret->ntmFlags = face->ntmFlags;
4244
4245     if (ret->charset == SYMBOL_CHARSET && 
4246         select_charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) {
4247         /* No ops */
4248     }
4249     else if (select_charmap(ret->ft_face, FT_ENCODING_UNICODE)) {
4250         /* No ops */
4251     }
4252     else {
4253         select_charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN);
4254     }
4255
4256     ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0;
4257     ret->name = psub ? strdupW(psub->from.name) : strdupW(family->FamilyName);
4258     ret->underline = lf.lfUnderline ? 0xff : 0;
4259     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
4260     create_child_font_list(ret);
4261
4262     if (lf.lfFaceName[0]=='@') /* We need to try to load the GSUB table */
4263     {
4264         int length = get_font_data(ret, GSUB_TAG , 0, NULL, 0);
4265         if (length != GDI_ERROR)
4266         {
4267             ret->GSUB_Table = HeapAlloc(GetProcessHeap(),0,length);
4268             get_font_data(ret, GSUB_TAG , 0, ret->GSUB_Table, length);
4269             TRACE("Loaded GSUB table of %i bytes\n",length);
4270         }
4271     }
4272
4273     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
4274
4275     add_to_cache(ret);
4276 done:
4277     if (ret)
4278     {
4279         dc->gdiFont = ret;
4280         physdev->font = ret;
4281     }
4282     LeaveCriticalSection( &freetype_cs );
4283     release_dc_ptr( dc );
4284     return ret ? hfont : 0;
4285 }
4286
4287 static void dump_gdi_font_list(void)
4288 {
4289     GdiFont *gdiFont;
4290     struct list *elem_ptr;
4291
4292     TRACE("---------- gdiFont Cache ----------\n");
4293     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
4294         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
4295         TRACE("gdiFont=%p %s %d\n",
4296               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
4297     }
4298
4299     TRACE("---------- Unused gdiFont Cache ----------\n");
4300     LIST_FOR_EACH(elem_ptr, &unused_gdi_font_list) {
4301         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
4302         TRACE("gdiFont=%p %s %d\n",
4303               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
4304     }
4305
4306     TRACE("---------- Child gdiFont Cache ----------\n");
4307     LIST_FOR_EACH(elem_ptr, &child_font_list) {
4308         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
4309         TRACE("gdiFont=%p %s %d\n",
4310               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
4311     }
4312 }
4313
4314 /*************************************************************
4315  * WineEngDestroyFontInstance
4316  *
4317  * free the gdiFont associated with this handle
4318  *
4319  */
4320 BOOL WineEngDestroyFontInstance(HFONT handle)
4321 {
4322     GdiFont *gdiFont;
4323     HFONTLIST *hflist;
4324     BOOL ret = FALSE;
4325     struct list *font_elem_ptr, *hfontlist_elem_ptr;
4326     int i = 0;
4327
4328     GDI_CheckNotLock();
4329     EnterCriticalSection( &freetype_cs );
4330
4331     LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry)
4332     {
4333         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
4334         while(hfontlist_elem_ptr) {
4335             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
4336             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
4337             if(hflist->hfont == handle) {
4338                 TRACE("removing child font %p from child list\n", gdiFont);
4339                 list_remove(&gdiFont->entry);
4340                 LeaveCriticalSection( &freetype_cs );
4341                 return TRUE;
4342             }
4343         }
4344     }
4345
4346     TRACE("destroying hfont=%p\n", handle);
4347     if(TRACE_ON(font))
4348         dump_gdi_font_list();
4349
4350     font_elem_ptr = list_head(&gdi_font_list);
4351     while(font_elem_ptr) {
4352         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
4353         font_elem_ptr = list_next(&gdi_font_list, font_elem_ptr);
4354
4355         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
4356         while(hfontlist_elem_ptr) {
4357             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
4358             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
4359             if(hflist->hfont == handle) {
4360                 list_remove(&hflist->entry);
4361                 HeapFree(GetProcessHeap(), 0, hflist);
4362                 ret = TRUE;
4363             }
4364         }
4365         if(list_empty(&gdiFont->hfontlist)) {
4366             TRACE("Moving to Unused list\n");
4367             list_remove(&gdiFont->entry);
4368             list_add_head(&unused_gdi_font_list, &gdiFont->entry);
4369         }
4370     }
4371
4372
4373     font_elem_ptr = list_head(&unused_gdi_font_list);
4374     while(font_elem_ptr && i++ < UNUSED_CACHE_SIZE)
4375         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
4376     while(font_elem_ptr) {
4377         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
4378         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
4379         TRACE("freeing %p\n", gdiFont);
4380         list_remove(&gdiFont->entry);
4381         free_font(gdiFont);
4382     }
4383     LeaveCriticalSection( &freetype_cs );
4384     return ret;
4385 }
4386
4387 /***************************************************
4388  * create_enum_charset_list
4389  *
4390  * This function creates charset enumeration list because in DEFAULT_CHARSET
4391  * case, the ANSI codepage's charset takes precedence over other charsets.
4392  * This function works as a filter other than DEFAULT_CHARSET case.
4393  */
4394 static DWORD create_enum_charset_list(DWORD charset, struct enum_charset_list *list)
4395 {
4396     CHARSETINFO csi;
4397     DWORD n = 0;
4398
4399     if (TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET) &&
4400         csi.fs.fsCsb[0] != 0) {
4401         list->element[n].mask    = csi.fs.fsCsb[0];
4402         list->element[n].charset = csi.ciCharset;
4403         list->element[n].name    = ElfScriptsW[ffs(csi.fs.fsCsb[0]) - 1];
4404         n++;
4405     }
4406     else { /* charset is DEFAULT_CHARSET or invalid. */
4407         INT acp, i;
4408
4409         /* Set the current codepage's charset as the first element. */
4410         acp = GetACP();
4411         if (TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE) &&
4412             csi.fs.fsCsb[0] != 0) {
4413             list->element[n].mask    = csi.fs.fsCsb[0];
4414             list->element[n].charset = csi.ciCharset;
4415             list->element[n].name    = ElfScriptsW[ffs(csi.fs.fsCsb[0]) - 1];
4416             n++;
4417         }
4418
4419         /* Fill out left elements. */
4420         for (i = 0; i < 32; i++) {
4421             FONTSIGNATURE fs;
4422             fs.fsCsb[0] = 1L << i;
4423             fs.fsCsb[1] = 0;
4424             if (n > 0 && fs.fsCsb[0] == list->element[0].mask)
4425                 continue; /* skip, already added. */
4426             if (!TranslateCharsetInfo(fs.fsCsb, &csi, TCI_SRCFONTSIG))
4427                 continue; /* skip, this is an invalid fsCsb bit. */
4428
4429             list->element[n].mask    = fs.fsCsb[0];
4430             list->element[n].charset = csi.ciCharset;
4431             list->element[n].name    = ElfScriptsW[i];
4432             n++;
4433         }
4434     }
4435     list->total = n;
4436
4437     return n;
4438 }
4439
4440 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
4441                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
4442 {
4443     GdiFont *font;
4444     LONG width, height;
4445
4446     if (face->cached_enum_data)
4447     {
4448         TRACE("Cached\n");
4449         *pelf = face->cached_enum_data->elf;
4450         *pntm = face->cached_enum_data->ntm;
4451         *ptype = face->cached_enum_data->type;
4452         return;
4453     }
4454
4455     font = alloc_font();
4456
4457     if(face->scalable) {
4458         height = -2048; /* 2048 is the most common em size */
4459         width = 0;
4460     } else {
4461         height = face->size.y_ppem >> 6;
4462         width = face->size.x_ppem >> 6;
4463     }
4464     font->scale_y = 1.0;
4465     
4466     if (!(font->ft_face = OpenFontFace(font, face, width, height)))
4467     {
4468         free_font(font);
4469         return;
4470     }
4471
4472     font->name = strdupW(face->family->FamilyName);
4473     font->ntmFlags = face->ntmFlags;
4474
4475     if (get_outline_text_metrics(font))
4476     {
4477         memcpy(&pntm->ntmTm, &font->potm->otmTextMetrics, sizeof(TEXTMETRICW));
4478
4479         pntm->ntmTm.ntmSizeEM = font->potm->otmEMSquare;
4480
4481         lstrcpynW(pelf->elfLogFont.lfFaceName,
4482                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFamilyName),
4483                  LF_FACESIZE);
4484         lstrcpynW(pelf->elfFullName,
4485                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFullName),
4486                  LF_FULLFACESIZE);
4487         lstrcpynW(pelf->elfStyle,
4488                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpStyleName),
4489                  LF_FACESIZE);
4490     }
4491     else
4492     {
4493         get_text_metrics(font, (TEXTMETRICW *)&pntm->ntmTm);
4494
4495         pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
4496
4497         lstrcpynW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
4498         if (face->FullName)
4499             lstrcpynW(pelf->elfFullName, face->FullName, LF_FULLFACESIZE);
4500         else
4501             lstrcpynW(pelf->elfFullName, face->family->FamilyName, LF_FULLFACESIZE);
4502         lstrcpynW(pelf->elfStyle, face->StyleName, LF_FACESIZE);
4503     }
4504
4505     pntm->ntmTm.ntmFlags = face->ntmFlags;
4506     pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
4507     pntm->ntmTm.ntmAvgWidth = pntm->ntmTm.tmAveCharWidth;
4508     pntm->ntmFontSig = face->fs;
4509
4510     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
4511
4512     pelf->elfLogFont.lfEscapement = 0;
4513     pelf->elfLogFont.lfOrientation = 0;
4514     pelf->elfLogFont.lfHeight = pntm->ntmTm.tmHeight;
4515     pelf->elfLogFont.lfWidth = pntm->ntmTm.tmAveCharWidth;
4516     pelf->elfLogFont.lfWeight = pntm->ntmTm.tmWeight;
4517     pelf->elfLogFont.lfItalic = pntm->ntmTm.tmItalic;
4518     pelf->elfLogFont.lfUnderline = pntm->ntmTm.tmUnderlined;
4519     pelf->elfLogFont.lfStrikeOut = pntm->ntmTm.tmStruckOut;
4520     pelf->elfLogFont.lfCharSet = pntm->ntmTm.tmCharSet;
4521     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
4522     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
4523     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
4524     pelf->elfLogFont.lfPitchAndFamily = (pntm->ntmTm.tmPitchAndFamily & 0xf1) + 1;
4525
4526     *ptype = 0;
4527     if (pntm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE)
4528         *ptype |= TRUETYPE_FONTTYPE;
4529     if (pntm->ntmTm.tmPitchAndFamily & TMPF_DEVICE)
4530         *ptype |= DEVICE_FONTTYPE;
4531     if(!(pntm->ntmTm.tmPitchAndFamily & TMPF_VECTOR))
4532         *ptype |= RASTER_FONTTYPE;
4533
4534     face->cached_enum_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*face->cached_enum_data));
4535     if (face->cached_enum_data)
4536     {
4537         face->cached_enum_data->elf = *pelf;
4538         face->cached_enum_data->ntm = *pntm;
4539         face->cached_enum_data->type = *ptype;
4540     }
4541
4542     free_font(font);
4543 }
4544
4545 static BOOL family_matches(Family *family, const LOGFONTW *lf)
4546 {
4547     struct list *face_elem_ptr;
4548
4549     if (!strcmpiW(lf->lfFaceName, family->FamilyName)) return TRUE;
4550
4551     LIST_FOR_EACH(face_elem_ptr, &family->faces)
4552     {
4553         static const WCHAR spaceW[] = { ' ',0 };
4554         WCHAR full_family_name[LF_FULLFACESIZE];
4555         Face *face = LIST_ENTRY(face_elem_ptr, Face, entry);
4556
4557         if (strlenW(family->FamilyName) + strlenW(face->StyleName) + 2 > LF_FULLFACESIZE)
4558         {
4559             FIXME("Length of %s + %s + 2 is longer than LF_FULLFACESIZE\n",
4560                   debugstr_w(family->FamilyName), debugstr_w(face->StyleName));
4561             continue;
4562         }
4563
4564         strcpyW(full_family_name, family->FamilyName);
4565         strcatW(full_family_name, spaceW);
4566         strcatW(full_family_name, face->StyleName);
4567         if (!strcmpiW(lf->lfFaceName, full_family_name)) return TRUE;
4568     }
4569
4570     return FALSE;
4571 }
4572
4573 static BOOL face_matches(Face *face, const LOGFONTW *lf)
4574 {
4575     static const WCHAR spaceW[] = { ' ',0 };
4576     WCHAR full_family_name[LF_FULLFACESIZE];
4577
4578     if (!strcmpiW(lf->lfFaceName, face->family->FamilyName)) return TRUE;
4579
4580     if (strlenW(face->family->FamilyName) + strlenW(face->StyleName) + 2 > LF_FULLFACESIZE)
4581     {
4582         FIXME("Length of %s + %s + 2 is longer than LF_FULLFACESIZE\n",
4583               debugstr_w(face->family->FamilyName), debugstr_w(face->StyleName));
4584         return FALSE;
4585     }
4586
4587     strcpyW(full_family_name, face->family->FamilyName);
4588     strcatW(full_family_name, spaceW);
4589     strcatW(full_family_name, face->StyleName);
4590     return !strcmpiW(lf->lfFaceName, full_family_name);
4591 }
4592
4593 static BOOL enum_face_charsets(Face *face, struct enum_charset_list *list,
4594                                FONTENUMPROCW proc, LPARAM lparam)
4595 {
4596     ENUMLOGFONTEXW elf;
4597     NEWTEXTMETRICEXW ntm;
4598     DWORD type = 0;
4599     int i;
4600
4601     GetEnumStructs(face, &elf, &ntm, &type);
4602     for(i = 0; i < list->total; i++) {
4603         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
4604             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
4605             strcpyW(elf.elfScript, OEM_DOSW);
4606             i = 32; /* break out of loop */
4607         } else if(!(face->fs.fsCsb[0] & list->element[i].mask))
4608             continue;
4609         else {
4610             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = list->element[i].charset;
4611             if(list->element[i].name)
4612                 strcpyW(elf.elfScript, list->element[i].name);
4613             else
4614                 FIXME("Unknown elfscript for bit %d\n", ffs(list->element[i].mask) - 1);
4615         }
4616         TRACE("enuming face %s full %s style %s charset = %d type %d script %s it %d weight %d ntmflags %08x\n",
4617               debugstr_w(elf.elfLogFont.lfFaceName),
4618               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
4619               list->element[i].charset, type, debugstr_w(elf.elfScript),
4620               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
4621               ntm.ntmTm.ntmFlags);
4622         /* release section before callback (FIXME) */
4623         LeaveCriticalSection( &freetype_cs );
4624         if (!proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam)) return FALSE;
4625         EnterCriticalSection( &freetype_cs );
4626     }
4627     return TRUE;
4628 }
4629
4630 /*************************************************************
4631  * freetype_EnumFonts
4632  */
4633 static BOOL freetype_EnumFonts( PHYSDEV dev, LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam )
4634 {
4635     Family *family;
4636     Face *face;
4637     struct list *family_elem_ptr, *face_elem_ptr;
4638     LOGFONTW lf;
4639     struct enum_charset_list enum_charsets;
4640
4641     if (!plf)
4642     {
4643         lf.lfCharSet = DEFAULT_CHARSET;
4644         lf.lfPitchAndFamily = 0;
4645         lf.lfFaceName[0] = 0;
4646         plf = &lf;
4647     }
4648
4649     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
4650
4651     create_enum_charset_list(plf->lfCharSet, &enum_charsets);
4652
4653     GDI_CheckNotLock();
4654     EnterCriticalSection( &freetype_cs );
4655     if(plf->lfFaceName[0]) {
4656         FontSubst *psub;
4657         psub = get_font_subst(&font_subst_list, plf->lfFaceName, plf->lfCharSet);
4658
4659         if(psub) {
4660             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
4661                   debugstr_w(psub->to.name));
4662             lf = *plf;
4663             strcpyW(lf.lfFaceName, psub->to.name);
4664             plf = &lf;
4665         }
4666
4667         LIST_FOR_EACH(family_elem_ptr, &font_list) {
4668             family = LIST_ENTRY(family_elem_ptr, Family, entry);
4669             if(family_matches(family, plf)) {
4670                 LIST_FOR_EACH(face_elem_ptr, &family->faces) {
4671                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
4672                     if (!face_matches(face, plf)) continue;
4673                     if (!enum_face_charsets(face, &enum_charsets, proc, lparam)) return FALSE;
4674                 }
4675             }
4676         }
4677     } else {
4678         LIST_FOR_EACH(family_elem_ptr, &font_list) {
4679             family = LIST_ENTRY(family_elem_ptr, Family, entry);
4680             face_elem_ptr = list_head(&family->faces);
4681             face = LIST_ENTRY(face_elem_ptr, Face, entry);
4682             if (!enum_face_charsets(face, &enum_charsets, proc, lparam)) return FALSE;
4683         }
4684     }
4685     LeaveCriticalSection( &freetype_cs );
4686     return TRUE;
4687 }
4688
4689 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
4690 {
4691     pt->x.value = vec->x >> 6;
4692     pt->x.fract = (vec->x & 0x3f) << 10;
4693     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
4694     pt->y.value = vec->y >> 6;
4695     pt->y.fract = (vec->y & 0x3f) << 10;
4696     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
4697     return;
4698 }
4699
4700 /***************************************************
4701  * According to the MSDN documentation on WideCharToMultiByte,
4702  * certain codepages cannot set the default_used parameter.
4703  * This returns TRUE if the codepage can set that parameter, false else
4704  * so that calls to WideCharToMultiByte don't fail with ERROR_INVALID_PARAMETER
4705  */
4706 static BOOL codepage_sets_default_used(UINT codepage)
4707 {
4708    switch (codepage)
4709    {
4710        case CP_UTF7:
4711        case CP_UTF8:
4712        case CP_SYMBOL:
4713            return FALSE;
4714        default:
4715            return TRUE;
4716    }
4717 }
4718
4719 /*
4720  * GSUB Table handling functions
4721  */
4722
4723 static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph)
4724 {
4725     const GSUB_CoverageFormat1* cf1;
4726
4727     cf1 = table;
4728
4729     if (GET_BE_WORD(cf1->CoverageFormat) == 1)
4730     {
4731         int count = GET_BE_WORD(cf1->GlyphCount);
4732         int i;
4733         TRACE("Coverage Format 1, %i glyphs\n",count);
4734         for (i = 0; i < count; i++)
4735             if (glyph == GET_BE_WORD(cf1->GlyphArray[i]))
4736                 return i;
4737         return -1;
4738     }
4739     else if (GET_BE_WORD(cf1->CoverageFormat) == 2)
4740     {
4741         const GSUB_CoverageFormat2* cf2;
4742         int i;
4743         int count;
4744         cf2 = (const GSUB_CoverageFormat2*)cf1;
4745
4746         count = GET_BE_WORD(cf2->RangeCount);
4747         TRACE("Coverage Format 2, %i ranges\n",count);
4748         for (i = 0; i < count; i++)
4749         {
4750             if (glyph < GET_BE_WORD(cf2->RangeRecord[i].Start))
4751                 return -1;
4752             if ((glyph >= GET_BE_WORD(cf2->RangeRecord[i].Start)) &&
4753                 (glyph <= GET_BE_WORD(cf2->RangeRecord[i].End)))
4754             {
4755                 return (GET_BE_WORD(cf2->RangeRecord[i].StartCoverageIndex) +
4756                     glyph - GET_BE_WORD(cf2->RangeRecord[i].Start));
4757             }
4758         }
4759         return -1;
4760     }
4761     else
4762         ERR("Unknown CoverageFormat %i\n",GET_BE_WORD(cf1->CoverageFormat));
4763
4764     return -1;
4765 }
4766
4767 static const GSUB_Script* GSUB_get_script_table( const GSUB_Header* header, const char* tag)
4768 {
4769     const GSUB_ScriptList *script;
4770     const GSUB_Script *deflt = NULL;
4771     int i;
4772     script = (const GSUB_ScriptList*)((const BYTE*)header + GET_BE_WORD(header->ScriptList));
4773
4774     TRACE("%i scripts in this font\n",GET_BE_WORD(script->ScriptCount));
4775     for (i = 0; i < GET_BE_WORD(script->ScriptCount); i++)
4776     {
4777         const GSUB_Script *scr;
4778         int offset;
4779
4780         offset = GET_BE_WORD(script->ScriptRecord[i].Script);
4781         scr = (const GSUB_Script*)((const BYTE*)script + offset);
4782
4783         if (strncmp(script->ScriptRecord[i].ScriptTag, tag,4)==0)
4784             return scr;
4785         if (strncmp(script->ScriptRecord[i].ScriptTag, "dflt",4)==0)
4786             deflt = scr;
4787     }
4788     return deflt;
4789 }
4790
4791 static const GSUB_LangSys* GSUB_get_lang_table( const GSUB_Script* script, const char* tag)
4792 {
4793     int i;
4794     int offset;
4795     const GSUB_LangSys *Lang;
4796
4797     TRACE("Deflang %x, LangCount %i\n",GET_BE_WORD(script->DefaultLangSys), GET_BE_WORD(script->LangSysCount));
4798
4799     for (i = 0; i < GET_BE_WORD(script->LangSysCount) ; i++)
4800     {
4801         offset = GET_BE_WORD(script->LangSysRecord[i].LangSys);
4802         Lang = (const GSUB_LangSys*)((const BYTE*)script + offset);
4803
4804         if ( strncmp(script->LangSysRecord[i].LangSysTag,tag,4)==0)
4805             return Lang;
4806     }
4807     offset = GET_BE_WORD(script->DefaultLangSys);
4808     if (offset)
4809     {
4810         Lang = (const GSUB_LangSys*)((const BYTE*)script + offset);
4811         return Lang;
4812     }
4813     return NULL;
4814 }
4815
4816 static const GSUB_Feature * GSUB_get_feature(const GSUB_Header *header, const GSUB_LangSys *lang, const char* tag)
4817 {
4818     int i;
4819     const GSUB_FeatureList *feature;
4820     feature = (const GSUB_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList));
4821
4822     TRACE("%i features\n",GET_BE_WORD(lang->FeatureCount));
4823     for (i = 0; i < GET_BE_WORD(lang->FeatureCount); i++)
4824     {
4825         int index = GET_BE_WORD(lang->FeatureIndex[i]);
4826         if (strncmp(feature->FeatureRecord[index].FeatureTag,tag,4)==0)
4827         {
4828             const GSUB_Feature *feat;
4829             feat = (const GSUB_Feature*)((const BYTE*)feature + GET_BE_WORD(feature->FeatureRecord[index].Feature));
4830             return feat;
4831         }
4832     }
4833     return NULL;
4834 }
4835
4836 static FT_UInt GSUB_apply_feature(const GSUB_Header * header, const GSUB_Feature* feature, UINT glyph)
4837 {
4838     int i;
4839     int offset;
4840     const GSUB_LookupList *lookup;
4841     lookup = (const GSUB_LookupList*)((const BYTE*)header + GET_BE_WORD(header->LookupList));
4842
4843     TRACE("%i lookups\n", GET_BE_WORD(feature->LookupCount));
4844     for (i = 0; i < GET_BE_WORD(feature->LookupCount); i++)
4845     {
4846         const GSUB_LookupTable *look;
4847         offset = GET_BE_WORD(lookup->Lookup[GET_BE_WORD(feature->LookupListIndex[i])]);
4848         look = (const GSUB_LookupTable*)((const BYTE*)lookup + offset);
4849         TRACE("type %i, flag %x, subtables %i\n",GET_BE_WORD(look->LookupType),GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount));
4850         if (GET_BE_WORD(look->LookupType) != 1)
4851             FIXME("We only handle SubType 1\n");
4852         else
4853         {
4854             int j;
4855
4856             for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
4857             {
4858                 const GSUB_SingleSubstFormat1 *ssf1;
4859                 offset = GET_BE_WORD(look->SubTable[j]);
4860                 ssf1 = (const GSUB_SingleSubstFormat1*)((const BYTE*)look+offset);
4861                 if (GET_BE_WORD(ssf1->SubstFormat) == 1)
4862                 {
4863                     int offset = GET_BE_WORD(ssf1->Coverage);
4864                     TRACE("  subtype 1, delta %i\n", GET_BE_WORD(ssf1->DeltaGlyphID));
4865                     if (GSUB_is_glyph_covered((const BYTE*)ssf1+offset, glyph) != -1)
4866                     {
4867                         TRACE("  Glyph 0x%x ->",glyph);
4868                         glyph += GET_BE_WORD(ssf1->DeltaGlyphID);
4869                         TRACE(" 0x%x\n",glyph);
4870                     }
4871                 }
4872                 else
4873                 {
4874                     const GSUB_SingleSubstFormat2 *ssf2;
4875                     INT index;
4876                     INT offset;
4877
4878                     ssf2 = (const GSUB_SingleSubstFormat2 *)ssf1;
4879                     offset = GET_BE_WORD(ssf1->Coverage);
4880                     TRACE("  subtype 2,  glyph count %i\n", GET_BE_WORD(ssf2->GlyphCount));
4881                     index = GSUB_is_glyph_covered((const BYTE*)ssf2+offset, glyph);
4882                     TRACE("  Coverage index %i\n",index);
4883                     if (index != -1)
4884                     {
4885                         TRACE("    Glyph is 0x%x ->",glyph);
4886                         glyph = GET_BE_WORD(ssf2->Substitute[index]);
4887                         TRACE("0x%x\n",glyph);
4888                     }
4889                 }
4890             }
4891         }
4892     }
4893     return glyph;
4894 }
4895
4896 static const char* get_opentype_script(const GdiFont *font)
4897 {
4898     /*
4899      * I am not sure if this is the correct way to generate our script tag
4900      */
4901
4902     switch (font->charset)
4903     {
4904         case ANSI_CHARSET: return "latn";
4905         case BALTIC_CHARSET: return "latn"; /* ?? */
4906         case CHINESEBIG5_CHARSET: return "hani";
4907         case EASTEUROPE_CHARSET: return "latn"; /* ?? */
4908         case GB2312_CHARSET: return "hani";
4909         case GREEK_CHARSET: return "grek";
4910         case HANGUL_CHARSET: return "hang";
4911         case RUSSIAN_CHARSET: return "cyrl";
4912         case SHIFTJIS_CHARSET: return "kana";
4913         case TURKISH_CHARSET: return "latn"; /* ?? */
4914         case VIETNAMESE_CHARSET: return "latn";
4915         case JOHAB_CHARSET: return "latn"; /* ?? */
4916         case ARABIC_CHARSET: return "arab";
4917         case HEBREW_CHARSET: return "hebr";
4918         case THAI_CHARSET: return "thai";
4919         default: return "latn";
4920     }
4921 }
4922
4923 static FT_UInt get_GSUB_vert_glyph(const GdiFont *font, UINT glyph)
4924 {
4925     const GSUB_Header *header;
4926     const GSUB_Script *script;
4927     const GSUB_LangSys *language;
4928     const GSUB_Feature *feature;
4929
4930     if (!font->GSUB_Table)
4931         return glyph;
4932
4933     header = font->GSUB_Table;
4934
4935     script = GSUB_get_script_table(header, get_opentype_script(font));
4936     if (!script)
4937     {
4938         TRACE("Script not found\n");
4939         return glyph;
4940     }
4941     language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
4942     if (!language)
4943     {
4944         TRACE("Language not found\n");
4945         return glyph;
4946     }
4947     feature  =  GSUB_get_feature(header, language, "vrt2");
4948     if (!feature)
4949         feature  =  GSUB_get_feature(header, language, "vert");
4950     if (!feature)
4951     {
4952         TRACE("vrt2/vert feature not found\n");
4953         return glyph;
4954     }
4955     return GSUB_apply_feature(header, feature, glyph);
4956 }
4957
4958 static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph)
4959 {
4960     FT_UInt glyphId;
4961
4962     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
4963         WCHAR wc = (WCHAR)glyph;
4964         BOOL default_used;
4965         BOOL *default_used_pointer;
4966         FT_UInt ret;
4967         char buf;
4968         default_used_pointer = NULL;
4969         default_used = FALSE;
4970         if (codepage_sets_default_used(font->codepage))
4971             default_used_pointer = &default_used;
4972         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
4973             ret = 0;
4974         else
4975             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
4976         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
4977         return get_GSUB_vert_glyph(font,ret);
4978     }
4979
4980     if(font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
4981     {
4982         if (glyph < 0x100) glyph += 0xf000;
4983         /* there is a number of old pre-Unicode "broken" TTFs, which
4984            do have symbols at U+00XX instead of U+f0XX */
4985         if (!(glyphId = pFT_Get_Char_Index(font->ft_face, glyph)))
4986             glyphId = pFT_Get_Char_Index(font->ft_face, glyph-0xf000);
4987     }
4988     else glyphId = pFT_Get_Char_Index(font->ft_face, glyph);
4989
4990     return get_GSUB_vert_glyph(font,glyphId);
4991 }
4992
4993 /*************************************************************
4994  * freetype_GetGlyphIndices
4995  */
4996 static DWORD freetype_GetGlyphIndices( PHYSDEV dev, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags )
4997 {
4998     struct freetype_physdev *physdev = get_freetype_dev( dev );
4999     int i;
5000     WORD default_char;
5001     BOOL got_default = FALSE;
5002
5003     if (!physdev->font)
5004     {
5005         dev = GET_NEXT_PHYSDEV( dev, pGetGlyphIndices );
5006         return dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
5007     }
5008
5009     if (flags & GGI_MARK_NONEXISTING_GLYPHS)
5010     {
5011         default_char = 0xffff;  /* XP would use 0x1f for bitmap fonts */
5012         got_default = TRUE;
5013     }
5014
5015     GDI_CheckNotLock();
5016     EnterCriticalSection( &freetype_cs );
5017
5018     for(i = 0; i < count; i++)
5019     {
5020         pgi[i] = get_glyph_index(physdev->font, lpstr[i]);
5021         if  (pgi[i] == 0)
5022         {
5023             if (!got_default)
5024             {
5025                 if (FT_IS_SFNT(physdev->font->ft_face))
5026                 {
5027                     TT_OS2 *pOS2 = pFT_Get_Sfnt_Table(physdev->font->ft_face, ft_sfnt_os2);
5028                     default_char = (pOS2->usDefaultChar ? get_glyph_index(physdev->font, pOS2->usDefaultChar) : 0);
5029                 }
5030                 else
5031                 {
5032                     TEXTMETRICW textm;
5033                     get_text_metrics(physdev->font, &textm);
5034                     default_char = textm.tmDefaultChar;
5035                 }
5036                 got_default = TRUE;
5037             }
5038             pgi[i] = default_char;
5039         }
5040     }
5041     LeaveCriticalSection( &freetype_cs );
5042     return count;
5043 }
5044
5045 static inline BOOL is_identity_FMAT2(const FMAT2 *matrix)
5046 {
5047     static const FMAT2 identity = { 1.0, 0.0, 0.0, 1.0 };
5048     return !memcmp(matrix, &identity, sizeof(FMAT2));
5049 }
5050
5051 static inline BOOL is_identity_MAT2(const MAT2 *matrix)
5052 {
5053     static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
5054     return !memcmp(matrix, &identity, sizeof(MAT2));
5055 }
5056
5057 static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
5058                                LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
5059                                const MAT2* lpmat)
5060 {
5061     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
5062     FT_Face ft_face = incoming_font->ft_face;
5063     GdiFont *font = incoming_font;
5064     FT_UInt glyph_index;
5065     DWORD width, height, pitch, needed = 0;
5066     FT_Bitmap ft_bitmap;
5067     FT_Error err;
5068     INT left, right, top = 0, bottom = 0, adv, lsb, bbx;
5069     FT_Angle angle = 0;
5070     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
5071     double widthRatio = 1.0;
5072     FT_Matrix transMat = identityMat;
5073     FT_Matrix transMatUnrotated;
5074     BOOL needsTransform = FALSE;
5075     BOOL tategaki = (font->GSUB_Table != NULL);
5076     UINT original_index;
5077
5078     TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
5079           buflen, buf, lpmat);
5080
5081     TRACE("font transform %f %f %f %f\n",
5082           font->font_desc.matrix.eM11, font->font_desc.matrix.eM12,
5083           font->font_desc.matrix.eM21, font->font_desc.matrix.eM22);
5084
5085     if(format & GGO_GLYPH_INDEX) {
5086         glyph_index = get_GSUB_vert_glyph(incoming_font,glyph);
5087         original_index = glyph;
5088         format &= ~GGO_GLYPH_INDEX;
5089     } else {
5090         get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index);
5091         ft_face = font->ft_face;
5092         original_index = glyph_index;
5093     }
5094
5095     if(format & GGO_UNHINTED) {
5096         load_flags |= FT_LOAD_NO_HINTING;
5097         format &= ~GGO_UNHINTED;
5098     }
5099
5100     /* tategaki never appears to happen to lower glyph index */
5101     if (glyph_index < TATEGAKI_LOWER_BOUND )
5102         tategaki = FALSE;
5103
5104     if(original_index >= font->gmsize * GM_BLOCK_SIZE) {
5105         font->gmsize = (original_index / GM_BLOCK_SIZE + 1);
5106         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
5107                                font->gmsize * sizeof(GM*));
5108     } else {
5109         if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL &&
5110             FONT_GM(font,original_index)->init && is_identity_MAT2(lpmat))
5111         {
5112             *lpgm = FONT_GM(font,original_index)->gm;
5113             TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
5114                   wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
5115                   lpgm->gmCellIncX, lpgm->gmCellIncY);
5116             return 1; /* FIXME */
5117         }
5118     }
5119
5120     if (!font->gm[original_index / GM_BLOCK_SIZE])
5121         font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
5122
5123     /* Scaling factor */
5124     if (font->aveWidth)
5125     {
5126         TEXTMETRICW tm;
5127
5128         get_text_metrics(font, &tm);
5129
5130         widthRatio = (double)font->aveWidth;
5131         widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5132     }
5133     else
5134         widthRatio = font->scale_y;
5135
5136     /* Scaling transform */
5137     if (widthRatio != 1.0 || font->scale_y != 1.0)
5138     {
5139         FT_Matrix scaleMat;
5140         scaleMat.xx = FT_FixedFromFloat(widthRatio);
5141         scaleMat.xy = 0;
5142         scaleMat.yx = 0;
5143         scaleMat.yy = FT_FixedFromFloat(font->scale_y);
5144
5145         pFT_Matrix_Multiply(&scaleMat, &transMat);
5146         needsTransform = TRUE;
5147     }
5148
5149     /* Slant transform */
5150     if (font->fake_italic) {
5151         FT_Matrix slantMat;
5152         
5153         slantMat.xx = (1 << 16);
5154         slantMat.xy = ((1 << 16) >> 2);
5155         slantMat.yx = 0;
5156         slantMat.yy = (1 << 16);
5157         pFT_Matrix_Multiply(&slantMat, &transMat);
5158         needsTransform = TRUE;
5159     }
5160
5161     /* Rotation transform */
5162     transMatUnrotated = transMat;
5163     if(font->orientation && !tategaki) {
5164         FT_Matrix rotationMat;
5165         FT_Vector vecAngle;
5166         angle = FT_FixedFromFloat((double)font->orientation / 10.0);
5167         pFT_Vector_Unit(&vecAngle, angle);
5168         rotationMat.xx = vecAngle.x;
5169         rotationMat.xy = -vecAngle.y;
5170         rotationMat.yx = -rotationMat.xy;
5171         rotationMat.yy = rotationMat.xx;
5172         
5173         pFT_Matrix_Multiply(&rotationMat, &transMat);
5174         needsTransform = TRUE;
5175     }
5176
5177     /* World transform */
5178     if (!is_identity_FMAT2(&font->font_desc.matrix))
5179     {
5180         FT_Matrix worldMat;
5181         worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11);
5182         worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM12);
5183         worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM21);
5184         worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22);
5185         pFT_Matrix_Multiply(&worldMat, &transMat);
5186         pFT_Matrix_Multiply(&worldMat, &transMatUnrotated);
5187         needsTransform = TRUE;
5188     }
5189
5190     /* Extra transformation specified by caller */
5191     if (!is_identity_MAT2(lpmat))
5192     {
5193         FT_Matrix extraMat;
5194         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
5195         extraMat.xy = FT_FixedFromFIXED(lpmat->eM12);
5196         extraMat.yx = FT_FixedFromFIXED(lpmat->eM21);
5197         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
5198         pFT_Matrix_Multiply(&extraMat, &transMat);
5199         pFT_Matrix_Multiply(&extraMat, &transMatUnrotated);
5200         needsTransform = TRUE;
5201     }
5202
5203     if (needsTransform || (format == GGO_NATIVE || format == GGO_BEZIER ||
5204                            format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
5205                            format == GGO_GRAY8_BITMAP))
5206     {
5207         load_flags |= FT_LOAD_NO_BITMAP;
5208     }
5209
5210     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
5211
5212     if(err) {
5213         WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
5214         return GDI_ERROR;
5215     }
5216
5217     if(!needsTransform) {
5218         left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64;
5219         right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64;
5220         adv = (INT)(ft_face->glyph->metrics.horiAdvance + 63) >> 6;
5221
5222         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
5223         bottom = (ft_face->glyph->metrics.horiBearingY -
5224                   ft_face->glyph->metrics.height) & -64;
5225         lpgm->gmCellIncX = adv;
5226         lpgm->gmCellIncY = 0;
5227     } else {
5228         INT xc, yc;
5229         FT_Vector vec;
5230
5231         left = right = 0;
5232
5233         for(xc = 0; xc < 2; xc++) {
5234             for(yc = 0; yc < 2; yc++) {
5235                 vec.x = (ft_face->glyph->metrics.horiBearingX +
5236                   xc * ft_face->glyph->metrics.width);
5237                 vec.y = ft_face->glyph->metrics.horiBearingY -
5238                   yc * ft_face->glyph->metrics.height;
5239                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
5240                 pFT_Vector_Transform(&vec, &transMat);
5241                 if(xc == 0 && yc == 0) {
5242                     left = right = vec.x;
5243                     top = bottom = vec.y;
5244                 } else {
5245                     if(vec.x < left) left = vec.x;
5246                     else if(vec.x > right) right = vec.x;
5247                     if(vec.y < bottom) bottom = vec.y;
5248                     else if(vec.y > top) top = vec.y;
5249                 }
5250             }
5251         }
5252         left = left & -64;
5253         right = (right + 63) & -64;
5254         bottom = bottom & -64;
5255         top = (top + 63) & -64;
5256
5257         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
5258         vec.x = ft_face->glyph->metrics.horiAdvance;
5259         vec.y = 0;
5260         pFT_Vector_Transform(&vec, &transMat);
5261         lpgm->gmCellIncX = (vec.x+63) >> 6;
5262         lpgm->gmCellIncY = -((vec.y+63) >> 6);
5263
5264         vec.x = ft_face->glyph->metrics.horiAdvance;
5265         vec.y = 0;
5266         pFT_Vector_Transform(&vec, &transMatUnrotated);
5267         adv = (vec.x+63) >> 6;
5268     }
5269
5270     lsb = left >> 6;
5271     bbx = (right - left) >> 6;
5272     lpgm->gmBlackBoxX = (right - left) >> 6;
5273     lpgm->gmBlackBoxY = (top - bottom) >> 6;
5274     lpgm->gmptGlyphOrigin.x = left >> 6;
5275     lpgm->gmptGlyphOrigin.y = top >> 6;
5276
5277     TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
5278           wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
5279           lpgm->gmCellIncX, lpgm->gmCellIncY);
5280
5281     if ((format == GGO_METRICS || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
5282         is_identity_MAT2(lpmat)) /* don't cache custom transforms */
5283     {
5284         FONT_GM(font,original_index)->gm = *lpgm;
5285         FONT_GM(font,original_index)->adv = adv;
5286         FONT_GM(font,original_index)->lsb = lsb;
5287         FONT_GM(font,original_index)->bbx = bbx;
5288         FONT_GM(font,original_index)->init = TRUE;
5289     }
5290
5291     if(format == GGO_METRICS)
5292     {
5293         return 1; /* FIXME */
5294     }
5295
5296     if(ft_face->glyph->format != ft_glyph_format_outline &&
5297        (format == GGO_NATIVE || format == GGO_BEZIER ||
5298         format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
5299         format == GGO_GRAY8_BITMAP))
5300     {
5301         TRACE("loaded a bitmap\n");
5302         return GDI_ERROR;
5303     }
5304
5305     switch(format) {
5306     case GGO_BITMAP:
5307         width = lpgm->gmBlackBoxX;
5308         height = lpgm->gmBlackBoxY;
5309         pitch = ((width + 31) >> 5) << 2;
5310         needed = pitch * height;
5311
5312         if(!buf || !buflen) break;
5313
5314         switch(ft_face->glyph->format) {
5315         case ft_glyph_format_bitmap:
5316           {
5317             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
5318             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
5319             INT h = ft_face->glyph->bitmap.rows;
5320             while(h--) {
5321                 memcpy(dst, src, w);
5322                 src += ft_face->glyph->bitmap.pitch;
5323                 dst += pitch;
5324             }
5325             break;
5326           }
5327
5328         case ft_glyph_format_outline:
5329             ft_bitmap.width = width;
5330             ft_bitmap.rows = height;
5331             ft_bitmap.pitch = pitch;
5332             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
5333             ft_bitmap.buffer = buf;
5334
5335             if(needsTransform)
5336                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
5337
5338             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
5339
5340             /* Note: FreeType will only set 'black' bits for us. */
5341             memset(buf, 0, needed);
5342             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
5343             break;
5344
5345         default:
5346             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
5347             return GDI_ERROR;
5348         }
5349         break;
5350
5351     case GGO_GRAY2_BITMAP:
5352     case GGO_GRAY4_BITMAP:
5353     case GGO_GRAY8_BITMAP:
5354     case WINE_GGO_GRAY16_BITMAP:
5355       {
5356         unsigned int mult, row, col;
5357         BYTE *start, *ptr;
5358
5359         width = lpgm->gmBlackBoxX;
5360         height = lpgm->gmBlackBoxY;
5361         pitch = (width + 3) / 4 * 4;
5362         needed = pitch * height;
5363
5364         if(!buf || !buflen) break;
5365
5366         switch(ft_face->glyph->format) {
5367         case ft_glyph_format_bitmap:
5368           {
5369             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
5370             INT h = ft_face->glyph->bitmap.rows;
5371             INT x;
5372             memset( buf, 0, needed );
5373             while(h--) {
5374                 for(x = 0; x < pitch && x < ft_face->glyph->bitmap.width; x++)
5375                     if (src[x / 8] & (1 << ( (7 - (x % 8))))) dst[x] = 0xff;
5376                 src += ft_face->glyph->bitmap.pitch;
5377                 dst += pitch;
5378             }
5379             return needed;
5380           }
5381         case ft_glyph_format_outline:
5382           {
5383             ft_bitmap.width = width;
5384             ft_bitmap.rows = height;
5385             ft_bitmap.pitch = pitch;
5386             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
5387             ft_bitmap.buffer = buf;
5388
5389             if(needsTransform)
5390                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
5391
5392             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
5393
5394             memset(ft_bitmap.buffer, 0, buflen);
5395
5396             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
5397
5398             if(format == GGO_GRAY2_BITMAP)
5399                 mult = 4;
5400             else if(format == GGO_GRAY4_BITMAP)
5401                 mult = 16;
5402             else if(format == GGO_GRAY8_BITMAP)
5403                 mult = 64;
5404             else /* format == WINE_GGO_GRAY16_BITMAP */
5405                 return needed;
5406             break;
5407           }
5408         default:
5409             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
5410             return GDI_ERROR;
5411         }
5412
5413         start = buf;
5414         for(row = 0; row < height; row++) {
5415             ptr = start;
5416             for(col = 0; col < width; col++, ptr++) {
5417                 *ptr = (((int)*ptr) * mult + 128) / 256;
5418             }
5419             start += pitch;
5420         }
5421         break;
5422       }
5423
5424     case WINE_GGO_HRGB_BITMAP:
5425     case WINE_GGO_HBGR_BITMAP:
5426     case WINE_GGO_VRGB_BITMAP:
5427     case WINE_GGO_VBGR_BITMAP:
5428 #ifdef HAVE_FREETYPE_FTLCDFIL_H
5429       {
5430         switch (ft_face->glyph->format)
5431         {
5432         case FT_GLYPH_FORMAT_BITMAP:
5433           {
5434             BYTE *src, *dst;
5435             INT src_pitch, x;
5436
5437             width  = lpgm->gmBlackBoxX;
5438             height = lpgm->gmBlackBoxY;
5439             pitch  = width * 4;
5440             needed = pitch * height;
5441
5442             if (!buf || !buflen) break;
5443
5444             memset(buf, 0, buflen);
5445             dst = buf;
5446             src = ft_face->glyph->bitmap.buffer;
5447             src_pitch = ft_face->glyph->bitmap.pitch;
5448
5449             height = min( height, ft_face->glyph->bitmap.rows );
5450             while ( height-- )
5451             {
5452                 for (x = 0; x < width && x < ft_face->glyph->bitmap.width; x++)
5453                 {
5454                     if ( src[x / 8] & (1 << ( (7 - (x % 8)))) )
5455                         ((unsigned int *)dst)[x] = ~0u;
5456                 }
5457                 src += src_pitch;
5458                 dst += pitch;
5459             }
5460
5461             break;
5462           }
5463
5464         case FT_GLYPH_FORMAT_OUTLINE:
5465           {
5466             unsigned int *dst;
5467             BYTE *src;
5468             INT x, src_pitch, src_width, src_height, rgb_interval, hmul, vmul;
5469             INT x_shift, y_shift;
5470             BOOL rgb;
5471             FT_LcdFilter lcdfilter = FT_LCD_FILTER_DEFAULT;
5472             FT_Render_Mode render_mode =
5473                 (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_HBGR_BITMAP)?
5474                     FT_RENDER_MODE_LCD: FT_RENDER_MODE_LCD_V;
5475
5476             if ( lcdfilter == FT_LCD_FILTER_DEFAULT || lcdfilter == FT_LCD_FILTER_LIGHT )
5477             {
5478                 if ( render_mode == FT_RENDER_MODE_LCD)
5479                 {
5480                     lpgm->gmBlackBoxX += 2;
5481                     lpgm->gmptGlyphOrigin.x -= 1;
5482                 }
5483                 else
5484                 {
5485                     lpgm->gmBlackBoxY += 2;
5486                     lpgm->gmptGlyphOrigin.y += 1;
5487                 }
5488             }
5489
5490             width  = lpgm->gmBlackBoxX;
5491             height = lpgm->gmBlackBoxY;
5492             pitch  = width * 4;
5493             needed = pitch * height;
5494
5495             if (!buf || !buflen) break;
5496
5497             memset(buf, 0, buflen);
5498             dst = buf;
5499             rgb = (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_VRGB_BITMAP);
5500
5501             if ( needsTransform )
5502                 pFT_Outline_Transform (&ft_face->glyph->outline, &transMat);
5503
5504             if ( pFT_Library_SetLcdFilter )
5505                 pFT_Library_SetLcdFilter( library, lcdfilter );
5506             pFT_Render_Glyph (ft_face->glyph, render_mode);
5507
5508             src = ft_face->glyph->bitmap.buffer;
5509             src_pitch = ft_face->glyph->bitmap.pitch;
5510             src_width = ft_face->glyph->bitmap.width;
5511             src_height = ft_face->glyph->bitmap.rows;
5512
5513             if ( render_mode == FT_RENDER_MODE_LCD)
5514             {
5515                 rgb_interval = 1;
5516                 hmul = 3;
5517                 vmul = 1;
5518             }
5519             else
5520             {
5521                 rgb_interval = src_pitch;
5522                 hmul = 1;
5523                 vmul = 3;
5524             }
5525
5526             x_shift = ft_face->glyph->bitmap_left - lpgm->gmptGlyphOrigin.x;
5527             if ( x_shift < 0 ) x_shift = 0;
5528             if ( x_shift + (src_width / hmul) > width )
5529                 x_shift = width - (src_width / hmul);
5530
5531             y_shift = lpgm->gmptGlyphOrigin.y - ft_face->glyph->bitmap_top;
5532             if ( y_shift < 0 ) y_shift = 0;
5533             if ( y_shift + (src_height / vmul) > height )
5534                 y_shift = height - (src_height / vmul);
5535
5536             dst += x_shift + y_shift * ( pitch / 4 );
5537             while ( src_height )
5538             {
5539                 for ( x = 0; x < src_width / hmul; x++ )
5540                 {
5541                     if ( rgb )
5542                     {
5543                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 0] << 16) |
5544                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
5545                                  ((unsigned int)src[hmul * x + rgb_interval * 2] <<  0) |
5546                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
5547                     }
5548                     else
5549                     {
5550                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 2] << 16) |
5551                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
5552                                  ((unsigned int)src[hmul * x + rgb_interval * 0] <<  0) |
5553                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
5554                     }
5555                 }
5556                 src += src_pitch * vmul;
5557                 dst += pitch / 4;
5558                 src_height -= vmul;
5559             }
5560
5561             break;
5562           }
5563
5564         default:
5565             FIXME ("loaded glyph format %x\n", ft_face->glyph->format);
5566             return GDI_ERROR;
5567         }
5568
5569         break;
5570       }
5571 #else
5572       return GDI_ERROR;
5573 #endif
5574
5575     case GGO_NATIVE:
5576       {
5577         int contour, point = 0, first_pt;
5578         FT_Outline *outline = &ft_face->glyph->outline;
5579         TTPOLYGONHEADER *pph;
5580         TTPOLYCURVE *ppc;
5581         DWORD pph_start, cpfx, type;
5582
5583         if(buflen == 0) buf = NULL;
5584
5585         if (needsTransform && buf) {
5586                 pFT_Outline_Transform(outline, &transMat);
5587         }
5588
5589         for(contour = 0; contour < outline->n_contours; contour++) {
5590             pph_start = needed;
5591             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
5592             first_pt = point;
5593             if(buf) {
5594                 pph->dwType = TT_POLYGON_TYPE;
5595                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
5596             }
5597             needed += sizeof(*pph);
5598             point++;
5599             while(point <= outline->contours[contour]) {
5600                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
5601                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
5602                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
5603                 cpfx = 0;
5604                 do {
5605                     if(buf)
5606                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
5607                     cpfx++;
5608                     point++;
5609                 } while(point <= outline->contours[contour] &&
5610                         (outline->tags[point] & FT_Curve_Tag_On) ==
5611                         (outline->tags[point-1] & FT_Curve_Tag_On));
5612                 /* At the end of a contour Windows adds the start point, but
5613                    only for Beziers */
5614                 if(point > outline->contours[contour] &&
5615                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
5616                     if(buf)
5617                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
5618                     cpfx++;
5619                 } else if(point <= outline->contours[contour] &&
5620                           outline->tags[point] & FT_Curve_Tag_On) {
5621                   /* add closing pt for bezier */
5622                     if(buf)
5623                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
5624                     cpfx++;
5625                     point++;
5626                 }
5627                 if(buf) {
5628                     ppc->wType = type;
5629                     ppc->cpfx = cpfx;
5630                 }
5631                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
5632             }
5633             if(buf)
5634                 pph->cb = needed - pph_start;
5635         }
5636         break;
5637       }
5638     case GGO_BEZIER:
5639       {
5640         /* Convert the quadratic Beziers to cubic Beziers.
5641            The parametric eqn for a cubic Bezier is, from PLRM:
5642            r(t) = at^3 + bt^2 + ct + r0
5643            with the control points:
5644            r1 = r0 + c/3
5645            r2 = r1 + (c + b)/3
5646            r3 = r0 + c + b + a
5647
5648            A quadratic Bezier has the form:
5649            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
5650
5651            So equating powers of t leads to:
5652            r1 = 2/3 p1 + 1/3 p0
5653            r2 = 2/3 p1 + 1/3 p2
5654            and of course r0 = p0, r3 = p2
5655         */
5656
5657         int contour, point = 0, first_pt;
5658         FT_Outline *outline = &ft_face->glyph->outline;
5659         TTPOLYGONHEADER *pph;
5660         TTPOLYCURVE *ppc;
5661         DWORD pph_start, cpfx, type;
5662         FT_Vector cubic_control[4];
5663         if(buflen == 0) buf = NULL;
5664
5665         if (needsTransform && buf) {
5666                 pFT_Outline_Transform(outline, &transMat);
5667         }
5668
5669         for(contour = 0; contour < outline->n_contours; contour++) {
5670             pph_start = needed;
5671             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
5672             first_pt = point;
5673             if(buf) {
5674                 pph->dwType = TT_POLYGON_TYPE;
5675                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
5676             }
5677             needed += sizeof(*pph);
5678             point++;
5679             while(point <= outline->contours[contour]) {
5680                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
5681                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
5682                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
5683                 cpfx = 0;
5684                 do {
5685                     if(type == TT_PRIM_LINE) {
5686                         if(buf)
5687                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
5688                         cpfx++;
5689                         point++;
5690                     } else {
5691                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
5692                          so cpfx = 3n */
5693
5694                       /* FIXME: Possible optimization in endpoint calculation
5695                          if there are two consecutive curves */
5696                         cubic_control[0] = outline->points[point-1];
5697                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
5698                             cubic_control[0].x += outline->points[point].x + 1;
5699                             cubic_control[0].y += outline->points[point].y + 1;
5700                             cubic_control[0].x >>= 1;
5701                             cubic_control[0].y >>= 1;
5702                         }
5703                         if(point+1 > outline->contours[contour])
5704                             cubic_control[3] = outline->points[first_pt];
5705                         else {
5706                             cubic_control[3] = outline->points[point+1];
5707                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
5708                                 cubic_control[3].x += outline->points[point].x + 1;
5709                                 cubic_control[3].y += outline->points[point].y + 1;
5710                                 cubic_control[3].x >>= 1;
5711                                 cubic_control[3].y >>= 1;
5712                             }
5713                         }
5714                         /* r1 = 1/3 p0 + 2/3 p1
5715                            r2 = 1/3 p2 + 2/3 p1 */
5716                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
5717                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
5718                         cubic_control[2] = cubic_control[1];
5719                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
5720                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
5721                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
5722                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
5723                         if(buf) {
5724                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
5725                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
5726                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
5727                         }
5728                         cpfx += 3;
5729                         point++;
5730                     }
5731                 } while(point <= outline->contours[contour] &&
5732                         (outline->tags[point] & FT_Curve_Tag_On) ==
5733                         (outline->tags[point-1] & FT_Curve_Tag_On));
5734                 /* At the end of a contour Windows adds the start point,
5735                    but only for Beziers and we've already done that.
5736                 */
5737                 if(point <= outline->contours[contour] &&
5738                    outline->tags[point] & FT_Curve_Tag_On) {
5739                   /* This is the closing pt of a bezier, but we've already
5740                      added it, so just inc point and carry on */
5741                     point++;
5742                 }
5743                 if(buf) {
5744                     ppc->wType = type;
5745                     ppc->cpfx = cpfx;
5746                 }
5747                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
5748             }
5749             if(buf)
5750                 pph->cb = needed - pph_start;
5751         }
5752         break;
5753       }
5754
5755     default:
5756         FIXME("Unsupported format %d\n", format);
5757         return GDI_ERROR;
5758     }
5759     return needed;
5760 }
5761
5762 static BOOL get_bitmap_text_metrics(GdiFont *font)
5763 {
5764     FT_Face ft_face = font->ft_face;
5765     FT_WinFNT_HeaderRec winfnt_header;
5766     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
5767     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
5768     font->potm->otmSize = size;
5769
5770 #define TM font->potm->otmTextMetrics
5771     if(!pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
5772     {
5773         TM.tmHeight = winfnt_header.pixel_height;
5774         TM.tmAscent = winfnt_header.ascent;
5775         TM.tmDescent = TM.tmHeight - TM.tmAscent;
5776         TM.tmInternalLeading = winfnt_header.internal_leading;
5777         TM.tmExternalLeading = winfnt_header.external_leading;
5778         TM.tmAveCharWidth = winfnt_header.avg_width;
5779         TM.tmMaxCharWidth = winfnt_header.max_width;
5780         TM.tmWeight = winfnt_header.weight;
5781         TM.tmOverhang = 0;
5782         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
5783         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
5784         TM.tmFirstChar = winfnt_header.first_char;
5785         TM.tmLastChar = winfnt_header.last_char;
5786         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
5787         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
5788         TM.tmItalic = winfnt_header.italic;
5789         TM.tmUnderlined = font->underline;
5790         TM.tmStruckOut = font->strikeout;
5791         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
5792         TM.tmCharSet = winfnt_header.charset;
5793     }
5794     else
5795     {
5796         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
5797         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
5798         TM.tmHeight = TM.tmAscent + TM.tmDescent;
5799         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
5800         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
5801         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
5802         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
5803         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
5804         TM.tmOverhang = 0;
5805         TM.tmDigitizedAspectX = 96; /* FIXME */
5806         TM.tmDigitizedAspectY = 96; /* FIXME */
5807         TM.tmFirstChar = 1;
5808         TM.tmLastChar = 255;
5809         TM.tmDefaultChar = 32;
5810         TM.tmBreakChar = 32;
5811         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
5812         TM.tmUnderlined = font->underline;
5813         TM.tmStruckOut = font->strikeout;
5814         /* NB inverted meaning of TMPF_FIXED_PITCH */
5815         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
5816         TM.tmCharSet = font->charset;
5817     }
5818 #undef TM
5819
5820     return TRUE;
5821 }
5822
5823
5824 static void scale_font_metrics(const GdiFont *font, LPTEXTMETRICW ptm)
5825 {
5826     double scale_x, scale_y;
5827
5828     if (font->aveWidth)
5829     {
5830         scale_x = (double)font->aveWidth;
5831         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5832     }
5833     else
5834         scale_x = font->scale_y;
5835
5836     scale_x *= fabs(font->font_desc.matrix.eM11);
5837     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
5838
5839 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
5840 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
5841
5842     SCALE_Y(ptm->tmHeight);
5843     SCALE_Y(ptm->tmAscent);
5844     SCALE_Y(ptm->tmDescent);
5845     SCALE_Y(ptm->tmInternalLeading);
5846     SCALE_Y(ptm->tmExternalLeading);
5847     SCALE_Y(ptm->tmOverhang);
5848
5849     SCALE_X(ptm->tmAveCharWidth);
5850     SCALE_X(ptm->tmMaxCharWidth);
5851
5852 #undef SCALE_X
5853 #undef SCALE_Y
5854 }
5855
5856 static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *potm)
5857 {
5858     double scale_x, scale_y;
5859
5860     if (font->aveWidth)
5861     {
5862         scale_x = (double)font->aveWidth;
5863         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5864     }
5865     else
5866         scale_x = font->scale_y;
5867
5868     scale_x *= fabs(font->font_desc.matrix.eM11);
5869     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
5870
5871     scale_font_metrics(font, &potm->otmTextMetrics);
5872
5873 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
5874 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
5875
5876     SCALE_Y(potm->otmAscent);
5877     SCALE_Y(potm->otmDescent);
5878     SCALE_Y(potm->otmLineGap);
5879     SCALE_Y(potm->otmsCapEmHeight);
5880     SCALE_Y(potm->otmsXHeight);
5881     SCALE_Y(potm->otmrcFontBox.top);
5882     SCALE_Y(potm->otmrcFontBox.bottom);
5883     SCALE_X(potm->otmrcFontBox.left);
5884     SCALE_X(potm->otmrcFontBox.right);
5885     SCALE_Y(potm->otmMacAscent);
5886     SCALE_Y(potm->otmMacDescent);
5887     SCALE_Y(potm->otmMacLineGap);
5888     SCALE_X(potm->otmptSubscriptSize.x);
5889     SCALE_Y(potm->otmptSubscriptSize.y);
5890     SCALE_X(potm->otmptSubscriptOffset.x);
5891     SCALE_Y(potm->otmptSubscriptOffset.y);
5892     SCALE_X(potm->otmptSuperscriptSize.x);
5893     SCALE_Y(potm->otmptSuperscriptSize.y);
5894     SCALE_X(potm->otmptSuperscriptOffset.x);
5895     SCALE_Y(potm->otmptSuperscriptOffset.y);
5896     SCALE_Y(potm->otmsStrikeoutSize);
5897     SCALE_Y(potm->otmsStrikeoutPosition);
5898     SCALE_Y(potm->otmsUnderscoreSize);
5899     SCALE_Y(potm->otmsUnderscorePosition);
5900
5901 #undef SCALE_X
5902 #undef SCALE_Y
5903 }
5904
5905 static BOOL get_text_metrics(GdiFont *font, LPTEXTMETRICW ptm)
5906 {
5907     if(!font->potm)
5908     {
5909         if (!get_outline_text_metrics(font) && !get_bitmap_text_metrics(font)) return FALSE;
5910
5911         /* Make sure that the font has sane width/height ratio */
5912         if (font->aveWidth)
5913         {
5914             if ((font->aveWidth + font->potm->otmTextMetrics.tmHeight - 1) / font->potm->otmTextMetrics.tmHeight > 100)
5915             {
5916                 WARN("Ignoring too large font->aveWidth %d\n", font->aveWidth);
5917                 font->aveWidth = 0;
5918             }
5919         }
5920     }
5921     *ptm = font->potm->otmTextMetrics;
5922     scale_font_metrics(font, ptm);
5923     return TRUE;
5924 }
5925
5926 static BOOL face_has_symbol_charmap(FT_Face ft_face)
5927 {
5928     int i;
5929
5930     for(i = 0; i < ft_face->num_charmaps; i++)
5931     {
5932         if(ft_face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
5933             return TRUE;
5934     }
5935     return FALSE;
5936 }
5937
5938 static BOOL get_outline_text_metrics(GdiFont *font)
5939 {
5940     BOOL ret = FALSE;
5941     FT_Face ft_face = font->ft_face;
5942     UINT needed, lenfam, lensty;
5943     TT_OS2 *pOS2;
5944     TT_HoriHeader *pHori;
5945     TT_Postscript *pPost;
5946     FT_Fixed x_scale, y_scale;
5947     WCHAR *family_nameW, *style_nameW;
5948     static const WCHAR spaceW[] = {' ', '\0'};
5949     char *cp;
5950     INT ascent, descent;
5951
5952     TRACE("font=%p\n", font);
5953
5954     if(!FT_IS_SCALABLE(ft_face))
5955         return FALSE;
5956
5957     needed = sizeof(*font->potm);
5958
5959     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
5960     family_nameW = strdupW(font->name);
5961
5962     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
5963       * sizeof(WCHAR);
5964     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
5965     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
5966                         style_nameW, lensty/sizeof(WCHAR));
5967
5968     /* These names should be read from the TT name table */
5969
5970     /* length of otmpFamilyName */
5971     needed += lenfam;
5972
5973     /* length of otmpFaceName */
5974     if ((ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) == 0) {
5975       needed += lenfam; /* just the family name */
5976     } else {
5977       needed += lenfam + lensty; /* family + " " + style */
5978     }
5979
5980     /* length of otmpStyleName */
5981     needed += lensty;
5982
5983     /* length of otmpFullName */
5984     needed += lenfam + lensty;
5985
5986
5987     x_scale = ft_face->size->metrics.x_scale;
5988     y_scale = ft_face->size->metrics.y_scale;
5989
5990     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
5991     if(!pOS2) {
5992         FIXME("Can't find OS/2 table - not TT font?\n");
5993         goto end;
5994     }
5995
5996     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
5997     if(!pHori) {
5998         FIXME("Can't find HHEA table - not TT font?\n");
5999         goto end;
6000     }
6001
6002     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
6003
6004     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",
6005           pOS2->usWinAscent, pOS2->usWinDescent,
6006           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
6007           ft_face->ascender, ft_face->descender, ft_face->height,
6008           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
6009           ft_face->bbox.yMax, ft_face->bbox.yMin);
6010
6011     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
6012     font->potm->otmSize = needed;
6013
6014 #define TM font->potm->otmTextMetrics
6015
6016     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
6017         ascent = pHori->Ascender;
6018         descent = -pHori->Descender;
6019     } else {
6020         ascent = pOS2->usWinAscent;
6021         descent = pOS2->usWinDescent;
6022     }
6023
6024     if(font->yMax) {
6025         TM.tmAscent = font->yMax;
6026         TM.tmDescent = -font->yMin;
6027         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
6028     } else {
6029         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
6030         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
6031         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
6032                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
6033     }
6034
6035     TM.tmHeight = TM.tmAscent + TM.tmDescent;
6036
6037     /* MSDN says:
6038      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
6039     */
6040     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
6041                  ((ascent + descent) -
6042                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
6043
6044     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
6045     if (TM.tmAveCharWidth == 0) {
6046         TM.tmAveCharWidth = 1; 
6047     }
6048     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
6049     TM.tmWeight = FW_REGULAR;
6050     if (font->fake_bold)
6051         TM.tmWeight = FW_BOLD;
6052     else
6053     {
6054         if (ft_face->style_flags & FT_STYLE_FLAG_BOLD)
6055         {
6056             if (pOS2->usWeightClass > FW_MEDIUM)
6057                 TM.tmWeight = pOS2->usWeightClass;
6058         }
6059         else if (pOS2->usWeightClass <= FW_MEDIUM)
6060             TM.tmWeight = pOS2->usWeightClass;
6061     }
6062     TM.tmOverhang = 0;
6063     TM.tmDigitizedAspectX = 300;
6064     TM.tmDigitizedAspectY = 300;
6065     /* It appears that for fonts with SYMBOL_CHARSET Windows always sets
6066      * symbol range to 0 - f0ff
6067      */
6068
6069     if (face_has_symbol_charmap(ft_face) || (pOS2->usFirstCharIndex >= 0xf000 && pOS2->usFirstCharIndex < 0xf100))
6070     {
6071         TM.tmFirstChar = 0;
6072         switch(GetACP())
6073         {
6074         case 1257: /* Baltic */
6075             TM.tmLastChar = 0xf8fd;
6076             break;
6077         default:
6078             TM.tmLastChar = 0xf0ff;
6079         }
6080         TM.tmBreakChar = 0x20;
6081         TM.tmDefaultChar = 0x1f;
6082     }
6083     else
6084     {
6085         TM.tmFirstChar = pOS2->usFirstCharIndex; /* Should be the first char in the cmap */
6086         TM.tmLastChar = pOS2->usLastCharIndex;   /* Should be min(cmap_last, os2_last) */
6087
6088         if(pOS2->usFirstCharIndex <= 1)
6089             TM.tmBreakChar = pOS2->usFirstCharIndex + 2;
6090         else if (pOS2->usFirstCharIndex > 0xff)
6091             TM.tmBreakChar = 0x20;
6092         else
6093             TM.tmBreakChar = pOS2->usFirstCharIndex;
6094         TM.tmDefaultChar = TM.tmBreakChar - 1;
6095     }
6096     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
6097     TM.tmUnderlined = font->underline;
6098     TM.tmStruckOut = font->strikeout;
6099
6100     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
6101     if(!FT_IS_FIXED_WIDTH(ft_face) &&
6102        (pOS2->version == 0xFFFFU || 
6103         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
6104         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
6105     else
6106         TM.tmPitchAndFamily = 0;
6107
6108     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX])
6109     {
6110     case PAN_FAMILY_SCRIPT:
6111         TM.tmPitchAndFamily |= FF_SCRIPT;
6112         break;
6113
6114     case PAN_FAMILY_DECORATIVE:
6115         TM.tmPitchAndFamily |= FF_DECORATIVE;
6116         break;
6117
6118     case PAN_ANY:
6119     case PAN_NO_FIT:
6120     case PAN_FAMILY_TEXT_DISPLAY:
6121     case PAN_FAMILY_PICTORIAL: /* symbol fonts get treated as if they were text */
6122                                /* which is clearly not what the panose spec says. */
6123     default:
6124         if(TM.tmPitchAndFamily == 0 || /* fixed */
6125            pOS2->panose[PAN_PROPORTION_INDEX] == PAN_PROP_MONOSPACED)
6126             TM.tmPitchAndFamily = FF_MODERN;
6127         else
6128         {
6129             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX])
6130             {
6131             case PAN_ANY:
6132             case PAN_NO_FIT:
6133             default:
6134                 TM.tmPitchAndFamily |= FF_DONTCARE;
6135                 break;
6136
6137             case PAN_SERIF_COVE:
6138             case PAN_SERIF_OBTUSE_COVE:
6139             case PAN_SERIF_SQUARE_COVE:
6140             case PAN_SERIF_OBTUSE_SQUARE_COVE:
6141             case PAN_SERIF_SQUARE:
6142             case PAN_SERIF_THIN:
6143             case PAN_SERIF_BONE:
6144             case PAN_SERIF_EXAGGERATED:
6145             case PAN_SERIF_TRIANGLE:
6146                 TM.tmPitchAndFamily |= FF_ROMAN;
6147                 break;
6148
6149             case PAN_SERIF_NORMAL_SANS:
6150             case PAN_SERIF_OBTUSE_SANS:
6151             case PAN_SERIF_PERP_SANS:
6152             case PAN_SERIF_FLARED:
6153             case PAN_SERIF_ROUNDED:
6154                 TM.tmPitchAndFamily |= FF_SWISS;
6155                 break;
6156             }
6157         }
6158         break;
6159     }
6160
6161     if(FT_IS_SCALABLE(ft_face))
6162         TM.tmPitchAndFamily |= TMPF_VECTOR;
6163
6164     if(FT_IS_SFNT(ft_face))
6165     {
6166         if (font->ntmFlags & NTM_PS_OPENTYPE)
6167             TM.tmPitchAndFamily |= TMPF_DEVICE;
6168         else
6169             TM.tmPitchAndFamily |= TMPF_TRUETYPE;
6170     }
6171
6172     TM.tmCharSet = font->charset;
6173
6174     font->potm->otmFiller = 0;
6175     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
6176     font->potm->otmfsSelection = pOS2->fsSelection;
6177     font->potm->otmfsType = pOS2->fsType;
6178     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
6179     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
6180     font->potm->otmItalicAngle = 0; /* POST table */
6181     font->potm->otmEMSquare = ft_face->units_per_EM;
6182     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
6183     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
6184     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
6185     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
6186     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
6187     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
6188     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
6189     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
6190     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
6191     font->potm->otmMacAscent = TM.tmAscent;
6192     font->potm->otmMacDescent = -TM.tmDescent;
6193     font->potm->otmMacLineGap = font->potm->otmLineGap;
6194     font->potm->otmusMinimumPPEM = 0; /* TT Header */
6195     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
6196     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
6197     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
6198     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
6199     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
6200     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
6201     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
6202     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
6203     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
6204     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
6205     if(!pPost) {
6206         font->potm->otmsUnderscoreSize = 0;
6207         font->potm->otmsUnderscorePosition = 0;
6208     } else {
6209         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
6210         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
6211     }
6212 #undef TM
6213
6214     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
6215     cp = (char*)font->potm + sizeof(*font->potm);
6216     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
6217     strcpyW((WCHAR*)cp, family_nameW);
6218     cp += lenfam;
6219     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
6220     strcpyW((WCHAR*)cp, style_nameW);
6221     cp += lensty;
6222     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
6223     strcpyW((WCHAR*)cp, family_nameW);
6224     if (ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) {
6225         strcatW((WCHAR*)cp, spaceW);
6226         strcatW((WCHAR*)cp, style_nameW);
6227         cp += lenfam + lensty;
6228     } else
6229         cp += lenfam;
6230     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
6231     strcpyW((WCHAR*)cp, family_nameW);
6232     strcatW((WCHAR*)cp, spaceW);
6233     strcatW((WCHAR*)cp, style_nameW);
6234     ret = TRUE;
6235
6236 end:
6237     HeapFree(GetProcessHeap(), 0, style_nameW);
6238     HeapFree(GetProcessHeap(), 0, family_nameW);
6239     return ret;
6240 }
6241
6242 /*************************************************************
6243  * freetype_GetGlyphOutline
6244  */
6245 static DWORD freetype_GetGlyphOutline( PHYSDEV dev, UINT glyph, UINT format,
6246                                        LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf, const MAT2 *lpmat )
6247 {
6248     struct freetype_physdev *physdev = get_freetype_dev( dev );
6249     DWORD ret;
6250
6251     if (!physdev->font)
6252     {
6253         dev = GET_NEXT_PHYSDEV( dev, pGetGlyphOutline );
6254         return dev->funcs->pGetGlyphOutline( dev, glyph, format, lpgm, buflen, buf, lpmat );
6255     }
6256
6257     GDI_CheckNotLock();
6258     EnterCriticalSection( &freetype_cs );
6259     ret = get_glyph_outline( physdev->font, glyph, format, lpgm, buflen, buf, lpmat );
6260     LeaveCriticalSection( &freetype_cs );
6261     return ret;
6262 }
6263
6264 /*************************************************************
6265  * freetype_GetTextMetrics
6266  */
6267 static BOOL freetype_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
6268 {
6269     struct freetype_physdev *physdev = get_freetype_dev( dev );
6270     BOOL ret;
6271
6272     if (!physdev->font)
6273     {
6274         dev = GET_NEXT_PHYSDEV( dev, pGetTextMetrics );
6275         return dev->funcs->pGetTextMetrics( dev, metrics );
6276     }
6277
6278     GDI_CheckNotLock();
6279     EnterCriticalSection( &freetype_cs );
6280     ret = get_text_metrics( physdev->font, metrics );
6281     LeaveCriticalSection( &freetype_cs );
6282     return ret;
6283 }
6284
6285 /*************************************************************
6286  * freetype_GetOutlineTextMetrics
6287  */
6288 static UINT freetype_GetOutlineTextMetrics( PHYSDEV dev, UINT cbSize, OUTLINETEXTMETRICW *potm )
6289 {
6290     struct freetype_physdev *physdev = get_freetype_dev( dev );
6291     UINT ret = 0;
6292
6293     if (!physdev->font)
6294     {
6295         dev = GET_NEXT_PHYSDEV( dev, pGetOutlineTextMetrics );
6296         return dev->funcs->pGetOutlineTextMetrics( dev, cbSize, potm );
6297     }
6298
6299     TRACE("font=%p\n", physdev->font);
6300
6301     if (!FT_IS_SCALABLE( physdev->font->ft_face )) return 0;
6302
6303     GDI_CheckNotLock();
6304     EnterCriticalSection( &freetype_cs );
6305
6306     if (physdev->font->potm || get_outline_text_metrics( physdev->font ))
6307     {
6308         if(cbSize >= physdev->font->potm->otmSize)
6309         {
6310             memcpy(potm, physdev->font->potm, physdev->font->potm->otmSize);
6311             scale_outline_font_metrics(physdev->font, potm);
6312         }
6313         ret = physdev->font->potm->otmSize;
6314     }
6315     LeaveCriticalSection( &freetype_cs );
6316     return ret;
6317 }
6318
6319 static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
6320 {
6321     HFONTLIST *hfontlist;
6322     child->font = alloc_font();
6323     child->font->ft_face = OpenFontFace(child->font, child->face, 0, -font->ppem);
6324     if(!child->font->ft_face)
6325     {
6326         free_font(child->font);
6327         child->font = NULL;
6328         return FALSE;
6329     }
6330
6331     child->font->font_desc = font->font_desc;
6332     child->font->ntmFlags = child->face->ntmFlags;
6333     child->font->orientation = font->orientation;
6334     child->font->scale_y = font->scale_y;
6335     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
6336     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
6337     child->font->name = strdupW(child->face->family->FamilyName);
6338     list_add_head(&child->font->hfontlist, &hfontlist->entry);
6339     child->font->base_font = font;
6340     list_add_head(&child_font_list, &child->font->entry);
6341     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
6342     return TRUE;
6343 }
6344
6345 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph)
6346 {
6347     FT_UInt g;
6348     CHILD_FONT *child_font;
6349
6350     if(font->base_font)
6351         font = font->base_font;
6352
6353     *linked_font = font;
6354
6355     if((*glyph = get_glyph_index(font, c)))
6356         return TRUE;
6357
6358     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
6359     {
6360         if(!child_font->font)
6361             if(!load_child_font(font, child_font))
6362                 continue;
6363
6364         if(!child_font->font->ft_face)
6365             continue;
6366         g = get_glyph_index(child_font->font, c);
6367         if(g)
6368         {
6369             *glyph = g;
6370             *linked_font = child_font->font;
6371             return TRUE;
6372         }
6373     }
6374     return FALSE;
6375 }
6376
6377 /*************************************************************
6378  * freetype_GetCharWidth
6379  */
6380 static BOOL freetype_GetCharWidth( PHYSDEV dev, UINT firstChar, UINT lastChar, LPINT buffer )
6381 {
6382     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
6383     UINT c;
6384     GLYPHMETRICS gm;
6385     FT_UInt glyph_index;
6386     GdiFont *linked_font;
6387     struct freetype_physdev *physdev = get_freetype_dev( dev );
6388
6389     if (!physdev->font)
6390     {
6391         dev = GET_NEXT_PHYSDEV( dev, pGetCharWidth );
6392         return dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
6393     }
6394
6395     TRACE("%p, %d, %d, %p\n", physdev->font, firstChar, lastChar, buffer);
6396
6397     GDI_CheckNotLock();
6398     EnterCriticalSection( &freetype_cs );
6399     for(c = firstChar; c <= lastChar; c++) {
6400         get_glyph_index_linked(physdev->font, c, &linked_font, &glyph_index);
6401         get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
6402                           &gm, 0, NULL, &identity);
6403         buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv;
6404     }
6405     LeaveCriticalSection( &freetype_cs );
6406     return TRUE;
6407 }
6408
6409 /*************************************************************
6410  * freetype_GetCharABCWidths
6411  */
6412 static BOOL freetype_GetCharABCWidths( PHYSDEV dev, UINT firstChar, UINT lastChar, LPABC buffer )
6413 {
6414     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
6415     UINT c;
6416     GLYPHMETRICS gm;
6417     FT_UInt glyph_index;
6418     GdiFont *linked_font;
6419     struct freetype_physdev *physdev = get_freetype_dev( dev );
6420
6421     if (!physdev->font)
6422     {
6423         dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidths );
6424         return dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, buffer );
6425     }
6426
6427     TRACE("%p, %d, %d, %p\n", physdev->font, firstChar, lastChar, buffer);
6428
6429     if(!FT_IS_SCALABLE(physdev->font->ft_face))
6430         return FALSE;
6431
6432     GDI_CheckNotLock();
6433     EnterCriticalSection( &freetype_cs );
6434
6435     for(c = firstChar; c <= lastChar; c++) {
6436         get_glyph_index_linked(physdev->font, c, &linked_font, &glyph_index);
6437         get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
6438                           &gm, 0, NULL, &identity);
6439         buffer[c - firstChar].abcA = FONT_GM(linked_font,glyph_index)->lsb;
6440         buffer[c - firstChar].abcB = FONT_GM(linked_font,glyph_index)->bbx;
6441         buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb -
6442             FONT_GM(linked_font,glyph_index)->bbx;
6443     }
6444     LeaveCriticalSection( &freetype_cs );
6445     return TRUE;
6446 }
6447
6448 /*************************************************************
6449  * freetype_GetCharABCWidthsI
6450  */
6451 static BOOL freetype_GetCharABCWidthsI( PHYSDEV dev, UINT firstChar, UINT count, LPWORD pgi, LPABC buffer )
6452 {
6453     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
6454     UINT c;
6455     GLYPHMETRICS gm;
6456     FT_UInt glyph_index;
6457     GdiFont *linked_font;
6458     struct freetype_physdev *physdev = get_freetype_dev( dev );
6459
6460     if (!physdev->font)
6461     {
6462         dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidthsI );
6463         return dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, buffer );
6464     }
6465
6466     if(!FT_HAS_HORIZONTAL(physdev->font->ft_face))
6467         return FALSE;
6468
6469     GDI_CheckNotLock();
6470     EnterCriticalSection( &freetype_cs );
6471
6472     get_glyph_index_linked(physdev->font, 'a', &linked_font, &glyph_index);
6473     if (!pgi)
6474         for(c = firstChar; c < firstChar+count; c++) {
6475             get_glyph_outline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
6476                               &gm, 0, NULL, &identity);
6477             buffer[c - firstChar].abcA = FONT_GM(linked_font,c)->lsb;
6478             buffer[c - firstChar].abcB = FONT_GM(linked_font,c)->bbx;
6479             buffer[c - firstChar].abcC = FONT_GM(linked_font,c)->adv - FONT_GM(linked_font,c)->lsb
6480                 - FONT_GM(linked_font,c)->bbx;
6481         }
6482     else
6483         for(c = 0; c < count; c++) {
6484             get_glyph_outline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
6485                               &gm, 0, NULL, &identity);
6486             buffer[c].abcA = FONT_GM(linked_font,pgi[c])->lsb;
6487             buffer[c].abcB = FONT_GM(linked_font,pgi[c])->bbx;
6488             buffer[c].abcC = FONT_GM(linked_font,pgi[c])->adv
6489                 - FONT_GM(linked_font,pgi[c])->lsb - FONT_GM(linked_font,pgi[c])->bbx;
6490         }
6491
6492     LeaveCriticalSection( &freetype_cs );
6493     return TRUE;
6494 }
6495
6496 /*************************************************************
6497  * freetype_GetTextExtentExPoint
6498  */
6499 static BOOL freetype_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR wstr, INT count,
6500                                            INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
6501 {
6502     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
6503     INT idx;
6504     INT nfit = 0, ext;
6505     GLYPHMETRICS gm;
6506     TEXTMETRICW tm;
6507     FT_UInt glyph_index;
6508     GdiFont *linked_font;
6509     struct freetype_physdev *physdev = get_freetype_dev( dev );
6510
6511     if (!physdev->font)
6512     {
6513         dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPoint );
6514         return dev->funcs->pGetTextExtentExPoint( dev, wstr, count, max_ext, pnfit, dxs, size );
6515     }
6516
6517     TRACE("%p, %s, %d, %d, %p\n", physdev->font, debugstr_wn(wstr, count), count, max_ext, size);
6518
6519     GDI_CheckNotLock();
6520     EnterCriticalSection( &freetype_cs );
6521
6522     size->cx = 0;
6523     get_text_metrics( physdev->font, &tm );
6524     size->cy = tm.tmHeight;
6525
6526     for(idx = 0; idx < count; idx++) {
6527         get_glyph_index_linked( physdev->font, wstr[idx], &linked_font, &glyph_index );
6528         get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
6529                           &gm, 0, NULL, &identity);
6530         size->cx += FONT_GM(linked_font,glyph_index)->adv;
6531         ext = size->cx;
6532         if (! pnfit || ext <= max_ext) {
6533             ++nfit;
6534             if (dxs)
6535                 dxs[idx] = ext;
6536         }
6537     }
6538
6539     if (pnfit)
6540         *pnfit = nfit;
6541
6542     LeaveCriticalSection( &freetype_cs );
6543     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
6544     return TRUE;
6545 }
6546
6547 /*************************************************************
6548  * freetype_GetTextExtentExPointI
6549  */
6550 static BOOL freetype_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, INT count,
6551                                             INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size )
6552 {
6553     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
6554     INT idx;
6555     INT nfit = 0, ext;
6556     GLYPHMETRICS gm;
6557     TEXTMETRICW tm;
6558     struct freetype_physdev *physdev = get_freetype_dev( dev );
6559
6560     if (!physdev->font)
6561     {
6562         dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPointI );
6563         return dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, pnfit, dxs, size );
6564     }
6565
6566     TRACE("%p, %p, %d, %d, %p\n", physdev->font, indices, count, max_ext, size);
6567
6568     GDI_CheckNotLock();
6569     EnterCriticalSection( &freetype_cs );
6570
6571     size->cx = 0;
6572     get_text_metrics(physdev->font, &tm);
6573     size->cy = tm.tmHeight;
6574
6575     for(idx = 0; idx < count; idx++) {
6576         get_glyph_outline(physdev->font, indices[idx], GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &identity);
6577         size->cx += FONT_GM(physdev->font,indices[idx])->adv;
6578         ext = size->cx;
6579         if (! pnfit || ext <= max_ext) {
6580             ++nfit;
6581             if (dxs)
6582                 dxs[idx] = ext;
6583         }
6584     }
6585
6586     if (pnfit)
6587         *pnfit = nfit;
6588
6589     LeaveCriticalSection( &freetype_cs );
6590     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
6591     return TRUE;
6592 }
6593
6594 /*************************************************************
6595  * freetype_GetFontData
6596  */
6597 static DWORD freetype_GetFontData( PHYSDEV dev, DWORD table, DWORD offset, LPVOID buf, DWORD cbData )
6598 {
6599     struct freetype_physdev *physdev = get_freetype_dev( dev );
6600
6601     if (!physdev->font)
6602     {
6603         dev = GET_NEXT_PHYSDEV( dev, pGetFontData );
6604         return dev->funcs->pGetFontData( dev, table, offset, buf, cbData );
6605     }
6606
6607     TRACE("font=%p, table=%c%c%c%c, offset=0x%x, buf=%p, cbData=0x%x\n",
6608           physdev->font, LOBYTE(LOWORD(table)), HIBYTE(LOWORD(table)),
6609           LOBYTE(HIWORD(table)), HIBYTE(HIWORD(table)), offset, buf, cbData);
6610
6611     return get_font_data( physdev->font, table, offset, buf, cbData );
6612 }
6613
6614 /*************************************************************
6615  * freetype_GetTextFace
6616  */
6617 static INT freetype_GetTextFace( PHYSDEV dev, INT count, LPWSTR str )
6618 {
6619     INT n;
6620     struct freetype_physdev *physdev = get_freetype_dev( dev );
6621
6622     if (!physdev->font)
6623     {
6624         dev = GET_NEXT_PHYSDEV( dev, pGetTextFace );
6625         return dev->funcs->pGetTextFace( dev, count, str );
6626     }
6627
6628     n = strlenW(physdev->font->name) + 1;
6629     if (str)
6630     {
6631         lstrcpynW(str, physdev->font->name, count);
6632         n = min(count, n);
6633     }
6634     return n;
6635 }
6636
6637 /*************************************************************
6638  * freetype_GetTextCharsetInfo
6639  */
6640 static UINT freetype_GetTextCharsetInfo( PHYSDEV dev, LPFONTSIGNATURE fs, DWORD flags )
6641 {
6642     struct freetype_physdev *physdev = get_freetype_dev( dev );
6643
6644     if (!physdev->font)
6645     {
6646         dev = GET_NEXT_PHYSDEV( dev, pGetTextCharsetInfo );
6647         return dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
6648     }
6649     if (fs) *fs = physdev->font->fs;
6650     return physdev->font->charset;
6651 }
6652
6653 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
6654 {
6655     GdiFont *font = dc->gdiFont, *linked_font;
6656     struct list *first_hfont;
6657     BOOL ret;
6658
6659     GDI_CheckNotLock();
6660     EnterCriticalSection( &freetype_cs );
6661     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
6662     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
6663     if(font == linked_font)
6664         *new_hfont = dc->hFont;
6665     else
6666     {
6667         first_hfont = list_head(&linked_font->hfontlist);
6668         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
6669     }
6670     LeaveCriticalSection( &freetype_cs );
6671     return ret;
6672 }
6673     
6674 /* Retrieve a list of supported Unicode ranges for a given font.
6675  * Can be called with NULL gs to calculate the buffer size. Returns
6676  * the number of ranges found.
6677  */
6678 static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
6679 {
6680     DWORD num_ranges = 0;
6681
6682     if (face->charmap->encoding == FT_ENCODING_UNICODE)
6683     {
6684         FT_UInt glyph_code;
6685         FT_ULong char_code, char_code_prev;
6686
6687         glyph_code = 0;
6688         char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
6689
6690         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
6691                face->num_glyphs, glyph_code, char_code);
6692
6693         if (!glyph_code) return 0;
6694
6695         if (gs)
6696         {
6697             gs->ranges[0].wcLow = (USHORT)char_code;
6698             gs->ranges[0].cGlyphs = 0;
6699             gs->cGlyphsSupported = 0;
6700         }
6701
6702         num_ranges = 1;
6703         while (glyph_code)
6704         {
6705             if (char_code < char_code_prev)
6706             {
6707                 ERR("expected increasing char code from FT_Get_Next_Char\n");
6708                 return 0;
6709             }
6710             if (char_code - char_code_prev > 1)
6711             {
6712                 num_ranges++;
6713                 if (gs)
6714                 {
6715                     gs->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
6716                     gs->ranges[num_ranges - 1].cGlyphs = 1;
6717                     gs->cGlyphsSupported++;
6718                 }
6719             }
6720             else if (gs)
6721             {
6722                 gs->ranges[num_ranges - 1].cGlyphs++;
6723                 gs->cGlyphsSupported++;
6724             }
6725             char_code_prev = char_code;
6726             char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
6727         }
6728     }
6729     else
6730         FIXME("encoding %u not supported\n", face->charmap->encoding);
6731
6732     return num_ranges;
6733 }
6734
6735 /*************************************************************
6736  * freetype_GetFontUnicodeRanges
6737  */
6738 static DWORD freetype_GetFontUnicodeRanges( PHYSDEV dev, LPGLYPHSET glyphset )
6739 {
6740     struct freetype_physdev *physdev = get_freetype_dev( dev );
6741     DWORD size, num_ranges;
6742
6743     if (!physdev->font)
6744     {
6745         dev = GET_NEXT_PHYSDEV( dev, pGetFontUnicodeRanges );
6746         return dev->funcs->pGetFontUnicodeRanges( dev, glyphset );
6747     }
6748
6749     num_ranges = get_font_unicode_ranges(physdev->font->ft_face, glyphset);
6750     size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
6751     if (glyphset)
6752     {
6753         glyphset->cbThis = size;
6754         glyphset->cRanges = num_ranges;
6755         glyphset->flAccel = 0;
6756     }
6757     return size;
6758 }
6759
6760 /*************************************************************
6761  * freetype_FontIsLinked
6762  */
6763 static BOOL freetype_FontIsLinked( PHYSDEV dev )
6764 {
6765     struct freetype_physdev *physdev = get_freetype_dev( dev );
6766     BOOL ret;
6767
6768     if (!physdev->font)
6769     {
6770         dev = GET_NEXT_PHYSDEV( dev, pFontIsLinked );
6771         return dev->funcs->pFontIsLinked( dev );
6772     }
6773
6774     GDI_CheckNotLock();
6775     EnterCriticalSection( &freetype_cs );
6776     ret = !list_empty(&physdev->font->child_fonts);
6777     LeaveCriticalSection( &freetype_cs );
6778     return ret;
6779 }
6780
6781 static BOOL is_hinting_enabled(void)
6782 {
6783     /* Use the >= 2.2.0 function if available */
6784     if(pFT_Get_TrueType_Engine_Type)
6785     {
6786         FT_TrueTypeEngineType type = pFT_Get_TrueType_Engine_Type(library);
6787         return type == FT_TRUETYPE_ENGINE_TYPE_PATENTED;
6788     }
6789 #ifdef FT_DRIVER_HAS_HINTER
6790     else
6791     {
6792         FT_Module mod;
6793
6794         /* otherwise if we've been compiled with < 2.2.0 headers 
6795            use the internal macro */
6796         mod = pFT_Get_Module(library, "truetype");
6797         if(mod && FT_DRIVER_HAS_HINTER(mod))
6798             return TRUE;
6799     }
6800 #endif
6801
6802     return FALSE;
6803 }
6804
6805 static BOOL is_subpixel_rendering_enabled( void )
6806 {
6807 #ifdef HAVE_FREETYPE_FTLCDFIL_H
6808     return pFT_Library_SetLcdFilter &&
6809            pFT_Library_SetLcdFilter( NULL, 0 ) != FT_Err_Unimplemented_Feature;
6810 #else
6811     return FALSE;
6812 #endif
6813 }
6814
6815 /*************************************************************************
6816  *             GetRasterizerCaps   (GDI32.@)
6817  */
6818 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
6819 {
6820     static int hinting = -1;
6821     static int subpixel = -1;
6822
6823     if(hinting == -1)
6824     {
6825         hinting = is_hinting_enabled();
6826         TRACE("hinting is %senabled\n", hinting ? "" : "NOT ");
6827     }
6828
6829     if ( subpixel == -1 )
6830     {
6831         subpixel = is_subpixel_rendering_enabled();
6832         TRACE("subpixel rendering is %senabled\n", subpixel ? "" : "NOT ");
6833     }
6834
6835     lprs->nSize = sizeof(RASTERIZER_STATUS);
6836     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
6837     if ( subpixel )
6838         lprs->wFlags |= WINE_TT_SUBPIXEL_RENDERING_ENABLED;
6839     lprs->nLanguageID = 0;
6840     return TRUE;
6841 }
6842
6843 /*************************************************************
6844  * freetype_GdiRealizationInfo
6845  */
6846 static BOOL freetype_GdiRealizationInfo( PHYSDEV dev, void *ptr )
6847 {
6848     struct freetype_physdev *physdev = get_freetype_dev( dev );
6849     realization_info_t *info = ptr;
6850
6851     if (!physdev->font)
6852     {
6853         dev = GET_NEXT_PHYSDEV( dev, pGdiRealizationInfo );
6854         return dev->funcs->pGdiRealizationInfo( dev, ptr );
6855     }
6856
6857     FIXME("(%p, %p): stub!\n", physdev->font, info);
6858
6859     info->flags = 1;
6860     if(FT_IS_SCALABLE(physdev->font->ft_face))
6861         info->flags |= 2;
6862
6863     info->cache_num = physdev->font->cache_num;
6864     info->unknown2 = -1;
6865     return TRUE;
6866 }
6867
6868 /*************************************************************************
6869  * Kerning support for TrueType fonts
6870  */
6871 #define MS_KERN_TAG MS_MAKE_TAG('k', 'e', 'r', 'n')
6872
6873 struct TT_kern_table
6874 {
6875     USHORT version;
6876     USHORT nTables;
6877 };
6878
6879 struct TT_kern_subtable
6880 {
6881     USHORT version;
6882     USHORT length;
6883     union
6884     {
6885         USHORT word;
6886         struct
6887         {
6888             USHORT horizontal : 1;
6889             USHORT minimum : 1;
6890             USHORT cross_stream: 1;
6891             USHORT override : 1;
6892             USHORT reserved1 : 4;
6893             USHORT format : 8;
6894         } bits;
6895     } coverage;
6896 };
6897
6898 struct TT_format0_kern_subtable
6899 {
6900     USHORT nPairs;
6901     USHORT searchRange;
6902     USHORT entrySelector;
6903     USHORT rangeShift;
6904 };
6905
6906 struct TT_kern_pair
6907 {
6908     USHORT left;
6909     USHORT right;
6910     short  value;
6911 };
6912
6913 static DWORD parse_format0_kern_subtable(GdiFont *font,
6914                                          const struct TT_format0_kern_subtable *tt_f0_ks,
6915                                          const USHORT *glyph_to_char,
6916                                          KERNINGPAIR *kern_pair, DWORD cPairs)
6917 {
6918     USHORT i, nPairs;
6919     const struct TT_kern_pair *tt_kern_pair;
6920
6921     TRACE("font height %d, units_per_EM %d\n", font->ppem, font->ft_face->units_per_EM);
6922
6923     nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
6924
6925     TRACE("nPairs %u, searchRange %u, entrySelector %u, rangeShift %u\n",
6926            nPairs, GET_BE_WORD(tt_f0_ks->searchRange),
6927            GET_BE_WORD(tt_f0_ks->entrySelector), GET_BE_WORD(tt_f0_ks->rangeShift));
6928
6929     if (!kern_pair || !cPairs)
6930         return nPairs;
6931
6932     tt_kern_pair = (const struct TT_kern_pair *)(tt_f0_ks + 1);
6933
6934     nPairs = min(nPairs, cPairs);
6935
6936     for (i = 0; i < nPairs; i++)
6937     {
6938         kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
6939         kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
6940         /* this algorithm appears to better match what Windows does */
6941         kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
6942         if (kern_pair->iKernAmount < 0)
6943         {
6944             kern_pair->iKernAmount -= font->ft_face->units_per_EM / 2;
6945             kern_pair->iKernAmount -= font->ppem;
6946         }
6947         else if (kern_pair->iKernAmount > 0)
6948         {
6949             kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
6950             kern_pair->iKernAmount += font->ppem;
6951         }
6952         kern_pair->iKernAmount /= font->ft_face->units_per_EM;
6953
6954         TRACE("left %u right %u value %d\n",
6955                kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
6956
6957         kern_pair++;
6958     }
6959     TRACE("copied %u entries\n", nPairs);
6960     return nPairs;
6961 }
6962
6963 /*************************************************************
6964  * freetype_GetKerningPairs
6965  */
6966 static DWORD freetype_GetKerningPairs( PHYSDEV dev, DWORD cPairs, KERNINGPAIR *kern_pair )
6967 {
6968     DWORD length;
6969     void *buf;
6970     const struct TT_kern_table *tt_kern_table;
6971     const struct TT_kern_subtable *tt_kern_subtable;
6972     USHORT i, nTables;
6973     USHORT *glyph_to_char;
6974     GdiFont *font;
6975     struct freetype_physdev *physdev = get_freetype_dev( dev );
6976
6977     if (!(font = physdev->font))
6978     {
6979         dev = GET_NEXT_PHYSDEV( dev, pGetKerningPairs );
6980         return dev->funcs->pGetKerningPairs( dev, cPairs, kern_pair );
6981     }
6982
6983     GDI_CheckNotLock();
6984     EnterCriticalSection( &freetype_cs );
6985     if (font->total_kern_pairs != (DWORD)-1)
6986     {
6987         if (cPairs && kern_pair)
6988         {
6989             cPairs = min(cPairs, font->total_kern_pairs);
6990             memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
6991         }
6992         else cPairs = font->total_kern_pairs;
6993
6994         LeaveCriticalSection( &freetype_cs );
6995         return cPairs;
6996     }
6997
6998     font->total_kern_pairs = 0;
6999
7000     length = get_font_data(font, MS_KERN_TAG, 0, NULL, 0);
7001
7002     if (length == GDI_ERROR)
7003     {
7004         TRACE("no kerning data in the font\n");
7005         LeaveCriticalSection( &freetype_cs );
7006         return 0;
7007     }
7008
7009     buf = HeapAlloc(GetProcessHeap(), 0, length);
7010     if (!buf)
7011     {
7012         WARN("Out of memory\n");
7013         LeaveCriticalSection( &freetype_cs );
7014         return 0;
7015     }
7016
7017     get_font_data(font, MS_KERN_TAG, 0, buf, length);
7018
7019     /* build a glyph index to char code map */
7020     glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
7021     if (!glyph_to_char)
7022     {
7023         WARN("Out of memory allocating a glyph index to char code map\n");
7024         HeapFree(GetProcessHeap(), 0, buf);
7025         LeaveCriticalSection( &freetype_cs );
7026         return 0;
7027     }
7028
7029     if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE)
7030     {
7031         FT_UInt glyph_code;
7032         FT_ULong char_code;
7033
7034         glyph_code = 0;
7035         char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
7036
7037         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
7038                font->ft_face->num_glyphs, glyph_code, char_code);
7039
7040         while (glyph_code)
7041         {
7042             /*TRACE("Char %04lX -> Index %u%s\n", char_code, glyph_code, glyph_to_char[glyph_code] ? "  !" : "" );*/
7043
7044             /* FIXME: This doesn't match what Windows does: it does some fancy
7045              * things with duplicate glyph index to char code mappings, while
7046              * we just avoid overriding existing entries.
7047              */
7048             if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
7049                 glyph_to_char[glyph_code] = (USHORT)char_code;
7050
7051             char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
7052         }
7053     }
7054     else
7055     {
7056         ULONG n;
7057
7058         FIXME("encoding %u not supported\n", font->ft_face->charmap->encoding);
7059         for (n = 0; n <= 65535; n++)
7060             glyph_to_char[n] = (USHORT)n;
7061     }
7062
7063     tt_kern_table = buf;
7064     nTables = GET_BE_WORD(tt_kern_table->nTables);
7065     TRACE("version %u, nTables %u\n",
7066            GET_BE_WORD(tt_kern_table->version), nTables);
7067
7068     tt_kern_subtable = (const struct TT_kern_subtable *)(tt_kern_table + 1);
7069
7070     for (i = 0; i < nTables; i++)
7071     {
7072         struct TT_kern_subtable tt_kern_subtable_copy;
7073
7074         tt_kern_subtable_copy.version = GET_BE_WORD(tt_kern_subtable->version);
7075         tt_kern_subtable_copy.length = GET_BE_WORD(tt_kern_subtable->length);
7076         tt_kern_subtable_copy.coverage.word = GET_BE_WORD(tt_kern_subtable->coverage.word);
7077
7078         TRACE("version %u, length %u, coverage %u, subtable format %u\n",
7079                tt_kern_subtable_copy.version, tt_kern_subtable_copy.length,
7080                tt_kern_subtable_copy.coverage.word, tt_kern_subtable_copy.coverage.bits.format);
7081
7082         /* According to the TrueType specification this is the only format
7083          * that will be properly interpreted by Windows and OS/2
7084          */
7085         if (tt_kern_subtable_copy.coverage.bits.format == 0)
7086         {
7087             DWORD new_chunk, old_total = font->total_kern_pairs;
7088
7089             new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
7090                                                     glyph_to_char, NULL, 0);
7091             font->total_kern_pairs += new_chunk;
7092
7093             if (!font->kern_pairs)
7094                 font->kern_pairs = HeapAlloc(GetProcessHeap(), 0,
7095                                              font->total_kern_pairs * sizeof(*font->kern_pairs));
7096             else
7097                 font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs,
7098                                                font->total_kern_pairs * sizeof(*font->kern_pairs));
7099
7100             parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
7101                         glyph_to_char, font->kern_pairs + old_total, new_chunk);
7102         }
7103         else
7104             TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format);
7105
7106         tt_kern_subtable = (const struct TT_kern_subtable *)((const char *)tt_kern_subtable + tt_kern_subtable_copy.length);
7107     }
7108
7109     HeapFree(GetProcessHeap(), 0, glyph_to_char);
7110     HeapFree(GetProcessHeap(), 0, buf);
7111
7112     if (cPairs && kern_pair)
7113     {
7114         cPairs = min(cPairs, font->total_kern_pairs);
7115         memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
7116     }
7117     else cPairs = font->total_kern_pairs;
7118
7119     LeaveCriticalSection( &freetype_cs );
7120     return cPairs;
7121 }
7122
7123 static const struct gdi_dc_funcs freetype_funcs =
7124 {
7125     NULL,                               /* pAbortDoc */
7126     NULL,                               /* pAbortPath */
7127     NULL,                               /* pAlphaBlend */
7128     NULL,                               /* pAngleArc */
7129     NULL,                               /* pArc */
7130     NULL,                               /* pArcTo */
7131     NULL,                               /* pBeginPath */
7132     NULL,                               /* pBlendImage */
7133     NULL,                               /* pChoosePixelFormat */
7134     NULL,                               /* pChord */
7135     NULL,                               /* pCloseFigure */
7136     NULL,                               /* pCreateBitmap */
7137     NULL,                               /* pCreateCompatibleDC */
7138     freetype_CreateDC,                  /* pCreateDC */
7139     NULL,                               /* pCreateDIBSection */
7140     NULL,                               /* pDeleteBitmap */
7141     freetype_DeleteDC,                  /* pDeleteDC */
7142     NULL,                               /* pDeleteObject */
7143     NULL,                               /* pDescribePixelFormat */
7144     NULL,                               /* pDeviceCapabilities */
7145     NULL,                               /* pEllipse */
7146     NULL,                               /* pEndDoc */
7147     NULL,                               /* pEndPage */
7148     NULL,                               /* pEndPath */
7149     freetype_EnumFonts,                 /* pEnumFonts */
7150     NULL,                               /* pEnumICMProfiles */
7151     NULL,                               /* pExcludeClipRect */
7152     NULL,                               /* pExtDeviceMode */
7153     NULL,                               /* pExtEscape */
7154     NULL,                               /* pExtFloodFill */
7155     NULL,                               /* pExtSelectClipRgn */
7156     NULL,                               /* pExtTextOut */
7157     NULL,                               /* pFillPath */
7158     NULL,                               /* pFillRgn */
7159     NULL,                               /* pFlattenPath */
7160     freetype_FontIsLinked,              /* pFontIsLinked */
7161     NULL,                               /* pFrameRgn */
7162     NULL,                               /* pGdiComment */
7163     freetype_GdiRealizationInfo,        /* pGdiRealizationInfo */
7164     freetype_GetCharABCWidths,          /* pGetCharABCWidths */
7165     freetype_GetCharABCWidthsI,         /* pGetCharABCWidthsI */
7166     freetype_GetCharWidth,              /* pGetCharWidth */
7167     NULL,                               /* pGetDeviceCaps */
7168     NULL,                               /* pGetDeviceGammaRamp */
7169     freetype_GetFontData,               /* pGetFontData */
7170     freetype_GetFontUnicodeRanges,      /* pGetFontUnicodeRanges */
7171     freetype_GetGlyphIndices,           /* pGetGlyphIndices */
7172     freetype_GetGlyphOutline,           /* pGetGlyphOutline */
7173     NULL,                               /* pGetICMProfile */
7174     NULL,                               /* pGetImage */
7175     freetype_GetKerningPairs,           /* pGetKerningPairs */
7176     NULL,                               /* pGetNearestColor */
7177     freetype_GetOutlineTextMetrics,     /* pGetOutlineTextMetrics */
7178     NULL,                               /* pGetPixel */
7179     NULL,                               /* pGetPixelFormat */
7180     NULL,                               /* pGetSystemPaletteEntries */
7181     freetype_GetTextCharsetInfo,        /* pGetTextCharsetInfo */
7182     freetype_GetTextExtentExPoint,      /* pGetTextExtentExPoint */
7183     freetype_GetTextExtentExPointI,     /* pGetTextExtentExPointI */
7184     freetype_GetTextFace,               /* pGetTextFace */
7185     freetype_GetTextMetrics,            /* pGetTextMetrics */
7186     NULL,                               /* pIntersectClipRect */
7187     NULL,                               /* pInvertRgn */
7188     NULL,                               /* pLineTo */
7189     NULL,                               /* pModifyWorldTransform */
7190     NULL,                               /* pMoveTo */
7191     NULL,                               /* pOffsetClipRgn */
7192     NULL,                               /* pOffsetViewportOrg */
7193     NULL,                               /* pOffsetWindowOrg */
7194     NULL,                               /* pPaintRgn */
7195     NULL,                               /* pPatBlt */
7196     NULL,                               /* pPie */
7197     NULL,                               /* pPolyBezier */
7198     NULL,                               /* pPolyBezierTo */
7199     NULL,                               /* pPolyDraw */
7200     NULL,                               /* pPolyPolygon */
7201     NULL,                               /* pPolyPolyline */
7202     NULL,                               /* pPolygon */
7203     NULL,                               /* pPolyline */
7204     NULL,                               /* pPolylineTo */
7205     NULL,                               /* pPutImage */
7206     NULL,                               /* pRealizeDefaultPalette */
7207     NULL,                               /* pRealizePalette */
7208     NULL,                               /* pRectangle */
7209     NULL,                               /* pResetDC */
7210     NULL,                               /* pRestoreDC */
7211     NULL,                               /* pRoundRect */
7212     NULL,                               /* pSaveDC */
7213     NULL,                               /* pScaleViewportExt */
7214     NULL,                               /* pScaleWindowExt */
7215     NULL,                               /* pSelectBitmap */
7216     NULL,                               /* pSelectBrush */
7217     NULL,                               /* pSelectClipPath */
7218     freetype_SelectFont,                /* pSelectFont */
7219     NULL,                               /* pSelectPalette */
7220     NULL,                               /* pSelectPen */
7221     NULL,                               /* pSetArcDirection */
7222     NULL,                               /* pSetBkColor */
7223     NULL,                               /* pSetBkMode */
7224     NULL,                               /* pSetDCBrushColor */
7225     NULL,                               /* pSetDCPenColor */
7226     NULL,                               /* pSetDIBColorTable */
7227     NULL,                               /* pSetDIBitsToDevice */
7228     NULL,                               /* pSetDeviceClipping */
7229     NULL,                               /* pSetDeviceGammaRamp */
7230     NULL,                               /* pSetLayout */
7231     NULL,                               /* pSetMapMode */
7232     NULL,                               /* pSetMapperFlags */
7233     NULL,                               /* pSetPixel */
7234     NULL,                               /* pSetPixelFormat */
7235     NULL,                               /* pSetPolyFillMode */
7236     NULL,                               /* pSetROP2 */
7237     NULL,                               /* pSetRelAbs */
7238     NULL,                               /* pSetStretchBltMode */
7239     NULL,                               /* pSetTextAlign */
7240     NULL,                               /* pSetTextCharacterExtra */
7241     NULL,                               /* pSetTextColor */
7242     NULL,                               /* pSetTextJustification */
7243     NULL,                               /* pSetViewportExt */
7244     NULL,                               /* pSetViewportOrg */
7245     NULL,                               /* pSetWindowExt */
7246     NULL,                               /* pSetWindowOrg */
7247     NULL,                               /* pSetWorldTransform */
7248     NULL,                               /* pStartDoc */
7249     NULL,                               /* pStartPage */
7250     NULL,                               /* pStretchBlt */
7251     NULL,                               /* pStretchDIBits */
7252     NULL,                               /* pStrokeAndFillPath */
7253     NULL,                               /* pStrokePath */
7254     NULL,                               /* pSwapBuffers */
7255     NULL,                               /* pUnrealizePalette */
7256     NULL,                               /* pWidenPath */
7257     /* OpenGL not supported */
7258 };
7259
7260 #else /* HAVE_FREETYPE */
7261
7262 /*************************************************************************/
7263
7264 BOOL WineEngInit(void)
7265 {
7266     return FALSE;
7267 }
7268 BOOL WineEngDestroyFontInstance(HFONT hfont)
7269 {
7270     return FALSE;
7271 }
7272
7273 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
7274 {
7275     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
7276     return 1;
7277 }
7278
7279 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
7280 {
7281     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
7282     return TRUE;
7283 }
7284
7285 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
7286 {
7287     FIXME("(%p, %u, %p, %p): stub\n", pbFont, cbFont, pdv, pcFonts);
7288     return NULL;
7289 }
7290
7291 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
7292 {
7293     return FALSE;
7294 }
7295
7296 /*************************************************************************
7297  *             GetRasterizerCaps   (GDI32.@)
7298  */
7299 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
7300 {
7301     lprs->nSize = sizeof(RASTERIZER_STATUS);
7302     lprs->wFlags = 0;
7303     lprs->nLanguageID = 0;
7304     return TRUE;
7305 }
7306
7307 #endif /* HAVE_FREETYPE */