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