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