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