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