gdi32: Allocate cache for face enumeration data only when necessary.
[wine] / dlls / gdi32 / freetype.c
1 /*
2  * FreeType font engine interface
3  *
4  * Copyright 2001 Huw D M Davies for CodeWeavers.
5  * Copyright 2006 Dmitry Timoshkov for CodeWeavers.
6  *
7  * This file contains the WineEng* functions.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #ifdef HAVE_SYS_STAT_H
30 # include <sys/stat.h>
31 #endif
32 #ifdef HAVE_SYS_MMAN_H
33 # include <sys/mman.h>
34 #endif
35 #include <string.h>
36 #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 bascially 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     BOOL Italic;
260     BOOL Bold;
261     FONTSIGNATURE fs;
262     FONTSIGNATURE fs_links;
263     DWORD ntmFlags;  /* Only some bits stored here. Others are computed on the fly */
264     FT_Fixed font_version;
265     BOOL scalable;
266     Bitmap_Size size;     /* set if face is a bitmap */
267     BOOL external; /* TRUE if we should manually add this font to the registry */
268     struct tagFamily *family;
269     /* Cached data for Enum */
270     struct enum_data *cached_enum_data;
271 } Face;
272
273 typedef struct tagFamily {
274     struct list entry;
275     const WCHAR *FamilyName;
276     struct list faces;
277 } Family;
278
279 typedef struct {
280     GLYPHMETRICS gm;
281     INT adv; /* These three hold to widths of the unrotated chars */
282     INT lsb;
283     INT bbx;
284     BOOL init;
285 } GM;
286
287 typedef struct {
288     FLOAT eM11, eM12;
289     FLOAT eM21, eM22;
290 } FMAT2;
291
292 typedef struct {
293     DWORD hash;
294     LOGFONTW lf;
295     FMAT2 matrix;
296     BOOL can_use_bitmap;
297 } FONT_DESC;
298
299 typedef struct tagHFONTLIST {
300     struct list entry;
301     HFONT hfont;
302 } HFONTLIST;
303
304 typedef struct {
305     struct list entry;
306     Face *face;
307     GdiFont *font;
308 } CHILD_FONT;
309
310 struct tagGdiFont {
311     struct list entry;
312     FT_Face ft_face;
313     struct font_mapping *mapping;
314     LPWSTR name;
315     int charset;
316     int codepage;
317     BOOL fake_italic;
318     BOOL fake_bold;
319     BYTE underline;
320     BYTE strikeout;
321     INT orientation;
322     GM **gm;
323     DWORD gmsize;
324     struct list hfontlist;
325     FONT_DESC font_desc;
326     LONG aveWidth, ppem;
327     float scale_x, scale_y;
328     SHORT yMax;
329     SHORT yMin;
330     OUTLINETEXTMETRICW *potm;
331     DWORD ntmFlags;
332     DWORD total_kern_pairs;
333     KERNINGPAIR *kern_pairs;
334     FONTSIGNATURE fs;
335     GdiFont *base_font;
336     struct list child_fonts;
337 };
338
339 typedef struct {
340     struct list entry;
341     const WCHAR *font_name;
342     struct list links;
343 } SYSTEM_LINKS;
344
345 #define GM_BLOCK_SIZE 128
346 #define FONT_GM(font,idx) (&(font)->gm[(idx) / GM_BLOCK_SIZE][(idx) % GM_BLOCK_SIZE])
347
348 static struct list gdi_font_list = LIST_INIT(gdi_font_list);
349 static struct list unused_gdi_font_list = LIST_INIT(unused_gdi_font_list);
350 #define UNUSED_CACHE_SIZE 10
351 static struct list child_font_list = LIST_INIT(child_font_list);
352 static struct list system_links = LIST_INIT(system_links);
353
354 static struct list font_subst_list = LIST_INIT(font_subst_list);
355
356 static struct list font_list = LIST_INIT(font_list);
357
358 static const WCHAR defSerif[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
359 static const WCHAR defSans[] = {'A','r','i','a','l','\0'};
360 static const WCHAR defFixed[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'};
361
362 static const WCHAR RegularW[] = {'R','e','g','u','l','a','r','\0'};
363
364 static const WCHAR fontsW[] = {'\\','f','o','n','t','s','\0'};
365 static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
366                                            'W','i','n','d','o','w','s','\\',
367                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
368                                            'F','o','n','t','s','\0'};
369
370 static const WCHAR winnt_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
371                                            'W','i','n','d','o','w','s',' ','N','T','\\',
372                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
373                                            'F','o','n','t','s','\0'};
374
375 static const WCHAR system_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
376 static const WCHAR FixedSys_Value[] = {'F','I','X','E','D','F','O','N','.','F','O','N','\0'};
377 static const WCHAR System_Value[] = {'F','O','N','T','S','.','F','O','N','\0'};
378 static const WCHAR OEMFont_Value[] = {'O','E','M','F','O','N','T','.','F','O','N','\0'};
379
380 static const WCHAR * const SystemFontValues[4] = {
381     System_Value,
382     OEMFont_Value,
383     FixedSys_Value,
384     NULL
385 };
386
387 static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
388                                                'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'};
389
390 static const WCHAR ArabicW[] = {'A','r','a','b','i','c','\0'};
391 static const WCHAR BalticW[] = {'B','a','l','t','i','c','\0'};
392 static const WCHAR CHINESE_BIG5W[] = {'C','H','I','N','E','S','E','_','B','I','G','5','\0'};
393 static const WCHAR CHINESE_GB2312W[] = {'C','H','I','N','E','S','E','_','G','B','2','3','1','2','\0'};
394 static const WCHAR Central_EuropeanW[] = {'C','e','n','t','r','a','l',' ',
395                                     'E','u','r','o','p','e','a','n','\0'};
396 static const WCHAR CyrillicW[] = {'C','y','r','i','l','l','i','c','\0'};
397 static const WCHAR GreekW[] = {'G','r','e','e','k','\0'};
398 static const WCHAR HangulW[] = {'H','a','n','g','u','l','\0'};
399 static const WCHAR Hangul_Johab_W[] = {'H','a','n','g','u','l','(','J','o','h','a','b',')','\0'};
400 static const WCHAR HebrewW[] = {'H','e','b','r','e','w','\0'};
401 static const WCHAR JapaneseW[] = {'J','a','p','a','n','e','s','e','\0'};
402 static const WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
403 static const WCHAR ThaiW[] = {'T','h','a','i','\0'};
404 static const WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'};
405 static const WCHAR VietnameseW[] = {'V','i','e','t','n','a','m','e','s','e','\0'};
406 static const WCHAR WesternW[] = {'W','e','s','t','e','r','n','\0'};
407 static const WCHAR OEM_DOSW[] = {'O','E','M','/','D','O','S','\0'};
408
409 static const WCHAR * const ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits */
410     WesternW, /*00*/
411     Central_EuropeanW,
412     CyrillicW,
413     GreekW,
414     TurkishW,
415     HebrewW,
416     ArabicW,
417     BalticW,
418     VietnameseW, /*08*/
419     NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/
420     ThaiW,
421     JapaneseW,
422     CHINESE_GB2312W,
423     HangulW,
424     CHINESE_BIG5W,
425     Hangul_Johab_W,
426     NULL, NULL, /*23*/
427     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
428     SymbolW /*31*/
429 };
430
431 typedef struct {
432     WCHAR *name;
433     INT charset;
434 } NameCs;
435
436 typedef struct tagFontSubst {
437     struct list entry;
438     NameCs from;
439     NameCs to;
440 } FontSubst;
441
442 struct font_mapping
443 {
444     struct list entry;
445     int         refcount;
446     dev_t       dev;
447     ino_t       ino;
448     void       *data;
449     size_t      size;
450 };
451
452 static struct list mappings_list = LIST_INIT( mappings_list );
453
454 static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail if this is still FALSE */
455
456 static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'};
457
458 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph);
459
460 /****************************************
461  *   Notes on .fon files
462  *
463  * The fonts System, FixedSys and Terminal are special.  There are typically multiple
464  * versions installed for different resolutions and codepages.  Windows stores which one to use
465  * in HKEY_CURRENT_CONFIG\\Software\\Fonts.
466  *    Key            Meaning
467  *  FIXEDFON.FON    FixedSys
468  *  FONTS.FON       System
469  *  OEMFONT.FON     Terminal
470  *  LogPixels       Current dpi set by the display control panel applet
471  *                  (HKLM\\Software\\Microsft\\Windows NT\\CurrentVersion\\FontDPI
472  *                  also has a LogPixels value that appears to mirror this)
473  *
474  * On my system these values have data: vgafix.fon, vgasys.fon, vga850.fon and 96 respectively
475  * (vgaoem.fon would be your oemfont.fon if you have a US setup).
476  * If the resolution is changed to be >= 109dpi then the fonts goto 8514fix, 8514sys and 8514oem
477  * (not sure what's happening to the oem codepage here). 109 is nicely halfway between 96 and 120dpi,
478  * so that makes sense.
479  *
480  * Additionally Windows also loads the fonts listed in the [386enh] section of system.ini (this doesn't appear
481  * to be mapped into the registry on Windows 2000 at least).
482  * I have
483  * woafont=app850.fon
484  * ega80woa.fon=ega80850.fon
485  * ega40woa.fon=ega40850.fon
486  * cga80woa.fon=cga80850.fon
487  * cga40woa.fon=cga40850.fon
488  */
489
490 #ifdef HAVE_CARBON_CARBON_H
491 static char *find_cache_dir(void)
492 {
493     FSRef ref;
494     OSErr err;
495     static char cached_path[MAX_PATH];
496     static const char *wine = "/Wine", *fonts = "/Fonts";
497
498     if(*cached_path) return cached_path;
499
500     err = FSFindFolder(kUserDomain, kCachedDataFolderType, kCreateFolder, &ref);
501     if(err != noErr)
502     {
503         WARN("can't create cached data folder\n");
504         return NULL;
505     }
506     err = FSRefMakePath(&ref, (unsigned char*)cached_path, sizeof(cached_path));
507     if(err != noErr)
508     {
509         WARN("can't create cached data path\n");
510         *cached_path = '\0';
511         return NULL;
512     }
513     if(strlen(cached_path) + strlen(wine) + strlen(fonts) + 1 > sizeof(cached_path))
514     {
515         ERR("Could not create full path\n");
516         *cached_path = '\0';
517         return NULL;
518     }
519     strcat(cached_path, wine);
520
521     if(mkdir(cached_path, 0700) == -1 && errno != EEXIST)
522     {
523         WARN("Couldn't mkdir %s\n", cached_path);
524         *cached_path = '\0';
525         return NULL;
526     }
527     strcat(cached_path, fonts);
528     if(mkdir(cached_path, 0700) == -1 && errno != EEXIST)
529     {
530         WARN("Couldn't mkdir %s\n", cached_path);
531         *cached_path = '\0';
532         return NULL;
533     }
534     return cached_path;
535 }
536
537 /******************************************************************
538  *            expand_mac_font
539  *
540  * Extracts individual TrueType font files from a Mac suitcase font
541  * and saves them into the user's caches directory (see
542  * find_cache_dir()).
543  * Returns a NULL terminated array of filenames.
544  *
545  * We do this because they are apps that try to read ttf files
546  * themselves and they don't like Mac suitcase files.
547  */
548 static char **expand_mac_font(const char *path)
549 {
550     FSRef ref;
551     SInt16 res_ref;
552     OSStatus s;
553     unsigned int idx;
554     const char *out_dir;
555     const char *filename;
556     int output_len;
557     struct {
558         char **array;
559         unsigned int size, max_size;
560     } ret;
561
562     TRACE("path %s\n", path);
563
564     s = FSPathMakeRef((unsigned char*)path, &ref, FALSE);
565     if(s != noErr)
566     {
567         WARN("failed to get ref\n");
568         return NULL;
569     }
570
571     s = FSOpenResourceFile(&ref, 0, NULL, fsRdPerm, &res_ref);
572     if(s != noErr)
573     {
574         TRACE("no data fork, so trying resource fork\n");
575         res_ref = FSOpenResFile(&ref, fsRdPerm);
576         if(res_ref == -1)
577         {
578             TRACE("unable to open resource fork\n");
579             return NULL;
580         }
581     }
582
583     ret.size = 0;
584     ret.max_size = 10;
585     ret.array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ret.max_size * sizeof(*ret.array));
586     if(!ret.array)
587     {
588         CloseResFile(res_ref);
589         return NULL;
590     }
591
592     out_dir = find_cache_dir();
593
594     filename = strrchr(path, '/');
595     if(!filename) filename = path;
596     else filename++;
597
598     /* output filename has the form out_dir/filename_%04x.ttf */
599     output_len = strlen(out_dir) + 1 + strlen(filename) + 5 + 5;
600
601     UseResFile(res_ref);
602     idx = 1;
603     while(1)
604     {
605         FamRec *fam_rec;
606         unsigned short *num_faces_ptr, num_faces, face;
607         AsscEntry *assoc;
608         Handle fond;
609         ResType fond_res = FT_MAKE_TAG('F','O','N','D');
610
611         fond = Get1IndResource(fond_res, idx);
612         if(!fond) break;
613         TRACE("got fond resource %d\n", idx);
614         HLock(fond);
615
616         fam_rec = *(FamRec**)fond;
617         num_faces_ptr = (unsigned short *)(fam_rec + 1);
618         num_faces = GET_BE_WORD(*num_faces_ptr);
619         num_faces++;
620         assoc = (AsscEntry*)(num_faces_ptr + 1);
621         TRACE("num faces %04x\n", num_faces);
622         for(face = 0; face < num_faces; face++, assoc++)
623         {
624             Handle sfnt;
625             ResType sfnt_res = FT_MAKE_TAG('s','f','n','t');
626             unsigned short size, font_id;
627             char *output;
628
629             size = GET_BE_WORD(assoc->fontSize);
630             font_id = GET_BE_WORD(assoc->fontID);
631             if(size != 0)
632             {
633                 TRACE("skipping id %04x because it's not scalable (fixed size %d)\n", font_id, size);
634                 continue;
635             }
636
637             TRACE("trying to load sfnt id %04x\n", font_id);
638             sfnt = GetResource(sfnt_res, font_id);
639             if(!sfnt)
640             {
641                 TRACE("can't get sfnt resource %04x\n", font_id);
642                 continue;
643             }
644
645             output = HeapAlloc(GetProcessHeap(), 0, output_len);
646             if(output)
647             {
648                 int fd;
649
650                 sprintf(output, "%s/%s_%04x.ttf", out_dir, filename, font_id);
651
652                 fd = open(output, O_CREAT | O_EXCL | O_WRONLY, 0600);
653                 if(fd != -1 || errno == EEXIST)
654                 {
655                     if(fd != -1)
656                     {
657                         unsigned char *sfnt_data;
658
659                         HLock(sfnt);
660                         sfnt_data = *(unsigned char**)sfnt;
661                         write(fd, sfnt_data, GetHandleSize(sfnt));
662                         HUnlock(sfnt);
663                         close(fd);
664                     }
665                     if(ret.size >= ret.max_size - 1) /* Always want the last element to be NULL */
666                     {
667                         ret.max_size *= 2;
668                         ret.array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ret.array, ret.max_size * sizeof(*ret.array));
669                     }
670                     ret.array[ret.size++] = output;
671                 }
672                 else
673                 {
674                     WARN("unable to create %s\n", output);
675                     HeapFree(GetProcessHeap(), 0, output);
676                 }
677             }
678             ReleaseResource(sfnt);
679         }
680         HUnlock(fond);
681         ReleaseResource(fond);
682         idx++;
683     }
684     CloseResFile(res_ref);
685
686     return ret.array;
687 }
688
689 #endif /* HAVE_CARBON_CARBON_H */
690
691 static inline BOOL is_win9x(void)
692 {
693     return GetVersion() & 0x80000000;
694 }
695 /* 
696    This function builds an FT_Fixed from a float. It puts the integer part
697    in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed.
698    It fails if the integer part of the float number is greater than SHORT_MAX.
699 */
700 static inline FT_Fixed FT_FixedFromFloat(float f)
701 {
702         short value = f;
703         unsigned short fract = (f - value) * 0xFFFF;
704         return (FT_Fixed)((long)value << 16 | (unsigned long)fract);
705 }
706
707 /* 
708    This function builds an FT_Fixed from a FIXED. It simply put f.value 
709    in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
710 */
711 static inline FT_Fixed FT_FixedFromFIXED(FIXED f)
712 {
713         return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
714 }
715
716
717 static Face *find_face_from_filename(const WCHAR *file_name, const WCHAR *face_name)
718 {
719     Family *family;
720     Face *face;
721     const char *file;
722     DWORD len = WideCharToMultiByte(CP_UNIXCP, 0, file_name, -1, NULL, 0, NULL, NULL);
723     char *file_nameA = HeapAlloc(GetProcessHeap(), 0, len);
724
725     WideCharToMultiByte(CP_UNIXCP, 0, file_name, -1, file_nameA, len, NULL, NULL);
726     TRACE("looking for file %s name %s\n", debugstr_a(file_nameA), debugstr_w(face_name));
727
728     LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
729     {
730         if(face_name && strcmpiW(face_name, family->FamilyName))
731             continue;
732         LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
733         {
734             if (!face->file)
735                 continue;
736             file = strrchr(face->file, '/');
737             if(!file)
738                 file = face->file;
739             else
740                 file++;
741             if(!strcasecmp(file, file_nameA))
742             {
743                 HeapFree(GetProcessHeap(), 0, file_nameA);
744                 return face;
745             }
746         }
747     }
748     HeapFree(GetProcessHeap(), 0, file_nameA);
749     return NULL;
750 }
751
752 static Family *find_family_from_name(const WCHAR *name)
753 {
754     Family *family;
755
756     LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
757     {
758         if(!strcmpiW(family->FamilyName, name))
759             return family;
760     }
761
762     return NULL;
763 }
764
765 static void DumpSubstList(void)
766 {
767     FontSubst *psub;
768
769     LIST_FOR_EACH_ENTRY(psub, &font_subst_list, FontSubst, entry)
770     {
771         if(psub->from.charset != -1 || psub->to.charset != -1)
772             TRACE("%s:%d -> %s:%d\n", debugstr_w(psub->from.name),
773               psub->from.charset, debugstr_w(psub->to.name), psub->to.charset);
774         else
775             TRACE("%s -> %s\n", debugstr_w(psub->from.name),
776                   debugstr_w(psub->to.name));
777     }
778     return;
779 }
780
781 static LPWSTR strdupW(LPCWSTR p)
782 {
783     LPWSTR ret;
784     DWORD len = (strlenW(p) + 1) * sizeof(WCHAR);
785     ret = HeapAlloc(GetProcessHeap(), 0, len);
786     memcpy(ret, p, len);
787     return ret;
788 }
789
790 static LPSTR strdupA(LPCSTR p)
791 {
792     LPSTR ret;
793     DWORD len = (strlen(p) + 1);
794     ret = HeapAlloc(GetProcessHeap(), 0, len);
795     memcpy(ret, p, len);
796     return ret;
797 }
798
799 static FontSubst *get_font_subst(const struct list *subst_list, const WCHAR *from_name,
800                                  INT from_charset)
801 {
802     FontSubst *element;
803
804     LIST_FOR_EACH_ENTRY(element, subst_list, FontSubst, entry)
805     {
806         if(!strcmpiW(element->from.name, from_name) &&
807            (element->from.charset == from_charset ||
808             element->from.charset == -1))
809             return element;
810     }
811
812     return NULL;
813 }
814
815 #define ADD_FONT_SUBST_FORCE  1
816
817 static BOOL add_font_subst(struct list *subst_list, FontSubst *subst, INT flags)
818 {
819     FontSubst *from_exist, *to_exist;
820
821     from_exist = get_font_subst(subst_list, subst->from.name, subst->from.charset);
822
823     if(from_exist && (flags & ADD_FONT_SUBST_FORCE))
824     {
825         list_remove(&from_exist->entry);
826         HeapFree(GetProcessHeap(), 0, &from_exist->from.name);
827         HeapFree(GetProcessHeap(), 0, &from_exist->to.name);
828         HeapFree(GetProcessHeap(), 0, from_exist);
829         from_exist = NULL;
830     }
831
832     if(!from_exist)
833     {
834         to_exist = get_font_subst(subst_list, subst->to.name, subst->to.charset);
835
836         if(to_exist)
837         {
838             HeapFree(GetProcessHeap(), 0, subst->to.name);
839             subst->to.name = strdupW(to_exist->to.name);
840         }
841             
842         list_add_tail(subst_list, &subst->entry);
843
844         return TRUE;
845     }
846
847     HeapFree(GetProcessHeap(), 0, subst->from.name);
848     HeapFree(GetProcessHeap(), 0, subst->to.name);
849     HeapFree(GetProcessHeap(), 0, subst);
850     return FALSE;
851 }
852
853 static void split_subst_info(NameCs *nc, LPSTR str)
854 {
855     CHAR *p = strrchr(str, ',');
856     DWORD len;
857
858     nc->charset = -1;
859     if(p && *(p+1)) {
860         nc->charset = strtol(p+1, NULL, 10);
861         *p = '\0';
862     }
863     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
864     nc->name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
865     MultiByteToWideChar(CP_ACP, 0, str, -1, nc->name, len);
866 }
867
868 static void LoadSubstList(void)
869 {
870     FontSubst *psub;
871     HKEY hkey;
872     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
873     LPSTR value;
874     LPVOID data;
875
876     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
877                    "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes",
878                    &hkey) == ERROR_SUCCESS) {
879
880         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
881                          &valuelen, &datalen, NULL, NULL);
882
883         valuelen++; /* returned value doesn't include room for '\0' */
884         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
885         data = HeapAlloc(GetProcessHeap(), 0, datalen);
886
887         dlen = datalen;
888         vlen = valuelen;
889         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
890                             &dlen) == ERROR_SUCCESS) {
891             TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
892
893             psub = HeapAlloc(GetProcessHeap(), 0, sizeof(*psub));
894             split_subst_info(&psub->from, value);
895             split_subst_info(&psub->to, data);
896
897             /* Win 2000 doesn't allow mapping between different charsets
898                or mapping of DEFAULT_CHARSET */
899             if((psub->to.charset != psub->from.charset) ||
900                psub->to.charset == DEFAULT_CHARSET) {
901                 HeapFree(GetProcessHeap(), 0, psub->to.name);
902                 HeapFree(GetProcessHeap(), 0, psub->from.name);
903                 HeapFree(GetProcessHeap(), 0, psub);
904             } else {
905                 add_font_subst(&font_subst_list, psub, 0);
906             }
907             /* reset dlen and vlen */
908             dlen = datalen;
909             vlen = valuelen;
910         }
911         HeapFree(GetProcessHeap(), 0, data);
912         HeapFree(GetProcessHeap(), 0, value);
913         RegCloseKey(hkey);
914     }
915 }
916
917 static WCHAR *get_familyname(FT_Face ft_face)
918 {
919     WCHAR *family = NULL;
920     FT_SfntName name;
921     FT_UInt num_names, name_index, i;
922
923     if(FT_IS_SFNT(ft_face))
924     {
925         num_names = pFT_Get_Sfnt_Name_Count(ft_face);
926
927         for(name_index = 0; name_index < num_names; name_index++)
928         {
929             if(!pFT_Get_Sfnt_Name(ft_face, name_index, &name))
930             {
931                 if((name.name_id == TT_NAME_ID_FONT_FAMILY) &&
932                    (name.language_id == GetUserDefaultLCID()) &&
933                    (name.platform_id == TT_PLATFORM_MICROSOFT) &&
934                    (name.encoding_id == TT_MS_ID_UNICODE_CS))
935                 {
936                     /* String is not nul terminated and string_len is a byte length. */
937                     family = HeapAlloc(GetProcessHeap(), 0, name.string_len + 2);
938                     for(i = 0; i < name.string_len / 2; i++)
939                     {
940                         WORD *tmp = (WORD *)&name.string[i * 2];
941                         family[i] = GET_BE_WORD(*tmp);
942                     }
943                     family[i] = 0;
944
945                     TRACE("Got localised name %s\n", debugstr_w(family));
946                     return family;
947                 }
948             }
949         }
950     }
951
952     return NULL;
953 }
954
955
956 /*****************************************************************
957  *  load_sfnt_table
958  *
959  * Wrapper around FT_Load_Sfnt_Table to cope with older versions
960  * of FreeType that don't export this function.
961  *
962  */
963 static FT_Error load_sfnt_table(FT_Face ft_face, FT_ULong table, FT_Long offset, FT_Byte *buf, FT_ULong *len)
964 {
965
966     FT_Error err;
967
968     /* If the FT_Load_Sfnt_Table function is there we'll use it */
969     if(pFT_Load_Sfnt_Table)
970     {
971         err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, len);
972     }
973 #ifdef HAVE_FREETYPE_INTERNAL_SFNT_H
974     else  /* Do it the hard way */
975     {
976         TT_Face tt_face = (TT_Face) ft_face;
977         SFNT_Interface *sfnt;
978         if (FT_Version.major==2 && FT_Version.minor==0)
979         {
980             /* 2.0.x */
981             sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
982         }
983         else
984         {
985             /* A field was added in the middle of the structure in 2.1.x */
986             sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
987         }
988         err = sfnt->load_any(tt_face, table, offset, buf, len);
989     }
990 #else
991     else
992     {
993         static int msg;
994         if(!msg)
995         {
996             MESSAGE("This version of Wine was compiled with freetype headers later than 2.2.0\n"
997                     "but is being run with a freetype library without the FT_Load_Sfnt_Table function.\n"
998                     "Please upgrade your freetype library.\n");
999             msg++;
1000         }
1001         err = FT_Err_Unimplemented_Feature;
1002     }
1003 #endif
1004     return err;
1005 }
1006
1007
1008 #define ADDFONT_EXTERNAL_FONT 0x01
1009 #define ADDFONT_FORCE_BITMAP  0x02
1010 static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_size, char *fake_family, const WCHAR *target_family, DWORD flags)
1011 {
1012     FT_Face ft_face;
1013     TT_OS2 *pOS2;
1014     TT_Header *pHeader = NULL;
1015     WCHAR *english_family, *localised_family, *StyleW;
1016     DWORD len;
1017     Family *family;
1018     Face *face;
1019     struct list *family_elem_ptr, *face_elem_ptr;
1020     FT_Error err;
1021     FT_Long face_index = 0, num_faces;
1022 #ifdef HAVE_FREETYPE_FTWINFNT_H
1023     FT_WinFNT_HeaderRec winfnt_header;
1024 #endif
1025     int i, bitmap_num, internal_leading;
1026     FONTSIGNATURE fs;
1027
1028     /* we always load external fonts from files - otherwise we would get a crash in update_reg_entries */
1029     assert(file || !(flags & ADDFONT_EXTERNAL_FONT));
1030
1031 #ifdef HAVE_CARBON_CARBON_H
1032     if(file && !fake_family)
1033     {
1034         char **mac_list = expand_mac_font(file);
1035         if(mac_list)
1036         {
1037             BOOL had_one = FALSE;
1038             char **cursor;
1039             for(cursor = mac_list; *cursor; cursor++)
1040             {
1041                 had_one = TRUE;
1042                 AddFontToList(*cursor, NULL, 0, NULL, NULL, flags);
1043                 HeapFree(GetProcessHeap(), 0, *cursor);
1044             }
1045             HeapFree(GetProcessHeap(), 0, mac_list);
1046             if(had_one)
1047                 return 1;
1048         }
1049     }
1050 #endif /* HAVE_CARBON_CARBON_H */
1051
1052     do {
1053         char *family_name = fake_family;
1054
1055         if (file)
1056         {
1057             TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
1058             err = pFT_New_Face(library, file, face_index, &ft_face);
1059         } else
1060         {
1061             TRACE("Loading font from ptr %p size %d, index %ld\n", font_data_ptr, font_data_size, face_index);
1062             err = pFT_New_Memory_Face(library, font_data_ptr, font_data_size, face_index, &ft_face);
1063         }
1064
1065         if(err != 0) {
1066             WARN("Unable to load font %s/%p err = %x\n", debugstr_a(file), font_data_ptr, err);
1067             return 0;
1068         }
1069
1070         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*/
1071             WARN("Ignoring font %s/%p\n", debugstr_a(file), font_data_ptr);
1072             pFT_Done_Face(ft_face);
1073             return 0;
1074         }
1075
1076         /* There are too many bugs in FreeType < 2.1.9 for bitmap font support */
1077         if(!FT_IS_SCALABLE(ft_face) && FT_SimpleVersion < ((2 << 16) | (1 << 8) | (9 << 0))) {
1078             WARN("FreeType version < 2.1.9, skipping bitmap font %s/%p\n", debugstr_a(file), font_data_ptr);
1079             pFT_Done_Face(ft_face);
1080             return 0;
1081         }
1082
1083         if(FT_IS_SFNT(ft_face))
1084         {
1085             if(!(pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2)) ||
1086                !pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea) ||
1087                !(pHeader = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_head)))
1088             {
1089                 TRACE("Font %s/%p lacks either an OS2, HHEA or HEAD table.\n"
1090                       "Skipping this font.\n", debugstr_a(file), font_data_ptr);
1091                 pFT_Done_Face(ft_face);
1092                 return 0;
1093             }
1094
1095             /* Wine uses ttfs as an intermediate step in building its bitmap fonts;
1096                we don't want to load these. */
1097             if(!memcmp(pOS2->achVendID, "Wine", sizeof(pOS2->achVendID)))
1098             {
1099                 FT_ULong len = 0;
1100
1101                 if(!load_sfnt_table(ft_face, FT_MAKE_TAG('E','B','S','C'), 0, NULL, &len))
1102                 {
1103                     TRACE("Skipping Wine bitmap-only TrueType font %s\n", debugstr_a(file));
1104                     pFT_Done_Face(ft_face);
1105                     return 0;
1106                 }
1107             }
1108         }
1109
1110         if(!ft_face->family_name || !ft_face->style_name) {
1111             TRACE("Font %s/%p lacks either a family or style name\n", debugstr_a(file), font_data_ptr);
1112             pFT_Done_Face(ft_face);
1113             return 0;
1114         }
1115
1116         if (target_family)
1117         {
1118             localised_family = get_familyname(ft_face);
1119             if (localised_family && strcmpiW(localised_family,target_family)!=0)
1120             {
1121                 TRACE("Skipping Index %i: Incorrect Family name for replacement\n",(INT)face_index);
1122                 HeapFree(GetProcessHeap(), 0, localised_family);
1123                 num_faces = ft_face->num_faces;
1124                 pFT_Done_Face(ft_face);
1125                 continue;
1126             }
1127             HeapFree(GetProcessHeap(), 0, localised_family);
1128         }
1129
1130         if(!family_name)
1131             family_name = ft_face->family_name;
1132
1133         bitmap_num = 0;
1134         do {
1135             My_FT_Bitmap_Size *size = NULL;
1136             FT_ULong tmp_size;
1137
1138             if(!FT_IS_SCALABLE(ft_face))
1139                 size = (My_FT_Bitmap_Size *)ft_face->available_sizes + bitmap_num;
1140
1141             len = MultiByteToWideChar(CP_ACP, 0, family_name, -1, NULL, 0);
1142             english_family = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1143             MultiByteToWideChar(CP_ACP, 0, family_name, -1, english_family, len);
1144
1145             localised_family = NULL;
1146             if(!fake_family) {
1147                 localised_family = get_familyname(ft_face);
1148                 if(localised_family && !strcmpW(localised_family, english_family)) {
1149                     HeapFree(GetProcessHeap(), 0, localised_family);
1150                     localised_family = NULL;
1151                 }
1152             }
1153
1154             family = NULL;
1155             LIST_FOR_EACH(family_elem_ptr, &font_list) {
1156                 family = LIST_ENTRY(family_elem_ptr, Family, entry);
1157                 if(!strcmpW(family->FamilyName, localised_family ? localised_family : english_family))
1158                     break;
1159                 family = NULL;
1160             }
1161             if(!family) {
1162                 family = HeapAlloc(GetProcessHeap(), 0, sizeof(*family));
1163                 family->FamilyName = strdupW(localised_family ? localised_family : english_family);
1164                 list_init(&family->faces);
1165                 list_add_tail(&font_list, &family->entry);
1166
1167                 if(localised_family) {
1168                     FontSubst *subst = HeapAlloc(GetProcessHeap(), 0, sizeof(*subst));
1169                     subst->from.name = strdupW(english_family);
1170                     subst->from.charset = -1;
1171                     subst->to.name = strdupW(localised_family);
1172                     subst->to.charset = -1;
1173                     add_font_subst(&font_subst_list, subst, 0);
1174                 }
1175             }
1176             HeapFree(GetProcessHeap(), 0, localised_family);
1177             HeapFree(GetProcessHeap(), 0, english_family);
1178
1179             len = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0);
1180             StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1181             MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
1182
1183             internal_leading = 0;
1184             memset(&fs, 0, sizeof(fs));
1185
1186             pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
1187             if(pOS2) {
1188                 fs.fsCsb[0] = pOS2->ulCodePageRange1;
1189                 fs.fsCsb[1] = pOS2->ulCodePageRange2;
1190                 fs.fsUsb[0] = pOS2->ulUnicodeRange1;
1191                 fs.fsUsb[1] = pOS2->ulUnicodeRange2;
1192                 fs.fsUsb[2] = pOS2->ulUnicodeRange3;
1193                 fs.fsUsb[3] = pOS2->ulUnicodeRange4;
1194                 if(pOS2->version == 0) {
1195                     FT_UInt dummy;
1196
1197                     if(!pFT_Get_First_Char || (pFT_Get_First_Char( ft_face, &dummy ) < 0x100))
1198                         fs.fsCsb[0] |= FS_LATIN1;
1199                     else
1200                         fs.fsCsb[0] |= FS_SYMBOL;
1201                 }
1202             }
1203 #ifdef HAVE_FREETYPE_FTWINFNT_H
1204             else if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header)) {
1205                 CHARSETINFO csi;
1206                 TRACE("pix_h %d charset %d dpi %dx%d pt %d\n", winfnt_header.pixel_height, winfnt_header.charset,
1207                       winfnt_header.vertical_resolution,winfnt_header.horizontal_resolution, winfnt_header.nominal_point_size);
1208                 if(TranslateCharsetInfo((DWORD*)(UINT_PTR)winfnt_header.charset, &csi, TCI_SRCCHARSET))
1209                     memcpy(&fs, &csi.fs, sizeof(csi.fs));
1210                 internal_leading = winfnt_header.internal_leading;
1211             }
1212 #endif
1213
1214             face_elem_ptr = list_head(&family->faces);
1215             while(face_elem_ptr) {
1216                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
1217                 face_elem_ptr = list_next(&family->faces, face_elem_ptr);
1218                 if(!strcmpW(face->StyleName, StyleW) &&
1219                    (FT_IS_SCALABLE(ft_face) || ((size->y_ppem == face->size.y_ppem) && !memcmp(&fs, &face->fs, sizeof(fs)) ))) {
1220                     TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
1221                           debugstr_w(family->FamilyName), debugstr_w(StyleW),
1222                           face->font_version,  pHeader ? pHeader->Font_Revision : 0);
1223
1224                     if(fake_family) {
1225                         TRACE("This font is a replacement but the original really exists, so we'll skip the replacement\n");
1226                         HeapFree(GetProcessHeap(), 0, StyleW);
1227                         pFT_Done_Face(ft_face);
1228                         return 1;
1229                     }
1230                     if(!pHeader || pHeader->Font_Revision <= face->font_version) {
1231                         TRACE("Original font is newer so skipping this one\n");
1232                         HeapFree(GetProcessHeap(), 0, StyleW);
1233                         pFT_Done_Face(ft_face);
1234                         return 1;
1235                     } else {
1236                         TRACE("Replacing original with this one\n");
1237                         list_remove(&face->entry);
1238                         HeapFree(GetProcessHeap(), 0, face->file);
1239                         HeapFree(GetProcessHeap(), 0, face->StyleName);
1240                         HeapFree(GetProcessHeap(), 0, face);
1241                         break;
1242                     }
1243                 }
1244             }
1245             face = HeapAlloc(GetProcessHeap(), 0, sizeof(*face));
1246             face->cached_enum_data = NULL;
1247             list_add_tail(&family->faces, &face->entry);
1248             face->StyleName = StyleW;
1249             if (file)
1250             {
1251                 face->file = strdupA(file);
1252                 face->font_data_ptr = NULL;
1253                 face->font_data_size = 0;
1254             }
1255             else
1256             {
1257                 face->file = NULL;
1258                 face->font_data_ptr = font_data_ptr;
1259                 face->font_data_size = font_data_size;
1260             }
1261             face->face_index = face_index;
1262             face->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
1263             face->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0;
1264             face->font_version = pHeader ? pHeader->Font_Revision : 0;
1265             face->family = family;
1266             face->external = (flags & ADDFONT_EXTERNAL_FONT) ? TRUE : FALSE;
1267             memcpy(&face->fs, &fs, sizeof(face->fs));
1268             memset(&face->fs_links, 0, sizeof(face->fs_links));
1269
1270             if(FT_IS_SCALABLE(ft_face)) {
1271                 memset(&face->size, 0, sizeof(face->size));
1272                 face->scalable = TRUE;
1273             } else {
1274                 TRACE("Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld\n",
1275                       size->height, size->width, size->size >> 6,
1276                       size->x_ppem >> 6, size->y_ppem >> 6);
1277                 face->size.height = size->height;
1278                 face->size.width = size->width;
1279                 face->size.size = size->size;
1280                 face->size.x_ppem = size->x_ppem;
1281                 face->size.y_ppem = size->y_ppem;
1282                 face->size.internal_leading = internal_leading;
1283                 face->scalable = FALSE;
1284             }
1285
1286             /* check for the presence of the 'CFF ' table to check if the font is Type1 */
1287             tmp_size = 0;
1288             if (pFT_Load_Sfnt_Table && !pFT_Load_Sfnt_Table(ft_face, FT_MAKE_TAG('C','F','F',' '), 0, NULL, &tmp_size))
1289             {
1290                 TRACE("Font %s/%p is OTF Type1\n", wine_dbgstr_a(file), font_data_ptr);
1291                 face->ntmFlags = NTM_PS_OPENTYPE;
1292             }
1293             else
1294                 face->ntmFlags = 0;
1295
1296             TRACE("fsCsb = %08x %08x/%08x %08x %08x %08x\n",
1297                   face->fs.fsCsb[0], face->fs.fsCsb[1],
1298                   face->fs.fsUsb[0], face->fs.fsUsb[1],
1299                   face->fs.fsUsb[2], face->fs.fsUsb[3]);
1300
1301
1302             if(face->fs.fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */
1303                 for(i = 0; i < ft_face->num_charmaps; i++) {
1304                     switch(ft_face->charmaps[i]->encoding) {
1305                     case FT_ENCODING_UNICODE:
1306                     case FT_ENCODING_APPLE_ROMAN:
1307                         face->fs.fsCsb[0] |= FS_LATIN1;
1308                         break;
1309                     case FT_ENCODING_MS_SYMBOL:
1310                         face->fs.fsCsb[0] |= FS_SYMBOL;
1311                         break;
1312                     default:
1313                         break;
1314                     }
1315                 }
1316             }
1317
1318             if (!(face->fs.fsCsb[0] & FS_SYMBOL))
1319                 have_installed_roman_font = TRUE;
1320         } while(!FT_IS_SCALABLE(ft_face) && ++bitmap_num < ft_face->num_fixed_sizes);
1321
1322         num_faces = ft_face->num_faces;
1323         pFT_Done_Face(ft_face);
1324         TRACE("Added font %s %s\n", debugstr_w(family->FamilyName),
1325               debugstr_w(StyleW));
1326     } while(num_faces > ++face_index);
1327     return num_faces;
1328 }
1329
1330 static INT AddFontFileToList(const char *file, char *fake_family, const WCHAR *target_family, DWORD flags)
1331 {
1332     return AddFontToList(file, NULL, 0, fake_family, target_family, flags);
1333 }
1334
1335 static void DumpFontList(void)
1336 {
1337     Family *family;
1338     Face *face;
1339     struct list *family_elem_ptr, *face_elem_ptr;
1340
1341     LIST_FOR_EACH(family_elem_ptr, &font_list) {
1342         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
1343         TRACE("Family: %s\n", debugstr_w(family->FamilyName));
1344         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
1345             face = LIST_ENTRY(face_elem_ptr, Face, entry);
1346             TRACE("\t%s\t%08x", debugstr_w(face->StyleName), face->fs.fsCsb[0]);
1347             if(!face->scalable)
1348                 TRACE(" %d", face->size.height);
1349             TRACE("\n");
1350         }
1351     }
1352     return;
1353 }
1354
1355 /***********************************************************
1356  * The replacement list is a way to map an entire font
1357  * family onto another family.  For example adding
1358  *
1359  * [HKCU\Software\Wine\Fonts\Replacements]
1360  * "Wingdings"="Winedings"
1361  *
1362  * would enumerate the Winedings font both as Winedings and
1363  * Wingdings.  However if a real Wingdings font is present the
1364  * replacement does not take place.
1365  * 
1366  */
1367 static void LoadReplaceList(void)
1368 {
1369     HKEY hkey;
1370     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
1371     LPWSTR value;
1372     LPVOID data;
1373     Family *family;
1374     Face *face;
1375     struct list *family_elem_ptr, *face_elem_ptr;
1376     CHAR familyA[400];
1377
1378     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\Replacements */
1379     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts\\Replacements", &hkey) == ERROR_SUCCESS)
1380     {
1381         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1382                          &valuelen, &datalen, NULL, NULL);
1383
1384         valuelen++; /* returned value doesn't include room for '\0' */
1385         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
1386         data = HeapAlloc(GetProcessHeap(), 0, datalen);
1387
1388         dlen = datalen;
1389         vlen = valuelen;
1390         while(RegEnumValueW(hkey, i++, value, &vlen, NULL, &type, data,
1391                             &dlen) == ERROR_SUCCESS) {
1392             TRACE("Got %s=%s\n", debugstr_w(value), debugstr_w(data));
1393             /* "NewName"="Oldname" */
1394             WideCharToMultiByte(CP_ACP, 0, value, -1, familyA, sizeof(familyA), NULL, NULL);
1395
1396             /* Find the old family and hence all of the font files
1397                in that family */
1398             LIST_FOR_EACH(family_elem_ptr, &font_list) {
1399                 family = LIST_ENTRY(family_elem_ptr, Family, entry);
1400                 if(!strcmpiW(family->FamilyName, data)) {
1401                     LIST_FOR_EACH(face_elem_ptr, &family->faces) {
1402                         face = LIST_ENTRY(face_elem_ptr, Face, entry);
1403                         TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName),
1404                               debugstr_w(face->StyleName), familyA);
1405                         /* Now add a new entry with the new family name */
1406                         AddFontToList(face->file, face->font_data_ptr, face->font_data_size, familyA, family->FamilyName, ADDFONT_FORCE_BITMAP | (face->external ? ADDFONT_EXTERNAL_FONT : 0));
1407                     }
1408                     break;
1409                 }
1410             }
1411             /* reset dlen and vlen */
1412             dlen = datalen;
1413             vlen = valuelen;
1414         }
1415         HeapFree(GetProcessHeap(), 0, data);
1416         HeapFree(GetProcessHeap(), 0, value);
1417         RegCloseKey(hkey);
1418     }
1419 }
1420
1421 /*************************************************************
1422  * init_system_links
1423  */
1424 static BOOL init_system_links(void)
1425 {
1426     static const WCHAR system_link[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
1427                                         'W','i','n','d','o','w','s',' ','N','T','\\',
1428                                         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','F','o','n','t','L','i','n','k','\\',
1429                                         'S','y','s','t','e','m','L','i','n','k',0};
1430     HKEY hkey;
1431     BOOL ret = FALSE;
1432     DWORD type, max_val, max_data, val_len, data_len, index;
1433     WCHAR *value, *data;
1434     WCHAR *entry, *next;
1435     SYSTEM_LINKS *font_link, *system_font_link;
1436     CHILD_FONT *child_font;
1437     static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
1438     static const WCHAR tahoma_ttf[] = {'t','a','h','o','m','a','.','t','t','f',0};
1439     static const WCHAR System[] = {'S','y','s','t','e','m',0};
1440     FONTSIGNATURE fs;
1441     Family *family;
1442     Face *face;
1443     FontSubst *psub;
1444
1445     if(RegOpenKeyW(HKEY_LOCAL_MACHINE, system_link, &hkey) == ERROR_SUCCESS)
1446     {
1447         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &max_val, &max_data, NULL, NULL);
1448         value = HeapAlloc(GetProcessHeap(), 0, (max_val + 1) * sizeof(WCHAR));
1449         data = HeapAlloc(GetProcessHeap(), 0, max_data);
1450         val_len = max_val + 1;
1451         data_len = max_data;
1452         index = 0;
1453         while(RegEnumValueW(hkey, index++, value, &val_len, NULL, &type, (LPBYTE)data, &data_len) == ERROR_SUCCESS)
1454         {
1455             TRACE("%s:\n", debugstr_w(value));
1456
1457             memset(&fs, 0, sizeof(fs));
1458             font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_link));
1459             psub = get_font_subst(&font_subst_list, value, -1);
1460             font_link->font_name = (psub)? strdupW(psub->to.name) : strdupW(value);
1461             list_init(&font_link->links);
1462             for(entry = data; (char*)entry < (char*)data + data_len && *entry != 0; entry = next)
1463             {
1464                 WCHAR *face_name;
1465                 CHILD_FONT *child_font;
1466
1467                 TRACE("\t%s\n", debugstr_w(entry));
1468
1469                 next = entry + strlenW(entry) + 1;
1470                 
1471                 face_name = strchrW(entry, ',');
1472                 if(face_name)
1473                 {
1474                     *face_name++ = 0;
1475                     while(isspaceW(*face_name))
1476                         face_name++;
1477
1478                     psub = get_font_subst(&font_subst_list, face_name, -1);
1479                     if(psub)
1480                         face_name = psub->to.name;
1481                 }
1482                 face = find_face_from_filename(entry, face_name);
1483                 if(!face)
1484                 {
1485                     TRACE("Unable to find file %s face name %s\n", debugstr_w(entry), debugstr_w(face_name));
1486                     continue;
1487                 }
1488
1489                 child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
1490                 child_font->face = face;
1491                 child_font->font = NULL;
1492                 fs.fsCsb[0] |= face->fs.fsCsb[0];
1493                 fs.fsCsb[1] |= face->fs.fsCsb[1];
1494                 TRACE("Adding file %s index %ld\n", child_font->face->file, child_font->face->face_index);
1495                 list_add_tail(&font_link->links, &child_font->entry);
1496             }
1497             family = find_family_from_name(font_link->font_name);
1498             if(family)
1499             {
1500                 LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
1501                 {
1502                     memcpy(&face->fs_links, &fs, sizeof(fs));
1503                 }
1504             }
1505             list_add_tail(&system_links, &font_link->entry);
1506             val_len = max_val + 1;
1507             data_len = max_data;
1508         }
1509
1510         HeapFree(GetProcessHeap(), 0, value);
1511         HeapFree(GetProcessHeap(), 0, data);
1512         RegCloseKey(hkey);
1513     }
1514
1515     /* Explicitly add an entry for the system font, this links to Tahoma and any links
1516        that Tahoma has */
1517
1518     system_font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*system_font_link));
1519     system_font_link->font_name = strdupW(System);
1520     list_init(&system_font_link->links);    
1521
1522     face = find_face_from_filename(tahoma_ttf, Tahoma);
1523     if(face)
1524     {
1525         child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
1526         child_font->face = face;
1527         child_font->font = NULL;
1528         TRACE("Found Tahoma in %s index %ld\n", child_font->face->file, child_font->face->face_index);
1529         list_add_tail(&system_font_link->links, &child_font->entry);
1530     }
1531     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
1532     {
1533         if(!strcmpiW(font_link->font_name, Tahoma))
1534         {
1535             CHILD_FONT *font_link_entry;
1536             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
1537             {
1538                 CHILD_FONT *new_child;
1539                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
1540                 new_child->face = font_link_entry->face;
1541                 new_child->font = NULL;
1542                 list_add_tail(&system_font_link->links, &new_child->entry);
1543             }
1544             break;
1545         }
1546     }
1547     list_add_tail(&system_links, &system_font_link->entry);
1548     return ret;
1549 }
1550
1551 static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
1552 {
1553     DIR *dir;
1554     struct dirent *dent;
1555     char path[MAX_PATH];
1556
1557     TRACE("Loading fonts from %s\n", debugstr_a(dirname));
1558
1559     dir = opendir(dirname);
1560     if(!dir) {
1561         WARN("Can't open directory %s\n", debugstr_a(dirname));
1562         return FALSE;
1563     }
1564     while((dent = readdir(dir)) != NULL) {
1565         struct stat statbuf;
1566
1567         if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
1568             continue;
1569
1570         TRACE("Found %s in %s\n", debugstr_a(dent->d_name), debugstr_a(dirname));
1571
1572         sprintf(path, "%s/%s", dirname, dent->d_name);
1573
1574         if(stat(path, &statbuf) == -1)
1575         {
1576             WARN("Can't stat %s\n", debugstr_a(path));
1577             continue;
1578         }
1579         if(S_ISDIR(statbuf.st_mode))
1580             ReadFontDir(path, external_fonts);
1581         else
1582             AddFontFileToList(path, NULL, NULL, external_fonts ? ADDFONT_EXTERNAL_FONT : 0);
1583     }
1584     closedir(dir);
1585     return TRUE;
1586 }
1587
1588 static void load_fontconfig_fonts(void)
1589 {
1590 #ifdef SONAME_LIBFONTCONFIG
1591     void *fc_handle = NULL;
1592     FcConfig *config;
1593     FcPattern *pat;
1594     FcObjectSet *os;
1595     FcFontSet *fontset;
1596     int i, len;
1597     char *file;
1598     const char *ext;
1599
1600     fc_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0);
1601     if(!fc_handle) {
1602         TRACE("Wine cannot find the fontconfig library (%s).\n",
1603               SONAME_LIBFONTCONFIG);
1604         return;
1605     }
1606 #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;}
1607 LOAD_FUNCPTR(FcConfigGetCurrent);
1608 LOAD_FUNCPTR(FcFontList);
1609 LOAD_FUNCPTR(FcFontSetDestroy);
1610 LOAD_FUNCPTR(FcInit);
1611 LOAD_FUNCPTR(FcObjectSetAdd);
1612 LOAD_FUNCPTR(FcObjectSetCreate);
1613 LOAD_FUNCPTR(FcObjectSetDestroy);
1614 LOAD_FUNCPTR(FcPatternCreate);
1615 LOAD_FUNCPTR(FcPatternDestroy);
1616 LOAD_FUNCPTR(FcPatternGetBool);
1617 LOAD_FUNCPTR(FcPatternGetString);
1618 #undef LOAD_FUNCPTR
1619
1620     if(!pFcInit()) return;
1621     
1622     config = pFcConfigGetCurrent();
1623     pat = pFcPatternCreate();
1624     os = pFcObjectSetCreate();
1625     pFcObjectSetAdd(os, FC_FILE);
1626     pFcObjectSetAdd(os, FC_SCALABLE);
1627     fontset = pFcFontList(config, pat, os);
1628     if(!fontset) return;
1629     for(i = 0; i < fontset->nfont; i++) {
1630         FcBool scalable;
1631
1632         if(pFcPatternGetString(fontset->fonts[i], FC_FILE, 0, (FcChar8**)&file) != FcResultMatch)
1633             continue;
1634         TRACE("fontconfig: %s\n", file);
1635
1636         /* We're just interested in OT/TT fonts for now, so this hack just
1637            picks up the scalable fonts without extensions .pf[ab] to save time
1638            loading every other font */
1639
1640         if(pFcPatternGetBool(fontset->fonts[i], FC_SCALABLE, 0, &scalable) == FcResultMatch && !scalable)
1641         {
1642             TRACE("not scalable\n");
1643             continue;
1644         }
1645
1646         len = strlen( file );
1647         if(len < 4) continue;
1648         ext = &file[ len - 3 ];
1649         if(strcasecmp(ext, "pfa") && strcasecmp(ext, "pfb"))
1650             AddFontFileToList(file, NULL, NULL,  ADDFONT_EXTERNAL_FONT);
1651     }
1652     pFcFontSetDestroy(fontset);
1653     pFcObjectSetDestroy(os);
1654     pFcPatternDestroy(pat);
1655  sym_not_found:
1656 #endif
1657     return;
1658 }
1659
1660 static BOOL load_font_from_data_dir(LPCWSTR file)
1661 {
1662     BOOL ret = FALSE;
1663     const char *data_dir = wine_get_data_dir();
1664
1665     if (!data_dir) data_dir = wine_get_build_dir();
1666
1667     if (data_dir)
1668     {
1669         INT len;
1670         char *unix_name;
1671
1672         len = WideCharToMultiByte(CP_UNIXCP, 0, file, -1, NULL, 0, NULL, NULL);
1673
1674         unix_name = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + len + sizeof("/fonts/"));
1675
1676         strcpy(unix_name, data_dir);
1677         strcat(unix_name, "/fonts/");
1678
1679         WideCharToMultiByte(CP_UNIXCP, 0, file, -1, unix_name + strlen(unix_name), len, NULL, NULL);
1680
1681         ret = AddFontFileToList(unix_name, NULL, NULL, ADDFONT_FORCE_BITMAP);
1682         HeapFree(GetProcessHeap(), 0, unix_name);
1683     }
1684     return ret;
1685 }
1686
1687 static BOOL load_font_from_winfonts_dir(LPCWSTR file)
1688 {
1689     static const WCHAR slashW[] = {'\\','\0'};
1690     BOOL ret = FALSE;
1691     WCHAR windowsdir[MAX_PATH];
1692     char *unixname;
1693
1694     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
1695     strcatW(windowsdir, fontsW);
1696     strcatW(windowsdir, slashW);
1697     strcatW(windowsdir, file);
1698     if ((unixname = wine_get_unix_file_name(windowsdir))) {
1699         ret = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
1700         HeapFree(GetProcessHeap(), 0, unixname);
1701     }
1702     return ret;
1703 }
1704
1705 static void load_system_fonts(void)
1706 {
1707     HKEY hkey;
1708     WCHAR data[MAX_PATH], windowsdir[MAX_PATH], pathW[MAX_PATH];
1709     const WCHAR * const *value;
1710     DWORD dlen, type;
1711     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
1712     char *unixname;
1713
1714     if(RegOpenKeyW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, &hkey) == ERROR_SUCCESS) {
1715         GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
1716         strcatW(windowsdir, fontsW);
1717         for(value = SystemFontValues; *value; value++) { 
1718             dlen = sizeof(data);
1719             if(RegQueryValueExW(hkey, *value, 0, &type, (void*)data, &dlen) == ERROR_SUCCESS &&
1720                type == REG_SZ) {
1721                 BOOL added = FALSE;
1722
1723                 sprintfW(pathW, fmtW, windowsdir, data);
1724                 if((unixname = wine_get_unix_file_name(pathW))) {
1725                     added = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
1726                     HeapFree(GetProcessHeap(), 0, unixname);
1727                 }
1728                 if (!added)
1729                     load_font_from_data_dir(data);
1730             }
1731         }
1732         RegCloseKey(hkey);
1733     }
1734 }
1735
1736 /*************************************************************
1737  *
1738  * This adds registry entries for any externally loaded fonts
1739  * (fonts from fontconfig or FontDirs).  It also deletes entries
1740  * of no longer existing fonts.
1741  *
1742  */
1743 static void update_reg_entries(void)
1744 {
1745     HKEY winkey = 0, externalkey = 0;
1746     LPWSTR valueW;
1747     LPVOID data;
1748     DWORD dlen, vlen, datalen, valuelen, i, type, len, len_fam;
1749     Family *family;
1750     Face *face;
1751     struct list *family_elem_ptr, *face_elem_ptr;
1752     WCHAR *file;
1753     static const WCHAR TrueType[] = {' ','(','T','r','u','e','T','y','p','e',')','\0'};
1754     static const WCHAR spaceW[] = {' ', '\0'};
1755     char *path;
1756
1757     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
1758                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &winkey, NULL) != ERROR_SUCCESS) {
1759         ERR("Can't create Windows font reg key\n");
1760         goto end;
1761     }
1762     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\ExternalFonts */
1763     if(RegCreateKeyW(HKEY_CURRENT_USER, external_fonts_reg_key, &externalkey) != ERROR_SUCCESS) {
1764         ERR("Can't create external font reg key\n");
1765         goto end;
1766     }
1767
1768     /* Delete all external fonts added last time */
1769
1770     RegQueryInfoKeyW(externalkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1771                      &valuelen, &datalen, NULL, NULL);
1772     valuelen++; /* returned value doesn't include room for '\0' */
1773     valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
1774     data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
1775
1776     dlen = datalen * sizeof(WCHAR);
1777     vlen = valuelen;
1778     i = 0;
1779     while(RegEnumValueW(externalkey, i++, valueW, &vlen, NULL, &type, data,
1780                         &dlen) == ERROR_SUCCESS) {
1781
1782         RegDeleteValueW(winkey, valueW);
1783         /* reset dlen and vlen */
1784         dlen = datalen;
1785         vlen = valuelen;
1786     }
1787     HeapFree(GetProcessHeap(), 0, data);
1788     HeapFree(GetProcessHeap(), 0, valueW);
1789
1790     /* Delete the old external fonts key */
1791     RegCloseKey(externalkey);
1792     externalkey = 0;
1793     RegDeleteKeyW(HKEY_CURRENT_USER, external_fonts_reg_key);
1794
1795     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\ExternalFonts */
1796     if(RegCreateKeyExW(HKEY_CURRENT_USER, external_fonts_reg_key,
1797                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &externalkey, NULL) != ERROR_SUCCESS) {
1798         ERR("Can't create external font reg key\n");
1799         goto end;
1800     }
1801
1802     /* enumerate the fonts and add external ones to the two keys */
1803
1804     LIST_FOR_EACH(family_elem_ptr, &font_list) {
1805         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
1806         len_fam = strlenW(family->FamilyName) + sizeof(TrueType) / sizeof(WCHAR) + 1;
1807         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
1808             face = LIST_ENTRY(face_elem_ptr, Face, entry);
1809             if(!face->external) continue;
1810             len = len_fam;
1811             if(strcmpiW(face->StyleName, RegularW))
1812                 len = len_fam + strlenW(face->StyleName) + 1;
1813             valueW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1814             strcpyW(valueW, family->FamilyName);
1815             if(len != len_fam) {
1816                 strcatW(valueW, spaceW);
1817                 strcatW(valueW, face->StyleName);
1818             }
1819             strcatW(valueW, TrueType);
1820             if((path = strrchr(face->file, '/')) == NULL)
1821                 path = face->file;
1822             else
1823                 path++;
1824             len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
1825
1826             file = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1827             MultiByteToWideChar(CP_ACP, 0, path, -1, file, len);
1828             RegSetValueExW(winkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
1829             RegSetValueExW(externalkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
1830
1831             HeapFree(GetProcessHeap(), 0, file);
1832             HeapFree(GetProcessHeap(), 0, valueW);
1833         }
1834     }
1835  end:
1836     if(externalkey)
1837         RegCloseKey(externalkey);
1838     if(winkey)
1839         RegCloseKey(winkey);
1840     return;
1841 }
1842
1843
1844 /*************************************************************
1845  *    WineEngAddFontResourceEx
1846  *
1847  */
1848 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
1849 {
1850     INT ret = 0;
1851     if (ft_handle)  /* do it only if we have freetype up and running */
1852     {
1853         char *unixname;
1854
1855         if(flags)
1856             FIXME("Ignoring flags %x\n", flags);
1857
1858         if((unixname = wine_get_unix_file_name(file)))
1859         {
1860             ret = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
1861             HeapFree(GetProcessHeap(), 0, unixname);
1862         }
1863         if (!ret && !strchrW(file, '\\')) {
1864             /* Try in %WINDIR%/fonts, needed for Fotobuch Designer */
1865             ret = load_font_from_winfonts_dir(file);
1866             if (!ret) {
1867                 /* Try in datadir/fonts (or builddir/fonts),
1868                  * needed for Magic the Gathering Online
1869                  */
1870                 ret = load_font_from_data_dir(file);
1871             }
1872         }
1873     }
1874    return ret;
1875 }
1876
1877 /*************************************************************
1878  *    WineEngAddFontMemResourceEx
1879  *
1880  */
1881 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
1882 {
1883     if (ft_handle)  /* do it only if we have freetype up and running */
1884     {
1885         PVOID pFontCopy = HeapAlloc(GetProcessHeap(), 0, cbFont);
1886
1887         TRACE("Copying %d bytes of data from %p to %p\n", cbFont, pbFont, pFontCopy);
1888         memcpy(pFontCopy, pbFont, cbFont);
1889
1890         *pcFonts = AddFontToList(NULL, pFontCopy, cbFont, NULL, NULL, ADDFONT_FORCE_BITMAP);
1891
1892         if (*pcFonts == 0)
1893         {
1894             TRACE("AddFontToList failed\n");
1895             HeapFree(GetProcessHeap(), 0, pFontCopy);
1896             return NULL;
1897         }
1898         /* FIXME: is the handle only for use in RemoveFontMemResourceEx or should it be a true handle?
1899          * For now return something unique but quite random
1900          */
1901         TRACE("Returning handle %lx\n", ((INT_PTR)pFontCopy)^0x87654321);
1902         return (HANDLE)(((INT_PTR)pFontCopy)^0x87654321);
1903     }
1904
1905     *pcFonts = 0;
1906     return 0;
1907 }
1908
1909 /*************************************************************
1910  *    WineEngRemoveFontResourceEx
1911  *
1912  */
1913 BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
1914 {
1915     FIXME(":stub\n");
1916     return TRUE;
1917 }
1918
1919 static const struct nls_update_font_list
1920 {
1921     UINT ansi_cp, oem_cp;
1922     const char *oem, *fixed, *system;
1923     const char *courier, *serif, *small, *sserif;
1924    /* these are for font substitute */
1925     const char *shelldlg, *tmsrmn;
1926 } nls_update_font_list[] =
1927 {
1928     /* Latin 1 (United States) */
1929     { 1252, 437, "vgaoem.fon", "vgafix.fon", "vgasys.fon",
1930       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1931       "Tahoma","Times New Roman",
1932     },
1933     /* Latin 1 (Multilingual) */
1934     { 1252, 850, "vga850.fon", "vgafix.fon", "vgasys.fon",
1935       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1936       "Tahoma","Times New Roman",  /* FIXME unverified */
1937     },
1938     /* Eastern Europe */
1939     { 1250, 852, "vga852.fon", "vgafixe.fon", "vgasyse.fon",
1940       "couree.fon", "serifee.fon", "smallee.fon", "sserifee.fon",
1941       "Tahoma","Times New Roman", /* FIXME unverified */
1942     },
1943     /* Cyrillic */
1944     { 1251, 866, "vga866.fon", "vgafixr.fon", "vgasysr.fon",
1945       "courer.fon", "serifer.fon", "smaller.fon", "sserifer.fon",
1946       "Tahoma","Times New Roman", /* FIXME unverified */
1947     },
1948     /* Greek */
1949     { 1253, 737, "vga869.fon", "vgafixg.fon", "vgasysg.fon",
1950       "coureg.fon", "serifeg.fon", "smalleg.fon", "sserifeg.fon",
1951       "Tahoma","Times New Roman", /* FIXME unverified */
1952     },
1953     /* Turkish */
1954     { 1254, 857, "vga857.fon", "vgafixt.fon", "vgasyst.fon",
1955       "couret.fon", "serifet.fon", "smallet.fon", "sserifet.fon",
1956       "Tahoma","Times New Roman", /* FIXME unverified */
1957     },
1958     /* Hebrew */
1959     { 1255, 862, "vgaoem.fon", "vgaf1255.fon", "vgas1255.fon",
1960       "coue1255.fon", "sere1255.fon", "smae1255.fon", "ssee1255.fon",
1961       "Tahoma","Times New Roman", /* FIXME unverified */
1962     },
1963     /* Arabic */
1964     { 1256, 720, "vgaoem.fon", "vgaf1256.fon", "vgas1256.fon",
1965       "coue1256.fon", "sere1256.fon", "smae1256.fon", "ssee1256.fon",
1966       "Tahoma","Times New Roman", /* FIXME unverified */
1967     },
1968     /* Baltic */
1969     { 1257, 775, "vga775.fon", "vgaf1257.fon", "vgas1257.fon",
1970       "coue1257.fon", "sere1257.fon", "smae1257.fon", "ssee1257.fon",
1971       "Tahoma","Times New Roman", /* FIXME unverified */
1972     },
1973     /* Vietnamese */
1974     { 1258, 1258, "vga850.fon", "vgafix.fon", "vgasys.fon",
1975       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1976       "Tahoma","Times New Roman", /* FIXME unverified */
1977     },
1978     /* Thai */
1979     { 874, 874, "vga850.fon", "vgaf874.fon", "vgas874.fon",
1980       "coure.fon", "serife.fon", "smalle.fon", "ssee874.fon",
1981       "Tahoma","Times New Roman", /* FIXME unverified */
1982     },
1983     /* Japanese */
1984     { 932, 932, "vga932.fon", "jvgafix.fon", "jvgasys.fon",
1985       "coure.fon", "serife.fon", "jsmalle.fon", "sserife.fon",
1986       "MS UI Gothic","MS Serif",
1987     },
1988     /* Chinese Simplified */
1989     { 936, 936, "vga936.fon", "svgafix.fon", "svgasys.fon",
1990       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1991       "Tahoma", "Times New Roman", /* FIXME unverified */
1992     },
1993     /* Korean */
1994     { 949, 949, "vga949.fon", "hvgafix.fon", "hvgasys.fon",
1995       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
1996       "Gulim",  "Batang",
1997     },
1998     /* Chinese Traditional */
1999     { 950, 950, "vga950.fon", "cvgafix.fon", "cvgasys.fon",
2000       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
2001       "Tahoma",  "Times New Roman", /* FIXME unverified */
2002     }
2003 };
2004
2005 static inline HKEY create_fonts_NT_registry_key(void)
2006 {
2007     HKEY hkey = 0;
2008
2009     RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key, 0, NULL,
2010                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2011     return hkey;
2012 }
2013
2014 static inline HKEY create_fonts_9x_registry_key(void)
2015 {
2016     HKEY hkey = 0;
2017
2018     RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key, 0, NULL,
2019                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2020     return hkey;
2021 }
2022
2023 static inline HKEY create_config_fonts_registry_key(void)
2024 {
2025     HKEY hkey = 0;
2026
2027     RegCreateKeyExW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, 0, NULL,
2028                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2029     return hkey;
2030 }
2031
2032 static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl)
2033 {
2034     RegSetValueExA(hkey, "Courier", 0, REG_SZ, (const BYTE *)fl->courier, strlen(fl->courier)+1);
2035     RegSetValueExA(hkey, "MS Serif", 0, REG_SZ, (const BYTE *)fl->serif, strlen(fl->serif)+1);
2036     RegSetValueExA(hkey, "MS Sans Serif", 0, REG_SZ, (const BYTE *)fl->sserif, strlen(fl->sserif)+1);
2037     RegSetValueExA(hkey, "Small Fonts", 0, REG_SZ, (const BYTE *)fl->small, strlen(fl->small)+1);
2038 }
2039
2040 static void update_font_info(void)
2041 {
2042     char buf[40], cpbuf[40];
2043     DWORD len, type;
2044     HKEY hkey = 0;
2045     UINT i, ansi_cp = 0, oem_cp = 0;
2046
2047     if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL) != ERROR_SUCCESS)
2048         return;
2049
2050     GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
2051                    (WCHAR *)&ansi_cp, sizeof(ansi_cp)/sizeof(WCHAR));
2052     GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTCODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
2053                    (WCHAR *)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR));
2054     sprintf( cpbuf, "%u,%u", ansi_cp, oem_cp );
2055
2056     len = sizeof(buf);
2057     if (RegQueryValueExA(hkey, "Codepages", 0, &type, (BYTE *)buf, &len) == ERROR_SUCCESS && type == REG_SZ)
2058     {
2059         if (!strcmp( buf, cpbuf ))  /* already set correctly */
2060         {
2061             RegCloseKey(hkey);
2062             return;
2063         }
2064         TRACE("updating registry, codepages changed %s -> %u,%u\n", buf, ansi_cp, oem_cp);
2065     }
2066     else TRACE("updating registry, codepages changed none -> %u,%u\n", ansi_cp, oem_cp);
2067
2068     RegSetValueExA(hkey, "Codepages", 0, REG_SZ, (const BYTE *)cpbuf, strlen(cpbuf)+1);
2069     RegCloseKey(hkey);
2070
2071     for (i = 0; i < sizeof(nls_update_font_list)/sizeof(nls_update_font_list[0]); i++)
2072     {
2073         if (nls_update_font_list[i].ansi_cp == ansi_cp &&
2074             nls_update_font_list[i].oem_cp == oem_cp)
2075         {
2076             HKEY hkey;
2077
2078             hkey = create_config_fonts_registry_key();
2079             RegSetValueExA(hkey, "OEMFONT.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].oem, strlen(nls_update_font_list[i].oem)+1);
2080             RegSetValueExA(hkey, "FIXEDFON.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].fixed, strlen(nls_update_font_list[i].fixed)+1);
2081             RegSetValueExA(hkey, "FONTS.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].system, strlen(nls_update_font_list[i].system)+1);
2082             RegCloseKey(hkey);
2083
2084             hkey = create_fonts_NT_registry_key();
2085             add_font_list(hkey, &nls_update_font_list[i]);
2086             RegCloseKey(hkey);
2087
2088             hkey = create_fonts_9x_registry_key();
2089             add_font_list(hkey, &nls_update_font_list[i]);
2090             RegCloseKey(hkey);
2091
2092             if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
2093             {
2094                 RegSetValueExA(hkey, "MS Shell Dlg", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].shelldlg,
2095                                strlen(nls_update_font_list[i].shelldlg)+1);
2096                 RegSetValueExA(hkey, "Tms Rmn", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].tmsrmn,
2097                                strlen(nls_update_font_list[i].tmsrmn)+1);
2098                 RegCloseKey(hkey);
2099             }
2100             return;
2101         }
2102     }
2103     FIXME("there is no font defaults for codepages %u,%u\n", ansi_cp, oem_cp);
2104 }
2105
2106 /*************************************************************
2107  *    WineEngInit
2108  *
2109  * Initialize FreeType library and create a list of available faces
2110  */
2111 BOOL WineEngInit(void)
2112 {
2113     static const WCHAR dot_fonW[] = {'.','f','o','n','\0'};
2114     static const WCHAR pathW[] = {'P','a','t','h',0};
2115     HKEY hkey;
2116     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
2117     LPVOID data;
2118     WCHAR windowsdir[MAX_PATH];
2119     char *unixname;
2120     HANDLE font_mutex;
2121     const char *data_dir;
2122
2123     TRACE("\n");
2124
2125     /* update locale dependent font info in registry */
2126     update_font_info();
2127
2128     ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0);
2129     if(!ft_handle) {
2130         WINE_MESSAGE(
2131       "Wine cannot find the FreeType font library.  To enable Wine to\n"
2132       "use TrueType fonts please install a version of FreeType greater than\n"
2133       "or equal to 2.0.5.\n"
2134       "http://www.freetype.org\n");
2135         return FALSE;
2136     }
2137
2138 #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;}
2139
2140     LOAD_FUNCPTR(FT_Vector_Unit)
2141     LOAD_FUNCPTR(FT_Done_Face)
2142     LOAD_FUNCPTR(FT_Get_Char_Index)
2143     LOAD_FUNCPTR(FT_Get_Module)
2144     LOAD_FUNCPTR(FT_Get_Sfnt_Name)
2145     LOAD_FUNCPTR(FT_Get_Sfnt_Name_Count)
2146     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
2147     LOAD_FUNCPTR(FT_Init_FreeType)
2148     LOAD_FUNCPTR(FT_Load_Glyph)
2149     LOAD_FUNCPTR(FT_Matrix_Multiply)
2150     LOAD_FUNCPTR(FT_MulFix)
2151     LOAD_FUNCPTR(FT_New_Face)
2152     LOAD_FUNCPTR(FT_New_Memory_Face)
2153     LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
2154     LOAD_FUNCPTR(FT_Outline_Transform)
2155     LOAD_FUNCPTR(FT_Outline_Translate)
2156     LOAD_FUNCPTR(FT_Select_Charmap)
2157     LOAD_FUNCPTR(FT_Set_Charmap)
2158     LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
2159     LOAD_FUNCPTR(FT_Vector_Transform)
2160
2161 #undef LOAD_FUNCPTR
2162     /* Don't warn if this one is missing */
2163     pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0);
2164     pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0);
2165     pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0);
2166     pFT_Get_Next_Char = wine_dlsym(ft_handle, "FT_Get_Next_Char", NULL, 0);
2167     pFT_Get_TrueType_Engine_Type = wine_dlsym(ft_handle, "FT_Get_TrueType_Engine_Type", NULL, 0);
2168 #ifdef HAVE_FREETYPE_FTWINFNT_H
2169     pFT_Get_WinFNT_Header = wine_dlsym(ft_handle, "FT_Get_WinFNT_Header", NULL, 0);
2170 #endif
2171       if(!wine_dlsym(ft_handle, "FT_Get_Postscript_Name", NULL, 0) &&
2172          !wine_dlsym(ft_handle, "FT_Sqrt64", NULL, 0)) {
2173         /* try to avoid 2.0.4: >= 2.0.5 has FT_Get_Postscript_Name and
2174            <= 2.0.3 has FT_Sqrt64 */
2175           goto sym_not_found;
2176       }
2177
2178     if(pFT_Init_FreeType(&library) != 0) {
2179         ERR("Can't init FreeType library\n");
2180         wine_dlclose(ft_handle, NULL, 0);
2181         ft_handle = NULL;
2182         return FALSE;
2183     }
2184     FT_Version.major=FT_Version.minor=FT_Version.patch=-1;
2185     if (pFT_Library_Version)
2186     {
2187         pFT_Library_Version(library,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
2188     }
2189     if (FT_Version.major<=0)
2190     {
2191         FT_Version.major=2;
2192         FT_Version.minor=0;
2193         FT_Version.patch=5;
2194     }
2195     TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
2196     FT_SimpleVersion = ((FT_Version.major << 16) & 0xff0000) |
2197                        ((FT_Version.minor <<  8) & 0x00ff00) |
2198                        ((FT_Version.patch      ) & 0x0000ff);
2199
2200     if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) {
2201         ERR("Failed to create font mutex\n");
2202         return FALSE;
2203     }
2204     WaitForSingleObject(font_mutex, INFINITE);
2205
2206     /* load the system bitmap fonts */
2207     load_system_fonts();
2208
2209     /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
2210     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
2211     strcatW(windowsdir, fontsW);
2212     if((unixname = wine_get_unix_file_name(windowsdir)))
2213     {
2214         ReadFontDir(unixname, FALSE);
2215         HeapFree(GetProcessHeap(), 0, unixname);
2216     }
2217
2218     /* load the system truetype fonts */
2219     data_dir = wine_get_data_dir();
2220     if (!data_dir) data_dir = wine_get_build_dir();
2221     if (data_dir && (unixname = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + sizeof("/fonts/")))) {
2222         strcpy(unixname, data_dir);
2223         strcat(unixname, "/fonts/");
2224         ReadFontDir(unixname, TRUE);
2225         HeapFree(GetProcessHeap(), 0, unixname);
2226     }
2227
2228     /* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
2229        for any fonts not installed in %WINDOWSDIR%\Fonts.  They will have their
2230        full path as the entry.  Also look for any .fon fonts, since ReadFontDir
2231        will skip these. */
2232     if(RegOpenKeyW(HKEY_LOCAL_MACHINE,
2233                    is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
2234                    &hkey) == ERROR_SUCCESS) {
2235         LPWSTR valueW;
2236         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2237                          &valuelen, &datalen, NULL, NULL);
2238
2239         valuelen++; /* returned value doesn't include room for '\0' */
2240         valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
2241         data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
2242         if (valueW && data)
2243         {
2244             dlen = datalen * sizeof(WCHAR);
2245             vlen = valuelen;
2246             while(RegEnumValueW(hkey, i++, valueW, &vlen, NULL, &type, data,
2247                                 &dlen) == ERROR_SUCCESS) {
2248                 if(((LPWSTR)data)[0] && ((LPWSTR)data)[1] == ':')
2249                 {
2250                     if((unixname = wine_get_unix_file_name((LPWSTR)data)))
2251                     {
2252                         AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
2253                         HeapFree(GetProcessHeap(), 0, unixname);
2254                     }
2255                 }
2256                 else if(dlen / 2 >= 6 && !strcmpiW(((LPWSTR)data) + dlen / 2 - 5, dot_fonW))
2257                 {
2258                     WCHAR pathW[MAX_PATH];
2259                     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
2260                     BOOL added = FALSE;
2261
2262                     sprintfW(pathW, fmtW, windowsdir, data);
2263                     if((unixname = wine_get_unix_file_name(pathW)))
2264                     {
2265                         added = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP);
2266                         HeapFree(GetProcessHeap(), 0, unixname);
2267                     }
2268                     if (!added)
2269                         load_font_from_data_dir(data);
2270                 }
2271                 /* reset dlen and vlen */
2272                 dlen = datalen;
2273                 vlen = valuelen;
2274             }
2275         }
2276         HeapFree(GetProcessHeap(), 0, data);
2277         HeapFree(GetProcessHeap(), 0, valueW);
2278         RegCloseKey(hkey);
2279     }
2280
2281     load_fontconfig_fonts();
2282
2283     /* then look in any directories that we've specified in the config file */
2284     /* @@ Wine registry key: HKCU\Software\Wine\Fonts */
2285     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", &hkey) == ERROR_SUCCESS)
2286     {
2287         DWORD len;
2288         LPWSTR valueW;
2289         LPSTR valueA, ptr;
2290
2291         if (RegQueryValueExW( hkey, pathW, NULL, NULL, NULL, &len ) == ERROR_SUCCESS)
2292         {
2293             len += sizeof(WCHAR);
2294             valueW = HeapAlloc( GetProcessHeap(), 0, len );
2295             if (RegQueryValueExW( hkey, pathW, NULL, NULL, (LPBYTE)valueW, &len ) == ERROR_SUCCESS)
2296             {
2297                 len = WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, NULL, 0, NULL, NULL );
2298                 valueA = HeapAlloc( GetProcessHeap(), 0, len );
2299                 WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, valueA, len, NULL, NULL );
2300                 TRACE( "got font path %s\n", debugstr_a(valueA) );
2301                 ptr = valueA;
2302                 while (ptr)
2303                 {
2304                     LPSTR next = strchr( ptr, ':' );
2305                     if (next) *next++ = 0;
2306                     ReadFontDir( ptr, TRUE );
2307                     ptr = next;
2308                 }
2309                 HeapFree( GetProcessHeap(), 0, valueA );
2310             }
2311             HeapFree( GetProcessHeap(), 0, valueW );
2312         }
2313         RegCloseKey(hkey);
2314     }
2315
2316     DumpFontList();
2317     LoadSubstList();
2318     DumpSubstList();
2319     LoadReplaceList();
2320     update_reg_entries();
2321
2322     init_system_links();
2323     
2324     ReleaseMutex(font_mutex);
2325     return TRUE;
2326 sym_not_found:
2327     WINE_MESSAGE(
2328       "Wine cannot find certain functions that it needs inside the FreeType\n"
2329       "font library.  To enable Wine to use TrueType fonts please upgrade\n"
2330       "FreeType to at least version 2.0.5.\n"
2331       "http://www.freetype.org\n");
2332     wine_dlclose(ft_handle, NULL, 0);
2333     ft_handle = NULL;
2334     return FALSE;
2335 }
2336
2337
2338 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
2339 {
2340     TT_OS2 *pOS2;
2341     TT_HoriHeader *pHori;
2342
2343     LONG ppem;
2344
2345     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
2346     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
2347
2348     if(height == 0) height = 16;
2349
2350     /* Calc. height of EM square:
2351      *
2352      * For +ve lfHeight we have
2353      * lfHeight = (winAscent + winDescent) * ppem / units_per_em
2354      * Re-arranging gives:
2355      * ppem = units_per_em * lfheight / (winAscent + winDescent)
2356      *
2357      * For -ve lfHeight we have
2358      * |lfHeight| = ppem
2359      * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
2360      * with il = winAscent + winDescent - units_per_em]
2361      *
2362      */
2363
2364     if(height > 0) {
2365         if(pOS2->usWinAscent + pOS2->usWinDescent == 0)
2366             ppem = ft_face->units_per_EM * height /
2367                 (pHori->Ascender - pHori->Descender);
2368         else
2369             ppem = ft_face->units_per_EM * height /
2370                 (pOS2->usWinAscent + pOS2->usWinDescent);
2371     }
2372     else
2373         ppem = -height;
2374
2375     return ppem;
2376 }
2377
2378 static struct font_mapping *map_font_file( const char *name )
2379 {
2380     struct font_mapping *mapping;
2381     struct stat st;
2382     int fd;
2383
2384     if ((fd = open( name, O_RDONLY )) == -1) return NULL;
2385     if (fstat( fd, &st ) == -1) goto error;
2386
2387     LIST_FOR_EACH_ENTRY( mapping, &mappings_list, struct font_mapping, entry )
2388     {
2389         if (mapping->dev == st.st_dev && mapping->ino == st.st_ino)
2390         {
2391             mapping->refcount++;
2392             close( fd );
2393             return mapping;
2394         }
2395     }
2396     if (!(mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(*mapping) )))
2397         goto error;
2398
2399     mapping->data = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
2400     close( fd );
2401
2402     if (mapping->data == MAP_FAILED)
2403     {
2404         HeapFree( GetProcessHeap(), 0, mapping );
2405         return NULL;
2406     }
2407     mapping->refcount = 1;
2408     mapping->dev = st.st_dev;
2409     mapping->ino = st.st_ino;
2410     mapping->size = st.st_size;
2411     list_add_tail( &mappings_list, &mapping->entry );
2412     return mapping;
2413
2414 error:
2415     close( fd );
2416     return NULL;
2417 }
2418
2419 static void unmap_font_file( struct font_mapping *mapping )
2420 {
2421     if (!--mapping->refcount)
2422     {
2423         list_remove( &mapping->entry );
2424         munmap( mapping->data, mapping->size );
2425         HeapFree( GetProcessHeap(), 0, mapping );
2426     }
2427 }
2428
2429 static LONG load_VDMX(GdiFont*, LONG);
2430
2431 static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height)
2432 {
2433     FT_Error err;
2434     FT_Face ft_face;
2435     void *data_ptr;
2436     DWORD data_size;
2437
2438     TRACE("%s/%p, %ld, %d x %d\n", debugstr_a(face->file), face->font_data_ptr, face->face_index, width, height);
2439
2440     if (face->file)
2441     {
2442         if (!(font->mapping = map_font_file( face->file )))
2443         {
2444             WARN("failed to map %s\n", debugstr_a(face->file));
2445             return 0;
2446         }
2447         data_ptr = font->mapping->data;
2448         data_size = font->mapping->size;
2449     }
2450     else
2451     {
2452         data_ptr = face->font_data_ptr;
2453         data_size = face->font_data_size;
2454     }
2455
2456     err = pFT_New_Memory_Face(library, data_ptr, data_size, face->face_index, &ft_face);
2457     if(err) {
2458         ERR("FT_New_Face rets %d\n", err);
2459         return 0;
2460     }
2461
2462     /* set it here, as load_VDMX needs it */
2463     font->ft_face = ft_face;
2464
2465     if(FT_IS_SCALABLE(ft_face)) {
2466         /* load the VDMX table if we have one */
2467         font->ppem = load_VDMX(font, height);
2468         if(font->ppem == 0)
2469             font->ppem = calc_ppem_for_height(ft_face, height);
2470
2471         if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0)
2472             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", 0, font->ppem, err);
2473     } else {
2474         if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
2475             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", width, height, err);
2476     }
2477     return ft_face;
2478 }
2479
2480
2481 static int get_nearest_charset(Face *face, int *cp)
2482 {
2483   /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
2484      a single face with the requested charset.  The idea is to check if
2485      the selected font supports the current ANSI codepage, if it does
2486      return the corresponding charset, else return the first charset */
2487
2488     CHARSETINFO csi;
2489     int acp = GetACP(), i;
2490     DWORD fs0;
2491
2492     *cp = acp;
2493     if(TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE))
2494         if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
2495             return csi.ciCharset;
2496
2497     for(i = 0; i < 32; i++) {
2498         fs0 = 1L << i;
2499         if(face->fs.fsCsb[0] & fs0) {
2500             if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG)) {
2501                 *cp = csi.ciACP;
2502                 return csi.ciCharset;
2503             }
2504             else
2505                 FIXME("TCI failing on %x\n", fs0);
2506         }
2507     }
2508
2509     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08x file = %s\n",
2510           face->fs.fsCsb[0], face->file);
2511     *cp = acp;
2512     return DEFAULT_CHARSET;
2513 }
2514
2515 static GdiFont *alloc_font(void)
2516 {
2517     GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
2518     ret->gmsize = 1;
2519     ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM*));
2520     ret->gm[0] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
2521     ret->potm = NULL;
2522     ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
2523     ret->total_kern_pairs = (DWORD)-1;
2524     ret->kern_pairs = NULL;
2525     list_init(&ret->hfontlist);
2526     list_init(&ret->child_fonts);
2527     return ret;
2528 }
2529
2530 static void free_font(GdiFont *font)
2531 {
2532     struct list *cursor, *cursor2;
2533     int i;
2534
2535     LIST_FOR_EACH_SAFE(cursor, cursor2, &font->child_fonts)
2536     {
2537         CHILD_FONT *child = LIST_ENTRY(cursor, CHILD_FONT, entry);
2538         struct list *first_hfont;
2539         HFONTLIST *hfontlist;
2540         list_remove(cursor);
2541         if(child->font)
2542         {
2543             first_hfont = list_head(&child->font->hfontlist);
2544             hfontlist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
2545             DeleteObject(hfontlist->hfont);
2546             HeapFree(GetProcessHeap(), 0, hfontlist);
2547             free_font(child->font);
2548         }
2549         HeapFree(GetProcessHeap(), 0, child);
2550     }
2551
2552     if (font->ft_face) pFT_Done_Face(font->ft_face);
2553     if (font->mapping) unmap_font_file( font->mapping );
2554     HeapFree(GetProcessHeap(), 0, font->kern_pairs);
2555     HeapFree(GetProcessHeap(), 0, font->potm);
2556     HeapFree(GetProcessHeap(), 0, font->name);
2557     for (i = 0; i < font->gmsize; i++)
2558         HeapFree(GetProcessHeap(),0,font->gm[i]);
2559     HeapFree(GetProcessHeap(), 0, font->gm);
2560     HeapFree(GetProcessHeap(), 0, font);
2561 }
2562
2563
2564 /*************************************************************
2565  * load_VDMX
2566  *
2567  * load the vdmx entry for the specified height
2568  */
2569
2570 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
2571           ( ( (FT_ULong)_x4 << 24 ) |     \
2572             ( (FT_ULong)_x3 << 16 ) |     \
2573             ( (FT_ULong)_x2 <<  8 ) |     \
2574               (FT_ULong)_x1         )
2575
2576 #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X')
2577
2578 typedef struct {
2579     BYTE bCharSet;
2580     BYTE xRatio;
2581     BYTE yStartRatio;
2582     BYTE yEndRatio;
2583 } Ratios;
2584
2585 typedef struct {
2586     WORD recs;
2587     BYTE startsz;
2588     BYTE endsz;
2589 } VDMX_group;
2590
2591 static LONG load_VDMX(GdiFont *font, LONG height)
2592 {
2593     WORD hdr[3], tmp;
2594     VDMX_group group;
2595     BYTE devXRatio, devYRatio;
2596     USHORT numRecs, numRatios;
2597     DWORD result, offset = -1;
2598     LONG ppem = 0;
2599     int i;
2600
2601     /* For documentation on VDMX records, see
2602      * http://www.microsoft.com/OpenType/OTSpec/vdmx.htm
2603      */
2604
2605     result = WineEngGetFontData(font, MS_VDMX_TAG, 0, hdr, 6);
2606
2607     if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
2608         return ppem;
2609
2610     /* FIXME: need the real device aspect ratio */
2611     devXRatio = 1;
2612     devYRatio = 1;
2613
2614     numRecs = GET_BE_WORD(hdr[1]);
2615     numRatios = GET_BE_WORD(hdr[2]);
2616
2617     TRACE("numRecs = %d numRatios = %d\n", numRecs, numRatios);
2618     for(i = 0; i < numRatios; i++) {
2619         Ratios ratio;
2620
2621         offset = (3 * 2) + (i * sizeof(Ratios));
2622         WineEngGetFontData(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
2623         offset = -1;
2624
2625         TRACE("Ratios[%d] %d  %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
2626
2627         if((ratio.xRatio == 0 &&
2628             ratio.yStartRatio == 0 &&
2629             ratio.yEndRatio == 0) ||
2630            (devXRatio == ratio.xRatio &&
2631             devYRatio >= ratio.yStartRatio &&
2632             devYRatio <= ratio.yEndRatio))
2633             {
2634                 offset = (3 * 2) + (numRatios * 4) + (i * 2);
2635                 WineEngGetFontData(font, MS_VDMX_TAG, offset, &tmp, 2);
2636                 offset = GET_BE_WORD(tmp);
2637                 break;
2638             }
2639     }
2640
2641     if(offset == -1) {
2642         FIXME("No suitable ratio found\n");
2643         return ppem;
2644     }
2645
2646     if(WineEngGetFontData(font, MS_VDMX_TAG, offset, &group, 4) != GDI_ERROR) {
2647         USHORT recs;
2648         BYTE startsz, endsz;
2649         WORD *vTable;
2650
2651         recs = GET_BE_WORD(group.recs);
2652         startsz = group.startsz;
2653         endsz = group.endsz;
2654
2655         TRACE("recs=%d  startsz=%d  endsz=%d\n", recs, startsz, endsz);
2656
2657         vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6);
2658         result = WineEngGetFontData(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6);
2659         if(result == GDI_ERROR) {
2660             FIXME("Failed to retrieve vTable\n");
2661             goto end;
2662         }
2663
2664         if(height > 0) {
2665             for(i = 0; i < recs; i++) {
2666                 SHORT yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
2667                 SHORT yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
2668                 ppem = GET_BE_WORD(vTable[i * 3]);
2669
2670                 if(yMax + -yMin == height) {
2671                     font->yMax = yMax;
2672                     font->yMin = yMin;
2673                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
2674                     break;
2675                 }
2676                 if(yMax + -yMin > height) {
2677                     if(--i < 0) {
2678                         ppem = 0;
2679                         goto end; /* failed */
2680                     }
2681                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
2682                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
2683                     ppem = GET_BE_WORD(vTable[i * 3]);
2684                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
2685                     break;
2686                 }
2687             }
2688             if(!font->yMax) {
2689                 ppem = 0;
2690                 TRACE("ppem not found for height %d\n", height);
2691             }
2692         } else {
2693             ppem = -height;
2694             if(ppem < startsz || ppem > endsz)
2695                 goto end;
2696
2697             for(i = 0; i < recs; i++) {
2698                 USHORT yPelHeight;
2699                 yPelHeight = GET_BE_WORD(vTable[i * 3]);
2700
2701                 if(yPelHeight > ppem)
2702                     break; /* failed */
2703
2704                 if(yPelHeight == ppem) {
2705                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
2706                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
2707                     TRACE("ppem %d found; yMax=%d  yMin=%d\n", ppem, font->yMax, font->yMin);
2708                     break;
2709                 }
2710             }
2711         }
2712         end:
2713         HeapFree(GetProcessHeap(), 0, vTable);
2714     }
2715
2716     return ppem;
2717 }
2718
2719 static BOOL fontcmp(GdiFont *font, FONT_DESC *fd)
2720 {
2721     if(font->font_desc.hash != fd->hash) return TRUE;
2722     if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE;
2723     if(memcmp(&font->font_desc.lf, &fd->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
2724     if(!font->font_desc.can_use_bitmap != !fd->can_use_bitmap) return TRUE;
2725     return strcmpiW(font->font_desc.lf.lfFaceName, fd->lf.lfFaceName);
2726 }
2727
2728 static void calc_hash(FONT_DESC *pfd)
2729 {
2730     DWORD hash = 0, *ptr, two_chars;
2731     WORD *pwc;
2732     unsigned int i;
2733
2734     for(i = 0, ptr = (DWORD*)&pfd->matrix; i < sizeof(FMAT2)/sizeof(DWORD); i++, ptr++)
2735         hash ^= *ptr;
2736     for(i = 0, ptr = (DWORD*)&pfd->lf; i < 7; i++, ptr++)
2737         hash ^= *ptr;
2738     for(i = 0, ptr = (DWORD*)&pfd->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
2739         two_chars = *ptr;
2740         pwc = (WCHAR *)&two_chars;
2741         if(!*pwc) break;
2742         *pwc = toupperW(*pwc);
2743         pwc++;
2744         *pwc = toupperW(*pwc);
2745         hash ^= two_chars;
2746         if(!*pwc) break;
2747     }
2748     hash ^= !pfd->can_use_bitmap;
2749     pfd->hash = hash;
2750     return;
2751 }
2752
2753 static GdiFont *find_in_cache(HFONT hfont, LOGFONTW *plf, XFORM *pxf, BOOL can_use_bitmap)
2754 {
2755     GdiFont *ret;
2756     FONT_DESC fd;
2757     HFONTLIST *hflist;
2758     struct list *font_elem_ptr, *hfontlist_elem_ptr;
2759
2760     memcpy(&fd.lf, plf, sizeof(LOGFONTW));
2761     memcpy(&fd.matrix, pxf, sizeof(FMAT2));
2762     fd.can_use_bitmap = can_use_bitmap;
2763     calc_hash(&fd);
2764
2765     /* try the in-use list */
2766     LIST_FOR_EACH(font_elem_ptr, &gdi_font_list) {
2767         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2768         if(!fontcmp(ret, &fd)) {
2769             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
2770             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
2771                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
2772                 if(hflist->hfont == hfont)
2773                     return ret;
2774             }
2775             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
2776             hflist->hfont = hfont;
2777             list_add_head(&ret->hfontlist, &hflist->entry);
2778             return ret;
2779         }
2780     }
2781  
2782     /* then the unused list */
2783     font_elem_ptr = list_head(&unused_gdi_font_list);
2784     while(font_elem_ptr) {
2785         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
2786         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
2787         if(!fontcmp(ret, &fd)) {
2788             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
2789             assert(list_empty(&ret->hfontlist));
2790             TRACE("Found %p in unused list\n", ret);
2791             list_remove(&ret->entry);
2792             list_add_head(&gdi_font_list, &ret->entry);
2793             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
2794             hflist->hfont = hfont;
2795             list_add_head(&ret->hfontlist, &hflist->entry);
2796             return ret;
2797         }
2798     }
2799     return NULL;
2800 }
2801
2802     
2803 /*************************************************************
2804  * create_child_font_list
2805  */
2806 static BOOL create_child_font_list(GdiFont *font)
2807 {
2808     BOOL ret = FALSE;
2809     SYSTEM_LINKS *font_link;
2810     CHILD_FONT *font_link_entry, *new_child;
2811
2812     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
2813     {
2814         if(!strcmpW(font_link->font_name, font->name))
2815         {
2816             TRACE("found entry in system list\n");
2817             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
2818             {
2819                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
2820                 new_child->face = font_link_entry->face;
2821                 new_child->font = NULL;
2822                 list_add_tail(&font->child_fonts, &new_child->entry);
2823                 TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
2824             }
2825             ret = TRUE;
2826             break;
2827         }
2828     }
2829
2830     return ret;
2831 }
2832
2833 static BOOL select_charmap(FT_Face ft_face, FT_Encoding encoding)
2834 {
2835     FT_Error ft_err = FT_Err_Invalid_CharMap_Handle;
2836
2837     if (pFT_Set_Charmap)
2838     {
2839         FT_Int i;
2840         FT_CharMap cmap0, cmap1, cmap2, cmap3, cmap_def;
2841
2842         cmap0 = cmap1 = cmap2 = cmap3 = cmap_def = NULL;
2843
2844         for (i = 0; i < ft_face->num_charmaps; i++)
2845         {
2846             if (ft_face->charmaps[i]->encoding == encoding)
2847             {
2848                 TRACE("found cmap with platform_id %u, encoding_id %u\n",
2849                        ft_face->charmaps[i]->platform_id, ft_face->charmaps[i]->encoding_id);
2850
2851                 switch (ft_face->charmaps[i]->platform_id)
2852                 {
2853                     default:
2854                         cmap_def = ft_face->charmaps[i];
2855                         break;
2856                     case 0: /* Apple Unicode */
2857                         cmap0 = ft_face->charmaps[i];
2858                         break;
2859                     case 1: /* Macintosh */
2860                         cmap1 = ft_face->charmaps[i];
2861                         break;
2862                     case 2: /* ISO */
2863                         cmap2 = ft_face->charmaps[i];
2864                         break;
2865                     case 3: /* Microsoft */
2866                         cmap3 = ft_face->charmaps[i];
2867                         break;
2868                 }
2869             }
2870
2871             if (cmap3) /* prefer Microsoft cmap table */
2872                 ft_err = pFT_Set_Charmap(ft_face, cmap3);
2873             else if (cmap1)
2874                 ft_err = pFT_Set_Charmap(ft_face, cmap1);
2875             else if (cmap2)
2876                 ft_err = pFT_Set_Charmap(ft_face, cmap2);
2877             else if (cmap0)
2878                 ft_err = pFT_Set_Charmap(ft_face, cmap0);
2879             else if (cmap_def)
2880                 ft_err = pFT_Set_Charmap(ft_face, cmap_def);
2881         }
2882         return ft_err == FT_Err_Ok;
2883     }
2884
2885     return pFT_Select_Charmap(ft_face, encoding) == FT_Err_Ok;
2886 }
2887
2888 /*************************************************************
2889  * WineEngCreateFontInstance
2890  *
2891  */
2892 GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont)
2893 {
2894     GdiFont *ret;
2895     Face *face, *best, *best_bitmap;
2896     Family *family, *last_resort_family;
2897     struct list *family_elem_ptr, *face_elem_ptr;
2898     INT height, width = 0;
2899     unsigned int score = 0, new_score;
2900     signed int diff = 0, newdiff;
2901     BOOL bd, it, can_use_bitmap;
2902     LOGFONTW lf;
2903     CHARSETINFO csi;
2904     HFONTLIST *hflist;
2905
2906     LIST_FOR_EACH_ENTRY(ret, &child_font_list, struct tagGdiFont, entry)
2907     {
2908         struct list *first_hfont = list_head(&ret->hfontlist);
2909         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
2910         if(hflist->hfont == hfont)
2911             return ret;
2912     }
2913
2914     if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
2915     can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
2916
2917     TRACE("%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n",
2918           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
2919           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
2920           lf.lfEscapement);
2921
2922     /* check the cache first */
2923     if((ret = find_in_cache(hfont, &lf, &dc->xformWorld2Vport, can_use_bitmap)) != NULL) {
2924         TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
2925         return ret;
2926     }
2927
2928     TRACE("not in cache\n");
2929     if(list_empty(&font_list)) /* No fonts installed */
2930     {
2931         TRACE("No fonts installed\n");
2932         return NULL;
2933     }
2934     if(!have_installed_roman_font)
2935     {
2936         TRACE("No roman font installed\n");
2937         return NULL;
2938     }
2939
2940     ret = alloc_font();
2941
2942      memcpy(&ret->font_desc.matrix, &dc->xformWorld2Vport, sizeof(FMAT2));
2943      memcpy(&ret->font_desc.lf, &lf, sizeof(LOGFONTW));
2944      ret->font_desc.can_use_bitmap = can_use_bitmap;
2945      calc_hash(&ret->font_desc);
2946      hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
2947      hflist->hfont = hfont;
2948      list_add_head(&ret->hfontlist, &hflist->entry);
2949
2950
2951     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
2952        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
2953        original value lfCharSet.  Note this is a special case for
2954        Symbol and doesn't happen at least for "Wingdings*" */
2955
2956     if(!strcmpiW(lf.lfFaceName, SymbolW))
2957         lf.lfCharSet = SYMBOL_CHARSET;
2958
2959     if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
2960         switch(lf.lfCharSet) {
2961         case DEFAULT_CHARSET:
2962             csi.fs.fsCsb[0] = 0;
2963             break;
2964         default:
2965             FIXME("Untranslated charset %d\n", lf.lfCharSet);
2966             csi.fs.fsCsb[0] = 0;
2967             break;
2968         }
2969     }
2970
2971     family = NULL;
2972     if(lf.lfFaceName[0] != '\0') {
2973         FontSubst *psub;
2974         SYSTEM_LINKS *font_link;
2975         CHILD_FONT *font_link_entry;
2976
2977         psub = get_font_subst(&font_subst_list, lf.lfFaceName, lf.lfCharSet);
2978
2979         if(psub) {
2980             TRACE("substituting %s -> %s\n", debugstr_w(lf.lfFaceName),
2981                   debugstr_w(psub->to.name));
2982             strcpyW(lf.lfFaceName, psub->to.name);
2983         }
2984
2985         /* We want a match on name and charset or just name if
2986            charset was DEFAULT_CHARSET.  If the latter then
2987            we fixup the returned charset later in get_nearest_charset
2988            where we'll either use the charset of the current ansi codepage
2989            or if that's unavailable the first charset that the font supports.
2990         */
2991         LIST_FOR_EACH(family_elem_ptr, &font_list) {
2992             family = LIST_ENTRY(family_elem_ptr, Family, entry);
2993             if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
2994                 LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
2995                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
2996                     if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
2997                         if(face->scalable || can_use_bitmap)
2998                             goto found;
2999                 }
3000             }
3001         }
3002
3003         /*
3004          * Try check the SystemLink list first for a replacement font.
3005          * We may find good replacements there.
3006          */
3007         LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
3008         {
3009             if(!strcmpiW(font_link->font_name, lf.lfFaceName))
3010             {
3011                 TRACE("found entry in system list\n");
3012                 LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
3013                 {
3014                     face = font_link_entry->face;
3015                     family = face->family;
3016                     if(csi.fs.fsCsb[0] &
3017                         (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]) || !csi.fs.fsCsb[0])
3018                     {
3019                         if(face->scalable || can_use_bitmap)
3020                             goto found;
3021                     }
3022                 }
3023             }
3024         }
3025     }
3026
3027     /* If requested charset was DEFAULT_CHARSET then try using charset
3028        corresponding to the current ansi codepage */
3029     if(!csi.fs.fsCsb[0]) {
3030         INT acp = GetACP();
3031         if(!TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE)) {
3032             FIXME("TCI failed on codepage %d\n", acp);
3033             csi.fs.fsCsb[0] = 0;
3034         } else
3035             lf.lfCharSet = csi.ciCharset;
3036     }
3037
3038     /* Face families are in the top 4 bits of lfPitchAndFamily,
3039        so mask with 0xF0 before testing */
3040
3041     if((lf.lfPitchAndFamily & FIXED_PITCH) ||
3042        (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
3043         strcpyW(lf.lfFaceName, defFixed);
3044     else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
3045         strcpyW(lf.lfFaceName, defSerif);
3046     else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
3047         strcpyW(lf.lfFaceName, defSans);
3048     else
3049         strcpyW(lf.lfFaceName, defSans);
3050     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3051         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3052         if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
3053             LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3054                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
3055                 if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
3056                     if(face->scalable || can_use_bitmap)
3057                         goto found;
3058             }
3059         }
3060     }
3061
3062     last_resort_family = NULL;
3063     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3064         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3065         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3066             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3067             if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) {
3068                 if(face->scalable)
3069                     goto found;
3070                 if(can_use_bitmap && !last_resort_family)
3071                     last_resort_family = family;
3072             }            
3073         }
3074     }
3075
3076     if(last_resort_family) {
3077         family = last_resort_family;
3078         csi.fs.fsCsb[0] = 0;
3079         goto found;
3080     }
3081
3082     LIST_FOR_EACH(family_elem_ptr, &font_list) {
3083         family = LIST_ENTRY(family_elem_ptr, Family, entry);
3084         LIST_FOR_EACH(face_elem_ptr, &family->faces) { 
3085             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3086             if(face->scalable) {
3087                 csi.fs.fsCsb[0] = 0;
3088                 WARN("just using first face for now\n");
3089                 goto found;
3090             }
3091             if(can_use_bitmap && !last_resort_family)
3092                 last_resort_family = family;
3093         }
3094     }
3095     if(!last_resort_family) {
3096         FIXME("can't find a single appropriate font - bailing\n");
3097         free_font(ret);
3098         return NULL;
3099     }
3100
3101     WARN("could only find a bitmap font - this will probably look awful!\n");
3102     family = last_resort_family;
3103     csi.fs.fsCsb[0] = 0;
3104
3105 found:
3106     it = lf.lfItalic ? 1 : 0;
3107     bd = lf.lfWeight > 550 ? 1 : 0;
3108
3109     height = GDI_ROUND( (FLOAT)lf.lfHeight * dc->xformWorld2Vport.eM22 );
3110     height = lf.lfHeight < 0 ? -abs(height) : abs(height);
3111
3112     face = best = best_bitmap = NULL;
3113     LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry)
3114     {
3115         if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
3116         {
3117             new_score = (face->Italic ^ it) + (face->Bold ^ bd);
3118             if(!best || new_score <= score)
3119             {
3120                 TRACE("(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n",
3121                       face->Italic, face->Bold, it, bd);
3122                 score = new_score;
3123                 best = face;
3124                 if(best->scalable  && score == 0) break;
3125                 if(!best->scalable)
3126                 {
3127                     if(height > 0)
3128                         newdiff = height - (signed int)(best->size.height);
3129                     else
3130                         newdiff = -height - ((signed int)(best->size.height) - best->size.internal_leading);
3131                     if(!best_bitmap || new_score < score ||
3132                        (diff > 0 && newdiff < diff && newdiff >= 0) || (diff < 0 && newdiff > diff))
3133                     {
3134                         TRACE("%d is better for %d diff was %d\n", best->size.height, height, diff);
3135                         diff = newdiff;
3136                         best_bitmap = best;
3137                         if(score == 0 && diff == 0) break;
3138                     }
3139                 }
3140             }
3141         }
3142     }
3143     if(best)
3144         face = best->scalable ? best : best_bitmap;
3145     ret->fake_italic = (it && !face->Italic);
3146     ret->fake_bold = (bd && !face->Bold);
3147
3148     memcpy(&ret->fs, &face->fs, sizeof(FONTSIGNATURE));
3149
3150     if(csi.fs.fsCsb[0]) {
3151         ret->charset = lf.lfCharSet;
3152         ret->codepage = csi.ciACP;
3153     }
3154     else
3155         ret->charset = get_nearest_charset(face, &ret->codepage);
3156
3157     TRACE("Chosen: %s %s (%s/%p:%ld)\n", debugstr_w(family->FamilyName),
3158           debugstr_w(face->StyleName), face->file, face->font_data_ptr, face->face_index);
3159
3160     ret->scale_x = 0.0;
3161     ret->scale_y = 0.0;
3162
3163     ret->aveWidth = abs(lf.lfWidth);
3164
3165     if(!face->scalable) {
3166         ret->ppem = face->size.height;
3167         if (height != 0) ret->ppem += diff;
3168
3169         width = face->size.x_ppem >> 6;
3170         height = face->size.y_ppem >> 6;
3171     }
3172     ret->ft_face = OpenFontFace(ret, face, width, height);
3173
3174     if (!ret->ft_face)
3175     {
3176         free_font( ret );
3177         return 0;
3178     }
3179
3180     ret->ntmFlags = face->ntmFlags;
3181
3182     if (ret->charset == SYMBOL_CHARSET && 
3183         select_charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) {
3184         /* No ops */
3185     }
3186     else if (select_charmap(ret->ft_face, FT_ENCODING_UNICODE)) {
3187         /* No ops */
3188     }
3189     else {
3190         select_charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN);
3191     }
3192
3193     ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0;
3194     ret->name = strdupW(family->FamilyName);
3195     ret->underline = lf.lfUnderline ? 0xff : 0;
3196     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
3197     create_child_font_list(ret);
3198
3199     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
3200
3201     list_add_head(&gdi_font_list, &ret->entry);
3202     return ret;
3203 }
3204
3205 static void dump_gdi_font_list(void)
3206 {
3207     GdiFont *gdiFont;
3208     struct list *elem_ptr;
3209
3210     TRACE("---------- gdiFont Cache ----------\n");
3211     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
3212         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
3213         TRACE("gdiFont=%p %s %d\n",
3214               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
3215     }
3216
3217     TRACE("---------- Unused gdiFont Cache ----------\n");
3218     LIST_FOR_EACH(elem_ptr, &unused_gdi_font_list) {
3219         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
3220         TRACE("gdiFont=%p %s %d\n",
3221               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
3222     }
3223 }
3224
3225 /*************************************************************
3226  * WineEngDestroyFontInstance
3227  *
3228  * free the gdiFont associated with this handle
3229  *
3230  */
3231 BOOL WineEngDestroyFontInstance(HFONT handle)
3232 {
3233     GdiFont *gdiFont;
3234     HFONTLIST *hflist;
3235     BOOL ret = FALSE;
3236     struct list *font_elem_ptr, *hfontlist_elem_ptr;
3237     int i = 0;
3238
3239     LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry)
3240     {
3241         struct list *first_hfont = list_head(&gdiFont->hfontlist);
3242         hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
3243         if(hflist->hfont == handle)
3244         {
3245             TRACE("removing child font %p from child list\n", gdiFont);
3246             list_remove(&gdiFont->entry);
3247             return TRUE;
3248         }
3249     }
3250
3251     TRACE("destroying hfont=%p\n", handle);
3252     if(TRACE_ON(font))
3253         dump_gdi_font_list();
3254
3255     font_elem_ptr = list_head(&gdi_font_list);
3256     while(font_elem_ptr) {
3257         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3258         font_elem_ptr = list_next(&gdi_font_list, font_elem_ptr);
3259
3260         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
3261         while(hfontlist_elem_ptr) {
3262             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
3263             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
3264             if(hflist->hfont == handle) {
3265                 list_remove(&hflist->entry);
3266                 HeapFree(GetProcessHeap(), 0, hflist);
3267                 ret = TRUE;
3268             }
3269         }
3270         if(list_empty(&gdiFont->hfontlist)) {
3271             TRACE("Moving to Unused list\n");
3272             list_remove(&gdiFont->entry);
3273             list_add_head(&unused_gdi_font_list, &gdiFont->entry);
3274         }
3275     }
3276
3277
3278     font_elem_ptr = list_head(&unused_gdi_font_list);
3279     while(font_elem_ptr && i++ < UNUSED_CACHE_SIZE)
3280         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
3281     while(font_elem_ptr) {
3282         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
3283         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
3284         TRACE("freeing %p\n", gdiFont);
3285         list_remove(&gdiFont->entry);
3286         free_font(gdiFont);
3287     }
3288     return ret;
3289 }
3290
3291 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
3292                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
3293 {
3294     GdiFont *font;
3295     LONG width, height;
3296
3297     if (face->cached_enum_data)
3298     {
3299         TRACE("Cached\n");
3300         memcpy(pelf, &face->cached_enum_data->elf, sizeof(ENUMLOGFONTEXW));
3301         memcpy(pntm, &face->cached_enum_data->ntm, sizeof(NEWTEXTMETRICEXW));
3302         *ptype = face->cached_enum_data->type;
3303         return;
3304     }
3305
3306     font = alloc_font();
3307
3308     if(face->scalable) {
3309         height = 100;
3310         width = 0;
3311     } else {
3312         height = face->size.y_ppem >> 6;
3313         width = face->size.x_ppem >> 6;
3314     }
3315     
3316     if (!(font->ft_face = OpenFontFace(font, face, width, height)))
3317     {
3318         free_font(font);
3319         return;
3320     }
3321
3322     font->name = strdupW(face->family->FamilyName);
3323     font->ntmFlags = face->ntmFlags;
3324
3325     if (WineEngGetOutlineTextMetrics(font, 0, NULL))
3326     {
3327         memcpy(&pntm->ntmTm, &font->potm->otmTextMetrics, sizeof(TEXTMETRICW));
3328
3329         pntm->ntmTm.ntmSizeEM = font->potm->otmEMSquare;
3330
3331         lstrcpynW(pelf->elfLogFont.lfFaceName,
3332                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFamilyName),
3333                  LF_FACESIZE);
3334         lstrcpynW(pelf->elfFullName,
3335                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFaceName),
3336                  LF_FULLFACESIZE);
3337         lstrcpynW(pelf->elfStyle,
3338                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpStyleName),
3339                  LF_FACESIZE);
3340     }
3341     else
3342     {
3343         WineEngGetTextMetrics(font, (TEXTMETRICW *)&pntm->ntmTm);
3344
3345         pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
3346
3347         lstrcpynW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
3348         lstrcpynW(pelf->elfFullName, face->family->FamilyName, LF_FULLFACESIZE);
3349         lstrcpynW(pelf->elfStyle, face->StyleName, LF_FACESIZE);
3350     }
3351
3352     pntm->ntmTm.ntmFlags = face->ntmFlags;
3353     pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
3354     pntm->ntmTm.ntmAvgWidth = pntm->ntmTm.tmAveCharWidth;
3355     memcpy(&pntm->ntmFontSig, &face->fs, sizeof(FONTSIGNATURE));
3356
3357     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
3358
3359     pelf->elfLogFont.lfEscapement = 0;
3360     pelf->elfLogFont.lfOrientation = 0;
3361     pelf->elfLogFont.lfHeight = pntm->ntmTm.tmHeight;
3362     pelf->elfLogFont.lfWidth = pntm->ntmTm.tmAveCharWidth;
3363     pelf->elfLogFont.lfWeight = pntm->ntmTm.tmWeight;
3364     pelf->elfLogFont.lfItalic = pntm->ntmTm.tmItalic;
3365     pelf->elfLogFont.lfUnderline = pntm->ntmTm.tmUnderlined;
3366     pelf->elfLogFont.lfStrikeOut = pntm->ntmTm.tmStruckOut;
3367     pelf->elfLogFont.lfCharSet = pntm->ntmTm.tmCharSet;
3368     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
3369     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
3370     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
3371     pelf->elfLogFont.lfPitchAndFamily = (pntm->ntmTm.tmPitchAndFamily & 0xf1) + 1;
3372
3373     *ptype = 0;
3374     if (pntm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE)
3375         *ptype |= TRUETYPE_FONTTYPE;
3376     if (pntm->ntmTm.tmPitchAndFamily & TMPF_DEVICE)
3377         *ptype |= DEVICE_FONTTYPE;
3378     if(!(pntm->ntmTm.tmPitchAndFamily & TMPF_VECTOR))
3379         *ptype |= RASTER_FONTTYPE;
3380
3381     face->cached_enum_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*face->cached_enum_data));
3382     if (face->cached_enum_data)
3383     {
3384         memcpy(&face->cached_enum_data->elf, pelf, sizeof(ENUMLOGFONTEXW));
3385         memcpy(&face->cached_enum_data->ntm, pntm, sizeof(NEWTEXTMETRICEXW));
3386         face->cached_enum_data->type = *ptype;
3387     }
3388
3389     free_font(font);
3390 }
3391
3392 /*************************************************************
3393  * WineEngEnumFonts
3394  *
3395  */
3396 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
3397 {
3398     Family *family;
3399     Face *face;
3400     struct list *family_elem_ptr, *face_elem_ptr;
3401     ENUMLOGFONTEXW elf;
3402     NEWTEXTMETRICEXW ntm;
3403     DWORD type, ret = 1;
3404     FONTSIGNATURE fs;
3405     CHARSETINFO csi;
3406     LOGFONTW lf;
3407     int i;
3408
3409     if (!plf)
3410     {
3411         lf.lfCharSet = DEFAULT_CHARSET;
3412         lf.lfPitchAndFamily = 0;
3413         lf.lfFaceName[0] = 0;
3414         plf = &lf;
3415     }
3416
3417     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
3418
3419     if(plf->lfFaceName[0]) {
3420         FontSubst *psub;
3421         psub = get_font_subst(&font_subst_list, plf->lfFaceName, plf->lfCharSet);
3422
3423         if(psub) {
3424             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
3425                   debugstr_w(psub->to.name));
3426             memcpy(&lf, plf, sizeof(lf));
3427             strcpyW(lf.lfFaceName, psub->to.name);
3428             plf = &lf;
3429         }
3430
3431         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3432             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3433             if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
3434                 LIST_FOR_EACH(face_elem_ptr, &family->faces) {
3435                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
3436                     GetEnumStructs(face, &elf, &ntm, &type);
3437                     for(i = 0; i < 32; i++) {
3438                         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
3439                             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
3440                             strcpyW(elf.elfScript, OEM_DOSW);
3441                             i = 32; /* break out of loop */
3442                         } else if(!(face->fs.fsCsb[0] & (1L << i)))
3443                             continue;
3444                         else {
3445                             fs.fsCsb[0] = 1L << i;
3446                             fs.fsCsb[1] = 0;
3447                             if(!TranslateCharsetInfo(fs.fsCsb, &csi,
3448                                                      TCI_SRCFONTSIG))
3449                                 csi.ciCharset = DEFAULT_CHARSET;
3450                             if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
3451                             if(csi.ciCharset != DEFAULT_CHARSET) {
3452                                 elf.elfLogFont.lfCharSet =
3453                                     ntm.ntmTm.tmCharSet = csi.ciCharset;
3454                                 if(ElfScriptsW[i])
3455                                     strcpyW(elf.elfScript, ElfScriptsW[i]);
3456                                 else
3457                                     FIXME("Unknown elfscript for bit %d\n", i);
3458                             }
3459                         }
3460                         TRACE("enuming face %s full %s style %s charset %d type %d script %s it %d weight %d ntmflags %08x\n",
3461                               debugstr_w(elf.elfLogFont.lfFaceName),
3462                               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
3463                               csi.ciCharset, type, debugstr_w(elf.elfScript),
3464                               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
3465                               ntm.ntmTm.ntmFlags);
3466                         ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
3467                         if(!ret) goto end;
3468                     }
3469                 }
3470             }
3471         }
3472     } else {
3473         LIST_FOR_EACH(family_elem_ptr, &font_list) {
3474             family = LIST_ENTRY(family_elem_ptr, Family, entry);
3475             face_elem_ptr = list_head(&family->faces);
3476             face = LIST_ENTRY(face_elem_ptr, Face, entry);
3477             GetEnumStructs(face, &elf, &ntm, &type);
3478             for(i = 0; i < 32; i++) {
3479                 if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
3480                     elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
3481                     strcpyW(elf.elfScript, OEM_DOSW);
3482                     i = 32; /* break out of loop */
3483                 } else if(!(face->fs.fsCsb[0] & (1L << i)))
3484                     continue;
3485                 else {
3486                     fs.fsCsb[0] = 1L << i;
3487                     fs.fsCsb[1] = 0;
3488                     if(!TranslateCharsetInfo(fs.fsCsb, &csi,
3489                                              TCI_SRCFONTSIG))
3490                         csi.ciCharset = DEFAULT_CHARSET;
3491                     if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
3492                     if(csi.ciCharset != DEFAULT_CHARSET) {
3493                         elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet =
3494                           csi.ciCharset;
3495                           if(ElfScriptsW[i])
3496                               strcpyW(elf.elfScript, ElfScriptsW[i]);
3497                           else
3498                               FIXME("Unknown elfscript for bit %d\n", i);
3499                     }
3500                 }
3501                 TRACE("enuming face %s full %s style %s charset = %d type %d script %s it %d weight %d ntmflags %08x\n",
3502                       debugstr_w(elf.elfLogFont.lfFaceName),
3503                       debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
3504                       csi.ciCharset, type, debugstr_w(elf.elfScript),
3505                       elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
3506                       ntm.ntmTm.ntmFlags);
3507                 ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
3508                 if(!ret) goto end;
3509             }
3510         }
3511     }
3512 end:
3513     return ret;
3514 }
3515
3516 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
3517 {
3518     pt->x.value = vec->x >> 6;
3519     pt->x.fract = (vec->x & 0x3f) << 10;
3520     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
3521     pt->y.value = vec->y >> 6;
3522     pt->y.fract = (vec->y & 0x3f) << 10;
3523     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
3524     return;
3525 }
3526
3527 /***************************************************
3528  * According to the MSDN documentation on WideCharToMultiByte,
3529  * certain codepages cannot set the default_used parameter.
3530  * This returns TRUE if the codepage can set that parameter, false else
3531  * so that calls to WideCharToMultiByte don't fail with ERROR_INVALID_PARAMETER
3532  */
3533 static BOOL codepage_sets_default_used(UINT codepage)
3534 {
3535    switch (codepage)
3536    {
3537        case CP_UTF7:
3538        case CP_UTF8:
3539        case CP_SYMBOL:
3540            return FALSE;
3541        default:
3542            return TRUE;
3543    }
3544 }
3545
3546 static FT_UInt get_glyph_index(GdiFont *font, UINT glyph)
3547 {
3548     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
3549         WCHAR wc = (WCHAR)glyph;
3550         BOOL default_used;
3551         BOOL *default_used_pointer;
3552         FT_UInt ret;
3553         char buf;
3554         default_used_pointer = NULL;
3555         default_used = FALSE;
3556         if (codepage_sets_default_used(font->codepage))
3557             default_used_pointer = &default_used;
3558         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
3559             ret = 0;
3560         else
3561             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
3562         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
3563         return ret;
3564     }
3565
3566     if(font->charset == SYMBOL_CHARSET && glyph < 0x100)
3567         glyph = glyph + 0xf000;
3568     return pFT_Get_Char_Index(font->ft_face, glyph);
3569 }
3570
3571 /*************************************************************
3572  * WineEngGetGlyphIndices
3573  *
3574  * FIXME: add support for GGI_MARK_NONEXISTING_GLYPHS
3575  */
3576 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
3577                                 LPWORD pgi, DWORD flags)
3578 {
3579     int i;
3580     WCHAR default_char = 0;
3581     TEXTMETRICW textm;
3582
3583     if  (flags & GGI_MARK_NONEXISTING_GLYPHS) default_char = 0x001f;  /* Indicate non existence */
3584
3585     for(i = 0; i < count; i++)
3586     {
3587         pgi[i] = get_glyph_index(font, lpstr[i]);
3588         if  (pgi[i] == 0)
3589         {
3590             if (!default_char)
3591             {
3592                 WineEngGetTextMetrics(font, &textm);
3593                 default_char = textm.tmDefaultChar;
3594             }
3595             pgi[i] = default_char;
3596         }
3597     }
3598     return count;
3599 }
3600
3601 /*************************************************************
3602  * WineEngGetGlyphOutline
3603  *
3604  * Behaves in exactly the same way as the win32 api GetGlyphOutline
3605  * except that the first parameter is the HWINEENGFONT of the font in
3606  * question rather than an HDC.
3607  *
3608  */
3609 DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
3610                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
3611                              const MAT2* lpmat)
3612 {
3613     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
3614     FT_Face ft_face = incoming_font->ft_face;
3615     GdiFont *font = incoming_font;
3616     FT_UInt glyph_index;
3617     DWORD width, height, pitch, needed = 0;
3618     FT_Bitmap ft_bitmap;
3619     FT_Error err;
3620     INT left, right, top = 0, bottom = 0, adv, lsb, bbx;
3621     FT_Angle angle = 0;
3622     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
3623     float widthRatio = 1.0, heightRatio = 1.0;
3624     FT_Matrix transMat = identityMat;
3625     BOOL needsTransform = FALSE;
3626
3627
3628     TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
3629           buflen, buf, lpmat);
3630
3631     if(format & GGO_GLYPH_INDEX) {
3632         glyph_index = glyph;
3633         format &= ~GGO_GLYPH_INDEX;
3634     } else {
3635         get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index);
3636         ft_face = font->ft_face;
3637     }
3638
3639     if(glyph_index >= font->gmsize * GM_BLOCK_SIZE) {
3640         font->gmsize = (glyph_index / GM_BLOCK_SIZE + 1);
3641         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
3642                                font->gmsize * sizeof(GM*));
3643     } else {
3644         if(format == GGO_METRICS && font->gm[glyph_index / GM_BLOCK_SIZE] != NULL && FONT_GM(font,glyph_index)->init ) {
3645             *lpgm = FONT_GM(font,glyph_index)->gm;
3646             return 1; /* FIXME */
3647         }
3648     }
3649
3650     if (!font->gm[glyph_index / GM_BLOCK_SIZE])
3651         font->gm[glyph_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
3652
3653     if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP && format != WINE_GGO_GRAY16_BITMAP) || lpmat)
3654         load_flags |= FT_LOAD_NO_BITMAP;
3655
3656     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
3657
3658     if(err) {
3659         WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
3660         return GDI_ERROR;
3661     }
3662         
3663     /* Scaling factor */
3664     if (font->scale_x != 0.0)
3665     {
3666         widthRatio = font->scale_x;
3667         heightRatio = font->scale_y;
3668     }
3669
3670     left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
3671     right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
3672
3673     adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
3674     lsb = left >> 6;
3675     bbx = (right - left) >> 6;
3676
3677     /* Scaling transform */
3678     if(font->aveWidth) {
3679         FT_Matrix scaleMat;
3680         scaleMat.xx = FT_FixedFromFloat(widthRatio);
3681         scaleMat.xy = 0;
3682         scaleMat.yx = 0;
3683         scaleMat.yy = FT_FixedFromFloat(heightRatio);
3684
3685         pFT_Matrix_Multiply(&scaleMat, &transMat);
3686         needsTransform = TRUE;
3687     }
3688
3689     /* Slant transform */
3690     if (font->fake_italic) {
3691         FT_Matrix slantMat;
3692         
3693         slantMat.xx = (1 << 16);
3694         slantMat.xy = ((1 << 16) >> 2);
3695         slantMat.yx = 0;
3696         slantMat.yy = (1 << 16);
3697         pFT_Matrix_Multiply(&slantMat, &transMat);
3698         needsTransform = TRUE;
3699     }
3700
3701     /* Rotation transform */
3702     if(font->orientation) {
3703         FT_Matrix rotationMat;
3704         FT_Vector vecAngle;
3705         angle = FT_FixedFromFloat((float)font->orientation / 10.0);
3706         pFT_Vector_Unit(&vecAngle, angle);
3707         rotationMat.xx = vecAngle.x;
3708         rotationMat.xy = -vecAngle.y;
3709         rotationMat.yx = -rotationMat.xy;
3710         rotationMat.yy = rotationMat.xx;
3711         
3712         pFT_Matrix_Multiply(&rotationMat, &transMat);
3713         needsTransform = TRUE;
3714     }
3715
3716     /* Extra transformation specified by caller */
3717     if (lpmat) {
3718         FT_Matrix extraMat;
3719         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
3720         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
3721         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
3722         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
3723         pFT_Matrix_Multiply(&extraMat, &transMat);
3724         needsTransform = TRUE;
3725     }
3726
3727     if(!needsTransform) {
3728         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
3729         bottom = (ft_face->glyph->metrics.horiBearingY -
3730                   ft_face->glyph->metrics.height) & -64;
3731         lpgm->gmCellIncX = adv;
3732         lpgm->gmCellIncY = 0;
3733     } else {
3734         INT xc, yc;
3735         FT_Vector vec;
3736         for(xc = 0; xc < 2; xc++) {
3737             for(yc = 0; yc < 2; yc++) {
3738                 vec.x = (ft_face->glyph->metrics.horiBearingX +
3739                   xc * ft_face->glyph->metrics.width);
3740                 vec.y = ft_face->glyph->metrics.horiBearingY -
3741                   yc * ft_face->glyph->metrics.height;
3742                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
3743                 pFT_Vector_Transform(&vec, &transMat);
3744                 if(xc == 0 && yc == 0) {
3745                     left = right = vec.x;
3746                     top = bottom = vec.y;
3747                 } else {
3748                     if(vec.x < left) left = vec.x;
3749                     else if(vec.x > right) right = vec.x;
3750                     if(vec.y < bottom) bottom = vec.y;
3751                     else if(vec.y > top) top = vec.y;
3752                 }
3753             }
3754         }
3755         left = left & -64;
3756         right = (right + 63) & -64;
3757         bottom = bottom & -64;
3758         top = (top + 63) & -64;
3759
3760         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
3761         vec.x = ft_face->glyph->metrics.horiAdvance;
3762         vec.y = 0;
3763         pFT_Vector_Transform(&vec, &transMat);
3764         lpgm->gmCellIncX = (vec.x+63) >> 6;
3765         lpgm->gmCellIncY = -((vec.y+63) >> 6);
3766     }
3767     lpgm->gmBlackBoxX = (right - left) >> 6;
3768     lpgm->gmBlackBoxY = (top - bottom) >> 6;
3769     lpgm->gmptGlyphOrigin.x = left >> 6;
3770     lpgm->gmptGlyphOrigin.y = top >> 6;
3771
3772     if(format == GGO_METRICS || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP)
3773     {
3774         FONT_GM(font,glyph_index)->gm = *lpgm;
3775         FONT_GM(font,glyph_index)->adv = adv;
3776         FONT_GM(font,glyph_index)->lsb = lsb;
3777         FONT_GM(font,glyph_index)->bbx = bbx;
3778         FONT_GM(font,glyph_index)->init = TRUE;
3779     }
3780
3781     if(format == GGO_METRICS)
3782         return 1; /* FIXME */
3783
3784     if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP && format != WINE_GGO_GRAY16_BITMAP) {
3785         TRACE("loaded a bitmap\n");
3786         return GDI_ERROR;
3787     }
3788
3789     switch(format) {
3790     case GGO_BITMAP:
3791         width = lpgm->gmBlackBoxX;
3792         height = lpgm->gmBlackBoxY;
3793         pitch = ((width + 31) >> 5) << 2;
3794         needed = pitch * height;
3795
3796         if(!buf || !buflen) break;
3797
3798         switch(ft_face->glyph->format) {
3799         case ft_glyph_format_bitmap:
3800           {
3801             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
3802             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
3803             INT h = ft_face->glyph->bitmap.rows;
3804             while(h--) {
3805                 memcpy(dst, src, w);
3806                 src += ft_face->glyph->bitmap.pitch;
3807                 dst += pitch;
3808             }
3809             break;
3810           }
3811
3812         case ft_glyph_format_outline:
3813             ft_bitmap.width = width;
3814             ft_bitmap.rows = height;
3815             ft_bitmap.pitch = pitch;
3816             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
3817             ft_bitmap.buffer = buf;
3818
3819                 if(needsTransform) {
3820                         pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
3821             }
3822
3823             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
3824
3825             /* Note: FreeType will only set 'black' bits for us. */
3826             memset(buf, 0, needed);
3827             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
3828             break;
3829
3830         default:
3831             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
3832             return GDI_ERROR;
3833         }
3834         break;
3835
3836     case GGO_GRAY2_BITMAP:
3837     case GGO_GRAY4_BITMAP:
3838     case GGO_GRAY8_BITMAP:
3839     case WINE_GGO_GRAY16_BITMAP:
3840       {
3841         unsigned int mult, row, col;
3842         BYTE *start, *ptr;
3843
3844         width = lpgm->gmBlackBoxX;
3845         height = lpgm->gmBlackBoxY;
3846         pitch = (width + 3) / 4 * 4;
3847         needed = pitch * height;
3848
3849         if(!buf || !buflen) break;
3850
3851         switch(ft_face->glyph->format) {
3852         case ft_glyph_format_bitmap:
3853           {
3854             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
3855             INT h = ft_face->glyph->bitmap.rows;
3856             INT x;
3857             while(h--) {
3858                 for(x = 0; x < pitch; x++)
3859                     dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0;
3860                 src += ft_face->glyph->bitmap.pitch;
3861                 dst += pitch;
3862             }
3863             return needed;
3864           }
3865         case ft_glyph_format_outline:
3866           {
3867             ft_bitmap.width = width;
3868             ft_bitmap.rows = height;
3869             ft_bitmap.pitch = pitch;
3870             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
3871             ft_bitmap.buffer = buf;
3872
3873             if(needsTransform)
3874                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
3875
3876             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
3877
3878             memset(ft_bitmap.buffer, 0, buflen);
3879
3880             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
3881
3882             if(format == GGO_GRAY2_BITMAP)
3883                 mult = 4;
3884             else if(format == GGO_GRAY4_BITMAP)
3885                 mult = 16;
3886             else if(format == GGO_GRAY8_BITMAP)
3887                 mult = 64;
3888             else /* format == WINE_GGO_GRAY16_BITMAP */
3889                 return needed;
3890
3891             break;
3892           }
3893         default:
3894             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
3895             return GDI_ERROR;
3896         }
3897
3898         start = buf;
3899         for(row = 0; row < height; row++) {
3900             ptr = start;
3901             for(col = 0; col < width; col++, ptr++) {
3902                 *ptr = (((int)*ptr) * mult + 128) / 256;
3903             }
3904             start += pitch;
3905         }
3906         break;
3907       }
3908
3909     case GGO_NATIVE:
3910       {
3911         int contour, point = 0, first_pt;
3912         FT_Outline *outline = &ft_face->glyph->outline;
3913         TTPOLYGONHEADER *pph;
3914         TTPOLYCURVE *ppc;
3915         DWORD pph_start, cpfx, type;
3916
3917         if(buflen == 0) buf = NULL;
3918
3919         if (needsTransform && buf) {
3920                 pFT_Outline_Transform(outline, &transMat);
3921         }
3922
3923         for(contour = 0; contour < outline->n_contours; contour++) {
3924             pph_start = needed;
3925             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
3926             first_pt = point;
3927             if(buf) {
3928                 pph->dwType = TT_POLYGON_TYPE;
3929                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3930             }
3931             needed += sizeof(*pph);
3932             point++;
3933             while(point <= outline->contours[contour]) {
3934                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
3935                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3936                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
3937                 cpfx = 0;
3938                 do {
3939                     if(buf)
3940                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3941                     cpfx++;
3942                     point++;
3943                 } while(point <= outline->contours[contour] &&
3944                         (outline->tags[point] & FT_Curve_Tag_On) ==
3945                         (outline->tags[point-1] & FT_Curve_Tag_On));
3946                 /* At the end of a contour Windows adds the start point, but
3947                    only for Beziers */
3948                 if(point > outline->contours[contour] &&
3949                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
3950                     if(buf)
3951                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
3952                     cpfx++;
3953                 } else if(point <= outline->contours[contour] &&
3954                           outline->tags[point] & FT_Curve_Tag_On) {
3955                   /* add closing pt for bezier */
3956                     if(buf)
3957                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3958                     cpfx++;
3959                     point++;
3960                 }
3961                 if(buf) {
3962                     ppc->wType = type;
3963                     ppc->cpfx = cpfx;
3964                 }
3965                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3966             }
3967             if(buf)
3968                 pph->cb = needed - pph_start;
3969         }
3970         break;
3971       }
3972     case GGO_BEZIER:
3973       {
3974         /* Convert the quadratic Beziers to cubic Beziers.
3975            The parametric eqn for a cubic Bezier is, from PLRM:
3976            r(t) = at^3 + bt^2 + ct + r0
3977            with the control points:
3978            r1 = r0 + c/3
3979            r2 = r1 + (c + b)/3
3980            r3 = r0 + c + b + a
3981
3982            A quadratic Beizer has the form:
3983            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
3984
3985            So equating powers of t leads to:
3986            r1 = 2/3 p1 + 1/3 p0
3987            r2 = 2/3 p1 + 1/3 p2
3988            and of course r0 = p0, r3 = p2
3989         */
3990
3991         int contour, point = 0, first_pt;
3992         FT_Outline *outline = &ft_face->glyph->outline;
3993         TTPOLYGONHEADER *pph;
3994         TTPOLYCURVE *ppc;
3995         DWORD pph_start, cpfx, type;
3996         FT_Vector cubic_control[4];
3997         if(buflen == 0) buf = NULL;
3998
3999         if (needsTransform && buf) {
4000                 pFT_Outline_Transform(outline, &transMat);
4001         }
4002
4003         for(contour = 0; contour < outline->n_contours; contour++) {
4004             pph_start = needed;
4005             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
4006             first_pt = point;
4007             if(buf) {
4008                 pph->dwType = TT_POLYGON_TYPE;
4009                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
4010             }
4011             needed += sizeof(*pph);
4012             point++;
4013             while(point <= outline->contours[contour]) {
4014                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
4015                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
4016                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
4017                 cpfx = 0;
4018                 do {
4019                     if(type == TT_PRIM_LINE) {
4020                         if(buf)
4021                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4022                         cpfx++;
4023                         point++;
4024                     } else {
4025                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
4026                          so cpfx = 3n */
4027
4028                       /* FIXME: Possible optimization in endpoint calculation
4029                          if there are two consecutive curves */
4030                         cubic_control[0] = outline->points[point-1];
4031                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
4032                             cubic_control[0].x += outline->points[point].x + 1;
4033                             cubic_control[0].y += outline->points[point].y + 1;
4034                             cubic_control[0].x >>= 1;
4035                             cubic_control[0].y >>= 1;
4036                         }
4037                         if(point+1 > outline->contours[contour])
4038                             cubic_control[3] = outline->points[first_pt];
4039                         else {
4040                             cubic_control[3] = outline->points[point+1];
4041                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
4042                                 cubic_control[3].x += outline->points[point].x + 1;
4043                                 cubic_control[3].y += outline->points[point].y + 1;
4044                                 cubic_control[3].x >>= 1;
4045                                 cubic_control[3].y >>= 1;
4046                             }
4047                         }
4048                         /* r1 = 1/3 p0 + 2/3 p1
4049                            r2 = 1/3 p2 + 2/3 p1 */
4050                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
4051                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
4052                         cubic_control[2] = cubic_control[1];
4053                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
4054                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
4055                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
4056                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
4057                         if(buf) {
4058                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
4059                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
4060                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
4061                         }
4062                         cpfx += 3;
4063                         point++;
4064                     }
4065                 } while(point <= outline->contours[contour] &&
4066                         (outline->tags[point] & FT_Curve_Tag_On) ==
4067                         (outline->tags[point-1] & FT_Curve_Tag_On));
4068                 /* At the end of a contour Windows adds the start point,
4069                    but only for Beziers and we've already done that.
4070                 */
4071                 if(point <= outline->contours[contour] &&
4072                    outline->tags[point] & FT_Curve_Tag_On) {
4073                   /* This is the closing pt of a bezier, but we've already
4074                      added it, so just inc point and carry on */
4075                     point++;
4076                 }
4077                 if(buf) {
4078                     ppc->wType = type;
4079                     ppc->cpfx = cpfx;
4080                 }
4081                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
4082             }
4083             if(buf)
4084                 pph->cb = needed - pph_start;
4085         }
4086         break;
4087       }
4088
4089     default:
4090         FIXME("Unsupported format %d\n", format);
4091         return GDI_ERROR;
4092     }
4093     return needed;
4094 }
4095
4096 static BOOL get_bitmap_text_metrics(GdiFont *font)
4097 {
4098     FT_Face ft_face = font->ft_face;
4099 #ifdef HAVE_FREETYPE_FTWINFNT_H
4100     FT_WinFNT_HeaderRec winfnt_header;
4101 #endif
4102     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
4103     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
4104     font->potm->otmSize = size;
4105
4106 #define TM font->potm->otmTextMetrics
4107 #ifdef HAVE_FREETYPE_FTWINFNT_H
4108     if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
4109     {
4110         TM.tmHeight = winfnt_header.pixel_height;
4111         TM.tmAscent = winfnt_header.ascent;
4112         TM.tmDescent = TM.tmHeight - TM.tmAscent;
4113         TM.tmInternalLeading = winfnt_header.internal_leading;
4114         TM.tmExternalLeading = winfnt_header.external_leading;
4115         TM.tmAveCharWidth = winfnt_header.avg_width;
4116         TM.tmMaxCharWidth = winfnt_header.max_width;
4117         TM.tmWeight = winfnt_header.weight;
4118         TM.tmOverhang = 0;
4119         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
4120         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
4121         TM.tmFirstChar = winfnt_header.first_char;
4122         TM.tmLastChar = winfnt_header.last_char;
4123         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
4124         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
4125         TM.tmItalic = winfnt_header.italic;
4126         TM.tmUnderlined = font->underline;
4127         TM.tmStruckOut = font->strikeout;
4128         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
4129         TM.tmCharSet = winfnt_header.charset;
4130     }
4131     else
4132 #endif
4133     {
4134         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
4135         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
4136         TM.tmHeight = TM.tmAscent + TM.tmDescent;
4137         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
4138         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
4139         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
4140         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
4141         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
4142         TM.tmOverhang = 0;
4143         TM.tmDigitizedAspectX = 96; /* FIXME */
4144         TM.tmDigitizedAspectY = 96; /* FIXME */
4145         TM.tmFirstChar = 1;
4146         TM.tmLastChar = 255;
4147         TM.tmDefaultChar = 32;
4148         TM.tmBreakChar = 32;
4149         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
4150         TM.tmUnderlined = font->underline;
4151         TM.tmStruckOut = font->strikeout;
4152         /* NB inverted meaning of TMPF_FIXED_PITCH */
4153         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
4154         TM.tmCharSet = font->charset;
4155     }
4156 #undef TM
4157
4158     return TRUE;
4159 }
4160
4161
4162 static void scale_font_metrics(GdiFont *font, LPTEXTMETRICW ptm)
4163 {
4164     if (font->scale_x == 0.0)
4165     {
4166         if (FT_IS_SCALABLE(font->ft_face) || !font->ppem)
4167             font->scale_y = 1.0;
4168         else
4169         {
4170             font->scale_y = (float)font->ppem * font->font_desc.matrix.eM22;
4171             font->scale_y /= (float)font->potm->otmTextMetrics.tmHeight;
4172         }
4173
4174         if (font->aveWidth)
4175         {
4176             font->scale_x = (float)font->aveWidth * font->font_desc.matrix.eM11;
4177             font->scale_x /= (float)font->potm->otmTextMetrics.tmAveCharWidth;
4178         }
4179         else
4180             font->scale_x = font->scale_y;
4181
4182         TRACE("font scale x: %f y: %f\n", font->scale_x, font->scale_y);
4183     }
4184     ptm->tmHeight = (float)ptm->tmHeight * font->scale_y;
4185     ptm->tmAscent = (float)ptm->tmAscent * font->scale_y;
4186     ptm->tmDescent = (float)ptm->tmDescent * font->scale_y;
4187     ptm->tmInternalLeading = (float)ptm->tmInternalLeading * font->scale_y;
4188     ptm->tmExternalLeading = (float)ptm->tmExternalLeading * font->scale_y;
4189
4190     ptm->tmAveCharWidth = (float)ptm->tmAveCharWidth * font->scale_x;
4191     ptm->tmMaxCharWidth = (float)ptm->tmMaxCharWidth * font->scale_x;
4192 }
4193
4194 /*************************************************************
4195  * WineEngGetTextMetrics
4196  *
4197  */
4198 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
4199 {
4200     if(!font->potm) {
4201         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
4202             if(!get_bitmap_text_metrics(font))
4203                 return FALSE;
4204     }
4205     if(!font->potm) return FALSE;
4206     memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm));
4207     scale_font_metrics(font, ptm);
4208
4209     return TRUE;
4210 }
4211
4212
4213 /*************************************************************
4214  * WineEngGetOutlineTextMetrics
4215  *
4216  */
4217 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
4218                                   OUTLINETEXTMETRICW *potm)
4219 {
4220     FT_Face ft_face = font->ft_face;
4221     UINT needed, lenfam, lensty, ret;
4222     TT_OS2 *pOS2;
4223     TT_HoriHeader *pHori;
4224     TT_Postscript *pPost;
4225     FT_Fixed x_scale, y_scale;
4226     WCHAR *family_nameW, *style_nameW;
4227     static const WCHAR spaceW[] = {' ', '\0'};
4228     char *cp;
4229     INT ascent, descent;
4230
4231     TRACE("font=%p\n", font);
4232
4233     if(!FT_IS_SCALABLE(ft_face))
4234         return 0;
4235
4236     if(font->potm) {
4237         if(cbSize >= font->potm->otmSize)
4238         {
4239             memcpy(potm, font->potm, font->potm->otmSize);
4240             scale_font_metrics(font, &potm->otmTextMetrics);
4241         }
4242         return font->potm->otmSize;
4243     }
4244
4245
4246     needed = sizeof(*potm);
4247
4248     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
4249     family_nameW = strdupW(font->name);
4250
4251     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
4252       * sizeof(WCHAR);
4253     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
4254     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
4255                         style_nameW, lensty/sizeof(WCHAR));
4256
4257     /* These names should be read from the TT name table */
4258
4259     /* length of otmpFamilyName */
4260     needed += lenfam;
4261
4262     /* length of otmpFaceName */
4263     if(!strcasecmp(ft_face->style_name, "regular")) {
4264       needed += lenfam; /* just the family name */
4265     } else {
4266       needed += lenfam + lensty; /* family + " " + style */
4267     }
4268
4269     /* length of otmpStyleName */
4270     needed += lensty;
4271
4272     /* length of otmpFullName */
4273     needed += lenfam + lensty;
4274
4275
4276     x_scale = ft_face->size->metrics.x_scale;
4277     y_scale = ft_face->size->metrics.y_scale;
4278
4279     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
4280     if(!pOS2) {
4281         FIXME("Can't find OS/2 table - not TT font?\n");
4282         ret = 0;
4283         goto end;
4284     }
4285
4286     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
4287     if(!pHori) {
4288         FIXME("Can't find HHEA table - not TT font?\n");
4289         ret = 0;
4290         goto end;
4291     }
4292
4293     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
4294
4295     TRACE("OS/2 winA = %d winD = %d typoA = %d typoD = %d typoLG = %d FT_Face a = %d, d = %d, h = %d: HORZ a = %d, d = %d lg = %d maxY = %ld minY = %ld\n",
4296           pOS2->usWinAscent, pOS2->usWinDescent,
4297           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
4298           ft_face->ascender, ft_face->descender, ft_face->height,
4299           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
4300           ft_face->bbox.yMax, ft_face->bbox.yMin);
4301
4302     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
4303     font->potm->otmSize = needed;
4304
4305 #define TM font->potm->otmTextMetrics
4306
4307     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
4308         ascent = pHori->Ascender;
4309         descent = -pHori->Descender;
4310     } else {
4311         ascent = pOS2->usWinAscent;
4312         descent = pOS2->usWinDescent;
4313     }
4314
4315     if(font->yMax) {
4316         TM.tmAscent = font->yMax;
4317         TM.tmDescent = -font->yMin;
4318         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
4319     } else {
4320         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
4321         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
4322         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
4323                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
4324     }
4325
4326     TM.tmHeight = TM.tmAscent + TM.tmDescent;
4327
4328     /* MSDN says:
4329      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
4330     */
4331     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
4332                  ((ascent + descent) -
4333                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
4334
4335     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
4336     if (TM.tmAveCharWidth == 0) {
4337         TM.tmAveCharWidth = 1; 
4338     }
4339     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
4340     TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
4341     TM.tmOverhang = 0;
4342     TM.tmDigitizedAspectX = 300;
4343     TM.tmDigitizedAspectY = 300;
4344     /* It appears that for fonts with SYMBOL_CHARSET Windows always sets
4345      * symbol range to 0 - f0ff
4346      */
4347     if (font->charset == SYMBOL_CHARSET)
4348         TM.tmFirstChar = 0;
4349     else
4350         TM.tmFirstChar = pOS2->usFirstCharIndex;
4351     TM.tmLastChar = pOS2->usLastCharIndex;
4352     TM.tmDefaultChar = pOS2->usDefaultChar ? pOS2->usDefaultChar : 0x1f;
4353     TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
4354     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
4355     TM.tmUnderlined = font->underline;
4356     TM.tmStruckOut = font->strikeout;
4357
4358     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
4359     if(!FT_IS_FIXED_WIDTH(ft_face) &&
4360        (pOS2->version == 0xFFFFU || 
4361         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
4362         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
4363     else
4364         TM.tmPitchAndFamily = 0;
4365
4366     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
4367     case PAN_FAMILY_SCRIPT:
4368         TM.tmPitchAndFamily |= FF_SCRIPT;
4369         break;
4370     case PAN_FAMILY_DECORATIVE:
4371     case PAN_FAMILY_PICTORIAL:
4372         TM.tmPitchAndFamily |= FF_DECORATIVE;
4373         break;
4374     case PAN_FAMILY_TEXT_DISPLAY:
4375         if(TM.tmPitchAndFamily == 0) /* fixed */
4376             TM.tmPitchAndFamily = FF_MODERN;
4377         else {
4378             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
4379             case PAN_SERIF_NORMAL_SANS:
4380             case PAN_SERIF_OBTUSE_SANS:
4381             case PAN_SERIF_PERP_SANS:
4382                 TM.tmPitchAndFamily |= FF_SWISS;
4383                 break;
4384             default:
4385                 TM.tmPitchAndFamily |= FF_ROMAN;
4386             }
4387         }
4388         break;
4389     default:
4390         TM.tmPitchAndFamily |= FF_DONTCARE;
4391     }
4392
4393     if(FT_IS_SCALABLE(ft_face))
4394         TM.tmPitchAndFamily |= TMPF_VECTOR;
4395
4396     if(FT_IS_SFNT(ft_face))
4397     {
4398         if (font->ntmFlags & NTM_PS_OPENTYPE)
4399             TM.tmPitchAndFamily |= TMPF_DEVICE;
4400         else
4401             TM.tmPitchAndFamily |= TMPF_TRUETYPE;
4402     }
4403
4404     TM.tmCharSet = font->charset;
4405 #undef TM
4406
4407     font->potm->otmFiller = 0;
4408     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
4409     font->potm->otmfsSelection = pOS2->fsSelection;
4410     font->potm->otmfsType = pOS2->fsType;
4411     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
4412     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
4413     font->potm->otmItalicAngle = 0; /* POST table */
4414     font->potm->otmEMSquare = ft_face->units_per_EM;
4415     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
4416     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
4417     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
4418     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
4419     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
4420     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
4421     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
4422     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
4423     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
4424     font->potm->otmMacAscent = 0; /* where do these come from ? */
4425     font->potm->otmMacDescent = 0;
4426     font->potm->otmMacLineGap = 0;
4427     font->potm->otmusMinimumPPEM = 0; /* TT Header */
4428     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
4429     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
4430     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
4431     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
4432     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
4433     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
4434     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
4435     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
4436     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
4437     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
4438     if(!pPost) {
4439         font->potm->otmsUnderscoreSize = 0;
4440         font->potm->otmsUnderscorePosition = 0;
4441     } else {
4442         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
4443         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
4444     }
4445
4446     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
4447     cp = (char*)font->potm + sizeof(*font->potm);
4448     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
4449     strcpyW((WCHAR*)cp, family_nameW);
4450     cp += lenfam;
4451     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
4452     strcpyW((WCHAR*)cp, style_nameW);
4453     cp += lensty;
4454     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
4455     strcpyW((WCHAR*)cp, family_nameW);
4456     if(strcasecmp(ft_face->style_name, "regular")) {
4457         strcatW((WCHAR*)cp, spaceW);
4458         strcatW((WCHAR*)cp, style_nameW);
4459         cp += lenfam + lensty;
4460     } else
4461         cp += lenfam;
4462     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
4463     strcpyW((WCHAR*)cp, family_nameW);
4464     strcatW((WCHAR*)cp, spaceW);
4465     strcatW((WCHAR*)cp, style_nameW);
4466     ret = needed;
4467
4468     if(potm && needed <= cbSize)
4469     {
4470         memcpy(potm, font->potm, font->potm->otmSize);
4471         scale_font_metrics(font, &potm->otmTextMetrics);
4472     }
4473
4474 end:
4475     HeapFree(GetProcessHeap(), 0, style_nameW);
4476     HeapFree(GetProcessHeap(), 0, family_nameW);
4477
4478     return ret;
4479 }
4480
4481 static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
4482 {
4483     HFONTLIST *hfontlist;
4484     child->font = alloc_font();
4485     child->font->ft_face = OpenFontFace(child->font, child->face, 0, -font->ppem);
4486     if(!child->font->ft_face)
4487     {
4488         free_font(child->font);
4489         child->font = NULL;
4490         return FALSE;
4491     }
4492
4493     child->font->ntmFlags = child->face->ntmFlags;
4494     child->font->orientation = font->orientation;
4495     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
4496     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
4497     list_add_head(&child->font->hfontlist, &hfontlist->entry);
4498     child->font->base_font = font;
4499     list_add_head(&child_font_list, &child->font->entry);
4500     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
4501     return TRUE;
4502 }
4503
4504 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph)
4505 {
4506     FT_UInt g;
4507     CHILD_FONT *child_font;
4508
4509     if(font->base_font)
4510         font = font->base_font;
4511
4512     *linked_font = font;
4513
4514     if((*glyph = get_glyph_index(font, c)))
4515         return TRUE;
4516
4517     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
4518     {
4519         if(!child_font->font)
4520             if(!load_child_font(font, child_font))
4521                 continue;
4522
4523         if(!child_font->font->ft_face)
4524             continue;
4525         g = get_glyph_index(child_font->font, c);
4526         if(g)
4527         {
4528             *glyph = g;
4529             *linked_font = child_font->font;
4530             return TRUE;
4531         }
4532     }
4533     return FALSE;
4534 }
4535
4536 /*************************************************************
4537  * WineEngGetCharWidth
4538  *
4539  */
4540 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
4541                          LPINT buffer)
4542 {
4543     UINT c;
4544     GLYPHMETRICS gm;
4545     FT_UInt glyph_index;
4546     GdiFont *linked_font;
4547
4548     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
4549
4550     for(c = firstChar; c <= lastChar; c++) {
4551         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
4552         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
4553                                &gm, 0, NULL, NULL);
4554         buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv;
4555     }
4556     return TRUE;
4557 }
4558
4559 /*************************************************************
4560  * WineEngGetCharABCWidths
4561  *
4562  */
4563 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
4564                              LPABC buffer)
4565 {
4566     UINT c;
4567     GLYPHMETRICS gm;
4568     FT_UInt glyph_index;
4569     GdiFont *linked_font;
4570
4571     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
4572
4573     if(!FT_IS_SCALABLE(font->ft_face))
4574         return FALSE;
4575
4576     for(c = firstChar; c <= lastChar; c++) {
4577         get_glyph_index_linked(font, c, &linked_font, &glyph_index);
4578         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
4579                                &gm, 0, NULL, NULL);
4580         buffer[c - firstChar].abcA = FONT_GM(linked_font,glyph_index)->lsb;
4581         buffer[c - firstChar].abcB = FONT_GM(linked_font,glyph_index)->bbx;
4582         buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb -
4583             FONT_GM(linked_font,glyph_index)->bbx;
4584     }
4585     return TRUE;
4586 }
4587
4588 /*************************************************************
4589  * WineEngGetCharABCWidthsI
4590  *
4591  */
4592 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
4593                               LPABC buffer)
4594 {
4595     UINT c;
4596     GLYPHMETRICS gm;
4597     FT_UInt glyph_index;
4598     GdiFont *linked_font;
4599
4600     if(!FT_HAS_HORIZONTAL(font->ft_face))
4601         return FALSE;
4602
4603     get_glyph_index_linked(font, 'a', &linked_font, &glyph_index);
4604     if (!pgi)
4605         for(c = firstChar; c < firstChar+count; c++) {
4606             WineEngGetGlyphOutline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
4607                                    &gm, 0, NULL, NULL);
4608             buffer[c - firstChar].abcA = FONT_GM(linked_font,c)->lsb;
4609             buffer[c - firstChar].abcB = FONT_GM(linked_font,c)->bbx;
4610             buffer[c - firstChar].abcC = FONT_GM(linked_font,c)->adv - FONT_GM(linked_font,c)->lsb
4611                 - FONT_GM(linked_font,c)->bbx;
4612         }
4613     else
4614         for(c = 0; c < count; c++) {
4615             WineEngGetGlyphOutline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
4616                                    &gm, 0, NULL, NULL);
4617             buffer[c].abcA = FONT_GM(linked_font,pgi[c])->lsb;
4618             buffer[c].abcB = FONT_GM(linked_font,pgi[c])->bbx;
4619             buffer[c].abcC = FONT_GM(linked_font,pgi[c])->adv
4620                 - FONT_GM(linked_font,pgi[c])->lsb - FONT_GM(linked_font,pgi[c])->bbx;
4621         }
4622
4623     return TRUE;
4624 }
4625
4626 /*************************************************************
4627  * WineEngGetTextExtentExPoint
4628  *
4629  */
4630 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
4631                                  INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
4632 {
4633     INT idx;
4634     INT nfit = 0, ext;
4635     GLYPHMETRICS gm;
4636     TEXTMETRICW tm;
4637     FT_UInt glyph_index;
4638     GdiFont *linked_font;
4639
4640     TRACE("%p, %s, %d, %d, %p\n", font, debugstr_wn(wstr, count), count,
4641           max_ext, size);
4642
4643     size->cx = 0;
4644     WineEngGetTextMetrics(font, &tm);
4645     size->cy = tm.tmHeight;
4646
4647     for(idx = 0; idx < count; idx++) {
4648         get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
4649         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
4650                                &gm, 0, NULL, NULL);
4651         size->cx += FONT_GM(linked_font,glyph_index)->adv;
4652         ext = size->cx;
4653         if (! pnfit || ext <= max_ext) {
4654             ++nfit;
4655             if (dxs)
4656                 dxs[idx] = ext;
4657         }
4658     }
4659
4660     if (pnfit)
4661         *pnfit = nfit;
4662
4663     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
4664     return TRUE;
4665 }
4666
4667 /*************************************************************
4668  * WineEngGetTextExtentExPointI
4669  *
4670  */
4671 BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count,
4672                                   INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
4673 {
4674     INT idx;
4675     INT nfit = 0, ext;
4676     GLYPHMETRICS gm;
4677     TEXTMETRICW tm;
4678
4679     TRACE("%p, %p, %d, %d, %p\n", font, indices, count, max_ext, size);
4680
4681     size->cx = 0;
4682     WineEngGetTextMetrics(font, &tm);
4683     size->cy = tm.tmHeight;
4684
4685     for(idx = 0; idx < count; idx++) {
4686         WineEngGetGlyphOutline(font, indices[idx],
4687                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
4688                                NULL);
4689         size->cx += FONT_GM(font,indices[idx])->adv;
4690         ext = size->cx;
4691         if (! pnfit || ext <= max_ext) {
4692             ++nfit;
4693             if (dxs)
4694                 dxs[idx] = ext;
4695         }
4696     }
4697
4698     if (pnfit)
4699         *pnfit = nfit;
4700
4701     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
4702     return TRUE;
4703 }
4704
4705 /*************************************************************
4706  * WineEngGetFontData
4707  *
4708  */
4709 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
4710                          DWORD cbData)
4711 {
4712     FT_Face ft_face = font->ft_face;
4713     FT_ULong len;
4714     FT_Error err;
4715
4716     TRACE("font=%p, table=%c%c%c%c, offset=0x%x, buf=%p, cbData=0x%x\n",
4717         font, LOBYTE(LOWORD(table)), HIBYTE(LOWORD(table)),
4718         LOBYTE(HIWORD(table)), HIBYTE(HIWORD(table)), offset, buf, cbData);
4719
4720     if(!FT_IS_SFNT(ft_face))
4721         return GDI_ERROR;
4722
4723     if(!buf || !cbData)
4724         len = 0;
4725     else
4726         len = cbData;
4727
4728     if(table) { /* MS tags differ in endidness from FT ones */
4729         table = table >> 24 | table << 24 |
4730           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
4731     }
4732
4733     /* make sure value of len is the value freetype says it needs */
4734     if(buf && len)
4735     {
4736         FT_ULong needed = 0;
4737         err = load_sfnt_table(ft_face, table, offset, NULL, &needed);
4738         if( !err && needed < len) len = needed;
4739     }
4740     err = load_sfnt_table(ft_face, table, offset, buf, &len);
4741
4742     if(err) {
4743         TRACE("Can't find table %c%c%c%c\n",
4744               /* bytes were reversed */
4745               HIBYTE(HIWORD(table)), LOBYTE(HIWORD(table)),
4746               HIBYTE(LOWORD(table)), LOBYTE(LOWORD(table)));
4747         return GDI_ERROR;
4748     }
4749     return len;
4750 }
4751
4752 /*************************************************************
4753  * WineEngGetTextFace
4754  *
4755  */
4756 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
4757 {
4758     if(str) {
4759         lstrcpynW(str, font->name, count);
4760         return strlenW(font->name);
4761     } else
4762         return strlenW(font->name) + 1;
4763 }
4764
4765 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
4766 {
4767     if (fs) memcpy(fs, &font->fs, sizeof(FONTSIGNATURE));
4768     return font->charset;
4769 }
4770
4771 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
4772 {
4773     GdiFont *font = dc->gdiFont, *linked_font;
4774     struct list *first_hfont;
4775     BOOL ret;
4776
4777     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
4778     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
4779     if(font == linked_font)
4780         *new_hfont = dc->hFont;
4781     else
4782     {
4783         first_hfont = list_head(&linked_font->hfontlist);
4784         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
4785     }
4786
4787     return ret;
4788 }
4789     
4790 /* Retrieve a list of supported Unicode ranges for a given font.
4791  * Can be called with NULL gs to calculate the buffer size. Returns
4792  * the number of ranges found.
4793  */
4794 static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
4795 {
4796     DWORD num_ranges = 0;
4797
4798     if (face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
4799     {
4800         FT_UInt glyph_code;
4801         FT_ULong char_code, char_code_prev;
4802
4803         glyph_code = 0;
4804         char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
4805
4806         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
4807                face->num_glyphs, glyph_code, char_code);
4808
4809         if (!glyph_code) return 0;
4810
4811         if (gs)
4812         {
4813             gs->ranges[0].wcLow = (USHORT)char_code;
4814             gs->ranges[0].cGlyphs = 0;
4815             gs->cGlyphsSupported = 0;
4816         }
4817
4818         num_ranges = 1;
4819         while (glyph_code)
4820         {
4821             if (char_code < char_code_prev)
4822             {
4823                 ERR("expected increasing char code from FT_Get_Next_Char\n");
4824                 return 0;
4825             }
4826             if (char_code - char_code_prev > 1)
4827             {
4828                 num_ranges++;
4829                 if (gs)
4830                 {
4831                     gs->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
4832                     gs->ranges[num_ranges - 1].cGlyphs = 1;
4833                     gs->cGlyphsSupported++;
4834                 }
4835             }
4836             else if (gs)
4837             {
4838                 gs->ranges[num_ranges - 1].cGlyphs++;
4839                 gs->cGlyphsSupported++;
4840             }
4841             char_code_prev = char_code;
4842             char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
4843         }
4844     }
4845     else
4846         FIXME("encoding %u not supported\n", face->charmap->encoding);
4847
4848     return num_ranges;
4849 }
4850
4851 DWORD WineEngGetFontUnicodeRanges(GdiFont *font, LPGLYPHSET glyphset)
4852 {
4853     DWORD size = 0;
4854     DWORD num_ranges = get_font_unicode_ranges(font->ft_face, glyphset);
4855
4856     size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
4857     if (glyphset)
4858     {
4859         glyphset->cbThis = size;
4860         glyphset->cRanges = num_ranges;
4861     }
4862     return size;
4863 }
4864
4865 /*************************************************************
4866  *     FontIsLinked
4867  */
4868 BOOL WineEngFontIsLinked(GdiFont *font)
4869 {
4870     return !list_empty(&font->child_fonts);
4871 }
4872
4873 static BOOL is_hinting_enabled(void)
4874 {
4875     /* Use the >= 2.2.0 function if available */
4876     if(pFT_Get_TrueType_Engine_Type)
4877     {
4878         FT_TrueTypeEngineType type = pFT_Get_TrueType_Engine_Type(library);
4879         return type == FT_TRUETYPE_ENGINE_TYPE_PATENTED;
4880     }
4881 #ifdef FT_DRIVER_HAS_HINTER
4882     else
4883     {
4884         FT_Module mod;
4885
4886         /* otherwise if we've been compiled with < 2.2.0 headers 
4887            use the internal macro */
4888         mod = pFT_Get_Module(library, "truetype");
4889         if(mod && FT_DRIVER_HAS_HINTER(mod))
4890             return TRUE;
4891     }
4892 #endif
4893
4894     return FALSE;
4895 }
4896
4897 /*************************************************************************
4898  *             GetRasterizerCaps   (GDI32.@)
4899  */
4900 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
4901 {
4902     static int hinting = -1;
4903
4904     if(hinting == -1)
4905     {
4906         hinting = is_hinting_enabled();
4907         TRACE("hinting is %senabled\n", hinting ? "" : "NOT ");
4908     }
4909
4910     lprs->nSize = sizeof(RASTERIZER_STATUS);
4911     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
4912     lprs->nLanguageID = 0;
4913     return TRUE;
4914 }
4915
4916 /*************************************************************************
4917  * Kerning support for TrueType fonts
4918  */
4919 #define MS_KERN_TAG MS_MAKE_TAG('k', 'e', 'r', 'n')
4920
4921 struct TT_kern_table
4922 {
4923     USHORT version;
4924     USHORT nTables;
4925 };
4926
4927 struct TT_kern_subtable
4928 {
4929     USHORT version;
4930     USHORT length;
4931     union
4932     {
4933         USHORT word;
4934         struct
4935         {
4936             USHORT horizontal : 1;
4937             USHORT minimum : 1;
4938             USHORT cross_stream: 1;
4939             USHORT override : 1;
4940             USHORT reserved1 : 4;
4941             USHORT format : 8;
4942         } bits;
4943     } coverage;
4944 };
4945
4946 struct TT_format0_kern_subtable
4947 {
4948     USHORT nPairs;
4949     USHORT searchRange;
4950     USHORT entrySelector;
4951     USHORT rangeShift;
4952 };
4953
4954 struct TT_kern_pair
4955 {
4956     USHORT left;
4957     USHORT right;
4958     short  value;
4959 };
4960
4961 static DWORD parse_format0_kern_subtable(GdiFont *font,
4962                                          const struct TT_format0_kern_subtable *tt_f0_ks,
4963                                          const USHORT *glyph_to_char,
4964                                          KERNINGPAIR *kern_pair, DWORD cPairs)
4965 {
4966     USHORT i, nPairs;
4967     const struct TT_kern_pair *tt_kern_pair;
4968
4969     TRACE("font height %d, units_per_EM %d\n", font->ppem, font->ft_face->units_per_EM);
4970
4971     nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
4972
4973     TRACE("nPairs %u, searchRange %u, entrySelector %u, rangeShift %u\n",
4974            nPairs, GET_BE_WORD(tt_f0_ks->searchRange),
4975            GET_BE_WORD(tt_f0_ks->entrySelector), GET_BE_WORD(tt_f0_ks->rangeShift));
4976
4977     if (!kern_pair || !cPairs)
4978         return nPairs;
4979
4980     tt_kern_pair = (const struct TT_kern_pair *)(tt_f0_ks + 1);
4981
4982     nPairs = min(nPairs, cPairs);
4983
4984     for (i = 0; i < nPairs; i++)
4985     {
4986         kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
4987         kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
4988         /* this algorithm appears to better match what Windows does */
4989         kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
4990         if (kern_pair->iKernAmount < 0)
4991         {
4992             kern_pair->iKernAmount -= font->ft_face->units_per_EM / 2;
4993             kern_pair->iKernAmount -= font->ppem;
4994         }
4995         else if (kern_pair->iKernAmount > 0)
4996         {
4997             kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
4998             kern_pair->iKernAmount += font->ppem;
4999         }
5000         kern_pair->iKernAmount /= font->ft_face->units_per_EM;
5001
5002         TRACE("left %u right %u value %d\n",
5003                kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
5004
5005         kern_pair++;
5006     }
5007     TRACE("copied %u entries\n", nPairs);
5008     return nPairs;
5009 }
5010
5011 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
5012 {
5013     DWORD length;
5014     void *buf;
5015     const struct TT_kern_table *tt_kern_table;
5016     const struct TT_kern_subtable *tt_kern_subtable;
5017     USHORT i, nTables;
5018     USHORT *glyph_to_char;
5019
5020     if (font->total_kern_pairs != (DWORD)-1)
5021     {
5022         if (cPairs && kern_pair)
5023         {
5024             cPairs = min(cPairs, font->total_kern_pairs);
5025             memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
5026             return cPairs;
5027         }
5028         return font->total_kern_pairs;
5029     }
5030
5031     font->total_kern_pairs = 0;
5032
5033     length = WineEngGetFontData(font, MS_KERN_TAG, 0, NULL, 0);
5034
5035     if (length == GDI_ERROR)
5036     {
5037         TRACE("no kerning data in the font\n");
5038         return 0;
5039     }
5040
5041     buf = HeapAlloc(GetProcessHeap(), 0, length);
5042     if (!buf)
5043     {
5044         WARN("Out of memory\n");
5045         return 0;
5046     }
5047
5048     WineEngGetFontData(font, MS_KERN_TAG, 0, buf, length);
5049
5050     /* build a glyph index to char code map */
5051     glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
5052     if (!glyph_to_char)
5053     {
5054         WARN("Out of memory allocating a glyph index to char code map\n");
5055         HeapFree(GetProcessHeap(), 0, buf);
5056         return 0;
5057     }
5058
5059     if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
5060     {
5061         FT_UInt glyph_code;
5062         FT_ULong char_code;
5063
5064         glyph_code = 0;
5065         char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
5066
5067         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
5068                font->ft_face->num_glyphs, glyph_code, char_code);
5069
5070         while (glyph_code)
5071         {
5072             /*TRACE("Char %04lX -> Index %u%s\n", char_code, glyph_code, glyph_to_char[glyph_code] ? "  !" : "" );*/
5073
5074             /* FIXME: This doesn't match what Windows does: it does some fancy
5075              * things with duplicate glyph index to char code mappings, while
5076              * we just avoid overriding existing entries.
5077              */
5078             if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
5079                 glyph_to_char[glyph_code] = (USHORT)char_code;
5080
5081             char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
5082         }
5083     }
5084     else
5085     {
5086         ULONG n;
5087
5088         FIXME("encoding %u not supported\n", font->ft_face->charmap->encoding);
5089         for (n = 0; n <= 65535; n++)
5090             glyph_to_char[n] = (USHORT)n;
5091     }
5092
5093     tt_kern_table = buf;
5094     nTables = GET_BE_WORD(tt_kern_table->nTables);
5095     TRACE("version %u, nTables %u\n",
5096            GET_BE_WORD(tt_kern_table->version), nTables);
5097
5098     tt_kern_subtable = (const struct TT_kern_subtable *)(tt_kern_table + 1);
5099
5100     for (i = 0; i < nTables; i++)
5101     {
5102         struct TT_kern_subtable tt_kern_subtable_copy;
5103
5104         tt_kern_subtable_copy.version = GET_BE_WORD(tt_kern_subtable->version);
5105         tt_kern_subtable_copy.length = GET_BE_WORD(tt_kern_subtable->length);
5106         tt_kern_subtable_copy.coverage.word = GET_BE_WORD(tt_kern_subtable->coverage.word);
5107
5108         TRACE("version %u, length %u, coverage %u, subtable format %u\n",
5109                tt_kern_subtable_copy.version, tt_kern_subtable_copy.length,
5110                tt_kern_subtable_copy.coverage.word, tt_kern_subtable_copy.coverage.bits.format);
5111
5112         /* According to the TrueType specification this is the only format
5113          * that will be properly interpreted by Windows and OS/2
5114          */
5115         if (tt_kern_subtable_copy.coverage.bits.format == 0)
5116         {
5117             DWORD new_chunk, old_total = font->total_kern_pairs;
5118
5119             new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
5120                                                     glyph_to_char, NULL, 0);
5121             font->total_kern_pairs += new_chunk;
5122
5123             if (!font->kern_pairs)
5124                 font->kern_pairs = HeapAlloc(GetProcessHeap(), 0,
5125                                              font->total_kern_pairs * sizeof(*font->kern_pairs));
5126             else
5127                 font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs,
5128                                                font->total_kern_pairs * sizeof(*font->kern_pairs));
5129
5130             parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
5131                         glyph_to_char, font->kern_pairs + old_total, new_chunk);
5132         }
5133         else
5134             TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format);
5135
5136         tt_kern_subtable = (const struct TT_kern_subtable *)((const char *)tt_kern_subtable + tt_kern_subtable_copy.length);
5137     }
5138
5139     HeapFree(GetProcessHeap(), 0, glyph_to_char);
5140     HeapFree(GetProcessHeap(), 0, buf);
5141
5142     if (cPairs && kern_pair)
5143     {
5144         cPairs = min(cPairs, font->total_kern_pairs);
5145         memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
5146         return cPairs;
5147     }
5148     return font->total_kern_pairs;
5149 }
5150
5151 #else /* HAVE_FREETYPE */
5152
5153 /*************************************************************************/
5154
5155 BOOL WineEngInit(void)
5156 {
5157     return FALSE;
5158 }
5159 GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont)
5160 {
5161     return NULL;
5162 }
5163 BOOL WineEngDestroyFontInstance(HFONT hfont)
5164 {
5165     return FALSE;
5166 }
5167
5168 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
5169 {
5170     return 1;
5171 }
5172
5173 DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
5174                                 LPWORD pgi, DWORD flags)
5175 {
5176     return GDI_ERROR;
5177 }
5178
5179 DWORD WineEngGetGlyphOutline(GdiFont *font, UINT glyph, UINT format,
5180                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
5181                              const MAT2* lpmat)
5182 {
5183     ERR("called but we don't have FreeType\n");
5184     return GDI_ERROR;
5185 }
5186
5187 BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
5188 {
5189     ERR("called but we don't have FreeType\n");
5190     return FALSE;
5191 }
5192
5193 UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
5194                                   OUTLINETEXTMETRICW *potm)
5195 {
5196     ERR("called but we don't have FreeType\n");
5197     return 0;
5198 }
5199
5200 BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar,
5201                          LPINT buffer)
5202 {
5203     ERR("called but we don't have FreeType\n");
5204     return FALSE;
5205 }
5206
5207 BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
5208                              LPABC buffer)
5209 {
5210     ERR("called but we don't have FreeType\n");
5211     return FALSE;
5212 }
5213
5214 BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi,
5215                               LPABC buffer)
5216 {
5217     ERR("called but we don't have FreeType\n");
5218     return FALSE;
5219 }
5220
5221 BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count,
5222                                  INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
5223 {
5224     ERR("called but we don't have FreeType\n");
5225     return FALSE;
5226 }
5227
5228 BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count,
5229                                   INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
5230 {
5231     ERR("called but we don't have FreeType\n");
5232     return FALSE;
5233 }
5234
5235 DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf,
5236                          DWORD cbData)
5237 {
5238     ERR("called but we don't have FreeType\n");
5239     return GDI_ERROR;
5240 }
5241
5242 INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str)
5243 {
5244     ERR("called but we don't have FreeType\n");
5245     return 0;
5246 }
5247
5248 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
5249 {
5250     FIXME(":stub\n");
5251     return 1;
5252 }
5253
5254 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
5255 {
5256     FIXME(":stub\n");
5257     return TRUE;
5258 }
5259
5260 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
5261 {
5262     FIXME(":stub\n");
5263     return NULL;
5264 }
5265
5266 UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags)
5267 {
5268     FIXME(":stub\n");
5269     return DEFAULT_CHARSET;
5270 }
5271
5272 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
5273 {
5274     return FALSE;
5275 }
5276
5277 DWORD WineEngGetFontUnicodeRanges(GdiFont *font, LPGLYPHSET glyphset)
5278 {
5279     FIXME("(%p, %p): stub\n", font, glyphset);
5280     return 0;
5281 }
5282
5283 BOOL WineEngFontIsLinked(GdiFont *font)
5284 {
5285     return FALSE;
5286 }
5287
5288 /*************************************************************************
5289  *             GetRasterizerCaps   (GDI32.@)
5290  */
5291 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
5292 {
5293     lprs->nSize = sizeof(RASTERIZER_STATUS);
5294     lprs->wFlags = 0;
5295     lprs->nLanguageID = 0;
5296     return TRUE;
5297 }
5298
5299 DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair)
5300 {
5301     ERR("called but we don't have FreeType\n");
5302     return 0;
5303 }
5304
5305 #endif /* HAVE_FREETYPE */