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