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