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