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