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