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