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