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