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