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