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