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