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