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