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