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