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