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