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