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