Implement A->W call for GetNamedSecurityInfo.
[wine] / dlls / gdi / freetype.c
1 /*
2  * FreeType font engine interface
3  *
4  * Copyright 2001 Huw D M Davies for CodeWeavers.
5  *
6  * This file contains the WineEng* functions.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <sys/stat.h>
29 #include <string.h>
30 #include <dirent.h>
31 #include <stdio.h>
32 #include <assert.h>
33
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "winreg.h"
38 #include "wingdi.h"
39 #include "gdi.h"
40 #include "gdi_private.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
43 #include "wine/list.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(font);
46
47 #ifdef HAVE_FREETYPE
48
49 #ifdef HAVE_FT2BUILD_H
50 #include <ft2build.h>
51 #endif
52 #ifdef HAVE_FREETYPE_FREETYPE_H
53 #include <freetype/freetype.h>
54 #endif
55 #ifdef HAVE_FREETYPE_FTGLYPH_H
56 #include <freetype/ftglyph.h>
57 #endif
58 #ifdef HAVE_FREETYPE_TTTABLES_H
59 #include <freetype/tttables.h>
60 #endif
61 #ifdef HAVE_FREETYPE_FTSNAMES_H
62 #include <freetype/ftsnames.h>
63 #else
64 # ifdef HAVE_FREETYPE_FTNAMES_H
65 # include <freetype/ftnames.h>
66 # endif
67 #endif
68 #ifdef HAVE_FREETYPE_TTNAMEID_H
69 #include <freetype/ttnameid.h>
70 #endif
71 #ifdef HAVE_FREETYPE_FTOUTLN_H
72 #include <freetype/ftoutln.h>
73 #endif
74 #ifdef HAVE_FREETYPE_INTERNAL_SFNT_H
75 #include <freetype/internal/sfnt.h>
76 #endif
77 #ifdef HAVE_FREETYPE_FTTRIGON_H
78 #include <freetype/fttrigon.h>
79 #endif
80 #ifdef HAVE_FREETYPE_FTWINFNT_H
81 #include <freetype/ftwinfnt.h>
82 #endif
83
84 #ifndef SONAME_LIBFREETYPE
85 #define SONAME_LIBFREETYPE "libfreetype.so"
86 #endif
87
88 static FT_Library library = 0;
89 typedef struct
90 {
91     FT_Int major;
92     FT_Int minor;
93     FT_Int patch;
94 } FT_Version_t;
95 static FT_Version_t FT_Version;
96 static DWORD FT_SimpleVersion;
97
98 static void *ft_handle = NULL;
99
100 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
101 MAKE_FUNCPTR(FT_Vector_Unit);
102 MAKE_FUNCPTR(FT_Done_Face);
103 MAKE_FUNCPTR(FT_Get_Char_Index);
104 MAKE_FUNCPTR(FT_Get_Sfnt_Table);
105 MAKE_FUNCPTR(FT_Init_FreeType);
106 MAKE_FUNCPTR(FT_Load_Glyph);
107 MAKE_FUNCPTR(FT_Matrix_Multiply);
108 MAKE_FUNCPTR(FT_MulFix);
109 MAKE_FUNCPTR(FT_New_Face);
110 MAKE_FUNCPTR(FT_Outline_Get_Bitmap);
111 MAKE_FUNCPTR(FT_Outline_Transform);
112 MAKE_FUNCPTR(FT_Outline_Translate);
113 MAKE_FUNCPTR(FT_Select_Charmap);
114 MAKE_FUNCPTR(FT_Set_Pixel_Sizes);
115 MAKE_FUNCPTR(FT_Vector_Transform);
116 static void (*pFT_Library_Version)(FT_Library,FT_Int*,FT_Int*,FT_Int*);
117 static FT_Error (*pFT_Load_Sfnt_Table)(FT_Face,FT_ULong,FT_Long,FT_Byte*,FT_ULong*);
118 static FT_ULong (*pFT_Get_First_Char)(FT_Face,FT_UInt*);
119 #ifdef HAVE_FREETYPE_FTWINFNT_H
120 MAKE_FUNCPTR(FT_Get_WinFNT_Header);
121 #endif
122
123 #ifdef HAVE_FONTCONFIG_FONTCONFIG_H
124 #include <fontconfig/fontconfig.h>
125 MAKE_FUNCPTR(FcConfigGetCurrent);
126 MAKE_FUNCPTR(FcFontList);
127 MAKE_FUNCPTR(FcFontSetDestroy);
128 MAKE_FUNCPTR(FcInit);
129 MAKE_FUNCPTR(FcObjectSetAdd);
130 MAKE_FUNCPTR(FcObjectSetCreate);
131 MAKE_FUNCPTR(FcObjectSetDestroy);
132 MAKE_FUNCPTR(FcPatternCreate);
133 MAKE_FUNCPTR(FcPatternDestroy);
134 MAKE_FUNCPTR(FcPatternGet);
135 #ifndef SONAME_LIBFONTCONFIG
136 #define SONAME_LIBFONTCONFIG "libfontconfig.so"
137 #endif
138 #endif
139
140 #undef MAKE_FUNCPTR
141
142
143 #define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
144
145 /* This is bascially a copy of FT_Bitmap_Size with an extra element added */
146 typedef struct {
147     FT_Short height;
148     FT_Short width;
149     FT_Pos  size;
150     FT_Pos x_ppem;
151     FT_Pos y_ppem;
152     FT_Short internal_leading;
153 } Bitmap_Size;
154
155 /* FT_Bitmap_Size gained 3 new elements between FreeType 2.1.4 and 2.1.5
156    So to let this compile on older versions of FreeType we'll define the
157    new structure here. */
158 typedef struct {
159     FT_Short height, width;
160     FT_Pos size, x_ppem, y_ppem;
161 } My_FT_Bitmap_Size;
162
163 typedef struct tagFace {
164     WCHAR *StyleName;
165     char *file;
166     FT_Long face_index;
167     BOOL Italic;
168     BOOL Bold;
169     FONTSIGNATURE fs;
170     FT_Fixed font_version;
171     BOOL scalable;
172     Bitmap_Size size;     /* set if face is a bitmap */
173     BOOL external; /* TRUE if we should manually add this font to the registry */
174     struct tagFace *next;
175     struct tagFamily *family;
176 } Face;
177
178 typedef struct tagFamily {
179     WCHAR *FamilyName;
180     Face *FirstFace;
181     struct tagFamily *next;
182 } Family;
183
184 typedef struct {
185     GLYPHMETRICS gm;
186     INT adv; /* These three hold to widths of the unrotated chars */
187     INT lsb;
188     INT bbx;
189     BOOL init;
190 } GM;
191
192 struct tagGdiFont {
193     struct list entry;
194     FT_Face ft_face;
195     XFORM xform;
196     LPWSTR name;
197     int charset;
198     BOOL fake_italic;
199     BOOL fake_bold;
200     BYTE underline;
201     BYTE strikeout;
202     INT orientation;
203     GM *gm;
204     DWORD gmsize;
205     HFONT hfont;
206     LONG aveWidth;
207     SHORT yMax;
208     SHORT yMin;
209     OUTLINETEXTMETRICW *potm;
210     FONTSIGNATURE fs;
211 };
212
213 #define INIT_GM_SIZE 128
214
215 static struct list gdi_font_list = LIST_INIT(gdi_font_list);
216
217 static Family *FontList = NULL;
218
219 static const WCHAR defSerif[] = {'T','i','m','e','s',' ','N','e','w',' ',
220                            'R','o','m','a','n','\0'};
221 static const WCHAR defSans[] = {'A','r','i','a','l','\0'};
222 static const WCHAR defFixed[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'};
223
224 static const WCHAR defSystem[] = {'A','r','i','a','l','\0'};
225 static const WCHAR SystemW[] = {'S','y','s','t','e','m','\0'};
226 static const WCHAR MSSansSerifW[] = {'M','S',' ','S','a','n','s',' ',
227                                'S','e','r','i','f','\0'};
228 static const WCHAR HelvW[] = {'H','e','l','v','\0'};
229 static const WCHAR RegularW[] = {'R','e','g','u','l','a','r','\0'};
230
231 static const WCHAR fontsW[] = {'\\','F','o','n','t','s','\0'};
232 static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
233                                            'W','i','n','d','o','w','s','\\',
234                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
235                                            'F','o','n','t','s','\0'};
236
237 static const WCHAR winnt_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
238                                            'W','i','n','d','o','w','s',' ','N','T','\\',
239                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
240                                            'F','o','n','t','s','\0'};
241
242 static const WCHAR system_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
243 static const WCHAR FixedSys_Value[] = {'F','I','X','E','D','F','O','N','.','F','O','N','\0'};
244 static const WCHAR System_Value[] = {'F','O','N','T','S','.','F','O','N','\0'};
245 static const WCHAR OEMFont_Value[] = {'O','E','M','F','O','N','T','.','F','O','N','\0'};
246
247 static const WCHAR *SystemFontValues[4] = {
248     System_Value,
249     OEMFont_Value,
250     FixedSys_Value,
251     NULL
252 };
253
254 static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','W','i','n','e','\\',
255                                                'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'};
256
257 static const WCHAR ArabicW[] = {'A','r','a','b','i','c','\0'};
258 static const WCHAR BalticW[] = {'B','a','l','t','i','c','\0'};
259 static const WCHAR CHINESE_BIG5W[] = {'C','H','I','N','E','S','E','_','B','I','G','5','\0'};
260 static const WCHAR CHINESE_GB2312W[] = {'C','H','I','N','E','S','E','_','G','B','2','3','1','2','\0'};
261 static const WCHAR Central_EuropeanW[] = {'C','e','n','t','r','a','l',' ',
262                                     'E','u','r','o','p','e','a','n','\0'};
263 static const WCHAR CyrillicW[] = {'C','y','r','i','l','l','i','c','\0'};
264 static const WCHAR GreekW[] = {'G','r','e','e','k','\0'};
265 static const WCHAR HangulW[] = {'H','a','n','g','u','l','\0'};
266 static const WCHAR Hangul_Johab_W[] = {'H','a','n','g','u','l','(','J','o','h','a','b',')','\0'};
267 static const WCHAR HebrewW[] = {'H','e','b','r','e','w','\0'};
268 static const WCHAR JapaneseW[] = {'J','a','p','a','n','e','s','e','\0'};
269 static const WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
270 static const WCHAR ThaiW[] = {'T','h','a','i','\0'};
271 static const WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'};
272 static const WCHAR VietnameseW[] = {'V','i','e','t','n','a','m','e','s','e','\0'};
273 static const WCHAR WesternW[] = {'W','e','s','t','e','r','n','\0'};
274 static const WCHAR OEM_DOSW[] = {'O','E','M','/','D','O','S','\0'};
275
276 static const WCHAR *ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits */
277     WesternW, /*00*/
278     Central_EuropeanW,
279     CyrillicW,
280     GreekW,
281     TurkishW,
282     HebrewW,
283     ArabicW,
284     BalticW,
285     VietnameseW, /*08*/
286     NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/
287     ThaiW,
288     JapaneseW,
289     CHINESE_GB2312W,
290     HangulW,
291     CHINESE_BIG5W,
292     Hangul_Johab_W,
293     NULL, NULL, /*23*/
294     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
295     SymbolW /*31*/
296 };
297
298 typedef struct {
299   WCHAR *name;
300   INT charset;
301 } NameCs;
302
303 typedef struct tagFontSubst {
304   NameCs from;
305   NameCs to;
306   struct tagFontSubst *next;
307 } FontSubst;
308
309 static FontSubst *substlist = NULL;
310 static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail if this is still FALSE */
311
312 static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'};
313
314
315 /****************************************
316  *   Notes on .fon files
317  *
318  * The fonts System, FixedSys and Terminal are special.  There are typically multiple
319  * versions installed for different resolutions and codepages.  Windows stores which one to use
320  * in HKEY_CURRENT_CONFIG\\Software\\Fonts.
321  *    Key            Meaning
322  *  FIXEDFON.FON    FixedSys
323  *  FONTS.FON       System
324  *  OEMFONT.FON     Termial
325  *  LogPixels       Current dpi set by the display control panel applet
326  *                  (HKLM\\Software\\Microsft\\Windows NT\\CurrentVersion\\FontDPI
327  *                  also has a LogPixels value that appears to mirror this)
328  *
329  * On my system these values have data: vgafix.fon, vgasys.fon, vga850.fon and 96 respectively
330  * (vgaoem.fon would be your oemfont.fon if you have a US setup).
331  * If the resolution is changed to be >= 109dpi then the fonts goto 8514fix, 8514sys and 8514oem
332  * (not sure what's happening to the oem codepage here). 109 is nicely halfway between 96 and 120dpi,
333  * so that makes sense.
334  *
335  * Additionally Windows also loads the fonts listed in the [386enh] section of system.ini (this doesn't appear
336  * to be mapped into the registry on Windows 2000 at least).
337  * I have
338  * woafont=app850.fon
339  * ega80woa.fon=ega80850.fon
340  * ega40woa.fon=ega40850.fon
341  * cga80woa.fon=cga80850.fon
342  * cga40woa.fon=cga40850.fon
343  */
344
345
346 static inline BOOL is_win9x(void)
347 {
348     return GetVersion() & 0x80000000;
349 }
350 /* 
351    This function builds an FT_Fixed from a float. It puts the integer part
352    in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed.
353    It fails if the integer part of the float number is greater than SHORT_MAX.
354 */
355 static inline FT_Fixed FT_FixedFromFloat(float f)
356 {
357         short value = f;
358         unsigned short fract = (f - value) * 0xFFFF;
359         return (FT_Fixed)((long)value << 16 | (unsigned long)fract);
360 }
361
362 /* 
363    This function builds an FT_Fixed from a FIXED. It simply put f.value 
364    in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
365 */
366 static inline FT_Fixed FT_FixedFromFIXED(FIXED f)
367 {
368         return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
369 }
370
371 #define ADDFONT_EXTERNAL_FONT 0x01
372 #define ADDFONT_FORCE_BITMAP  0x02
373 static BOOL AddFontFileToList(const char *file, char *fake_family, DWORD flags)
374 {
375     FT_Face ft_face;
376     TT_OS2 *pOS2;
377     TT_Header *pHeader = NULL;
378     WCHAR *FamilyW, *StyleW;
379     DWORD len;
380     Family **pfamily;
381     Face **insertface, *next;
382     FT_Error err;
383     FT_Long face_index = 0, num_faces;
384 #ifdef HAVE_FREETYPE_FTWINFNT_H
385     FT_WinFNT_HeaderRec winfnt_header;
386 #endif
387     int i, bitmap_num;
388
389     do {
390         char *family_name = fake_family;
391
392         TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
393         if((err = pFT_New_Face(library, file, face_index, &ft_face)) != 0) {
394             WARN("Unable to load font file %s err = %x\n", debugstr_a(file), err);
395             return FALSE;
396         }
397
398         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*/
399             pFT_Done_Face(ft_face);
400             return FALSE;
401         }
402
403         /* There are too many bugs in FreeType < 2.1.9 for bitmap font support */
404         if(!FT_IS_SCALABLE(ft_face) && FT_SimpleVersion < ((2 << 16) | (1 << 8) | (9 << 0))) {
405             pFT_Done_Face(ft_face);
406             return FALSE;
407         }
408
409         if(FT_IS_SFNT(ft_face) && (!pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2) ||
410            !pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea) ||
411            !(pHeader = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_head)))) {
412             TRACE("Font file %s lacks either an OS2, HHEA or HEAD table.\n"
413                   "Skipping this font.\n", debugstr_a(file));
414             pFT_Done_Face(ft_face);
415             return FALSE;
416         }
417
418         if(!ft_face->family_name || !ft_face->style_name) {
419             TRACE("Font file %s lacks either a family or style name\n", debugstr_a(file));
420             pFT_Done_Face(ft_face);
421             return FALSE;
422         }
423
424         if(!family_name)
425             family_name = ft_face->family_name;
426
427         bitmap_num = 0;
428         do {
429             My_FT_Bitmap_Size *size = NULL;
430
431             if(!FT_IS_SCALABLE(ft_face))
432                 size = (My_FT_Bitmap_Size *)ft_face->available_sizes + bitmap_num;
433
434             len = MultiByteToWideChar(CP_ACP, 0, family_name, -1, NULL, 0);
435             FamilyW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
436             MultiByteToWideChar(CP_ACP, 0, family_name, -1, FamilyW, len);
437
438             pfamily = &FontList;
439             while(*pfamily) {
440                 if(!strcmpW((*pfamily)->FamilyName, FamilyW))
441                     break;
442                 pfamily = &(*pfamily)->next;
443             }
444             if(!*pfamily) {
445                 *pfamily = HeapAlloc(GetProcessHeap(), 0, sizeof(**pfamily));
446                 (*pfamily)->FamilyName = FamilyW;
447                 (*pfamily)->FirstFace = NULL;
448                 (*pfamily)->next = NULL;
449             } else {
450                 HeapFree(GetProcessHeap(), 0, FamilyW);
451             }
452
453             len = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0);
454             StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
455             MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
456
457             next = NULL;
458             for(insertface = &(*pfamily)->FirstFace; *insertface;
459                 insertface = &(*insertface)->next) {
460                 if(!strcmpW((*insertface)->StyleName, StyleW) && (FT_IS_SCALABLE(ft_face) || (size->y_ppem == (*insertface)->size.y_ppem))) {
461                     TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
462                           debugstr_w((*pfamily)->FamilyName), debugstr_w(StyleW),
463                           (*insertface)->font_version,  pHeader ? pHeader->Font_Revision : 0);
464
465                     if(fake_family) {
466                         TRACE("This font is a replacement but the original really exists, so we'll skip the replacement\n");
467                         HeapFree(GetProcessHeap(), 0, StyleW);
468                         pFT_Done_Face(ft_face);
469                         return FALSE;
470                     }
471                     if(!pHeader || pHeader->Font_Revision <= (*insertface)->font_version) {
472                         TRACE("Original font is newer so skipping this one\n");
473                         HeapFree(GetProcessHeap(), 0, StyleW);
474                         pFT_Done_Face(ft_face);
475                         return FALSE;
476                     } else {
477                         TRACE("Replacing original with this one\n");
478                         next = (*insertface)->next;
479                         HeapFree(GetProcessHeap(), 0, (*insertface)->file);
480                         HeapFree(GetProcessHeap(), 0, (*insertface)->StyleName);
481                         HeapFree(GetProcessHeap(), 0, *insertface);
482                         break;
483                     }
484                 }
485             }
486             *insertface = HeapAlloc(GetProcessHeap(), 0, sizeof(**insertface));
487             (*insertface)->StyleName = StyleW;
488             (*insertface)->file = HeapAlloc(GetProcessHeap(),0,strlen(file)+1);
489             strcpy((*insertface)->file, file);
490             (*insertface)->face_index = face_index;
491             (*insertface)->next = next;
492             (*insertface)->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
493             (*insertface)->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0;
494             (*insertface)->font_version = pHeader ? pHeader->Font_Revision : 0;
495             (*insertface)->family = *pfamily;
496             (*insertface)->external = (flags & ADDFONT_EXTERNAL_FONT) ? TRUE : FALSE;
497
498             if(FT_IS_SCALABLE(ft_face)) {
499                 memset(&(*insertface)->size, 0, sizeof((*insertface)->size));
500                 (*insertface)->scalable = TRUE;
501             } else {
502                 TRACE("Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld\n",
503                       size->height, size->width, size->size >> 6,
504                       size->x_ppem >> 6, size->y_ppem >> 6);
505                 (*insertface)->size.height = size->height;
506                 (*insertface)->size.width = size->width;
507                 (*insertface)->size.size = size->size;
508                 (*insertface)->size.x_ppem = size->x_ppem;
509                 (*insertface)->size.y_ppem = size->y_ppem;
510                 (*insertface)->size.internal_leading = 0;
511                 (*insertface)->scalable = FALSE;
512             }
513
514             memset(&(*insertface)->fs, 0, sizeof((*insertface)->fs));
515
516             pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
517             if(pOS2) {
518                 (*insertface)->fs.fsCsb[0] = pOS2->ulCodePageRange1;
519                 (*insertface)->fs.fsCsb[1] = pOS2->ulCodePageRange2;
520                 (*insertface)->fs.fsUsb[0] = pOS2->ulUnicodeRange1;
521                 (*insertface)->fs.fsUsb[1] = pOS2->ulUnicodeRange2;
522                 (*insertface)->fs.fsUsb[2] = pOS2->ulUnicodeRange3;
523                 (*insertface)->fs.fsUsb[3] = pOS2->ulUnicodeRange4;
524                 if(pOS2->version == 0) {
525                     FT_UInt dummy;
526
527                     if(!pFT_Get_First_Char || (pFT_Get_First_Char( ft_face, &dummy ) < 0x100))
528                         (*insertface)->fs.fsCsb[0] |= 1;
529                     else
530                         (*insertface)->fs.fsCsb[0] |= 1L << 31;
531                 }
532             }
533 #ifdef HAVE_FREETYPE_FTWINFNT_H
534             else if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header)) {
535                 CHARSETINFO csi;
536                 TRACE("pix_h %d charset %d dpi %dx%d pt %d\n", winfnt_header.pixel_height, winfnt_header.charset,
537                       winfnt_header.vertical_resolution,winfnt_header.horizontal_resolution, winfnt_header.nominal_point_size);
538                 if(TranslateCharsetInfo((DWORD*)(UINT)winfnt_header.charset, &csi, TCI_SRCCHARSET))
539                     memcpy(&(*insertface)->fs, &csi.fs, sizeof(csi.fs));
540                 (*insertface)->size.internal_leading = winfnt_header.internal_leading;
541             }
542 #endif
543             TRACE("fsCsb = %08lx %08lx/%08lx %08lx %08lx %08lx\n",
544                   (*insertface)->fs.fsCsb[0], (*insertface)->fs.fsCsb[1],
545                   (*insertface)->fs.fsUsb[0], (*insertface)->fs.fsUsb[1],
546                   (*insertface)->fs.fsUsb[2], (*insertface)->fs.fsUsb[3]);
547
548
549             if((*insertface)->fs.fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */
550                 for(i = 0; i < ft_face->num_charmaps; i++) {
551                     switch(ft_face->charmaps[i]->encoding) {
552                     case ft_encoding_unicode:
553                     case ft_encoding_apple_roman:
554                         (*insertface)->fs.fsCsb[0] |= 1;
555                         break;
556                     case ft_encoding_symbol:
557                         (*insertface)->fs.fsCsb[0] |= 1L << 31;
558                         break;
559                     default:
560                         break;
561                     }
562                 }
563             }
564
565             if((*insertface)->fs.fsCsb[0] & ~(1L << 31))
566                 have_installed_roman_font = TRUE;
567         } while(!FT_IS_SCALABLE(ft_face) && ++bitmap_num < ft_face->num_fixed_sizes);
568
569         num_faces = ft_face->num_faces;
570         pFT_Done_Face(ft_face);
571         TRACE("Added font %s %s\n", debugstr_w((*pfamily)->FamilyName),
572               debugstr_w(StyleW));
573     } while(num_faces > ++face_index);
574     return TRUE;
575 }
576
577 static void DumpFontList(void)
578 {
579     Family *family;
580     Face *face;
581
582     for(family = FontList; family; family = family->next) {
583         TRACE("Family: %s\n", debugstr_w(family->FamilyName));
584         for(face = family->FirstFace; face; face = face->next) {
585             TRACE("\t%s", debugstr_w(face->StyleName));
586             if(!face->scalable)
587                 TRACE(" %ld", face->size.y_ppem >> 6);
588             TRACE("\n");
589         }
590     }
591     return;
592 }
593
594 static void DumpSubstList(void)
595 {
596     FontSubst *psub;
597
598     for(psub = substlist; psub; psub = psub->next)
599         if(psub->from.charset != -1 || psub->to.charset != -1)
600             TRACE("%s:%d -> %s:%d\n", debugstr_w(psub->from.name),
601               psub->from.charset, debugstr_w(psub->to.name), psub->to.charset);
602         else
603             TRACE("%s -> %s\n", debugstr_w(psub->from.name),
604                   debugstr_w(psub->to.name));
605     return;
606 }
607
608 static LPWSTR strdupW(LPWSTR p)
609 {
610     LPWSTR ret;
611     DWORD len = (strlenW(p) + 1) * sizeof(WCHAR);
612     ret = HeapAlloc(GetProcessHeap(), 0, len);
613     memcpy(ret, p, len);
614     return ret;
615 }
616
617 static void split_subst_info(NameCs *nc, LPSTR str)
618 {
619     CHAR *p = strrchr(str, ',');
620     DWORD len;
621
622     nc->charset = -1;
623     if(p && *(p+1)) {
624         nc->charset = strtol(p+1, NULL, 10);
625         *p = '\0';
626     }
627     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
628     nc->name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
629     MultiByteToWideChar(CP_ACP, 0, str, -1, nc->name, len);
630 }
631
632 static void LoadSubstList(void)
633 {
634     FontSubst *psub, **ppsub;
635     HKEY hkey;
636     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
637     LPSTR value;
638     LPVOID data;
639
640     if(substlist) {
641         for(psub = substlist; psub;) {
642             FontSubst *ptmp;
643             HeapFree(GetProcessHeap(), 0, psub->to.name);
644             HeapFree(GetProcessHeap(), 0, psub->from.name);
645             ptmp = psub;
646             psub = psub->next;
647             HeapFree(GetProcessHeap(), 0, ptmp);
648         }
649         substlist = NULL;
650     }
651
652     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
653                    "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes",
654                    &hkey) == ERROR_SUCCESS) {
655
656         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
657                          &valuelen, &datalen, NULL, NULL);
658
659         valuelen++; /* returned value doesn't include room for '\0' */
660         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
661         data = HeapAlloc(GetProcessHeap(), 0, datalen);
662
663         dlen = datalen;
664         vlen = valuelen;
665         ppsub = &substlist;
666         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
667                             &dlen) == ERROR_SUCCESS) {
668             TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
669
670             *ppsub = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppsub));
671             (*ppsub)->next = NULL;
672             split_subst_info(&((*ppsub)->from), value);
673             split_subst_info(&((*ppsub)->to), data);
674
675             /* Win 2000 doesn't allow mapping between different charsets
676                or mapping of DEFAULT_CHARSET */
677             if(((*ppsub)->to.charset != (*ppsub)->from.charset) ||
678                (*ppsub)->to.charset == DEFAULT_CHARSET) {
679                 HeapFree(GetProcessHeap(), 0, (*ppsub)->to.name);
680                 HeapFree(GetProcessHeap(), 0, (*ppsub)->from.name);
681                 HeapFree(GetProcessHeap(), 0, *ppsub);
682                 *ppsub = NULL;
683             } else {
684                 ppsub = &((*ppsub)->next);
685             }
686             /* reset dlen and vlen */
687             dlen = datalen;
688             vlen = valuelen;
689         }
690         HeapFree(GetProcessHeap(), 0, data);
691         HeapFree(GetProcessHeap(), 0, value);
692         RegCloseKey(hkey);
693     }
694 }
695
696 /***********************************************************
697  * The replacement list is a way to map an entire font
698  * family onto another family.  For example adding
699  *
700  * [HKLM\Software\Wine\Wine\FontReplacements]
701  * "Wingdings"="Winedings"
702  *
703  * would enumerate the Winedings font both as Winedings and
704  * Wingdings.  However if a real Wingdings font is present the
705  * replacement does not take place.
706  * 
707  */
708 static void LoadReplaceList(void)
709 {
710     HKEY hkey;
711     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
712     LPSTR value;
713     LPVOID data;
714     Family *family;
715     Face *face;
716     WCHAR old_nameW[200];
717
718     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
719                    "Software\\Wine\\Wine\\FontReplacements",
720                    &hkey) == ERROR_SUCCESS) {
721
722         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
723                          &valuelen, &datalen, NULL, NULL);
724
725         valuelen++; /* returned value doesn't include room for '\0' */
726         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
727         data = HeapAlloc(GetProcessHeap(), 0, datalen);
728
729         dlen = datalen;
730         vlen = valuelen;
731         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
732                             &dlen) == ERROR_SUCCESS) {
733             TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
734             /* "NewName"="Oldname" */
735             if(!MultiByteToWideChar(CP_ACP, 0, data, -1, old_nameW, sizeof(old_nameW)))
736                 break;
737
738             /* Find the old family and hence all of the font files
739                in that family */
740             for(family = FontList; family; family = family->next) {
741                 if(!strcmpiW(family->FamilyName, old_nameW)) {
742                     for(face = family->FirstFace; face; face = face->next) {
743                         TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName),
744                               debugstr_w(face->StyleName), value);
745                         /* Now add a new entry with the new family name */
746                         AddFontFileToList(face->file, value, ADDFONT_FORCE_BITMAP | (face->external ? ADDFONT_EXTERNAL_FONT : 0));
747                     }
748                     break;
749                 }
750             }
751             /* reset dlen and vlen */
752             dlen = datalen;
753             vlen = valuelen;
754         }
755         HeapFree(GetProcessHeap(), 0, data);
756         HeapFree(GetProcessHeap(), 0, value);
757         RegCloseKey(hkey);
758     }
759 }
760
761
762 static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
763 {
764     DIR *dir;
765     struct dirent *dent;
766     char path[MAX_PATH];
767
768     TRACE("Loading fonts from %s\n", debugstr_a(dirname));
769
770     dir = opendir(dirname);
771     if(!dir) {
772         ERR("Can't open directory %s\n", debugstr_a(dirname));
773         return FALSE;
774     }
775     while((dent = readdir(dir)) != NULL) {
776         struct stat statbuf;
777
778         if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
779             continue;
780
781         TRACE("Found %s in %s\n", debugstr_a(dent->d_name), debugstr_a(dirname));
782
783         sprintf(path, "%s/%s", dirname, dent->d_name);
784
785         if(stat(path, &statbuf) == -1)
786         {
787             WARN("Can't stat %s\n", debugstr_a(path));
788             continue;
789         }
790         if(S_ISDIR(statbuf.st_mode))
791             ReadFontDir(path, external_fonts);
792         else
793             AddFontFileToList(path, NULL, external_fonts ? ADDFONT_EXTERNAL_FONT : 0);
794     }
795     closedir(dir);
796     return TRUE;
797 }
798
799 static void load_fontconfig_fonts(void)
800 {
801 #ifdef HAVE_FONTCONFIG_FONTCONFIG_H
802     void *fc_handle = NULL;
803     FcConfig *config;
804     FcPattern *pat;
805     FcObjectSet *os;
806     FcFontSet *fontset;
807     FcValue v;
808     int i, len;
809     const char *ext;
810
811     fc_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0);
812     if(!fc_handle) {
813         TRACE("Wine cannot find the fontconfig library (%s).\n",
814               SONAME_LIBFONTCONFIG);
815         return;
816     }
817 #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;}
818 LOAD_FUNCPTR(FcConfigGetCurrent);
819 LOAD_FUNCPTR(FcFontList);
820 LOAD_FUNCPTR(FcFontSetDestroy);
821 LOAD_FUNCPTR(FcInit);
822 LOAD_FUNCPTR(FcObjectSetAdd);
823 LOAD_FUNCPTR(FcObjectSetCreate);
824 LOAD_FUNCPTR(FcObjectSetDestroy);
825 LOAD_FUNCPTR(FcPatternCreate);
826 LOAD_FUNCPTR(FcPatternDestroy);
827 LOAD_FUNCPTR(FcPatternGet);
828 #undef LOAD_FUNCPTR
829
830     if(!pFcInit()) return;
831     
832     config = pFcConfigGetCurrent();
833     pat = pFcPatternCreate();
834     os = pFcObjectSetCreate();
835     pFcObjectSetAdd(os, FC_FILE);
836     fontset = pFcFontList(config, pat, os);
837     if(!fontset) return;
838     for(i = 0; i < fontset->nfont; i++) {
839         if(pFcPatternGet(fontset->fonts[i], FC_FILE, 0, &v) != FcResultMatch)
840             continue;
841         if(v.type != FcTypeString) continue;
842         TRACE("fontconfig: %s\n", v.u.s);
843
844         /* We're just interested in OT/TT fonts for now, so this hack just
845            picks up the standard extensions to save time loading every other
846            font */
847         len = strlen(v.u.s);
848         if(len < 4) continue;
849         ext = v.u.s + len - 3;
850         if(!strcasecmp(ext, "ttf") || !strcasecmp(ext, "ttc") || !strcasecmp(ext, "otf"))
851             AddFontFileToList(v.u.s, NULL, ADDFONT_EXTERNAL_FONT);
852     }
853     pFcFontSetDestroy(fontset);
854     pFcObjectSetDestroy(os);
855     pFcPatternDestroy(pat);
856  sym_not_found:
857 #endif
858     return;
859 }
860
861
862 void load_system_fonts(void)
863 {
864     HKEY hkey;
865     WCHAR data[MAX_PATH], windowsdir[MAX_PATH], pathW[MAX_PATH];
866     const WCHAR **value;
867     DWORD dlen, type;
868     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
869     char *unixname;
870
871     if(RegOpenKeyW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, &hkey) == ERROR_SUCCESS) {
872         GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
873         strcatW(windowsdir, fontsW);
874         for(value = SystemFontValues; *value; value++) { 
875             dlen = sizeof(data);
876             if(RegQueryValueExW(hkey, *value, 0, &type, (void*)data, &dlen) == ERROR_SUCCESS &&
877                type == REG_SZ) {
878                 sprintfW(pathW, fmtW, windowsdir, data);
879                 if((unixname = wine_get_unix_file_name(pathW))) {
880                     AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
881                     HeapFree(GetProcessHeap(), 0, unixname);
882                 }
883             }
884         }
885         RegCloseKey(hkey);
886     }
887 }
888
889 /*************************************************************
890  *
891  * This adds registry entries for any externally loaded fonts
892  * (fonts from fontconfig or FontDirs).  It also deletes entries
893  * of no longer existing fonts.
894  *
895  */
896 void update_reg_entries(void)
897 {
898     HKEY winkey = 0, externalkey = 0;
899     LPWSTR valueW;
900     LPVOID data;
901     DWORD dlen, vlen, datalen, valuelen, i, type, len, len_fam;
902     Family *family;
903     Face *face;
904     WCHAR *file;
905     static const WCHAR TrueType[] = {' ','(','T','r','u','e','T','y','p','e',')','\0'};
906     static const WCHAR spaceW[] = {' ', '\0'};
907     char *path;
908
909     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
910                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &winkey, NULL) != ERROR_SUCCESS) {
911         ERR("Can't create Windows font reg key\n");
912         goto end;
913     }
914     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, external_fonts_reg_key,
915                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &externalkey, NULL) != ERROR_SUCCESS) {
916         ERR("Can't create external font reg key\n");
917         goto end;
918     }
919
920     /* Delete all external fonts added last time */
921
922     RegQueryInfoKeyW(externalkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
923                      &valuelen, &datalen, NULL, NULL);
924     valuelen++; /* returned value doesn't include room for '\0' */
925     valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
926     data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
927
928     dlen = datalen * sizeof(WCHAR);
929     vlen = valuelen;
930     i = 0;
931     while(RegEnumValueW(externalkey, i++, valueW, &vlen, NULL, &type, data,
932                         &dlen) == ERROR_SUCCESS) {
933
934         RegDeleteValueW(winkey, valueW);
935         /* reset dlen and vlen */
936         dlen = datalen;
937         vlen = valuelen;
938     }
939     HeapFree(GetProcessHeap(), 0, data);
940     HeapFree(GetProcessHeap(), 0, valueW);
941
942     /* Delete the old external fonts key */
943     RegCloseKey(externalkey);
944     externalkey = 0;
945     RegDeleteKeyW(HKEY_LOCAL_MACHINE, external_fonts_reg_key);
946
947     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, external_fonts_reg_key,
948                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &externalkey, NULL) != ERROR_SUCCESS) {
949         ERR("Can't create external font reg key\n");
950         goto end;
951     }
952
953     /* enumerate the fonts and add external ones to the two keys */
954
955     for(family = FontList; family; family = family->next) {
956         len_fam = strlenW(family->FamilyName) + sizeof(TrueType) / sizeof(WCHAR) + 1;
957         for(face = family->FirstFace; face; face = face->next) {
958             if(!face->external) continue;
959             len = len_fam;
960             if(strcmpiW(face->StyleName, RegularW))
961                 len = len_fam + strlenW(face->StyleName) + 1;
962             valueW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
963             strcpyW(valueW, family->FamilyName);
964             if(len != len_fam) {
965                 strcatW(valueW, spaceW);
966                 strcatW(valueW, face->StyleName);
967             }
968             strcatW(valueW, TrueType);
969             if((path = strrchr(face->file, '/')) == NULL)
970                 path = face->file;
971             else
972                 path++;
973             len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
974
975             file = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
976             MultiByteToWideChar(CP_ACP, 0, path, -1, file, len);
977             RegSetValueExW(winkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
978             RegSetValueExW(externalkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
979
980             HeapFree(GetProcessHeap(), 0, file);
981             HeapFree(GetProcessHeap(), 0, valueW);
982         }
983     }
984  end:
985     if(externalkey)
986         RegCloseKey(externalkey);
987     if(winkey)
988         RegCloseKey(winkey);
989     return;
990 }
991
992
993 /*************************************************************
994  *    WineEngAddFontResourceEx
995  *
996  */
997 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
998 {
999     if (ft_handle)  /* do it only if we have freetype up and running */
1000     {
1001         char *unixname;
1002
1003         if(flags)
1004             FIXME("Ignoring flags %lx\n", flags);
1005
1006         if((unixname = wine_get_unix_file_name(file)))
1007         {
1008             AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1009             HeapFree(GetProcessHeap(), 0, unixname);
1010         }
1011     }
1012     return 1;
1013 }
1014
1015 /*************************************************************
1016  *    WineEngRemoveFontResourceEx
1017  *
1018  */
1019 BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
1020 {
1021     FIXME(":stub\n");
1022     return TRUE;
1023 }
1024
1025 /*************************************************************
1026  *    WineEngInit
1027  *
1028  * Initialize FreeType library and create a list of available faces
1029  */
1030 BOOL WineEngInit(void)
1031 {
1032     static const WCHAR dot_fonW[] = {'.','f','o','n','\0'};
1033     HKEY hkey;
1034     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
1035     LPVOID data;
1036     WCHAR windowsdir[MAX_PATH];
1037     char *unixname;
1038     HANDLE font_mutex;
1039
1040     TRACE("\n");
1041
1042     ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0);
1043     if(!ft_handle) {
1044         WINE_MESSAGE(
1045       "Wine cannot find the FreeType font library.  To enable Wine to\n"
1046       "use TrueType fonts please install a version of FreeType greater than\n"
1047       "or equal to 2.0.5.\n"
1048       "http://www.freetype.org\n");
1049         return FALSE;
1050     }
1051
1052 #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;}
1053
1054     LOAD_FUNCPTR(FT_Vector_Unit)
1055     LOAD_FUNCPTR(FT_Done_Face)
1056     LOAD_FUNCPTR(FT_Get_Char_Index)
1057     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
1058     LOAD_FUNCPTR(FT_Init_FreeType)
1059     LOAD_FUNCPTR(FT_Load_Glyph)
1060     LOAD_FUNCPTR(FT_Matrix_Multiply)
1061     LOAD_FUNCPTR(FT_MulFix)
1062     LOAD_FUNCPTR(FT_New_Face)
1063     LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
1064     LOAD_FUNCPTR(FT_Outline_Transform)
1065     LOAD_FUNCPTR(FT_Outline_Translate)
1066     LOAD_FUNCPTR(FT_Select_Charmap)
1067     LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
1068     LOAD_FUNCPTR(FT_Vector_Transform)
1069
1070 #undef LOAD_FUNCPTR
1071     /* Don't warn if this one is missing */
1072     pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0);
1073     pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0);
1074     pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0);
1075 #ifdef HAVE_FREETYPE_FTWINFNT_H
1076     pFT_Get_WinFNT_Header = wine_dlsym(ft_handle, "FT_Get_WinFNT_Header", NULL, 0);
1077 #endif
1078       if(!wine_dlsym(ft_handle, "FT_Get_Postscript_Name", NULL, 0) &&
1079          !wine_dlsym(ft_handle, "FT_Sqrt64", NULL, 0)) {
1080         /* try to avoid 2.0.4: >= 2.0.5 has FT_Get_Postscript_Name and
1081            <= 2.0.3 has FT_Sqrt64 */
1082           goto sym_not_found;
1083       }
1084
1085     if(pFT_Init_FreeType(&library) != 0) {
1086         ERR("Can't init FreeType library\n");
1087         wine_dlclose(ft_handle, NULL, 0);
1088         ft_handle = NULL;
1089         return FALSE;
1090     }
1091     FT_Version.major=FT_Version.minor=FT_Version.patch=-1;
1092     if (pFT_Library_Version)
1093     {
1094         pFT_Library_Version(library,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
1095     }
1096     if (FT_Version.major<=0)
1097     {
1098         FT_Version.major=2;
1099         FT_Version.minor=0;
1100         FT_Version.patch=5;
1101     }
1102     TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
1103     FT_SimpleVersion = ((FT_Version.major << 16) & 0xff0000) |
1104                        ((FT_Version.minor <<  8) & 0x00ff00) |
1105                        ((FT_Version.patch      ) & 0x0000ff);
1106
1107     if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) {
1108         ERR("Failed to create font mutex\n");
1109         return FALSE;
1110     }
1111     WaitForSingleObject(font_mutex, INFINITE);
1112
1113     /* load the system fonts */
1114     load_system_fonts();
1115
1116     /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
1117     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
1118     strcatW(windowsdir, fontsW);
1119     if((unixname = wine_get_unix_file_name(windowsdir)))
1120     {
1121         ReadFontDir(unixname, FALSE);
1122         HeapFree(GetProcessHeap(), 0, unixname);
1123     }
1124
1125     /* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
1126        for any fonts not installed in %WINDOWSDIR%\Fonts.  They will have their
1127        full path as the entry.  Also look for any .fon fonts, since ReadFontDir
1128        will skip these. */
1129     if(RegOpenKeyW(HKEY_LOCAL_MACHINE,
1130                    is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
1131                    &hkey) == ERROR_SUCCESS) {
1132         LPWSTR valueW;
1133         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1134                          &valuelen, &datalen, NULL, NULL);
1135
1136         valuelen++; /* returned value doesn't include room for '\0' */
1137         valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
1138         data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
1139         if (valueW && data)
1140         {
1141             dlen = datalen * sizeof(WCHAR);
1142             vlen = valuelen;
1143             while(RegEnumValueW(hkey, i++, valueW, &vlen, NULL, &type, data,
1144                                 &dlen) == ERROR_SUCCESS) {
1145                 if(((LPWSTR)data)[0] && ((LPWSTR)data)[1] == ':')
1146                 {
1147                     if((unixname = wine_get_unix_file_name((LPWSTR)data)))
1148                     {
1149                         AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1150                         HeapFree(GetProcessHeap(), 0, unixname);
1151                     }
1152                 }
1153                 else if(dlen / 2 >= 6 && !strcmpiW(((LPWSTR)data) + dlen / 2 - 5, dot_fonW))
1154                 {
1155                     WCHAR pathW[MAX_PATH];
1156                     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
1157                     sprintfW(pathW, fmtW, windowsdir, data);
1158                     if((unixname = wine_get_unix_file_name(pathW)))
1159                     {
1160                         AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
1161                         HeapFree(GetProcessHeap(), 0, unixname);
1162                     }
1163                 }
1164                 /* reset dlen and vlen */
1165                 dlen = datalen;
1166                 vlen = valuelen;
1167             }
1168         }
1169         if (data) HeapFree(GetProcessHeap(), 0, data);
1170         if (valueW) HeapFree(GetProcessHeap(), 0, valueW);
1171         RegCloseKey(hkey);
1172     }
1173
1174     load_fontconfig_fonts();
1175
1176     /* then look in any directories that we've specified in the config file */
1177     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
1178                    "Software\\Wine\\Wine\\Config\\FontDirs",
1179                    &hkey) == ERROR_SUCCESS) {
1180         LPSTR value;
1181         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1182                          &valuelen, &datalen, NULL, NULL);
1183
1184         valuelen++; /* returned value doesn't include room for '\0' */
1185         value = HeapAlloc(GetProcessHeap(), 0, valuelen);
1186         data = HeapAlloc(GetProcessHeap(), 0, datalen);
1187
1188         dlen = datalen;
1189         vlen = valuelen;
1190         i = 0;
1191         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
1192                             &dlen) == ERROR_SUCCESS) {
1193             TRACE("Got %s=%s\n", value, (LPSTR)data);
1194             ReadFontDir((LPSTR)data, TRUE);
1195             /* reset dlen and vlen */
1196             dlen = datalen;
1197             vlen = valuelen;
1198         }
1199         HeapFree(GetProcessHeap(), 0, data);
1200         HeapFree(GetProcessHeap(), 0, value);
1201         RegCloseKey(hkey);
1202     }
1203
1204     DumpFontList();
1205     LoadSubstList();
1206     DumpSubstList();
1207     LoadReplaceList();
1208     update_reg_entries();
1209
1210     ReleaseMutex(font_mutex);
1211     return TRUE;
1212 sym_not_found:
1213     WINE_MESSAGE(
1214       "Wine cannot find certain functions that it needs inside the FreeType\n"
1215       "font library.  To enable Wine to use TrueType fonts please upgrade\n"
1216       "FreeType to at least version 2.0.5.\n"
1217       "http://www.freetype.org\n");
1218     wine_dlclose(ft_handle, NULL, 0);
1219     ft_handle = NULL;
1220     return FALSE;
1221 }
1222
1223
1224 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
1225 {
1226     TT_OS2 *pOS2;
1227     TT_HoriHeader *pHori;
1228
1229     LONG ppem;
1230
1231     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
1232     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
1233
1234     if(height == 0) height = 16;
1235
1236     /* Calc. height of EM square:
1237      *
1238      * For +ve lfHeight we have
1239      * lfHeight = (winAscent + winDescent) * ppem / units_per_em
1240      * Re-arranging gives:
1241      * ppem = units_per_em * lfheight / (winAscent + winDescent)
1242      *
1243      * For -ve lfHeight we have
1244      * |lfHeight| = ppem
1245      * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
1246      * with il = winAscent + winDescent - units_per_em]
1247      *
1248      */
1249
1250     if(height > 0) {
1251         if(pOS2->usWinAscent + pOS2->usWinDescent == 0)
1252             ppem = ft_face->units_per_EM * height /
1253                 (pHori->Ascender - pHori->Descender);
1254         else
1255             ppem = ft_face->units_per_EM * height /
1256                 (pOS2->usWinAscent + pOS2->usWinDescent);
1257     }
1258     else
1259         ppem = -height;
1260
1261     return ppem;
1262 }
1263
1264 static LONG load_VDMX(GdiFont, LONG);
1265
1266 static FT_Face OpenFontFile(GdiFont font, char *file, FT_Long face_index, LONG width, LONG height)
1267 {
1268     FT_Error err;
1269     FT_Face ft_face;
1270     LONG ppem;
1271
1272     err = pFT_New_Face(library, file, face_index, &ft_face);
1273     if(err) {
1274         ERR("FT_New_Face rets %d\n", err);
1275         return 0;
1276     }
1277
1278     /* set it here, as load_VDMX needs it */
1279     font->ft_face = ft_face;
1280
1281     if(FT_IS_SCALABLE(ft_face)) {
1282         /* load the VDMX table if we have one */
1283         ppem = load_VDMX(font, height);
1284         if(ppem == 0)
1285             ppem = calc_ppem_for_height(ft_face, height);
1286
1287         if((err = pFT_Set_Pixel_Sizes(ft_face, 0, ppem)) != 0)
1288             WARN("FT_Set_Pixel_Sizes %d, %ld rets %x\n", 0, ppem, err);
1289     } else {
1290         if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
1291             WARN("FT_Set_Pixel_Sizes %ld, %ld rets %x\n", width, height, err);
1292     }
1293     return ft_face;
1294 }
1295
1296
1297 static int get_nearest_charset(Face *face)
1298 {
1299   /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
1300      a single face with the requested charset.  The idea is to check if
1301      the selected font supports the current ANSI codepage, if it does
1302      return the corresponding charset, else return the first charset */
1303
1304     CHARSETINFO csi;
1305     int acp = GetACP(), i;
1306     DWORD fs0;
1307
1308     if(TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE))
1309         if(csi.fs.fsCsb[0] & face->fs.fsCsb[0])
1310             return csi.ciCharset;
1311
1312     for(i = 0; i < 32; i++) {
1313         fs0 = 1L << i;
1314         if(face->fs.fsCsb[0] & fs0) {
1315             if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG))
1316                 return csi.ciCharset;
1317             else
1318                 FIXME("TCI failing on %lx\n", fs0);
1319         }
1320     }
1321
1322     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08lx file = %s\n",
1323           face->fs.fsCsb[0], face->file);
1324     return DEFAULT_CHARSET;
1325 }
1326
1327 static GdiFont alloc_font(void)
1328 {
1329     GdiFont ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
1330     ret->gmsize = INIT_GM_SIZE;
1331     ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1332                         ret->gmsize * sizeof(*ret->gm));
1333     ret->potm = NULL;
1334     ret->xform.eM11 = ret->xform.eM22 = 1.0;
1335     return ret;
1336 }
1337
1338 static void free_font(GdiFont font)
1339 {
1340     if (font->ft_face) pFT_Done_Face(font->ft_face);
1341     if (font->potm) HeapFree(GetProcessHeap(), 0, font->potm);
1342     if (font->name) HeapFree(GetProcessHeap(), 0, font->name);
1343     HeapFree(GetProcessHeap(), 0, font->gm);
1344     HeapFree(GetProcessHeap(), 0, font);
1345 }
1346
1347
1348 /*************************************************************
1349  * load_VDMX
1350  *
1351  * load the vdmx entry for the specified height
1352  */
1353
1354 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
1355           ( ( (FT_ULong)_x4 << 24 ) |     \
1356             ( (FT_ULong)_x3 << 16 ) |     \
1357             ( (FT_ULong)_x2 <<  8 ) |     \
1358               (FT_ULong)_x1         )
1359
1360 #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X')
1361
1362 typedef struct {
1363     BYTE bCharSet;
1364     BYTE xRatio;
1365     BYTE yStartRatio;
1366     BYTE yEndRatio;
1367 } Ratios;
1368
1369
1370 static LONG load_VDMX(GdiFont font, LONG height)
1371 {
1372     BYTE hdr[6], tmp[2], group[4];
1373     BYTE devXRatio, devYRatio;
1374     USHORT numRecs, numRatios;
1375     DWORD offset = -1;
1376     LONG ppem = 0;
1377     int i, result;
1378
1379     result = WineEngGetFontData(font, MS_VDMX_TAG, 0, hdr, 6);
1380
1381     if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
1382         return ppem;
1383
1384     /* FIXME: need the real device aspect ratio */
1385     devXRatio = 1;
1386     devYRatio = 1;
1387
1388     numRecs = GET_BE_WORD(&hdr[2]);
1389     numRatios = GET_BE_WORD(&hdr[4]);
1390
1391     TRACE("numRecs = %d numRatios = %d\n", numRecs, numRatios);
1392     for(i = 0; i < numRatios; i++) {
1393         Ratios ratio;
1394
1395         offset = (3 * 2) + (i * sizeof(Ratios));
1396         WineEngGetFontData(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
1397         offset = -1;
1398
1399         TRACE("Ratios[%d] %d  %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
1400
1401         if(ratio.bCharSet != 1)
1402             continue;
1403
1404         if((ratio.xRatio == 0 &&
1405             ratio.yStartRatio == 0 &&
1406             ratio.yEndRatio == 0) ||
1407            (devXRatio == ratio.xRatio &&
1408             devYRatio >= ratio.yStartRatio &&
1409             devYRatio <= ratio.yEndRatio))
1410             {
1411                 offset = (3 * 2) + (numRatios * 4) + (i * 2);
1412                 WineEngGetFontData(font, MS_VDMX_TAG, offset, tmp, 2);
1413                 offset = GET_BE_WORD(tmp);
1414                 break;
1415             }
1416     }
1417
1418     if(offset < 0) {
1419         FIXME("No suitable ratio found\n");
1420         return ppem;
1421     }
1422
1423     if(WineEngGetFontData(font, MS_VDMX_TAG, offset, group, 4) != GDI_ERROR) {
1424         USHORT recs;
1425         BYTE startsz, endsz;
1426         BYTE *vTable;
1427
1428         recs = GET_BE_WORD(group);
1429         startsz = group[2];
1430         endsz = group[3];
1431
1432         TRACE("recs=%d  startsz=%d  endsz=%d\n", recs, startsz, endsz);
1433
1434         vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6);
1435         result = WineEngGetFontData(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6);
1436         if(result == GDI_ERROR) {
1437             FIXME("Failed to retrieve vTable\n");
1438             goto end;
1439         }
1440
1441         if(height > 0) {
1442             for(i = 0; i < recs; i++) {
1443                 SHORT yMax = GET_BE_WORD(&vTable[(i * 6) + 2]);
1444                 SHORT yMin = GET_BE_WORD(&vTable[(i * 6) + 4]);
1445                 ppem = GET_BE_WORD(&vTable[i * 6]);
1446
1447                 if(yMax + -yMin == height) {
1448                     font->yMax = yMax;
1449                     font->yMin = yMin;
1450                     TRACE("ppem %ld found; height=%ld  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
1451                     break;
1452                 }
1453                 if(yMax + -yMin > height) {
1454                     if(--i < 0) {
1455                         ppem = 0;
1456                         goto end; /* failed */
1457                     }
1458                     font->yMax = GET_BE_WORD(&vTable[(i * 6) + 2]);
1459                     font->yMin = GET_BE_WORD(&vTable[(i * 6) + 4]);
1460                     TRACE("ppem %ld found; height=%ld  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
1461                     break;
1462                 }
1463             }
1464             if(!font->yMax) {
1465                 ppem = 0;
1466                 TRACE("ppem not found for height %ld\n", height);
1467             }
1468         } else {
1469             ppem = -height;
1470             if(ppem < startsz || ppem > endsz)
1471                 goto end;
1472
1473             for(i = 0; i < recs; i++) {
1474                 USHORT yPelHeight;
1475                 yPelHeight = GET_BE_WORD(&vTable[i * 6]);
1476
1477                 if(yPelHeight > ppem)
1478                     break; /* failed */
1479
1480                 if(yPelHeight == ppem) {
1481                     font->yMax = GET_BE_WORD(&vTable[(i * 6) + 2]);
1482                     font->yMin = GET_BE_WORD(&vTable[(i * 6) + 4]);
1483                     TRACE("ppem %ld found; yMax=%d  yMin=%d\n", ppem, font->yMax, font->yMin);
1484                     break;
1485                 }
1486             }
1487         }
1488         end:
1489         HeapFree(GetProcessHeap(), 0, vTable);
1490     }
1491
1492     return ppem;
1493 }
1494
1495
1496 /*************************************************************
1497  * WineEngCreateFontInstance
1498  *
1499  */
1500 GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
1501 {
1502     GdiFont ret;
1503     Face *face, *best;
1504     Family *family = NULL;
1505     INT height, width = 0;
1506     signed int diff = 0, newdiff;
1507     BOOL bd, it, can_use_bitmap;
1508     LOGFONTW lf;
1509     CHARSETINFO csi;
1510     struct list *elem_ptr;
1511
1512     if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
1513     can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
1514
1515     TRACE("%s, h=%ld, it=%d, weight=%ld, PandF=%02x, charset=%d orient %ld escapement %ld\n",
1516           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
1517           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
1518           lf.lfEscapement);
1519
1520     /* check the cache first */
1521     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
1522         ret = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
1523         if(ret->hfont == hfont && !memcmp(&ret->xform, &dc->xformWorld2Vport, offsetof(XFORM, eDx)) &&
1524            (can_use_bitmap || FT_IS_SCALABLE(ret->ft_face))) {
1525
1526             TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
1527             return ret;
1528         }
1529     }
1530
1531     if(!FontList || !have_installed_roman_font) /* No fonts installed */
1532     {
1533         TRACE("No fonts installed\n");
1534         return NULL;
1535     }
1536
1537     ret = alloc_font();
1538     memcpy(&ret->xform, &dc->xformWorld2Vport, sizeof(XFORM));
1539
1540     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
1541        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
1542        original value lfCharSet.  Note this is a special case for
1543        Symbol and doesn't happen at least for "Wingdings*" */
1544
1545     if(!strcmpiW(lf.lfFaceName, SymbolW))
1546         lf.lfCharSet = SYMBOL_CHARSET;
1547
1548     if(!TranslateCharsetInfo((DWORD*)(INT)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
1549         switch(lf.lfCharSet) {
1550         case DEFAULT_CHARSET:
1551             csi.fs.fsCsb[0] = 0;
1552             break;
1553         default:
1554             FIXME("Untranslated charset %d\n", lf.lfCharSet);
1555             csi.fs.fsCsb[0] = 0;
1556             break;
1557         }
1558     }
1559
1560     if(lf.lfFaceName[0] != '\0') {
1561         FontSubst *psub;
1562         for(psub = substlist; psub; psub = psub->next)
1563             if(!strcmpiW(lf.lfFaceName, psub->from.name) &&
1564                (psub->from.charset == -1 ||
1565                 psub->from.charset == lf.lfCharSet))
1566               break;
1567         if(psub) {
1568             TRACE("substituting %s -> %s\n", debugstr_w(lf.lfFaceName),
1569                   debugstr_w(psub->to.name));
1570             strcpyW(lf.lfFaceName, psub->to.name);
1571         }
1572
1573         /* We want a match on name and charset or just name if
1574            charset was DEFAULT_CHARSET.  If the latter then
1575            we fixup the returned charset later in get_nearest_charset
1576            where we'll either use the charset of the current ansi codepage
1577            or if that's unavailable the first charset that the font supports.
1578         */
1579         for(family = FontList; family; family = family->next) {
1580             if(!strcmpiW(family->FamilyName, lf.lfFaceName))
1581                 if((csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) || !csi.fs.fsCsb[0])
1582                     if(family->FirstFace->scalable || can_use_bitmap)
1583                         break;
1584         }
1585     }
1586
1587     if(!family) {
1588       /* If requested charset was DEFAULT_CHARSET then try using charset
1589          corresponding to the current ansi codepage */
1590         if(!csi.fs.fsCsb[0]) {
1591             INT acp = GetACP();
1592             if(!TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE)) {
1593                 FIXME("TCI failed on codepage %d\n", acp);
1594                 csi.fs.fsCsb[0] = 0;
1595             } else
1596                 lf.lfCharSet = csi.ciCharset;
1597         }
1598
1599                 /* Face families are in the top 4 bits of lfPitchAndFamily,
1600                    so mask with 0xF0 before testing */
1601
1602         if((lf.lfPitchAndFamily & FIXED_PITCH) ||
1603            (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
1604           strcpyW(lf.lfFaceName, defFixed);
1605         else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
1606           strcpyW(lf.lfFaceName, defSerif);
1607         else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
1608           strcpyW(lf.lfFaceName, defSans);
1609         else
1610           strcpyW(lf.lfFaceName, defSans);
1611         for(family = FontList; family; family = family->next) {
1612             if(!strcmpiW(family->FamilyName, lf.lfFaceName) &&
1613                (csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]))
1614                     if(family->FirstFace->scalable || can_use_bitmap)
1615                         break;
1616         }
1617     }
1618
1619     if(!family) {
1620         for(family = FontList; family; family = family->next) {
1621             if(csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0])
1622                 if(family->FirstFace->scalable || can_use_bitmap)
1623                     break;
1624         }
1625     }
1626
1627     if(!family) {
1628         family = FontList;
1629         csi.fs.fsCsb[0] = 0;
1630         FIXME("just using first face for now\n");
1631     }
1632
1633     it = lf.lfItalic ? 1 : 0;
1634     bd = lf.lfWeight > 550 ? 1 : 0;
1635
1636     height = GDI_ROUND( (FLOAT)lf.lfHeight * dc->xformWorld2Vport.eM22 );
1637     height = lf.lfHeight < 0 ? -abs(height) : abs(height);
1638
1639     best = NULL;
1640     for(face = family->FirstFace; face; face = face->next) {
1641         if(!(face->Italic ^ it) && !(face->Bold ^ bd)) {
1642             if(face->scalable)
1643                 break;
1644             if(height > 0)
1645                 newdiff = height - (signed int)(face->size.y_ppem >> 6);
1646             else
1647                 newdiff = -height - ((signed int)(face->size.y_ppem >> 6) - face->size.internal_leading);
1648             if(!best || (diff > 0 && newdiff < diff && newdiff >= 0) ||
1649                (diff < 0 && newdiff > diff)) {
1650                 TRACE("%ld is better for %d diff was %d\n", face->size.y_ppem >> 6, height, diff);
1651                 diff = newdiff;
1652                 best = face;
1653                 if(diff == 0)
1654                     break;
1655             }
1656         }
1657     }
1658     if(!face && best)
1659         face = best;
1660     else if(!face) {
1661         face = family->FirstFace;
1662         if(it && !face->Italic) ret->fake_italic = TRUE;
1663         if(bd && !face->Bold) ret->fake_bold = TRUE;
1664     }
1665
1666     memcpy(&ret->fs, &face->fs, sizeof(FONTSIGNATURE));
1667
1668     if(csi.fs.fsCsb[0])
1669         ret->charset = lf.lfCharSet;
1670     else
1671         ret->charset = get_nearest_charset(face);
1672
1673     TRACE("Chosen: %s %s\n", debugstr_w(family->FamilyName),
1674           debugstr_w(face->StyleName));
1675
1676     if(!face->scalable) {
1677         width = face->size.x_ppem >> 6;
1678         height = face->size.y_ppem >> 6;
1679     }
1680     ret->ft_face = OpenFontFile(ret, face->file, face->face_index, width, height);
1681
1682     if (!ret->ft_face)
1683     {
1684         free_font( ret );
1685         return 0;
1686     }
1687
1688     if (ret->charset == SYMBOL_CHARSET && 
1689         !pFT_Select_Charmap(ret->ft_face, ft_encoding_symbol)) {
1690         /* No ops */
1691     }
1692     else if (!pFT_Select_Charmap(ret->ft_face, ft_encoding_unicode)) {
1693         /* No ops */
1694     }
1695     else {
1696         pFT_Select_Charmap(ret->ft_face, ft_encoding_apple_roman);
1697     }
1698
1699     ret->orientation = lf.lfOrientation;
1700     ret->name = strdupW(family->FamilyName);
1701     ret->underline = lf.lfUnderline ? 0xff : 0;
1702     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
1703
1704     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
1705     ret->hfont = hfont;
1706     ret->aveWidth= lf.lfWidth;
1707     list_add_head(&gdi_font_list, &ret->entry);
1708     return ret;
1709 }
1710
1711 static void dump_gdi_font_list(void)
1712 {
1713     GdiFont gdiFont;
1714     LOGFONTW lf;
1715     struct list *elem_ptr;
1716
1717     TRACE("---------- gdiFont Cache ----------\n");
1718     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
1719         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
1720         GetObjectW( gdiFont->hfont, sizeof(lf), &lf );
1721         TRACE("gdiFont=%p  hfont=%p (%s)\n",
1722                gdiFont, gdiFont->hfont, debugstr_w(lf.lfFaceName));
1723     }
1724 }
1725
1726 /*************************************************************
1727  * WineEngDestroyFontInstance
1728  *
1729  * free the gdiFont associated with this handle
1730  *
1731  */
1732 BOOL WineEngDestroyFontInstance(HFONT handle)
1733 {
1734     GdiFont gdiFont;
1735     BOOL ret = FALSE;
1736     struct list *elem_ptr;
1737
1738     TRACE("destroying hfont=%p\n", handle);
1739     if(TRACE_ON(font))
1740         dump_gdi_font_list();
1741
1742     elem_ptr = list_head(&gdi_font_list);
1743     while(elem_ptr) {
1744         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
1745         elem_ptr = list_next(&gdi_font_list, elem_ptr);
1746         if(gdiFont->hfont == handle) {
1747             list_remove(&gdiFont->entry);
1748             free_font(gdiFont);
1749             ret = TRUE;
1750         }
1751     }
1752     return ret;
1753 }
1754
1755 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
1756                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
1757 {
1758     OUTLINETEXTMETRICW *potm = NULL;
1759     UINT size;
1760     TEXTMETRICW tm, *ptm;
1761     GdiFont font = alloc_font();
1762     LONG width, height;
1763
1764     if(face->scalable) {
1765         height = 100;
1766         width = 0;
1767     } else {
1768         height = face->size.y_ppem >> 6;
1769         width = face->size.x_ppem >> 6;
1770     }
1771     
1772     if (!(font->ft_face = OpenFontFile(font, face->file, face->face_index, width, height)))
1773     {
1774         free_font(font);
1775         return;
1776     }
1777
1778     font->name = strdupW(face->family->FamilyName);
1779
1780     memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
1781
1782     size = WineEngGetOutlineTextMetrics(font, 0, NULL);
1783     if(size) {
1784         potm = HeapAlloc(GetProcessHeap(), 0, size);
1785         WineEngGetOutlineTextMetrics(font, size, potm);
1786         ptm = (TEXTMETRICW*)&potm->otmTextMetrics;
1787     } else {
1788         WineEngGetTextMetrics(font, &tm);
1789         ptm = &tm;
1790     }
1791         
1792     pntm->ntmTm.tmHeight = pelf->elfLogFont.lfHeight = ptm->tmHeight;
1793     pntm->ntmTm.tmAscent = ptm->tmAscent;
1794     pntm->ntmTm.tmDescent = ptm->tmDescent;
1795     pntm->ntmTm.tmInternalLeading = ptm->tmInternalLeading;
1796     pntm->ntmTm.tmExternalLeading = ptm->tmExternalLeading;
1797     pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWidth = ptm->tmAveCharWidth;
1798     pntm->ntmTm.tmMaxCharWidth = ptm->tmMaxCharWidth;
1799     pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = ptm->tmWeight;
1800     pntm->ntmTm.tmOverhang = ptm->tmOverhang;
1801     pntm->ntmTm.tmDigitizedAspectX = ptm->tmDigitizedAspectX;
1802     pntm->ntmTm.tmDigitizedAspectY = ptm->tmDigitizedAspectY;
1803     pntm->ntmTm.tmFirstChar = ptm->tmFirstChar;
1804     pntm->ntmTm.tmLastChar = ptm->tmLastChar;
1805     pntm->ntmTm.tmDefaultChar = ptm->tmDefaultChar;
1806     pntm->ntmTm.tmBreakChar = ptm->tmBreakChar;
1807     pntm->ntmTm.tmItalic = pelf->elfLogFont.lfItalic = ptm->tmItalic;
1808     pntm->ntmTm.tmUnderlined = pelf->elfLogFont.lfUnderline = ptm->tmUnderlined;
1809     pntm->ntmTm.tmStruckOut = pelf->elfLogFont.lfStrikeOut = ptm->tmStruckOut;
1810     pntm->ntmTm.tmPitchAndFamily = ptm->tmPitchAndFamily;
1811     pelf->elfLogFont.lfPitchAndFamily = (ptm->tmPitchAndFamily & 0xf1) + 1;
1812     pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = ptm->tmCharSet;
1813     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
1814     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
1815     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
1816
1817     *ptype = ptm->tmPitchAndFamily & TMPF_TRUETYPE ? TRUETYPE_FONTTYPE : 0;
1818     if(!(ptm->tmPitchAndFamily & TMPF_VECTOR))
1819         *ptype |= RASTER_FONTTYPE;
1820
1821     if(potm) {
1822         pntm->ntmTm.ntmFlags = ptm->tmItalic ? NTM_ITALIC : 0;
1823         if(ptm->tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD;
1824         if(pntm->ntmTm.ntmFlags == 0) pntm->ntmTm.ntmFlags = NTM_REGULAR;
1825
1826         pntm->ntmTm.ntmSizeEM = potm->otmEMSquare;
1827         pntm->ntmTm.ntmCellHeight = 0;
1828         pntm->ntmTm.ntmAvgWidth = 0;
1829
1830         memset(&pntm->ntmFontSig, 0, sizeof(FONTSIGNATURE));
1831
1832         strncpyW(pelf->elfLogFont.lfFaceName,
1833                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFamilyName),
1834                  LF_FACESIZE);
1835         strncpyW(pelf->elfFullName,
1836                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFaceName),
1837                  LF_FULLFACESIZE);
1838         strncpyW(pelf->elfStyle,
1839                  (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName),
1840                  LF_FACESIZE);
1841
1842     } else {
1843         strncpyW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
1844         strncpyW(pelf->elfFullName, face->family->FamilyName, LF_FACESIZE);
1845         pelf->elfStyle[0] = '\0';
1846     }
1847
1848     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
1849
1850     HeapFree(GetProcessHeap(), 0, potm);
1851     free_font(font);
1852     return;
1853 }
1854
1855 /*************************************************************
1856  * WineEngEnumFonts
1857  *
1858  */
1859 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
1860 {
1861     Family *family;
1862     Face *face;
1863     ENUMLOGFONTEXW elf;
1864     NEWTEXTMETRICEXW ntm;
1865     DWORD type, ret = 1;
1866     FONTSIGNATURE fs;
1867     CHARSETINFO csi;
1868     LOGFONTW lf;
1869     int i;
1870
1871     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
1872
1873     if(plf->lfFaceName[0]) {
1874         FontSubst *psub;
1875         for(psub = substlist; psub; psub = psub->next)
1876             if(!strcmpiW(plf->lfFaceName, psub->from.name) &&
1877                (psub->from.charset == -1 ||
1878                 psub->from.charset == plf->lfCharSet))
1879                 break;
1880         if(psub) {
1881             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
1882                   debugstr_w(psub->to.name));
1883             memcpy(&lf, plf, sizeof(lf));
1884             strcpyW(lf.lfFaceName, psub->to.name);
1885             plf = &lf;
1886         }
1887         for(family = FontList; family; family = family->next) {
1888             if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
1889                 for(face = family->FirstFace; face; face = face->next) {
1890                     GetEnumStructs(face, &elf, &ntm, &type);
1891                     for(i = 0; i < 32; i++) {
1892                         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
1893                             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
1894                             strcpyW(elf.elfScript, OEM_DOSW);
1895                             i = 32; /* break out of loop */
1896                         } else if(!(face->fs.fsCsb[0] & (1L << i)))
1897                             continue;
1898                         else {
1899                             fs.fsCsb[0] = 1L << i;
1900                             fs.fsCsb[1] = 0;
1901                             if(!TranslateCharsetInfo(fs.fsCsb, &csi,
1902                                                      TCI_SRCFONTSIG))
1903                                 csi.ciCharset = DEFAULT_CHARSET;
1904                             if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
1905                             if(csi.ciCharset != DEFAULT_CHARSET) {
1906                                 elf.elfLogFont.lfCharSet =
1907                                     ntm.ntmTm.tmCharSet = csi.ciCharset;
1908                                 if(ElfScriptsW[i])
1909                                     strcpyW(elf.elfScript, ElfScriptsW[i]);
1910                                 else
1911                                     FIXME("Unknown elfscript for bit %d\n", i);
1912                             }
1913                         }
1914                         TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
1915                               debugstr_w(elf.elfLogFont.lfFaceName),
1916                               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
1917                               csi.ciCharset, type, debugstr_w(elf.elfScript),
1918                               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
1919                               ntm.ntmTm.ntmFlags);
1920                         ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
1921                         if(!ret) goto end;
1922                     }
1923                 }
1924             }
1925         }
1926     } else {
1927         for(family = FontList; family; family = family->next) {
1928             GetEnumStructs(family->FirstFace, &elf, &ntm, &type);
1929             for(i = 0; i < 32; i++) {
1930                 if(!family->FirstFace->scalable && family->FirstFace->fs.fsCsb[0] == 0) { /* OEM bitmap */
1931                     elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
1932                     strcpyW(elf.elfScript, OEM_DOSW);
1933                     i = 32; /* break out of loop */
1934                 } else if(!(family->FirstFace->fs.fsCsb[0] & (1L << i)))
1935                     continue;
1936                 else {
1937                     fs.fsCsb[0] = 1L << i;
1938                     fs.fsCsb[1] = 0;
1939                     if(!TranslateCharsetInfo(fs.fsCsb, &csi,
1940                                              TCI_SRCFONTSIG))
1941                         csi.ciCharset = DEFAULT_CHARSET;
1942                     if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
1943                     if(csi.ciCharset != DEFAULT_CHARSET) {
1944                         elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet =
1945                           csi.ciCharset;
1946                           if(ElfScriptsW[i])
1947                               strcpyW(elf.elfScript, ElfScriptsW[i]);
1948                           else
1949                               FIXME("Unknown elfscript for bit %d\n", i);
1950                     }
1951                 }
1952                 TRACE("enuming face %s full %s style %s charset = %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
1953                       debugstr_w(elf.elfLogFont.lfFaceName),
1954                       debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
1955                       csi.ciCharset, type, debugstr_w(elf.elfScript),
1956                       elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
1957                       ntm.ntmTm.ntmFlags);
1958                 ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
1959                 if(!ret) goto end;
1960             }
1961         }
1962     }
1963 end:
1964     return ret;
1965 }
1966
1967 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
1968 {
1969     pt->x.value = vec->x >> 6;
1970     pt->x.fract = (vec->x & 0x3f) << 10;
1971     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
1972     pt->y.value = vec->y >> 6;
1973     pt->y.fract = (vec->y & 0x3f) << 10;
1974     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
1975     return;
1976 }
1977
1978 static FT_UInt get_glyph_index(GdiFont font, UINT glyph)
1979 {
1980     if(font->charset == SYMBOL_CHARSET && glyph < 0x100)
1981         glyph = glyph + 0xf000;
1982     return pFT_Get_Char_Index(font->ft_face, glyph);
1983 }
1984
1985 /*************************************************************
1986  * WineEngGetGlyphIndices
1987  *
1988  * FIXME: add support for GGI_MARK_NONEXISTING_GLYPHS
1989  */
1990 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
1991                                 LPWORD pgi, DWORD flags)
1992 {
1993     INT i;
1994
1995     for(i = 0; i < count; i++)
1996         pgi[i] = get_glyph_index(font, lpstr[i]);
1997
1998     return count;
1999 }
2000
2001 /*************************************************************
2002  * WineEngGetGlyphOutline
2003  *
2004  * Behaves in exactly the same way as the win32 api GetGlyphOutline
2005  * except that the first parameter is the HWINEENGFONT of the font in
2006  * question rather than an HDC.
2007  *
2008  */
2009 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
2010                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
2011                              const MAT2* lpmat)
2012 {
2013     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
2014     FT_Face ft_face = font->ft_face;
2015     FT_UInt glyph_index;
2016     DWORD width, height, pitch, needed = 0;
2017     FT_Bitmap ft_bitmap;
2018     FT_Error err;
2019     INT left, right, top = 0, bottom = 0;
2020     FT_Angle angle = 0;
2021     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
2022     float widthRatio = 1.0;
2023     FT_Matrix transMat = identityMat;
2024     BOOL needsTransform = FALSE;
2025
2026
2027     TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm,
2028           buflen, buf, lpmat);
2029
2030     if(format & GGO_GLYPH_INDEX) {
2031         glyph_index = glyph;
2032         format &= ~GGO_GLYPH_INDEX;
2033     } else
2034         glyph_index = get_glyph_index(font, glyph);
2035
2036     if(glyph_index >= font->gmsize) {
2037         font->gmsize = (glyph_index / INIT_GM_SIZE + 1) * INIT_GM_SIZE;
2038         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
2039                                font->gmsize * sizeof(*font->gm));
2040     } else {
2041         if(format == GGO_METRICS && font->gm[glyph_index].init) {
2042             memcpy(lpgm, &font->gm[glyph_index].gm, sizeof(*lpgm));
2043             return 1; /* FIXME */
2044         }
2045     }
2046
2047     if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP) || font->aveWidth || lpmat)
2048         load_flags |= FT_LOAD_NO_BITMAP;
2049
2050     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
2051
2052     if(err) {
2053         FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
2054         return GDI_ERROR;
2055     }
2056         
2057     /* Scaling factor */
2058     if (font->aveWidth && font->potm) {
2059              widthRatio = (float)font->aveWidth * font->xform.eM11 / (float) font->potm->otmTextMetrics.tmAveCharWidth;
2060     }
2061
2062     left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
2063     right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
2064
2065     font->gm[glyph_index].adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
2066     font->gm[glyph_index].lsb = left >> 6;
2067     font->gm[glyph_index].bbx = (right - left) >> 6;
2068
2069     /* Scaling transform */
2070     if(font->aveWidth) {
2071         FT_Matrix scaleMat;
2072         scaleMat.xx = FT_FixedFromFloat(widthRatio);
2073         scaleMat.xy = 0;
2074         scaleMat.yx = 0;
2075         scaleMat.yy = (1 << 16);
2076
2077         pFT_Matrix_Multiply(&scaleMat, &transMat);
2078         needsTransform = TRUE;
2079     }
2080
2081     /* Rotation transform */
2082     if(font->orientation) {
2083         FT_Matrix rotationMat;
2084         FT_Vector vecAngle;
2085         angle = FT_FixedFromFloat((float)font->orientation / 10.0);
2086         pFT_Vector_Unit(&vecAngle, angle);
2087         rotationMat.xx = vecAngle.x;
2088         rotationMat.xy = -vecAngle.y;
2089         rotationMat.yx = -rotationMat.xy;
2090         rotationMat.yy = rotationMat.xx;
2091         
2092         pFT_Matrix_Multiply(&rotationMat, &transMat);
2093         needsTransform = TRUE;
2094     }
2095
2096     /* Extra transformation specified by caller */
2097     if (lpmat) {
2098         FT_Matrix extraMat;
2099         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
2100         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
2101         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
2102         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
2103         pFT_Matrix_Multiply(&extraMat, &transMat);
2104         needsTransform = TRUE;
2105     }
2106
2107     if(!needsTransform) {
2108         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
2109         bottom = (ft_face->glyph->metrics.horiBearingY -
2110                   ft_face->glyph->metrics.height) & -64;
2111         lpgm->gmCellIncX = font->gm[glyph_index].adv;
2112         lpgm->gmCellIncY = 0;
2113     } else {
2114         INT xc, yc;
2115         FT_Vector vec;
2116         for(xc = 0; xc < 2; xc++) {
2117             for(yc = 0; yc < 2; yc++) {
2118                 vec.x = (ft_face->glyph->metrics.horiBearingX +
2119                   xc * ft_face->glyph->metrics.width);
2120                 vec.y = ft_face->glyph->metrics.horiBearingY -
2121                   yc * ft_face->glyph->metrics.height;
2122                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
2123                 pFT_Vector_Transform(&vec, &transMat);
2124                 if(xc == 0 && yc == 0) {
2125                     left = right = vec.x;
2126                     top = bottom = vec.y;
2127                 } else {
2128                     if(vec.x < left) left = vec.x;
2129                     else if(vec.x > right) right = vec.x;
2130                     if(vec.y < bottom) bottom = vec.y;
2131                     else if(vec.y > top) top = vec.y;
2132                 }
2133             }
2134         }
2135         left = left & -64;
2136         right = (right + 63) & -64;
2137         bottom = bottom & -64;
2138         top = (top + 63) & -64;
2139
2140         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
2141         vec.x = ft_face->glyph->metrics.horiAdvance;
2142         vec.y = 0;
2143         pFT_Vector_Transform(&vec, &transMat);
2144         lpgm->gmCellIncX = (vec.x+63) >> 6;
2145         lpgm->gmCellIncY = -((vec.y+63) >> 6);
2146     }
2147     lpgm->gmBlackBoxX = (right - left) >> 6;
2148     lpgm->gmBlackBoxY = (top - bottom) >> 6;
2149     lpgm->gmptGlyphOrigin.x = left >> 6;
2150     lpgm->gmptGlyphOrigin.y = top >> 6;
2151
2152     memcpy(&font->gm[glyph_index].gm, lpgm, sizeof(*lpgm));
2153     font->gm[glyph_index].init = TRUE;
2154
2155     if(format == GGO_METRICS)
2156         return 1; /* FIXME */
2157
2158     if (buf && !buflen){
2159         return GDI_ERROR;
2160     }
2161
2162     if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) {
2163         TRACE("loaded a bitmap\n");
2164         return GDI_ERROR;
2165     }
2166
2167     switch(format) {
2168     case GGO_BITMAP:
2169         width = lpgm->gmBlackBoxX;
2170         height = lpgm->gmBlackBoxY;
2171         pitch = ((width + 31) >> 5) << 2;
2172         needed = pitch * height;
2173
2174         if(!buf || !buflen) break;
2175
2176         switch(ft_face->glyph->format) {
2177         case ft_glyph_format_bitmap:
2178           {
2179             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
2180             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
2181             INT h = ft_face->glyph->bitmap.rows;
2182             while(h--) {
2183                 memcpy(dst, src, w);
2184                 src += ft_face->glyph->bitmap.pitch;
2185                 dst += pitch;
2186             }
2187             break;
2188           }
2189
2190         case ft_glyph_format_outline:
2191             ft_bitmap.width = width;
2192             ft_bitmap.rows = height;
2193             ft_bitmap.pitch = pitch;
2194             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
2195             ft_bitmap.buffer = buf;
2196
2197                 if(needsTransform) {
2198                         pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
2199             }
2200
2201             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
2202
2203             /* Note: FreeType will only set 'black' bits for us. */
2204             memset(buf, 0, needed);
2205             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
2206             break;
2207
2208         default:
2209             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
2210             return GDI_ERROR;
2211         }
2212         break;
2213
2214     case GGO_GRAY2_BITMAP:
2215     case GGO_GRAY4_BITMAP:
2216     case GGO_GRAY8_BITMAP:
2217     case WINE_GGO_GRAY16_BITMAP:
2218       {
2219         int mult, row, col;
2220         BYTE *start, *ptr;
2221
2222         width = lpgm->gmBlackBoxX;
2223         height = lpgm->gmBlackBoxY;
2224         pitch = (width + 3) / 4 * 4;
2225         needed = pitch * height;
2226
2227         if(!buf || !buflen) break;
2228         ft_bitmap.width = width;
2229         ft_bitmap.rows = height;
2230         ft_bitmap.pitch = pitch;
2231         ft_bitmap.pixel_mode = ft_pixel_mode_grays;
2232         ft_bitmap.buffer = buf;
2233
2234         if(needsTransform) {
2235                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
2236         }
2237
2238         pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
2239
2240         pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
2241
2242         if(format == GGO_GRAY2_BITMAP)
2243             mult = 5;
2244         else if(format == GGO_GRAY4_BITMAP)
2245             mult = 17;
2246         else if(format == GGO_GRAY8_BITMAP)
2247             mult = 65;
2248         else if(format == WINE_GGO_GRAY16_BITMAP)
2249             break;
2250         else {
2251             assert(0);
2252             break;
2253         }
2254
2255         start = buf;
2256         for(row = 0; row < height; row++) {
2257             ptr = start;
2258             for(col = 0; col < width; col++, ptr++) {
2259                 *ptr = (*(unsigned int*)ptr * mult + 128) / 256;
2260             }
2261             start += pitch;
2262         }
2263         break;
2264       }
2265
2266     case GGO_NATIVE:
2267       {
2268         int contour, point = 0, first_pt;
2269         FT_Outline *outline = &ft_face->glyph->outline;
2270         TTPOLYGONHEADER *pph;
2271         TTPOLYCURVE *ppc;
2272         DWORD pph_start, cpfx, type;
2273
2274         if(buflen == 0) buf = NULL;
2275
2276         if (needsTransform && buf) {
2277                 pFT_Outline_Transform(outline, &transMat);
2278         }
2279
2280         for(contour = 0; contour < outline->n_contours; contour++) {
2281             pph_start = needed;
2282             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
2283             first_pt = point;
2284             if(buf) {
2285                 pph->dwType = TT_POLYGON_TYPE;
2286                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
2287             }
2288             needed += sizeof(*pph);
2289             point++;
2290             while(point <= outline->contours[contour]) {
2291                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
2292                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
2293                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
2294                 cpfx = 0;
2295                 do {
2296                     if(buf)
2297                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
2298                     cpfx++;
2299                     point++;
2300                 } while(point <= outline->contours[contour] &&
2301                         (outline->tags[point] & FT_Curve_Tag_On) ==
2302                         (outline->tags[point-1] & FT_Curve_Tag_On));
2303                 /* At the end of a contour Windows adds the start point, but
2304                    only for Beziers */
2305                 if(point > outline->contours[contour] &&
2306                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
2307                     if(buf)
2308                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
2309                     cpfx++;
2310                 } else if(point <= outline->contours[contour] &&
2311                           outline->tags[point] & FT_Curve_Tag_On) {
2312                   /* add closing pt for bezier */
2313                     if(buf)
2314                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
2315                     cpfx++;
2316                     point++;
2317                 }
2318                 if(buf) {
2319                     ppc->wType = type;
2320                     ppc->cpfx = cpfx;
2321                 }
2322                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
2323             }
2324             if(buf)
2325                 pph->cb = needed - pph_start;
2326         }
2327         break;
2328       }
2329     case GGO_BEZIER:
2330       {
2331         /* Convert the quadratic Beziers to cubic Beziers.
2332            The parametric eqn for a cubic Bezier is, from PLRM:
2333            r(t) = at^3 + bt^2 + ct + r0
2334            with the control points:
2335            r1 = r0 + c/3
2336            r2 = r1 + (c + b)/3
2337            r3 = r0 + c + b + a
2338
2339            A quadratic Beizer has the form:
2340            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
2341
2342            So equating powers of t leads to:
2343            r1 = 2/3 p1 + 1/3 p0
2344            r2 = 2/3 p1 + 1/3 p2
2345            and of course r0 = p0, r3 = p2
2346         */
2347
2348         int contour, point = 0, first_pt;
2349         FT_Outline *outline = &ft_face->glyph->outline;
2350         TTPOLYGONHEADER *pph;
2351         TTPOLYCURVE *ppc;
2352         DWORD pph_start, cpfx, type;
2353         FT_Vector cubic_control[4];
2354         if(buflen == 0) buf = NULL;
2355
2356         if (needsTransform && buf) {
2357                 pFT_Outline_Transform(outline, &transMat);
2358         }
2359
2360         for(contour = 0; contour < outline->n_contours; contour++) {
2361             pph_start = needed;
2362             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
2363             first_pt = point;
2364             if(buf) {
2365                 pph->dwType = TT_POLYGON_TYPE;
2366                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
2367             }
2368             needed += sizeof(*pph);
2369             point++;
2370             while(point <= outline->contours[contour]) {
2371                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
2372                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
2373                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
2374                 cpfx = 0;
2375                 do {
2376                     if(type == TT_PRIM_LINE) {
2377                         if(buf)
2378                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
2379                         cpfx++;
2380                         point++;
2381                     } else {
2382                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
2383                          so cpfx = 3n */
2384
2385                       /* FIXME: Possible optimization in endpoint calculation
2386                          if there are two consecutive curves */
2387                         cubic_control[0] = outline->points[point-1];
2388                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
2389                             cubic_control[0].x += outline->points[point].x + 1;
2390                             cubic_control[0].y += outline->points[point].y + 1;
2391                             cubic_control[0].x >>= 1;
2392                             cubic_control[0].y >>= 1;
2393                         }
2394                         if(point+1 > outline->contours[contour])
2395                             cubic_control[3] = outline->points[first_pt];
2396                         else {
2397                             cubic_control[3] = outline->points[point+1];
2398                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
2399                                 cubic_control[3].x += outline->points[point].x + 1;
2400                                 cubic_control[3].y += outline->points[point].y + 1;
2401                                 cubic_control[3].x >>= 1;
2402                                 cubic_control[3].y >>= 1;
2403                             }
2404                         }
2405                         /* r1 = 1/3 p0 + 2/3 p1
2406                            r2 = 1/3 p2 + 2/3 p1 */
2407                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
2408                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
2409                         cubic_control[2] = cubic_control[1];
2410                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
2411                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
2412                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
2413                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
2414                         if(buf) {
2415                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
2416                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
2417                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
2418                         }
2419                         cpfx += 3;
2420                         point++;
2421                     }
2422                 } while(point <= outline->contours[contour] &&
2423                         (outline->tags[point] & FT_Curve_Tag_On) ==
2424                         (outline->tags[point-1] & FT_Curve_Tag_On));
2425                 /* At the end of a contour Windows adds the start point,
2426                    but only for Beziers and we've already done that.
2427                 */
2428                 if(point <= outline->contours[contour] &&
2429                    outline->tags[point] & FT_Curve_Tag_On) {
2430                   /* This is the closing pt of a bezier, but we've already
2431                      added it, so just inc point and carry on */
2432                     point++;
2433                 }
2434                 if(buf) {
2435                     ppc->wType = type;
2436                     ppc->cpfx = cpfx;
2437                 }
2438                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
2439             }
2440             if(buf)
2441                 pph->cb = needed - pph_start;
2442         }
2443         break;
2444       }
2445
2446     default:
2447         FIXME("Unsupported format %d\n", format);
2448         return GDI_ERROR;
2449     }
2450     return needed;
2451 }
2452
2453 static BOOL get_bitmap_text_metrics(GdiFont font)
2454 {
2455     FT_Face ft_face = font->ft_face;
2456 #ifdef HAVE_FREETYPE_FTWINFNT_H
2457     FT_WinFNT_HeaderRec winfnt_header;
2458 #endif
2459     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
2460     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
2461     font->potm->otmSize = size;
2462
2463 #define TM font->potm->otmTextMetrics
2464 #ifdef HAVE_FREETYPE_FTWINFNT_H
2465     if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
2466     {
2467         TM.tmHeight = winfnt_header.pixel_height;
2468         TM.tmAscent = winfnt_header.ascent;
2469         TM.tmDescent = TM.tmHeight - TM.tmAscent;
2470         TM.tmInternalLeading = winfnt_header.internal_leading;
2471         TM.tmExternalLeading = winfnt_header.external_leading;
2472         TM.tmAveCharWidth = winfnt_header.avg_width;
2473         TM.tmMaxCharWidth = winfnt_header.max_width;
2474         TM.tmWeight = winfnt_header.weight;
2475         TM.tmOverhang = 0;
2476         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
2477         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
2478         TM.tmFirstChar = winfnt_header.first_char;
2479         TM.tmLastChar = winfnt_header.last_char;
2480         TM.tmDefaultChar = winfnt_header.default_char;
2481         TM.tmBreakChar = winfnt_header.break_char;
2482         TM.tmItalic = winfnt_header.italic;
2483         TM.tmUnderlined = font->underline;
2484         TM.tmStruckOut = font->strikeout;
2485         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
2486         TM.tmCharSet = winfnt_header.charset;
2487     }
2488     else
2489 #endif
2490     {
2491         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
2492         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
2493         TM.tmHeight = TM.tmAscent + TM.tmDescent;
2494         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
2495         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
2496         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
2497         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
2498         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
2499         TM.tmOverhang = 0;
2500         TM.tmDigitizedAspectX = 96; /* FIXME */
2501         TM.tmDigitizedAspectY = 96; /* FIXME */
2502         TM.tmFirstChar = 1;
2503         TM.tmLastChar = 255;
2504         TM.tmDefaultChar = 32;
2505         TM.tmBreakChar = 32;
2506         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
2507         TM.tmUnderlined = font->underline;
2508         TM.tmStruckOut = font->strikeout;
2509         /* NB inverted meaning of TMPF_FIXED_PITCH */
2510         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
2511         TM.tmCharSet = font->charset;
2512     }
2513 #undef TM
2514
2515     return TRUE;
2516 }
2517
2518 /*************************************************************
2519  * WineEngGetTextMetrics
2520  *
2521  */
2522 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
2523 {
2524     if(!font->potm) {
2525         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
2526             if(!get_bitmap_text_metrics(font))
2527                 return FALSE;
2528     }
2529     if(!font->potm) return FALSE;
2530     memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm));
2531
2532     if (font->aveWidth) {
2533              ptm->tmAveCharWidth = font->aveWidth * font->xform.eM11;
2534     }
2535     return TRUE;
2536 }
2537
2538
2539 /*************************************************************
2540  * WineEngGetOutlineTextMetrics
2541  *
2542  */
2543 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
2544                                   OUTLINETEXTMETRICW *potm)
2545 {
2546     FT_Face ft_face = font->ft_face;
2547     UINT needed, lenfam, lensty, ret;
2548     TT_OS2 *pOS2;
2549     TT_HoriHeader *pHori;
2550     TT_Postscript *pPost;
2551     FT_Fixed x_scale, y_scale;
2552     WCHAR *family_nameW, *style_nameW;
2553     static const WCHAR spaceW[] = {' ', '\0'};
2554     char *cp;
2555     INT ascent, descent;
2556
2557     TRACE("font=%p\n", font);
2558
2559     if(!FT_IS_SCALABLE(ft_face))
2560         return 0;
2561
2562     if(font->potm) {
2563         if(cbSize >= font->potm->otmSize)
2564             memcpy(potm, font->potm, font->potm->otmSize);
2565         return font->potm->otmSize;
2566     }
2567
2568
2569     needed = sizeof(*potm);
2570
2571     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
2572     family_nameW = strdupW(font->name);
2573
2574     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
2575       * sizeof(WCHAR);
2576     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
2577     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
2578                         style_nameW, lensty);
2579
2580     /* These names should be read from the TT name table */
2581
2582     /* length of otmpFamilyName */
2583     needed += lenfam;
2584
2585     /* length of otmpFaceName */
2586     if(!strcasecmp(ft_face->style_name, "regular")) {
2587       needed += lenfam; /* just the family name */
2588     } else {
2589       needed += lenfam + lensty; /* family + " " + style */
2590     }
2591
2592     /* length of otmpStyleName */
2593     needed += lensty;
2594
2595     /* length of otmpFullName */
2596     needed += lenfam + lensty;
2597
2598
2599     x_scale = ft_face->size->metrics.x_scale;
2600     y_scale = ft_face->size->metrics.y_scale;
2601
2602     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
2603     if(!pOS2) {
2604         FIXME("Can't find OS/2 table - not TT font?\n");
2605         ret = 0;
2606         goto end;
2607     }
2608
2609     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
2610     if(!pHori) {
2611         FIXME("Can't find HHEA table - not TT font?\n");
2612         ret = 0;
2613         goto end;
2614     }
2615
2616     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
2617
2618     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",
2619           pOS2->usWinAscent, pOS2->usWinDescent,
2620           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
2621           ft_face->ascender, ft_face->descender, ft_face->height,
2622           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
2623           ft_face->bbox.yMax, ft_face->bbox.yMin);
2624
2625     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
2626     font->potm->otmSize = needed;
2627
2628 #define TM font->potm->otmTextMetrics
2629
2630     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
2631         ascent = pHori->Ascender;
2632         descent = -pHori->Descender;
2633     } else {
2634         ascent = pOS2->usWinAscent;
2635         descent = pOS2->usWinDescent;
2636     }
2637
2638     if(font->yMax) {
2639         TM.tmAscent = font->yMax;
2640         TM.tmDescent = -font->yMin;
2641         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
2642     } else {
2643         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
2644         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
2645         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
2646                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
2647     }
2648
2649     TM.tmHeight = TM.tmAscent + TM.tmDescent;
2650
2651     /* MSDN says:
2652      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
2653     */
2654     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
2655                  ((ascent + descent) -
2656                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
2657
2658     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
2659     if (TM.tmAveCharWidth == 0) {
2660         TM.tmAveCharWidth = 1; 
2661     }
2662     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
2663     TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
2664     TM.tmOverhang = 0;
2665     TM.tmDigitizedAspectX = 300;
2666     TM.tmDigitizedAspectY = 300;
2667     TM.tmFirstChar = pOS2->usFirstCharIndex;
2668     TM.tmLastChar = pOS2->usLastCharIndex;
2669     TM.tmDefaultChar = pOS2->usDefaultChar;
2670     TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
2671     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
2672     TM.tmUnderlined = font->underline;
2673     TM.tmStruckOut = font->strikeout;
2674
2675     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
2676     if(!FT_IS_FIXED_WIDTH(ft_face))
2677         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
2678     else
2679         TM.tmPitchAndFamily = 0;
2680
2681     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
2682     case PAN_FAMILY_SCRIPT:
2683         TM.tmPitchAndFamily |= FF_SCRIPT;
2684         break;
2685     case PAN_FAMILY_DECORATIVE:
2686     case PAN_FAMILY_PICTORIAL:
2687         TM.tmPitchAndFamily |= FF_DECORATIVE;
2688         break;
2689     case PAN_FAMILY_TEXT_DISPLAY:
2690         if(TM.tmPitchAndFamily == 0) /* fixed */
2691             TM.tmPitchAndFamily = FF_MODERN;
2692         else {
2693             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
2694             case PAN_SERIF_NORMAL_SANS:
2695             case PAN_SERIF_OBTUSE_SANS:
2696             case PAN_SERIF_PERP_SANS:
2697                 TM.tmPitchAndFamily |= FF_SWISS;
2698                 break;
2699             default:
2700                 TM.tmPitchAndFamily |= FF_ROMAN;
2701             }
2702         }
2703         break;
2704     default:
2705         TM.tmPitchAndFamily |= FF_DONTCARE;
2706     }
2707
2708     if(FT_IS_SCALABLE(ft_face))
2709         TM.tmPitchAndFamily |= TMPF_VECTOR;
2710     if(FT_IS_SFNT(ft_face))
2711         TM.tmPitchAndFamily |= TMPF_TRUETYPE;
2712
2713     TM.tmCharSet = font->charset;
2714 #undef TM
2715
2716     font->potm->otmFiller = 0;
2717     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
2718     font->potm->otmfsSelection = pOS2->fsSelection;
2719     font->potm->otmfsType = pOS2->fsType;
2720     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
2721     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
2722     font->potm->otmItalicAngle = 0; /* POST table */
2723     font->potm->otmEMSquare = ft_face->units_per_EM;
2724     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
2725     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
2726     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
2727     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
2728     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
2729     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
2730     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
2731     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
2732     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
2733     font->potm->otmMacAscent = 0; /* where do these come from ? */
2734     font->potm->otmMacDescent = 0;
2735     font->potm->otmMacLineGap = 0;
2736     font->potm->otmusMinimumPPEM = 0; /* TT Header */
2737     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
2738     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
2739     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
2740     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
2741     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
2742     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
2743     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
2744     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
2745     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
2746     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
2747     if(!pPost) {
2748         font->potm->otmsUnderscoreSize = 0;
2749         font->potm->otmsUnderscorePosition = 0;
2750     } else {
2751         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
2752         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
2753     }
2754
2755     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
2756     cp = (char*)font->potm + sizeof(*font->potm);
2757     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
2758     strcpyW((WCHAR*)cp, family_nameW);
2759     cp += lenfam;
2760     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
2761     strcpyW((WCHAR*)cp, style_nameW);
2762     cp += lensty;
2763     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
2764     strcpyW((WCHAR*)cp, family_nameW);
2765     if(strcasecmp(ft_face->style_name, "regular")) {
2766         strcatW((WCHAR*)cp, spaceW);
2767         strcatW((WCHAR*)cp, style_nameW);
2768         cp += lenfam + lensty;
2769     } else
2770         cp += lenfam;
2771     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
2772     strcpyW((WCHAR*)cp, family_nameW);
2773     strcatW((WCHAR*)cp, spaceW);
2774     strcatW((WCHAR*)cp, style_nameW);
2775     ret = needed;
2776
2777     if(potm && needed <= cbSize)
2778         memcpy(potm, font->potm, font->potm->otmSize);
2779
2780 end:
2781     HeapFree(GetProcessHeap(), 0, style_nameW);
2782     HeapFree(GetProcessHeap(), 0, family_nameW);
2783
2784     return ret;
2785 }
2786
2787
2788 /*************************************************************
2789  * WineEngGetCharWidth
2790  *
2791  */
2792 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
2793                          LPINT buffer)
2794 {
2795     UINT c;
2796     GLYPHMETRICS gm;
2797     FT_UInt glyph_index;
2798
2799     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
2800
2801     for(c = firstChar; c <= lastChar; c++) {
2802         glyph_index = get_glyph_index(font, c);
2803         WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
2804                                &gm, 0, NULL, NULL);
2805         buffer[c - firstChar] = font->gm[glyph_index].adv;
2806     }
2807     return TRUE;
2808 }
2809
2810 /*************************************************************
2811  * WineEngGetCharABCWidths
2812  *
2813  */
2814 BOOL WineEngGetCharABCWidths(GdiFont font, UINT firstChar, UINT lastChar,
2815                              LPABC buffer)
2816 {
2817     UINT c;
2818     GLYPHMETRICS gm;
2819     FT_UInt glyph_index;
2820
2821     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
2822
2823     for(c = firstChar; c <= lastChar; c++) {
2824         glyph_index = get_glyph_index(font, c);
2825         WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
2826                                &gm, 0, NULL, NULL);
2827         buffer[c - firstChar].abcA = font->gm[glyph_index].lsb;
2828         buffer[c - firstChar].abcB = font->gm[glyph_index].bbx;
2829         buffer[c - firstChar].abcC = font->gm[glyph_index].adv - font->gm[glyph_index].lsb -
2830           font->gm[glyph_index].bbx;
2831     }
2832     return TRUE;
2833 }
2834
2835 /*************************************************************
2836  * WineEngGetTextExtentPoint
2837  *
2838  */
2839 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
2840                                LPSIZE size)
2841 {
2842     INT idx;
2843     GLYPHMETRICS gm;
2844     TEXTMETRICW tm;
2845     FT_UInt glyph_index;
2846
2847     TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count,
2848           size);
2849
2850     size->cx = 0;
2851     WineEngGetTextMetrics(font, &tm);
2852     size->cy = tm.tmHeight;
2853
2854     for(idx = 0; idx < count; idx++) {
2855         glyph_index = get_glyph_index(font, wstr[idx]);
2856         WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
2857                                &gm, 0, NULL, NULL);
2858         size->cx += font->gm[glyph_index].adv;
2859     }
2860     TRACE("return %ld,%ld\n", size->cx, size->cy);
2861     return TRUE;
2862 }
2863
2864 /*************************************************************
2865  * WineEngGetTextExtentPointI
2866  *
2867  */
2868 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
2869                                 LPSIZE size)
2870 {
2871     INT idx;
2872     GLYPHMETRICS gm;
2873     TEXTMETRICW tm;
2874
2875     TRACE("%p, %p, %d, %p\n", font, indices, count, size);
2876
2877     size->cx = 0;
2878     WineEngGetTextMetrics(font, &tm);
2879     size->cy = tm.tmHeight;
2880
2881     for(idx = 0; idx < count; idx++) {
2882         WineEngGetGlyphOutline(font, indices[idx],
2883                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
2884                                NULL);
2885         size->cx += font->gm[indices[idx]].adv;
2886     }
2887     TRACE("return %ld,%ld\n", size->cx, size->cy);
2888     return TRUE;
2889 }
2890
2891 /*************************************************************
2892  * WineEngGetFontData
2893  *
2894  */
2895 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
2896                          DWORD cbData)
2897 {
2898     FT_Face ft_face = font->ft_face;
2899     DWORD len;
2900     FT_Error err;
2901
2902     TRACE("font=%p, table=%08lx, offset=%08lx, buf=%p, cbData=%lx\n",
2903         font, table, offset, buf, cbData);
2904
2905     if(!FT_IS_SFNT(ft_face))
2906         return GDI_ERROR;
2907
2908     if(!buf || !cbData)
2909         len = 0;
2910     else
2911         len = cbData;
2912
2913     if(table) { /* MS tags differ in endidness from FT ones */
2914         table = table >> 24 | table << 24 |
2915           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
2916     }
2917
2918     /* If the FT_Load_Sfnt_Table function is there we'll use it */
2919     if(pFT_Load_Sfnt_Table)
2920         err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, &len);
2921     else { /* Do it the hard way */
2922         TT_Face tt_face = (TT_Face) ft_face;
2923         SFNT_Interface *sfnt;
2924         if (FT_Version.major==2 && FT_Version.minor==0)
2925         {
2926             /* 2.0.x */
2927             sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
2928         }
2929         else
2930         {
2931             /* A field was added in the middle of the structure in 2.1.x */
2932             sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
2933         }
2934         err = sfnt->load_any(tt_face, table, offset, buf, &len);
2935     }
2936     if(err) {
2937         TRACE("Can't find table %08lx.\n", table);
2938         return GDI_ERROR;
2939     }
2940     return len;
2941 }
2942
2943 /*************************************************************
2944  * WineEngGetTextFace
2945  *
2946  */
2947 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
2948 {
2949     if(str) {
2950         lstrcpynW(str, font->name, count);
2951         return strlenW(font->name);
2952     } else
2953         return strlenW(font->name) + 1;
2954 }
2955
2956 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
2957 {
2958     if (fs) memcpy(fs, &font->fs, sizeof(FONTSIGNATURE));
2959     return font->charset;
2960 }
2961
2962 #else /* HAVE_FREETYPE */
2963
2964 BOOL WineEngInit(void)
2965 {
2966     return FALSE;
2967 }
2968 GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
2969 {
2970     return NULL;
2971 }
2972 BOOL WineEngDestroyFontInstance(HFONT hfont)
2973 {
2974     return FALSE;
2975 }
2976
2977 DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
2978 {
2979     return 1;
2980 }
2981
2982 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
2983                                 LPWORD pgi, DWORD flags)
2984 {
2985     return GDI_ERROR;
2986 }
2987
2988 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
2989                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
2990                              const MAT2* lpmat)
2991 {
2992     ERR("called but we don't have FreeType\n");
2993     return GDI_ERROR;
2994 }
2995
2996 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
2997 {
2998     ERR("called but we don't have FreeType\n");
2999     return FALSE;
3000 }
3001
3002 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
3003                                   OUTLINETEXTMETRICW *potm)
3004 {
3005     ERR("called but we don't have FreeType\n");
3006     return 0;
3007 }
3008
3009 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
3010                          LPINT buffer)
3011 {
3012     ERR("called but we don't have FreeType\n");
3013     return FALSE;
3014 }
3015
3016 BOOL WineEngGetCharABCWidths(GdiFont font, UINT firstChar, UINT lastChar,
3017                              LPABC buffer)
3018 {
3019     ERR("called but we don't have FreeType\n");
3020     return FALSE;
3021 }
3022
3023 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
3024                                LPSIZE size)
3025 {
3026     ERR("called but we don't have FreeType\n");
3027     return FALSE;
3028 }
3029
3030 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
3031                                 LPSIZE size)
3032 {
3033     ERR("called but we don't have FreeType\n");
3034     return FALSE;
3035 }
3036
3037 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
3038                          DWORD cbData)
3039 {
3040     ERR("called but we don't have FreeType\n");
3041     return GDI_ERROR;
3042 }
3043
3044 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
3045 {
3046     ERR("called but we don't have FreeType\n");
3047     return 0;
3048 }
3049
3050 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
3051 {
3052     FIXME(":stub\n");
3053     return 1;
3054 }
3055
3056 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
3057 {
3058     FIXME(":stub\n");
3059     return TRUE;
3060 }
3061
3062 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
3063 {
3064     FIXME(":stub\n");
3065     return DEFAULT_CHARSET;
3066 }
3067
3068 #endif /* HAVE_FREETYPE */