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

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

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