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