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