ole32/tests: Fix a test failure on newer Windows versions.
[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         DWORD mask = 0;
5015
5016         /* Set the current codepage's charset as the first element. */
5017         acp = GetACP();
5018         if (TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE) &&
5019             csi.fs.fsCsb[0] != 0) {
5020             list->element[n].mask    = csi.fs.fsCsb[0];
5021             list->element[n].charset = csi.ciCharset;
5022             load_script_name( ffs(csi.fs.fsCsb[0]) - 1, list->element[n].name );
5023             mask |= csi.fs.fsCsb[0];
5024             n++;
5025         }
5026
5027         /* Fill out left elements. */
5028         for (i = 0; i < 32; i++) {
5029             FONTSIGNATURE fs;
5030             fs.fsCsb[0] = 1L << i;
5031             fs.fsCsb[1] = 0;
5032             if (fs.fsCsb[0] & mask)
5033                 continue; /* skip, already added. */
5034             if (!TranslateCharsetInfo(fs.fsCsb, &csi, TCI_SRCFONTSIG))
5035                 continue; /* skip, this is an invalid fsCsb bit. */
5036
5037             list->element[n].mask    = fs.fsCsb[0];
5038             list->element[n].charset = csi.ciCharset;
5039             load_script_name( i, list->element[n].name );
5040             mask |= fs.fsCsb[0];
5041             n++;
5042         }
5043
5044         /* add catch all mask for remaining bits */
5045         if (~mask)
5046         {
5047             list->element[n].mask    = ~mask;
5048             list->element[n].charset = DEFAULT_CHARSET;
5049             load_script_name( IDS_OTHER - IDS_FIRST_SCRIPT, list->element[n].name );
5050             n++;
5051         }
5052     }
5053     list->total = n;
5054
5055     return n;
5056 }
5057
5058 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
5059                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
5060 {
5061     GdiFont *font;
5062     LONG width, height;
5063
5064     if (face->cached_enum_data)
5065     {
5066         TRACE("Cached\n");
5067         *pelf = face->cached_enum_data->elf;
5068         *pntm = face->cached_enum_data->ntm;
5069         *ptype = face->cached_enum_data->type;
5070         return;
5071     }
5072
5073     font = alloc_font();
5074
5075     if(face->scalable) {
5076         height = 100;
5077         width = 0;
5078     } else {
5079         height = face->size.y_ppem >> 6;
5080         width = face->size.x_ppem >> 6;
5081     }
5082     font->scale_y = 1.0;
5083     
5084     if (!(font->ft_face = OpenFontFace(font, face, width, height)))
5085     {
5086         free_font(font);
5087         return;
5088     }
5089
5090     font->name = strdupW(face->family->FamilyName);
5091     font->ntmFlags = face->ntmFlags;
5092
5093     if (get_outline_text_metrics(font))
5094     {
5095         memcpy(&pntm->ntmTm, &font->potm->otmTextMetrics, sizeof(TEXTMETRICW));
5096
5097         pntm->ntmTm.ntmSizeEM = font->potm->otmEMSquare;
5098         pntm->ntmTm.ntmCellHeight = font->ntmCellHeight;
5099         pntm->ntmTm.ntmAvgWidth = font->ntmAvgWidth;
5100
5101         lstrcpynW(pelf->elfLogFont.lfFaceName,
5102                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFamilyName),
5103                  LF_FACESIZE);
5104         lstrcpynW(pelf->elfFullName,
5105                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFaceName),
5106                  LF_FULLFACESIZE);
5107         lstrcpynW(pelf->elfStyle,
5108                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpStyleName),
5109                  LF_FACESIZE);
5110     }
5111     else
5112     {
5113         get_text_metrics(font, (TEXTMETRICW *)&pntm->ntmTm);
5114
5115         pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
5116         pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
5117         pntm->ntmTm.ntmAvgWidth = pntm->ntmTm.tmAveCharWidth;
5118
5119         lstrcpynW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
5120         if (face->FullName)
5121             lstrcpynW(pelf->elfFullName, face->FullName, LF_FULLFACESIZE);
5122         else
5123             lstrcpynW(pelf->elfFullName, face->family->FamilyName, LF_FULLFACESIZE);
5124         lstrcpynW(pelf->elfStyle, face->StyleName, LF_FACESIZE);
5125     }
5126
5127     pntm->ntmTm.ntmFlags = face->ntmFlags;
5128     pntm->ntmFontSig = face->fs;
5129
5130     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
5131
5132     pelf->elfLogFont.lfEscapement = 0;
5133     pelf->elfLogFont.lfOrientation = 0;
5134     pelf->elfLogFont.lfHeight = pntm->ntmTm.tmHeight;
5135     pelf->elfLogFont.lfWidth = pntm->ntmTm.tmAveCharWidth;
5136     pelf->elfLogFont.lfWeight = pntm->ntmTm.tmWeight;
5137     pelf->elfLogFont.lfItalic = pntm->ntmTm.tmItalic;
5138     pelf->elfLogFont.lfUnderline = pntm->ntmTm.tmUnderlined;
5139     pelf->elfLogFont.lfStrikeOut = pntm->ntmTm.tmStruckOut;
5140     pelf->elfLogFont.lfCharSet = pntm->ntmTm.tmCharSet;
5141     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
5142     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
5143     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
5144     pelf->elfLogFont.lfPitchAndFamily = (pntm->ntmTm.tmPitchAndFamily & 0xf1) + 1;
5145
5146     *ptype = 0;
5147     if (pntm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE)
5148         *ptype |= TRUETYPE_FONTTYPE;
5149     if (pntm->ntmTm.tmPitchAndFamily & TMPF_DEVICE)
5150         *ptype |= DEVICE_FONTTYPE;
5151     if(!(pntm->ntmTm.tmPitchAndFamily & TMPF_VECTOR))
5152         *ptype |= RASTER_FONTTYPE;
5153
5154     face->cached_enum_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*face->cached_enum_data));
5155     if (face->cached_enum_data)
5156     {
5157         face->cached_enum_data->elf = *pelf;
5158         face->cached_enum_data->ntm = *pntm;
5159         face->cached_enum_data->type = *ptype;
5160     }
5161
5162     free_font(font);
5163 }
5164
5165 static BOOL family_matches(Family *family, const LOGFONTW *lf)
5166 {
5167     const struct list *face_list, *face_elem_ptr;
5168
5169     if (!strcmpiW(lf->lfFaceName, family->FamilyName)) return TRUE;
5170
5171     face_list = get_face_list_from_family(family);
5172     LIST_FOR_EACH(face_elem_ptr, face_list)
5173     {
5174         Face *face = LIST_ENTRY(face_elem_ptr, Face, entry);
5175
5176         if (face->FullName && !strcmpiW(lf->lfFaceName, face->FullName)) return TRUE;
5177     }
5178
5179     return FALSE;
5180 }
5181
5182 static BOOL face_matches(const WCHAR *family_name, Face *face, const LOGFONTW *lf)
5183 {
5184     if (!strcmpiW(lf->lfFaceName, family_name)) return TRUE;
5185
5186     return (face->FullName && !strcmpiW(lf->lfFaceName, face->FullName));
5187 }
5188
5189 static BOOL enum_face_charsets(const Family *family, Face *face, struct enum_charset_list *list,
5190                                FONTENUMPROCW proc, LPARAM lparam)
5191 {
5192     ENUMLOGFONTEXW elf;
5193     NEWTEXTMETRICEXW ntm;
5194     DWORD type = 0;
5195     int i;
5196
5197     GetEnumStructs(face, &elf, &ntm, &type);
5198     for(i = 0; i < list->total; i++) {
5199         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
5200             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
5201             load_script_name( IDS_OEM_DOS - IDS_FIRST_SCRIPT, elf.elfScript );
5202             i = list->total; /* break out of loop after enumeration */
5203         }
5204         else
5205         {
5206             if(!(face->fs.fsCsb[0] & list->element[i].mask)) continue;
5207             /* use the DEFAULT_CHARSET case only if no other charset is present */
5208             if (list->element[i].charset == DEFAULT_CHARSET &&
5209                 (face->fs.fsCsb[0] & ~list->element[i].mask)) continue;
5210             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = list->element[i].charset;
5211             strcpyW(elf.elfScript, list->element[i].name);
5212             if (!elf.elfScript[0])
5213                 FIXME("Unknown elfscript for bit %d\n", ffs(list->element[i].mask) - 1);
5214         }
5215         /* Font Replacement */
5216         if (family != face->family)
5217         {
5218             strcpyW(elf.elfLogFont.lfFaceName, family->FamilyName);
5219             if (face->FullName)
5220                 strcpyW(elf.elfFullName, face->FullName);
5221             else
5222                 strcpyW(elf.elfFullName, family->FamilyName);
5223         }
5224         TRACE("enuming face %s full %s style %s charset = %d type %d script %s it %d weight %d ntmflags %08x\n",
5225               debugstr_w(elf.elfLogFont.lfFaceName),
5226               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
5227               elf.elfLogFont.lfCharSet, type, debugstr_w(elf.elfScript),
5228               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
5229               ntm.ntmTm.ntmFlags);
5230         /* release section before callback (FIXME) */
5231         LeaveCriticalSection( &freetype_cs );
5232         if (!proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam)) return FALSE;
5233         EnterCriticalSection( &freetype_cs );
5234     }
5235     return TRUE;
5236 }
5237
5238 /*************************************************************
5239  * freetype_EnumFonts
5240  */
5241 static BOOL freetype_EnumFonts( PHYSDEV dev, LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam )
5242 {
5243     Family *family;
5244     Face *face;
5245     const struct list *family_elem_ptr, *face_list, *face_elem_ptr;
5246     LOGFONTW lf;
5247     struct enum_charset_list enum_charsets;
5248
5249     if (!plf)
5250     {
5251         lf.lfCharSet = DEFAULT_CHARSET;
5252         lf.lfPitchAndFamily = 0;
5253         lf.lfFaceName[0] = 0;
5254         plf = &lf;
5255     }
5256
5257     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
5258
5259     create_enum_charset_list(plf->lfCharSet, &enum_charsets);
5260
5261     GDI_CheckNotLock();
5262     EnterCriticalSection( &freetype_cs );
5263     if(plf->lfFaceName[0]) {
5264         FontSubst *psub;
5265         psub = get_font_subst(&font_subst_list, plf->lfFaceName, plf->lfCharSet);
5266
5267         if(psub) {
5268             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
5269                   debugstr_w(psub->to.name));
5270             lf = *plf;
5271             strcpyW(lf.lfFaceName, psub->to.name);
5272             plf = &lf;
5273         }
5274
5275         LIST_FOR_EACH(family_elem_ptr, &font_list) {
5276             family = LIST_ENTRY(family_elem_ptr, Family, entry);
5277             if(family_matches(family, plf)) {
5278                 face_list = get_face_list_from_family(family);
5279                 LIST_FOR_EACH(face_elem_ptr, face_list) {
5280                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
5281                     if (!face_matches(family->FamilyName, face, plf)) continue;
5282                     if (!enum_face_charsets(family, face, &enum_charsets, proc, lparam)) return FALSE;
5283                 }
5284             }
5285         }
5286     } else {
5287         LIST_FOR_EACH(family_elem_ptr, &font_list) {
5288             family = LIST_ENTRY(family_elem_ptr, Family, entry);
5289             face_list = get_face_list_from_family(family);
5290             face_elem_ptr = list_head(face_list);
5291             face = LIST_ENTRY(face_elem_ptr, Face, entry);
5292             if (!enum_face_charsets(family, face, &enum_charsets, proc, lparam)) return FALSE;
5293         }
5294     }
5295     LeaveCriticalSection( &freetype_cs );
5296     return TRUE;
5297 }
5298
5299 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
5300 {
5301     pt->x.value = vec->x >> 6;
5302     pt->x.fract = (vec->x & 0x3f) << 10;
5303     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
5304     pt->y.value = vec->y >> 6;
5305     pt->y.fract = (vec->y & 0x3f) << 10;
5306     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
5307     return;
5308 }
5309
5310 /***************************************************
5311  * According to the MSDN documentation on WideCharToMultiByte,
5312  * certain codepages cannot set the default_used parameter.
5313  * This returns TRUE if the codepage can set that parameter, false else
5314  * so that calls to WideCharToMultiByte don't fail with ERROR_INVALID_PARAMETER
5315  */
5316 static BOOL codepage_sets_default_used(UINT codepage)
5317 {
5318    switch (codepage)
5319    {
5320        case CP_UTF7:
5321        case CP_UTF8:
5322        case CP_SYMBOL:
5323            return FALSE;
5324        default:
5325            return TRUE;
5326    }
5327 }
5328
5329 /*
5330  * GSUB Table handling functions
5331  */
5332
5333 static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph)
5334 {
5335     const GSUB_CoverageFormat1* cf1;
5336
5337     cf1 = table;
5338
5339     if (GET_BE_WORD(cf1->CoverageFormat) == 1)
5340     {
5341         int count = GET_BE_WORD(cf1->GlyphCount);
5342         int i;
5343         TRACE("Coverage Format 1, %i glyphs\n",count);
5344         for (i = 0; i < count; i++)
5345             if (glyph == GET_BE_WORD(cf1->GlyphArray[i]))
5346                 return i;
5347         return -1;
5348     }
5349     else if (GET_BE_WORD(cf1->CoverageFormat) == 2)
5350     {
5351         const GSUB_CoverageFormat2* cf2;
5352         int i;
5353         int count;
5354         cf2 = (const GSUB_CoverageFormat2*)cf1;
5355
5356         count = GET_BE_WORD(cf2->RangeCount);
5357         TRACE("Coverage Format 2, %i ranges\n",count);
5358         for (i = 0; i < count; i++)
5359         {
5360             if (glyph < GET_BE_WORD(cf2->RangeRecord[i].Start))
5361                 return -1;
5362             if ((glyph >= GET_BE_WORD(cf2->RangeRecord[i].Start)) &&
5363                 (glyph <= GET_BE_WORD(cf2->RangeRecord[i].End)))
5364             {
5365                 return (GET_BE_WORD(cf2->RangeRecord[i].StartCoverageIndex) +
5366                     glyph - GET_BE_WORD(cf2->RangeRecord[i].Start));
5367             }
5368         }
5369         return -1;
5370     }
5371     else
5372         ERR("Unknown CoverageFormat %i\n",GET_BE_WORD(cf1->CoverageFormat));
5373
5374     return -1;
5375 }
5376
5377 static const GSUB_Script* GSUB_get_script_table( const GSUB_Header* header, const char* tag)
5378 {
5379     const GSUB_ScriptList *script;
5380     const GSUB_Script *deflt = NULL;
5381     int i;
5382     script = (const GSUB_ScriptList*)((const BYTE*)header + GET_BE_WORD(header->ScriptList));
5383
5384     TRACE("%i scripts in this font\n",GET_BE_WORD(script->ScriptCount));
5385     for (i = 0; i < GET_BE_WORD(script->ScriptCount); i++)
5386     {
5387         const GSUB_Script *scr;
5388         int offset;
5389
5390         offset = GET_BE_WORD(script->ScriptRecord[i].Script);
5391         scr = (const GSUB_Script*)((const BYTE*)script + offset);
5392
5393         if (strncmp(script->ScriptRecord[i].ScriptTag, tag,4)==0)
5394             return scr;
5395         if (strncmp(script->ScriptRecord[i].ScriptTag, "dflt",4)==0)
5396             deflt = scr;
5397     }
5398     return deflt;
5399 }
5400
5401 static const GSUB_LangSys* GSUB_get_lang_table( const GSUB_Script* script, const char* tag)
5402 {
5403     int i;
5404     int offset;
5405     const GSUB_LangSys *Lang;
5406
5407     TRACE("Deflang %x, LangCount %i\n",GET_BE_WORD(script->DefaultLangSys), GET_BE_WORD(script->LangSysCount));
5408
5409     for (i = 0; i < GET_BE_WORD(script->LangSysCount) ; i++)
5410     {
5411         offset = GET_BE_WORD(script->LangSysRecord[i].LangSys);
5412         Lang = (const GSUB_LangSys*)((const BYTE*)script + offset);
5413
5414         if ( strncmp(script->LangSysRecord[i].LangSysTag,tag,4)==0)
5415             return Lang;
5416     }
5417     offset = GET_BE_WORD(script->DefaultLangSys);
5418     if (offset)
5419     {
5420         Lang = (const GSUB_LangSys*)((const BYTE*)script + offset);
5421         return Lang;
5422     }
5423     return NULL;
5424 }
5425
5426 static const GSUB_Feature * GSUB_get_feature(const GSUB_Header *header, const GSUB_LangSys *lang, const char* tag)
5427 {
5428     int i;
5429     const GSUB_FeatureList *feature;
5430     feature = (const GSUB_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList));
5431
5432     TRACE("%i features\n",GET_BE_WORD(lang->FeatureCount));
5433     for (i = 0; i < GET_BE_WORD(lang->FeatureCount); i++)
5434     {
5435         int index = GET_BE_WORD(lang->FeatureIndex[i]);
5436         if (strncmp(feature->FeatureRecord[index].FeatureTag,tag,4)==0)
5437         {
5438             const GSUB_Feature *feat;
5439             feat = (const GSUB_Feature*)((const BYTE*)feature + GET_BE_WORD(feature->FeatureRecord[index].Feature));
5440             return feat;
5441         }
5442     }
5443     return NULL;
5444 }
5445
5446 static FT_UInt GSUB_apply_feature(const GSUB_Header * header, const GSUB_Feature* feature, UINT glyph)
5447 {
5448     int i;
5449     int offset;
5450     const GSUB_LookupList *lookup;
5451     lookup = (const GSUB_LookupList*)((const BYTE*)header + GET_BE_WORD(header->LookupList));
5452
5453     TRACE("%i lookups\n", GET_BE_WORD(feature->LookupCount));
5454     for (i = 0; i < GET_BE_WORD(feature->LookupCount); i++)
5455     {
5456         const GSUB_LookupTable *look;
5457         offset = GET_BE_WORD(lookup->Lookup[GET_BE_WORD(feature->LookupListIndex[i])]);
5458         look = (const GSUB_LookupTable*)((const BYTE*)lookup + offset);
5459         TRACE("type %i, flag %x, subtables %i\n",GET_BE_WORD(look->LookupType),GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount));
5460         if (GET_BE_WORD(look->LookupType) != 1)
5461             FIXME("We only handle SubType 1\n");
5462         else
5463         {
5464             int j;
5465
5466             for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
5467             {
5468                 const GSUB_SingleSubstFormat1 *ssf1;
5469                 offset = GET_BE_WORD(look->SubTable[j]);
5470                 ssf1 = (const GSUB_SingleSubstFormat1*)((const BYTE*)look+offset);
5471                 if (GET_BE_WORD(ssf1->SubstFormat) == 1)
5472                 {
5473                     int offset = GET_BE_WORD(ssf1->Coverage);
5474                     TRACE("  subtype 1, delta %i\n", GET_BE_WORD(ssf1->DeltaGlyphID));
5475                     if (GSUB_is_glyph_covered((const BYTE*)ssf1+offset, glyph) != -1)
5476                     {
5477                         TRACE("  Glyph 0x%x ->",glyph);
5478                         glyph += GET_BE_WORD(ssf1->DeltaGlyphID);
5479                         TRACE(" 0x%x\n",glyph);
5480                     }
5481                 }
5482                 else
5483                 {
5484                     const GSUB_SingleSubstFormat2 *ssf2;
5485                     INT index;
5486                     INT offset;
5487
5488                     ssf2 = (const GSUB_SingleSubstFormat2 *)ssf1;
5489                     offset = GET_BE_WORD(ssf1->Coverage);
5490                     TRACE("  subtype 2,  glyph count %i\n", GET_BE_WORD(ssf2->GlyphCount));
5491                     index = GSUB_is_glyph_covered((const BYTE*)ssf2+offset, glyph);
5492                     TRACE("  Coverage index %i\n",index);
5493                     if (index != -1)
5494                     {
5495                         TRACE("    Glyph is 0x%x ->",glyph);
5496                         glyph = GET_BE_WORD(ssf2->Substitute[index]);
5497                         TRACE("0x%x\n",glyph);
5498                     }
5499                 }
5500             }
5501         }
5502     }
5503     return glyph;
5504 }
5505
5506 static const char* get_opentype_script(const GdiFont *font)
5507 {
5508     /*
5509      * I am not sure if this is the correct way to generate our script tag
5510      */
5511
5512     switch (font->charset)
5513     {
5514         case ANSI_CHARSET: return "latn";
5515         case BALTIC_CHARSET: return "latn"; /* ?? */
5516         case CHINESEBIG5_CHARSET: return "hani";
5517         case EASTEUROPE_CHARSET: return "latn"; /* ?? */
5518         case GB2312_CHARSET: return "hani";
5519         case GREEK_CHARSET: return "grek";
5520         case HANGUL_CHARSET: return "hang";
5521         case RUSSIAN_CHARSET: return "cyrl";
5522         case SHIFTJIS_CHARSET: return "kana";
5523         case TURKISH_CHARSET: return "latn"; /* ?? */
5524         case VIETNAMESE_CHARSET: return "latn";
5525         case JOHAB_CHARSET: return "latn"; /* ?? */
5526         case ARABIC_CHARSET: return "arab";
5527         case HEBREW_CHARSET: return "hebr";
5528         case THAI_CHARSET: return "thai";
5529         default: return "latn";
5530     }
5531 }
5532
5533 static FT_UInt get_GSUB_vert_glyph(const GdiFont *font, UINT glyph)
5534 {
5535     const GSUB_Header *header;
5536     const GSUB_Script *script;
5537     const GSUB_LangSys *language;
5538     const GSUB_Feature *feature;
5539
5540     if (!font->GSUB_Table)
5541         return glyph;
5542
5543     header = font->GSUB_Table;
5544
5545     script = GSUB_get_script_table(header, get_opentype_script(font));
5546     if (!script)
5547     {
5548         TRACE("Script not found\n");
5549         return glyph;
5550     }
5551     language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
5552     if (!language)
5553     {
5554         TRACE("Language not found\n");
5555         return glyph;
5556     }
5557     feature  =  GSUB_get_feature(header, language, "vrt2");
5558     if (!feature)
5559         feature  =  GSUB_get_feature(header, language, "vert");
5560     if (!feature)
5561     {
5562         TRACE("vrt2/vert feature not found\n");
5563         return glyph;
5564     }
5565     return GSUB_apply_feature(header, feature, glyph);
5566 }
5567
5568 static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph)
5569 {
5570     FT_UInt glyphId;
5571
5572     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
5573         WCHAR wc = (WCHAR)glyph;
5574         BOOL default_used;
5575         BOOL *default_used_pointer;
5576         FT_UInt ret;
5577         char buf;
5578         default_used_pointer = NULL;
5579         default_used = FALSE;
5580         if (codepage_sets_default_used(font->codepage))
5581             default_used_pointer = &default_used;
5582         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
5583             ret = 0;
5584         else
5585             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
5586         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
5587         return ret;
5588     }
5589
5590     if(font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
5591     {
5592         if (glyph < 0x100) glyph += 0xf000;
5593         /* there is a number of old pre-Unicode "broken" TTFs, which
5594            do have symbols at U+00XX instead of U+f0XX */
5595         if (!(glyphId = pFT_Get_Char_Index(font->ft_face, glyph)))
5596             glyphId = pFT_Get_Char_Index(font->ft_face, glyph-0xf000);
5597     }
5598     else glyphId = pFT_Get_Char_Index(font->ft_face, glyph);
5599
5600     return glyphId;
5601 }
5602
5603 /*************************************************************
5604  * freetype_GetGlyphIndices
5605  */
5606 static DWORD freetype_GetGlyphIndices( PHYSDEV dev, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags )
5607 {
5608     struct freetype_physdev *physdev = get_freetype_dev( dev );
5609     int i;
5610     WORD default_char;
5611     BOOL got_default = FALSE;
5612
5613     if (!physdev->font)
5614     {
5615         dev = GET_NEXT_PHYSDEV( dev, pGetGlyphIndices );
5616         return dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
5617     }
5618
5619     if (flags & GGI_MARK_NONEXISTING_GLYPHS)
5620     {
5621         default_char = 0xffff;  /* XP would use 0x1f for bitmap fonts */
5622         got_default = TRUE;
5623     }
5624
5625     GDI_CheckNotLock();
5626     EnterCriticalSection( &freetype_cs );
5627
5628     for(i = 0; i < count; i++)
5629     {
5630         pgi[i] = get_glyph_index(physdev->font, lpstr[i]);
5631         if  (pgi[i] == 0)
5632         {
5633             if (!got_default)
5634             {
5635                 if (FT_IS_SFNT(physdev->font->ft_face))
5636                 {
5637                     TT_OS2 *pOS2 = pFT_Get_Sfnt_Table(physdev->font->ft_face, ft_sfnt_os2);
5638                     default_char = (pOS2->usDefaultChar ? get_glyph_index(physdev->font, pOS2->usDefaultChar) : 0);
5639                 }
5640                 else
5641                 {
5642                     TEXTMETRICW textm;
5643                     get_text_metrics(physdev->font, &textm);
5644                     default_char = textm.tmDefaultChar;
5645                 }
5646                 got_default = TRUE;
5647             }
5648             pgi[i] = default_char;
5649         }
5650     }
5651     LeaveCriticalSection( &freetype_cs );
5652     return count;
5653 }
5654
5655 static inline BOOL is_identity_FMAT2(const FMAT2 *matrix)
5656 {
5657     static const FMAT2 identity = { 1.0, 0.0, 0.0, 1.0 };
5658     return !memcmp(matrix, &identity, sizeof(FMAT2));
5659 }
5660
5661 static inline BOOL is_identity_MAT2(const MAT2 *matrix)
5662 {
5663     static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
5664     return !memcmp(matrix, &identity, sizeof(MAT2));
5665 }
5666
5667 static inline BYTE get_max_level( UINT format )
5668 {
5669     switch( format )
5670     {
5671     case GGO_GRAY2_BITMAP: return 4;
5672     case GGO_GRAY4_BITMAP: return 16;
5673     case GGO_GRAY8_BITMAP: return 64;
5674     }
5675     return 255;
5676 }
5677
5678 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5679
5680 static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
5681                                LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
5682                                const MAT2* lpmat)
5683 {
5684     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
5685     FT_Face ft_face = incoming_font->ft_face;
5686     GdiFont *font = incoming_font;
5687     FT_UInt glyph_index;
5688     DWORD width, height, pitch, needed = 0;
5689     FT_Bitmap ft_bitmap;
5690     FT_Error err;
5691     INT left, right, top = 0, bottom = 0, adv, lsb, bbx;
5692     FT_Angle angle = 0;
5693     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
5694     double widthRatio = 1.0;
5695     FT_Matrix transMat = identityMat;
5696     FT_Matrix transMatUnrotated;
5697     BOOL needsTransform = FALSE;
5698     BOOL tategaki = (font->GSUB_Table != NULL);
5699     UINT original_index;
5700
5701     TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
5702           buflen, buf, lpmat);
5703
5704     TRACE("font transform %f %f %f %f\n",
5705           font->font_desc.matrix.eM11, font->font_desc.matrix.eM12,
5706           font->font_desc.matrix.eM21, font->font_desc.matrix.eM22);
5707
5708     if(format & GGO_GLYPH_INDEX) {
5709         glyph_index = get_GSUB_vert_glyph(incoming_font,glyph);
5710         original_index = glyph;
5711         format &= ~GGO_GLYPH_INDEX;
5712     } else {
5713         get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index);
5714         ft_face = font->ft_face;
5715         original_index = glyph_index;
5716     }
5717
5718     if(format & GGO_UNHINTED) {
5719         load_flags |= FT_LOAD_NO_HINTING;
5720         format &= ~GGO_UNHINTED;
5721     }
5722
5723     /* tategaki never appears to happen to lower glyph index */
5724     if (glyph_index < TATEGAKI_LOWER_BOUND )
5725         tategaki = FALSE;
5726
5727     if(original_index >= font->gmsize * GM_BLOCK_SIZE) {
5728         font->gmsize = (original_index / GM_BLOCK_SIZE + 1);
5729         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
5730                                font->gmsize * sizeof(GM*));
5731     } else {
5732         if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL &&
5733             FONT_GM(font,original_index)->init && is_identity_MAT2(lpmat))
5734         {
5735             *lpgm = FONT_GM(font,original_index)->gm;
5736             TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
5737                   wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
5738                   lpgm->gmCellIncX, lpgm->gmCellIncY);
5739             return 1; /* FIXME */
5740         }
5741     }
5742
5743     if (!font->gm[original_index / GM_BLOCK_SIZE])
5744         font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
5745
5746     /* Scaling factor */
5747     if (font->aveWidth)
5748     {
5749         TEXTMETRICW tm;
5750
5751         get_text_metrics(font, &tm);
5752
5753         widthRatio = (double)font->aveWidth;
5754         widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5755     }
5756     else
5757         widthRatio = font->scale_y;
5758
5759     /* Scaling transform */
5760     if (widthRatio != 1.0 || font->scale_y != 1.0)
5761     {
5762         FT_Matrix scaleMat;
5763         scaleMat.xx = FT_FixedFromFloat(widthRatio);
5764         scaleMat.xy = 0;
5765         scaleMat.yx = 0;
5766         scaleMat.yy = FT_FixedFromFloat(font->scale_y);
5767
5768         pFT_Matrix_Multiply(&scaleMat, &transMat);
5769         needsTransform = TRUE;
5770     }
5771
5772     /* Slant transform */
5773     if (font->fake_italic) {
5774         FT_Matrix slantMat;
5775         
5776         slantMat.xx = (1 << 16);
5777         slantMat.xy = ((1 << 16) >> 2);
5778         slantMat.yx = 0;
5779         slantMat.yy = (1 << 16);
5780         pFT_Matrix_Multiply(&slantMat, &transMat);
5781         needsTransform = TRUE;
5782     }
5783
5784     /* Rotation transform */
5785     transMatUnrotated = transMat;
5786     if(font->orientation && !tategaki) {
5787         FT_Matrix rotationMat;
5788         FT_Vector vecAngle;
5789         angle = FT_FixedFromFloat((double)font->orientation / 10.0);
5790         pFT_Vector_Unit(&vecAngle, angle);
5791         rotationMat.xx = vecAngle.x;
5792         rotationMat.xy = -vecAngle.y;
5793         rotationMat.yx = -rotationMat.xy;
5794         rotationMat.yy = rotationMat.xx;
5795         
5796         pFT_Matrix_Multiply(&rotationMat, &transMat);
5797         needsTransform = TRUE;
5798     }
5799
5800     /* World transform */
5801     if (!is_identity_FMAT2(&font->font_desc.matrix))
5802     {
5803         FT_Matrix worldMat;
5804         worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11);
5805         worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM12);
5806         worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM21);
5807         worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22);
5808         pFT_Matrix_Multiply(&worldMat, &transMat);
5809         pFT_Matrix_Multiply(&worldMat, &transMatUnrotated);
5810         needsTransform = TRUE;
5811     }
5812
5813     /* Extra transformation specified by caller */
5814     if (!is_identity_MAT2(lpmat))
5815     {
5816         FT_Matrix extraMat;
5817         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
5818         extraMat.xy = FT_FixedFromFIXED(lpmat->eM12);
5819         extraMat.yx = FT_FixedFromFIXED(lpmat->eM21);
5820         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
5821         pFT_Matrix_Multiply(&extraMat, &transMat);
5822         pFT_Matrix_Multiply(&extraMat, &transMatUnrotated);
5823         needsTransform = TRUE;
5824     }
5825
5826     if (needsTransform || (format == GGO_NATIVE || format == GGO_BEZIER ||
5827                            format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
5828                            format == GGO_GRAY8_BITMAP))
5829     {
5830         load_flags |= FT_LOAD_NO_BITMAP;
5831     }
5832
5833     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
5834
5835     if(err) {
5836         WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
5837         return GDI_ERROR;
5838     }
5839
5840     if(!needsTransform) {
5841         left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64;
5842         right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64;
5843         adv = (INT)(ft_face->glyph->metrics.horiAdvance + 63) >> 6;
5844
5845         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
5846         bottom = (ft_face->glyph->metrics.horiBearingY -
5847                   ft_face->glyph->metrics.height) & -64;
5848         lpgm->gmCellIncX = adv;
5849         lpgm->gmCellIncY = 0;
5850     } else {
5851         INT xc, yc;
5852         FT_Vector vec;
5853
5854         left = right = 0;
5855
5856         for(xc = 0; xc < 2; xc++) {
5857             for(yc = 0; yc < 2; yc++) {
5858                 vec.x = (ft_face->glyph->metrics.horiBearingX +
5859                   xc * ft_face->glyph->metrics.width);
5860                 vec.y = ft_face->glyph->metrics.horiBearingY -
5861                   yc * ft_face->glyph->metrics.height;
5862                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
5863                 pFT_Vector_Transform(&vec, &transMat);
5864                 if(xc == 0 && yc == 0) {
5865                     left = right = vec.x;
5866                     top = bottom = vec.y;
5867                 } else {
5868                     if(vec.x < left) left = vec.x;
5869                     else if(vec.x > right) right = vec.x;
5870                     if(vec.y < bottom) bottom = vec.y;
5871                     else if(vec.y > top) top = vec.y;
5872                 }
5873             }
5874         }
5875         left = left & -64;
5876         right = (right + 63) & -64;
5877         bottom = bottom & -64;
5878         top = (top + 63) & -64;
5879
5880         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
5881         vec.x = ft_face->glyph->metrics.horiAdvance;
5882         vec.y = 0;
5883         pFT_Vector_Transform(&vec, &transMat);
5884         lpgm->gmCellIncX = (vec.x+63) >> 6;
5885         lpgm->gmCellIncY = -((vec.y+63) >> 6);
5886
5887         vec.x = ft_face->glyph->metrics.horiAdvance;
5888         vec.y = 0;
5889         pFT_Vector_Transform(&vec, &transMatUnrotated);
5890         adv = (vec.x+63) >> 6;
5891     }
5892
5893     lsb = left >> 6;
5894     bbx = (right - left) >> 6;
5895     lpgm->gmBlackBoxX = (right - left) >> 6;
5896     lpgm->gmBlackBoxY = (top - bottom) >> 6;
5897     lpgm->gmptGlyphOrigin.x = left >> 6;
5898     lpgm->gmptGlyphOrigin.y = top >> 6;
5899
5900     TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
5901           wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
5902           lpgm->gmCellIncX, lpgm->gmCellIncY);
5903
5904     if ((format == GGO_METRICS || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
5905         is_identity_MAT2(lpmat)) /* don't cache custom transforms */
5906     {
5907         FONT_GM(font,original_index)->gm = *lpgm;
5908         FONT_GM(font,original_index)->adv = adv;
5909         FONT_GM(font,original_index)->lsb = lsb;
5910         FONT_GM(font,original_index)->bbx = bbx;
5911         FONT_GM(font,original_index)->init = TRUE;
5912     }
5913
5914     if(format == GGO_METRICS)
5915     {
5916         return 1; /* FIXME */
5917     }
5918
5919     if(ft_face->glyph->format != ft_glyph_format_outline &&
5920        (format == GGO_NATIVE || format == GGO_BEZIER))
5921     {
5922         TRACE("loaded a bitmap\n");
5923         return GDI_ERROR;
5924     }
5925
5926     switch(format) {
5927     case GGO_BITMAP:
5928         width = lpgm->gmBlackBoxX;
5929         height = lpgm->gmBlackBoxY;
5930         pitch = ((width + 31) >> 5) << 2;
5931         needed = pitch * height;
5932
5933         if(!buf || !buflen) break;
5934
5935         switch(ft_face->glyph->format) {
5936         case ft_glyph_format_bitmap:
5937           {
5938             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
5939             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
5940             INT h = ft_face->glyph->bitmap.rows;
5941             while(h--) {
5942                 memcpy(dst, src, w);
5943                 src += ft_face->glyph->bitmap.pitch;
5944                 dst += pitch;
5945             }
5946             break;
5947           }
5948
5949         case ft_glyph_format_outline:
5950             ft_bitmap.width = width;
5951             ft_bitmap.rows = height;
5952             ft_bitmap.pitch = pitch;
5953             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
5954             ft_bitmap.buffer = buf;
5955
5956             if(needsTransform)
5957                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
5958
5959             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
5960
5961             /* Note: FreeType will only set 'black' bits for us. */
5962             memset(buf, 0, needed);
5963             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
5964             break;
5965
5966         default:
5967             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
5968             return GDI_ERROR;
5969         }
5970         break;
5971
5972     case GGO_GRAY2_BITMAP:
5973     case GGO_GRAY4_BITMAP:
5974     case GGO_GRAY8_BITMAP:
5975     case WINE_GGO_GRAY16_BITMAP:
5976       {
5977         unsigned int max_level, row, col;
5978         BYTE *start, *ptr;
5979
5980         width = lpgm->gmBlackBoxX;
5981         height = lpgm->gmBlackBoxY;
5982         pitch = (width + 3) / 4 * 4;
5983         needed = pitch * height;
5984
5985         if(!buf || !buflen) break;
5986
5987         max_level = get_max_level( format );
5988
5989         switch(ft_face->glyph->format) {
5990         case ft_glyph_format_bitmap:
5991           {
5992             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
5993             INT h = ft_face->glyph->bitmap.rows;
5994             INT x;
5995             memset( buf, 0, needed );
5996             while(h--) {
5997                 for(x = 0; x < pitch && x < ft_face->glyph->bitmap.width; x++)
5998                     if (src[x / 8] & masks[x % 8]) dst[x] = max_level;
5999                 src += ft_face->glyph->bitmap.pitch;
6000                 dst += pitch;
6001             }
6002             return needed;
6003           }
6004         case ft_glyph_format_outline:
6005           {
6006             ft_bitmap.width = width;
6007             ft_bitmap.rows = height;
6008             ft_bitmap.pitch = pitch;
6009             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
6010             ft_bitmap.buffer = buf;
6011
6012             if(needsTransform)
6013                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
6014
6015             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
6016
6017             memset(ft_bitmap.buffer, 0, buflen);
6018
6019             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
6020
6021             if (max_level != 255)
6022             {
6023                 for (row = 0, start = buf; row < height; row++)
6024                 {
6025                     for (col = 0, ptr = start; col < width; col++, ptr++)
6026                         *ptr = (((int)*ptr) * (max_level + 1)) / 256;
6027                     start += pitch;
6028                 }
6029             }
6030             return needed;
6031           }
6032
6033         default:
6034             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
6035             return GDI_ERROR;
6036         }
6037         break;
6038       }
6039
6040     case WINE_GGO_HRGB_BITMAP:
6041     case WINE_GGO_HBGR_BITMAP:
6042     case WINE_GGO_VRGB_BITMAP:
6043     case WINE_GGO_VBGR_BITMAP:
6044 #ifdef HAVE_FREETYPE_FTLCDFIL_H
6045       {
6046         switch (ft_face->glyph->format)
6047         {
6048         case FT_GLYPH_FORMAT_BITMAP:
6049           {
6050             BYTE *src, *dst;
6051             INT src_pitch, x;
6052
6053             width  = lpgm->gmBlackBoxX;
6054             height = lpgm->gmBlackBoxY;
6055             pitch  = width * 4;
6056             needed = pitch * height;
6057
6058             if (!buf || !buflen) break;
6059
6060             memset(buf, 0, buflen);
6061             dst = buf;
6062             src = ft_face->glyph->bitmap.buffer;
6063             src_pitch = ft_face->glyph->bitmap.pitch;
6064
6065             height = min( height, ft_face->glyph->bitmap.rows );
6066             while ( height-- )
6067             {
6068                 for (x = 0; x < width && x < ft_face->glyph->bitmap.width; x++)
6069                 {
6070                     if ( src[x / 8] & masks[x % 8] )
6071                         ((unsigned int *)dst)[x] = ~0u;
6072                 }
6073                 src += src_pitch;
6074                 dst += pitch;
6075             }
6076
6077             break;
6078           }
6079
6080         case FT_GLYPH_FORMAT_OUTLINE:
6081           {
6082             unsigned int *dst;
6083             BYTE *src;
6084             INT x, src_pitch, src_width, src_height, rgb_interval, hmul, vmul;
6085             INT x_shift, y_shift;
6086             BOOL rgb;
6087             FT_LcdFilter lcdfilter = FT_LCD_FILTER_DEFAULT;
6088             FT_Render_Mode render_mode =
6089                 (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_HBGR_BITMAP)?
6090                     FT_RENDER_MODE_LCD: FT_RENDER_MODE_LCD_V;
6091
6092             if ( lcdfilter == FT_LCD_FILTER_DEFAULT || lcdfilter == FT_LCD_FILTER_LIGHT )
6093             {
6094                 if ( render_mode == FT_RENDER_MODE_LCD)
6095                 {
6096                     lpgm->gmBlackBoxX += 2;
6097                     lpgm->gmptGlyphOrigin.x -= 1;
6098                 }
6099                 else
6100                 {
6101                     lpgm->gmBlackBoxY += 2;
6102                     lpgm->gmptGlyphOrigin.y += 1;
6103                 }
6104             }
6105
6106             width  = lpgm->gmBlackBoxX;
6107             height = lpgm->gmBlackBoxY;
6108             pitch  = width * 4;
6109             needed = pitch * height;
6110
6111             if (!buf || !buflen) break;
6112
6113             memset(buf, 0, buflen);
6114             dst = buf;
6115             rgb = (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_VRGB_BITMAP);
6116
6117             if ( needsTransform )
6118                 pFT_Outline_Transform (&ft_face->glyph->outline, &transMat);
6119
6120             if ( pFT_Library_SetLcdFilter )
6121                 pFT_Library_SetLcdFilter( library, lcdfilter );
6122             pFT_Render_Glyph (ft_face->glyph, render_mode);
6123
6124             src = ft_face->glyph->bitmap.buffer;
6125             src_pitch = ft_face->glyph->bitmap.pitch;
6126             src_width = ft_face->glyph->bitmap.width;
6127             src_height = ft_face->glyph->bitmap.rows;
6128
6129             if ( render_mode == FT_RENDER_MODE_LCD)
6130             {
6131                 rgb_interval = 1;
6132                 hmul = 3;
6133                 vmul = 1;
6134             }
6135             else
6136             {
6137                 rgb_interval = src_pitch;
6138                 hmul = 1;
6139                 vmul = 3;
6140             }
6141
6142             x_shift = ft_face->glyph->bitmap_left - lpgm->gmptGlyphOrigin.x;
6143             if ( x_shift < 0 ) x_shift = 0;
6144             if ( x_shift + (src_width / hmul) > width )
6145                 x_shift = width - (src_width / hmul);
6146
6147             y_shift = lpgm->gmptGlyphOrigin.y - ft_face->glyph->bitmap_top;
6148             if ( y_shift < 0 ) y_shift = 0;
6149             if ( y_shift + (src_height / vmul) > height )
6150                 y_shift = height - (src_height / vmul);
6151
6152             dst += x_shift + y_shift * ( pitch / 4 );
6153             while ( src_height )
6154             {
6155                 for ( x = 0; x < src_width / hmul; x++ )
6156                 {
6157                     if ( rgb )
6158                     {
6159                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 0] << 16) |
6160                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
6161                                  ((unsigned int)src[hmul * x + rgb_interval * 2] <<  0) |
6162                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
6163                     }
6164                     else
6165                     {
6166                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 2] << 16) |
6167                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
6168                                  ((unsigned int)src[hmul * x + rgb_interval * 0] <<  0) |
6169                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
6170                     }
6171                 }
6172                 src += src_pitch * vmul;
6173                 dst += pitch / 4;
6174                 src_height -= vmul;
6175             }
6176
6177             break;
6178           }
6179
6180         default:
6181             FIXME ("loaded glyph format %x\n", ft_face->glyph->format);
6182             return GDI_ERROR;
6183         }
6184
6185         break;
6186       }
6187 #else
6188       return GDI_ERROR;
6189 #endif
6190
6191     case GGO_NATIVE:
6192       {
6193         int contour, point = 0, first_pt;
6194         FT_Outline *outline = &ft_face->glyph->outline;
6195         TTPOLYGONHEADER *pph;
6196         TTPOLYCURVE *ppc;
6197         DWORD pph_start, cpfx, type;
6198
6199         if(buflen == 0) buf = NULL;
6200
6201         if (needsTransform && buf) {
6202                 pFT_Outline_Transform(outline, &transMat);
6203         }
6204
6205         for(contour = 0; contour < outline->n_contours; contour++) {
6206             pph_start = needed;
6207             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
6208             first_pt = point;
6209             if(buf) {
6210                 pph->dwType = TT_POLYGON_TYPE;
6211                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
6212             }
6213             needed += sizeof(*pph);
6214             point++;
6215             while(point <= outline->contours[contour]) {
6216                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
6217                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
6218                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
6219                 cpfx = 0;
6220                 do {
6221                     if(buf)
6222                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
6223                     cpfx++;
6224                     point++;
6225                 } while(point <= outline->contours[contour] &&
6226                         (outline->tags[point] & FT_Curve_Tag_On) ==
6227                         (outline->tags[point-1] & FT_Curve_Tag_On));
6228                 /* At the end of a contour Windows adds the start point, but
6229                    only for Beziers */
6230                 if(point > outline->contours[contour] &&
6231                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
6232                     if(buf)
6233                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
6234                     cpfx++;
6235                 } else if(point <= outline->contours[contour] &&
6236                           outline->tags[point] & FT_Curve_Tag_On) {
6237                   /* add closing pt for bezier */
6238                     if(buf)
6239                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
6240                     cpfx++;
6241                     point++;
6242                 }
6243                 if(buf) {
6244                     ppc->wType = type;
6245                     ppc->cpfx = cpfx;
6246                 }
6247                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
6248             }
6249             if(buf)
6250                 pph->cb = needed - pph_start;
6251         }
6252         break;
6253       }
6254     case GGO_BEZIER:
6255       {
6256         /* Convert the quadratic Beziers to cubic Beziers.
6257            The parametric eqn for a cubic Bezier is, from PLRM:
6258            r(t) = at^3 + bt^2 + ct + r0
6259            with the control points:
6260            r1 = r0 + c/3
6261            r2 = r1 + (c + b)/3
6262            r3 = r0 + c + b + a
6263
6264            A quadratic Bezier has the form:
6265            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
6266
6267            So equating powers of t leads to:
6268            r1 = 2/3 p1 + 1/3 p0
6269            r2 = 2/3 p1 + 1/3 p2
6270            and of course r0 = p0, r3 = p2
6271         */
6272
6273         int contour, point = 0, first_pt;
6274         FT_Outline *outline = &ft_face->glyph->outline;
6275         TTPOLYGONHEADER *pph;
6276         TTPOLYCURVE *ppc;
6277         DWORD pph_start, cpfx, type;
6278         FT_Vector cubic_control[4];
6279         if(buflen == 0) buf = NULL;
6280
6281         if (needsTransform && buf) {
6282                 pFT_Outline_Transform(outline, &transMat);
6283         }
6284
6285         for(contour = 0; contour < outline->n_contours; contour++) {
6286             pph_start = needed;
6287             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
6288             first_pt = point;
6289             if(buf) {
6290                 pph->dwType = TT_POLYGON_TYPE;
6291                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
6292             }
6293             needed += sizeof(*pph);
6294             point++;
6295             while(point <= outline->contours[contour]) {
6296                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
6297                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
6298                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
6299                 cpfx = 0;
6300                 do {
6301                     if(type == TT_PRIM_LINE) {
6302                         if(buf)
6303                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
6304                         cpfx++;
6305                         point++;
6306                     } else {
6307                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
6308                          so cpfx = 3n */
6309
6310                       /* FIXME: Possible optimization in endpoint calculation
6311                          if there are two consecutive curves */
6312                         cubic_control[0] = outline->points[point-1];
6313                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
6314                             cubic_control[0].x += outline->points[point].x + 1;
6315                             cubic_control[0].y += outline->points[point].y + 1;
6316                             cubic_control[0].x >>= 1;
6317                             cubic_control[0].y >>= 1;
6318                         }
6319                         if(point+1 > outline->contours[contour])
6320                             cubic_control[3] = outline->points[first_pt];
6321                         else {
6322                             cubic_control[3] = outline->points[point+1];
6323                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
6324                                 cubic_control[3].x += outline->points[point].x + 1;
6325                                 cubic_control[3].y += outline->points[point].y + 1;
6326                                 cubic_control[3].x >>= 1;
6327                                 cubic_control[3].y >>= 1;
6328                             }
6329                         }
6330                         /* r1 = 1/3 p0 + 2/3 p1
6331                            r2 = 1/3 p2 + 2/3 p1 */
6332                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
6333                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
6334                         cubic_control[2] = cubic_control[1];
6335                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
6336                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
6337                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
6338                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
6339                         if(buf) {
6340                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
6341                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
6342                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
6343                         }
6344                         cpfx += 3;
6345                         point++;
6346                     }
6347                 } while(point <= outline->contours[contour] &&
6348                         (outline->tags[point] & FT_Curve_Tag_On) ==
6349                         (outline->tags[point-1] & FT_Curve_Tag_On));
6350                 /* At the end of a contour Windows adds the start point,
6351                    but only for Beziers and we've already done that.
6352                 */
6353                 if(point <= outline->contours[contour] &&
6354                    outline->tags[point] & FT_Curve_Tag_On) {
6355                   /* This is the closing pt of a bezier, but we've already
6356                      added it, so just inc point and carry on */
6357                     point++;
6358                 }
6359                 if(buf) {
6360                     ppc->wType = type;
6361                     ppc->cpfx = cpfx;
6362                 }
6363                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
6364             }
6365             if(buf)
6366                 pph->cb = needed - pph_start;
6367         }
6368         break;
6369       }
6370
6371     default:
6372         FIXME("Unsupported format %d\n", format);
6373         return GDI_ERROR;
6374     }
6375     return needed;
6376 }
6377
6378 static BOOL get_bitmap_text_metrics(GdiFont *font)
6379 {
6380     FT_Face ft_face = font->ft_face;
6381     FT_WinFNT_HeaderRec winfnt_header;
6382     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
6383     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
6384     font->potm->otmSize = size;
6385
6386 #define TM font->potm->otmTextMetrics
6387     if(!pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
6388     {
6389         TM.tmHeight = winfnt_header.pixel_height;
6390         TM.tmAscent = winfnt_header.ascent;
6391         TM.tmDescent = TM.tmHeight - TM.tmAscent;
6392         TM.tmInternalLeading = winfnt_header.internal_leading;
6393         TM.tmExternalLeading = winfnt_header.external_leading;
6394         TM.tmAveCharWidth = winfnt_header.avg_width;
6395         TM.tmMaxCharWidth = winfnt_header.max_width;
6396         TM.tmWeight = winfnt_header.weight;
6397         TM.tmOverhang = 0;
6398         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
6399         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
6400         TM.tmFirstChar = winfnt_header.first_char;
6401         TM.tmLastChar = winfnt_header.last_char;
6402         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
6403         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
6404         TM.tmItalic = winfnt_header.italic;
6405         TM.tmUnderlined = font->underline;
6406         TM.tmStruckOut = font->strikeout;
6407         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
6408         TM.tmCharSet = winfnt_header.charset;
6409     }
6410     else
6411     {
6412         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
6413         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
6414         TM.tmHeight = TM.tmAscent + TM.tmDescent;
6415         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
6416         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
6417         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
6418         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
6419         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
6420         TM.tmOverhang = 0;
6421         TM.tmDigitizedAspectX = 96; /* FIXME */
6422         TM.tmDigitizedAspectY = 96; /* FIXME */
6423         TM.tmFirstChar = 1;
6424         TM.tmLastChar = 255;
6425         TM.tmDefaultChar = 32;
6426         TM.tmBreakChar = 32;
6427         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
6428         TM.tmUnderlined = font->underline;
6429         TM.tmStruckOut = font->strikeout;
6430         /* NB inverted meaning of TMPF_FIXED_PITCH */
6431         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
6432         TM.tmCharSet = font->charset;
6433     }
6434 #undef TM
6435
6436     return TRUE;
6437 }
6438
6439
6440 static void scale_font_metrics(const GdiFont *font, LPTEXTMETRICW ptm)
6441 {
6442     double scale_x, scale_y;
6443
6444     if (font->aveWidth)
6445     {
6446         scale_x = (double)font->aveWidth;
6447         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
6448     }
6449     else
6450         scale_x = font->scale_y;
6451
6452     scale_x *= fabs(font->font_desc.matrix.eM11);
6453     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
6454
6455 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
6456 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
6457
6458     SCALE_Y(ptm->tmHeight);
6459     SCALE_Y(ptm->tmAscent);
6460     SCALE_Y(ptm->tmDescent);
6461     SCALE_Y(ptm->tmInternalLeading);
6462     SCALE_Y(ptm->tmExternalLeading);
6463     SCALE_Y(ptm->tmOverhang);
6464
6465     SCALE_X(ptm->tmAveCharWidth);
6466     SCALE_X(ptm->tmMaxCharWidth);
6467
6468 #undef SCALE_X
6469 #undef SCALE_Y
6470 }
6471
6472 static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *potm)
6473 {
6474     double scale_x, scale_y;
6475
6476     if (font->aveWidth)
6477     {
6478         scale_x = (double)font->aveWidth;
6479         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
6480     }
6481     else
6482         scale_x = font->scale_y;
6483
6484     scale_x *= fabs(font->font_desc.matrix.eM11);
6485     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
6486
6487     scale_font_metrics(font, &potm->otmTextMetrics);
6488
6489 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
6490 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
6491
6492     SCALE_Y(potm->otmAscent);
6493     SCALE_Y(potm->otmDescent);
6494     SCALE_Y(potm->otmLineGap);
6495     SCALE_Y(potm->otmsCapEmHeight);
6496     SCALE_Y(potm->otmsXHeight);
6497     SCALE_Y(potm->otmrcFontBox.top);
6498     SCALE_Y(potm->otmrcFontBox.bottom);
6499     SCALE_X(potm->otmrcFontBox.left);
6500     SCALE_X(potm->otmrcFontBox.right);
6501     SCALE_Y(potm->otmMacAscent);
6502     SCALE_Y(potm->otmMacDescent);
6503     SCALE_Y(potm->otmMacLineGap);
6504     SCALE_X(potm->otmptSubscriptSize.x);
6505     SCALE_Y(potm->otmptSubscriptSize.y);
6506     SCALE_X(potm->otmptSubscriptOffset.x);
6507     SCALE_Y(potm->otmptSubscriptOffset.y);
6508     SCALE_X(potm->otmptSuperscriptSize.x);
6509     SCALE_Y(potm->otmptSuperscriptSize.y);
6510     SCALE_X(potm->otmptSuperscriptOffset.x);
6511     SCALE_Y(potm->otmptSuperscriptOffset.y);
6512     SCALE_Y(potm->otmsStrikeoutSize);
6513     SCALE_Y(potm->otmsStrikeoutPosition);
6514     SCALE_Y(potm->otmsUnderscoreSize);
6515     SCALE_Y(potm->otmsUnderscorePosition);
6516
6517 #undef SCALE_X
6518 #undef SCALE_Y
6519 }
6520
6521 static BOOL get_text_metrics(GdiFont *font, LPTEXTMETRICW ptm)
6522 {
6523     if(!font->potm)
6524     {
6525         if (!get_outline_text_metrics(font) && !get_bitmap_text_metrics(font)) return FALSE;
6526
6527         /* Make sure that the font has sane width/height ratio */
6528         if (font->aveWidth)
6529         {
6530             if ((font->aveWidth + font->potm->otmTextMetrics.tmHeight - 1) / font->potm->otmTextMetrics.tmHeight > 100)
6531             {
6532                 WARN("Ignoring too large font->aveWidth %d\n", font->aveWidth);
6533                 font->aveWidth = 0;
6534             }
6535         }
6536     }
6537     *ptm = font->potm->otmTextMetrics;
6538     scale_font_metrics(font, ptm);
6539     return TRUE;
6540 }
6541
6542 static BOOL face_has_symbol_charmap(FT_Face ft_face)
6543 {
6544     int i;
6545
6546     for(i = 0; i < ft_face->num_charmaps; i++)
6547     {
6548         if(ft_face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
6549             return TRUE;
6550     }
6551     return FALSE;
6552 }
6553
6554 static BOOL get_outline_text_metrics(GdiFont *font)
6555 {
6556     BOOL ret = FALSE;
6557     FT_Face ft_face = font->ft_face;
6558     UINT needed, lenfam, lensty, lenface, lenfull;
6559     TT_OS2 *pOS2;
6560     TT_HoriHeader *pHori;
6561     TT_Postscript *pPost;
6562     FT_Fixed x_scale, y_scale;
6563     WCHAR *family_nameW, *style_nameW, *face_nameW, *full_nameW;
6564     char *cp;
6565     INT ascent, descent;
6566
6567     TRACE("font=%p\n", font);
6568
6569     if(!FT_IS_SCALABLE(ft_face))
6570         return FALSE;
6571
6572     needed = sizeof(*font->potm);
6573
6574     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
6575     family_nameW = strdupW(font->name);
6576
6577     style_nameW = get_face_name( ft_face, TT_NAME_ID_FONT_SUBFAMILY, GetSystemDefaultLangID() );
6578     if (!style_nameW)
6579         style_nameW = get_face_name( ft_face, TT_NAME_ID_FONT_SUBFAMILY, TT_MS_LANGID_ENGLISH_UNITED_STATES );
6580     if (!style_nameW)
6581     {
6582         FIXME("failed to read style_nameW for font %s!\n", wine_dbgstr_w(font->name));
6583         lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0) * sizeof(WCHAR);
6584         style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
6585         MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, style_nameW, lensty/sizeof(WCHAR));
6586     }
6587     else
6588         lensty = (strlenW(style_nameW) + 1) * sizeof(WCHAR);
6589
6590     face_nameW = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, GetSystemDefaultLangID() );
6591     if (!face_nameW)
6592         face_nameW = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, TT_MS_LANGID_ENGLISH_UNITED_STATES );
6593     if (!face_nameW)
6594     {
6595         FIXME("failed to read face_nameW for font %s!\n", wine_dbgstr_w(font->name));
6596         face_nameW = strdupW(font->name);
6597     }
6598     if (font->name[0] == '@') face_nameW = prepend_at( face_nameW );
6599     lenface = (strlenW(face_nameW) + 1) * sizeof(WCHAR);
6600
6601     full_nameW = get_face_name( ft_face, TT_NAME_ID_UNIQUE_ID, GetSystemDefaultLangID() );
6602     if (!full_nameW)
6603         full_nameW = get_face_name( ft_face, TT_NAME_ID_UNIQUE_ID, TT_MS_LANGID_ENGLISH_UNITED_STATES );
6604     if (!full_nameW)
6605     {
6606         WCHAR fake_nameW[] = {'f','a','k','e',' ','n','a','m','e', 0};
6607         FIXME("failed to read full_nameW for font %s!\n", wine_dbgstr_w(font->name));
6608         full_nameW = strdupW(fake_nameW);
6609     }
6610     lenfull = (strlenW(full_nameW) + 1) * sizeof(WCHAR);
6611
6612     /* These names should be read from the TT name table */
6613
6614     /* length of otmpFamilyName */
6615     needed += lenfam;
6616
6617     /* length of otmpFaceName */
6618     needed += lenface;
6619
6620     /* length of otmpStyleName */
6621     needed += lensty;
6622
6623     /* length of otmpFullName */
6624     needed += lenfull;
6625
6626
6627     x_scale = ft_face->size->metrics.x_scale;
6628     y_scale = ft_face->size->metrics.y_scale;
6629
6630     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
6631     if(!pOS2) {
6632         FIXME("Can't find OS/2 table - not TT font?\n");
6633         goto end;
6634     }
6635
6636     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
6637     if(!pHori) {
6638         FIXME("Can't find HHEA table - not TT font?\n");
6639         goto end;
6640     }
6641
6642     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
6643
6644     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",
6645           pOS2->usWinAscent, pOS2->usWinDescent,
6646           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
6647           pOS2->xAvgCharWidth,
6648           ft_face->ascender, ft_face->descender, ft_face->height,
6649           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
6650           ft_face->bbox.yMax, ft_face->bbox.yMin);
6651
6652     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
6653     font->potm->otmSize = needed;
6654
6655 #define TM font->potm->otmTextMetrics
6656
6657     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
6658         ascent = pHori->Ascender;
6659         descent = -pHori->Descender;
6660     } else {
6661         ascent = pOS2->usWinAscent;
6662         descent = pOS2->usWinDescent;
6663     }
6664
6665     font->ntmCellHeight = ascent + descent;
6666     font->ntmAvgWidth = pOS2->xAvgCharWidth;
6667
6668     if(font->yMax) {
6669         TM.tmAscent = font->yMax;
6670         TM.tmDescent = -font->yMin;
6671         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
6672     } else {
6673         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
6674         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
6675         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
6676                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
6677     }
6678
6679     TM.tmHeight = TM.tmAscent + TM.tmDescent;
6680
6681     /* MSDN says:
6682      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
6683     */
6684     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
6685                  ((ascent + descent) -
6686                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
6687
6688     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
6689     if (TM.tmAveCharWidth == 0) {
6690         TM.tmAveCharWidth = 1; 
6691     }
6692     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
6693     TM.tmWeight = FW_REGULAR;
6694     if (font->fake_bold)
6695         TM.tmWeight = FW_BOLD;
6696     else
6697     {
6698         if (ft_face->style_flags & FT_STYLE_FLAG_BOLD)
6699         {
6700             if (pOS2->usWeightClass > FW_MEDIUM)
6701                 TM.tmWeight = pOS2->usWeightClass;
6702         }
6703         else if (pOS2->usWeightClass <= FW_MEDIUM)
6704             TM.tmWeight = pOS2->usWeightClass;
6705     }
6706     TM.tmOverhang = 0;
6707     TM.tmDigitizedAspectX = 96; /* FIXME */
6708     TM.tmDigitizedAspectY = 96; /* FIXME */
6709     /* It appears that for fonts with SYMBOL_CHARSET Windows always sets
6710      * symbol range to 0 - f0ff
6711      */
6712
6713     if (face_has_symbol_charmap(ft_face) || (pOS2->usFirstCharIndex >= 0xf000 && pOS2->usFirstCharIndex < 0xf100))
6714     {
6715         TM.tmFirstChar = 0;
6716         switch(GetACP())
6717         {
6718         case 1257: /* Baltic */
6719             TM.tmLastChar = 0xf8fd;
6720             break;
6721         default:
6722             TM.tmLastChar = 0xf0ff;
6723         }
6724         TM.tmBreakChar = 0x20;
6725         TM.tmDefaultChar = 0x1f;
6726     }
6727     else
6728     {
6729         TM.tmFirstChar = pOS2->usFirstCharIndex; /* Should be the first char in the cmap */
6730         TM.tmLastChar = pOS2->usLastCharIndex;   /* Should be min(cmap_last, os2_last) */
6731
6732         if(pOS2->usFirstCharIndex <= 1)
6733             TM.tmBreakChar = pOS2->usFirstCharIndex + 2;
6734         else if (pOS2->usFirstCharIndex > 0xff)
6735             TM.tmBreakChar = 0x20;
6736         else
6737             TM.tmBreakChar = pOS2->usFirstCharIndex;
6738         TM.tmDefaultChar = TM.tmBreakChar - 1;
6739     }
6740     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
6741     TM.tmUnderlined = font->underline;
6742     TM.tmStruckOut = font->strikeout;
6743
6744     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
6745     if(!FT_IS_FIXED_WIDTH(ft_face) &&
6746        (pOS2->version == 0xFFFFU || 
6747         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
6748         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
6749     else
6750         TM.tmPitchAndFamily = 0;
6751
6752     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX])
6753     {
6754     case PAN_FAMILY_SCRIPT:
6755         TM.tmPitchAndFamily |= FF_SCRIPT;
6756         break;
6757
6758     case PAN_FAMILY_DECORATIVE:
6759         TM.tmPitchAndFamily |= FF_DECORATIVE;
6760         break;
6761
6762     case PAN_ANY:
6763     case PAN_NO_FIT:
6764     case PAN_FAMILY_TEXT_DISPLAY:
6765     case PAN_FAMILY_PICTORIAL: /* symbol fonts get treated as if they were text */
6766                                /* which is clearly not what the panose spec says. */
6767     default:
6768         if(TM.tmPitchAndFamily == 0 || /* fixed */
6769            pOS2->panose[PAN_PROPORTION_INDEX] == PAN_PROP_MONOSPACED)
6770             TM.tmPitchAndFamily = FF_MODERN;
6771         else
6772         {
6773             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX])
6774             {
6775             case PAN_ANY:
6776             case PAN_NO_FIT:
6777             default:
6778                 TM.tmPitchAndFamily |= FF_DONTCARE;
6779                 break;
6780
6781             case PAN_SERIF_COVE:
6782             case PAN_SERIF_OBTUSE_COVE:
6783             case PAN_SERIF_SQUARE_COVE:
6784             case PAN_SERIF_OBTUSE_SQUARE_COVE:
6785             case PAN_SERIF_SQUARE:
6786             case PAN_SERIF_THIN:
6787             case PAN_SERIF_BONE:
6788             case PAN_SERIF_EXAGGERATED:
6789             case PAN_SERIF_TRIANGLE:
6790                 TM.tmPitchAndFamily |= FF_ROMAN;
6791                 break;
6792
6793             case PAN_SERIF_NORMAL_SANS:
6794             case PAN_SERIF_OBTUSE_SANS:
6795             case PAN_SERIF_PERP_SANS:
6796             case PAN_SERIF_FLARED:
6797             case PAN_SERIF_ROUNDED:
6798                 TM.tmPitchAndFamily |= FF_SWISS;
6799                 break;
6800             }
6801         }
6802         break;
6803     }
6804
6805     if(FT_IS_SCALABLE(ft_face))
6806         TM.tmPitchAndFamily |= TMPF_VECTOR;
6807
6808     if(FT_IS_SFNT(ft_face))
6809     {
6810         if (font->ntmFlags & NTM_PS_OPENTYPE)
6811             TM.tmPitchAndFamily |= TMPF_DEVICE;
6812         else
6813             TM.tmPitchAndFamily |= TMPF_TRUETYPE;
6814     }
6815
6816     TM.tmCharSet = font->charset;
6817
6818     font->potm->otmFiller = 0;
6819     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
6820     font->potm->otmfsSelection = pOS2->fsSelection;
6821     font->potm->otmfsType = pOS2->fsType;
6822     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
6823     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
6824     font->potm->otmItalicAngle = 0; /* POST table */
6825     font->potm->otmEMSquare = ft_face->units_per_EM;
6826     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
6827     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
6828     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
6829     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
6830     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
6831     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
6832     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
6833     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
6834     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
6835     font->potm->otmMacAscent = TM.tmAscent;
6836     font->potm->otmMacDescent = -TM.tmDescent;
6837     font->potm->otmMacLineGap = font->potm->otmLineGap;
6838     font->potm->otmusMinimumPPEM = 0; /* TT Header */
6839     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
6840     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
6841     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
6842     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
6843     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
6844     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
6845     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
6846     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
6847     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
6848     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
6849     if(!pPost) {
6850         font->potm->otmsUnderscoreSize = 0;
6851         font->potm->otmsUnderscorePosition = 0;
6852     } else {
6853         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
6854         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
6855     }
6856 #undef TM
6857
6858     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
6859     cp = (char*)font->potm + sizeof(*font->potm);
6860     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
6861     strcpyW((WCHAR*)cp, family_nameW);
6862     cp += lenfam;
6863     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
6864     strcpyW((WCHAR*)cp, style_nameW);
6865     cp += lensty;
6866     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
6867     strcpyW((WCHAR*)cp, face_nameW);
6868         cp += lenface;
6869     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
6870     strcpyW((WCHAR*)cp, full_nameW);
6871     ret = TRUE;
6872
6873 end:
6874     HeapFree(GetProcessHeap(), 0, style_nameW);
6875     HeapFree(GetProcessHeap(), 0, family_nameW);
6876     HeapFree(GetProcessHeap(), 0, face_nameW);
6877     HeapFree(GetProcessHeap(), 0, full_nameW);
6878     return ret;
6879 }
6880
6881 /*************************************************************
6882  * freetype_GetGlyphOutline
6883  */
6884 static DWORD freetype_GetGlyphOutline( PHYSDEV dev, UINT glyph, UINT format,
6885                                        LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf, const MAT2 *lpmat )
6886 {
6887     struct freetype_physdev *physdev = get_freetype_dev( dev );
6888     DWORD ret;
6889
6890     if (!physdev->font)
6891     {
6892         dev = GET_NEXT_PHYSDEV( dev, pGetGlyphOutline );
6893         return dev->funcs->pGetGlyphOutline( dev, glyph, format, lpgm, buflen, buf, lpmat );
6894     }
6895
6896     GDI_CheckNotLock();
6897     EnterCriticalSection( &freetype_cs );
6898     ret = get_glyph_outline( physdev->font, glyph, format, lpgm, buflen, buf, lpmat );
6899     LeaveCriticalSection( &freetype_cs );
6900     return ret;
6901 }
6902
6903 /*************************************************************
6904  * freetype_GetTextMetrics
6905  */
6906 static BOOL freetype_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
6907 {
6908     struct freetype_physdev *physdev = get_freetype_dev( dev );
6909     BOOL ret;
6910
6911     if (!physdev->font)
6912     {
6913         dev = GET_NEXT_PHYSDEV( dev, pGetTextMetrics );
6914         return dev->funcs->pGetTextMetrics( dev, metrics );
6915     }
6916
6917     GDI_CheckNotLock();
6918     EnterCriticalSection( &freetype_cs );
6919     ret = get_text_metrics( physdev->font, metrics );
6920     LeaveCriticalSection( &freetype_cs );
6921     return ret;
6922 }
6923
6924 /*************************************************************
6925  * freetype_GetOutlineTextMetrics
6926  */
6927 static UINT freetype_GetOutlineTextMetrics( PHYSDEV dev, UINT cbSize, OUTLINETEXTMETRICW *potm )
6928 {
6929     struct freetype_physdev *physdev = get_freetype_dev( dev );
6930     UINT ret = 0;
6931
6932     if (!physdev->font)
6933     {
6934         dev = GET_NEXT_PHYSDEV( dev, pGetOutlineTextMetrics );
6935         return dev->funcs->pGetOutlineTextMetrics( dev, cbSize, potm );
6936     }
6937
6938     TRACE("font=%p\n", physdev->font);
6939
6940     if (!FT_IS_SCALABLE( physdev->font->ft_face )) return 0;
6941
6942     GDI_CheckNotLock();
6943     EnterCriticalSection( &freetype_cs );
6944
6945     if (physdev->font->potm || get_outline_text_metrics( physdev->font ))
6946     {
6947         if(cbSize >= physdev->font->potm->otmSize)
6948         {
6949             memcpy(potm, physdev->font->potm, physdev->font->potm->otmSize);
6950             scale_outline_font_metrics(physdev->font, potm);
6951         }
6952         ret = physdev->font->potm->otmSize;
6953     }
6954     LeaveCriticalSection( &freetype_cs );
6955     return ret;
6956 }
6957
6958 static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
6959 {
6960     HFONTLIST *hfontlist;
6961     child->font = alloc_font();
6962     child->font->ft_face = OpenFontFace(child->font, child->face, 0, -font->ppem);
6963     if(!child->font->ft_face)
6964     {
6965         free_font(child->font);
6966         child->font = NULL;
6967         return FALSE;
6968     }
6969
6970     child->font->font_desc = font->font_desc;
6971     child->font->ntmFlags = child->face->ntmFlags;
6972     child->font->orientation = font->orientation;
6973     child->font->scale_y = font->scale_y;
6974     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
6975     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
6976     child->font->name = strdupW(child->face->family->FamilyName);
6977     list_add_head(&child->font->hfontlist, &hfontlist->entry);
6978     child->font->base_font = font;
6979     list_add_head(&child_font_list, &child->font->entry);
6980     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
6981     return TRUE;
6982 }
6983
6984 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph)
6985 {
6986     FT_UInt g;
6987     CHILD_FONT *child_font;
6988
6989     if(font->base_font)
6990         font = font->base_font;
6991
6992     *linked_font = font;
6993
6994     if((*glyph = get_glyph_index(font, c)))
6995     {
6996         *glyph = get_GSUB_vert_glyph(font, *glyph);
6997         return TRUE;
6998     }
6999
7000     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
7001     {
7002         if(!child_font->font)
7003             if(!load_child_font(font, child_font))
7004                 continue;
7005
7006         if(!child_font->font->ft_face)
7007             continue;
7008         g = get_glyph_index(child_font->font, c);
7009         g = get_GSUB_vert_glyph(child_font->font, g);
7010         if(g)
7011         {
7012             *glyph = g;
7013             *linked_font = child_font->font;
7014             return TRUE;
7015         }
7016     }
7017     return FALSE;
7018 }
7019
7020 /*************************************************************
7021  * freetype_GetCharWidth
7022  */
7023 static BOOL freetype_GetCharWidth( PHYSDEV dev, UINT firstChar, UINT lastChar, LPINT buffer )
7024 {
7025     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7026     UINT c;
7027     GLYPHMETRICS gm;
7028     FT_UInt glyph_index;
7029     GdiFont *linked_font;
7030     struct freetype_physdev *physdev = get_freetype_dev( dev );
7031
7032     if (!physdev->font)
7033     {
7034         dev = GET_NEXT_PHYSDEV( dev, pGetCharWidth );
7035         return dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
7036     }
7037
7038     TRACE("%p, %d, %d, %p\n", physdev->font, firstChar, lastChar, buffer);
7039
7040     GDI_CheckNotLock();
7041     EnterCriticalSection( &freetype_cs );
7042     for(c = firstChar; c <= lastChar; c++) {
7043         get_glyph_index_linked(physdev->font, c, &linked_font, &glyph_index);
7044         get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
7045                           &gm, 0, NULL, &identity);
7046         buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv;
7047     }
7048     LeaveCriticalSection( &freetype_cs );
7049     return TRUE;
7050 }
7051
7052 /*************************************************************
7053  * freetype_GetCharABCWidths
7054  */
7055 static BOOL freetype_GetCharABCWidths( PHYSDEV dev, UINT firstChar, UINT lastChar, LPABC buffer )
7056 {
7057     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7058     UINT c;
7059     GLYPHMETRICS gm;
7060     FT_UInt glyph_index;
7061     GdiFont *linked_font;
7062     struct freetype_physdev *physdev = get_freetype_dev( dev );
7063
7064     if (!physdev->font)
7065     {
7066         dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidths );
7067         return dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, buffer );
7068     }
7069
7070     TRACE("%p, %d, %d, %p\n", physdev->font, firstChar, lastChar, buffer);
7071
7072     GDI_CheckNotLock();
7073     EnterCriticalSection( &freetype_cs );
7074
7075     for(c = firstChar; c <= lastChar; c++) {
7076         get_glyph_index_linked(physdev->font, c, &linked_font, &glyph_index);
7077         get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
7078                           &gm, 0, NULL, &identity);
7079         buffer[c - firstChar].abcA = FONT_GM(linked_font,glyph_index)->lsb;
7080         buffer[c - firstChar].abcB = FONT_GM(linked_font,glyph_index)->bbx;
7081         buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb -
7082             FONT_GM(linked_font,glyph_index)->bbx;
7083     }
7084     LeaveCriticalSection( &freetype_cs );
7085     return TRUE;
7086 }
7087
7088 /*************************************************************
7089  * freetype_GetCharABCWidthsI
7090  */
7091 static BOOL freetype_GetCharABCWidthsI( PHYSDEV dev, UINT firstChar, UINT count, LPWORD pgi, LPABC buffer )
7092 {
7093     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7094     UINT c;
7095     GLYPHMETRICS gm;
7096     FT_UInt glyph_index;
7097     GdiFont *linked_font;
7098     struct freetype_physdev *physdev = get_freetype_dev( dev );
7099
7100     if (!physdev->font)
7101     {
7102         dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidthsI );
7103         return dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, buffer );
7104     }
7105
7106     if(!FT_HAS_HORIZONTAL(physdev->font->ft_face))
7107         return FALSE;
7108
7109     GDI_CheckNotLock();
7110     EnterCriticalSection( &freetype_cs );
7111
7112     get_glyph_index_linked(physdev->font, 'a', &linked_font, &glyph_index);
7113     if (!pgi)
7114         for(c = firstChar; c < firstChar+count; c++) {
7115             get_glyph_outline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
7116                               &gm, 0, NULL, &identity);
7117             buffer[c - firstChar].abcA = FONT_GM(linked_font,c)->lsb;
7118             buffer[c - firstChar].abcB = FONT_GM(linked_font,c)->bbx;
7119             buffer[c - firstChar].abcC = FONT_GM(linked_font,c)->adv - FONT_GM(linked_font,c)->lsb
7120                 - FONT_GM(linked_font,c)->bbx;
7121         }
7122     else
7123         for(c = 0; c < count; c++) {
7124             get_glyph_outline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
7125                               &gm, 0, NULL, &identity);
7126             buffer[c].abcA = FONT_GM(linked_font,pgi[c])->lsb;
7127             buffer[c].abcB = FONT_GM(linked_font,pgi[c])->bbx;
7128             buffer[c].abcC = FONT_GM(linked_font,pgi[c])->adv
7129                 - FONT_GM(linked_font,pgi[c])->lsb - FONT_GM(linked_font,pgi[c])->bbx;
7130         }
7131
7132     LeaveCriticalSection( &freetype_cs );
7133     return TRUE;
7134 }
7135
7136 /*************************************************************
7137  * freetype_GetTextExtentExPoint
7138  */
7139 static BOOL freetype_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR wstr, INT count,
7140                                            INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
7141 {
7142     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7143     INT idx;
7144     INT nfit = 0, ext;
7145     GLYPHMETRICS gm;
7146     TEXTMETRICW tm;
7147     FT_UInt glyph_index;
7148     GdiFont *linked_font;
7149     struct freetype_physdev *physdev = get_freetype_dev( dev );
7150
7151     if (!physdev->font)
7152     {
7153         dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPoint );
7154         return dev->funcs->pGetTextExtentExPoint( dev, wstr, count, max_ext, pnfit, dxs, size );
7155     }
7156
7157     TRACE("%p, %s, %d, %d, %p\n", physdev->font, debugstr_wn(wstr, count), count, max_ext, size);
7158
7159     GDI_CheckNotLock();
7160     EnterCriticalSection( &freetype_cs );
7161
7162     size->cx = 0;
7163     get_text_metrics( physdev->font, &tm );
7164     size->cy = tm.tmHeight;
7165
7166     for(idx = 0; idx < count; idx++) {
7167         get_glyph_index_linked( physdev->font, wstr[idx], &linked_font, &glyph_index );
7168         get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
7169                           &gm, 0, NULL, &identity);
7170         size->cx += FONT_GM(linked_font,glyph_index)->adv;
7171         ext = size->cx;
7172         if (! pnfit || ext <= max_ext) {
7173             ++nfit;
7174             if (dxs)
7175                 dxs[idx] = ext;
7176         }
7177     }
7178
7179     if (pnfit)
7180         *pnfit = nfit;
7181
7182     LeaveCriticalSection( &freetype_cs );
7183     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
7184     return TRUE;
7185 }
7186
7187 /*************************************************************
7188  * freetype_GetTextExtentExPointI
7189  */
7190 static BOOL freetype_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, INT count,
7191                                             INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size )
7192 {
7193     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7194     INT idx;
7195     INT nfit = 0, ext;
7196     GLYPHMETRICS gm;
7197     TEXTMETRICW tm;
7198     struct freetype_physdev *physdev = get_freetype_dev( dev );
7199
7200     if (!physdev->font)
7201     {
7202         dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPointI );
7203         return dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, pnfit, dxs, size );
7204     }
7205
7206     TRACE("%p, %p, %d, %d, %p\n", physdev->font, indices, count, max_ext, size);
7207
7208     GDI_CheckNotLock();
7209     EnterCriticalSection( &freetype_cs );
7210
7211     size->cx = 0;
7212     get_text_metrics(physdev->font, &tm);
7213     size->cy = tm.tmHeight;
7214
7215     for(idx = 0; idx < count; idx++) {
7216         get_glyph_outline(physdev->font, indices[idx], GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &identity);
7217         size->cx += FONT_GM(physdev->font,indices[idx])->adv;
7218         ext = size->cx;
7219         if (! pnfit || ext <= max_ext) {
7220             ++nfit;
7221             if (dxs)
7222                 dxs[idx] = ext;
7223         }
7224     }
7225
7226     if (pnfit)
7227         *pnfit = nfit;
7228
7229     LeaveCriticalSection( &freetype_cs );
7230     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
7231     return TRUE;
7232 }
7233
7234 /*************************************************************
7235  * freetype_GetFontData
7236  */
7237 static DWORD freetype_GetFontData( PHYSDEV dev, DWORD table, DWORD offset, LPVOID buf, DWORD cbData )
7238 {
7239     struct freetype_physdev *physdev = get_freetype_dev( dev );
7240
7241     if (!physdev->font)
7242     {
7243         dev = GET_NEXT_PHYSDEV( dev, pGetFontData );
7244         return dev->funcs->pGetFontData( dev, table, offset, buf, cbData );
7245     }
7246
7247     TRACE("font=%p, table=%c%c%c%c, offset=0x%x, buf=%p, cbData=0x%x\n",
7248           physdev->font, LOBYTE(LOWORD(table)), HIBYTE(LOWORD(table)),
7249           LOBYTE(HIWORD(table)), HIBYTE(HIWORD(table)), offset, buf, cbData);
7250
7251     return get_font_data( physdev->font, table, offset, buf, cbData );
7252 }
7253
7254 /*************************************************************
7255  * freetype_GetTextFace
7256  */
7257 static INT freetype_GetTextFace( PHYSDEV dev, INT count, LPWSTR str )
7258 {
7259     INT n;
7260     struct freetype_physdev *physdev = get_freetype_dev( dev );
7261
7262     if (!physdev->font)
7263     {
7264         dev = GET_NEXT_PHYSDEV( dev, pGetTextFace );
7265         return dev->funcs->pGetTextFace( dev, count, str );
7266     }
7267
7268     n = strlenW(physdev->font->name) + 1;
7269     if (str)
7270     {
7271         lstrcpynW(str, physdev->font->name, count);
7272         n = min(count, n);
7273     }
7274     return n;
7275 }
7276
7277 /*************************************************************
7278  * freetype_GetTextCharsetInfo
7279  */
7280 static UINT freetype_GetTextCharsetInfo( PHYSDEV dev, LPFONTSIGNATURE fs, DWORD flags )
7281 {
7282     struct freetype_physdev *physdev = get_freetype_dev( dev );
7283
7284     if (!physdev->font)
7285     {
7286         dev = GET_NEXT_PHYSDEV( dev, pGetTextCharsetInfo );
7287         return dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
7288     }
7289     if (fs) *fs = physdev->font->fs;
7290     return physdev->font->charset;
7291 }
7292
7293 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
7294 {
7295     GdiFont *font = dc->gdiFont, *linked_font;
7296     struct list *first_hfont;
7297     BOOL ret;
7298
7299     GDI_CheckNotLock();
7300     EnterCriticalSection( &freetype_cs );
7301     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
7302     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
7303     if(font == linked_font)
7304         *new_hfont = dc->hFont;
7305     else
7306     {
7307         first_hfont = list_head(&linked_font->hfontlist);
7308         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
7309     }
7310     LeaveCriticalSection( &freetype_cs );
7311     return ret;
7312 }
7313     
7314 /* Retrieve a list of supported Unicode ranges for a given font.
7315  * Can be called with NULL gs to calculate the buffer size. Returns
7316  * the number of ranges found.
7317  */
7318 static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
7319 {
7320     DWORD num_ranges = 0;
7321
7322     if (face->charmap->encoding == FT_ENCODING_UNICODE)
7323     {
7324         FT_UInt glyph_code;
7325         FT_ULong char_code, char_code_prev;
7326
7327         glyph_code = 0;
7328         char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
7329
7330         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
7331                face->num_glyphs, glyph_code, char_code);
7332
7333         if (!glyph_code) return 0;
7334
7335         if (gs)
7336         {
7337             gs->ranges[0].wcLow = (USHORT)char_code;
7338             gs->ranges[0].cGlyphs = 0;
7339             gs->cGlyphsSupported = 0;
7340         }
7341
7342         num_ranges = 1;
7343         while (glyph_code)
7344         {
7345             if (char_code < char_code_prev)
7346             {
7347                 ERR("expected increasing char code from FT_Get_Next_Char\n");
7348                 return 0;
7349             }
7350             if (char_code - char_code_prev > 1)
7351             {
7352                 num_ranges++;
7353                 if (gs)
7354                 {
7355                     gs->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
7356                     gs->ranges[num_ranges - 1].cGlyphs = 1;
7357                     gs->cGlyphsSupported++;
7358                 }
7359             }
7360             else if (gs)
7361             {
7362                 gs->ranges[num_ranges - 1].cGlyphs++;
7363                 gs->cGlyphsSupported++;
7364             }
7365             char_code_prev = char_code;
7366             char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
7367         }
7368     }
7369     else
7370         FIXME("encoding %u not supported\n", face->charmap->encoding);
7371
7372     return num_ranges;
7373 }
7374
7375 /*************************************************************
7376  * freetype_GetFontUnicodeRanges
7377  */
7378 static DWORD freetype_GetFontUnicodeRanges( PHYSDEV dev, LPGLYPHSET glyphset )
7379 {
7380     struct freetype_physdev *physdev = get_freetype_dev( dev );
7381     DWORD size, num_ranges;
7382
7383     if (!physdev->font)
7384     {
7385         dev = GET_NEXT_PHYSDEV( dev, pGetFontUnicodeRanges );
7386         return dev->funcs->pGetFontUnicodeRanges( dev, glyphset );
7387     }
7388
7389     num_ranges = get_font_unicode_ranges(physdev->font->ft_face, glyphset);
7390     size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
7391     if (glyphset)
7392     {
7393         glyphset->cbThis = size;
7394         glyphset->cRanges = num_ranges;
7395         glyphset->flAccel = 0;
7396     }
7397     return size;
7398 }
7399
7400 /*************************************************************
7401  * freetype_FontIsLinked
7402  */
7403 static BOOL freetype_FontIsLinked( PHYSDEV dev )
7404 {
7405     struct freetype_physdev *physdev = get_freetype_dev( dev );
7406     BOOL ret;
7407
7408     if (!physdev->font)
7409     {
7410         dev = GET_NEXT_PHYSDEV( dev, pFontIsLinked );
7411         return dev->funcs->pFontIsLinked( dev );
7412     }
7413
7414     GDI_CheckNotLock();
7415     EnterCriticalSection( &freetype_cs );
7416     ret = !list_empty(&physdev->font->child_fonts);
7417     LeaveCriticalSection( &freetype_cs );
7418     return ret;
7419 }
7420
7421 static BOOL is_hinting_enabled(void)
7422 {
7423     /* Use the >= 2.2.0 function if available */
7424     if(pFT_Get_TrueType_Engine_Type)
7425     {
7426         FT_TrueTypeEngineType type = pFT_Get_TrueType_Engine_Type(library);
7427         return type == FT_TRUETYPE_ENGINE_TYPE_PATENTED;
7428     }
7429 #ifdef FT_DRIVER_HAS_HINTER
7430     else
7431     {
7432         FT_Module mod;
7433
7434         /* otherwise if we've been compiled with < 2.2.0 headers 
7435            use the internal macro */
7436         mod = pFT_Get_Module(library, "truetype");
7437         if(mod && FT_DRIVER_HAS_HINTER(mod))
7438             return TRUE;
7439     }
7440 #endif
7441
7442     return FALSE;
7443 }
7444
7445 static BOOL is_subpixel_rendering_enabled( void )
7446 {
7447 #ifdef HAVE_FREETYPE_FTLCDFIL_H
7448     return pFT_Library_SetLcdFilter &&
7449            pFT_Library_SetLcdFilter( NULL, 0 ) != FT_Err_Unimplemented_Feature;
7450 #else
7451     return FALSE;
7452 #endif
7453 }
7454
7455 /*************************************************************************
7456  *             GetRasterizerCaps   (GDI32.@)
7457  */
7458 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
7459 {
7460     static int hinting = -1;
7461     static int subpixel = -1;
7462
7463     if(hinting == -1)
7464     {
7465         hinting = is_hinting_enabled();
7466         TRACE("hinting is %senabled\n", hinting ? "" : "NOT ");
7467     }
7468
7469     if ( subpixel == -1 )
7470     {
7471         subpixel = is_subpixel_rendering_enabled();
7472         TRACE("subpixel rendering is %senabled\n", subpixel ? "" : "NOT ");
7473     }
7474
7475     lprs->nSize = sizeof(RASTERIZER_STATUS);
7476     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
7477     if ( subpixel )
7478         lprs->wFlags |= WINE_TT_SUBPIXEL_RENDERING_ENABLED;
7479     lprs->nLanguageID = 0;
7480     return TRUE;
7481 }
7482
7483 /*************************************************************
7484  * freetype_GdiRealizationInfo
7485  */
7486 static BOOL freetype_GdiRealizationInfo( PHYSDEV dev, void *ptr )
7487 {
7488     struct freetype_physdev *physdev = get_freetype_dev( dev );
7489     realization_info_t *info = ptr;
7490
7491     if (!physdev->font)
7492     {
7493         dev = GET_NEXT_PHYSDEV( dev, pGdiRealizationInfo );
7494         return dev->funcs->pGdiRealizationInfo( dev, ptr );
7495     }
7496
7497     FIXME("(%p, %p): stub!\n", physdev->font, info);
7498
7499     info->flags = 1;
7500     if(FT_IS_SCALABLE(physdev->font->ft_face))
7501         info->flags |= 2;
7502
7503     info->cache_num = physdev->font->cache_num;
7504     info->unknown2 = -1;
7505     return TRUE;
7506 }
7507
7508 /*************************************************************************
7509  * Kerning support for TrueType fonts
7510  */
7511 #define MS_KERN_TAG MS_MAKE_TAG('k', 'e', 'r', 'n')
7512
7513 struct TT_kern_table
7514 {
7515     USHORT version;
7516     USHORT nTables;
7517 };
7518
7519 struct TT_kern_subtable
7520 {
7521     USHORT version;
7522     USHORT length;
7523     union
7524     {
7525         USHORT word;
7526         struct
7527         {
7528             USHORT horizontal : 1;
7529             USHORT minimum : 1;
7530             USHORT cross_stream: 1;
7531             USHORT override : 1;
7532             USHORT reserved1 : 4;
7533             USHORT format : 8;
7534         } bits;
7535     } coverage;
7536 };
7537
7538 struct TT_format0_kern_subtable
7539 {
7540     USHORT nPairs;
7541     USHORT searchRange;
7542     USHORT entrySelector;
7543     USHORT rangeShift;
7544 };
7545
7546 struct TT_kern_pair
7547 {
7548     USHORT left;
7549     USHORT right;
7550     short  value;
7551 };
7552
7553 static DWORD parse_format0_kern_subtable(GdiFont *font,
7554                                          const struct TT_format0_kern_subtable *tt_f0_ks,
7555                                          const USHORT *glyph_to_char,
7556                                          KERNINGPAIR *kern_pair, DWORD cPairs)
7557 {
7558     USHORT i, nPairs;
7559     const struct TT_kern_pair *tt_kern_pair;
7560
7561     TRACE("font height %d, units_per_EM %d\n", font->ppem, font->ft_face->units_per_EM);
7562
7563     nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
7564
7565     TRACE("nPairs %u, searchRange %u, entrySelector %u, rangeShift %u\n",
7566            nPairs, GET_BE_WORD(tt_f0_ks->searchRange),
7567            GET_BE_WORD(tt_f0_ks->entrySelector), GET_BE_WORD(tt_f0_ks->rangeShift));
7568
7569     if (!kern_pair || !cPairs)
7570         return nPairs;
7571
7572     tt_kern_pair = (const struct TT_kern_pair *)(tt_f0_ks + 1);
7573
7574     nPairs = min(nPairs, cPairs);
7575
7576     for (i = 0; i < nPairs; i++)
7577     {
7578         kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
7579         kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
7580         /* this algorithm appears to better match what Windows does */
7581         kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
7582         if (kern_pair->iKernAmount < 0)
7583         {
7584             kern_pair->iKernAmount -= font->ft_face->units_per_EM / 2;
7585             kern_pair->iKernAmount -= font->ppem;
7586         }
7587         else if (kern_pair->iKernAmount > 0)
7588         {
7589             kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
7590             kern_pair->iKernAmount += font->ppem;
7591         }
7592         kern_pair->iKernAmount /= font->ft_face->units_per_EM;
7593
7594         TRACE("left %u right %u value %d\n",
7595                kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
7596
7597         kern_pair++;
7598     }
7599     TRACE("copied %u entries\n", nPairs);
7600     return nPairs;
7601 }
7602
7603 /*************************************************************
7604  * freetype_GetKerningPairs
7605  */
7606 static DWORD freetype_GetKerningPairs( PHYSDEV dev, DWORD cPairs, KERNINGPAIR *kern_pair )
7607 {
7608     DWORD length;
7609     void *buf;
7610     const struct TT_kern_table *tt_kern_table;
7611     const struct TT_kern_subtable *tt_kern_subtable;
7612     USHORT i, nTables;
7613     USHORT *glyph_to_char;
7614     GdiFont *font;
7615     struct freetype_physdev *physdev = get_freetype_dev( dev );
7616
7617     if (!(font = physdev->font))
7618     {
7619         dev = GET_NEXT_PHYSDEV( dev, pGetKerningPairs );
7620         return dev->funcs->pGetKerningPairs( dev, cPairs, kern_pair );
7621     }
7622
7623     GDI_CheckNotLock();
7624     EnterCriticalSection( &freetype_cs );
7625     if (font->total_kern_pairs != (DWORD)-1)
7626     {
7627         if (cPairs && kern_pair)
7628         {
7629             cPairs = min(cPairs, font->total_kern_pairs);
7630             memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
7631         }
7632         else cPairs = font->total_kern_pairs;
7633
7634         LeaveCriticalSection( &freetype_cs );
7635         return cPairs;
7636     }
7637
7638     font->total_kern_pairs = 0;
7639
7640     length = get_font_data(font, MS_KERN_TAG, 0, NULL, 0);
7641
7642     if (length == GDI_ERROR)
7643     {
7644         TRACE("no kerning data in the font\n");
7645         LeaveCriticalSection( &freetype_cs );
7646         return 0;
7647     }
7648
7649     buf = HeapAlloc(GetProcessHeap(), 0, length);
7650     if (!buf)
7651     {
7652         WARN("Out of memory\n");
7653         LeaveCriticalSection( &freetype_cs );
7654         return 0;
7655     }
7656
7657     get_font_data(font, MS_KERN_TAG, 0, buf, length);
7658
7659     /* build a glyph index to char code map */
7660     glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
7661     if (!glyph_to_char)
7662     {
7663         WARN("Out of memory allocating a glyph index to char code map\n");
7664         HeapFree(GetProcessHeap(), 0, buf);
7665         LeaveCriticalSection( &freetype_cs );
7666         return 0;
7667     }
7668
7669     if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE)
7670     {
7671         FT_UInt glyph_code;
7672         FT_ULong char_code;
7673
7674         glyph_code = 0;
7675         char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
7676
7677         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
7678                font->ft_face->num_glyphs, glyph_code, char_code);
7679
7680         while (glyph_code)
7681         {
7682             /*TRACE("Char %04lX -> Index %u%s\n", char_code, glyph_code, glyph_to_char[glyph_code] ? "  !" : "" );*/
7683
7684             /* FIXME: This doesn't match what Windows does: it does some fancy
7685              * things with duplicate glyph index to char code mappings, while
7686              * we just avoid overriding existing entries.
7687              */
7688             if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
7689                 glyph_to_char[glyph_code] = (USHORT)char_code;
7690
7691             char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
7692         }
7693     }
7694     else
7695     {
7696         ULONG n;
7697
7698         FIXME("encoding %u not supported\n", font->ft_face->charmap->encoding);
7699         for (n = 0; n <= 65535; n++)
7700             glyph_to_char[n] = (USHORT)n;
7701     }
7702
7703     tt_kern_table = buf;
7704     nTables = GET_BE_WORD(tt_kern_table->nTables);
7705     TRACE("version %u, nTables %u\n",
7706            GET_BE_WORD(tt_kern_table->version), nTables);
7707
7708     tt_kern_subtable = (const struct TT_kern_subtable *)(tt_kern_table + 1);
7709
7710     for (i = 0; i < nTables; i++)
7711     {
7712         struct TT_kern_subtable tt_kern_subtable_copy;
7713
7714         tt_kern_subtable_copy.version = GET_BE_WORD(tt_kern_subtable->version);
7715         tt_kern_subtable_copy.length = GET_BE_WORD(tt_kern_subtable->length);
7716         tt_kern_subtable_copy.coverage.word = GET_BE_WORD(tt_kern_subtable->coverage.word);
7717
7718         TRACE("version %u, length %u, coverage %u, subtable format %u\n",
7719                tt_kern_subtable_copy.version, tt_kern_subtable_copy.length,
7720                tt_kern_subtable_copy.coverage.word, tt_kern_subtable_copy.coverage.bits.format);
7721
7722         /* According to the TrueType specification this is the only format
7723          * that will be properly interpreted by Windows and OS/2
7724          */
7725         if (tt_kern_subtable_copy.coverage.bits.format == 0)
7726         {
7727             DWORD new_chunk, old_total = font->total_kern_pairs;
7728
7729             new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
7730                                                     glyph_to_char, NULL, 0);
7731             font->total_kern_pairs += new_chunk;
7732
7733             if (!font->kern_pairs)
7734                 font->kern_pairs = HeapAlloc(GetProcessHeap(), 0,
7735                                              font->total_kern_pairs * sizeof(*font->kern_pairs));
7736             else
7737                 font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs,
7738                                                font->total_kern_pairs * sizeof(*font->kern_pairs));
7739
7740             parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
7741                         glyph_to_char, font->kern_pairs + old_total, new_chunk);
7742         }
7743         else
7744             TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format);
7745
7746         tt_kern_subtable = (const struct TT_kern_subtable *)((const char *)tt_kern_subtable + tt_kern_subtable_copy.length);
7747     }
7748
7749     HeapFree(GetProcessHeap(), 0, glyph_to_char);
7750     HeapFree(GetProcessHeap(), 0, buf);
7751
7752     if (cPairs && kern_pair)
7753     {
7754         cPairs = min(cPairs, font->total_kern_pairs);
7755         memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
7756     }
7757     else cPairs = font->total_kern_pairs;
7758
7759     LeaveCriticalSection( &freetype_cs );
7760     return cPairs;
7761 }
7762
7763 static const struct gdi_dc_funcs freetype_funcs =
7764 {
7765     NULL,                               /* pAbortDoc */
7766     NULL,                               /* pAbortPath */
7767     NULL,                               /* pAlphaBlend */
7768     NULL,                               /* pAngleArc */
7769     NULL,                               /* pArc */
7770     NULL,                               /* pArcTo */
7771     NULL,                               /* pBeginPath */
7772     NULL,                               /* pBlendImage */
7773     NULL,                               /* pChord */
7774     NULL,                               /* pCloseFigure */
7775     NULL,                               /* pCreateCompatibleDC */
7776     freetype_CreateDC,                  /* pCreateDC */
7777     freetype_DeleteDC,                  /* pDeleteDC */
7778     NULL,                               /* pDeleteObject */
7779     NULL,                               /* pDeviceCapabilities */
7780     NULL,                               /* pEllipse */
7781     NULL,                               /* pEndDoc */
7782     NULL,                               /* pEndPage */
7783     NULL,                               /* pEndPath */
7784     freetype_EnumFonts,                 /* pEnumFonts */
7785     NULL,                               /* pEnumICMProfiles */
7786     NULL,                               /* pExcludeClipRect */
7787     NULL,                               /* pExtDeviceMode */
7788     NULL,                               /* pExtEscape */
7789     NULL,                               /* pExtFloodFill */
7790     NULL,                               /* pExtSelectClipRgn */
7791     NULL,                               /* pExtTextOut */
7792     NULL,                               /* pFillPath */
7793     NULL,                               /* pFillRgn */
7794     NULL,                               /* pFlattenPath */
7795     freetype_FontIsLinked,              /* pFontIsLinked */
7796     NULL,                               /* pFrameRgn */
7797     NULL,                               /* pGdiComment */
7798     freetype_GdiRealizationInfo,        /* pGdiRealizationInfo */
7799     NULL,                               /* pGetBoundsRect */
7800     freetype_GetCharABCWidths,          /* pGetCharABCWidths */
7801     freetype_GetCharABCWidthsI,         /* pGetCharABCWidthsI */
7802     freetype_GetCharWidth,              /* pGetCharWidth */
7803     NULL,                               /* pGetDeviceCaps */
7804     NULL,                               /* pGetDeviceGammaRamp */
7805     freetype_GetFontData,               /* pGetFontData */
7806     freetype_GetFontUnicodeRanges,      /* pGetFontUnicodeRanges */
7807     freetype_GetGlyphIndices,           /* pGetGlyphIndices */
7808     freetype_GetGlyphOutline,           /* pGetGlyphOutline */
7809     NULL,                               /* pGetICMProfile */
7810     NULL,                               /* pGetImage */
7811     freetype_GetKerningPairs,           /* pGetKerningPairs */
7812     NULL,                               /* pGetNearestColor */
7813     freetype_GetOutlineTextMetrics,     /* pGetOutlineTextMetrics */
7814     NULL,                               /* pGetPixel */
7815     NULL,                               /* pGetSystemPaletteEntries */
7816     freetype_GetTextCharsetInfo,        /* pGetTextCharsetInfo */
7817     freetype_GetTextExtentExPoint,      /* pGetTextExtentExPoint */
7818     freetype_GetTextExtentExPointI,     /* pGetTextExtentExPointI */
7819     freetype_GetTextFace,               /* pGetTextFace */
7820     freetype_GetTextMetrics,            /* pGetTextMetrics */
7821     NULL,                               /* pGradientFill */
7822     NULL,                               /* pIntersectClipRect */
7823     NULL,                               /* pInvertRgn */
7824     NULL,                               /* pLineTo */
7825     NULL,                               /* pModifyWorldTransform */
7826     NULL,                               /* pMoveTo */
7827     NULL,                               /* pOffsetClipRgn */
7828     NULL,                               /* pOffsetViewportOrg */
7829     NULL,                               /* pOffsetWindowOrg */
7830     NULL,                               /* pPaintRgn */
7831     NULL,                               /* pPatBlt */
7832     NULL,                               /* pPie */
7833     NULL,                               /* pPolyBezier */
7834     NULL,                               /* pPolyBezierTo */
7835     NULL,                               /* pPolyDraw */
7836     NULL,                               /* pPolyPolygon */
7837     NULL,                               /* pPolyPolyline */
7838     NULL,                               /* pPolygon */
7839     NULL,                               /* pPolyline */
7840     NULL,                               /* pPolylineTo */
7841     NULL,                               /* pPutImage */
7842     NULL,                               /* pRealizeDefaultPalette */
7843     NULL,                               /* pRealizePalette */
7844     NULL,                               /* pRectangle */
7845     NULL,                               /* pResetDC */
7846     NULL,                               /* pRestoreDC */
7847     NULL,                               /* pRoundRect */
7848     NULL,                               /* pSaveDC */
7849     NULL,                               /* pScaleViewportExt */
7850     NULL,                               /* pScaleWindowExt */
7851     NULL,                               /* pSelectBitmap */
7852     NULL,                               /* pSelectBrush */
7853     NULL,                               /* pSelectClipPath */
7854     freetype_SelectFont,                /* pSelectFont */
7855     NULL,                               /* pSelectPalette */
7856     NULL,                               /* pSelectPen */
7857     NULL,                               /* pSetArcDirection */
7858     NULL,                               /* pSetBkColor */
7859     NULL,                               /* pSetBkMode */
7860     NULL,                               /* pSetDCBrushColor */
7861     NULL,                               /* pSetDCPenColor */
7862     NULL,                               /* pSetDIBColorTable */
7863     NULL,                               /* pSetDIBitsToDevice */
7864     NULL,                               /* pSetDeviceClipping */
7865     NULL,                               /* pSetDeviceGammaRamp */
7866     NULL,                               /* pSetLayout */
7867     NULL,                               /* pSetMapMode */
7868     NULL,                               /* pSetMapperFlags */
7869     NULL,                               /* pSetPixel */
7870     NULL,                               /* pSetPolyFillMode */
7871     NULL,                               /* pSetROP2 */
7872     NULL,                               /* pSetRelAbs */
7873     NULL,                               /* pSetStretchBltMode */
7874     NULL,                               /* pSetTextAlign */
7875     NULL,                               /* pSetTextCharacterExtra */
7876     NULL,                               /* pSetTextColor */
7877     NULL,                               /* pSetTextJustification */
7878     NULL,                               /* pSetViewportExt */
7879     NULL,                               /* pSetViewportOrg */
7880     NULL,                               /* pSetWindowExt */
7881     NULL,                               /* pSetWindowOrg */
7882     NULL,                               /* pSetWorldTransform */
7883     NULL,                               /* pStartDoc */
7884     NULL,                               /* pStartPage */
7885     NULL,                               /* pStretchBlt */
7886     NULL,                               /* pStretchDIBits */
7887     NULL,                               /* pStrokeAndFillPath */
7888     NULL,                               /* pStrokePath */
7889     NULL,                               /* pUnrealizePalette */
7890     NULL,                               /* pWidenPath */
7891     NULL,                               /* wine_get_wgl_driver */
7892     GDI_PRIORITY_FONT_DRV               /* priority */
7893 };
7894
7895 #else /* HAVE_FREETYPE */
7896
7897 /*************************************************************************/
7898
7899 BOOL WineEngInit(void)
7900 {
7901     return FALSE;
7902 }
7903 BOOL WineEngDestroyFontInstance(HFONT hfont)
7904 {
7905     return FALSE;
7906 }
7907
7908 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
7909 {
7910     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
7911     return 1;
7912 }
7913
7914 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
7915 {
7916     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
7917     return TRUE;
7918 }
7919
7920 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
7921 {
7922     FIXME("(%p, %u, %p, %p): stub\n", pbFont, cbFont, pdv, pcFonts);
7923     return NULL;
7924 }
7925
7926 BOOL WineEngCreateScalableFontResource( DWORD hidden, LPCWSTR resource,
7927                                         LPCWSTR font_file, LPCWSTR font_path )
7928 {
7929     FIXME("stub\n");
7930     return FALSE;
7931 }
7932
7933 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
7934 {
7935     return FALSE;
7936 }
7937
7938 /*************************************************************************
7939  *             GetRasterizerCaps   (GDI32.@)
7940  */
7941 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
7942 {
7943     lprs->nSize = sizeof(RASTERIZER_STATUS);
7944     lprs->wFlags = 0;
7945     lprs->nLanguageID = 0;
7946     return TRUE;
7947 }
7948
7949 #endif /* HAVE_FREETYPE */