Release 1.5.29.
[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     LONG avgAdvance = 0;
5885     FT_Fixed em_scale;
5886
5887     TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
5888           buflen, buf, lpmat);
5889
5890     TRACE("font transform %f %f %f %f\n",
5891           font->font_desc.matrix.eM11, font->font_desc.matrix.eM12,
5892           font->font_desc.matrix.eM21, font->font_desc.matrix.eM22);
5893
5894     if(format & GGO_GLYPH_INDEX) {
5895         glyph_index = get_GSUB_vert_glyph(incoming_font,glyph);
5896         original_index = glyph;
5897         format &= ~GGO_GLYPH_INDEX;
5898     } else {
5899         get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index);
5900         ft_face = font->ft_face;
5901         original_index = glyph_index;
5902     }
5903
5904     if(format & GGO_UNHINTED) {
5905         load_flags |= FT_LOAD_NO_HINTING;
5906         format &= ~GGO_UNHINTED;
5907     }
5908
5909     /* tategaki never appears to happen to lower glyph index */
5910     if (glyph_index < TATEGAKI_LOWER_BOUND )
5911         tategaki = FALSE;
5912
5913     if(original_index >= font->gmsize * GM_BLOCK_SIZE) {
5914         font->gmsize = (original_index / GM_BLOCK_SIZE + 1);
5915         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
5916                                font->gmsize * sizeof(GM*));
5917     } else {
5918         if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL &&
5919             FONT_GM(font,original_index)->init && is_identity_MAT2(lpmat))
5920         {
5921             *lpgm = FONT_GM(font,original_index)->gm;
5922             *abc = FONT_GM(font,original_index)->abc;
5923             TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
5924                   wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
5925                   lpgm->gmCellIncX, lpgm->gmCellIncY);
5926             return 1; /* FIXME */
5927         }
5928     }
5929
5930     if (!font->gm[original_index / GM_BLOCK_SIZE])
5931         font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
5932
5933     /* Scaling factor */
5934     if (font->aveWidth)
5935     {
5936         TEXTMETRICW tm;
5937
5938         get_text_metrics(font, &tm);
5939
5940         widthRatio = (double)font->aveWidth;
5941         widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5942     }
5943     else
5944         widthRatio = font->scale_y;
5945
5946     /* Scaling transform */
5947     if (widthRatio != 1.0 || font->scale_y != 1.0)
5948     {
5949         FT_Matrix scaleMat;
5950         scaleMat.xx = FT_FixedFromFloat(widthRatio);
5951         scaleMat.xy = 0;
5952         scaleMat.yx = 0;
5953         scaleMat.yy = FT_FixedFromFloat(font->scale_y);
5954
5955         pFT_Matrix_Multiply(&scaleMat, &transMat);
5956         needsTransform = TRUE;
5957     }
5958
5959     /* Slant transform */
5960     if (font->fake_italic) {
5961         FT_Matrix slantMat;
5962         
5963         slantMat.xx = (1 << 16);
5964         slantMat.xy = ((1 << 16) >> 2);
5965         slantMat.yx = 0;
5966         slantMat.yy = (1 << 16);
5967         pFT_Matrix_Multiply(&slantMat, &transMat);
5968         needsTransform = TRUE;
5969     }
5970
5971     /* Rotation transform */
5972     transMatUnrotated = transMat;
5973     if(font->orientation && !tategaki) {
5974         FT_Matrix rotationMat;
5975         FT_Vector vecAngle;
5976         angle = FT_FixedFromFloat((double)font->orientation / 10.0);
5977         pFT_Vector_Unit(&vecAngle, angle);
5978         rotationMat.xx = vecAngle.x;
5979         rotationMat.xy = -vecAngle.y;
5980         rotationMat.yx = -rotationMat.xy;
5981         rotationMat.yy = rotationMat.xx;
5982         
5983         pFT_Matrix_Multiply(&rotationMat, &transMat);
5984         needsTransform = TRUE;
5985     }
5986
5987     /* World transform */
5988     if (!is_identity_FMAT2(&font->font_desc.matrix))
5989     {
5990         FT_Matrix worldMat;
5991         worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11);
5992         worldMat.xy = -FT_FixedFromFloat(font->font_desc.matrix.eM21);
5993         worldMat.yx = -FT_FixedFromFloat(font->font_desc.matrix.eM12);
5994         worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22);
5995         pFT_Matrix_Multiply(&worldMat, &transMat);
5996         pFT_Matrix_Multiply(&worldMat, &transMatUnrotated);
5997         needsTransform = TRUE;
5998     }
5999
6000     /* Extra transformation specified by caller */
6001     if (!is_identity_MAT2(lpmat))
6002     {
6003         FT_Matrix extraMat;
6004         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
6005         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
6006         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
6007         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
6008         pFT_Matrix_Multiply(&extraMat, &transMat);
6009         pFT_Matrix_Multiply(&extraMat, &transMatUnrotated);
6010         needsTransform = TRUE;
6011     }
6012
6013     if (needsTransform || format != GGO_BITMAP) load_flags |= FT_LOAD_NO_BITMAP;
6014
6015     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
6016
6017     if(err) {
6018         WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
6019         return GDI_ERROR;
6020     }
6021
6022     if(FT_IS_SCALABLE(incoming_font->ft_face)) {
6023         TEXTMETRICW tm;
6024         if (get_text_metrics(incoming_font, &tm) &&
6025             !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
6026             em_scale = MulDiv(incoming_font->ppem, 1 << 16, incoming_font->ft_face->units_per_EM);
6027             avgAdvance = pFT_MulFix(incoming_font->ntmAvgWidth, em_scale);
6028             if (avgAdvance &&
6029                 (ft_face->glyph->metrics.horiAdvance+63) >> 6 == pFT_MulFix(incoming_font->ntmAvgWidth*2, em_scale))
6030                 TRACE("Fixed-pitch full-width character detected\n");
6031             else
6032                 avgAdvance = 0; /* cancel this feature */
6033         }
6034     }
6035
6036     if(!needsTransform) {
6037         left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64;
6038         right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64;
6039         if (!avgAdvance)
6040             adv = (INT)(ft_face->glyph->metrics.horiAdvance + 63) >> 6;
6041         else
6042             adv = (INT)avgAdvance * 2;
6043
6044         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
6045         bottom = (ft_face->glyph->metrics.horiBearingY -
6046                   ft_face->glyph->metrics.height) & -64;
6047         lpgm->gmCellIncX = adv;
6048         lpgm->gmCellIncY = 0;
6049     } else {
6050         INT xc, yc;
6051         FT_Vector vec;
6052
6053         left = right = 0;
6054
6055         for(xc = 0; xc < 2; xc++) {
6056             for(yc = 0; yc < 2; yc++) {
6057                 vec.x = (ft_face->glyph->metrics.horiBearingX +
6058                   xc * ft_face->glyph->metrics.width);
6059                 vec.y = ft_face->glyph->metrics.horiBearingY -
6060                   yc * ft_face->glyph->metrics.height;
6061                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
6062                 pFT_Vector_Transform(&vec, &transMat);
6063                 if(xc == 0 && yc == 0) {
6064                     left = right = vec.x;
6065                     top = bottom = vec.y;
6066                 } else {
6067                     if(vec.x < left) left = vec.x;
6068                     else if(vec.x > right) right = vec.x;
6069                     if(vec.y < bottom) bottom = vec.y;
6070                     else if(vec.y > top) top = vec.y;
6071                 }
6072             }
6073         }
6074         left = left & -64;
6075         right = (right + 63) & -64;
6076         bottom = bottom & -64;
6077         top = (top + 63) & -64;
6078
6079         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
6080         vec.x = ft_face->glyph->metrics.horiAdvance;
6081         vec.y = 0;
6082         pFT_Vector_Transform(&vec, &transMat);
6083         lpgm->gmCellIncY = -((vec.y+63) >> 6);
6084         if (!avgAdvance || vec.y)
6085             lpgm->gmCellIncX = (vec.x+63) >> 6;
6086         else {
6087             vec.x = incoming_font->ntmAvgWidth;
6088             vec.y = 0;
6089             pFT_Vector_Transform(&vec, &transMat);
6090             lpgm->gmCellIncX = pFT_MulFix(vec.x, em_scale) * 2;
6091         }
6092
6093         vec.x = ft_face->glyph->metrics.horiAdvance;
6094         vec.y = 0;
6095         pFT_Vector_Transform(&vec, &transMatUnrotated);
6096         if (!avgAdvance || vec.y)
6097             adv = (vec.x+63) >> 6;
6098         else {
6099             vec.x = incoming_font->ntmAvgWidth;
6100             vec.y = 0;
6101             pFT_Vector_Transform(&vec, &transMatUnrotated);
6102             adv = pFT_MulFix(vec.x, em_scale) * 2;
6103         }
6104     }
6105
6106     lpgm->gmBlackBoxX = (right - left) >> 6;
6107     lpgm->gmBlackBoxY = (top - bottom) >> 6;
6108     lpgm->gmptGlyphOrigin.x = left >> 6;
6109     lpgm->gmptGlyphOrigin.y = top >> 6;
6110     abc->abcA = left >> 6;
6111     abc->abcB = (right - left) >> 6;
6112     abc->abcC = adv - abc->abcA - abc->abcB;
6113
6114     TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
6115           wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
6116           lpgm->gmCellIncX, lpgm->gmCellIncY);
6117
6118     if ((format == GGO_METRICS || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
6119         is_identity_MAT2(lpmat)) /* don't cache custom transforms */
6120     {
6121         FONT_GM(font,original_index)->gm = *lpgm;
6122         FONT_GM(font,original_index)->abc = *abc;
6123         FONT_GM(font,original_index)->init = TRUE;
6124     }
6125
6126     if(format == GGO_METRICS)
6127     {
6128         return 1; /* FIXME */
6129     }
6130
6131     if(ft_face->glyph->format != ft_glyph_format_outline &&
6132        (format == GGO_NATIVE || format == GGO_BEZIER))
6133     {
6134         TRACE("loaded a bitmap\n");
6135         return GDI_ERROR;
6136     }
6137
6138     switch(format) {
6139     case GGO_BITMAP:
6140         width = lpgm->gmBlackBoxX;
6141         height = lpgm->gmBlackBoxY;
6142         pitch = ((width + 31) >> 5) << 2;
6143         needed = pitch * height;
6144
6145         if(!buf || !buflen) break;
6146
6147         switch(ft_face->glyph->format) {
6148         case ft_glyph_format_bitmap:
6149           {
6150             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
6151             INT w = min( pitch, (ft_face->glyph->bitmap.width + 7) >> 3 );
6152             INT h = min( height, ft_face->glyph->bitmap.rows );
6153             while(h--) {
6154                 memcpy(dst, src, w);
6155                 src += ft_face->glyph->bitmap.pitch;
6156                 dst += pitch;
6157             }
6158             break;
6159           }
6160
6161         case ft_glyph_format_outline:
6162             ft_bitmap.width = width;
6163             ft_bitmap.rows = height;
6164             ft_bitmap.pitch = pitch;
6165             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
6166             ft_bitmap.buffer = buf;
6167
6168             if(needsTransform)
6169                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
6170
6171             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
6172
6173             /* Note: FreeType will only set 'black' bits for us. */
6174             memset(buf, 0, needed);
6175             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
6176             break;
6177
6178         default:
6179             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
6180             return GDI_ERROR;
6181         }
6182         break;
6183
6184     case GGO_GRAY2_BITMAP:
6185     case GGO_GRAY4_BITMAP:
6186     case GGO_GRAY8_BITMAP:
6187     case WINE_GGO_GRAY16_BITMAP:
6188       {
6189         unsigned int max_level, row, col;
6190         BYTE *start, *ptr;
6191
6192         width = lpgm->gmBlackBoxX;
6193         height = lpgm->gmBlackBoxY;
6194         pitch = (width + 3) / 4 * 4;
6195         needed = pitch * height;
6196
6197         if(!buf || !buflen) break;
6198
6199         max_level = get_max_level( format );
6200
6201         switch(ft_face->glyph->format) {
6202         case ft_glyph_format_bitmap:
6203           {
6204             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
6205             INT h = min( height, ft_face->glyph->bitmap.rows );
6206             INT x;
6207             memset( buf, 0, needed );
6208             while(h--) {
6209                 for(x = 0; x < pitch && x < ft_face->glyph->bitmap.width; x++)
6210                     if (src[x / 8] & masks[x % 8]) dst[x] = max_level;
6211                 src += ft_face->glyph->bitmap.pitch;
6212                 dst += pitch;
6213             }
6214             return needed;
6215           }
6216         case ft_glyph_format_outline:
6217           {
6218             ft_bitmap.width = width;
6219             ft_bitmap.rows = height;
6220             ft_bitmap.pitch = pitch;
6221             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
6222             ft_bitmap.buffer = buf;
6223
6224             if(needsTransform)
6225                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
6226
6227             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
6228
6229             memset(ft_bitmap.buffer, 0, buflen);
6230
6231             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
6232
6233             if (max_level != 255)
6234             {
6235                 for (row = 0, start = buf; row < height; row++)
6236                 {
6237                     for (col = 0, ptr = start; col < width; col++, ptr++)
6238                         *ptr = (((int)*ptr) * (max_level + 1)) / 256;
6239                     start += pitch;
6240                 }
6241             }
6242             return needed;
6243           }
6244
6245         default:
6246             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
6247             return GDI_ERROR;
6248         }
6249         break;
6250       }
6251
6252     case WINE_GGO_HRGB_BITMAP:
6253     case WINE_GGO_HBGR_BITMAP:
6254     case WINE_GGO_VRGB_BITMAP:
6255     case WINE_GGO_VBGR_BITMAP:
6256 #ifdef HAVE_FREETYPE_FTLCDFIL_H
6257       {
6258         switch (ft_face->glyph->format)
6259         {
6260         case FT_GLYPH_FORMAT_BITMAP:
6261           {
6262             BYTE *src, *dst;
6263             INT src_pitch, x;
6264
6265             width  = lpgm->gmBlackBoxX;
6266             height = lpgm->gmBlackBoxY;
6267             pitch  = width * 4;
6268             needed = pitch * height;
6269
6270             if (!buf || !buflen) break;
6271
6272             memset(buf, 0, buflen);
6273             dst = buf;
6274             src = ft_face->glyph->bitmap.buffer;
6275             src_pitch = ft_face->glyph->bitmap.pitch;
6276
6277             height = min( height, ft_face->glyph->bitmap.rows );
6278             while ( height-- )
6279             {
6280                 for (x = 0; x < width && x < ft_face->glyph->bitmap.width; x++)
6281                 {
6282                     if ( src[x / 8] & masks[x % 8] )
6283                         ((unsigned int *)dst)[x] = ~0u;
6284                 }
6285                 src += src_pitch;
6286                 dst += pitch;
6287             }
6288
6289             break;
6290           }
6291
6292         case FT_GLYPH_FORMAT_OUTLINE:
6293           {
6294             unsigned int *dst;
6295             BYTE *src;
6296             INT x, src_pitch, src_width, src_height, rgb_interval, hmul, vmul;
6297             INT x_shift, y_shift;
6298             BOOL rgb;
6299             FT_LcdFilter lcdfilter = FT_LCD_FILTER_DEFAULT;
6300             FT_Render_Mode render_mode =
6301                 (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_HBGR_BITMAP)?
6302                     FT_RENDER_MODE_LCD: FT_RENDER_MODE_LCD_V;
6303
6304             if ( lcdfilter == FT_LCD_FILTER_DEFAULT || lcdfilter == FT_LCD_FILTER_LIGHT )
6305             {
6306                 if ( render_mode == FT_RENDER_MODE_LCD)
6307                 {
6308                     lpgm->gmBlackBoxX += 2;
6309                     lpgm->gmptGlyphOrigin.x -= 1;
6310                 }
6311                 else
6312                 {
6313                     lpgm->gmBlackBoxY += 2;
6314                     lpgm->gmptGlyphOrigin.y += 1;
6315                 }
6316             }
6317
6318             width  = lpgm->gmBlackBoxX;
6319             height = lpgm->gmBlackBoxY;
6320             pitch  = width * 4;
6321             needed = pitch * height;
6322
6323             if (!buf || !buflen) break;
6324
6325             memset(buf, 0, buflen);
6326             dst = buf;
6327             rgb = (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_VRGB_BITMAP);
6328
6329             if ( needsTransform )
6330                 pFT_Outline_Transform (&ft_face->glyph->outline, &transMat);
6331
6332             if ( pFT_Library_SetLcdFilter )
6333                 pFT_Library_SetLcdFilter( library, lcdfilter );
6334             pFT_Render_Glyph (ft_face->glyph, render_mode);
6335
6336             src = ft_face->glyph->bitmap.buffer;
6337             src_pitch = ft_face->glyph->bitmap.pitch;
6338             src_width = ft_face->glyph->bitmap.width;
6339             src_height = ft_face->glyph->bitmap.rows;
6340
6341             if ( render_mode == FT_RENDER_MODE_LCD)
6342             {
6343                 rgb_interval = 1;
6344                 hmul = 3;
6345                 vmul = 1;
6346             }
6347             else
6348             {
6349                 rgb_interval = src_pitch;
6350                 hmul = 1;
6351                 vmul = 3;
6352             }
6353
6354             x_shift = ft_face->glyph->bitmap_left - lpgm->gmptGlyphOrigin.x;
6355             if ( x_shift < 0 ) x_shift = 0;
6356             if ( x_shift + (src_width / hmul) > width )
6357                 x_shift = width - (src_width / hmul);
6358
6359             y_shift = lpgm->gmptGlyphOrigin.y - ft_face->glyph->bitmap_top;
6360             if ( y_shift < 0 ) y_shift = 0;
6361             if ( y_shift + (src_height / vmul) > height )
6362                 y_shift = height - (src_height / vmul);
6363
6364             dst += x_shift + y_shift * ( pitch / 4 );
6365             while ( src_height )
6366             {
6367                 for ( x = 0; x < src_width / hmul; x++ )
6368                 {
6369                     if ( rgb )
6370                     {
6371                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 0] << 16) |
6372                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
6373                                  ((unsigned int)src[hmul * x + rgb_interval * 2] <<  0) |
6374                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
6375                     }
6376                     else
6377                     {
6378                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 2] << 16) |
6379                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
6380                                  ((unsigned int)src[hmul * x + rgb_interval * 0] <<  0) |
6381                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
6382                     }
6383                 }
6384                 src += src_pitch * vmul;
6385                 dst += pitch / 4;
6386                 src_height -= vmul;
6387             }
6388
6389             break;
6390           }
6391
6392         default:
6393             FIXME ("loaded glyph format %x\n", ft_face->glyph->format);
6394             return GDI_ERROR;
6395         }
6396
6397         break;
6398       }
6399 #else
6400       return GDI_ERROR;
6401 #endif
6402
6403     case GGO_NATIVE:
6404       {
6405         int contour, point = 0, first_pt;
6406         FT_Outline *outline = &ft_face->glyph->outline;
6407         TTPOLYGONHEADER *pph;
6408         TTPOLYCURVE *ppc;
6409         DWORD pph_start, cpfx, type;
6410
6411         if(buflen == 0) buf = NULL;
6412
6413         if (needsTransform && buf) {
6414                 pFT_Outline_Transform(outline, &transMat);
6415         }
6416
6417         for(contour = 0; contour < outline->n_contours; contour++) {
6418             /* Ignore contours containing one point */
6419             if(point == outline->contours[contour]) {
6420                 point++;
6421                 continue;
6422             }
6423
6424             pph_start = needed;
6425             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
6426             first_pt = point;
6427             if(buf) {
6428                 pph->dwType = TT_POLYGON_TYPE;
6429                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
6430             }
6431             needed += sizeof(*pph);
6432             point++;
6433             while(point <= outline->contours[contour]) {
6434                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
6435                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
6436                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
6437                 cpfx = 0;
6438                 do {
6439                     if(buf)
6440                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
6441                     cpfx++;
6442                     point++;
6443                 } while(point <= outline->contours[contour] &&
6444                         (outline->tags[point] & FT_Curve_Tag_On) ==
6445                         (outline->tags[point-1] & FT_Curve_Tag_On));
6446                 /* At the end of a contour Windows adds the start point, but
6447                    only for Beziers */
6448                 if(point > outline->contours[contour] &&
6449                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
6450                     if(buf)
6451                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
6452                     cpfx++;
6453                 } else if(point <= outline->contours[contour] &&
6454                           outline->tags[point] & FT_Curve_Tag_On) {
6455                   /* add closing pt for bezier */
6456                     if(buf)
6457                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
6458                     cpfx++;
6459                     point++;
6460                 }
6461                 if(buf) {
6462                     ppc->wType = type;
6463                     ppc->cpfx = cpfx;
6464                 }
6465                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
6466             }
6467             if(buf)
6468                 pph->cb = needed - pph_start;
6469         }
6470         break;
6471       }
6472     case GGO_BEZIER:
6473       {
6474         /* Convert the quadratic Beziers to cubic Beziers.
6475            The parametric eqn for a cubic Bezier is, from PLRM:
6476            r(t) = at^3 + bt^2 + ct + r0
6477            with the control points:
6478            r1 = r0 + c/3
6479            r2 = r1 + (c + b)/3
6480            r3 = r0 + c + b + a
6481
6482            A quadratic Bezier has the form:
6483            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
6484
6485            So equating powers of t leads to:
6486            r1 = 2/3 p1 + 1/3 p0
6487            r2 = 2/3 p1 + 1/3 p2
6488            and of course r0 = p0, r3 = p2
6489         */
6490
6491         int contour, point = 0, first_pt;
6492         FT_Outline *outline = &ft_face->glyph->outline;
6493         TTPOLYGONHEADER *pph;
6494         TTPOLYCURVE *ppc;
6495         DWORD pph_start, cpfx, type;
6496         FT_Vector cubic_control[4];
6497         if(buflen == 0) buf = NULL;
6498
6499         if (needsTransform && buf) {
6500                 pFT_Outline_Transform(outline, &transMat);
6501         }
6502
6503         for(contour = 0; contour < outline->n_contours; contour++) {
6504             pph_start = needed;
6505             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
6506             first_pt = point;
6507             if(buf) {
6508                 pph->dwType = TT_POLYGON_TYPE;
6509                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
6510             }
6511             needed += sizeof(*pph);
6512             point++;
6513             while(point <= outline->contours[contour]) {
6514                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
6515                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
6516                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
6517                 cpfx = 0;
6518                 do {
6519                     if(type == TT_PRIM_LINE) {
6520                         if(buf)
6521                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
6522                         cpfx++;
6523                         point++;
6524                     } else {
6525                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
6526                          so cpfx = 3n */
6527
6528                       /* FIXME: Possible optimization in endpoint calculation
6529                          if there are two consecutive curves */
6530                         cubic_control[0] = outline->points[point-1];
6531                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
6532                             cubic_control[0].x += outline->points[point].x + 1;
6533                             cubic_control[0].y += outline->points[point].y + 1;
6534                             cubic_control[0].x >>= 1;
6535                             cubic_control[0].y >>= 1;
6536                         }
6537                         if(point+1 > outline->contours[contour])
6538                             cubic_control[3] = outline->points[first_pt];
6539                         else {
6540                             cubic_control[3] = outline->points[point+1];
6541                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
6542                                 cubic_control[3].x += outline->points[point].x + 1;
6543                                 cubic_control[3].y += outline->points[point].y + 1;
6544                                 cubic_control[3].x >>= 1;
6545                                 cubic_control[3].y >>= 1;
6546                             }
6547                         }
6548                         /* r1 = 1/3 p0 + 2/3 p1
6549                            r2 = 1/3 p2 + 2/3 p1 */
6550                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
6551                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
6552                         cubic_control[2] = cubic_control[1];
6553                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
6554                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
6555                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
6556                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
6557                         if(buf) {
6558                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
6559                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
6560                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
6561                         }
6562                         cpfx += 3;
6563                         point++;
6564                     }
6565                 } while(point <= outline->contours[contour] &&
6566                         (outline->tags[point] & FT_Curve_Tag_On) ==
6567                         (outline->tags[point-1] & FT_Curve_Tag_On));
6568                 /* At the end of a contour Windows adds the start point,
6569                    but only for Beziers and we've already done that.
6570                 */
6571                 if(point <= outline->contours[contour] &&
6572                    outline->tags[point] & FT_Curve_Tag_On) {
6573                   /* This is the closing pt of a bezier, but we've already
6574                      added it, so just inc point and carry on */
6575                     point++;
6576                 }
6577                 if(buf) {
6578                     ppc->wType = type;
6579                     ppc->cpfx = cpfx;
6580                 }
6581                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
6582             }
6583             if(buf)
6584                 pph->cb = needed - pph_start;
6585         }
6586         break;
6587       }
6588
6589     default:
6590         FIXME("Unsupported format %d\n", format);
6591         return GDI_ERROR;
6592     }
6593     return needed;
6594 }
6595
6596 static BOOL get_bitmap_text_metrics(GdiFont *font)
6597 {
6598     FT_Face ft_face = font->ft_face;
6599     FT_WinFNT_HeaderRec winfnt_header;
6600     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
6601     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
6602     font->potm->otmSize = size;
6603
6604 #define TM font->potm->otmTextMetrics
6605     if(!pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
6606     {
6607         TM.tmHeight = winfnt_header.pixel_height;
6608         TM.tmAscent = winfnt_header.ascent;
6609         TM.tmDescent = TM.tmHeight - TM.tmAscent;
6610         TM.tmInternalLeading = winfnt_header.internal_leading;
6611         TM.tmExternalLeading = winfnt_header.external_leading;
6612         TM.tmAveCharWidth = winfnt_header.avg_width;
6613         TM.tmMaxCharWidth = winfnt_header.max_width;
6614         TM.tmWeight = winfnt_header.weight;
6615         TM.tmOverhang = 0;
6616         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
6617         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
6618         TM.tmFirstChar = winfnt_header.first_char;
6619         TM.tmLastChar = winfnt_header.last_char;
6620         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
6621         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
6622         TM.tmItalic = winfnt_header.italic;
6623         TM.tmUnderlined = font->underline;
6624         TM.tmStruckOut = font->strikeout;
6625         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
6626         TM.tmCharSet = winfnt_header.charset;
6627     }
6628     else
6629     {
6630         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
6631         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
6632         TM.tmHeight = TM.tmAscent + TM.tmDescent;
6633         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
6634         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
6635         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
6636         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
6637         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
6638         TM.tmOverhang = 0;
6639         TM.tmDigitizedAspectX = 96; /* FIXME */
6640         TM.tmDigitizedAspectY = 96; /* FIXME */
6641         TM.tmFirstChar = 1;
6642         TM.tmLastChar = 255;
6643         TM.tmDefaultChar = 32;
6644         TM.tmBreakChar = 32;
6645         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
6646         TM.tmUnderlined = font->underline;
6647         TM.tmStruckOut = font->strikeout;
6648         /* NB inverted meaning of TMPF_FIXED_PITCH */
6649         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
6650         TM.tmCharSet = font->charset;
6651     }
6652 #undef TM
6653
6654     return TRUE;
6655 }
6656
6657
6658 static void scale_font_metrics(const GdiFont *font, LPTEXTMETRICW ptm)
6659 {
6660     double scale_x, scale_y;
6661
6662     if (font->aveWidth)
6663     {
6664         scale_x = (double)font->aveWidth;
6665         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
6666     }
6667     else
6668         scale_x = font->scale_y;
6669
6670     scale_x *= fabs(font->font_desc.matrix.eM11);
6671     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
6672
6673 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
6674 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
6675
6676     SCALE_Y(ptm->tmHeight);
6677     SCALE_Y(ptm->tmAscent);
6678     SCALE_Y(ptm->tmDescent);
6679     SCALE_Y(ptm->tmInternalLeading);
6680     SCALE_Y(ptm->tmExternalLeading);
6681     SCALE_Y(ptm->tmOverhang);
6682
6683     SCALE_X(ptm->tmAveCharWidth);
6684     SCALE_X(ptm->tmMaxCharWidth);
6685
6686 #undef SCALE_X
6687 #undef SCALE_Y
6688 }
6689
6690 static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *potm)
6691 {
6692     double scale_x, scale_y;
6693
6694     if (font->aveWidth)
6695     {
6696         scale_x = (double)font->aveWidth;
6697         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
6698     }
6699     else
6700         scale_x = font->scale_y;
6701
6702     scale_x *= fabs(font->font_desc.matrix.eM11);
6703     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
6704
6705     scale_font_metrics(font, &potm->otmTextMetrics);
6706
6707 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
6708 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
6709
6710     SCALE_Y(potm->otmAscent);
6711     SCALE_Y(potm->otmDescent);
6712     SCALE_Y(potm->otmLineGap);
6713     SCALE_Y(potm->otmsCapEmHeight);
6714     SCALE_Y(potm->otmsXHeight);
6715     SCALE_Y(potm->otmrcFontBox.top);
6716     SCALE_Y(potm->otmrcFontBox.bottom);
6717     SCALE_X(potm->otmrcFontBox.left);
6718     SCALE_X(potm->otmrcFontBox.right);
6719     SCALE_Y(potm->otmMacAscent);
6720     SCALE_Y(potm->otmMacDescent);
6721     SCALE_Y(potm->otmMacLineGap);
6722     SCALE_X(potm->otmptSubscriptSize.x);
6723     SCALE_Y(potm->otmptSubscriptSize.y);
6724     SCALE_X(potm->otmptSubscriptOffset.x);
6725     SCALE_Y(potm->otmptSubscriptOffset.y);
6726     SCALE_X(potm->otmptSuperscriptSize.x);
6727     SCALE_Y(potm->otmptSuperscriptSize.y);
6728     SCALE_X(potm->otmptSuperscriptOffset.x);
6729     SCALE_Y(potm->otmptSuperscriptOffset.y);
6730     SCALE_Y(potm->otmsStrikeoutSize);
6731     SCALE_Y(potm->otmsStrikeoutPosition);
6732     SCALE_Y(potm->otmsUnderscoreSize);
6733     SCALE_Y(potm->otmsUnderscorePosition);
6734
6735 #undef SCALE_X
6736 #undef SCALE_Y
6737 }
6738
6739 static BOOL get_text_metrics(GdiFont *font, LPTEXTMETRICW ptm)
6740 {
6741     if(!font->potm)
6742     {
6743         if (!get_outline_text_metrics(font) && !get_bitmap_text_metrics(font)) return FALSE;
6744
6745         /* Make sure that the font has sane width/height ratio */
6746         if (font->aveWidth)
6747         {
6748             if ((font->aveWidth + font->potm->otmTextMetrics.tmHeight - 1) / font->potm->otmTextMetrics.tmHeight > 100)
6749             {
6750                 WARN("Ignoring too large font->aveWidth %d\n", font->aveWidth);
6751                 font->aveWidth = 0;
6752             }
6753         }
6754     }
6755     *ptm = font->potm->otmTextMetrics;
6756     scale_font_metrics(font, ptm);
6757     return TRUE;
6758 }
6759
6760 static BOOL face_has_symbol_charmap(FT_Face ft_face)
6761 {
6762     int i;
6763
6764     for(i = 0; i < ft_face->num_charmaps; i++)
6765     {
6766         if(ft_face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
6767             return TRUE;
6768     }
6769     return FALSE;
6770 }
6771
6772 static BOOL get_outline_text_metrics(GdiFont *font)
6773 {
6774     BOOL ret = FALSE;
6775     FT_Face ft_face = font->ft_face;
6776     UINT needed, lenfam, lensty, lenface, lenfull;
6777     TT_OS2 *pOS2;
6778     TT_HoriHeader *pHori;
6779     TT_Postscript *pPost;
6780     FT_Fixed em_scale;
6781     WCHAR *family_nameW, *style_nameW, *face_nameW, *full_nameW;
6782     char *cp;
6783     INT ascent, descent;
6784
6785     TRACE("font=%p\n", font);
6786
6787     if(!FT_IS_SCALABLE(ft_face))
6788         return FALSE;
6789
6790     needed = sizeof(*font->potm);
6791
6792     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
6793     family_nameW = strdupW(font->name);
6794
6795     style_nameW = get_face_name( ft_face, TT_NAME_ID_FONT_SUBFAMILY, GetSystemDefaultLangID() );
6796     if (!style_nameW)
6797         style_nameW = get_face_name( ft_face, TT_NAME_ID_FONT_SUBFAMILY, TT_MS_LANGID_ENGLISH_UNITED_STATES );
6798     if (!style_nameW)
6799     {
6800         FIXME("failed to read style_nameW for font %s!\n", wine_dbgstr_w(font->name));
6801         style_nameW = towstr( CP_ACP, ft_face->style_name );
6802     }
6803     lensty = (strlenW(style_nameW) + 1) * sizeof(WCHAR);
6804
6805     face_nameW = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, GetSystemDefaultLangID() );
6806     if (!face_nameW)
6807         face_nameW = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, TT_MS_LANGID_ENGLISH_UNITED_STATES );
6808     if (!face_nameW)
6809     {
6810         FIXME("failed to read face_nameW for font %s!\n", wine_dbgstr_w(font->name));
6811         face_nameW = strdupW(font->name);
6812     }
6813     if (font->name[0] == '@') face_nameW = prepend_at( face_nameW );
6814     lenface = (strlenW(face_nameW) + 1) * sizeof(WCHAR);
6815
6816     full_nameW = get_face_name( ft_face, TT_NAME_ID_UNIQUE_ID, GetSystemDefaultLangID() );
6817     if (!full_nameW)
6818         full_nameW = get_face_name( ft_face, TT_NAME_ID_UNIQUE_ID, TT_MS_LANGID_ENGLISH_UNITED_STATES );
6819     if (!full_nameW)
6820     {
6821         WCHAR fake_nameW[] = {'f','a','k','e',' ','n','a','m','e', 0};
6822         FIXME("failed to read full_nameW for font %s!\n", wine_dbgstr_w(font->name));
6823         full_nameW = strdupW(fake_nameW);
6824     }
6825     lenfull = (strlenW(full_nameW) + 1) * sizeof(WCHAR);
6826
6827     /* These names should be read from the TT name table */
6828
6829     /* length of otmpFamilyName */
6830     needed += lenfam;
6831
6832     /* length of otmpFaceName */
6833     needed += lenface;
6834
6835     /* length of otmpStyleName */
6836     needed += lensty;
6837
6838     /* length of otmpFullName */
6839     needed += lenfull;
6840
6841
6842     em_scale = (FT_Fixed)MulDiv(font->ppem, 1 << 16, ft_face->units_per_EM);
6843
6844     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
6845     if(!pOS2) {
6846         FIXME("Can't find OS/2 table - not TT font?\n");
6847         goto end;
6848     }
6849
6850     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
6851     if(!pHori) {
6852         FIXME("Can't find HHEA table - not TT font?\n");
6853         goto end;
6854     }
6855
6856     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
6857
6858     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",
6859           pOS2->usWinAscent, pOS2->usWinDescent,
6860           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
6861           pOS2->xAvgCharWidth,
6862           ft_face->ascender, ft_face->descender, ft_face->height,
6863           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
6864           ft_face->bbox.yMax, ft_face->bbox.yMin);
6865
6866     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
6867     font->potm->otmSize = needed;
6868
6869 #define TM font->potm->otmTextMetrics
6870
6871     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
6872         ascent = pHori->Ascender;
6873         descent = -pHori->Descender;
6874     } else {
6875         ascent = pOS2->usWinAscent;
6876         descent = pOS2->usWinDescent;
6877     }
6878
6879     font->ntmCellHeight = ascent + descent;
6880     font->ntmAvgWidth = pOS2->xAvgCharWidth;
6881
6882 #define SCALE_X(x) (pFT_MulFix(x, em_scale))
6883 #define SCALE_Y(y) (pFT_MulFix(y, em_scale))
6884
6885     if(font->yMax) {
6886         TM.tmAscent = font->yMax;
6887         TM.tmDescent = -font->yMin;
6888         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
6889     } else {
6890         TM.tmAscent = SCALE_Y(ascent);
6891         TM.tmDescent = SCALE_Y(descent);
6892         TM.tmInternalLeading = SCALE_Y(ascent + descent - ft_face->units_per_EM);
6893     }
6894
6895     TM.tmHeight = TM.tmAscent + TM.tmDescent;
6896
6897     /* MSDN says:
6898      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
6899     */
6900     TM.tmExternalLeading = max(0, SCALE_Y(pHori->Line_Gap -
6901                                           ((ascent + descent) -
6902                                            (pHori->Ascender - pHori->Descender))));
6903
6904     TM.tmAveCharWidth = SCALE_X(pOS2->xAvgCharWidth);
6905     if (TM.tmAveCharWidth == 0) {
6906         TM.tmAveCharWidth = 1; 
6907     }
6908     TM.tmMaxCharWidth = SCALE_X(ft_face->bbox.xMax - ft_face->bbox.xMin);
6909     TM.tmWeight = FW_REGULAR;
6910     if (font->fake_bold)
6911         TM.tmWeight = FW_BOLD;
6912     else
6913     {
6914         if (ft_face->style_flags & FT_STYLE_FLAG_BOLD)
6915         {
6916             if (pOS2->usWeightClass > FW_MEDIUM)
6917                 TM.tmWeight = pOS2->usWeightClass;
6918         }
6919         else if (pOS2->usWeightClass <= FW_MEDIUM)
6920             TM.tmWeight = pOS2->usWeightClass;
6921     }
6922     TM.tmOverhang = 0;
6923     TM.tmDigitizedAspectX = 96; /* FIXME */
6924     TM.tmDigitizedAspectY = 96; /* FIXME */
6925     /* It appears that for fonts with SYMBOL_CHARSET Windows always sets
6926      * symbol range to 0 - f0ff
6927      */
6928
6929     if (face_has_symbol_charmap(ft_face) || (pOS2->usFirstCharIndex >= 0xf000 && pOS2->usFirstCharIndex < 0xf100))
6930     {
6931         TM.tmFirstChar = 0;
6932         switch(GetACP())
6933         {
6934         case 1257: /* Baltic */
6935             TM.tmLastChar = 0xf8fd;
6936             break;
6937         default:
6938             TM.tmLastChar = 0xf0ff;
6939         }
6940         TM.tmBreakChar = 0x20;
6941         TM.tmDefaultChar = 0x1f;
6942     }
6943     else
6944     {
6945         TM.tmFirstChar = pOS2->usFirstCharIndex; /* Should be the first char in the cmap */
6946         TM.tmLastChar = pOS2->usLastCharIndex;   /* Should be min(cmap_last, os2_last) */
6947
6948         if(pOS2->usFirstCharIndex <= 1)
6949             TM.tmBreakChar = pOS2->usFirstCharIndex + 2;
6950         else if (pOS2->usFirstCharIndex > 0xff)
6951             TM.tmBreakChar = 0x20;
6952         else
6953             TM.tmBreakChar = pOS2->usFirstCharIndex;
6954         TM.tmDefaultChar = TM.tmBreakChar - 1;
6955     }
6956     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
6957     TM.tmUnderlined = font->underline;
6958     TM.tmStruckOut = font->strikeout;
6959
6960     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
6961     if(!FT_IS_FIXED_WIDTH(ft_face) &&
6962        (pOS2->version == 0xFFFFU || 
6963         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
6964         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
6965     else
6966         TM.tmPitchAndFamily = 0;
6967
6968     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX])
6969     {
6970     case PAN_FAMILY_SCRIPT:
6971         TM.tmPitchAndFamily |= FF_SCRIPT;
6972         break;
6973
6974     case PAN_FAMILY_DECORATIVE:
6975         TM.tmPitchAndFamily |= FF_DECORATIVE;
6976         break;
6977
6978     case PAN_ANY:
6979     case PAN_NO_FIT:
6980     case PAN_FAMILY_TEXT_DISPLAY:
6981     case PAN_FAMILY_PICTORIAL: /* symbol fonts get treated as if they were text */
6982                                /* which is clearly not what the panose spec says. */
6983     default:
6984         if(TM.tmPitchAndFamily == 0 || /* fixed */
6985            pOS2->panose[PAN_PROPORTION_INDEX] == PAN_PROP_MONOSPACED)
6986             TM.tmPitchAndFamily = FF_MODERN;
6987         else
6988         {
6989             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX])
6990             {
6991             case PAN_ANY:
6992             case PAN_NO_FIT:
6993             default:
6994                 TM.tmPitchAndFamily |= FF_DONTCARE;
6995                 break;
6996
6997             case PAN_SERIF_COVE:
6998             case PAN_SERIF_OBTUSE_COVE:
6999             case PAN_SERIF_SQUARE_COVE:
7000             case PAN_SERIF_OBTUSE_SQUARE_COVE:
7001             case PAN_SERIF_SQUARE:
7002             case PAN_SERIF_THIN:
7003             case PAN_SERIF_BONE:
7004             case PAN_SERIF_EXAGGERATED:
7005             case PAN_SERIF_TRIANGLE:
7006                 TM.tmPitchAndFamily |= FF_ROMAN;
7007                 break;
7008
7009             case PAN_SERIF_NORMAL_SANS:
7010             case PAN_SERIF_OBTUSE_SANS:
7011             case PAN_SERIF_PERP_SANS:
7012             case PAN_SERIF_FLARED:
7013             case PAN_SERIF_ROUNDED:
7014                 TM.tmPitchAndFamily |= FF_SWISS;
7015                 break;
7016             }
7017         }
7018         break;
7019     }
7020
7021     if(FT_IS_SCALABLE(ft_face))
7022         TM.tmPitchAndFamily |= TMPF_VECTOR;
7023
7024     if(FT_IS_SFNT(ft_face))
7025     {
7026         if (font->ntmFlags & NTM_PS_OPENTYPE)
7027             TM.tmPitchAndFamily |= TMPF_DEVICE;
7028         else
7029             TM.tmPitchAndFamily |= TMPF_TRUETYPE;
7030     }
7031
7032     TM.tmCharSet = font->charset;
7033
7034     font->potm->otmFiller = 0;
7035     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
7036     font->potm->otmfsSelection = pOS2->fsSelection;
7037     font->potm->otmfsType = pOS2->fsType;
7038     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
7039     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
7040     font->potm->otmItalicAngle = 0; /* POST table */
7041     font->potm->otmEMSquare = ft_face->units_per_EM;
7042     font->potm->otmAscent = SCALE_Y(pOS2->sTypoAscender);
7043     font->potm->otmDescent = SCALE_Y(pOS2->sTypoDescender);
7044     font->potm->otmLineGap = SCALE_Y(pOS2->sTypoLineGap);
7045     font->potm->otmsCapEmHeight = SCALE_Y(pOS2->sCapHeight);
7046     font->potm->otmsXHeight = SCALE_Y(pOS2->sxHeight);
7047     font->potm->otmrcFontBox.left = SCALE_X(ft_face->bbox.xMin);
7048     font->potm->otmrcFontBox.right = SCALE_X(ft_face->bbox.xMax);
7049     font->potm->otmrcFontBox.top = SCALE_Y(ft_face->bbox.yMax);
7050     font->potm->otmrcFontBox.bottom = SCALE_Y(ft_face->bbox.yMin);
7051     font->potm->otmMacAscent = TM.tmAscent;
7052     font->potm->otmMacDescent = -TM.tmDescent;
7053     font->potm->otmMacLineGap = font->potm->otmLineGap;
7054     font->potm->otmusMinimumPPEM = 0; /* TT Header */
7055     font->potm->otmptSubscriptSize.x = SCALE_X(pOS2->ySubscriptXSize);
7056     font->potm->otmptSubscriptSize.y = SCALE_Y(pOS2->ySubscriptYSize);
7057     font->potm->otmptSubscriptOffset.x = SCALE_X(pOS2->ySubscriptXOffset);
7058     font->potm->otmptSubscriptOffset.y = SCALE_Y(pOS2->ySubscriptYOffset);
7059     font->potm->otmptSuperscriptSize.x = SCALE_X(pOS2->ySuperscriptXSize);
7060     font->potm->otmptSuperscriptSize.y = SCALE_Y(pOS2->ySuperscriptYSize);
7061     font->potm->otmptSuperscriptOffset.x = SCALE_X(pOS2->ySuperscriptXOffset);
7062     font->potm->otmptSuperscriptOffset.y = SCALE_Y(pOS2->ySuperscriptYOffset);
7063     font->potm->otmsStrikeoutSize = SCALE_Y(pOS2->yStrikeoutSize);
7064     font->potm->otmsStrikeoutPosition = SCALE_Y(pOS2->yStrikeoutPosition);
7065     if(!pPost) {
7066         font->potm->otmsUnderscoreSize = 0;
7067         font->potm->otmsUnderscorePosition = 0;
7068     } else {
7069         font->potm->otmsUnderscoreSize = SCALE_Y(pPost->underlineThickness);
7070         font->potm->otmsUnderscorePosition = SCALE_Y(pPost->underlinePosition);
7071     }
7072 #undef SCALE_X
7073 #undef SCALE_Y
7074 #undef TM
7075
7076     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
7077     cp = (char*)font->potm + sizeof(*font->potm);
7078     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
7079     strcpyW((WCHAR*)cp, family_nameW);
7080     cp += lenfam;
7081     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
7082     strcpyW((WCHAR*)cp, style_nameW);
7083     cp += lensty;
7084     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
7085     strcpyW((WCHAR*)cp, face_nameW);
7086         cp += lenface;
7087     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
7088     strcpyW((WCHAR*)cp, full_nameW);
7089     ret = TRUE;
7090
7091 end:
7092     HeapFree(GetProcessHeap(), 0, style_nameW);
7093     HeapFree(GetProcessHeap(), 0, family_nameW);
7094     HeapFree(GetProcessHeap(), 0, face_nameW);
7095     HeapFree(GetProcessHeap(), 0, full_nameW);
7096     return ret;
7097 }
7098
7099 /*************************************************************
7100  * freetype_GetGlyphOutline
7101  */
7102 static DWORD freetype_GetGlyphOutline( PHYSDEV dev, UINT glyph, UINT format,
7103                                        LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf, const MAT2 *lpmat )
7104 {
7105     struct freetype_physdev *physdev = get_freetype_dev( dev );
7106     DWORD ret;
7107     ABC abc;
7108
7109     if (!physdev->font)
7110     {
7111         dev = GET_NEXT_PHYSDEV( dev, pGetGlyphOutline );
7112         return dev->funcs->pGetGlyphOutline( dev, glyph, format, lpgm, buflen, buf, lpmat );
7113     }
7114
7115     GDI_CheckNotLock();
7116     EnterCriticalSection( &freetype_cs );
7117     ret = get_glyph_outline( physdev->font, glyph, format, lpgm, &abc, buflen, buf, lpmat );
7118     LeaveCriticalSection( &freetype_cs );
7119     return ret;
7120 }
7121
7122 /*************************************************************
7123  * freetype_GetTextMetrics
7124  */
7125 static BOOL freetype_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
7126 {
7127     struct freetype_physdev *physdev = get_freetype_dev( dev );
7128     BOOL ret;
7129
7130     if (!physdev->font)
7131     {
7132         dev = GET_NEXT_PHYSDEV( dev, pGetTextMetrics );
7133         return dev->funcs->pGetTextMetrics( dev, metrics );
7134     }
7135
7136     GDI_CheckNotLock();
7137     EnterCriticalSection( &freetype_cs );
7138     ret = get_text_metrics( physdev->font, metrics );
7139     LeaveCriticalSection( &freetype_cs );
7140     return ret;
7141 }
7142
7143 /*************************************************************
7144  * freetype_GetOutlineTextMetrics
7145  */
7146 static UINT freetype_GetOutlineTextMetrics( PHYSDEV dev, UINT cbSize, OUTLINETEXTMETRICW *potm )
7147 {
7148     struct freetype_physdev *physdev = get_freetype_dev( dev );
7149     UINT ret = 0;
7150
7151     if (!physdev->font)
7152     {
7153         dev = GET_NEXT_PHYSDEV( dev, pGetOutlineTextMetrics );
7154         return dev->funcs->pGetOutlineTextMetrics( dev, cbSize, potm );
7155     }
7156
7157     TRACE("font=%p\n", physdev->font);
7158
7159     if (!FT_IS_SCALABLE( physdev->font->ft_face )) return 0;
7160
7161     GDI_CheckNotLock();
7162     EnterCriticalSection( &freetype_cs );
7163
7164     if (physdev->font->potm || get_outline_text_metrics( physdev->font ))
7165     {
7166         if(cbSize >= physdev->font->potm->otmSize)
7167         {
7168             memcpy(potm, physdev->font->potm, physdev->font->potm->otmSize);
7169             scale_outline_font_metrics(physdev->font, potm);
7170         }
7171         ret = physdev->font->potm->otmSize;
7172     }
7173     LeaveCriticalSection( &freetype_cs );
7174     return ret;
7175 }
7176
7177 static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
7178 {
7179     child->font = alloc_font();
7180     child->font->ft_face = OpenFontFace(child->font, child->face, 0, -font->ppem);
7181     if(!child->font->ft_face)
7182     {
7183         free_font(child->font);
7184         child->font = NULL;
7185         return FALSE;
7186     }
7187
7188     child->font->font_desc = font->font_desc;
7189     child->font->ntmFlags = child->face->ntmFlags;
7190     child->font->orientation = font->orientation;
7191     child->font->scale_y = font->scale_y;
7192     child->font->name = strdupW(child->face->family->FamilyName);
7193     child->font->base_font = font;
7194     TRACE("created child font %p for base %p\n", child->font, font);
7195     return TRUE;
7196 }
7197
7198 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph)
7199 {
7200     FT_UInt g;
7201     CHILD_FONT *child_font;
7202
7203     if(font->base_font)
7204         font = font->base_font;
7205
7206     *linked_font = font;
7207
7208     if((*glyph = get_glyph_index(font, c)))
7209     {
7210         *glyph = get_GSUB_vert_glyph(font, *glyph);
7211         return TRUE;
7212     }
7213
7214     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
7215     {
7216         if(!child_font->font)
7217             if(!load_child_font(font, child_font))
7218                 continue;
7219
7220         if(!child_font->font->ft_face)
7221             continue;
7222         g = get_glyph_index(child_font->font, c);
7223         g = get_GSUB_vert_glyph(child_font->font, g);
7224         if(g)
7225         {
7226             *glyph = g;
7227             *linked_font = child_font->font;
7228             return TRUE;
7229         }
7230     }
7231     return FALSE;
7232 }
7233
7234 /*************************************************************
7235  * freetype_GetCharWidth
7236  */
7237 static BOOL freetype_GetCharWidth( PHYSDEV dev, UINT firstChar, UINT lastChar, LPINT buffer )
7238 {
7239     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7240     UINT c;
7241     GLYPHMETRICS gm;
7242     ABC abc;
7243     struct freetype_physdev *physdev = get_freetype_dev( dev );
7244
7245     if (!physdev->font)
7246     {
7247         dev = GET_NEXT_PHYSDEV( dev, pGetCharWidth );
7248         return dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
7249     }
7250
7251     TRACE("%p, %d, %d, %p\n", physdev->font, firstChar, lastChar, buffer);
7252
7253     GDI_CheckNotLock();
7254     EnterCriticalSection( &freetype_cs );
7255     for(c = firstChar; c <= lastChar; c++) {
7256         get_glyph_outline( physdev->font, c, GGO_METRICS, &gm, &abc, 0, NULL, &identity );
7257         buffer[c - firstChar] = abc.abcA + abc.abcB + abc.abcC;
7258     }
7259     LeaveCriticalSection( &freetype_cs );
7260     return TRUE;
7261 }
7262
7263 /*************************************************************
7264  * freetype_GetCharABCWidths
7265  */
7266 static BOOL freetype_GetCharABCWidths( PHYSDEV dev, UINT firstChar, UINT lastChar, LPABC buffer )
7267 {
7268     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7269     UINT c;
7270     GLYPHMETRICS gm;
7271     struct freetype_physdev *physdev = get_freetype_dev( dev );
7272
7273     if (!physdev->font)
7274     {
7275         dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidths );
7276         return dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, buffer );
7277     }
7278
7279     TRACE("%p, %d, %d, %p\n", physdev->font, firstChar, lastChar, buffer);
7280
7281     GDI_CheckNotLock();
7282     EnterCriticalSection( &freetype_cs );
7283
7284     for(c = firstChar; c <= lastChar; c++, buffer++)
7285         get_glyph_outline( physdev->font, c, GGO_METRICS, &gm, buffer, 0, NULL, &identity );
7286
7287     LeaveCriticalSection( &freetype_cs );
7288     return TRUE;
7289 }
7290
7291 /*************************************************************
7292  * freetype_GetCharABCWidthsI
7293  */
7294 static BOOL freetype_GetCharABCWidthsI( PHYSDEV dev, UINT firstChar, UINT count, LPWORD pgi, LPABC buffer )
7295 {
7296     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7297     UINT c;
7298     GLYPHMETRICS gm;
7299     struct freetype_physdev *physdev = get_freetype_dev( dev );
7300
7301     if (!physdev->font)
7302     {
7303         dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidthsI );
7304         return dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, buffer );
7305     }
7306
7307     if(!FT_HAS_HORIZONTAL(physdev->font->ft_face))
7308         return FALSE;
7309
7310     GDI_CheckNotLock();
7311     EnterCriticalSection( &freetype_cs );
7312
7313     for(c = 0; c < count; c++, buffer++)
7314         get_glyph_outline( physdev->font, pgi ? pgi[c] : firstChar + c, GGO_METRICS | GGO_GLYPH_INDEX,
7315                            &gm, buffer, 0, NULL, &identity );
7316
7317     LeaveCriticalSection( &freetype_cs );
7318     return TRUE;
7319 }
7320
7321 /*************************************************************
7322  * freetype_GetTextExtentExPoint
7323  */
7324 static BOOL freetype_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR wstr, INT count, LPINT dxs )
7325 {
7326     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7327     INT idx, pos;
7328     ABC abc;
7329     GLYPHMETRICS gm;
7330     struct freetype_physdev *physdev = get_freetype_dev( dev );
7331
7332     if (!physdev->font)
7333     {
7334         dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPoint );
7335         return dev->funcs->pGetTextExtentExPoint( dev, wstr, count, dxs );
7336     }
7337
7338     TRACE("%p, %s, %d\n", physdev->font, debugstr_wn(wstr, count), count);
7339
7340     GDI_CheckNotLock();
7341     EnterCriticalSection( &freetype_cs );
7342
7343     for (idx = pos = 0; idx < count; idx++)
7344     {
7345         get_glyph_outline( physdev->font, wstr[idx], GGO_METRICS, &gm, &abc, 0, NULL, &identity );
7346         pos += abc.abcA + abc.abcB + abc.abcC;
7347         dxs[idx] = pos;
7348     }
7349
7350     LeaveCriticalSection( &freetype_cs );
7351     return TRUE;
7352 }
7353
7354 /*************************************************************
7355  * freetype_GetTextExtentExPointI
7356  */
7357 static BOOL freetype_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, INT count, LPINT dxs )
7358 {
7359     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7360     INT idx, pos;
7361     ABC abc;
7362     GLYPHMETRICS gm;
7363     struct freetype_physdev *physdev = get_freetype_dev( dev );
7364
7365     if (!physdev->font)
7366     {
7367         dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPointI );
7368         return dev->funcs->pGetTextExtentExPointI( dev, indices, count, dxs );
7369     }
7370
7371     TRACE("%p, %p, %d\n", physdev->font, indices, count);
7372
7373     GDI_CheckNotLock();
7374     EnterCriticalSection( &freetype_cs );
7375
7376     for (idx = pos = 0; idx < count; idx++)
7377     {
7378         get_glyph_outline( physdev->font, indices[idx], GGO_METRICS | GGO_GLYPH_INDEX,
7379                            &gm, &abc, 0, NULL, &identity );
7380         pos += abc.abcA + abc.abcB + abc.abcC;
7381         dxs[idx] = pos;
7382     }
7383
7384     LeaveCriticalSection( &freetype_cs );
7385     return TRUE;
7386 }
7387
7388 /*************************************************************
7389  * freetype_GetFontData
7390  */
7391 static DWORD freetype_GetFontData( PHYSDEV dev, DWORD table, DWORD offset, LPVOID buf, DWORD cbData )
7392 {
7393     struct freetype_physdev *physdev = get_freetype_dev( dev );
7394
7395     if (!physdev->font)
7396     {
7397         dev = GET_NEXT_PHYSDEV( dev, pGetFontData );
7398         return dev->funcs->pGetFontData( dev, table, offset, buf, cbData );
7399     }
7400
7401     TRACE("font=%p, table=%c%c%c%c, offset=0x%x, buf=%p, cbData=0x%x\n",
7402           physdev->font, LOBYTE(LOWORD(table)), HIBYTE(LOWORD(table)),
7403           LOBYTE(HIWORD(table)), HIBYTE(HIWORD(table)), offset, buf, cbData);
7404
7405     return get_font_data( physdev->font, table, offset, buf, cbData );
7406 }
7407
7408 /*************************************************************
7409  * freetype_GetTextFace
7410  */
7411 static INT freetype_GetTextFace( PHYSDEV dev, INT count, LPWSTR str )
7412 {
7413     INT n;
7414     struct freetype_physdev *physdev = get_freetype_dev( dev );
7415
7416     if (!physdev->font)
7417     {
7418         dev = GET_NEXT_PHYSDEV( dev, pGetTextFace );
7419         return dev->funcs->pGetTextFace( dev, count, str );
7420     }
7421
7422     n = strlenW(physdev->font->name) + 1;
7423     if (str)
7424     {
7425         lstrcpynW(str, physdev->font->name, count);
7426         n = min(count, n);
7427     }
7428     return n;
7429 }
7430
7431 /*************************************************************
7432  * freetype_GetTextCharsetInfo
7433  */
7434 static UINT freetype_GetTextCharsetInfo( PHYSDEV dev, LPFONTSIGNATURE fs, DWORD flags )
7435 {
7436     struct freetype_physdev *physdev = get_freetype_dev( dev );
7437
7438     if (!physdev->font)
7439     {
7440         dev = GET_NEXT_PHYSDEV( dev, pGetTextCharsetInfo );
7441         return dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
7442     }
7443     if (fs) *fs = physdev->font->fs;
7444     return physdev->font->charset;
7445 }
7446
7447 /* Retrieve a list of supported Unicode ranges for a given font.
7448  * Can be called with NULL gs to calculate the buffer size. Returns
7449  * the number of ranges found.
7450  */
7451 static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
7452 {
7453     DWORD num_ranges = 0;
7454
7455     if (face->charmap->encoding == FT_ENCODING_UNICODE)
7456     {
7457         FT_UInt glyph_code;
7458         FT_ULong char_code, char_code_prev;
7459
7460         glyph_code = 0;
7461         char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
7462
7463         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
7464                face->num_glyphs, glyph_code, char_code);
7465
7466         if (!glyph_code) return 0;
7467
7468         if (gs)
7469         {
7470             gs->ranges[0].wcLow = (USHORT)char_code;
7471             gs->ranges[0].cGlyphs = 0;
7472             gs->cGlyphsSupported = 0;
7473         }
7474
7475         num_ranges = 1;
7476         while (glyph_code)
7477         {
7478             if (char_code < char_code_prev)
7479             {
7480                 ERR("expected increasing char code from FT_Get_Next_Char\n");
7481                 return 0;
7482             }
7483             if (char_code - char_code_prev > 1)
7484             {
7485                 num_ranges++;
7486                 if (gs)
7487                 {
7488                     gs->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
7489                     gs->ranges[num_ranges - 1].cGlyphs = 1;
7490                     gs->cGlyphsSupported++;
7491                 }
7492             }
7493             else if (gs)
7494             {
7495                 gs->ranges[num_ranges - 1].cGlyphs++;
7496                 gs->cGlyphsSupported++;
7497             }
7498             char_code_prev = char_code;
7499             char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
7500         }
7501     }
7502     else
7503         FIXME("encoding %u not supported\n", face->charmap->encoding);
7504
7505     return num_ranges;
7506 }
7507
7508 /*************************************************************
7509  * freetype_GetFontUnicodeRanges
7510  */
7511 static DWORD freetype_GetFontUnicodeRanges( PHYSDEV dev, LPGLYPHSET glyphset )
7512 {
7513     struct freetype_physdev *physdev = get_freetype_dev( dev );
7514     DWORD size, num_ranges;
7515
7516     if (!physdev->font)
7517     {
7518         dev = GET_NEXT_PHYSDEV( dev, pGetFontUnicodeRanges );
7519         return dev->funcs->pGetFontUnicodeRanges( dev, glyphset );
7520     }
7521
7522     num_ranges = get_font_unicode_ranges(physdev->font->ft_face, glyphset);
7523     size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
7524     if (glyphset)
7525     {
7526         glyphset->cbThis = size;
7527         glyphset->cRanges = num_ranges;
7528         glyphset->flAccel = 0;
7529     }
7530     return size;
7531 }
7532
7533 /*************************************************************
7534  * freetype_FontIsLinked
7535  */
7536 static BOOL freetype_FontIsLinked( PHYSDEV dev )
7537 {
7538     struct freetype_physdev *physdev = get_freetype_dev( dev );
7539     BOOL ret;
7540
7541     if (!physdev->font)
7542     {
7543         dev = GET_NEXT_PHYSDEV( dev, pFontIsLinked );
7544         return dev->funcs->pFontIsLinked( dev );
7545     }
7546
7547     GDI_CheckNotLock();
7548     EnterCriticalSection( &freetype_cs );
7549     ret = !list_empty(&physdev->font->child_fonts);
7550     LeaveCriticalSection( &freetype_cs );
7551     return ret;
7552 }
7553
7554 /*************************************************************************
7555  *             GetRasterizerCaps   (GDI32.@)
7556  */
7557 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
7558 {
7559     lprs->nSize = sizeof(RASTERIZER_STATUS);
7560     lprs->wFlags = TT_AVAILABLE | TT_ENABLED;
7561     lprs->nLanguageID = 0;
7562     return TRUE;
7563 }
7564
7565 /*************************************************************
7566  * freetype_GdiRealizationInfo
7567  */
7568 static BOOL freetype_GdiRealizationInfo( PHYSDEV dev, void *ptr )
7569 {
7570     struct freetype_physdev *physdev = get_freetype_dev( dev );
7571     realization_info_t *info = ptr;
7572
7573     if (!physdev->font)
7574     {
7575         dev = GET_NEXT_PHYSDEV( dev, pGdiRealizationInfo );
7576         return dev->funcs->pGdiRealizationInfo( dev, ptr );
7577     }
7578
7579     FIXME("(%p, %p): stub!\n", physdev->font, info);
7580
7581     info->flags = 1;
7582     if(FT_IS_SCALABLE(physdev->font->ft_face))
7583         info->flags |= 2;
7584
7585     info->cache_num = physdev->font->cache_num;
7586     info->unknown2 = -1;
7587     return TRUE;
7588 }
7589
7590 /*************************************************************************
7591  * Kerning support for TrueType fonts
7592  */
7593 #define MS_KERN_TAG MS_MAKE_TAG('k', 'e', 'r', 'n')
7594
7595 struct TT_kern_table
7596 {
7597     USHORT version;
7598     USHORT nTables;
7599 };
7600
7601 struct TT_kern_subtable
7602 {
7603     USHORT version;
7604     USHORT length;
7605     union
7606     {
7607         USHORT word;
7608         struct
7609         {
7610             USHORT horizontal : 1;
7611             USHORT minimum : 1;
7612             USHORT cross_stream: 1;
7613             USHORT override : 1;
7614             USHORT reserved1 : 4;
7615             USHORT format : 8;
7616         } bits;
7617     } coverage;
7618 };
7619
7620 struct TT_format0_kern_subtable
7621 {
7622     USHORT nPairs;
7623     USHORT searchRange;
7624     USHORT entrySelector;
7625     USHORT rangeShift;
7626 };
7627
7628 struct TT_kern_pair
7629 {
7630     USHORT left;
7631     USHORT right;
7632     short  value;
7633 };
7634
7635 static DWORD parse_format0_kern_subtable(GdiFont *font,
7636                                          const struct TT_format0_kern_subtable *tt_f0_ks,
7637                                          const USHORT *glyph_to_char,
7638                                          KERNINGPAIR *kern_pair, DWORD cPairs)
7639 {
7640     USHORT i, nPairs;
7641     const struct TT_kern_pair *tt_kern_pair;
7642
7643     TRACE("font height %d, units_per_EM %d\n", font->ppem, font->ft_face->units_per_EM);
7644
7645     nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
7646
7647     TRACE("nPairs %u, searchRange %u, entrySelector %u, rangeShift %u\n",
7648            nPairs, GET_BE_WORD(tt_f0_ks->searchRange),
7649            GET_BE_WORD(tt_f0_ks->entrySelector), GET_BE_WORD(tt_f0_ks->rangeShift));
7650
7651     if (!kern_pair || !cPairs)
7652         return nPairs;
7653
7654     tt_kern_pair = (const struct TT_kern_pair *)(tt_f0_ks + 1);
7655
7656     nPairs = min(nPairs, cPairs);
7657
7658     for (i = 0; i < nPairs; i++)
7659     {
7660         kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
7661         kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
7662         /* this algorithm appears to better match what Windows does */
7663         kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
7664         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         else if (kern_pair->iKernAmount > 0)
7670         {
7671             kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
7672             kern_pair->iKernAmount += font->ppem;
7673         }
7674         kern_pair->iKernAmount /= font->ft_face->units_per_EM;
7675
7676         TRACE("left %u right %u value %d\n",
7677                kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
7678
7679         kern_pair++;
7680     }
7681     TRACE("copied %u entries\n", nPairs);
7682     return nPairs;
7683 }
7684
7685 /*************************************************************
7686  * freetype_GetKerningPairs
7687  */
7688 static DWORD freetype_GetKerningPairs( PHYSDEV dev, DWORD cPairs, KERNINGPAIR *kern_pair )
7689 {
7690     DWORD length;
7691     void *buf;
7692     const struct TT_kern_table *tt_kern_table;
7693     const struct TT_kern_subtable *tt_kern_subtable;
7694     USHORT i, nTables;
7695     USHORT *glyph_to_char;
7696     GdiFont *font;
7697     struct freetype_physdev *physdev = get_freetype_dev( dev );
7698
7699     if (!(font = physdev->font))
7700     {
7701         dev = GET_NEXT_PHYSDEV( dev, pGetKerningPairs );
7702         return dev->funcs->pGetKerningPairs( dev, cPairs, kern_pair );
7703     }
7704
7705     GDI_CheckNotLock();
7706     EnterCriticalSection( &freetype_cs );
7707     if (font->total_kern_pairs != (DWORD)-1)
7708     {
7709         if (cPairs && kern_pair)
7710         {
7711             cPairs = min(cPairs, font->total_kern_pairs);
7712             memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
7713         }
7714         else cPairs = font->total_kern_pairs;
7715
7716         LeaveCriticalSection( &freetype_cs );
7717         return cPairs;
7718     }
7719
7720     font->total_kern_pairs = 0;
7721
7722     length = get_font_data(font, MS_KERN_TAG, 0, NULL, 0);
7723
7724     if (length == GDI_ERROR)
7725     {
7726         TRACE("no kerning data in the font\n");
7727         LeaveCriticalSection( &freetype_cs );
7728         return 0;
7729     }
7730
7731     buf = HeapAlloc(GetProcessHeap(), 0, length);
7732     if (!buf)
7733     {
7734         WARN("Out of memory\n");
7735         LeaveCriticalSection( &freetype_cs );
7736         return 0;
7737     }
7738
7739     get_font_data(font, MS_KERN_TAG, 0, buf, length);
7740
7741     /* build a glyph index to char code map */
7742     glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
7743     if (!glyph_to_char)
7744     {
7745         WARN("Out of memory allocating a glyph index to char code map\n");
7746         HeapFree(GetProcessHeap(), 0, buf);
7747         LeaveCriticalSection( &freetype_cs );
7748         return 0;
7749     }
7750
7751     if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE)
7752     {
7753         FT_UInt glyph_code;
7754         FT_ULong char_code;
7755
7756         glyph_code = 0;
7757         char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
7758
7759         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
7760                font->ft_face->num_glyphs, glyph_code, char_code);
7761
7762         while (glyph_code)
7763         {
7764             /*TRACE("Char %04lX -> Index %u%s\n", char_code, glyph_code, glyph_to_char[glyph_code] ? "  !" : "" );*/
7765
7766             /* FIXME: This doesn't match what Windows does: it does some fancy
7767              * things with duplicate glyph index to char code mappings, while
7768              * we just avoid overriding existing entries.
7769              */
7770             if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
7771                 glyph_to_char[glyph_code] = (USHORT)char_code;
7772
7773             char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
7774         }
7775     }
7776     else
7777     {
7778         ULONG n;
7779
7780         FIXME("encoding %u not supported\n", font->ft_face->charmap->encoding);
7781         for (n = 0; n <= 65535; n++)
7782             glyph_to_char[n] = (USHORT)n;
7783     }
7784
7785     tt_kern_table = buf;
7786     nTables = GET_BE_WORD(tt_kern_table->nTables);
7787     TRACE("version %u, nTables %u\n",
7788            GET_BE_WORD(tt_kern_table->version), nTables);
7789
7790     tt_kern_subtable = (const struct TT_kern_subtable *)(tt_kern_table + 1);
7791
7792     for (i = 0; i < nTables; i++)
7793     {
7794         struct TT_kern_subtable tt_kern_subtable_copy;
7795
7796         tt_kern_subtable_copy.version = GET_BE_WORD(tt_kern_subtable->version);
7797         tt_kern_subtable_copy.length = GET_BE_WORD(tt_kern_subtable->length);
7798         tt_kern_subtable_copy.coverage.word = GET_BE_WORD(tt_kern_subtable->coverage.word);
7799
7800         TRACE("version %u, length %u, coverage %u, subtable format %u\n",
7801                tt_kern_subtable_copy.version, tt_kern_subtable_copy.length,
7802                tt_kern_subtable_copy.coverage.word, tt_kern_subtable_copy.coverage.bits.format);
7803
7804         /* According to the TrueType specification this is the only format
7805          * that will be properly interpreted by Windows and OS/2
7806          */
7807         if (tt_kern_subtable_copy.coverage.bits.format == 0)
7808         {
7809             DWORD new_chunk, old_total = font->total_kern_pairs;
7810
7811             new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
7812                                                     glyph_to_char, NULL, 0);
7813             font->total_kern_pairs += new_chunk;
7814
7815             if (!font->kern_pairs)
7816                 font->kern_pairs = HeapAlloc(GetProcessHeap(), 0,
7817                                              font->total_kern_pairs * sizeof(*font->kern_pairs));
7818             else
7819                 font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs,
7820                                                font->total_kern_pairs * sizeof(*font->kern_pairs));
7821
7822             parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
7823                         glyph_to_char, font->kern_pairs + old_total, new_chunk);
7824         }
7825         else
7826             TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format);
7827
7828         tt_kern_subtable = (const struct TT_kern_subtable *)((const char *)tt_kern_subtable + tt_kern_subtable_copy.length);
7829     }
7830
7831     HeapFree(GetProcessHeap(), 0, glyph_to_char);
7832     HeapFree(GetProcessHeap(), 0, buf);
7833
7834     if (cPairs && kern_pair)
7835     {
7836         cPairs = min(cPairs, font->total_kern_pairs);
7837         memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
7838     }
7839     else cPairs = font->total_kern_pairs;
7840
7841     LeaveCriticalSection( &freetype_cs );
7842     return cPairs;
7843 }
7844
7845 static const struct gdi_dc_funcs freetype_funcs =
7846 {
7847     NULL,                               /* pAbortDoc */
7848     NULL,                               /* pAbortPath */
7849     NULL,                               /* pAlphaBlend */
7850     NULL,                               /* pAngleArc */
7851     NULL,                               /* pArc */
7852     NULL,                               /* pArcTo */
7853     NULL,                               /* pBeginPath */
7854     NULL,                               /* pBlendImage */
7855     NULL,                               /* pChord */
7856     NULL,                               /* pCloseFigure */
7857     NULL,                               /* pCreateCompatibleDC */
7858     freetype_CreateDC,                  /* pCreateDC */
7859     freetype_DeleteDC,                  /* pDeleteDC */
7860     NULL,                               /* pDeleteObject */
7861     NULL,                               /* pDeviceCapabilities */
7862     NULL,                               /* pEllipse */
7863     NULL,                               /* pEndDoc */
7864     NULL,                               /* pEndPage */
7865     NULL,                               /* pEndPath */
7866     freetype_EnumFonts,                 /* pEnumFonts */
7867     NULL,                               /* pEnumICMProfiles */
7868     NULL,                               /* pExcludeClipRect */
7869     NULL,                               /* pExtDeviceMode */
7870     NULL,                               /* pExtEscape */
7871     NULL,                               /* pExtFloodFill */
7872     NULL,                               /* pExtSelectClipRgn */
7873     NULL,                               /* pExtTextOut */
7874     NULL,                               /* pFillPath */
7875     NULL,                               /* pFillRgn */
7876     NULL,                               /* pFlattenPath */
7877     freetype_FontIsLinked,              /* pFontIsLinked */
7878     NULL,                               /* pFrameRgn */
7879     NULL,                               /* pGdiComment */
7880     freetype_GdiRealizationInfo,        /* pGdiRealizationInfo */
7881     NULL,                               /* pGetBoundsRect */
7882     freetype_GetCharABCWidths,          /* pGetCharABCWidths */
7883     freetype_GetCharABCWidthsI,         /* pGetCharABCWidthsI */
7884     freetype_GetCharWidth,              /* pGetCharWidth */
7885     NULL,                               /* pGetDeviceCaps */
7886     NULL,                               /* pGetDeviceGammaRamp */
7887     freetype_GetFontData,               /* pGetFontData */
7888     freetype_GetFontUnicodeRanges,      /* pGetFontUnicodeRanges */
7889     freetype_GetGlyphIndices,           /* pGetGlyphIndices */
7890     freetype_GetGlyphOutline,           /* pGetGlyphOutline */
7891     NULL,                               /* pGetICMProfile */
7892     NULL,                               /* pGetImage */
7893     freetype_GetKerningPairs,           /* pGetKerningPairs */
7894     NULL,                               /* pGetNearestColor */
7895     freetype_GetOutlineTextMetrics,     /* pGetOutlineTextMetrics */
7896     NULL,                               /* pGetPixel */
7897     NULL,                               /* pGetSystemPaletteEntries */
7898     freetype_GetTextCharsetInfo,        /* pGetTextCharsetInfo */
7899     freetype_GetTextExtentExPoint,      /* pGetTextExtentExPoint */
7900     freetype_GetTextExtentExPointI,     /* pGetTextExtentExPointI */
7901     freetype_GetTextFace,               /* pGetTextFace */
7902     freetype_GetTextMetrics,            /* pGetTextMetrics */
7903     NULL,                               /* pGradientFill */
7904     NULL,                               /* pIntersectClipRect */
7905     NULL,                               /* pInvertRgn */
7906     NULL,                               /* pLineTo */
7907     NULL,                               /* pModifyWorldTransform */
7908     NULL,                               /* pMoveTo */
7909     NULL,                               /* pOffsetClipRgn */
7910     NULL,                               /* pOffsetViewportOrg */
7911     NULL,                               /* pOffsetWindowOrg */
7912     NULL,                               /* pPaintRgn */
7913     NULL,                               /* pPatBlt */
7914     NULL,                               /* pPie */
7915     NULL,                               /* pPolyBezier */
7916     NULL,                               /* pPolyBezierTo */
7917     NULL,                               /* pPolyDraw */
7918     NULL,                               /* pPolyPolygon */
7919     NULL,                               /* pPolyPolyline */
7920     NULL,                               /* pPolygon */
7921     NULL,                               /* pPolyline */
7922     NULL,                               /* pPolylineTo */
7923     NULL,                               /* pPutImage */
7924     NULL,                               /* pRealizeDefaultPalette */
7925     NULL,                               /* pRealizePalette */
7926     NULL,                               /* pRectangle */
7927     NULL,                               /* pResetDC */
7928     NULL,                               /* pRestoreDC */
7929     NULL,                               /* pRoundRect */
7930     NULL,                               /* pSaveDC */
7931     NULL,                               /* pScaleViewportExt */
7932     NULL,                               /* pScaleWindowExt */
7933     NULL,                               /* pSelectBitmap */
7934     NULL,                               /* pSelectBrush */
7935     NULL,                               /* pSelectClipPath */
7936     freetype_SelectFont,                /* pSelectFont */
7937     NULL,                               /* pSelectPalette */
7938     NULL,                               /* pSelectPen */
7939     NULL,                               /* pSetArcDirection */
7940     NULL,                               /* pSetBkColor */
7941     NULL,                               /* pSetBkMode */
7942     NULL,                               /* pSetDCBrushColor */
7943     NULL,                               /* pSetDCPenColor */
7944     NULL,                               /* pSetDIBColorTable */
7945     NULL,                               /* pSetDIBitsToDevice */
7946     NULL,                               /* pSetDeviceClipping */
7947     NULL,                               /* pSetDeviceGammaRamp */
7948     NULL,                               /* pSetLayout */
7949     NULL,                               /* pSetMapMode */
7950     NULL,                               /* pSetMapperFlags */
7951     NULL,                               /* pSetPixel */
7952     NULL,                               /* pSetPolyFillMode */
7953     NULL,                               /* pSetROP2 */
7954     NULL,                               /* pSetRelAbs */
7955     NULL,                               /* pSetStretchBltMode */
7956     NULL,                               /* pSetTextAlign */
7957     NULL,                               /* pSetTextCharacterExtra */
7958     NULL,                               /* pSetTextColor */
7959     NULL,                               /* pSetTextJustification */
7960     NULL,                               /* pSetViewportExt */
7961     NULL,                               /* pSetViewportOrg */
7962     NULL,                               /* pSetWindowExt */
7963     NULL,                               /* pSetWindowOrg */
7964     NULL,                               /* pSetWorldTransform */
7965     NULL,                               /* pStartDoc */
7966     NULL,                               /* pStartPage */
7967     NULL,                               /* pStretchBlt */
7968     NULL,                               /* pStretchDIBits */
7969     NULL,                               /* pStrokeAndFillPath */
7970     NULL,                               /* pStrokePath */
7971     NULL,                               /* pUnrealizePalette */
7972     NULL,                               /* pWidenPath */
7973     NULL,                               /* wine_get_wgl_driver */
7974     GDI_PRIORITY_FONT_DRV               /* priority */
7975 };
7976
7977 #else /* HAVE_FREETYPE */
7978
7979 /*************************************************************************/
7980
7981 BOOL WineEngInit(void)
7982 {
7983     return FALSE;
7984 }
7985
7986 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
7987 {
7988     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
7989     return 1;
7990 }
7991
7992 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
7993 {
7994     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
7995     return TRUE;
7996 }
7997
7998 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
7999 {
8000     FIXME("(%p, %u, %p, %p): stub\n", pbFont, cbFont, pdv, pcFonts);
8001     return NULL;
8002 }
8003
8004 BOOL WineEngCreateScalableFontResource( DWORD hidden, LPCWSTR resource,
8005                                         LPCWSTR font_file, LPCWSTR font_path )
8006 {
8007     FIXME("stub\n");
8008     return FALSE;
8009 }
8010
8011 /*************************************************************************
8012  *             GetRasterizerCaps   (GDI32.@)
8013  */
8014 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
8015 {
8016     lprs->nSize = sizeof(RASTERIZER_STATUS);
8017     lprs->wFlags = 0;
8018     lprs->nLanguageID = 0;
8019     return TRUE;
8020 }
8021
8022 #endif /* HAVE_FREETYPE */