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