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