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