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