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