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