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