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