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