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