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