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