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