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