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