~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/gdi32/freetype.c

Version: ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  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/unicode.h"
 88 #include "wine/debug.h"
 89 #include "wine/list.h"
 90 
 91 WINE_DEFAULT_DEBUG_CHANNEL(font);
 92 
 93 #ifdef HAVE_FREETYPE
 94 
 95 #ifdef HAVE_FT2BUILD_H
 96 #include <ft2build.h>
 97 #endif
 98 #ifdef HAVE_FREETYPE_FREETYPE_H
 99 #include <freetype/freetype.h>
100 #endif
101 #ifdef HAVE_FREETYPE_FTGLYPH_H
102 #include <freetype/ftglyph.h>
103 #endif
104 #ifdef HAVE_FREETYPE_TTTABLES_H
105 #include <freetype/tttables.h>
106 #endif
107 #ifdef HAVE_FREETYPE_FTTYPES_H
108 #include <freetype/fttypes.h>
109 #endif
110 #ifdef HAVE_FREETYPE_FTSNAMES_H
111 #include <freetype/ftsnames.h>
112 #endif
113 #ifdef HAVE_FREETYPE_TTNAMEID_H
114 #include <freetype/ttnameid.h>
115 #endif
116 #ifdef HAVE_FREETYPE_FTOUTLN_H
117 #include <freetype/ftoutln.h>
118 #endif
119 #ifdef HAVE_FREETYPE_INTERNAL_SFNT_H
120 #include <freetype/internal/sfnt.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_Vector_Unit);
158 MAKE_FUNCPTR(FT_Done_Face);
159 MAKE_FUNCPTR(FT_Get_Char_Index);
160 MAKE_FUNCPTR(FT_Get_Module);
161 MAKE_FUNCPTR(FT_Get_Sfnt_Name);
162 MAKE_FUNCPTR(FT_Get_Sfnt_Name_Count);
163 MAKE_FUNCPTR(FT_Get_Sfnt_Table);
164 MAKE_FUNCPTR(FT_Init_FreeType);
165 MAKE_FUNCPTR(FT_Load_Glyph);
166 MAKE_FUNCPTR(FT_Matrix_Multiply);
167 #ifdef FT_MULFIX_INLINED
168 #define pFT_MulFix FT_MULFIX_INLINED
169 #else
170 MAKE_FUNCPTR(FT_MulFix);
171 #endif
172 MAKE_FUNCPTR(FT_New_Face);
173 MAKE_FUNCPTR(FT_New_Memory_Face);
174 MAKE_FUNCPTR(FT_Outline_Get_Bitmap);
175 MAKE_FUNCPTR(FT_Outline_Transform);
176 MAKE_FUNCPTR(FT_Outline_Translate);
177 MAKE_FUNCPTR(FT_Select_Charmap);
178 MAKE_FUNCPTR(FT_Set_Charmap);
179 MAKE_FUNCPTR(FT_Set_Pixel_Sizes);
180 MAKE_FUNCPTR(FT_Vector_Transform);
181 MAKE_FUNCPTR(FT_Render_Glyph);
182 static void (*pFT_Library_Version)(FT_Library,FT_Int*,FT_Int*,FT_Int*);
183 static FT_Error (*pFT_Load_Sfnt_Table)(FT_Face,FT_ULong,FT_Long,FT_Byte*,FT_ULong*);
184 static FT_ULong (*pFT_Get_First_Char)(FT_Face,FT_UInt*);
185 static FT_ULong (*pFT_Get_Next_Char)(FT_Face,FT_ULong,FT_UInt*);
186 static FT_TrueTypeEngineType (*pFT_Get_TrueType_Engine_Type)(FT_Library);
187 #ifdef HAVE_FREETYPE_FTLCDFIL_H
188 static FT_Error (*pFT_Library_SetLcdFilter)(FT_Library, FT_LcdFilter);
189 #endif
190 #ifdef HAVE_FREETYPE_FTWINFNT_H
191 MAKE_FUNCPTR(FT_Get_WinFNT_Header);
192 #endif
193 
194 #ifdef SONAME_LIBFONTCONFIG
195 #include <fontconfig/fontconfig.h>
196 MAKE_FUNCPTR(FcConfigGetCurrent);
197 MAKE_FUNCPTR(FcFontList);
198 MAKE_FUNCPTR(FcFontSetDestroy);
199 MAKE_FUNCPTR(FcInit);
200 MAKE_FUNCPTR(FcObjectSetAdd);
201 MAKE_FUNCPTR(FcObjectSetCreate);
202 MAKE_FUNCPTR(FcObjectSetDestroy);
203 MAKE_FUNCPTR(FcPatternCreate);
204 MAKE_FUNCPTR(FcPatternDestroy);
205 MAKE_FUNCPTR(FcPatternGetBool);
206 MAKE_FUNCPTR(FcPatternGetString);
207 #endif
208 
209 #undef MAKE_FUNCPTR
210 
211 #ifndef FT_MAKE_TAG
212 #define FT_MAKE_TAG( ch0, ch1, ch2, ch3 ) \
213         ( ((DWORD)(BYTE)(ch0) << 24) | ((DWORD)(BYTE)(ch1) << 16) | \
214           ((DWORD)(BYTE)(ch2) << 8) | (DWORD)(BYTE)(ch3) )
215 #endif
216 
217 #ifndef ft_encoding_none
218 #define FT_ENCODING_NONE ft_encoding_none
219 #endif
220 #ifndef ft_encoding_ms_symbol
221 #define FT_ENCODING_MS_SYMBOL ft_encoding_symbol
222 #endif
223 #ifndef ft_encoding_unicode
224 #define FT_ENCODING_UNICODE ft_encoding_unicode
225 #endif
226 #ifndef ft_encoding_apple_roman
227 #define FT_ENCODING_APPLE_ROMAN ft_encoding_apple_roman
228 #endif
229 
230 #ifdef WORDS_BIGENDIAN
231 #define GET_BE_WORD(x) (x)
232 #else
233 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
234 #endif
235 
236 /* This is basically a copy of FT_Bitmap_Size with an extra element added */
237 typedef struct {
238     FT_Short height;
239     FT_Short width;
240     FT_Pos size;
241     FT_Pos x_ppem;
242     FT_Pos y_ppem;
243     FT_Short internal_leading;
244 } Bitmap_Size;
245 
246 /* FT_Bitmap_Size gained 3 new elements between FreeType 2.1.4 and 2.1.5
247    So to let this compile on older versions of FreeType we'll define the
248    new structure here. */
249 typedef struct {
250     FT_Short height, width;
251     FT_Pos size, x_ppem, y_ppem;
252 } My_FT_Bitmap_Size;
253 
254 struct enum_data
255 {
256     ENUMLOGFONTEXW elf;
257     NEWTEXTMETRICEXW ntm;
258     DWORD type;
259 };
260 
261 typedef struct tagFace {
262     struct list entry;
263     WCHAR *StyleName;
264     char *file;
265     void *font_data_ptr;
266     DWORD font_data_size;
267     FT_Long face_index;
268     FONTSIGNATURE fs;
269     FONTSIGNATURE fs_links;
270     DWORD ntmFlags;
271     FT_Fixed font_version;
272     BOOL scalable;
273     Bitmap_Size size;     /* set if face is a bitmap */
274     BOOL external; /* TRUE if we should manually add this font to the registry */
275     struct tagFamily *family;
276     /* Cached data for Enum */
277     struct enum_data *cached_enum_data;
278 } Face;
279 
280 typedef struct tagFamily {
281     struct list entry;
282     const WCHAR *FamilyName;
283     struct list faces;
284 } Family;
285 
286 typedef struct {
287     GLYPHMETRICS gm;
288     INT adv; /* These three hold to widths of the unrotated chars */
289     INT lsb;
290     INT bbx;
291     BOOL init;
292 } GM;
293 
294 typedef struct {
295     FLOAT eM11, eM12;
296     FLOAT eM21, eM22;
297 } FMAT2;
298 
299 typedef struct {
300     DWORD hash;
301     LOGFONTW lf;
302     FMAT2 matrix;
303     BOOL can_use_bitmap;
304 } FONT_DESC;
305 
306 typedef struct tagHFONTLIST {
307     struct list entry;
308     HFONT hfont;
309 } HFONTLIST;
310 
311 typedef struct {
312     struct list entry;
313     Face *face;
314     GdiFont *font;
315 } CHILD_FONT;
316 
317 struct tagGdiFont {
318     struct list entry;
319     GM **gm;
320     DWORD gmsize;
321     struct list hfontlist;
322     OUTLINETEXTMETRICW *potm;
323     DWORD total_kern_pairs;
324     KERNINGPAIR *kern_pairs;
325     struct list child_fonts;
326 
327     /* the following members can be accessed without locking, they are never modified after creation */
328     FT_Face ft_face;
329     struct font_mapping *mapping;
330     LPWSTR name;
331     int charset;
332     int codepage;
333     BOOL fake_italic;
334     BOOL fake_bold;
335     BYTE underline;
336     BYTE strikeout;
337     INT orientation;
338     FONT_DESC font_desc;
339     LONG aveWidth, ppem;
340     double scale_y;
341     SHORT yMax;
342     SHORT yMin;
343     DWORD ntmFlags;
344     FONTSIGNATURE fs;
345     GdiFont *base_font;
346     VOID *GSUB_Table;
347     DWORD cache_num;
348 };
349 
350 typedef struct {
351     struct list entry;
352     const WCHAR *font_name;
353     struct list links;
354 } SYSTEM_LINKS;
355 
356 #define GM_BLOCK_SIZE 128
357 #define FONT_GM(font,idx) (&(font)->gm[(idx) / GM_BLOCK_SIZE][(idx) % GM_BLOCK_SIZE])
358 
359 static struct list gdi_font_list = LIST_INIT(gdi_font_list);
360 static struct list unused_gdi_font_list = LIST_INIT(unused_gdi_font_list);
361 #define UNUSED_CACHE_SIZE 10
362 static struct list child_font_list = LIST_INIT(child_font_list);
363 static struct list system_links = LIST_INIT(system_links);
364 
365 static struct list font_subst_list = LIST_INIT(font_subst_list);
366 
367 static struct list font_list = LIST_INIT(font_list);
368 
369 static const WCHAR defSerif[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
370 static const WCHAR defSans[] = {'A','r','i','a','l','\0'};
371 static const WCHAR defFixed[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'};
372 
373 static const WCHAR fontsW[] = {'\\','f','o','n','t','s','\0'};
374 static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
375                                            'W','i','n','d','o','w','s','\\',
376                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
377                                            'F','o','n','t','s','\0'};
378 
379 static const WCHAR winnt_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
380                                            'W','i','n','d','o','w','s',' ','N','T','\\',
381                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
382                                            'F','o','n','t','s','\0'};
383 
384 static const WCHAR system_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
385 static const WCHAR FixedSys_Value[] = {'F','I','X','E','D','F','O','N','.','F','O','N','\0'};
386 static const WCHAR System_Value[] = {'F','O','N','T','S','.','F','O','N','\0'};
387 static const WCHAR OEMFont_Value[] = {'O','E','M','F','O','N','T','.','F','O','N','\0'};
388 
389 static const WCHAR * const SystemFontValues[4] = {
390     System_Value,
391     OEMFont_Value,
392     FixedSys_Value,
393     NULL
394 };
395 
396 static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
397                                                'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'};
398 
399 /* Interesting and well-known (frequently-assumed!) font names */
400 static const WCHAR Lucida_Sans_Unicode[] = {'L','u','c','i','d','a',' ','S','a','n','s',' ','U','n','i','c','o','d','e',0};
401 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 };
402 static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
403 static const WCHAR MS_UI_Gothic[] = {'M','S',' ','U','I',' ','G','o','t','h','i','c',0};
404 static const WCHAR SimSun[] = {'S','i','m','S','u','n',0};
405 static const WCHAR Gulim[] = {'G','u','l','i','m',0};
406 static const WCHAR PMingLiU[] = {'P','M','i','n','g','L','i','U',0};
407 static const WCHAR Batang[] = {'B','a','t','a','n','g',0};
408 
409 static const WCHAR ArabicW[] = {'A','r','a','b','i','c','\0'};
410 static const WCHAR BalticW[] = {'B','a','l','t','i','c','\0'};
411 static const WCHAR CHINESE_BIG5W[] = {'C','H','I','N','E','S','E','_','B','I','G','5','\0'};
412 static const WCHAR CHINESE_GB2312W[] = {'C','H','I','N','E','S','E','_','G','B','2','3','1','2','\0'};
413 static const WCHAR Central_EuropeanW[] = {'C','e','n','t','r','a','l',' ',
414                                     'E','u','r','o','p','e','a','n','\0'};
415 static const WCHAR CyrillicW[] = {'C','y','r','i','l','l','i','c','\0'};
416 static const WCHAR GreekW[] = {'G','r','e','e','k','\0'};
417 static const WCHAR HangulW[] = {'H','a','n','g','u','l','\0'};
418 static const WCHAR Hangul_Johab_W[] = {'H','a','n','g','u','l','(','J','o','h','a','b',')','\0'};
419 static const WCHAR HebrewW[] = {'H','e','b','r','e','w','\0'};
420 static const WCHAR JapaneseW[] = {'J','a','p','a','n','e','s','e','\0'};
421 static const WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
422 static const WCHAR ThaiW[] = {'T','h','a','i','\0'};
423 static const WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'};
424 static const WCHAR VietnameseW[] = {'V','i','e','t','n','a','m','e','s','e','\0'};
425 static const WCHAR WesternW[] = {'W','e','s','t','e','r','n','\0'};
426 static const WCHAR OEM_DOSW[] = {'O','E','M','/','D','O','S','\0'};
427 
428 static const WCHAR * const ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits */
429     WesternW, /*00*/
430     Central_EuropeanW,
431     CyrillicW,
432     GreekW,
433     TurkishW,
434     HebrewW,
435     ArabicW,
436     BalticW,
437     VietnameseW, /*08*/
438     NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/
439     ThaiW,
440     JapaneseW,
441     CHINESE_GB2312W,
442     HangulW,
443     CHINESE_BIG5W,
444     Hangul_Johab_W,
445     NULL, NULL, /*23*/
446     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
447     SymbolW /*31*/
448 };
449 
450 typedef struct {
451     WCHAR *name;
452     INT charset;
453 } NameCs;
454 
455 typedef struct tagFontSubst {
456     struct list entry;
457     NameCs from;
458     NameCs to;
459 } FontSubst;
460 
461 struct font_mapping
462 {
463     struct list entry;
464     int         refcount;
465     dev_t       dev;
466     ino_t       ino;
467     void       *data;
468     size_t      size;
469 };
470 
471 static struct list mappings_list = LIST_INIT( mappings_list );
472 
473 static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail if this is still FALSE */
474 
475 static CRITICAL_SECTION freetype_cs;
476 static CRITICAL_SECTION_DEBUG critsect_debug =
477 {
478     0, 0, &freetype_cs,
479     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
480       0, 0, { (DWORD_PTR)(__FILE__ ": freetype_cs") }
481 };
482 static CRITICAL_SECTION freetype_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
483 
484 static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'};
485 
486 static const WCHAR szDefaultFallbackLink[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0};
487 static BOOL use_default_fallback = FALSE;
488 
489 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph);
490 
491 static const WCHAR system_link[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
492                                     'W','i','n','d','o','w','s',' ','N','T','\\',
493                                     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','F','o','n','t','L','i','n','k','\\',
494                                     'S','y','s','t','e','m','L','i','n','k',0};
495 
496 /****************************************
497  *   Notes on .fon files
498  *
499  * The fonts System, FixedSys and Terminal are special.  There are typically multiple
500  * versions installed for different resolutions and codepages.  Windows stores which one to use
501  * in HKEY_CURRENT_CONFIG\\Software\\Fonts.
502  *    Key            Meaning
503  *  FIXEDFON.FON    FixedSys
504  *  FONTS.FON       System
505  *  OEMFONT.FON     Terminal
506  *  LogPixels       Current dpi set by the display control panel applet
507  *                  (HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontDPI
508  *                  also has a LogPixels value that appears to mirror this)
509  *
510  * On my system these values have data: vgafix.fon, vgasys.fon, vga850.fon and 96 respectively
511  * (vgaoem.fon would be your oemfont.fon if you have a US setup).
512  * If the resolution is changed to be >= 109dpi then the fonts goto 8514fix, 8514sys and 8514oem
513  * (not sure what's happening to the oem codepage here). 109 is nicely halfway between 96 and 120dpi,
514  * so that makes sense.
515  *
516  * Additionally Windows also loads the fonts listed in the [386enh] section of system.ini (this doesn't appear
517  * to be mapped into the registry on Windows 2000 at least).
518  * I have
519  * woafont=app850.fon
520  * ega80woa.fon=ega80850.fon
521  * ega40woa.fon=ega40850.fon
522  * cga80woa.fon=cga80850.fon
523  * cga40woa.fon=cga40850.fon
524  */
525 
526 /* These are all structures needed for the GSUB table */
527 
528 #define GSUB_TAG MS_MAKE_TAG('G', 'S', 'U', 'B')
529 #define TATEGAKI_LOWER_BOUND  0x02F1
530 
531 typedef struct {
532     DWORD version;
533     WORD ScriptList;
534     WORD FeatureList;
535     WORD LookupList;
536 } GSUB_Header;
537 
538 typedef struct {
539     CHAR ScriptTag[4];
540     WORD Script;
541 } GSUB_ScriptRecord;
542 
543 typedef struct {
544     WORD ScriptCount;
545     GSUB_ScriptRecord ScriptRecord[1];
546 } GSUB_ScriptList;
547 
548 typedef struct {
549     CHAR LangSysTag[4];
550     WORD LangSys;
551 } GSUB_LangSysRecord;
552 
553 typedef struct {
554     WORD DefaultLangSys;
555     WORD LangSysCount;
556     GSUB_LangSysRecord LangSysRecord[1];
557 } GSUB_Script;
558 
559 typedef struct {
560     WORD LookupOrder; /* Reserved */
561     WORD ReqFeatureIndex;
562     WORD FeatureCount;
563     WORD FeatureIndex[1];
564 } GSUB_LangSys;
565 
566 typedef struct {
567     CHAR FeatureTag[4];
568     WORD Feature;
569 } GSUB_FeatureRecord;
570 
571 typedef struct {
572     WORD FeatureCount;
573     GSUB_FeatureRecord FeatureRecord[1];
574 } GSUB_FeatureList;
575 
576 typedef struct {
577     WORD FeatureParams; /* Reserved */
578     WORD LookupCount;
579     WORD LookupListIndex[1];
580 } GSUB_Feature;
581 
582 typedef struct {
583     WORD LookupCount;
584     WORD Lookup[1];
585 } GSUB_LookupList;
586 
587 typedef struct {
588     WORD LookupType;
589     WORD LookupFlag;
590     WORD SubTableCount;
591     WORD SubTable[1];
592 } GSUB_LookupTable;
593 
594 typedef struct {
595     WORD CoverageFormat;
596     WORD GlyphCount;
597     WORD GlyphArray[1];
598 } GSUB_CoverageFormat1;
599 
600 typedef struct {
601     WORD Start;
602     WORD End;
603     WORD StartCoverageIndex;
604 } GSUB_RangeRecord;
605 
606 typedef struct {
607     WORD CoverageFormat;
608     WORD RangeCount;
609     GSUB_RangeRecord RangeRecord[1];
610 } GSUB_CoverageFormat2;
611 
612 typedef struct {
613     WORD SubstFormat; /* = 1 */
614     WORD Coverage;
615     WORD DeltaGlyphID;
616 } GSUB_SingleSubstFormat1;
617 
618 typedef struct {
619     WORD SubstFormat; /* = 2 */
620     WORD Coverage;
621     WORD GlyphCount;
622     WORD Substitute[1];
623 }GSUB_SingleSubstFormat2;
624 
625 #ifdef HAVE_CARBON_CARBON_H
626 static char *find_cache_dir(void)
627 {
628     FSRef ref;
629     OSErr err;
630     static char cached_path[MAX_PATH];
631     static const char *wine = "/Wine", *fonts = "/Fonts";
632 
633     if(*cached_path) return cached_path;
634 
635     err = FSFindFolder(kUserDomain, kCachedDataFolderType, kCreateFolder, &ref);
636     if(err != noErr)
637     {
638         WARN("can't create cached data folder\n");
639         return NULL;
640     }
641     err = FSRefMakePath(&ref, (unsigned char*)cached_path, sizeof(cached_path));
642     if(err != noErr)
643     {
644         WARN("can't create cached data path\n");
645         *cached_path = '\0';
646         return NULL;
647     }
648     if(strlen(cached_path) + strlen(wine) + strlen(fonts) + 1 > sizeof(cached_path))
649     {
650         ERR("Could not create full path\n");
651         *cached_path = '\0';
652         return NULL;
653     }
654     strcat(cached_path, wine);
655 
656     if(mkdir(cached_path, 0700) == -1 && errno != EEXIST)
657     {
658         WARN("Couldn't mkdir %s\n", cached_path);
659         *cached_path = '\0';
660         return NULL;
661     }
662     strcat(cached_path, fonts);
663     if(mkdir(cached_path, 0700) == -1 && errno != EEXIST)
664     {
665         WARN("Couldn't mkdir %s\n", cached_path);
666         *cached_path = '\0';
667         return NULL;
668     }
669     return cached_path;
670 }
671 
672 /******************************************************************
673  *            expand_mac_font
674  *
675  * Extracts individual TrueType font files from a Mac suitcase font
676  * and saves them into the user's caches directory (see
677  * find_cache_dir()).
678  * Returns a NULL terminated array of filenames.
679  *
680  * We do this because they are apps that try to read ttf files
681  * themselves and they don't like Mac suitcase files.
682  */
683 static char **expand_mac_font(const char *path)
684 {
685     FSRef ref;
686     SInt16 res_ref;
687     OSStatus s;
688     unsigned int idx;
689     const char *out_dir;
690     const char *filename;
691     int output_len;
692     struct {
693         char **array;
694         unsigned int size, max_size;
695     } ret;
696 
697     TRACE("path %s\n", path);
698 
699     s = FSPathMakeRef((unsigned char*)path, &ref, FALSE);
700     if(s != noErr)
701     {
702         WARN("failed to get ref\n");
703         return NULL;
704     }
705 
706     s = FSOpenResourceFile(&ref, 0, NULL, fsRdPerm, &res_ref);
707     if(s != noErr)
708     {
709         TRACE("no data fork, so trying resource fork\n");
710         res_ref = FSOpenResFile(&ref, fsRdPerm);
711         if(res_ref == -1)
712         {
713             TRACE("unable to open resource fork\n");
714             return NULL;
715         }
716     }
717 
718     ret.size = 0;
719     ret.max_size = 10;
720     ret.array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ret.max_size * sizeof(*ret.array));
721     if(!ret.array)
722     {
723         CloseResFile(res_ref);
724         return NULL;
725     }
726 
727     out_dir = find_cache_dir();
728 
729     filename = strrchr(path, '/');
730     if(!filename) filename = path;
731     else filename++;
732 
733     /* output filename has the form out_dir/filename_%04x.ttf */
734     output_len = strlen(out_dir) + 1 + strlen(filename) + 5 + 5;
735 
736     UseResFile(res_ref);
737     idx = 1;
738     while(1)
739     {
740         FamRec *fam_rec;
741         unsigned short *num_faces_ptr, num_faces, face;
742         AsscEntry *assoc;
743         Handle fond;
744         ResType fond_res = FT_MAKE_TAG('F','O','N','D');
745 
746         fond = Get1IndResource(fond_res, idx);
747         if(!fond) break;
748         TRACE("got fond resource %d\n", idx);
749         HLock(fond);
750 
751         fam_rec = *(FamRec**)fond;
752         num_faces_ptr = (unsigned short *)(fam_rec + 1);
753         num_faces = GET_BE_WORD(*num_faces_ptr);
754         num_faces++;
755         assoc = (AsscEntry*)(num_faces_ptr + 1);
756         TRACE("num faces %04x\n", num_faces);
757         for(face = 0; face < num_faces; face++, assoc++)
758         {
759             Handle sfnt;
760             ResType sfnt_res = FT_MAKE_TAG('s','f','n','t');
761             unsigned short size, font_id;
762             char *output;
763 
764             size = GET_BE_WORD(assoc->fontSize);
765             font_id = GET_BE_WORD(assoc->fontID);
766             if(size != 0)
767             {
768                 TRACE("skipping id %04x because it's not scalable (fixed size %d)\n", font_id, size);
769                 continue;
770             }
771 
772             TRACE("trying to load sfnt id %04x\n", font_id);
773             sfnt = GetResource(sfnt_res, font_id);
774             if(!sfnt)
775             {
776                 TRACE("can't get sfnt resource %04x\n", font_id);
777                 continue;
778             }
779 
780             output = HeapAlloc(GetProcessHeap(), 0, output_len);
781             if(output)
782             {
783                 int fd;
784 
785                 sprintf(output, "%s/%s_%04x.ttf", out_dir, filename, font_id);
786 
787                 fd = open(output, O_CREAT | O_EXCL | O_WRONLY, 0600);
788                 if(fd != -1 || errno == EEXIST)
789                 {
790                     if(fd != -1)
791                     {
792                         unsigned char *sfnt_data;
793 
794                         HLock(sfnt);
795                         sfnt_data = *(unsigned char**)sfnt;
796                         write(fd, sfnt_data, GetHandleSize(sfnt));
797                         HUnlock(sfnt);
798                         close(fd);
799                     }
800                     if(ret.size >= ret.max_size - 1) /* Always want the last element to be NULL */
801                     {
802                         ret.max_size *= 2;
803                         ret.array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ret.array, ret.max_size * sizeof(*ret.array));
804                     }
805                     ret.array[ret.size++] = output;
806                 }
807                 else
808                 {
809                     WARN("unable to create %s\n", output);
810                     HeapFree(GetProcessHeap(), 0, output);
811                 }
812             }
813             ReleaseResource(sfnt);
814         }
815         HUnlock(fond);
816         ReleaseResource(fond);
817         idx++;
818     }
819     CloseResFile(res_ref);
820 
821     return ret.array;
822 }
823 
824 #endif /* HAVE_CARBON_CARBON_H */
825 
826 static inline BOOL is_win9x(void)
827 {
828     return GetVersion() & 0x80000000;
829 }
830 /* 
831    This function builds an FT_Fixed from a double. It fails if the absolute
832    value of the float number is greater than 32768.
833 */
834 static inline FT_Fixed FT_FixedFromFloat(double f)
835 {
836         return f * 0x10000;
837 }
838 
839 /* 
840    This function builds an FT_Fixed from a FIXED. It simply put f.value 
841    in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
842 */
843 static inline FT_Fixed FT_FixedFromFIXED(FIXED f)
844 {
845     return (FT_Fixed)((int)f.value << 16 | (unsigned int)f.fract);
846 }
847 
848 
849 static Face *find_face_from_filename(const WCHAR *file_name, const WCHAR *face_name)
850 {
851     Family *family;
852     Face *face;
853     const char *file;
854     DWORD len = WideCharToMultiByte(CP_UNIXCP, 0, file_name, -1, NULL, 0, NULL, NULL);
855     char *file_nameA = HeapAlloc(GetProcessHeap(), 0, len);
856 
857     WideCharToMultiByte(CP_UNIXCP, 0, file_name, -1, file_nameA, len, NULL, NULL);
858     TRACE("looking for file %s name %s\n", debugstr_a(file_nameA), debugstr_w(face_name));
859 
860     LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
861     {
862         if(face_name && strcmpiW(face_name, family->FamilyName))
863             continue;
864         LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
865         {
866             if (!face->file)
867                 continue;
868             file = strrchr(face->file, '/');
869             if(!file)
870                 file = face->file;
871             else
872                 file++;
873             if(!strcasecmp(file, file_nameA))
874             {
875                 HeapFree(GetProcessHeap(), 0, file_nameA);
876                 return face;
877             }
878         }
879     }
880     HeapFree(GetProcessHeap(), 0, file_nameA);
881     return NULL;
882 }
883 
884 static Family *find_family_from_name(const WCHAR *name)
885 {
886     Family *family;
887 
888     LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
889     {
890         if(!strcmpiW(family->FamilyName, name))
891             return family;
892     }
893 
894     return NULL;
895 }
896 
897 static void DumpSubstList(void)
898 {
899     FontSubst *psub;
900 
901     LIST_FOR_EACH_ENTRY(psub, &font_subst_list, FontSubst, entry)
902     {
903         if(psub->from.charset != -1 || psub->to.charset != -1)
904             TRACE("%s:%d -> %s:%d\n", debugstr_w(psub->from.name),
905               psub->from.charset, debugstr_w(psub->to.name), psub->to.charset);
906         else
907             TRACE("%s -> %s\n", debugstr_w(psub->from.name),
908                   debugstr_w(psub->to.name));
909     }
910     return;
911 }
912 
913 static LPWSTR strdupW(LPCWSTR p)
914 {
915     LPWSTR ret;
916     DWORD len = (strlenW(p) + 1) * sizeof(WCHAR);
917     ret = HeapAlloc(GetProcessHeap(), 0, len);
918     memcpy(ret, p, len);
919     return ret;
920 }
921 
922 static LPSTR strdupA(LPCSTR p)
923 {
924     LPSTR ret;
925     DWORD len = (strlen(p) + 1);
926     ret = HeapAlloc(GetProcessHeap(), 0, len);
927     memcpy(ret, p, len);
928     return ret;
929 }
930 
931 static FontSubst *get_font_subst(const struct list *subst_list, const WCHAR *from_name,
932                                  INT from_charset)
933 {
934     FontSubst *element;
935 
936     LIST_FOR_EACH_ENTRY(element, subst_list, FontSubst, entry)
937     {
938         if(!strcmpiW(element->from.name, from_name) &&
939            (element->from.charset == from_charset ||
940             element->from.charset == -1))
941             return element;
942     }
943 
944     return NULL;
945 }
946 
947 #define ADD_FONT_SUBST_FORCE  1
948 
949 static BOOL add_font_subst(struct list *subst_list, FontSubst *subst, INT flags)
950 {
951     FontSubst *from_exist, *to_exist;
952 
953     from_exist = get_font_subst(subst_list, subst->from.name, subst->from.charset);
954 
955     if(from_exist && (flags & ADD_FONT_SUBST_FORCE))
956     {
957         list_remove(&from_exist->entry);
958         HeapFree(GetProcessHeap(), 0, &from_exist->from.name);
959         HeapFree(GetProcessHeap(), 0, &from_exist->to.name);
960         HeapFree(GetProcessHeap(), 0, from_exist);
961         from_exist = NULL;
962     }
963 
964     if(!from_exist)
965     {
966         to_exist = get_font_subst(subst_list, subst->to.name, subst->to.charset);
967 
968         if(to_exist)
969         {
970             HeapFree(GetProcessHeap(), 0, subst->to.name);
971             subst->to.name = strdupW(to_exist->to.name);
972         }
973             
974         list_add_tail(subst_list, &subst->entry);
975 
976         return TRUE;
977     }
978 
979     HeapFree(GetProcessHeap(), 0, subst->from.name);
980     HeapFree(GetProcessHeap(), 0, subst->to.name);
981     HeapFree(GetProcessHeap(), 0, subst);
982     return FALSE;
983 }
984 
985 static void split_subst_info(NameCs *nc, LPSTR str)
986 {
987     CHAR *p = strrchr(str, ',');
988     DWORD len;
989 
990     nc->charset = -1;
991     if(p && *(p+1)) {
992         nc->charset = strtol(p+1, NULL, 10);
993         *p = '\0';
994     }
995     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
996     nc->name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
997     MultiByteToWideChar(CP_ACP, 0, str, -1, nc->name, len);
998 }
999 
1000 static void LoadSubstList(void)
1001 {
1002     FontSubst *psub;
1003     HKEY hkey;
1004     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
1005     LPSTR value;
1006     LPVOID data;
1007 
1008     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
1009                    "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes",
1010                    &hkey) == ERROR_SUCCESS) {
1011 
1012         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1013                          &valuelen, &datalen, NULL, NULL);
1014 
1015         valuelen++; /* returned value doesn't include room for '\0' */
1016         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
1017         data = HeapAlloc(GetProcessHeap(), 0, datalen);
1018 
1019         dlen = datalen;
1020         vlen = valuelen;
1021         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
1022                             &dlen) == ERROR_SUCCESS) {
1023             TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
1024 
1025             psub = HeapAlloc(GetProcessHeap(), 0, sizeof(*psub));
1026             split_subst_info(&psub->from, value);
1027             split_subst_info(&psub->to, data);
1028 
1029             /* Win 2000 doesn't allow mapping between different charsets
1030                or mapping of DEFAULT_CHARSET */
1031             if ((psub->from.charset && psub->to.charset != psub->from.charset) ||
1032                psub->to.charset == DEFAULT_CHARSET) {
1033                 HeapFree(GetProcessHeap(), 0, psub->to.name);
1034                 HeapFree(GetProcessHeap(), 0, psub->from.name);
1035                 HeapFree(GetProcessHeap(), 0, psub);
1036             } else {
1037                 add_font_subst(&font_subst_list, psub, 0);
1038             }
1039             /* reset dlen and vlen */
1040             dlen = datalen;
1041             vlen = valuelen;
1042         }
1043         HeapFree(GetProcessHeap(), 0, data);
1044         HeapFree(GetProcessHeap(), 0, value);
1045         RegCloseKey(hkey);
1046     }
1047 }
1048 
1049 
1050 /*****************************************************************
1051  *       get_name_table_entry
1052  *
1053  * Supply the platform, encoding, language and name ids in req
1054  * and if the name exists the function will fill in the string
1055  * and string_len members.  The string is owned by FreeType so
1056  * don't free it.  Returns TRUE if the name is found else FALSE.
1057  */
1058 static BOOL get_name_table_entry(FT_Face ft_face, FT_SfntName *req)
1059 {
1060     FT_SfntName name;
1061     FT_UInt num_names, name_index;
1062 
1063     if(FT_IS_SFNT(ft_face))
1064     {
1065         num_names = pFT_Get_Sfnt_Name_Count(ft_face);
1066 
1067         for(name_index = 0; name_index < num_names; name_index++)
1068         {
1069             if(!pFT_Get_Sfnt_Name(ft_face, name_index, &name))
1070             {
1071                 if((name.platform_id == req->platform_id) &&
1072                    (name.encoding_id == req->encoding_id) &&
1073                    (name.language_id == req->language_id) &&
1074                    (name.name_id     == req->name_id))
1075                 {
1076                     req->string = name.string;
1077                     req->string_len = name.string_len;
1078                     return TRUE;
1079                 }
1080             }
1081         }
1082     }
1083     req->string = NULL;
1084     req->string_len = 0;
1085     return FALSE;
1086 }
1087 
1088 static WCHAR *get_familyname(FT_Face ft_face)
1089 {
1090     WCHAR *family = NULL;
1091     FT_SfntName name;
1092 
1093     name.platform_id = TT_PLATFORM_MICROSOFT;
1094     name.encoding_id = TT_MS_ID_UNICODE_CS;
1095     name.language_id = GetUserDefaultLCID();
1096     name.name_id     = TT_NAME_ID_FONT_FAMILY;
1097 
1098     if(get_name_table_entry(ft_face, &name))
1099     {
1100         FT_UInt i;
1101 
1102         /* String is not nul terminated and string_len is a byte length. */
1103         family = HeapAlloc(GetProcessHeap(), 0, name.string_len + 2);
1104         for(i = 0; i < name.string_len / 2; i++)
1105         {
1106             WORD *tmp = (WORD *)&name.string[i * 2];
1107             family[i] = GET_BE_WORD(*tmp);
1108         }
1109         family[i] = 0;
1110         TRACE("Got localised name %s\n", debugstr_w(family));
1111     }
1112 
1113     return family;
1114 }
1115 
1116 
1117 /*****************************************************************
1118  *  load_sfnt_table
1119  *
1120  * Wrapper around FT_Load_Sfnt_Table to cope with older versions
1121  * of FreeType that don't export this function.
1122  *
1123  */
1124 static FT_Error load_sfnt_table(FT_Face ft_face, FT_ULong table, FT_Long offset, FT_Byte *buf, FT_ULong *len)
1125 {
1126 
1127     FT_Error err;
1128 
1129     /* If the FT_Load_Sfnt_Table function is there we'll use it */
1130     if(pFT_Load_Sfnt_Table)
1131     {
1132         err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, len);
1133     }
1134 #ifdef HAVE_FREETYPE_INTERNAL_SFNT_H
1135     else  /* Do it the hard way */
1136     {
1137         TT_Face tt_face = (TT_Face) ft_face;
1138         SFNT_Interface *sfnt;
1139         if (FT_Version.major==2 && FT_Version.minor==0)
1140         {
1141             /* 2.0.x */
1142             sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
1143         }
1144         else
1145         {
1146             /* A field was added in the middle of the structure in 2.1.x */
1147             sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
1148         }
1149         err = sfnt->load_any(tt_face, table, offset, buf, len);
1150     }
1151 #else
1152     else
1153     {
1154         static int msg;
1155         if(!msg)
1156         {
1157             MESSAGE("This version of Wine was compiled with freetype headers later than 2.2.0\n"
1158                     "but is being run with a freetype library without the FT_Load_Sfnt_Table function.\n"
1159                     "Please upgrade your freetype library.\n");
1160             msg++;
1161         }
1162         err = FT_Err_Unimplemented_Feature;
1163     }
1164 #endif
1165     return err;
1166 }
1167 
1168 static inline int TestStyles(DWORD flags, DWORD styles)
1169 {
1170     return (flags & styles) == styles;
1171 }
1172 
1173 static int StyleOrdering(Face *face)
1174 {
1175     if (TestStyles(face->ntmFlags, NTM_BOLD | NTM_ITALIC))
1176         return 3;
1177     if (TestStyles(face->ntmFlags, NTM_ITALIC))
1178         return 2;
1179     if (TestStyles(face->ntmFlags, NTM_BOLD))
1180         return 1;
1181     if (TestStyles(face->ntmFlags, NTM_REGULAR))
1182         return 0;
1183 
1184     WARN("Don't know how to order font %s %s with flags 0x%08x\n",
1185          debugstr_w(face->family->FamilyName),
1186          debugstr_w(face->StyleName),
1187          face->ntmFlags);
1188 
1189     return 9999;
1190 }
1191 
1192 /* Add a style of face to a font family using an ordering of the list such
1193    that regular fonts come before bold and italic, and single styles come
1194    before compound styles.  */
1195 static void AddFaceToFamily(Face *face, Family *family)
1196 {
1197     struct list *entry;
1198 
1199     LIST_FOR_EACH( entry, &family->faces )
1200     {
1201         Face *ent = LIST_ENTRY(entry, Face, entry);
1202         if (StyleOrdering(face) < StyleOrdering(ent)) break;
1203     }
1204     list_add_before( entry, &face->entry );
1205 }
1206 
1207 #define ADDFONT_EXTERNAL_FONT 0x01
1208 #define ADDFONT_FORCE_BITMAP  0x02
1209 static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_size, char *fake_family, const WCHAR *target_family, DWORD flags)
1210 {
1211     FT_Face ft_face;
1212     TT_OS2 *pOS2;
1213     TT_Header *pHeader = NULL;
1214     WCHAR *english_family, *localised_family, *StyleW;
1215     DWORD len;
1216     Family *family;
1217     Face *face;
1218     struct list *family_elem_ptr, *face_elem_ptr;
1219     FT_Error err;
1220     FT_Long face_index = 0, num_faces;
1221 #ifdef HAVE_FREETYPE_FTWINFNT_H
1222     FT_WinFNT_HeaderRec winfnt_header;
1223 #endif
1224     int i, bitmap_num, internal_leading;
1225     FONTSIGNATURE fs;
1226 
1227     /* we always load external fonts from files - otherwise we would get a crash in update_reg_entries */
1228     assert(file || !(flags & ADDFONT_EXTERNAL_FONT));
1229 
1230 #ifdef HAVE_CARBON_CARBON_H
1231     if(file && !fake_family)
1232     {
1233         char **mac_list = expand_mac_font(file);
1234         if(mac_list)
1235         {
1236             BOOL had_one = FALSE;
1237             char **cursor;
1238             for(cursor = mac_list; *cursor; cursor++)
1239             {
1240                 had_one = TRUE;
1241                 AddFontToList(*cursor, NULL, 0, NULL, NULL, flags);
1242                 HeapFree(GetProcessHeap(), 0, *cursor);
1243             }
1244             HeapFree(GetProcessHeap(), 0, mac_list);
1245             if(had_one)
1246                 return 1;
1247         }
1248     }
1249 #endif /* HAVE_CARBON_CARBON_H */
1250 
1251     do {
1252         char *family_name = fake_family;
1253 
1254         if (file)
1255         {
1256             TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
1257             err = pFT_New_Face(library, file, face_index, &ft_face);
1258         } else
1259         {
1260             TRACE("Loading font from ptr %p size %d, index %ld\n", font_data_ptr, font_data_size, face_index);
1261             err = pFT_New_Memory_Face(library, font_data_ptr, font_data_size, face_index, &ft_face);
1262         }
1263 
1264         if(err != 0) {
1265             WARN("Unable to load font %s/%p err = %x\n", debugstr_a(file), font_data_ptr, err);
1266             return 0;
1267         }
1268 
1269         if(!FT_IS_SFNT(ft_face) && (FT_IS_SCALABLE(ft_face) || !(flags & ADDFONT_FORCE_BITMAP))) { /* for now we'll accept TT/OT or bitmap fonts*/
1270             WARN("Ignoring font %s/%p\n", debugstr_a(file), font_data_ptr);
1271             pFT_Done_Face(ft_face);
1272             return 0;
1273         }
1274 
1275         /* There are too many bugs in FreeType < 2.1.9 for bitmap font support */
1276         if(!FT_IS_SCALABLE(ft_face) && FT_SimpleVersion < ((2 << 16) | (1 << 8) | (9 << 0))) {
1277             WARN("FreeType version < 2.1.9, skipping bitmap font %s/%p\n", debugstr_a(file), font_data_ptr);
1278             pFT_Done_Face(ft_face);
1279             return 0;
1280         }
1281 
1282         if(FT_IS_SFNT(ft_face))
1283         {
1284             if(!(pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2)) ||
1285                !pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea) ||
1286                !(pHeader = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_head)))
1287             {
1288                 TRACE("Font %s/%p lacks either an OS2, HHEA or HEAD table.\n"
1289                       "Skipping this font.\n", debugstr_a(file), font_data_ptr);
1290                 pFT_Done_Face(ft_face);
1291                 return 0;
1292             }
1293 
1294             /* Wine uses ttfs as an intermediate step in building its bitmap fonts;
1295                we don't want to load these. */
1296             if(!memcmp(pOS2->achVendID, "Wine", sizeof(pOS2->achVendID)))
1297             {
1298                 FT_ULong len = 0;
1299 
1300                 if(!load_sfnt_table(ft_face, FT_MAKE_TAG('E','B','S','C'), 0, NULL, &len))
1301                 {
1302                     TRACE("Skipping Wine bitmap-only TrueType font %s\n", debugstr_a(file));
1303                     pFT_Done_Face(ft_face);
1304                     return 0;
1305                 }
1306             }
1307         }
1308 
1309         if(!ft_face->family_name || !ft_face->style_name) {
1310             TRACE("Font %s/%p lacks either a family or style name\n", debugstr_a(file), font_data_ptr);
1311             pFT_Done_Face(ft_face);
1312             return 0;
1313         }
1314 
1315         if(ft_face->family_name[0] == '.') /* Ignore fonts with names beginning with a dot */
1316         {
1317             TRACE("Ignoring %s since its family name begins with a dot\n", debugstr_a(file));
1318             pFT_Done_Face(ft_face);
1319             return 0;
1320         }
1321 
1322         if (target_family)
1323         {
1324             localised_family = get_familyname(ft_face);
1325             if (localised_family && strcmpiW(localised_family,target_family)!=0)
1326             {
1327                 TRACE("Skipping Index %i: Incorrect Family name for replacement\n",(INT)face_index);
1328                 HeapFree(GetProcessHeap(), 0, localised_family);
1329                 num_faces = ft_face->num_faces;
1330                 pFT_Done_Face(ft_face);
1331                 continue;
1332             }
1333             HeapFree(GetProcessHeap(), 0, localised_family);
1334         }
1335 
1336         if(!family_name)
1337             family_name = ft_face->family_name;
1338 
1339         bitmap_num = 0;
1340         do {
1341             My_FT_Bitmap_Size *size = NULL;
1342             FT_ULong tmp_size;
1343 
1344             if(!FT_IS_SCALABLE(ft_face))
1345                 size = (My_FT_Bitmap_Size *)ft_face->available_sizes + bitmap_num;
1346 
1347             len = MultiByteToWideChar(CP_ACP, 0, family_name, -1, NULL, 0);
1348             english_family = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1349             MultiByteToWideChar(CP_ACP, 0, family_name, -1, english_family, len);
1350 
1351             localised_family = NULL;
1352             if(!fake_family) {
1353                 localised_family = get_familyname(ft_face);
1354                 if(localised_family && !strcmpiW(localised_family, english_family)) {
1355                     HeapFree(GetProcessHeap(), 0, localised_family);
1356                     localised_family = NULL;
1357                 }
1358             }
1359 
1360             family = NULL;
1361             LIST_FOR_EACH(family_elem_ptr, &font_list) {
1362                 family = LIST_ENTRY(family_elem_ptr, Family, entry);
1363                 if(!strcmpiW(family->FamilyName, localised_family ? localised_family : english_family))
1364                     break;
1365                 family = NULL;
1366             }
1367             if(!family) {
1368                 family = HeapAlloc(GetProcessHeap(), 0, sizeof(*family));
1369                 family->FamilyName = strdupW(localised_family ? localised_family : english_family);
1370                 list_init(&family->faces);
1371                 list_add_tail(&font_list, &family->entry);
1372 
1373                 if(localised_family) {
1374                     FontSubst *subst = HeapAlloc(GetProcessHeap(), 0, sizeof(*subst));
1375                     subst->from.name = strdupW(english_family);
1376                     subst->from.charset = -1;
1377                     subst->to.name = strdupW(localised_family);
1378                     subst->to.charset = -1;
1379                     add_font_subst(&font_subst_list, subst, 0);
1380                 }
1381             }
1382             HeapFree(GetProcessHeap(), 0, localised_family);
1383             HeapFree(GetProcessHeap(), 0, english_family);
1384 
1385             len = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0);
1386             StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1387             MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
1388 
1389             internal_leading = 0;
1390             memset(&fs, 0, sizeof(fs));
1391 
1392             pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
1393             if(pOS2) {
1394                 fs.fsCsb[0] = pOS2->ulCodePageRange1;
1395                 fs.fsCsb[1] = pOS2->ulCodePageRange2;
1396                 fs.fsUsb[0] = pOS2->ulUnicodeRange1;
1397                 fs.fsUsb[1] = pOS2->ulUnicodeRange2;
1398                 fs.fsUsb[2] = pOS2->ulUnicodeRange3;
1399                 fs.fsUsb[3] = pOS2->ulUnicodeRange4;
1400                 if(pOS2->version == 0) {
1401                     FT_UInt dummy;
1402 
1403                     if(!pFT_Get_First_Char || (pFT_Get_First_Char( ft_face, &dummy ) < 0x100))
1404                         fs.fsCsb[0] |= FS_LATIN1;
1405                     else
1406                         fs.fsCsb[0] |= FS_SYMBOL;
1407                 }
1408             }
1409 #ifdef HAVE_FREETYPE_FTWINFNT_H
1410             else if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header)) {
1411                 CHARSETINFO csi;
1412                 TRACE("pix_h %d charset %d dpi %dx%d pt %d\n", winfnt_header.pixel_height, winfnt_header.charset,
1413                       winfnt_header.vertical_resolution,winfnt_header.horizontal_resolution, winfnt_header.nominal_point_size);
1414                 if(TranslateCharsetInfo((DWORD*)(UINT_PTR)winfnt_header.charset, &csi, TCI_SRCCHARSET))
1415                     fs = csi.fs;
1416                 internal_leading = winfnt_header.internal_leading;
1417             }
1418 #endif
1419 
1420             face_elem_ptr = list_head(&family->faces);
1421             while(face_elem_ptr) {
1422                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
1423                 face_elem_ptr = list_next(&family->faces, face_elem_ptr);
1424                 if(!strcmpiW(face->StyleName, StyleW) &&
1425                    (FT_IS_SCALABLE(ft_face) || ((size->y_ppem == face->size.y_ppem) && !memcmp(&fs, &face->fs, sizeof(fs)) ))) {
1426                     TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
1427                           debugstr_w(family->FamilyName), debugstr_w(StyleW),
1428                           face->font_version,  pHeader ? pHeader->Font_Revision : 0);
1429 
1430                     if(fake_family) {
1431                         TRACE("This font is a replacement but the original really exists, so we'll skip the replacement\n");
1432                         HeapFree(GetProcessHeap(), 0, StyleW);
1433                         pFT_Done_Face(ft_face);
1434                         return 1;
1435                     }
1436                     if(!pHeader || pHeader->Font_Revision <= face->font_version) {
1437                         TRACE("Original font is newer so skipping this one\n");
1438                         HeapFree(GetProcessHeap(), 0, StyleW);
1439                         pFT_Done_Face(ft_face);
1440                         return 1;
1441                     } else {
1442                         TRACE("Replacing original with this one\n");
1443                         list_remove(&face->entry);
1444                         HeapFree(GetProcessHeap(), 0, face->file);
1445                         HeapFree(GetProcessHeap(), 0, face->StyleName);
1446                         HeapFree(GetProcessHeap(), 0, face);
1447                         break;
1448                     }
1449                 }
1450             }
1451             face = HeapAlloc(GetProcessHeap(), 0, sizeof(*face));
1452             face->cached_enum_data = NULL;
1453             face->StyleName = StyleW;
1454             if (file)
1455             {
1456                 face->file = strdupA(file);
1457                 face->font_data_ptr = NULL;
1458                 face->font_data_size = 0;
1459             }
1460             else
1461             {
1462                 face->file = NULL;
1463                 face->font_data_ptr = font_data_ptr;
1464                 face->font_data_size = font_data_size;
1465             }
1466             face->face_index = face_index;
1467             face->ntmFlags = 0;
1468             if (ft_face->style_flags & FT_STYLE_FLAG_ITALIC)
1469                 face->ntmFlags |= NTM_ITALIC;
1470             if (ft_face->style_flags & FT_STYLE_FLAG_BOLD)
1471                 face->ntmFlags |= NTM_BOLD;
1472             if (face->ntmFlags == 0) face->ntmFlags = NTM_REGULAR;
1473             face->font_version = pHeader ? pHeader->Font_Revision : 0;
1474             face->family = family;
1475             face->external = (flags & ADDFONT_EXTERNAL_FONT) ? TRUE : FALSE;
1476             face->fs = fs;
1477             memset(&face->fs_links, 0, sizeof(face->fs_links));
1478 
1479             if(FT_IS_SCALABLE(ft_face)) {
1480                 memset(&face->size, 0, sizeof(face->size));
1481                 face->scalable = TRUE;
1482             } else {
1483                 TRACE("Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld\n",
1484                       size->height, size->width, size->size >> 6,
1485                       size->x_ppem >> 6, size->y_ppem >> 6);
1486                 face->size.height = size->height;
1487                 face->size.width = size->width;
1488                 face->size.size = size->size;
1489                 face->size.x_ppem = size->x_ppem;
1490                 face->size.y_ppem = size->y_ppem;
1491                 face->size.internal_leading = internal_leading;
1492                 face->scalable = FALSE;
1493             }
1494 
1495             /* check for the presence of the 'CFF ' table to check if the font is Type1 */
1496             tmp_size = 0;
1497             if (pFT_Load_Sfnt_Table && !pFT_Load_Sfnt_Table(ft_face, FT_MAKE_TAG('C','F','F',' '), 0, NULL, &tmp_size))
1498             {
1499                 TRACE("Font %s/%p is OTF Type1\n", wine_dbgstr_a(file), font_data_ptr);
1500                 face->ntmFlags |= NTM_PS_OPENTYPE;
1501             }
1502 
1503             TRACE("fsCsb = %08x %08x/%08x %08x %08x %08x\n",
1504                   face->fs.fsCsb[0], face->fs.fsCsb[1],
1505                   face->fs.fsUsb[0], face->fs.fsUsb[1],
1506                   face->fs.fsUsb[2], face->fs.fsUsb[3]);
1507 
1508 
1509             if(face->fs.fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */
1510                 for(i = 0; i < ft_face->num_charmaps; i++) {
1511                     switch(ft_face->charmaps[i]->encoding) {
1512                     case FT_ENCODING_UNICODE:
1513                     case FT_ENCODING_APPLE_ROMAN:
1514                         face->fs.fsCsb[0] |= FS_LATIN1;
1515                         break;
1516                     case FT_ENCODING_MS_SYMBOL:
1517                         face->fs.fsCsb[0] |= FS_SYMBOL;
1518                         break;
1519                     default:
1520                         break;
1521                     }
1522                 }
1523             }
1524 
1525             if (!(face->fs.fsCsb[0] & FS_SYMBOL))
1526                 have_installed_roman_font = TRUE;
1527 
1528             AddFaceToFamily(face, family);
1529 
1530         } while(!FT_IS_SCALABLE(ft_face) && ++bitmap_num < ft_face->num_fixed_sizes);
1531 
1532         num_faces = ft_face->num_faces;
1533         pFT_Done_Face(ft_face);
1534         TRACE("Added font %s %s\n", debugstr_w(family->FamilyName),
1535               debugstr_w(StyleW));
1536     } while(num_faces > ++face_index);
1537     return num_faces;
1538 }
1539 
1540 static INT AddFontFileToList(const char *file, char *fake_family, const WCHAR *target_family, DWORD flags)
1541 {
1542     return AddFontToList(file, NULL, 0, fake_family, target_family, flags);
1543 }
1544 
1545 static void DumpFontList(void)
1546 {
1547     Family *family;
1548     Face *face;
1549     struct list *family_elem_ptr, *face_elem_ptr;
1550 
1551     LIST_FOR_EACH(family_elem_ptr, &font_list) {
1552         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
1553         TRACE("Family: %s\n", debugstr_w(family->FamilyName));
1554         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
1555             face = LIST_ENTRY(face_elem_ptr, Face, entry);
1556             TRACE("\t%s\t%08x", debugstr_w(face->StyleName), face->fs.fsCsb[0]);
1557             if(!face->scalable)
1558                 TRACE(" %d", face->size.height);
1559             TRACE("\n");
1560         }
1561     }
1562     return;
1563 }
1564 
1565 /***********************************************************
1566  * The replacement list is a way to map an entire font
1567  * family onto another family.  For example adding
1568  *
1569  * [HKCU\Software\Wine\Fonts\Replacements]
1570  * "Wingdings"="Winedings"
1571  *
1572  * would enumerate the Winedings font both as Winedings and
1573  * Wingdings.  However if a real Wingdings font is present the
1574  * replacement does not take place.
1575  * 
1576  */
1577 static void LoadReplaceList(void)
1578 {
1579     HKEY hkey;
1580     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
1581     LPWSTR value;
1582     LPVOID data;
1583     Family *family;
1584     Face *face;
1585     struct list *family_elem_ptr, *face_elem_ptr;
1586     CHAR familyA[400];
1587 
1588     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\Replacements */
1589     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts\\Replacements", &hkey) == ERROR_SUCCESS)
1590     {
1591         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1592                          &valuelen, &datalen, NULL, NULL);
1593 
1594         valuelen++; /* returned value doesn't include room for '\0' */
1595         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
1596         data = HeapAlloc(GetProcessHeap(), 0, datalen);
1597 
1598         dlen = datalen;
1599         vlen = valuelen;
1600         while(RegEnumValueW(hkey, i++, value, &vlen, NULL, &type, data,
1601                             &dlen) == ERROR_SUCCESS) {
1602             TRACE("Got %s=%s\n", debugstr_w(value), debugstr_w(data));
1603             /* "NewName"="Oldname" */
1604             WideCharToMultiByte(CP_ACP, 0, value, -1, familyA, sizeof(familyA), NULL, NULL);
1605 
1606             /* Find the old family and hence all of the font files
1607                in that family */
1608             LIST_FOR_EACH(family_elem_ptr, &font_list) {
1609                 family = LIST_ENTRY(family_elem_ptr, Family, entry);
1610                 if(!strcmpiW(family->FamilyName, data)) {
1611                     LIST_FOR_EACH(face_elem_ptr, &family->faces) {
1612                         face = LIST_ENTRY(face_elem_ptr, Face, entry);
1613                         TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName),
1614                               debugstr_w(face->StyleName), familyA);
1615                         /* Now add a new entry with the new family name */
1616                         AddFontToList(face->file, face->font_data_ptr, face->font_data_size, familyA, family->FamilyName, ADDFONT_FORCE_BITMAP | (face->external ? ADDFONT_EXTERNAL_FONT : 0));
1617                     }
1618                     break;
1619                 }
1620             }
1621             /* reset dlen and vlen */
1622             dlen = datalen;
1623             vlen = valuelen;
1624         }
1625         HeapFree(GetProcessHeap(), 0, data);
1626         HeapFree(GetProcessHeap(), 0, value);
1627         RegCloseKey(hkey);
1628     }
1629 }
1630 
1631 /*************************************************************
1632  * init_system_links
1633  */
1634 static BOOL init_system_links(void)
1635 {
1636     HKEY hkey;
1637     BOOL ret = FALSE;
1638     DWORD type, max_val, max_data, val_len, data_len, index;
1639     WCHAR *value, *data;
1640     WCHAR *entry, *next;
1641     SYSTEM_LINKS *font_link, *system_font_link;
1642     CHILD_FONT *child_font;
1643     static const WCHAR tahoma_ttf[] = {'t','a','h','o','m','a','.','t','t','f',0};
1644     static const WCHAR System[] = {'S','y','s','t','e','m',0};
1645     FONTSIGNATURE fs;
1646     Family *family;
1647     Face *face;
1648     FontSubst *psub;
1649 
1650     if(RegOpenKeyW(HKEY_LOCAL_MACHINE, system_link, &hkey) == ERROR_SUCCESS)
1651     {
1652         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &max_val, &max_data, NULL, NULL);
1653         value = HeapAlloc(GetProcessHeap(), 0, (max_val + 1) * sizeof(WCHAR));
1654         data = HeapAlloc(GetProcessHeap(), 0, max_data);
1655         val_len = max_val + 1;
1656         data_len = max_data;
1657         index = 0;
1658         while(RegEnumValueW(hkey, index++, value, &val_len, NULL, &type, (LPBYTE)data, &data_len) == ERROR_SUCCESS)
1659         {
1660             memset(&fs, 0, sizeof(fs));
1661             psub = get_font_subst(&font_subst_list, value, -1);
1662             /* Don't store fonts that are only substitutes for other fonts */
1663             if(psub)
1664             {
1665                 TRACE("%s: SystemLink entry for substituted font, ignoring\n", debugstr_w(value));
1666                 continue;
1667             }
1668             font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_link));
1669             font_link->font_name = strdupW(value);
1670             list_init(&font_link->links);
1671             for(entry = data; (char*)entry < (char*)data + data_len && *entry != 0; entry = next)
1672             {
1673                 WCHAR *face_name;
1674                 CHILD_FONT *child_font;
1675 
1676                 TRACE("%s: %s\n", debugstr_w(value), debugstr_w(entry));
1677 
1678                 next = entry + strlenW(entry) + 1;
1679                 
1680                 face_name = strchrW(entry, ',');
1681                 if(face_name)
1682                 {
1683                     *face_name++ = 0;
1684                     while(isspaceW(*face_name))
1685                         face_name++;
1686 
1687                     psub = get_font_subst(&font_subst_list, face_name, -1);
1688                     if(psub)
1689                         face_name = psub->to.name;
1690                 }
1691                 face = find_face_from_filename(entry, face_name);
1692                 if(!face)
1693                 {
1694                     TRACE("Unable to find file %s face name %s\n", debugstr_w(entry), debugstr_w(face_name));
1695                     continue;
1696                 }
1697 
1698                 child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
1699                 child_font->face = face;
1700                 child_font->font = NULL;
1701                 fs.fsCsb[0] |= face->fs.fsCsb[0];
1702                 fs.fsCsb[1] |= face->fs.fsCsb[1];
1703                 TRACE("Adding file %s index %ld\n", child_font->face->file, child_font->face->face_index);
1704                 list_add_tail(&font_link->links, &child_font->entry);
1705             }
1706             family = find_family_from_name(font_link->font_name);
1707             if(family)
1708             {
1709                 LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
1710                 {
1711                     face->fs_links = fs;
1712                 }
1713             }
1714             list_add_tail(&system_links, &font_link->entry);
1715             val_len = max_val + 1;
1716             data_len = max_data;
1717         }
1718 
1719         HeapFree(GetProcessHeap(), 0, value);
1720         HeapFree(GetProcessHeap(), 0, data);
1721         RegCloseKey(hkey);
1722     }
1723 
1724     /* Explicitly add an entry for the system font, this links to Tahoma and any links
1725        that Tahoma has */
1726 
1727     system_font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*system_font_link));
1728     system_font_link->font_name = strdupW(System);
1729     list_init(&system_font_link->links);    
1730 
1731     face = find_face_from_filename(tahoma_ttf, Tahoma);
1732     if(face)
1733     {
1734         child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
1735         child_font->face = face;
1736         child_font->font = NULL;
1737         TRACE("Found Tahoma in %s index %ld\n", child_font->face->file, child_font->face->face_index);
1738         list_add_tail(&system_font_link->links, &child_font->entry);
1739     }
1740     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
1741     {
1742         if(!strcmpiW(font_link->font_name, Tahoma))
1743         {
1744             CHILD_FONT *font_link_entry;
1745             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
1746             {
1747                 CHILD_FONT *new_child;
1748                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
1749                 new_child->face = font_link_entry->face;
1750                 new_child->font = NULL;
1751                 list_add_tail(&system_font_link->links, &new_child->entry);
1752             }
1753             break;
1754         }
1755     }
1756     list_add_tail(&system_links, &system_font_link->entry);
1757     return ret;
1758 }
1759 
1760 static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
1761 {
1762     DIR *dir;
1763     struct dirent *dent;
1764     char path[MAX_PATH];
1765 
1766     TRACE("Loading fonts from %s\n", debugstr_a(dirname));
1767 
1768     dir = opendir(dirname);
1769     if(!dir) {
1770         WARN("Can't open directory %s\n", debugstr_a(dirname));
1771         return FALSE;
1772     }
1773     while((dent = readdir(dir)) != NULL) {
1774         struct stat statbuf;
1775 
1776         if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
1777             continue;
1778 
1779         TRACE("Found %s in %s\n", debugstr_a(dent->d_name), debugstr_a(dirname));
1780 
1781         sprintf(path, "%s/%s", dirname, dent->d_name);
1782 
1783         if(stat(path, &statbuf) == -1)
1784         {
1785             WARN("Can't stat %s\n", debugstr_a(path));
1786             continue;
1787         }
1788         if(S_ISDIR(statbuf.st_mode))
1789             ReadFontDir(path, external_fonts);
1790         else
1791             AddFontFileToList(path, NULL, NULL, external_fonts ? ADDFONT_EXTERNAL_FONT : 0);
1792     }
1793     closedir(dir);
1794     return TRUE;
1795 }
1796 
1797 static void load_fontconfig_fonts(void)
1798 {
1799 #ifdef SONAME_LIBFONTCONFIG
1800     void *fc_handle = NULL;
1801     FcConfig *config;
1802     FcPattern *pat;
1803     FcObjectSet *os;
1804     FcFontSet *fontset;
1805     int i, len;
1806     char *file;
1807     const char *ext;
1808 
1809     fc_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0);
1810     if(!fc_handle) {
1811         TRACE("Wine cannot find the fontconfig library (%s).\n",
1812               SONAME_LIBFONTCONFIG);
1813         return;
1814     }
1815 #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;}
1816 LOAD_FUNCPTR(FcConfigGetCurrent);
1817 LOAD_FUNCPTR(FcFontList);
1818 LOAD_FUNCPTR(FcFontSetDestroy);
1819 LOAD_FUNCPTR(FcInit);
1820 LOAD_FUNCPTR(FcObjectSetAdd);
1821 LOAD_FUNCPTR(FcObjectSetCreate);
1822 LOAD_FUNCPTR(FcObjectSetDestroy);
1823 LOAD_FUNCPTR(FcPatternCreate);
1824 LOAD_FUNCPTR(FcPatternDestroy);
1825 LOAD_FUNCPTR(FcPatternGetBool);
1826 LOAD_FUNCPTR(FcPatternGetString);
1827 #undef LOAD_FUNCPTR
1828 
1829     if(!pFcInit()) return;
1830     
1831     config = pFcConfigGetCurrent();
1832     pat = pFcPatternCreate();
1833     os = pFcObjectSetCreate();
1834     pFcObjectSetAdd(os, FC_FILE);
1835     pFcObjectSetAdd(os, FC_SCALABLE);
1836     fontset = pFcFontList(config, pat, os);
1837     if(!fontset) return;
1838     for(i = 0; i < fontset->nfont; i++) {
1839         FcBool scalable;
1840 
1841         if(pFcPatternGetString(fontset->fonts[i], FC_FILE, 0, (FcChar8**)&file) != FcResultMatch)
1842             continue;
1843         TRACE("fontconfig: %s\n", file);
1844 
1845         /* We're just interested in OT/TT fonts for now, so this hack just
1846            picks up the scalable fonts without extensions .pf[ab] to save time
1847            loading every other font */
1848 
1849         if(pFcPatternGetBool(fontset->fonts[i], FC_SCALABLE, 0, &scalable) == FcResultMatch && !scalable)
1850         {
1851             TRACE("not scalable\n");
1852             continue;
1853         }
1854 
1855         len = strlen( file );
1856         if(len < 4) continue;
1857         ext = &file[ len - 3 ];
1858         if(strcasecmp(ext, "pfa") && strcasecmp(ext, "pfb"))
1859             AddFontFileToList(file, NULL, NULL,  ADDFONT_EXTERNAL_FONT);
1860     }
1861     pFcFontSetDestroy(fontset);
1862     pFcObjectSetDestroy(os);
1863     pFcPatternDestroy(pat);
1864  sym_not_found:
1865 #endif
1866     return;
1867 }
1868 
1869 static BOOL load_font_from_data_dir(LPCWSTR file)
1870 {
1871     BOOL ret = FALSE;
1872     const char *data_dir = wine_get_data_dir();
1873 
1874     if (!data_dir) data_dir = wine_get_build_dir();
1875 
1876     if (data_dir)
1877     {
1878         INT len;
1879         char *unix_name;
1880 
1881         len = WideCharToMultiByte(CP_UNIXCP, 0, file, -1, NULL, 0, NULL, NULL);
1882 
1883         unix_name = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + len + sizeof("/fonts/"));
1884 
1885         strcpy(unix_name, data_dir);
1886         strcat(unix_name, "/fonts/");
1887 
1888         WideCharToMultiByte(CP_UNIXCP, 0, file, -1, unix_name + strlen(unix_name), len, NULL, NULL);
1889 
1890         EnterCriticalSection( &freetype_cs );
1891         ret = AddFontFileToList(unix_name, NULL, NULL, ADDFONT_FORCE_BITMAP);
1892         LeaveCriticalSection( &freetype_cs );
1893         HeapFree(GetProcessHeap(), 0, unix_name);
1894     }
1895     return ret;
1896 }
1897 
1898 static BOOL load_font_from_winfonts_dir(LPCWSTR file)
1899 {
1900     static const WCHAR slashW[] = {'\\','\0'};
1901     BOOL ret = FALSE;
1902     WCHAR windowsdir[MAX_PATH];
1903     char *unixname;
1904 
1905     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
1906     strcatW(windowsdir, fontsW);
1907     strcatW(windowsdir, slashW);
1908     strcatW(windowsdir, file);
1909     if ((unixname = wine_get_unix_file_name(windowsdir))) {
1910         EnterCriticalSection( &freetype_cs );
1911         ret = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
1912         LeaveCriticalSection( &freetype_cs );
1913         HeapFree(GetProcessHeap(), 0, unixname);
1914     }
1915     return ret;
1916 }
1917 
1918 static void load_system_fonts(void)
1919 {
1920     HKEY hkey;
1921     WCHAR data[MAX_PATH], windowsdir[MAX_PATH], pathW[MAX_PATH];
1922     const WCHAR * const *value;
1923     DWORD dlen, type;
1924     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
1925     char *unixname;
1926 
1927     if(RegOpenKeyW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, &hkey) == ERROR_SUCCESS) {
1928         GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
1929         strcatW(windowsdir, fontsW);
1930         for(value = SystemFontValues; *value; value++) { 
1931             dlen = sizeof(data);
1932             if(RegQueryValueExW(hkey, *value, 0, &type, (void*)data, &dlen) == ERROR_SUCCESS &&
1933                type == REG_SZ) {
1934                 BOOL added = FALSE;
1935 
1936                 sprintfW(pathW, fmtW, windowsdir, data);
1937                 if((unixname = wine_get_unix_file_name(pathW))) {
1938                     added = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
1939                     HeapFree(GetProcessHeap(), 0, unixname);
1940                 }
1941                 if (!added)
1942                     load_font_from_data_dir(data);
1943             }
1944         }
1945         RegCloseKey(hkey);
1946     }
1947 }
1948 
1949 /*************************************************************
1950  *
1951  * This adds registry entries for any externally loaded fonts
1952  * (fonts from fontconfig or FontDirs).  It also deletes entries
1953  * of no longer existing fonts.
1954  *
1955  */
1956 static void update_reg_entries(void)
1957 {
1958     HKEY winnt_key = 0, win9x_key = 0, external_key = 0;
1959     LPWSTR valueW;
1960     DWORD len, len_fam;
1961     Family *family;
1962     Face *face;
1963     struct list *family_elem_ptr, *face_elem_ptr;
1964     WCHAR *file;
1965     static const WCHAR TrueType[] = {' ','(','T','r','u','e','T','y','p','e',')','\0'};
1966     static const WCHAR spaceW[] = {' ', '\0'};
1967     char *path;
1968 
1969     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key,
1970                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &winnt_key, NULL) != ERROR_SUCCESS) {
1971         ERR("Can't create Windows font reg key\n");
1972         goto end;
1973     }
1974 
1975     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key,
1976                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &win9x_key, NULL) != ERROR_SUCCESS) {
1977         ERR("Can't create Windows font reg key\n");
1978         goto end;
1979     }
1980 
1981     if(RegCreateKeyExW(HKEY_CURRENT_USER, external_fonts_reg_key,
1982                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &external_key, NULL) != ERROR_SUCCESS) {
1983         ERR("Can't create external font reg key\n");
1984         goto end;
1985     }
1986 
1987     /* enumerate the fonts and add external ones to the two keys */
1988 
1989     LIST_FOR_EACH(family_elem_ptr, &font_list) {
1990         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
1991         len_fam = strlenW(family->FamilyName) + sizeof(TrueType) / sizeof(WCHAR) + 1;
1992         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
1993             face = LIST_ENTRY(face_elem_ptr, Face, entry);
1994             if(!face->external) continue;
1995             len = len_fam;
1996             if (!(face->ntmFlags & NTM_REGULAR))
1997                 len = len_fam + strlenW(face->StyleName) + 1;
1998             valueW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1999             strcpyW(valueW, family->FamilyName);
2000             if(len != len_fam) {
2001                 strcatW(valueW, spaceW);
2002                 strcatW(valueW, face->StyleName);
2003             }
2004             strcatW(valueW, TrueType);
2005 
2006             file = wine_get_dos_file_name(face->file);
2007             if(file)
2008                 len = strlenW(file) + 1;
2009             else
2010             {
2011                 if((path = strrchr(face->file, '/')) == NULL)
2012                     path = face->file;
2013                 else
2014                     path++;
2015                 len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
2016 
2017                 file = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2018                 MultiByteToWideChar(CP_ACP, 0, path, -1, file, len);
2019             }
2020             RegSetValueExW(winnt_key, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
2021             RegSetValueExW(win9x_key, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
2022             RegSetValueExW(external_key, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
2023 
2024             HeapFree(GetProcessHeap(), 0, file);
2025             HeapFree(GetProcessHeap(), 0, valueW);
2026         }
2027     }
2028  end:
2029     if(external_key) RegCloseKey(external_key);
2030     if(win9x_key) RegCloseKey(win9x_key);
2031     if(winnt_key) RegCloseKey(winnt_key);
2032     return;
2033 }
2034 
2035 static void delete_external_font_keys(void)
2036 {
2037     HKEY winnt_key = 0, win9x_key = 0, external_key = 0;
2038     DWORD dlen, vlen, datalen, valuelen, i, type;
2039     LPWSTR valueW;
2040     LPVOID data;
2041 
2042     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key,
2043                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &winnt_key, NULL) != ERROR_SUCCESS) {
2044         ERR("Can't create Windows font reg key\n");
2045         goto end;
2046     }
2047 
2048     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key,
2049                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &win9x_key, NULL) != ERROR_SUCCESS) {
2050         ERR("Can't create Windows font reg key\n");
2051         goto end;
2052     }
2053 
2054     if(RegCreateKeyW(HKEY_CURRENT_USER, external_fonts_reg_key, &external_key) != ERROR_SUCCESS) {
2055         ERR("Can't create external font reg key\n");
2056         goto end;
2057     }
2058 
2059     /* Delete all external fonts added last time */
2060 
2061     RegQueryInfoKeyW(external_key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2062                      &valuelen, &datalen, NULL, NULL);
2063     valuelen++; /* returned value doesn't include room for '\0' */
2064     valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
2065     data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
2066 
2067     dlen = datalen * sizeof(WCHAR);
2068     vlen = valuelen;
2069     i = 0;
2070     while(RegEnumValueW(external_key, i++, valueW, &vlen, NULL, &type, data,
2071                         &dlen) == ERROR_SUCCESS) {
2072 
2073         RegDeleteValueW(winnt_key, valueW);
2074         RegDeleteValueW(win9x_key, valueW);
2075         /* reset dlen and vlen */
2076         dlen = datalen;
2077         vlen = valuelen;
2078     }
2079     HeapFree(GetProcessHeap(), 0, data);
2080     HeapFree(GetProcessHeap(), 0, valueW);
2081 
2082     /* Delete the old external fonts key */
2083     RegCloseKey(external_key);
2084     RegDeleteKeyW(HKEY_CURRENT_USER, external_fonts_reg_key);
2085 
2086  end:
2087     if(win9x_key) RegCloseKey(win9x_key);
2088     if(winnt_key) RegCloseKey(winnt_key);
2089 }
2090 
2091 /*************************************************************
2092  *    WineEngAddFontResourceEx
2093  *
2094  */
2095 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
2096 {
2097     INT ret = 0;
2098 
2099     GDI_CheckNotLock();
2100 
2101     if (ft_handle)  /* do it only if we have freetype up and running */
2102     {
2103         char *unixname;
2104 
2105         if(flags)
2106             FIXME("Ignoring flags %x\n", flags);
2107 
2108         if((unixname = wine_get_unix_file_name(file)))
2109         {
2110             EnterCriticalSection( &freetype_cs );
2111             ret = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
2112             LeaveCriticalSection( &freetype_cs );
2113             HeapFree(GetProcessHeap(), 0, unixname);
2114         }
2115         if (!ret && !strchrW(file, '\\')) {
2116             /* Try in %WINDIR%/fonts, needed for Fotobuch Designer */
2117             ret = load_font_from_winfonts_dir(file);
2118             if (!ret) {
2119                 /* Try in datadir/fonts (or builddir/fonts),
2120                  * needed for Magic the Gathering Online
2121                  */
2122                 ret = load_font_from_data_dir(file);
2123             }
2124         }
2125     }
2126    return ret;
2127 }
2128 
2129 /*************************************************************
2130  *    WineEngAddFontMemResourceEx
2131  *
2132  */
2133 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
2134 {
2135     GDI_CheckNotLock();
2136 
2137     if (ft_handle)  /* do it only if we have freetype up and running */
2138     {
2139         PVOID pFontCopy = HeapAlloc(GetProcessHeap(), 0, cbFont);
2140 
2141         TRACE("Copying %d bytes of data from %p to %p\n", cbFont, pbFont, pFontCopy);
2142         memcpy(pFontCopy, pbFont, cbFont);
2143 
2144         EnterCriticalSection( &freetype_cs );
2145         *pcFonts = AddFontToList(NULL, pFontCopy, cbFont, NULL, NULL, ADDFONT_FORCE_BITMAP);
2146         LeaveCriticalSection( &freetype_cs );
2147 
2148         if (*pcFonts == 0)
2149         {
2150             TRACE("AddFontToList failed\n");
2151             HeapFree(GetProcessHeap(), 0, pFontCopy);
2152             return NULL;
2153         }
2154         /* FIXME: is the handle only for use in RemoveFontMemResourceEx or should it be a true handle?
2155          * For now return something unique but quite random
2156          */
2157         TRACE("Returning handle %lx\n", ((INT_PTR)pFontCopy)^0x87654321);
2158         return (HANDLE)(((INT_PTR)pFontCopy)^0x87654321);
2159     }
2160 
2161     *pcFonts = 0;
2162     return 0;
2163 }
2164 
2165 /*************************************************************
2166  *    WineEngRemoveFontResourceEx
2167  *
2168  */
2169 BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
2170 {
2171     GDI_CheckNotLock();
2172     FIXME(":stub\n");
2173     return TRUE;
2174 }
2175 
2176 static const struct nls_update_font_list
2177 {
2178     UINT ansi_cp, oem_cp;
2179     const char *oem, *fixed, *system;
2180     const char *courier, *serif, *small, *sserif;
2181     /* these are for font substitutes */
2182     const char *shelldlg, *tmsrmn;
2183     const char *fixed_0, *system_0, *courier_0, *serif_0, *small_0, *sserif_0,
2184                *helv_0, *tmsrmn_0;
2185     const struct subst
2186     {
2187         const char *from, *to;
2188     } arial_0, courier_new_0, times_new_roman_0;
2189 } nls_update_font_list[] =
2190 {
2191     /* Latin 1 (United States) */
2192     { 1252, 437, "vgaoem.fon", "vgafix.fon", "vgasys.fon",
2193       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2194       "Tahoma","Times New Roman",
2195       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2196       { 0 }, { 0 }, { 0 }
2197     },
2198     /* Latin 1 (Multilingual) */
2199     { 1252, 850, "vga850.fon", "vgafix.fon", "vgasys.fon",
2200       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2201       "Tahoma","Times New Roman",  /* FIXME unverified */
2202       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2203       { 0 }, { 0 }, { 0 }
2204     },
2205     /* Eastern Europe */
2206     { 1250, 852, "vga852.fon", "vgafixe.fon", "vgasyse.fon",
2207       "couree.fon", "serifee.fon", "smallee.fon", "sserifee.fon",
2208       "Tahoma","Times New Roman", /* FIXME unverified */
2209       "Fixedsys,238", "System,238",
2210       "Courier New,238", "MS Serif,238", "Small Fonts,238",
2211       "MS Sans Serif,238", "MS Sans Serif,238", "MS Serif,238",
2212       { "Arial CE,0", "Arial,238" },
2213       { "Courier New CE,0", "Courier New,238" },
2214       { "Times New Roman CE,0", "Times New Roman,238" }
2215     },
2216     /* Cyrillic */
2217     { 1251, 866, "vga866.fon", "vgafixr.fon", "vgasysr.fon",
2218       "courer.fon", "serifer.fon", "smaller.fon", "sserifer.fon",
2219       "Tahoma","Times New Roman", /* FIXME unverified */
2220       "Fixedsys,204", "System,204",
2221       "Courier New,204", "MS Serif,204", "Small Fonts,204",
2222       "MS Sans Serif,204", "MS Sans Serif,204", "MS Serif,204",
2223       { "Arial Cyr,0", "Arial,204" },
2224       { "Courier New Cyr,0", "Courier New,204" },
2225       { "Times New Roman Cyr,0", "Times New Roman,204" }
2226     },
2227     /* Greek */
2228     { 1253, 737, "vga869.fon", "vgafixg.fon", "vgasysg.fon",
2229       "coureg.fon", "serifeg.fon", "smalleg.fon", "sserifeg.fon",
2230       "Tahoma","Times New Roman", /* FIXME unverified */
2231       "Fixedsys,161", "System,161",
2232       "Courier New,161", "MS Serif,161", "Small Fonts,161",
2233       "MS Sans Serif,161", "MS Sans Serif,161", "MS Serif,161",
2234       { "Arial Greek,0", "Arial,161" },
2235       { "Courier New Greek,0", "Courier New,161" },
2236       { "Times New Roman Greek,0", "Times New Roman,161" }
2237     },
2238     /* Turkish */
2239     { 1254, 857, "vga857.fon", "vgafixt.fon", "vgasyst.fon",
2240       "couret.fon", "serifet.fon", "smallet.fon", "sserifet.fon",
2241       "Tahoma","Times New Roman", /* FIXME unverified */
2242       "Fixedsys,162", "System,162",
2243       "Courier New,162", "MS Serif,162", "Small Fonts,162",
2244       "MS Sans Serif,162", "MS Sans Serif,162", "MS Serif,162",
2245       { "Arial Tur,0", "Arial,162" },
2246       { "Courier New Tur,0", "Courier New,162" },
2247       { "Times New Roman Tur,0", "Times New Roman,162" }
2248     },
2249     /* Hebrew */
2250     { 1255, 862, "vgaoem.fon", "vgaf1255.fon", "vgas1255.fon",
2251       "coue1255.fon", "sere1255.fon", "smae1255.fon", "ssee1255.fon",
2252       "Tahoma","Times New Roman", /* FIXME unverified */
2253       "Fixedsys,177", "System,177",
2254       "Courier New,177", "MS Serif,177", "Small Fonts,177",
2255       "MS Sans Serif,177", "MS Sans Serif,177", "MS Serif,177",
2256       { 0 }, { 0 }, { 0 }
2257     },
2258     /* Arabic */
2259     { 1256, 720, "vgaoem.fon", "vgaf1256.fon", "vgas1256.fon",
2260       "coue1256.fon", "sere1256.fon", "smae1256.fon", "ssee1256.fon",
2261       "Tahoma","Times New Roman", /* FIXME unverified */
2262       "Fixedsys,178", "System,178",
2263       "Courier New,178", "MS Serif,178", "Small Fonts,178",
2264       "MS Sans Serif,178", "MS Sans Serif,178", "MS Serif,178",
2265       { 0 }, { 0 }, { 0 }
2266     },
2267     /* Baltic */
2268     { 1257, 775, "vga775.fon", "vgaf1257.fon", "vgas1257.fon",
2269       "coue1257.fon", "sere1257.fon", "smae1257.fon", "ssee1257.fon",
2270       "Tahoma","Times New Roman", /* FIXME unverified */
2271       "Fixedsys,186", "System,186",
2272       "Courier New,186", "MS Serif,186", "Small Fonts,186",
2273       "MS Sans Serif,186", "MS Sans Serif,186", "MS Serif,186",
2274       { "Arial Baltic,0", "Arial,186" },
2275       { "Courier New Baltic,0", "Courier New,186" },
2276       { "Times New Roman Baltic,0", "Times New Roman,186" }
2277     },
2278     /* Vietnamese */
2279     { 1258, 1258, "vga850.fon", "vgafix.fon", "vgasys.fon",
2280       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2281       "Tahoma","Times New Roman", /* FIXME unverified */
2282       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2283       { 0 }, { 0 }, { 0 }
2284     },
2285     /* Thai */
2286     { 874, 874, "vga850.fon", "vgaf874.fon", "vgas874.fon",
2287       "coure.fon", "serife.fon", "smalle.fon", "ssee874.fon",
2288       "Tahoma","Times New Roman", /* FIXME unverified */
2289       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2290       { 0 }, { 0 }, { 0 }
2291     },
2292     /* Japanese */
2293     { 932, 932, "vga932.fon", "jvgafix.fon", "jvgasys.fon",
2294       "coure.fon", "serife.fon", "jsmalle.fon", "sserife.fon",
2295       "MS UI Gothic","MS Serif",
2296       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2297       { 0 }, { 0 }, { 0 }
2298     },
2299     /* Chinese Simplified */
2300     { 936, 936, "vga936.fon", "svgafix.fon", "svgasys.fon",
2301       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2302       "SimSun", "NSimSun",
2303       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2304       { 0 }, { 0 }, { 0 }
2305     },
2306     /* Korean */
2307     { 949, 949, "vga949.fon", "hvgafix.fon", "hvgasys.fon",
2308       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2309       "Gulim",  "Batang",
2310       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2311       { 0 }, { 0 }, { 0 }
2312     },
2313     /* Chinese Traditional */
2314     { 950, 950, "vga950.fon", "cvgafix.fon", "cvgasys.fon",
2315       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2316       "PMingLiU",  "MingLiU",
2317       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2318       { 0 }, { 0 }, { 0 }
2319     }
2320 };
2321 
2322 static const WCHAR *font_links_list[] =
2323 {
2324     Lucida_Sans_Unicode,
2325     Microsoft_Sans_Serif,
2326     Tahoma
2327 };
2328 
2329 static const struct font_links_defaults_list
2330 {
2331     /* Keyed off substitution for "MS Shell Dlg" */
2332     const WCHAR *shelldlg;
2333     /* Maximum of four substitutes, plus terminating NULL pointer */
2334     const WCHAR *substitutes[5];
2335 } font_links_defaults_list[] =
2336 {
2337     /* Non East-Asian */
2338     { Tahoma, /* FIXME unverified ordering */
2339       { MS_UI_Gothic, SimSun, Gulim, PMingLiU, NULL }
2340     },
2341     /* Below lists are courtesy of
2342      * http://blogs.msdn.com/michkap/archive/2005/06/18/430507.aspx
2343      */
2344     /* Japanese */
2345     { MS_UI_Gothic,
2346       { MS_UI_Gothic, PMingLiU, SimSun, Gulim, NULL }
2347     },
2348     /* Chinese Simplified */
2349     { SimSun,
2350       { SimSun, PMingLiU, MS_UI_Gothic, Batang, NULL }
2351     },
2352     /* Korean */
2353     { Gulim,
2354       { Gulim, PMingLiU, MS_UI_Gothic, SimSun, NULL }
2355     },
2356     /* Chinese Traditional */
2357     { PMingLiU,
2358       { PMingLiU, SimSun, MS_UI_Gothic, Batang, NULL }
2359     }
2360 };
2361 
2362 static inline BOOL is_dbcs_ansi_cp(UINT ansi_cp)
2363 {
2364     return ( ansi_cp == 932       /* CP932 for Japanese */
2365             || ansi_cp == 936     /* CP936 for Chinese Simplified */
2366             || ansi_cp == 949     /* CP949 for Korean */
2367             || ansi_cp == 950 );  /* CP950 for Chinese Traditional */
2368 }
2369 
2370 static inline HKEY create_fonts_NT_registry_key(void)
2371 {
2372     HKEY hkey = 0;
2373 
2374     RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key, 0, NULL,
2375                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2376     return hkey;
2377 }
2378 
2379 static inline HKEY create_fonts_9x_registry_key(void)
2380 {
2381     HKEY hkey = 0;
2382 
2383     RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key, 0, NULL,
2384                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2385     return hkey;
2386 }
2387 
2388 static inline HKEY create_config_fonts_registry_key(void)
2389 {
2390     HKEY hkey = 0;
2391 
2392     RegCreateKeyExW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, 0, NULL,
2393                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2394     return hkey;
2395 }
2396 
2397 static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl)
2398 {
2399     RegSetValueExA(hkey, "Courier", 0, REG_SZ, (const BYTE *)fl->courier, strlen(fl->courier)+1);
2400     RegSetValueExA(hkey, "MS Serif", 0, REG_SZ, (const BYTE *)fl->serif, strlen(fl->serif)+1);
2401     RegSetValueExA(hkey, "MS Sans Serif", 0, REG_SZ, (const BYTE *)fl->sserif, strlen(fl->sserif)+1);
2402     RegSetValueExA(hkey, "Small Fonts", 0, REG_SZ, (const BYTE *)fl->small, strlen(fl->small)+1);
2403 }
2404 
2405 static void set_value_key(HKEY hkey, const char *name, const char *value)
2406 {
2407     if (value)
2408         RegSetValueExA(hkey, name, 0, REG_SZ, (const BYTE *)value, strlen(value) + 1);
2409     else if (name)
2410         RegDeleteValueA(hkey, name);
2411 }
2412 
2413 static void update_font_info(void)
2414 {
2415     char buf[40], cpbuf[40];
2416     DWORD len, type;
2417     HKEY hkey = 0;
2418     UINT i, ansi_cp = 0, oem_cp = 0;
2419     BOOL done = FALSE;
2420 
2421     if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL) != ERROR_SUCCESS)
2422         return;
2423 
2424     GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
2425                    (WCHAR *)&ansi_cp, sizeof(ansi_cp)/sizeof(WCHAR));
2426     GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTCODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
2427                    (WCHAR *)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR));
2428     sprintf( cpbuf, "%u,%u", ansi_cp, oem_cp );
2429 
2430     /* Setup Default_Fallback usage for DBCS ANSI codepages */
2431     if (is_dbcs_ansi_cp(ansi_cp))
2432         use_default_fallback = TRUE;
2433 
2434     len = sizeof(buf);
2435     if (RegQueryValueExA(hkey, "Codepages", 0, &type, (BYTE *)buf, &len) == ERROR_SUCCESS && type == REG_SZ)
2436     {
2437         if (!strcmp( buf, cpbuf ))  /* already set correctly */
2438         {
2439             RegCloseKey(hkey);
2440             return;
2441         }
2442         TRACE("updating registry, codepages changed %s -> %u,%u\n", buf, ansi_cp, oem_cp);
2443     }
2444     else TRACE("updating registry, codepages changed none -> %u,%u\n", ansi_cp, oem_cp);
2445 
2446     RegSetValueExA(hkey, "Codepages", 0, REG_SZ, (const BYTE *)cpbuf, strlen(cpbuf)+1);
2447     RegCloseKey(hkey);
2448 
2449     for (i = 0; i < sizeof(nls_update_font_list)/sizeof(nls_update_font_list[0]); i++)
2450     {
2451         HKEY hkey;
2452 
2453         if (nls_update_font_list[i].ansi_cp == ansi_cp &&
2454             nls_update_font_list[i].oem_cp == oem_cp)
2455         {
2456             hkey = create_config_fonts_registry_key();
2457             RegSetValueExA(hkey, "OEMFONT.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].oem, strlen(nls_update_font_list[i].oem)+1);
2458             RegSetValueExA(hkey, "FIXEDFON.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].fixed, strlen(nls_update_font_list[i].fixed)+1);
2459             RegSetValueExA(hkey, "FONTS.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].system, strlen(nls_update_font_list[i].system)+1);
2460             RegCloseKey(hkey);
2461 
2462             hkey = create_fonts_NT_registry_key();
2463             add_font_list(hkey, &nls_update_font_list[i]);
2464             RegCloseKey(hkey);
2465 
2466             hkey = create_fonts_9x_registry_key();
2467             add_font_list(hkey, &nls_update_font_list[i]);
2468             RegCloseKey(hkey);
2469 
2470             if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
2471             {
2472                 RegSetValueExA(hkey, "MS Shell Dlg", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].shelldlg,
2473                                strlen(nls_update_font_list[i].shelldlg)+1);
2474                 RegSetValueExA(hkey, "Tms Rmn", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].tmsrmn,
2475                                strlen(nls_update_font_list[i].tmsrmn)+1);
2476 
2477                 set_value_key(hkey, "Fixedsys,0", nls_update_font_list[i].fixed_0);
2478                 set_value_key(hkey, "System,0", nls_update_font_list[i].system_0);
2479                 set_value_key(hkey, "Courier,0", nls_update_font_list[i].courier_0);
2480                 set_value_key(hkey, "MS Serif,0", nls_update_font_list[i].serif_0);
2481                 set_value_key(hkey, "Small Fonts,0", nls_update_font_list[i].small_0);
2482                 set_value_key(hkey, "MS Sans Serif,0", nls_update_font_list[i].sserif_0);
2483                 set_value_key(hkey, "Helv,0", nls_update_font_list[i].helv_0);
2484                 set_value_key(hkey, "Tms Rmn,0", nls_update_font_list[i].tmsrmn_0);
2485 
2486                 set_value_key(hkey, nls_update_font_list[i].arial_0.from, nls_update_font_list[i].arial_0.to);
2487                 set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, nls_update_font_list[i].courier_new_0.to);
2488                 set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, nls_update_font_list[i].times_new_roman_0.to);
2489 
2490                 RegCloseKey(hkey);
2491             }
2492             done = TRUE;
2493         }
2494         else
2495         {
2496             /* Delete the FontSubstitutes from other locales */
2497             if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
2498             {
2499                 set_value_key(hkey, nls_update_font_list[i].arial_0.from, NULL);
2500                 set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, NULL);
2501                 set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, NULL);
2502                 RegCloseKey(hkey);
2503             }
2504         }
2505     }
2506     if (!done)
2507         FIXME("there is no font defaults for codepages %u,%u\n", ansi_cp, oem_cp);
2508 
2509     /* Clear out system links */
2510     RegDeleteKeyW(HKEY_LOCAL_MACHINE, system_link);
2511 }
2512 
2513 static void populate_system_links(HKEY hkey, const WCHAR *name, const WCHAR *const *values)
2514 {
2515     const WCHAR *value;
2516     int i;
2517     FontSubst *psub;
2518     Family *family;
2519     Face *face;
2520     const char *file;
2521     WCHAR *fileW;
2522     int fileLen;
2523     WCHAR buff[MAX_PATH];
2524     WCHAR *data;
2525     int entryLen;
2526 
2527     static const WCHAR comma[] = {',',0};
2528 
2529     RegDeleteValueW(hkey, name);
2530     if (values)
2531     {
2532         data = buff;
2533         data[0] = '\0';
2534         for (i = 0; values[i] != NULL; i++)
2535         {
2536             value = values[i];
2537             if (!strcmpiW(name,value))
2538                 continue;
2539             psub = get_font_subst(&font_subst_list, value, -1);
2540             if(psub)
2541                 value = psub->to.name;
2542             family = find_family_from_name(value);
2543             if (!family)
2544                 continue;
2545             file = NULL;
2546             /* Use first extant filename for this Family */
2547             LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
2548             {
2549                 if (!face->file)
2550                     continue;
2551                 file = strrchr(face->file, '/');
2552                 if (!file)
2553                     file = face->file;
2554                 else
2555                     file++;
2556                 break;
2557             }
2558             if (!file)
2559                 continue;
2560             fileLen = MultiByteToWideChar(CP_UNIXCP, 0, file, -1, NULL, 0);
2561             fileW = HeapAlloc(GetProcessHeap(), 0, fileLen * sizeof(WCHAR));
2562             MultiByteToWideChar(CP_UNIXCP, 0, file, -1, fileW, fileLen);
2563             entryLen = strlenW(fileW) + 1 + strlenW(value) + 1;
2564             if (sizeof(buff)-(data-buff) < entryLen + 1)
2565             {
2566                 WARN("creating SystemLink for %s, ran out of buffer space\n", debugstr_w(name));
2567                 HeapFree(GetProcessHeap(), 0, fileW);
2568                 break;
2569             }
2570             strcpyW(data, fileW);
2571             strcatW(data, comma);
2572             strcatW(data, value);
2573             data += entryLen;
2574             TRACE("added SystemLink for %s to %s in %s\n", debugstr_w(name), debugstr_w(value),debugstr_w(fileW));
2575             HeapFree(GetProcessHeap(), 0, fileW);
2576         }
2577         if (data != buff)
2578         {
2579             *data='\0';
2580             data++;
2581             RegSetValueExW(hkey, name, 0, REG_MULTI_SZ, (BYTE*)buff, (data-buff) * sizeof(WCHAR));
2582         } else
2583             TRACE("no SystemLink fonts found for %s\n", debugstr_w(name));
2584     } else
2585         TRACE("removed SystemLink for %s\n", debugstr_w(name));
2586 }
2587 
2588 static void update_system_links(void)
2589 {
2590     HKEY hkey = 0;
2591     UINT i, j;
2592     BOOL done = FALSE;
2593     DWORD disposition;
2594     FontSubst *psub;
2595 
2596     static const WCHAR MS_Shell_Dlg[] = {'M','S',' ','S','h','e','l','l',' ','D','l','g',0};
2597 
2598     if (!RegCreateKeyExW(HKEY_LOCAL_MACHINE, system_link, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, &disposition))
2599     {
2600         if (disposition == REG_OPENED_EXISTING_KEY)
2601         {
2602             TRACE("SystemLink key already exists, doing nothing\n");
2603             RegCloseKey(hkey);
2604             return;
2605         }
2606 
2607         psub = get_font_subst(&font_subst_list, MS_Shell_Dlg, -1);
2608         if (!psub) {
2609             WARN("could not find FontSubstitute for MS Shell Dlg\n");
2610             RegCloseKey(hkey);
2611             return;
2612         }
2613 
2614         for (i = 0; i < sizeof(font_links_defaults_list)/sizeof(font_links_defaults_list[0]); i++)
2615         {
2616             if (!strcmpiW(font_links_defaults_list[i].shelldlg, psub->to.name))
2617             {
2618                 for (j = 0; j < sizeof(font_links_list)/sizeof(font_links_list[0]); j++)
2619                     populate_system_links(hkey, font_links_list[j], font_links_defaults_list[i].substitutes);
2620 
2621                 if (!strcmpiW(psub->to.name, font_links_defaults_list[i].substitutes[0]))
2622                     populate_system_links(hkey, psub->to.name, font_links_defaults_list[i].substitutes);
2623                 done = TRUE;
2624             }
2625             else if (strcmpiW(psub->to.name, font_links_defaults_list[i].substitutes[0]))
2626             {
2627                 populate_system_links(hkey, font_links_defaults_list[i].substitutes[0], NULL);
2628             }
2629         }
2630         RegCloseKey(hkey);
2631         if (!done)
2632             WARN("there is no SystemLink default list for MS Shell Dlg %s\n", debugstr_w(psub->to.name));
2633     } else
2634         WARN("failed to create SystemLink key\n");
2635 }
2636 
2637 
2638 static BOOL init_freetype(void)
2639 {
2640     ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0);
2641     if(!ft_handle) {
2642         WINE_MESSAGE(
2643       "Wine cannot find the FreeType font library.  To enable Wine to\n"
2644       "use TrueType fonts please install a version of FreeType greater than\n"
2645       "or equal to 2.0.5.\n"
2646       "http://www.freetype.org\n");
2647         return FALSE;
2648     }
2649 
2650 #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;}
2651 
2652     LOAD_FUNCPTR(FT_Vector_Unit)
2653     LOAD_FUNCPTR(FT_Done_Face)
2654     LOAD_FUNCPTR(FT_Get_Char_Index)
2655     LOAD_FUNCPTR(FT_Get_Module)
2656     LOAD_FUNCPTR(FT_Get_Sfnt_Name)
2657     LOAD_FUNCPTR(FT_Get_Sfnt_Name_Count)
2658     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
2659     LOAD_FUNCPTR(FT_Init_FreeType)
2660     LOAD_FUNCPTR(FT_Load_Glyph)
2661     LOAD_FUNCPTR(FT_Matrix_Multiply)
2662 #ifndef FT_MULFIX_INLINED
2663     LOAD_FUNCPTR(FT_MulFix)
2664 #endif
2665     LOAD_FUNCPTR(FT_New_Face)
2666     LOAD_FUNCPTR(FT_New_Memory_Face)
2667     LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
2668     LOAD_FUNCPTR(FT_Outline_Transform)
2669     LOAD_FUNCPTR(FT_Outline_Translate)
2670     LOAD_FUNCPTR(FT_Select_Charmap)
2671     LOAD_FUNCPTR(FT_Set_Charmap)
2672     LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
2673     LOAD_FUNCPTR(FT_Vector_Transform)
2674     LOAD_FUNCPTR(FT_Render_Glyph)
2675 
2676 #undef LOAD_FUNCPTR
2677     /* Don't warn if these ones are missing */
2678     pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0);
2679     pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0);
2680     pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0);
2681     pFT_Get_Next_Char = wine_dlsym(ft_handle, "FT_Get_Next_Char", NULL, 0);
2682     pFT_Get_TrueType_Engine_Type = wine_dlsym(ft_handle, "FT_Get_TrueType_Engine_Type", NULL, 0);
2683 #ifdef HAVE_FREETYPE_FTLCDFIL_H
2684     pFT_Library_SetLcdFilter = wine_dlsym(ft_handle, "FT_Library_SetLcdFilter", NULL, 0);
2685 #endif
2686 #ifdef HAVE_FREETYPE_FTWINFNT_H
2687     pFT_Get_WinFNT_Header = wine_dlsym(ft_handle, "FT_Get_WinFNT_Header", NULL, 0);
2688 #endif
2689       if(!wine_dlsym(ft_handle, "FT_Get_Postscript_Name", NULL, 0) &&
2690          !wine_dlsym(ft_handle, "FT_Sqrt64", NULL, 0)) {
2691         /* try to avoid 2.0.4: >= 2.0.5 has FT_Get_Postscript_Name and
2692            <= 2.0.3 has FT_Sqrt64 */
2693           goto sym_not_found;
2694       }
2695 
2696     if(pFT_Init_FreeType(&library) != 0) {
2697         ERR("Can't init FreeType library\n");
2698         wine_dlclose(ft_handle, NULL, 0);
2699         ft_handle = NULL;
2700         return FALSE;
2701     }
2702     FT_Version.major = FT_Version.minor = FT_Version.patch = -1;
2703     if (pFT_Library_Version)
2704         pFT_Library_Version(library,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
2705 
2706     if (FT_Version.major<=0)
2707     {
2708         FT_Version.major=2;
2709         FT_Version.minor=0;
2710         FT_Version.patch=5;
2711     }
2712     TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
2713     FT_SimpleVersion = ((FT_Version.major << 16) & 0xff0000) |
2714                        ((FT_Version.minor <<  8) & 0x00ff00) |
2715                        ((FT_Version.patch      ) & 0x0000ff);
2716 
2717     return TRUE;
2718 
2719 sym_not_found:
2720     WINE_MESSAGE(
2721       "Wine cannot find certain functions that it needs inside the FreeType\n"
2722       "font library.  To enable Wine to use TrueType fonts please upgrade\n"
2723       "FreeType to at least version 2.0.5.\n"
2724       "http://www.freetype.org\n");
2725     wine_dlclose(ft_handle, NULL, 0);
2726     ft_handle = NULL;
2727     return FALSE;
2728 }
2729 
2730 /*************************************************************
2731  *    WineEngInit
2732  *
2733  * Initialize FreeType library and create a list of available faces
2734  */
2735 BOOL WineEngInit(void)
2736 {
2737     static const WCHAR dot_fonW[] = {'.','f','o','n','\0'};
2738     static const WCHAR pathW[] = {'P','a','t','h',0};
2739     HKEY hkey;
2740     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
2741     WCHAR windowsdir[MAX_PATH];
2742     char *unixname;
2743     HANDLE font_mutex;
2744     const char *data_dir;
2745 
2746     TRACE("\n");
2747 
2748     /* update locale dependent font info in registry */
2749     update_font_info();
2750 
2751     if(!init_freetype()) return FALSE;
2752 
2753     if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) {
2754         ERR("Failed to create font mutex\n");
2755         return FALSE;
2756     }
2757     WaitForSingleObject(font_mutex, INFINITE);
2758 
2759     delete_external_font_keys();
2760 
2761     /* load the system bitmap fonts */
2762     load_system_fonts();
2763 
2764     /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
2765     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
2766     strcatW(windowsdir, fontsW);
2767     if((unixname = wine_get_unix_file_name(windowsdir)))
2768     {
2769         ReadFontDir(unixname, FALSE);
2770         HeapFree(GetProcessHeap(), 0, unixname);
2771     }
2772 
2773     /* load the system truetype fonts */
2774     data_dir = wine_get_data_dir();
2775     if (!data_dir) data_dir = wine_get_build_dir();
2776     if (data_dir && (unixname = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + sizeof("/fonts/")))) {
2777         strcpy(unixname, data_dir);
2778         strcat(unixname, "/fonts/");
2779         ReadFontDir(unixname, TRUE);
2780         HeapFree(GetProcessHeap(), 0, unixname);
2781     }
2782 
2783     /* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
2784        for any fonts not installed in %WINDOWSDIR%\Fonts.  They will have their
2785        full path as the entry.  Also look for any .fon fonts, since ReadFontDir
2786        will skip these. */
2787     if(RegOpenKeyW(HKEY_LOCAL_MACHINE,
2788                    is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
2789                    &hkey) == ERROR_SUCCESS) {
2790         LPWSTR data, valueW;
2791         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2792                          &valuelen, &datalen, NULL, NULL);
2793 
2794         valuelen++; /* returned value doesn't include room for '\0' */
2795         valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
2796         data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
2797         if (valueW && data)
2798         {
2799             dlen = datalen * sizeof(WCHAR);
2800             vlen = valuelen;
2801             while(RegEnumValueW(hkey, i++, valueW, &vlen, NULL, &type, (LPBYTE)data,
2802                                 &dlen) == ERROR_SUCCESS) {
2803                 if(data[0] && (data[1] == ':'))
2804                 {
2805                     if((unixname = wine_get_unix_file_name(data)))
2806                     {
2807                         AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
2808                         HeapFree(GetProcessHeap(), 0, unixname);
2809                     }
2810                 }
2811                 else if(dlen / 2 >= 6 && !strcmpiW(data + dlen / 2 - 5, dot_fonW))
2812                 {
2813                     WCHAR pathW[MAX_PATH];
2814                     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
2815                     BOOL added = FALSE;
2816 
2817                     sprintfW(pathW, fmtW, windowsdir, data);
2818                     if((unixname = wine_get_unix_file_name(pathW)))
2819                     {
2820                         added = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
2821                         HeapFree(GetProcessHeap(), 0, unixname);
2822                     }
2823                     if (!added)
2824                         load_font_from_data_dir(data);
2825                 }
2826                 /* reset dlen and vlen */
2827                 dlen = datalen;
2828                 vlen = valuelen;
2829             }
2830         }
2831         HeapFree(GetProcessHeap(), 0, data);
2832         HeapFree(GetProcessHeap(), 0, valueW);
2833         RegCloseKey(hkey);
2834     }
2835 
2836     load_fontconfig_fonts();
2837 
2838     /* then look in any directories that we've specified in the config file */
2839     /* @@ Wine registry key: HKCU\Software\Wine\Fonts */
2840     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", &hkey) == ERROR_SUCCESS)
2841     {
2842         DWORD len;
2843         LPWSTR valueW;
2844         LPSTR valueA, ptr;
2845 
2846         if (RegQueryValueExW( hkey, pathW, NULL, NULL, NULL, &len ) == ERROR_SUCCESS)
2847         {
2848             len += sizeof(WCHAR);
2849             valueW = HeapAlloc( GetProcessHeap(), 0, len );
2850             if (RegQueryValueExW( hkey, pathW, NULL, NULL, (LPBYTE)valueW, &len ) == ERROR_SUCCESS)
2851             {
2852                 len = WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, NULL, 0, NULL, NULL );
2853                 valueA = HeapAlloc( GetProcessHeap(), 0, len );
2854                 WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, valueA, len, NULL, NULL );
2855                 TRACE( "got font path %s\n", debugstr_a(valueA) );
2856                 ptr = valueA;
2857                 while (ptr)
2858                 {
2859                     LPSTR next = strchr( ptr, ':' );
2860                     if (next) *next++ = 0;
2861                     ReadFontDir( ptr, TRUE );
2862                     ptr = next;
2863                 }
2864                 HeapFree( GetProcessHeap(), 0, valueA );
2865             }
2866             HeapFree( GetProcessHeap(), 0, valueW );
2867         }
2868         RegCloseKey(hkey);
2869     }
2870 
2871     DumpFontList();
2872     LoadSubstList();
2873     DumpSubstList();
2874     LoadReplaceList();
2875     update_reg_entries();
2876 
2877     update_system_links();
2878     init_system_links();
2879     
2880     ReleaseMutex(font_mutex);
2881     return TRUE;
2882 }
2883 
2884 
2885 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
2886 {
2887     TT_OS2 *pOS2;
2888     TT_HoriHeader *pHori;
2889 
2890     LONG ppem;
2891 
2892     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
2893     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
2894 
2895     if(height == 0) height = 16;
2896 
2897     /* Calc. height of EM square:
2898      *
2899      * For +ve lfHeight we have
2900      * lfHeight = (winAscent + winDescent) * ppem / units_per_em
2901      * Re-arranging gives:
2902      * ppem = units_per_em * lfheight / (winAscent + winDescent)
2903      *
2904      * For -ve lfHeight we have
2905      * |lfHeight| = ppem
2906      * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
2907      * with il = winAscent + winDescent - units_per_em]
2908      *
2909      */
2910 
2911     if(height > 0) {
2912         if(pOS2->usWinAscent + pOS2->usWinDescent == 0)
2913             ppem = MulDiv(ft_face->units_per_EM, height,
2914                           pHori->Ascender - pHori->Descender);
2915         else
2916             ppem = MulDiv(ft_face->units_per_EM, height,
2917                           pOS2->usWinAscent + pOS2->usWinDescent);
2918     }
2919     else
2920         ppem = -height;
2921 
2922     return ppem;
2923 }
2924 
2925 static struct font_mapping *map_font_file( const char *name )
2926 {
2927     struct font_mapping *mapping;
2928     struct stat st;
2929     int fd;
2930 
2931     if ((fd = open( name, O_RDONLY )) == -1) return NULL;
2932     if (fstat( fd, &st ) == -1) goto error;
2933 
2934     LIST_FOR_EACH_ENTRY( mapping, &mappings_list, struct font_mapping, entry )
2935     {
2936         if (mapping->dev == st.st_dev && mapping->ino == st.st_ino)
2937         {
2938             mapping->refcount++;
2939             close( fd );
2940             return mapping;
2941         }
2942     }
2943     if (!(mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(*mapping) )))
2944         goto error;
2945 
2946     mapping->data = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
2947     close( fd );
2948 
2949     if (mapping->data == MAP_FAILED)
2950     {
2951         HeapFree( GetProcessHeap(), 0, mapping );
2952         return NULL;
2953     }
2954     mapping->refcount = 1;
2955     mapping->dev = st.st_dev;
2956     mapping->ino = st.st_ino;
2957     mapping->size = st.st_size;
2958     list_add_tail( &mappings_list, &mapping->entry );
2959     return mapping;
2960 
2961 error:
2962     close( fd );
2963     return NULL;
2964 }
2965 
2966 static void unmap_font_file( struct font_mapping *mapping )
2967 {
2968     if (!--mapping->refcount)
2969     {
2970         list_remove( &mapping->entry );
2971         munmap( mapping->data, mapping->size );
2972         HeapFree( GetProcessHeap(), 0, mapping );
2973     }
2974 }
2975 
2976 static LONG load_VDMX(GdiFont*, LONG);
2977 
2978 static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height)
2979 {
2980     FT_Error err;
2981     FT_Face ft_face;
2982     void *data_ptr;
2983     DWORD data_size;
2984 
2985     TRACE("%s/%p, %ld, %d x %d\n", debugstr_a(face->file), face->font_data_ptr, face->face_index, width, height);
2986 
2987     if (face->file)
2988     {
2989         if (!(font->mapping = map_font_file( face->file )))
2990         {
2991             WARN("failed to map %s\n", debugstr_a(face->file));
2992             return 0;
2993         }
2994         data_ptr = font->mapping->data;
2995         data_size = font->mapping->size;
2996     }
2997     else
2998     {
2999         data_ptr = face->font_data_ptr;
3000         data_size = face->font_data_size;
3001     }
3002 
3003     err = pFT_New_Memory_Face(library, data_ptr, data_size, face->face_index, &ft_face);
3004     if(err) {
3005         ERR("FT_New_Face rets %d\n", err);
3006         return 0;
3007     }
3008 
3009     /* set it here, as load_VDMX needs it */
3010     font->ft_face = ft_face;
3011 
3012     if(FT_IS_SCALABLE(ft_face)) {
3013         /* load the VDMX table if we have one */
3014         font->ppem = load_VDMX(font, height);
3015         if(font->ppem == 0)
3016             font->ppem = calc_ppem_for_height(ft_face, height);
3017         TRACE("height %d => ppem %d\n", height, font->ppem);
3018 
3019         if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0)
3020             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", 0, font->ppem, err);
3021     } else {
3022         font->ppem = height;
3023         if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
3024             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", width, height, err);
3025     }
3026     return ft_face;
3027 }
3028 
3029 
3030 static int get_nearest_charset(Face *face, int *cp)
3031 {
3032   /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
3033      a single face with the requested charset.  The idea is to check if
3034      the selected font supports the current ANSI codepage, if it does
3035      return the corresponding charset, else return the first charset */
3036 
3037     CHARSETINFO csi;
3038     int acp = GetACP(), i;
3039     DWORD fs0;
3040 
3041     *cp = acp;
3042     if(TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE))
3043         if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
3044             return csi.ciCharset;
3045 
3046     for(i = 0; i < 32; i++) {
3047         fs0 = 1L << i;
3048         if(face->fs.fsCsb[0] & fs0) {
3049             if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG)) {
3050                 *cp = csi.ciACP;
3051                 return csi.ciCharset;
3052             }
3053             else
3054                 FIXME("TCI failing on %x\n", fs0);
3055         }
3056     }
3057 
3058     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08x file = %s\n",
3059           face->fs.fsCsb[0], face->file);
3060     *cp = acp;
3061     return DEFAULT_CHARSET;
3062 }
3063 
3064 static GdiFont *alloc_font(void)
3065 {
3066     GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
3067     ret->gmsize = 1;
3068     ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM*));
3069     ret->gm[0] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
3070     ret->potm = NULL;
3071     ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
3072     ret->total_kern_pairs = (DWORD)-1;
3073     ret->kern_pairs = NULL;
3074     list_init(&ret->hfontlist);
3075     list_init(&ret->child_fonts);
3076     return ret;
3077 }
3078 
3079 static void free_font(GdiFont *font)
3080 {
3081     struct list *cursor, *cursor2;
3082     DWORD i;
3083 
3084     LIST_FOR_EACH_SAFE(cursor, cursor2, &font->child_fonts)
3085     {
3086         CHILD_FONT *child = LIST_ENTRY(cursor, CHILD_FONT, entry);
3087         struct list *first_hfont;
3088         HFONTLIST *hfontlist;
3089         list_remove(cursor);
3090         if(child->font)
3091         {
3092             first_hfont = list_head(&child->font->hfontlist);
3093             hfontlist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
3094             DeleteObject(hfontlist->hfont);
3095             HeapFree(GetProcessHeap(), 0, hfontlist);
3096             free_font(child->font);
3097         }
3098         HeapFree(GetProcessHeap(), 0, child);
3099     }
3100 
3101     if (font->ft_face) pFT_Done_Face(font->ft_face);
3102     if (font->mapping) unmap_font_file( font->mapping );
3103     HeapFree(GetProcessHeap(), 0, font->kern_pairs);
3104     HeapFree(GetProcessHeap(), 0, font->potm);
3105     HeapFree(GetProcessHeap(), 0, font->name);
3106     for (i = 0; i < font->gmsize; i++)
3107         HeapFree(GetProcessHeap(),0,font->gm[i]);
3108     HeapFree(GetProcessHeap(), 0, font->gm);
3109     HeapFree(GetProcessHeap(), 0, font->GSUB_Table);
3110     HeapFree(GetProcessHeap(), 0, font);
3111 }
3112 
3113 
3114 /*************************************************************
3115  * load_VDMX
3116  *
3117  * load the vdmx entry for the specified height
3118  */
3119 
3120 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
3121           ( ( (FT_ULong)_x4 << 24 ) |     \
3122             ( (FT_ULong)_x3 << 16 ) |     \
3123             ( (FT_ULong)_x2 <<  8 ) |     \
3124               (FT_ULong)_x1         )
3125 
3126 #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X')
3127 
3128 typedef struct {
3129     BYTE bCharSet;
3130     BYTE xRatio;
3131     BYTE yStartRatio;
3132     BYTE yEndRatio;
3133 } Ratios;
3134 
3135 typedef struct {
3136     WORD recs;
3137     BYTE startsz;
3138     BYTE endsz;
3139 } VDMX_group;
3140 
3141 static LONG load_VDMX(GdiFont *font, LONG height)
3142 {
3143     WORD hdr[3], tmp;
3144     VDMX_group group;
3145     BYTE devXRatio, devYRatio;
3146     USHORT numRecs, numRatios;
3147     DWORD result, offset = -1;
3148     LONG ppem = 0;
3149     int i;
3150 
3151     result = WineEngGetFontData(font, MS_VDMX_TAG, 0, hdr, 6);
3152 
3153     if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
3154         return ppem;
3155 
3156     /* FIXME: need the real device aspect ratio */
3157     devXRatio = 1;
3158     devYRatio = 1;
3159 
3160     numRecs = GET_BE_WORD(hdr[1]);
3161     numRatios = GET_BE_WORD(hdr[2]);
3162 
3163     TRACE("numRecs = %d numRatios = %d\n", numRecs, numRatios);
3164     for(i = 0; i < numRatios; i++) {
3165         Ratios ratio;
3166 
3167         offset = (3 * 2) + (i * sizeof(Ratios));
3168         WineEngGetFontData(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
3169         offset = -1;
3170 
3171         TRACE("Ratios[%d] %d  %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
3172 
3173         if((ratio.xRatio == 0 &&
3174             ratio.yStartRatio == 0 &&
3175             ratio.yEndRatio == 0) ||
3176            (devXRatio == ratio.xRatio &&
3177             devYRatio >= ratio.yStartRatio &&
3178             devYRatio <= ratio.yEndRatio))
3179             {
3180                 offset = (3 * 2) + (numRatios * 4) + (i * 2);
3181                 WineEngGetFontData(font, MS_VDMX_TAG, offset, &tmp, 2);
3182                 offset = GET_BE_WORD(tmp);
3183                 break;
3184             }
3185     }
3186 
3187     if(offset == -1) {
3188         FIXME("No suitable ratio found\n");
3189         return ppem;
3190     }
3191 
3192     if(WineEngGetFontData(font, MS_VDMX_TAG, offset, &group, 4) != GDI_ERROR) {
3193         USHORT recs;
3194         BYTE startsz, endsz;
3195         WORD *vTable;
3196 
3197         recs = GET_BE_WORD(group.recs);
3198         startsz = group.startsz;
3199         endsz = group.endsz;
3200 
3201         TRACE("recs=%d  startsz=%d  endsz=%d\n", recs, startsz, endsz);
3202 
3203         vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6);
3204         result = WineEngGetFontData(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6);
3205         if(result == GDI_ERROR) {
3206             FIXME("Failed to retrieve vTable\n");
3207             goto end;
3208         }
3209 
3210         if(height > 0) {
3211             for(i = 0; i < recs; i++) {
3212                 SHORT yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
3213                 SHORT yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
3214                 ppem = GET_BE_WORD(vTable[i * 3]);
3215 
3216                 if(yMax + -yMin == height) {
3217                     font->yMax = yMax;
3218                     font->yMin = yMin;
3219                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
3220                     break;
3221                 }
3222                 if(yMax + -yMin > height) {
3223                     if(--i < 0) {
3224                         ppem = 0;
3225                         goto end; /* failed */
3226                     }
3227                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
3228                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
3229                     ppem = GET_BE_WORD(vTable[i * 3]);
3230                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
3231                     break;
3232                 }
3233             }
3234             if(!font->yMax) {
3235                 ppem = 0;
3236                 TRACE("ppem not found for height %d\n", height);
3237             }
3238         } else {
3239             ppem = -height;
3240             if(ppem < startsz || ppem > endsz)
3241                 goto end;
3242 
3243             for(i = 0; i < recs; i++) {
3244                 USHORT yPelHeight;
3245                 yPelHeight = GET_BE_WORD(vTable[i * 3]);
3246 
3247                 if(yPelHeight > ppem)
3248                     break; /* failed */
3249 
3250                 if(yPelHeight == ppem) {
3251                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
3252                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
3253                     TRACE("ppem %d found; yMax=%d  yMin=%d\n", ppem, font->yMax, font->yMin);
3254                     break;
3255                 }
3256             }
3257         }
3258         end:
3259         HeapFree(GetProcessHeap(), 0, vTable);
3260     }
3261 
3262     return ppem;
3263 }
3264 
3265 static BOOL fontcmp(const GdiFont *font, FONT_DESC *fd)
3266 {
3267     if(font->font_desc.hash != fd->hash) return TRUE;
3268     if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE;
3269     if(memcmp(&font->font_desc.lf, &fd->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
3270     if(!font->font_desc.can_use_bitmap != !fd->can_use_bitmap) return TRUE;
3271     return strcmpiW(font->font_desc.lf.lfFaceName, fd->lf.lfFaceName);
3272 }
3273 
3274 static void calc_hash(FONT_DESC *pfd)
3275 {
3276     DWORD hash = 0, *ptr, two_chars;
3277     WORD *pwc;
3278     unsigned int i;
3279 
3280     for(i = 0, ptr = (DWORD*)&pfd->matrix; i < sizeof(FMAT2)/sizeof(DWORD); i++, ptr++)
3281         hash ^= *ptr;
3282     for(i = 0, ptr = (DWORD*)&pfd->lf; i < 7; i++, ptr++)
3283         hash ^= *ptr;
3284     for(i = 0, ptr = (DWORD*)pfd->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
3285         two_chars = *ptr;
3286         pwc = (WCHAR *)&two_chars;
3287         if(!*pwc) break;
3288         *pwc = toupperW(*pwc);
3289         pwc++;
3290         *pwc = toupperW(*pwc);
3291         hash ^= two_chars;
3292         if(!*pwc) break;
3293     }
3294     hash ^= !pfd->can_use_bitmap;
3295     pfd->hash = hash;
3296     return;
3297 }
3298 
3299 static GdiFont *find_in_cache(HFONT hfont, const LOGFONTW *plf, const FMAT2 *pmat, BOOL can_use_bitmap)
3300 {
3301     GdiFont *ret;
3302     FONT_DESC fd;
3303     HFONTLIST *hflist;
3304     struct list *font_elem_ptr, *hfontlist_elem_ptr;
3305 
3306     fd.lf = *plf;
3307     fd.matrix = *pmat;
3308     fd.can_use_bitmap = can_use_bitmap;
3309     calc_hash(&fd);
3310 
3311     /* try the child list */
3312     LIST_FOR_EACH(font_elem_ptr, &child_font_list) {
3313         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3314         if(!fontcmp(ret, &fd)) {
3315             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
3316             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
3317                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3318                 if(hflist->hfont == hfont)
3319                     return ret;
3320             }
3321         }
3322     }
3323 
3324     /* try the in-use list */
3325     LIST_FOR_EACH(font_elem_ptr, &gdi_font_list) {
3326         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3327         if(!fontcmp(ret, &fd)) {
3328             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
3329             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
3330                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3331                 if(hflist->hfont == hfont)
3332                     return ret;
3333             }
3334             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3335             hflist->hfont = hfont;
3336             list_add_head(&ret->hfontlist, &hflist->entry);
3337             return ret;
3338         }
3339     }
3340  
3341     /* then the unused list */
3342     font_elem_ptr = list_head(&unused_gdi_font_list);
3343     while(font_elem_ptr) {
3344         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3345         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
3346         if(!fontcmp(ret, &fd)) {
3347             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
3348             assert(list_empty(&ret->hfontlist));
3349             TRACE("Found %p in unused list\n", ret);
3350             list_remove(&ret->entry);
3351             list_add_head(&gdi_font_list, &ret->entry);
3352             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3353             hflist->hfont = hfont;
3354             list_add_head(&ret->hfontlist, &hflist->entry);
3355             return ret;
3356         }
3357     }
3358     return NULL;
3359 }
3360 
3361 static void add_to_cache(GdiFont *font)
3362 {
3363     static DWORD cache_num = 1;
3364 
3365     font->cache_num = cache_num++;
3366     list_add_head(&gdi_font_list, &font->entry);
3367 }
3368 
3369 /*************************************************************
3370  * create_child_font_list
3371  */
3372 static BOOL create_child_font_list(GdiFont *font)
3373 {
3374     BOOL ret = FALSE;
3375     SYSTEM_LINKS *font_link;
3376     CHILD_FONT *font_link_entry, *new_child;
3377     FontSubst *psub;
3378     WCHAR* font_name;
3379 
3380     psub = get_font_subst(&font_subst_list, font->name, -1);
3381     font_name = psub ? psub->to.name : font->name;
3382     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3383     {
3384         if(!strcmpiW(font_link->font_name, font_name))
3385         {
3386             TRACE("found entry in system list\n");
3387             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3388             {
3389                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
3390                 new_child->face = font_link_entry->face;
3391                 new_child->font = NULL;
3392                 list_add_tail(&font->child_fonts, &new_child->entry);
3393                 TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
3394             }
3395             ret = TRUE;
3396             break;
3397         }
3398     }
3399     /*
3400      * if not SYMBOL or OEM then we also get all the fonts for Microsoft
3401      * Sans Serif.  This is how asian windows get default fallbacks for fonts
3402      */
3403     if (use_default_fallback && font->charset != SYMBOL_CHARSET &&
3404         font->charset != OEM_CHARSET &&
3405         strcmpiW(font_name,szDefaultFallbackLink) != 0)
3406         LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3407         {
3408             if(!strcmpiW(font_link->font_name,szDefaultFallbackLink))
3409             {
3410                 TRACE("found entry in default fallback list\n");
3411                 LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3412                 {
3413                     new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
3414                     new_child->face = font_link_entry->face;
3415                     new_child->font = NULL;
3416                     list_add_tail(&font->child_fonts, &new_child->entry);
3417                     TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
3418                 }
3419                 ret = TRUE;
3420                 break;
3421             }
3422         }
3423 
3424     return ret;
3425 }
3426 
3427 static BOOL select_charmap(FT_Face ft_face, FT_Encoding encoding)
3428 {
3429     FT_Error ft_err = FT_Err_Invalid_CharMap_Handle;
3430 
3431     if (pFT_Set_Charmap)
3432     {
3433         FT_Int i;
3434         FT_CharMap cmap0, cmap1, cmap2, cmap3, cmap_def;
3435 
3436         cmap0 = cmap1 = cmap2 = cmap3 = cmap_def = NULL;
3437 
3438         for (i = 0; i < ft_face->num_charmaps; i++)
3439         {
3440             if (ft_face->charmaps[i]->encoding == encoding)
3441             {
3442                 TRACE("found cmap with platform_id %u, encoding_id %u\n",
3443                        ft_face->charmaps[i]->platform_id, ft_face->charmaps[i]->encoding_id);
3444 
3445                 switch (ft_face->charmaps[i]->platform_id)
3446                 {
3447                     default:
3448                         cmap_def = ft_face->charmaps[i];
3449                         break;
3450                     case 0: /* Apple Unicode */
3451                         cmap0 = ft_face->charmaps[i];
3452                         break;
3453                     case 1: /* Macintosh */
3454                         cmap1 = ft_face->charmaps[i];
3455                         break;
3456                     case 2: /* ISO */
3457                         cmap2 = ft_face->charmaps[i];
3458                         break;
3459                     case 3: /* Microsoft */
3460                         cmap3 = ft_face->charmaps[i];
3461                         break;
3462                 }
3463             }
3464 
3465             if (cmap3) /* prefer Microsoft cmap table */
3466                 ft_err = pFT_Set_Charmap(ft_face, cmap3);
3467             else if (cmap1)
3468                 ft_err = pFT_Set_Charmap(ft_face, cmap1);
3469             else if (cmap2)
3470                 ft_err = pFT_Set_Charmap(ft_face, cmap2);
3471             else if (cmap0)
3472                 ft_err = pFT_Set_Charmap(ft_face, cmap0);
3473             else if (cmap_def)
3474                 ft_err = pFT_Set_Charmap(ft_face, cmap_def);
3475         }
3476         return ft_err == FT_Err_Ok;
3477     }
3478 
3479     return pFT_Select_Charmap(ft_face, encoding) == FT_Err_Ok;
3480 }
3481 
3482 /*************************************************************
3483  * WineEngCreateFontInstance
3484  *
3485  */
3486 GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont)
3487 {
3488     GdiFont *ret;
3489     Face *face, *best, *best_bitmap;
3490     Family *family, *last_resort_family;
3491     struct list *family_elem_ptr, *face_elem_ptr;
3492     INT height, width = 0;
3493     unsigned int score = 0, new_score;
3494     signed int diff = 0, newdiff;
3495     BOOL bd, it, can_use_bitmap;
3496     LOGFONTW lf;
3497     CHARSETINFO csi;
3498     HFONTLIST *hflist;
3499     FMAT2 dcmat;
3500     FontSubst *psub = NULL;
3501 
3502     if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
3503     lf.lfWidth = abs(lf.lfWidth);
3504 
3505     can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
3506 
3507     TRACE("%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n",
3508           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
3509           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
3510           lf.lfEscapement);
3511 
3512     if(dc->GraphicsMode == GM_ADVANCED)
3513         memcpy(&dcmat, &dc->xformWorld2Vport, sizeof(FMAT2));
3514     else
3515     {
3516         /* Windows 3.1 compatibility mode GM_COMPATIBLE has only limited
3517            font scaling abilities. */
3518         dcmat.eM11 = dcmat.eM22 = dc->vport2WorldValid ? fabs(dc->xformWorld2Vport.eM22) : 1.0;
3519         dcmat.eM21 = dcmat.eM12 = 0;
3520     }
3521 
3522     /* Try to avoid not necessary glyph transformations */
3523     if (dcmat.eM21 == 0.0 && dcmat.eM12 == 0.0 && dcmat.eM11 == dcmat.eM22)
3524     {
3525         lf.lfHeight *= fabs(dcmat.eM11);
3526         lf.lfWidth *= fabs(dcmat.eM11);
3527         dcmat.eM11 = dcmat.eM22 = 1.0;
3528     }
3529 
3530     TRACE("DC transform %f %f %f %f\n", dcmat.eM11, dcmat.eM12,
3531                                         dcmat.eM21, dcmat.eM22);
3532 
3533     GDI_CheckNotLock();
3534     EnterCriticalSection( &freetype_cs );
3535 
3536     /* check the cache first */
3537     if((ret = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap)) != NULL) {
3538         TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
3539         LeaveCriticalSection( &freetype_cs );
3540         return ret;
3541     }
3542 
3543     TRACE("not in cache\n");
3544     if(list_empty(&font_list)) /* No fonts installed */
3545     {
3546         TRACE("No fonts installed\n");
3547         LeaveCriticalSection( &freetype_cs );
3548         return NULL;
3549     }
3550     if(!have_installed_roman_font)
3551     {
3552         TRACE("No roman font installed\n");
3553         LeaveCriticalSection( &freetype_cs );
3554         return NULL;
3555     }
3556 
3557     ret = alloc_font();
3558 
3559     ret->font_desc.matrix = dcmat;
3560     ret->font_desc.lf = lf;
3561     ret->font_desc.can_use_bitmap = can_use_bitmap;
3562     calc_hash(&ret->font_desc);
3563     hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
3564     hflist->hfont = hfont;
3565     list_add_head(&ret->hfontlist, &hflist->entry);
3566 
3567     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
3568        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
3569        original value lfCharSet.  Note this is a special case for
3570        Symbol and doesn't happen at least for "Wingdings*" */
3571 
3572     if(!strcmpiW(lf.lfFaceName, SymbolW))
3573         lf.lfCharSet = SYMBOL_CHARSET;
3574 
3575     if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
3576         switch(lf.lfCharSet) {
3577         case DEFAULT_CHARSET:
3578             csi.fs.fsCsb[0] = 0;
3579             break;
3580         default:
3581             FIXME("Untranslated charset %d\n", lf.lfCharSet);
3582             csi.fs.fsCsb[0] = 0;
3583             break;
3584         }
3585     }
3586 
3587     family = NULL;
3588     if(lf.lfFaceName[0] != '\0') {
3589         SYSTEM_LINKS *font_link;
3590         CHILD_FONT *font_link_entry;
3591         LPWSTR FaceName = lf.lfFaceName;
3592 
3593         /*
3594          * Check for a leading '@' this signals that the font is being
3595          * requested in tategaki mode (vertical writing substitution) but
3596          * does not affect the fontface that is to be selected.
3597          */
3598         if (lf.lfFaceName[0]=='@')
3599             FaceName = &lf.lfFaceName[1];
3600 
3601         psub = get_font_subst(&font_subst_list, FaceName, lf.lfCharSet);
3602 
3603         if(psub) {
3604             TRACE("substituting %s,%d -> %s,%d\n", debugstr_w(FaceName), lf.lfCharSet,
3605                   debugstr_w(psub->to.name), (psub->to.charset != -1) ? psub->to.charset : lf.lfCharSet);
3606             if (psub->to.charset != -1)
3607                 lf.lfCharSet = psub->to.charset;
3608         }
3609 
3610         /* We want a match on name and charset or just name if
3611            charset was DEFAULT_CHARSET.  If the latter then
3612            we fixup the returned charset later in get_nearest_charset
3613            where we'll either use the charset of the current ansi codepage
3614            or if that's unavailable the first charset that the font supports.
3615         */
3616         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3617             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3618             if (!strcmpiW(family->FamilyName, FaceName) ||
3619                 (psub && !strcmpiW(family->FamilyName, psub->to.name)))
3620             {
3621                 LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3622                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
3623                     if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
3624                         if(face->scalable || can_use_bitmap)
3625                             goto found;
3626                 }
3627             }
3628         }
3629 
3630         /*
3631          * Try check the SystemLink list first for a replacement font.
3632          * We may find good replacements there.
3633          */
3634         LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3635         {
3636             if(!strcmpiW(font_link->font_name, FaceName) ||
3637                (psub && !strcmpiW(font_link->font_name,psub->to.name)))
3638             {
3639                 TRACE("found entry in system list\n");
3640                 LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3641                 {
3642                     face = font_link_entry->face;
3643                     family = face->family;
3644                     if(csi.fs.fsCsb[0] &
3645                         (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]) || !csi.fs.fsCsb[0])
3646                     {
3647                         if(face->scalable || can_use_bitmap)
3648                             goto found;
3649                     }
3650                 }
3651             }
3652         }
3653     }
3654 
3655     psub = NULL; /* substitution is no more relevant */
3656 
3657     /* If requested charset was DEFAULT_CHARSET then try using charset
3658        corresponding to the current ansi codepage */
3659     if (!csi.fs.fsCsb[0])
3660     {
3661         INT acp = GetACP();
3662         if(!TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE)) {
3663             FIXME("TCI failed on codepage %d\n", acp);
3664             csi.fs.fsCsb[0] = 0;
3665         } else
3666             lf.lfCharSet = csi.ciCharset;
3667     }
3668 
3669     /* Face families are in the top 4 bits of lfPitchAndFamily,
3670        so mask with 0xF0 before testing */
3671 
3672     if((lf.lfPitchAndFamily & FIXED_PITCH) ||
3673        (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
3674         strcpyW(lf.lfFaceName, defFixed);
3675     else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
3676         strcpyW(lf.lfFaceName, defSerif);
3677     else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
3678         strcpyW(lf.lfFaceName, defSans);
3679     else
3680         strcpyW(lf.lfFaceName, defSans);
3681     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3682         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3683         if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
3684             LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3685                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
3686                 if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
3687                     if(face->scalable || can_use_bitmap)
3688                         goto found;
3689             }
3690         }
3691     }
3692 
3693     last_resort_family = NULL;
3694     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3695         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3696         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3697             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3698             if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) {
3699                 if(face->scalable)
3700                     goto found;
3701                 if(can_use_bitmap && !last_resort_family)
3702                     last_resort_family = family;
3703             }            
3704         }
3705     }
3706 
3707     if(last_resort_family) {
3708         family = last_resort_family;
3709         csi.fs.fsCsb[0] = 0;
3710         goto found;
3711     }
3712 
3713     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3714         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3715         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3716             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3717             if(face->scalable) {
3718                 csi.fs.fsCsb[0] = 0;
3719                 WARN("just using first face for now\n");
3720                 goto found;
3721             }
3722             if(can_use_bitmap && !last_resort_family)
3723                 last_resort_family = family;
3724         }
3725     }
3726     if(!last_resort_family) {
3727         FIXME("can't find a single appropriate font - bailing\n");
3728         free_font(ret);
3729         LeaveCriticalSection( &freetype_cs );
3730         return NULL;
3731     }
3732 
3733     WARN("could only find a bitmap font - this will probably look awful!\n");
3734     family = last_resort_family;
3735     csi.fs.fsCsb[0] = 0;
3736 
3737 found:
3738     it = lf.lfItalic ? 1 : 0;
3739     bd = lf.lfWeight > 550 ? 1 : 0;
3740 
3741     height = lf.lfHeight;
3742 
3743     face = best = best_bitmap = NULL;
3744     LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
3745     {
3746         if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
3747         {
3748             BOOL italic, bold;
3749 
3750             italic = (face->ntmFlags & NTM_ITALIC) ? 1 : 0;
3751             bold = (face->ntmFlags & NTM_BOLD) ? 1 : 0;
3752             new_score = (italic ^ it) + (bold ^ bd);
3753             if(!best || new_score <= score)
3754             {
3755                 TRACE("(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n",
3756                       italic, bold, it, bd);
3757                 score = new_score;
3758                 best = face;
3759                 if(best->scalable  && score == 0) break;
3760                 if(!best->scalable)
3761                 {
3762                     if(height > 0)
3763                         newdiff = height - (signed int)(best->size.height);
3764                     else
3765                         newdiff = -height - ((signed int)(best->size.height) - best->size.internal_leading);
3766                     if(!best_bitmap || new_score < score ||
3767                        (diff > 0 && newdiff < diff && newdiff >= 0) || (diff < 0 && newdiff > diff))
3768                     {
3769                         TRACE("%d is better for %d diff was %d\n", best->size.height, height, diff);
3770                         diff = newdiff;
3771                         best_bitmap = best;
3772                         if(score == 0 && diff == 0) break;
3773                     }
3774                 }
3775             }
3776         }
3777     }
3778     if(best)
3779         face = best->scalable ? best : best_bitmap;
3780     ret->fake_italic = (it && !(face->ntmFlags & NTM_ITALIC));
3781     ret->fake_bold = (bd && !(face->ntmFlags & NTM_BOLD));
3782 
3783     ret->fs = face->fs;
3784 
3785     if(csi.fs.fsCsb[0]) {
3786         ret->charset = lf.lfCharSet;
3787         ret->codepage = csi.ciACP;
3788     }
3789     else
3790         ret->charset = get_nearest_charset(face, &ret->codepage);
3791 
3792     TRACE("Chosen: %s %s (%s/%p:%ld)\n", debugstr_w(family->FamilyName),
3793           debugstr_w(face->StyleName), face->file, face->font_data_ptr, face->face_index);
3794 
3795     ret->aveWidth = height ? lf.lfWidth : 0;
3796 
3797     if(!face->scalable) {
3798         /* Windows uses integer scaling factors for bitmap fonts */
3799         INT scale, scaled_height;
3800 
3801         /* FIXME: rotation of bitmap fonts is ignored */
3802         height = abs(GDI_ROUND( (double)height * ret->font_desc.matrix.eM22 ));
3803         if (ret->aveWidth)
3804             ret->aveWidth = (double)ret->aveWidth * ret->font_desc.matrix.eM11;
3805         ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
3806 
3807         if (height != 0) height = diff;
3808         height += face->size.height;
3809 
3810         scale = (height + face->size.height - 1) / face->size.height;
3811         scaled_height = scale * face->size.height;
3812         /* Only jump to the next height if the difference <= 25% original height */
3813         if (scale > 2 && scaled_height - height > face->size.height / 4) scale--;
3814         /* The jump between unscaled and doubled is delayed by 1 */
3815         else if (scale == 2 && scaled_height - height > (face->size.height / 4 - 1)) scale--;
3816         ret->scale_y = scale;
3817 
3818         width = face->size.x_ppem >> 6;
3819         height = face->size.y_ppem >> 6;
3820     }
3821     else
3822         ret->scale_y = 1.0;
3823     TRACE("font scale y: %f\n", ret->scale_y);
3824 
3825     ret->ft_face = OpenFontFace(ret, face, width, height);
3826 
3827     if (!ret->ft_face)
3828     {
3829         free_font( ret );
3830         LeaveCriticalSection( &freetype_cs );
3831         return 0;
3832     }
3833 
3834     ret->ntmFlags = face->ntmFlags;
3835 
3836     if (ret->charset == SYMBOL_CHARSET && 
3837         select_charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) {
3838         /* No ops */
3839     }
3840     else if (select_charmap(ret->ft_face, FT_ENCODING_UNICODE)) {
3841         /* No ops */
3842     }
3843     else {
3844         select_charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN);
3845     }
3846 
3847     ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0;
3848     ret->name = psub ? strdupW(psub->from.name) : strdupW(family->FamilyName);
3849     ret->underline = lf.lfUnderline ? 0xff : 0;
3850     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
3851     create_child_font_list(ret);
3852 
3853     if (lf.lfFaceName[0]=='@') /* We need to try to load the GSUB table */
3854     {
3855         int length = WineEngGetFontData (ret, GSUB_TAG , 0, NULL, 0);
3856         if (length != GDI_ERROR)
3857         {
3858             ret->GSUB_Table = HeapAlloc(GetProcessHeap(),0,length);
3859             WineEngGetFontData(ret, GSUB_TAG , 0, ret->GSUB_Table, length);
3860             TRACE("Loaded GSUB table of %i bytes\n",length);
3861         }
3862     }
3863 
3864     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
3865 
3866     add_to_cache(ret);
3867     LeaveCriticalSection( &freetype_cs );
3868     return ret;
3869 }
3870 
3871 static void dump_gdi_font_list(void)
3872 {
3873     GdiFont *gdiFont;
3874     struct list *elem_ptr;
3875 
3876     TRACE("---------- gdiFont Cache ----------\n");
3877     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
3878         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
3879         TRACE("gdiFont=%p %s %d\n",
3880               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
3881     }
3882 
3883     TRACE("---------- Unused gdiFont Cache ----------\n");
3884     LIST_FOR_EACH(elem_ptr, &unused_gdi_font_list) {
3885         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
3886         TRACE("gdiFont=%p %s %d\n",
3887               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
3888     }
3889 }
3890 
3891 /*************************************************************
3892  * WineEngDestroyFontInstance
3893  *
3894  * free the gdiFont associated with this handle
3895  *
3896  */
3897 BOOL WineEngDestroyFontInstance(HFONT handle)
3898 {
3899     GdiFont *gdiFont;
3900     HFONTLIST *hflist;
3901     BOOL ret = FALSE;
3902     struct list *font_elem_ptr, *hfontlist_elem_ptr;
3903     int i = 0;
3904 
3905     GDI_CheckNotLock();
3906     EnterCriticalSection( &freetype_cs );
3907 
3908     LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry)
3909     {
3910         struct list *first_hfont = list_head(&gdiFont->hfontlist);
3911         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
3912         if(hflist->hfont == handle)
3913         {
3914             TRACE("removing child font %p from child list\n", gdiFont);
3915             list_remove(&gdiFont->entry);
3916             LeaveCriticalSection( &freetype_cs );
3917             return TRUE;
3918         }
3919     }
3920 
3921     TRACE("destroying hfont=%p\n", handle);
3922     if(TRACE_ON(font))
3923         dump_gdi_font_list();
3924 
3925     font_elem_ptr = list_head(&gdi_font_list);
3926     while(font_elem_ptr) {
3927         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3928         font_elem_ptr = list_next(&gdi_font_list, font_elem_ptr);
3929 
3930         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
3931         while(hfontlist_elem_ptr) {
3932             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3933             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
3934             if(hflist->hfont == handle) {
3935                 list_remove(&hflist->entry);