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