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