mshtml: Added better IHTMLWindow2::get_opener stub.
[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 #ifdef HAVE_DIRENT_H
37 # include <dirent.h>
38 #endif
39 #include <stdio.h>
40 #include <assert.h>
41
42 #ifdef HAVE_CARBON_CARBON_H
43 #define LoadResource __carbon_LoadResource
44 #define CompareString __carbon_CompareString
45 #define GetCurrentThread __carbon_GetCurrentThread
46 #define GetCurrentProcess __carbon_GetCurrentProcess
47 #define AnimatePalette __carbon_AnimatePalette
48 #define EqualRgn __carbon_EqualRgn
49 #define FillRgn __carbon_FillRgn
50 #define FrameRgn __carbon_FrameRgn
51 #define GetPixel __carbon_GetPixel
52 #define InvertRgn __carbon_InvertRgn
53 #define LineTo __carbon_LineTo
54 #define OffsetRgn __carbon_OffsetRgn
55 #define PaintRgn __carbon_PaintRgn
56 #define Polygon __carbon_Polygon
57 #define ResizePalette __carbon_ResizePalette
58 #define SetRectRgn __carbon_SetRectRgn
59 #include <Carbon/Carbon.h>
60 #undef LoadResource
61 #undef CompareString
62 #undef GetCurrentThread
63 #undef _CDECL
64 #undef DPRINTF
65 #undef GetCurrentProcess
66 #undef AnimatePalette
67 #undef EqualRgn
68 #undef FillRgn
69 #undef FrameRgn
70 #undef GetPixel
71 #undef InvertRgn
72 #undef LineTo
73 #undef OffsetRgn
74 #undef PaintRgn
75 #undef Polygon
76 #undef ResizePalette
77 #undef SetRectRgn
78 #endif /* HAVE_CARBON_CARBON_H */
79
80 #include "windef.h"
81 #include "winbase.h"
82 #include "winternl.h"
83 #include "winerror.h"
84 #include "winreg.h"
85 #include "wingdi.h"
86 #include "gdi_private.h"
87 #include "wine/library.h"
88 #include "wine/unicode.h"
89 #include "wine/debug.h"
90 #include "wine/list.h"
91
92 #include "resource.h"
93
94 WINE_DEFAULT_DEBUG_CHANNEL(font);
95
96 #ifdef HAVE_FREETYPE
97
98 #ifdef HAVE_FT2BUILD_H
99 #include <ft2build.h>
100 #endif
101 #ifdef HAVE_FREETYPE_FREETYPE_H
102 #include <freetype/freetype.h>
103 #endif
104 #ifdef HAVE_FREETYPE_FTGLYPH_H
105 #include <freetype/ftglyph.h>
106 #endif
107 #ifdef HAVE_FREETYPE_TTTABLES_H
108 #include <freetype/tttables.h>
109 #endif
110 #ifdef HAVE_FREETYPE_FTTYPES_H
111 #include <freetype/fttypes.h>
112 #endif
113 #ifdef HAVE_FREETYPE_FTSNAMES_H
114 #include <freetype/ftsnames.h>
115 #endif
116 #ifdef HAVE_FREETYPE_TTNAMEID_H
117 #include <freetype/ttnameid.h>
118 #endif
119 #ifdef HAVE_FREETYPE_FTOUTLN_H
120 #include <freetype/ftoutln.h>
121 #endif
122 #ifdef HAVE_FREETYPE_FTTRIGON_H
123 #include <freetype/fttrigon.h>
124 #endif
125 #ifdef HAVE_FREETYPE_FTWINFNT_H
126 #include <freetype/ftwinfnt.h>
127 #endif
128 #ifdef HAVE_FREETYPE_FTMODAPI_H
129 #include <freetype/ftmodapi.h>
130 #endif
131 #ifdef HAVE_FREETYPE_FTLCDFIL_H
132 #include <freetype/ftlcdfil.h>
133 #endif
134
135 #ifndef HAVE_FT_TRUETYPEENGINETYPE
136 typedef enum
137 {
138     FT_TRUETYPE_ENGINE_TYPE_NONE = 0,
139     FT_TRUETYPE_ENGINE_TYPE_UNPATENTED,
140     FT_TRUETYPE_ENGINE_TYPE_PATENTED
141 } FT_TrueTypeEngineType;
142 #endif
143
144 static FT_Library library = 0;
145 typedef struct
146 {
147     FT_Int major;
148     FT_Int minor;
149     FT_Int patch;
150 } FT_Version_t;
151 static FT_Version_t FT_Version;
152 static DWORD FT_SimpleVersion;
153
154 static void *ft_handle = NULL;
155
156 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
157 MAKE_FUNCPTR(FT_Done_Face);
158 MAKE_FUNCPTR(FT_Get_Char_Index);
159 MAKE_FUNCPTR(FT_Get_First_Char);
160 MAKE_FUNCPTR(FT_Get_Module);
161 MAKE_FUNCPTR(FT_Get_Next_Char);
162 MAKE_FUNCPTR(FT_Get_Sfnt_Name);
163 MAKE_FUNCPTR(FT_Get_Sfnt_Name_Count);
164 MAKE_FUNCPTR(FT_Get_Sfnt_Table);
165 MAKE_FUNCPTR(FT_Get_WinFNT_Header);
166 MAKE_FUNCPTR(FT_Init_FreeType);
167 MAKE_FUNCPTR(FT_Library_Version);
168 MAKE_FUNCPTR(FT_Load_Glyph);
169 MAKE_FUNCPTR(FT_Load_Sfnt_Table);
170 MAKE_FUNCPTR(FT_Matrix_Multiply);
171 #ifdef FT_MULFIX_INLINED
172 #define pFT_MulFix FT_MULFIX_INLINED
173 #else
174 MAKE_FUNCPTR(FT_MulFix);
175 #endif
176 MAKE_FUNCPTR(FT_New_Face);
177 MAKE_FUNCPTR(FT_New_Memory_Face);
178 MAKE_FUNCPTR(FT_Outline_Get_Bitmap);
179 MAKE_FUNCPTR(FT_Outline_Transform);
180 MAKE_FUNCPTR(FT_Outline_Translate);
181 MAKE_FUNCPTR(FT_Render_Glyph);
182 MAKE_FUNCPTR(FT_Select_Charmap);
183 MAKE_FUNCPTR(FT_Set_Charmap);
184 MAKE_FUNCPTR(FT_Set_Pixel_Sizes);
185 MAKE_FUNCPTR(FT_Vector_Transform);
186 MAKE_FUNCPTR(FT_Vector_Unit);
187 static FT_TrueTypeEngineType (*pFT_Get_TrueType_Engine_Type)(FT_Library);
188 #ifdef HAVE_FREETYPE_FTLCDFIL_H
189 static FT_Error (*pFT_Library_SetLcdFilter)(FT_Library, FT_LcdFilter);
190 #endif
191
192 #ifdef SONAME_LIBFONTCONFIG
193 #include <fontconfig/fontconfig.h>
194 MAKE_FUNCPTR(FcConfigGetCurrent);
195 MAKE_FUNCPTR(FcFontList);
196 MAKE_FUNCPTR(FcFontSetDestroy);
197 MAKE_FUNCPTR(FcInit);
198 MAKE_FUNCPTR(FcObjectSetAdd);
199 MAKE_FUNCPTR(FcObjectSetCreate);
200 MAKE_FUNCPTR(FcObjectSetDestroy);
201 MAKE_FUNCPTR(FcPatternCreate);
202 MAKE_FUNCPTR(FcPatternDestroy);
203 MAKE_FUNCPTR(FcPatternGetBool);
204 MAKE_FUNCPTR(FcPatternGetString);
205 #endif
206
207 #undef MAKE_FUNCPTR
208
209 #ifndef FT_MAKE_TAG
210 #define FT_MAKE_TAG( ch0, ch1, ch2, ch3 ) \
211         ( ((DWORD)(BYTE)(ch0) << 24) | ((DWORD)(BYTE)(ch1) << 16) | \
212           ((DWORD)(BYTE)(ch2) << 8) | (DWORD)(BYTE)(ch3) )
213 #endif
214
215 #ifndef ft_encoding_none
216 #define FT_ENCODING_NONE ft_encoding_none
217 #endif
218 #ifndef ft_encoding_ms_symbol
219 #define FT_ENCODING_MS_SYMBOL ft_encoding_symbol
220 #endif
221 #ifndef ft_encoding_unicode
222 #define FT_ENCODING_UNICODE ft_encoding_unicode
223 #endif
224 #ifndef ft_encoding_apple_roman
225 #define FT_ENCODING_APPLE_ROMAN ft_encoding_apple_roman
226 #endif
227
228 #ifdef WORDS_BIGENDIAN
229 #define GET_BE_WORD(x) (x)
230 #else
231 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
232 #endif
233
234 /* This is basically a copy of FT_Bitmap_Size with an extra element added */
235 typedef struct {
236     FT_Short height;
237     FT_Short width;
238     FT_Pos size;
239     FT_Pos x_ppem;
240     FT_Pos y_ppem;
241     FT_Short internal_leading;
242 } Bitmap_Size;
243
244 /* FT_Bitmap_Size gained 3 new elements between FreeType 2.1.4 and 2.1.5
245    So to let this compile on older versions of FreeType we'll define the
246    new structure here. */
247 typedef struct {
248     FT_Short height, width;
249     FT_Pos size, x_ppem, y_ppem;
250 } My_FT_Bitmap_Size;
251
252 struct enum_data
253 {
254     ENUMLOGFONTEXW elf;
255     NEWTEXTMETRICEXW ntm;
256     DWORD type;
257 };
258
259 typedef struct tagFace {
260     struct list entry;
261     WCHAR *StyleName;
262     WCHAR *FullName;
263     char *file;
264     void *font_data_ptr;
265     DWORD font_data_size;
266     FT_Long face_index;
267     FONTSIGNATURE fs;
268     DWORD ntmFlags;
269     FT_Fixed font_version;
270     BOOL scalable;
271     BOOL vertical;
272     Bitmap_Size size;     /* set if face is a bitmap */
273     BOOL external; /* TRUE if we should manually add this font to the registry */
274     struct tagFamily *family;
275     /* Cached data for Enum */
276     struct enum_data *cached_enum_data;
277 } Face;
278
279 typedef struct tagFamily {
280     struct list entry;
281     WCHAR *FamilyName;
282     WCHAR *EnglishName;
283     struct list faces;
284     struct list *replacement;
285 } Family;
286
287 typedef struct {
288     GLYPHMETRICS gm;
289     INT adv; /* These three hold to widths of the unrotated chars */
290     INT lsb;
291     INT bbx;
292     BOOL init;
293 } GM;
294
295 typedef struct {
296     FLOAT eM11, eM12;
297     FLOAT eM21, eM22;
298 } FMAT2;
299
300 typedef struct {
301     DWORD hash;
302     LOGFONTW lf;
303     FMAT2 matrix;
304     BOOL can_use_bitmap;
305 } FONT_DESC;
306
307 typedef struct tagHFONTLIST {
308     struct list entry;
309     HFONT hfont;
310 } HFONTLIST;
311
312 typedef struct {
313     struct list entry;
314     Face *face;
315     GdiFont *font;
316 } CHILD_FONT;
317
318 struct tagGdiFont {
319     struct list entry;
320     GM **gm;
321     DWORD gmsize;
322     struct list hfontlist;
323     OUTLINETEXTMETRICW *potm;
324     DWORD total_kern_pairs;
325     KERNINGPAIR *kern_pairs;
326     struct list child_fonts;
327
328     /* the following members can be accessed without locking, they are never modified after creation */
329     FT_Face ft_face;
330     struct font_mapping *mapping;
331     LPWSTR name;
332     int charset;
333     int codepage;
334     BOOL fake_italic;
335     BOOL fake_bold;
336     BYTE underline;
337     BYTE strikeout;
338     INT orientation;
339     FONT_DESC font_desc;
340     LONG aveWidth, ppem;
341     double scale_y;
342     SHORT yMax;
343     SHORT yMin;
344     DWORD ntmFlags;
345     FONTSIGNATURE fs;
346     GdiFont *base_font;
347     VOID *GSUB_Table;
348     DWORD cache_num;
349 };
350
351 typedef struct {
352     struct list entry;
353     const WCHAR *font_name;
354     FONTSIGNATURE fs;
355     struct list links;
356 } SYSTEM_LINKS;
357
358 struct enum_charset_element {
359     DWORD mask;
360     DWORD charset;
361     WCHAR name[LF_FACESIZE];
362 };
363
364 struct enum_charset_list {
365     DWORD total;
366     struct enum_charset_element element[32];
367 };
368
369 #define GM_BLOCK_SIZE 128
370 #define FONT_GM(font,idx) (&(font)->gm[(idx) / GM_BLOCK_SIZE][(idx) % GM_BLOCK_SIZE])
371
372 static struct list gdi_font_list = LIST_INIT(gdi_font_list);
373 static struct list unused_gdi_font_list = LIST_INIT(unused_gdi_font_list);
374 #define UNUSED_CACHE_SIZE 10
375 static struct list child_font_list = LIST_INIT(child_font_list);
376 static struct list system_links = LIST_INIT(system_links);
377
378 static struct list font_subst_list = LIST_INIT(font_subst_list);
379
380 static struct list font_list = LIST_INIT(font_list);
381
382 struct freetype_physdev
383 {
384     struct gdi_physdev dev;
385     GdiFont           *font;
386 };
387
388 static inline struct freetype_physdev *get_freetype_dev( PHYSDEV dev )
389 {
390     return (struct freetype_physdev *)dev;
391 }
392
393 static const struct gdi_dc_funcs freetype_funcs;
394
395 static const WCHAR defSerif[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
396 static const WCHAR defSans[] = {'A','r','i','a','l','\0'};
397 static const WCHAR defFixed[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'};
398
399 static const WCHAR fontsW[] = {'\\','f','o','n','t','s','\0'};
400 static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
401                                            'W','i','n','d','o','w','s','\\',
402                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
403                                            'F','o','n','t','s','\0'};
404
405 static const WCHAR winnt_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
406                                            'W','i','n','d','o','w','s',' ','N','T','\\',
407                                            'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
408                                            'F','o','n','t','s','\0'};
409
410 static const WCHAR system_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
411 static const WCHAR FixedSys_Value[] = {'F','I','X','E','D','F','O','N','.','F','O','N','\0'};
412 static const WCHAR System_Value[] = {'F','O','N','T','S','.','F','O','N','\0'};
413 static const WCHAR OEMFont_Value[] = {'O','E','M','F','O','N','T','.','F','O','N','\0'};
414
415 static const WCHAR * const SystemFontValues[] = {
416     System_Value,
417     OEMFont_Value,
418     FixedSys_Value,
419     NULL
420 };
421
422 static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
423                                                'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'};
424
425 /* Interesting and well-known (frequently-assumed!) font names */
426 static const WCHAR Lucida_Sans_Unicode[] = {'L','u','c','i','d','a',' ','S','a','n','s',' ','U','n','i','c','o','d','e',0};
427 static const WCHAR Microsoft_Sans_Serif[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0 };
428 static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
429 static const WCHAR MS_UI_Gothic[] = {'M','S',' ','U','I',' ','G','o','t','h','i','c',0};
430 static const WCHAR SimSun[] = {'S','i','m','S','u','n',0};
431 static const WCHAR Gulim[] = {'G','u','l','i','m',0};
432 static const WCHAR PMingLiU[] = {'P','M','i','n','g','L','i','U',0};
433 static const WCHAR Batang[] = {'B','a','t','a','n','g',0};
434
435 static const WCHAR arial[] = {'A','r','i','a','l',0};
436 static const WCHAR bitstream_vera_sans[] = {'B','i','t','s','t','r','e','a','m',' ','V','e','r','a',' ','S','a','n','s',0};
437 static const WCHAR bitstream_vera_sans_mono[] = {'B','i','t','s','t','r','e','a','m',' ','V','e','r','a',' ','S','a','n','s',' ','M','o','n','o',0};
438 static const WCHAR bitstream_vera_serif[] = {'B','i','t','s','t','r','e','a','m',' ','V','e','r','a',' ','S','e','r','i','f',0};
439 static const WCHAR courier_new[] = {'C','o','u','r','i','e','r',' ','N','e','w',0};
440 static const WCHAR liberation_mono[] = {'L','i','b','e','r','a','t','i','o','n',' ','M','o','n','o',0};
441 static const WCHAR liberation_sans[] = {'L','i','b','e','r','a','t','i','o','n',' ','S','a','n','s',0};
442 static const WCHAR liberation_serif[] = {'L','i','b','e','r','a','t','i','o','n',' ','S','e','r','i','f',0};
443 static const WCHAR times_new_roman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n',0};
444 static const WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
445
446 static const WCHAR *default_serif_list[] =
447 {
448     times_new_roman,
449     liberation_serif,
450     bitstream_vera_serif,
451     NULL
452 };
453
454 static const WCHAR *default_fixed_list[] =
455 {
456     courier_new,
457     liberation_mono,
458     bitstream_vera_sans_mono,
459     NULL
460 };
461
462 static const WCHAR *default_sans_list[] =
463 {
464     arial,
465     liberation_sans,
466     bitstream_vera_sans,
467     NULL
468 };
469
470 typedef struct {
471     WCHAR *name;
472     INT charset;
473 } NameCs;
474
475 typedef struct tagFontSubst {
476     struct list entry;
477     NameCs from;
478     NameCs to;
479 } FontSubst;
480
481 /* Registry font cache key and value names */
482 static const WCHAR wine_fonts_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
483                                        'F','o','n','t','s',0};
484 static const WCHAR wine_fonts_cache_key[] = {'C','a','c','h','e',0};
485 static const WCHAR english_name_value[] = {'E','n','g','l','i','s','h',' ','N','a','m','e',0};
486 static const WCHAR face_index_value[] = {'I','n','d','e','x',0};
487 static const WCHAR face_ntmflags_value[] = {'N','t','m','f','l','a','g','s',0};
488 static const WCHAR face_version_value[] = {'V','e','r','s','i','o','n',0};
489 static const WCHAR face_vertical_value[] = {'V','e','r','t','i','c','a','l',0};
490 static const WCHAR face_height_value[] = {'H','e','i','g','h','t',0};
491 static const WCHAR face_width_value[] = {'W','i','d','t','h',0};
492 static const WCHAR face_size_value[] = {'S','i','z','e',0};
493 static const WCHAR face_x_ppem_value[] = {'X','p','p','e','m',0};
494 static const WCHAR face_y_ppem_value[] = {'Y','p','p','e','m',0};
495 static const WCHAR face_internal_leading_value[] = {'I','n','t','e','r','n','a','l',' ','L','e','a','d','i','n','g',0};
496 static const WCHAR face_font_sig_value[] = {'F','o','n','t',' ','S','i','g','n','a','t','u','r','e',0};
497 static const WCHAR face_full_name_value[] = {'F','u','l','l',' ','N','a','m','e','\0'};
498
499
500 struct font_mapping
501 {
502     struct list entry;
503     int         refcount;
504     dev_t       dev;
505     ino_t       ino;
506     void       *data;
507     size_t      size;
508 };
509
510 static struct list mappings_list = LIST_INIT( mappings_list );
511
512 static CRITICAL_SECTION freetype_cs;
513 static CRITICAL_SECTION_DEBUG critsect_debug =
514 {
515     0, 0, &freetype_cs,
516     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
517       0, 0, { (DWORD_PTR)(__FILE__ ": freetype_cs") }
518 };
519 static CRITICAL_SECTION freetype_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
520
521 static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'};
522
523 static const WCHAR szDefaultFallbackLink[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0};
524 static BOOL use_default_fallback = FALSE;
525
526 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph);
527 static BOOL get_outline_text_metrics(GdiFont *font);
528 static BOOL get_text_metrics(GdiFont *font, LPTEXTMETRICW ptm);
529
530 static const WCHAR system_link[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
531                                     'W','i','n','d','o','w','s',' ','N','T','\\',
532                                     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','F','o','n','t','L','i','n','k','\\',
533                                     'S','y','s','t','e','m','L','i','n','k',0};
534
535 static const WCHAR internal_system_link[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
536                                     'F','o','n','t','L','i','n','k','\\',
537                                     'S','y','s','t','e','m','L','i','n','k',0};
538
539 /****************************************
540  *   Notes on .fon files
541  *
542  * The fonts System, FixedSys and Terminal are special.  There are typically multiple
543  * versions installed for different resolutions and codepages.  Windows stores which one to use
544  * in HKEY_CURRENT_CONFIG\\Software\\Fonts.
545  *    Key            Meaning
546  *  FIXEDFON.FON    FixedSys
547  *  FONTS.FON       System
548  *  OEMFONT.FON     Terminal
549  *  LogPixels       Current dpi set by the display control panel applet
550  *                  (HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontDPI
551  *                  also has a LogPixels value that appears to mirror this)
552  *
553  * On my system these values have data: vgafix.fon, vgasys.fon, vga850.fon and 96 respectively
554  * (vgaoem.fon would be your oemfont.fon if you have a US setup).
555  * If the resolution is changed to be >= 109dpi then the fonts goto 8514fix, 8514sys and 8514oem
556  * (not sure what's happening to the oem codepage here). 109 is nicely halfway between 96 and 120dpi,
557  * so that makes sense.
558  *
559  * Additionally Windows also loads the fonts listed in the [386enh] section of system.ini (this doesn't appear
560  * to be mapped into the registry on Windows 2000 at least).
561  * I have
562  * woafont=app850.fon
563  * ega80woa.fon=ega80850.fon
564  * ega40woa.fon=ega40850.fon
565  * cga80woa.fon=cga80850.fon
566  * cga40woa.fon=cga40850.fon
567  */
568
569 /* These are all structures needed for the GSUB table */
570
571 #define GSUB_TAG MS_MAKE_TAG('G', 'S', 'U', 'B')
572 #define TATEGAKI_LOWER_BOUND  0x02F1
573
574 typedef struct {
575     DWORD version;
576     WORD ScriptList;
577     WORD FeatureList;
578     WORD LookupList;
579 } GSUB_Header;
580
581 typedef struct {
582     CHAR ScriptTag[4];
583     WORD Script;
584 } GSUB_ScriptRecord;
585
586 typedef struct {
587     WORD ScriptCount;
588     GSUB_ScriptRecord ScriptRecord[1];
589 } GSUB_ScriptList;
590
591 typedef struct {
592     CHAR LangSysTag[4];
593     WORD LangSys;
594 } GSUB_LangSysRecord;
595
596 typedef struct {
597     WORD DefaultLangSys;
598     WORD LangSysCount;
599     GSUB_LangSysRecord LangSysRecord[1];
600 } GSUB_Script;
601
602 typedef struct {
603     WORD LookupOrder; /* Reserved */
604     WORD ReqFeatureIndex;
605     WORD FeatureCount;
606     WORD FeatureIndex[1];
607 } GSUB_LangSys;
608
609 typedef struct {
610     CHAR FeatureTag[4];
611     WORD Feature;
612 } GSUB_FeatureRecord;
613
614 typedef struct {
615     WORD FeatureCount;
616     GSUB_FeatureRecord FeatureRecord[1];
617 } GSUB_FeatureList;
618
619 typedef struct {
620     WORD FeatureParams; /* Reserved */
621     WORD LookupCount;
622     WORD LookupListIndex[1];
623 } GSUB_Feature;
624
625 typedef struct {
626     WORD LookupCount;
627     WORD Lookup[1];
628 } GSUB_LookupList;
629
630 typedef struct {
631     WORD LookupType;
632     WORD LookupFlag;
633     WORD SubTableCount;
634     WORD SubTable[1];
635 } GSUB_LookupTable;
636
637 typedef struct {
638     WORD CoverageFormat;
639     WORD GlyphCount;
640     WORD GlyphArray[1];
641 } GSUB_CoverageFormat1;
642
643 typedef struct {
644     WORD Start;
645     WORD End;
646     WORD StartCoverageIndex;
647 } GSUB_RangeRecord;
648
649 typedef struct {
650     WORD CoverageFormat;
651     WORD RangeCount;
652     GSUB_RangeRecord RangeRecord[1];
653 } GSUB_CoverageFormat2;
654
655 typedef struct {
656     WORD SubstFormat; /* = 1 */
657     WORD Coverage;
658     WORD DeltaGlyphID;
659 } GSUB_SingleSubstFormat1;
660
661 typedef struct {
662     WORD SubstFormat; /* = 2 */
663     WORD Coverage;
664     WORD GlyphCount;
665     WORD Substitute[1];
666 }GSUB_SingleSubstFormat2;
667
668 #ifdef HAVE_CARBON_CARBON_H
669 static char *find_cache_dir(void)
670 {
671     FSRef ref;
672     OSErr err;
673     static char cached_path[MAX_PATH];
674     static const char *wine = "/Wine", *fonts = "/Fonts";
675
676     if(*cached_path) return cached_path;
677
678     err = FSFindFolder(kUserDomain, kCachedDataFolderType, kCreateFolder, &ref);
679     if(err != noErr)
680     {
681         WARN("can't create cached data folder\n");
682         return NULL;
683     }
684     err = FSRefMakePath(&ref, (unsigned char*)cached_path, sizeof(cached_path));
685     if(err != noErr)
686     {
687         WARN("can't create cached data path\n");
688         *cached_path = '\0';
689         return NULL;
690     }
691     if(strlen(cached_path) + strlen(wine) + strlen(fonts) + 1 > sizeof(cached_path))
692     {
693         ERR("Could not create full path\n");
694         *cached_path = '\0';
695         return NULL;
696     }
697     strcat(cached_path, wine);
698
699     if(mkdir(cached_path, 0700) == -1 && errno != EEXIST)
700     {
701         WARN("Couldn't mkdir %s\n", cached_path);
702         *cached_path = '\0';
703         return NULL;
704     }
705     strcat(cached_path, fonts);
706     if(mkdir(cached_path, 0700) == -1 && errno != EEXIST)
707     {
708         WARN("Couldn't mkdir %s\n", cached_path);
709         *cached_path = '\0';
710         return NULL;
711     }
712     return cached_path;
713 }
714
715 /******************************************************************
716  *            expand_mac_font
717  *
718  * Extracts individual TrueType font files from a Mac suitcase font
719  * and saves them into the user's caches directory (see
720  * find_cache_dir()).
721  * Returns a NULL terminated array of filenames.
722  *
723  * We do this because they are apps that try to read ttf files
724  * themselves and they don't like Mac suitcase files.
725  */
726 static char **expand_mac_font(const char *path)
727 {
728     FSRef ref;
729     SInt16 res_ref;
730     OSStatus s;
731     unsigned int idx;
732     const char *out_dir;
733     const char *filename;
734     int output_len;
735     struct {
736         char **array;
737         unsigned int size, max_size;
738     } ret;
739
740     TRACE("path %s\n", path);
741
742     s = FSPathMakeRef((unsigned char*)path, &ref, FALSE);
743     if(s != noErr)
744     {
745         WARN("failed to get ref\n");
746         return NULL;
747     }
748
749     s = FSOpenResourceFile(&ref, 0, NULL, fsRdPerm, &res_ref);
750     if(s != noErr)
751     {
752         TRACE("no data fork, so trying resource fork\n");
753         res_ref = FSOpenResFile(&ref, fsRdPerm);
754         if(res_ref == -1)
755         {
756             TRACE("unable to open resource fork\n");
757             return NULL;
758         }
759     }
760
761     ret.size = 0;
762     ret.max_size = 10;
763     ret.array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ret.max_size * sizeof(*ret.array));
764     if(!ret.array)
765     {
766         CloseResFile(res_ref);
767         return NULL;
768     }
769
770     out_dir = find_cache_dir();
771
772     filename = strrchr(path, '/');
773     if(!filename) filename = path;
774     else filename++;
775
776     /* output filename has the form out_dir/filename_%04x.ttf */
777     output_len = strlen(out_dir) + 1 + strlen(filename) + 5 + 5;
778
779     UseResFile(res_ref);
780     idx = 1;
781     while(1)
782     {
783         FamRec *fam_rec;
784         unsigned short *num_faces_ptr, num_faces, face;
785         AsscEntry *assoc;
786         Handle fond;
787         ResType fond_res = FT_MAKE_TAG('F','O','N','D');
788
789         fond = Get1IndResource(fond_res, idx);
790         if(!fond) break;
791         TRACE("got fond resource %d\n", idx);
792         HLock(fond);
793
794         fam_rec = *(FamRec**)fond;
795         num_faces_ptr = (unsigned short *)(fam_rec + 1);
796         num_faces = GET_BE_WORD(*num_faces_ptr);
797         num_faces++;
798         assoc = (AsscEntry*)(num_faces_ptr + 1);
799         TRACE("num faces %04x\n", num_faces);
800         for(face = 0; face < num_faces; face++, assoc++)
801         {
802             Handle sfnt;
803             ResType sfnt_res = FT_MAKE_TAG('s','f','n','t');
804             unsigned short size, font_id;
805             char *output;
806
807             size = GET_BE_WORD(assoc->fontSize);
808             font_id = GET_BE_WORD(assoc->fontID);
809             if(size != 0)
810             {
811                 TRACE("skipping id %04x because it's not scalable (fixed size %d)\n", font_id, size);
812                 continue;
813             }
814
815             TRACE("trying to load sfnt id %04x\n", font_id);
816             sfnt = GetResource(sfnt_res, font_id);
817             if(!sfnt)
818             {
819                 TRACE("can't get sfnt resource %04x\n", font_id);
820                 continue;
821             }
822
823             output = HeapAlloc(GetProcessHeap(), 0, output_len);
824             if(output)
825             {
826                 int fd;
827
828                 sprintf(output, "%s/%s_%04x.ttf", out_dir, filename, font_id);
829
830                 fd = open(output, O_CREAT | O_EXCL | O_WRONLY, 0600);
831                 if(fd != -1 || errno == EEXIST)
832                 {
833                     if(fd != -1)
834                     {
835                         unsigned char *sfnt_data;
836
837                         HLock(sfnt);
838                         sfnt_data = *(unsigned char**)sfnt;
839                         write(fd, sfnt_data, GetHandleSize(sfnt));
840                         HUnlock(sfnt);
841                         close(fd);
842                     }
843                     if(ret.size >= ret.max_size - 1) /* Always want the last element to be NULL */
844                     {
845                         ret.max_size *= 2;
846                         ret.array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ret.array, ret.max_size * sizeof(*ret.array));
847                     }
848                     ret.array[ret.size++] = output;
849                 }
850                 else
851                 {
852                     WARN("unable to create %s\n", output);
853                     HeapFree(GetProcessHeap(), 0, output);
854                 }
855             }
856             ReleaseResource(sfnt);
857         }
858         HUnlock(fond);
859         ReleaseResource(fond);
860         idx++;
861     }
862     CloseResFile(res_ref);
863
864     return ret.array;
865 }
866
867 #endif /* HAVE_CARBON_CARBON_H */
868
869 static inline BOOL is_win9x(void)
870 {
871     return GetVersion() & 0x80000000;
872 }
873 /* 
874    This function builds an FT_Fixed from a double. It fails if the absolute
875    value of the float number is greater than 32768.
876 */
877 static inline FT_Fixed FT_FixedFromFloat(double f)
878 {
879         return f * 0x10000;
880 }
881
882 /* 
883    This function builds an FT_Fixed from a FIXED. It simply put f.value 
884    in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
885 */
886 static inline FT_Fixed FT_FixedFromFIXED(FIXED f)
887 {
888     return (FT_Fixed)((int)f.value << 16 | (unsigned int)f.fract);
889 }
890
891
892 static const struct list *get_face_list_from_family(const Family *family)
893 {
894     if (!list_empty(&family->faces))
895         return &family->faces;
896     else
897         return family->replacement;
898 }
899
900 static Face *find_face_from_filename(const WCHAR *file_name, const WCHAR *face_name)
901 {
902     Family *family;
903     Face *face;
904     const char *file;
905     DWORD len = WideCharToMultiByte(CP_UNIXCP, 0, file_name, -1, NULL, 0, NULL, NULL);
906     char *file_nameA = HeapAlloc(GetProcessHeap(), 0, len);
907
908     WideCharToMultiByte(CP_UNIXCP, 0, file_name, -1, file_nameA, len, NULL, NULL);
909     TRACE("looking for file %s name %s\n", debugstr_a(file_nameA), debugstr_w(face_name));
910
911     LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
912     {
913         const struct list *face_list;
914         if(face_name && strcmpiW(face_name, family->FamilyName))
915             continue;
916         face_list = get_face_list_from_family(family);
917         LIST_FOR_EACH_ENTRY(face, face_list, Face, entry)
918         {
919             if (!face->file)
920                 continue;
921             file = strrchr(face->file, '/');
922             if(!file)
923                 file = face->file;
924             else
925                 file++;
926             if(!strcasecmp(file, file_nameA))
927             {
928                 HeapFree(GetProcessHeap(), 0, file_nameA);
929                 return face;
930             }
931         }
932     }
933     HeapFree(GetProcessHeap(), 0, file_nameA);
934     return NULL;
935 }
936
937 static Family *find_family_from_name(const WCHAR *name)
938 {
939     Family *family;
940
941     LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
942     {
943         if(!strcmpiW(family->FamilyName, name))
944             return family;
945     }
946
947     return NULL;
948 }
949
950 static Family *find_family_from_any_name(const WCHAR *name)
951 {
952     Family *family;
953
954     LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
955     {
956         if(!strcmpiW(family->FamilyName, name))
957             return family;
958         if(family->EnglishName && !strcmpiW(family->EnglishName, name))
959             return family;
960     }
961
962     return NULL;
963 }
964
965 static void DumpSubstList(void)
966 {
967     FontSubst *psub;
968
969     LIST_FOR_EACH_ENTRY(psub, &font_subst_list, FontSubst, entry)
970     {
971         if(psub->from.charset != -1 || psub->to.charset != -1)
972             TRACE("%s:%d -> %s:%d\n", debugstr_w(psub->from.name),
973               psub->from.charset, debugstr_w(psub->to.name), psub->to.charset);
974         else
975             TRACE("%s -> %s\n", debugstr_w(psub->from.name),
976                   debugstr_w(psub->to.name));
977     }
978     return;
979 }
980
981 static LPWSTR strdupW(LPCWSTR p)
982 {
983     LPWSTR ret;
984     DWORD len = (strlenW(p) + 1) * sizeof(WCHAR);
985     ret = HeapAlloc(GetProcessHeap(), 0, len);
986     memcpy(ret, p, len);
987     return ret;
988 }
989
990 static LPSTR strdupA(LPCSTR p)
991 {
992     LPSTR ret;
993     DWORD len = (strlen(p) + 1);
994     ret = HeapAlloc(GetProcessHeap(), 0, len);
995     memcpy(ret, p, len);
996     return ret;
997 }
998
999 static FontSubst *get_font_subst(const struct list *subst_list, const WCHAR *from_name,
1000                                  INT from_charset)
1001 {
1002     FontSubst *element;
1003
1004     LIST_FOR_EACH_ENTRY(element, subst_list, FontSubst, entry)
1005     {
1006         if(!strcmpiW(element->from.name, from_name) &&
1007            (element->from.charset == from_charset ||
1008             element->from.charset == -1))
1009             return element;
1010     }
1011
1012     return NULL;
1013 }
1014
1015 #define ADD_FONT_SUBST_FORCE  1
1016
1017 static BOOL add_font_subst(struct list *subst_list, FontSubst *subst, INT flags)
1018 {
1019     FontSubst *from_exist, *to_exist;
1020
1021     from_exist = get_font_subst(subst_list, subst->from.name, subst->from.charset);
1022
1023     if(from_exist && (flags & ADD_FONT_SUBST_FORCE))
1024     {
1025         list_remove(&from_exist->entry);
1026         HeapFree(GetProcessHeap(), 0, &from_exist->from.name);
1027         HeapFree(GetProcessHeap(), 0, &from_exist->to.name);
1028         HeapFree(GetProcessHeap(), 0, from_exist);
1029         from_exist = NULL;
1030     }
1031
1032     if(!from_exist)
1033     {
1034         to_exist = get_font_subst(subst_list, subst->to.name, subst->to.charset);
1035
1036         if(to_exist)
1037         {
1038             HeapFree(GetProcessHeap(), 0, subst->to.name);
1039             subst->to.name = strdupW(to_exist->to.name);
1040         }
1041             
1042         list_add_tail(subst_list, &subst->entry);
1043
1044         return TRUE;
1045     }
1046
1047     HeapFree(GetProcessHeap(), 0, subst->from.name);
1048     HeapFree(GetProcessHeap(), 0, subst->to.name);
1049     HeapFree(GetProcessHeap(), 0, subst);
1050     return FALSE;
1051 }
1052
1053 static WCHAR *towstr(UINT cp, const char *str)
1054 {
1055     int len;
1056     WCHAR *wstr;
1057
1058     len = MultiByteToWideChar(cp, 0, str, -1, NULL, 0);
1059     wstr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1060     MultiByteToWideChar(cp, 0, str, -1, wstr, len);
1061     return wstr;
1062 }
1063
1064 static void split_subst_info(NameCs *nc, LPSTR str)
1065 {
1066     CHAR *p = strrchr(str, ',');
1067
1068     nc->charset = -1;
1069     if(p && *(p+1)) {
1070         nc->charset = strtol(p+1, NULL, 10);
1071         *p = '\0';
1072     }
1073     nc->name = towstr(CP_ACP, str);
1074 }
1075
1076 static void LoadSubstList(void)
1077 {
1078     FontSubst *psub;
1079     HKEY hkey;
1080     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
1081     LPSTR value;
1082     LPVOID data;
1083
1084     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
1085                    "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes",
1086                    &hkey) == ERROR_SUCCESS) {
1087
1088         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1089                          &valuelen, &datalen, NULL, NULL);
1090
1091         valuelen++; /* returned value doesn't include room for '\0' */
1092         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
1093         data = HeapAlloc(GetProcessHeap(), 0, datalen);
1094
1095         dlen = datalen;
1096         vlen = valuelen;
1097         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
1098                             &dlen) == ERROR_SUCCESS) {
1099             TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
1100
1101             psub = HeapAlloc(GetProcessHeap(), 0, sizeof(*psub));
1102             split_subst_info(&psub->from, value);
1103             split_subst_info(&psub->to, data);
1104
1105             /* Win 2000 doesn't allow mapping between different charsets
1106                or mapping of DEFAULT_CHARSET */
1107             if ((psub->from.charset && psub->to.charset != psub->from.charset) ||
1108                psub->to.charset == DEFAULT_CHARSET) {
1109                 HeapFree(GetProcessHeap(), 0, psub->to.name);
1110                 HeapFree(GetProcessHeap(), 0, psub->from.name);
1111                 HeapFree(GetProcessHeap(), 0, psub);
1112             } else {
1113                 add_font_subst(&font_subst_list, psub, 0);
1114             }
1115             /* reset dlen and vlen */
1116             dlen = datalen;
1117             vlen = valuelen;
1118         }
1119         HeapFree(GetProcessHeap(), 0, data);
1120         HeapFree(GetProcessHeap(), 0, value);
1121         RegCloseKey(hkey);
1122     }
1123 }
1124
1125
1126 /*****************************************************************
1127  *       get_name_table_entry
1128  *
1129  * Supply the platform, encoding, language and name ids in req
1130  * and if the name exists the function will fill in the string
1131  * and string_len members.  The string is owned by FreeType so
1132  * don't free it.  Returns TRUE if the name is found else FALSE.
1133  */
1134 static BOOL get_name_table_entry(FT_Face ft_face, FT_SfntName *req)
1135 {
1136     FT_SfntName name;
1137     FT_UInt num_names, name_index;
1138
1139     if(FT_IS_SFNT(ft_face))
1140     {
1141         num_names = pFT_Get_Sfnt_Name_Count(ft_face);
1142
1143         for(name_index = 0; name_index < num_names; name_index++)
1144         {
1145             if(!pFT_Get_Sfnt_Name(ft_face, name_index, &name))
1146             {
1147                 if((name.platform_id == req->platform_id) &&
1148                    (name.encoding_id == req->encoding_id) &&
1149                    (name.language_id == req->language_id) &&
1150                    (name.name_id     == req->name_id))
1151                 {
1152                     req->string = name.string;
1153                     req->string_len = name.string_len;
1154                     return TRUE;
1155                 }
1156             }
1157         }
1158     }
1159     req->string = NULL;
1160     req->string_len = 0;
1161     return FALSE;
1162 }
1163
1164 static WCHAR *get_face_name(FT_Face ft_face, FT_UShort name_id, FT_UShort language_id)
1165 {
1166     WCHAR *ret = NULL;
1167     FT_SfntName name;
1168
1169     name.platform_id = TT_PLATFORM_MICROSOFT;
1170     name.encoding_id = TT_MS_ID_UNICODE_CS;
1171     name.language_id = language_id;
1172     name.name_id     = name_id;
1173
1174     if(get_name_table_entry(ft_face, &name))
1175     {
1176         FT_UInt i;
1177
1178         /* String is not nul terminated and string_len is a byte length. */
1179         ret = HeapAlloc(GetProcessHeap(), 0, name.string_len + 2);
1180         for(i = 0; i < name.string_len / 2; i++)
1181         {
1182             WORD *tmp = (WORD *)&name.string[i * 2];
1183             ret[i] = GET_BE_WORD(*tmp);
1184         }
1185         ret[i] = 0;
1186         TRACE("Got localised name %s\n", debugstr_w(ret));
1187     }
1188
1189     return ret;
1190 }
1191
1192 static inline BOOL faces_equal( const Face *f1, const Face *f2 )
1193 {
1194     if (strcmpiW( f1->StyleName, f2->StyleName )) return FALSE;
1195     if (f1->scalable) return TRUE;
1196     if (f1->size.y_ppem != f2->size.y_ppem) return FALSE;
1197     return !memcmp( &f1->fs, &f2->fs, sizeof(f1->fs) );
1198 }
1199
1200 static inline void free_face( Face *face )
1201 {
1202     HeapFree( GetProcessHeap(), 0, face->file );
1203     HeapFree( GetProcessHeap(), 0, face->StyleName );
1204     HeapFree( GetProcessHeap(), 0, face->FullName );
1205     HeapFree( GetProcessHeap(), 0, face->cached_enum_data );
1206     HeapFree( GetProcessHeap(), 0, face );
1207 }
1208
1209 static inline void free_family( Family *family )
1210 {
1211     Face *face, *cursor2;
1212
1213     LIST_FOR_EACH_ENTRY_SAFE( face, cursor2, &family->faces, Face, entry )
1214     {
1215         list_remove( &face->entry );
1216         free_face( face );
1217     }
1218     HeapFree( GetProcessHeap(), 0, family->FamilyName );
1219     HeapFree( GetProcessHeap(), 0, family->EnglishName );
1220     HeapFree( GetProcessHeap(), 0, family );
1221 }
1222
1223 static inline int style_order(const Face *face)
1224 {
1225     switch (face->ntmFlags & (NTM_REGULAR | NTM_BOLD | NTM_ITALIC))
1226     {
1227     case NTM_REGULAR:
1228         return 0;
1229     case NTM_BOLD:
1230         return 1;
1231     case NTM_ITALIC:
1232         return 2;
1233     case NTM_BOLD | NTM_ITALIC:
1234         return 3;
1235     default:
1236         WARN("Don't know how to order font %s %s with flags 0x%08x\n",
1237              debugstr_w(face->family->FamilyName),
1238              debugstr_w(face->StyleName),
1239              face->ntmFlags);
1240         return 9999;
1241     }
1242 }
1243
1244 static BOOL insert_face_in_family_list( Face *face, Family *family )
1245 {
1246     Face *cursor;
1247
1248     LIST_FOR_EACH_ENTRY( cursor, &family->faces, Face, entry )
1249     {
1250         if (faces_equal( face, cursor ))
1251         {
1252             TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
1253                   debugstr_w(family->FamilyName), debugstr_w(face->StyleName),
1254                   cursor->font_version, face->font_version);
1255
1256             if (face->font_version <= cursor->font_version)
1257             {
1258                 TRACE("Original font %s is newer so skipping %s\n",
1259                       debugstr_a(cursor->file), debugstr_a(face->file));
1260                 return FALSE;
1261             }
1262             else
1263             {
1264                 TRACE("Replacing original %s with %s\n",
1265                       debugstr_a(cursor->file), debugstr_a(face->file));
1266                 list_add_before( &cursor->entry, &face->entry );
1267                 face->family = family;
1268                 list_remove( &cursor->entry);
1269                 free_face( cursor );
1270                 return TRUE;
1271             }
1272         }
1273         else
1274             TRACE("Adding new %s\n", debugstr_a(face->file));
1275
1276         if (style_order( face ) < style_order( cursor )) break;
1277     }
1278
1279     list_add_before( &cursor->entry, &face->entry );
1280     face->family = family;
1281     return TRUE;
1282 }
1283
1284 /****************************************************************
1285  * NB This function stores the ptrs to the strings to save copying.
1286  * Don't free them after calling.
1287  */
1288 static Family *create_family( WCHAR *name, WCHAR *english_name )
1289 {
1290     Family * const family = HeapAlloc( GetProcessHeap(), 0, sizeof(*family) );
1291     family->FamilyName = name;
1292     family->EnglishName = english_name;
1293     list_init( &family->faces );
1294     family->replacement = &family->faces;
1295
1296     return family;
1297 }
1298
1299 static LONG reg_load_dword(HKEY hkey, const WCHAR *value, DWORD *data)
1300 {
1301     DWORD type, needed;
1302     LONG r = RegQueryValueExW(hkey, value, NULL, &type, NULL, &needed);
1303     if(r != ERROR_SUCCESS) return r;
1304     if(type != REG_DWORD || needed != sizeof(DWORD)) return ERROR_BAD_CONFIGURATION;
1305     return RegQueryValueExW(hkey, value, NULL, &type, (BYTE*)data, &needed);
1306 }
1307
1308 static inline LONG reg_save_dword(HKEY hkey, const WCHAR *value, DWORD data)
1309 {
1310     return RegSetValueExW(hkey, value, 0, REG_DWORD, (BYTE*)&data, sizeof(DWORD));
1311 }
1312
1313 static void load_face(HKEY hkey_face, WCHAR *face_name, Family *family)
1314 {
1315     DWORD needed;
1316     DWORD num_strikes, max_strike_key_len;
1317
1318     /* If we have a File Name key then this is a real font, not just the parent
1319        key of a bunch of non-scalable strikes */
1320     if(RegQueryValueExA(hkey_face, "File Name", NULL, NULL, NULL, &needed) == ERROR_SUCCESS)
1321     {
1322         Face *face;
1323         face = HeapAlloc(GetProcessHeap(), 0, sizeof(*face));
1324         face->cached_enum_data = NULL;
1325
1326         face->file = HeapAlloc(GetProcessHeap(), 0, needed);
1327         RegQueryValueExA(hkey_face, "File Name", NULL, NULL, (BYTE*)face->file, &needed);
1328
1329         face->StyleName = strdupW(face_name);
1330
1331         if(RegQueryValueExW(hkey_face, face_full_name_value, NULL, NULL, NULL, &needed) == ERROR_SUCCESS)
1332         {
1333             WCHAR *fullName = HeapAlloc(GetProcessHeap(), 0, needed);
1334             RegQueryValueExW(hkey_face, face_full_name_value, NULL, NULL, (BYTE*)fullName, &needed);
1335             face->FullName = fullName;
1336         }
1337         else
1338             face->FullName = NULL;
1339
1340         reg_load_dword(hkey_face, face_index_value, (DWORD*)&face->face_index);
1341         reg_load_dword(hkey_face, face_ntmflags_value, &face->ntmFlags);
1342         reg_load_dword(hkey_face, face_version_value, (DWORD*)&face->font_version);
1343         reg_load_dword(hkey_face, face_vertical_value, (DWORD*)&face->vertical);
1344
1345         needed = sizeof(face->fs);
1346         RegQueryValueExW(hkey_face, face_font_sig_value, NULL, NULL, (BYTE*)&face->fs, &needed);
1347
1348         if(reg_load_dword(hkey_face, face_height_value, (DWORD*)&face->size.height) != ERROR_SUCCESS)
1349         {
1350             face->scalable = TRUE;
1351             memset(&face->size, 0, sizeof(face->size));
1352         }
1353         else
1354         {
1355             face->scalable = FALSE;
1356             reg_load_dword(hkey_face, face_width_value, (DWORD*)&face->size.width);
1357             reg_load_dword(hkey_face, face_size_value, (DWORD*)&face->size.size);
1358             reg_load_dword(hkey_face, face_x_ppem_value, (DWORD*)&face->size.x_ppem);
1359             reg_load_dword(hkey_face, face_y_ppem_value, (DWORD*)&face->size.y_ppem);
1360             reg_load_dword(hkey_face, face_internal_leading_value, (DWORD*)&face->size.internal_leading);
1361
1362             TRACE("Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld\n",
1363                   face->size.height, face->size.width, face->size.size >> 6,
1364                   face->size.x_ppem >> 6, face->size.y_ppem >> 6);
1365         }
1366
1367         TRACE("fsCsb = %08x %08x/%08x %08x %08x %08x\n",
1368               face->fs.fsCsb[0], face->fs.fsCsb[1],
1369               face->fs.fsUsb[0], face->fs.fsUsb[1],
1370               face->fs.fsUsb[2], face->fs.fsUsb[3]);
1371
1372         insert_face_in_family_list(face, family);
1373
1374         TRACE("Added font %s %s\n", debugstr_w(family->FamilyName), debugstr_w(face->StyleName));
1375     }
1376
1377     /* do we have any bitmap strikes? */
1378     RegQueryInfoKeyW(hkey_face, NULL, NULL, NULL, &num_strikes, &max_strike_key_len, NULL, NULL,
1379                      NULL, NULL, NULL, NULL);
1380     if(num_strikes != 0)
1381     {
1382         WCHAR strike_name[10];
1383         DWORD strike_index = 0;
1384
1385         needed = sizeof(strike_name) / sizeof(WCHAR);
1386         while(RegEnumKeyExW(hkey_face, strike_index++, strike_name, &needed,
1387                             NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1388         {
1389             HKEY hkey_strike;
1390             RegOpenKeyExW(hkey_face, strike_name, 0, KEY_ALL_ACCESS, &hkey_strike);
1391             load_face(hkey_strike, face_name, family);
1392             RegCloseKey(hkey_strike);
1393             needed = sizeof(strike_name) / sizeof(WCHAR);
1394         }
1395     }
1396 }
1397
1398 static void load_font_list_from_cache(HKEY hkey_font_cache)
1399 {
1400     DWORD max_family_key_len, size;
1401     WCHAR *family_name;
1402     DWORD family_index = 0;
1403     Family *family;
1404     HKEY hkey_family;
1405
1406     RegQueryInfoKeyW(hkey_font_cache, NULL, NULL, NULL, NULL, &max_family_key_len, NULL, NULL,
1407                      NULL, NULL, NULL, NULL);
1408     family_name = HeapAlloc(GetProcessHeap(), 0, (max_family_key_len + 1) * sizeof(WCHAR));
1409
1410     size = max_family_key_len + 1;
1411     while(RegEnumKeyExW(hkey_font_cache, family_index++, family_name, &size,
1412                         NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1413     {
1414         WCHAR *english_family = NULL;
1415         DWORD face_index = 0;
1416         WCHAR *face_name;
1417         DWORD max_face_key_len;
1418
1419         RegOpenKeyExW(hkey_font_cache, family_name, 0, KEY_ALL_ACCESS, &hkey_family);
1420         TRACE("opened family key %s\n", debugstr_w(family_name));
1421         if(RegQueryValueExW(hkey_family, english_name_value, NULL, NULL, NULL, &size) == ERROR_SUCCESS)
1422         {
1423             english_family = HeapAlloc(GetProcessHeap(), 0, size);
1424             RegQueryValueExW(hkey_family, english_name_value, NULL, NULL, (BYTE*)english_family, &size);
1425         }
1426
1427         family = create_family(strdupW(family_name), english_family);
1428         list_add_tail(&font_list, &family->entry);
1429
1430         if(english_family)
1431         {
1432             FontSubst *subst = HeapAlloc(GetProcessHeap(), 0, sizeof(*subst));
1433             subst->from.name = strdupW(english_family);
1434             subst->from.charset = -1;
1435             subst->to.name = strdupW(family_name);
1436             subst->to.charset = -1;
1437             add_font_subst(&font_subst_list, subst, 0);
1438         }
1439
1440         RegQueryInfoKeyW(hkey_family, NULL, NULL, NULL, NULL, &max_face_key_len, NULL, NULL,
1441                          NULL, NULL, NULL, NULL);
1442
1443         face_name = HeapAlloc(GetProcessHeap(), 0, (max_face_key_len + 1) * sizeof(WCHAR));
1444         size = max_face_key_len + 1;
1445         while(RegEnumKeyExW(hkey_family, face_index++, face_name, &size,
1446                             NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1447         {
1448             HKEY hkey_face;
1449
1450             RegOpenKeyExW(hkey_family, face_name, 0, KEY_ALL_ACCESS, &hkey_face);
1451             load_face(hkey_face, face_name, family);
1452             RegCloseKey(hkey_face);
1453             size = max_face_key_len + 1;
1454         }
1455         HeapFree(GetProcessHeap(), 0, face_name);
1456         RegCloseKey(hkey_family);
1457         size = max_family_key_len + 1;
1458     }
1459
1460     HeapFree(GetProcessHeap(), 0, family_name);
1461 }
1462
1463 static LONG create_font_cache_key(HKEY *hkey, DWORD *disposition)
1464 {
1465     LONG ret;
1466     HKEY hkey_wine_fonts;
1467
1468     /* We don't want to create the fonts key as volatile, so open this first */
1469     ret = RegCreateKeyExW(HKEY_CURRENT_USER, wine_fonts_key, 0, NULL, 0,
1470                           KEY_ALL_ACCESS, NULL, &hkey_wine_fonts, NULL);
1471     if(ret != ERROR_SUCCESS)
1472     {
1473         WARN("Can't create %s\n", debugstr_w(wine_fonts_key));
1474         return ret;
1475     }
1476
1477     ret = RegCreateKeyExW(hkey_wine_fonts, wine_fonts_cache_key, 0, NULL, REG_OPTION_VOLATILE,
1478                           KEY_ALL_ACCESS, NULL, hkey, disposition);
1479     RegCloseKey(hkey_wine_fonts);
1480     return ret;
1481 }
1482
1483 static void add_face_to_cache(Face *face)
1484 {
1485     HKEY hkey_font_cache, hkey_family, hkey_face;
1486     WCHAR *face_key_name;
1487
1488     create_font_cache_key(&hkey_font_cache, NULL);
1489
1490     RegCreateKeyExW(hkey_font_cache, face->family->FamilyName, 0,
1491                     NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey_family, NULL);
1492     if(face->family->EnglishName)
1493         RegSetValueExW(hkey_family, english_name_value, 0, REG_SZ, (BYTE*)face->family->EnglishName,
1494                        (strlenW(face->family->EnglishName) + 1) * sizeof(WCHAR));
1495
1496     if(face->scalable)
1497         face_key_name = face->StyleName;
1498     else
1499     {
1500         static const WCHAR fmtW[] = {'%','s','\\','%','d',0};
1501         face_key_name = HeapAlloc(GetProcessHeap(), 0, (strlenW(face->StyleName) + 10) * sizeof(WCHAR));
1502         sprintfW(face_key_name, fmtW, face->StyleName, face->size.y_ppem);
1503     }
1504     RegCreateKeyExW(hkey_family, face_key_name, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL,
1505                     &hkey_face, NULL);
1506     if(!face->scalable)
1507         HeapFree(GetProcessHeap(), 0, face_key_name);
1508
1509     RegSetValueExA(hkey_face, "File Name", 0, REG_BINARY, (BYTE*)face->file, strlen(face->file) + 1);
1510     if (face->FullName)
1511         RegSetValueExW(hkey_face, face_full_name_value, 0, REG_SZ, (BYTE*)face->FullName,
1512                        (strlenW(face->FullName) + 1) * sizeof(WCHAR));
1513
1514     reg_save_dword(hkey_face, face_index_value, face->face_index);
1515     reg_save_dword(hkey_face, face_ntmflags_value, face->ntmFlags);
1516     reg_save_dword(hkey_face, face_version_value, face->font_version);
1517     reg_save_dword(hkey_face, face_vertical_value, face->vertical);
1518
1519     RegSetValueExW(hkey_face, face_font_sig_value, 0, REG_BINARY, (BYTE*)&face->fs, sizeof(face->fs));
1520
1521     if(!face->scalable)
1522     {
1523         reg_save_dword(hkey_face, face_height_value, face->size.height);
1524         reg_save_dword(hkey_face, face_width_value, face->size.width);
1525         reg_save_dword(hkey_face, face_size_value, face->size.size);
1526         reg_save_dword(hkey_face, face_x_ppem_value, face->size.x_ppem);
1527         reg_save_dword(hkey_face, face_y_ppem_value, face->size.y_ppem);
1528         reg_save_dword(hkey_face, face_internal_leading_value, face->size.internal_leading);
1529     }
1530     RegCloseKey(hkey_face);
1531     RegCloseKey(hkey_family);
1532     RegCloseKey(hkey_font_cache);
1533 }
1534
1535 static WCHAR *prepend_at(WCHAR *family)
1536 {
1537     WCHAR *str;
1538
1539     if (!family)
1540         return NULL;
1541
1542     str = HeapAlloc(GetProcessHeap(), 0, sizeof (WCHAR) * (strlenW(family) + 2));
1543     str[0] = '@';
1544     strcpyW(str + 1, family);
1545     HeapFree(GetProcessHeap(), 0, family);
1546     return str;
1547 }
1548
1549 static void get_family_names( FT_Face ft_face, WCHAR **name, WCHAR **english, BOOL vertical )
1550 {
1551     *english = get_face_name( ft_face, TT_NAME_ID_FONT_FAMILY, TT_MS_LANGID_ENGLISH_UNITED_STATES );
1552     if (!*english) *english = towstr( CP_ACP, ft_face->family_name );
1553
1554     *name = get_face_name( ft_face, TT_NAME_ID_FONT_FAMILY, GetUserDefaultLCID() );
1555     if (!*name)
1556     {
1557         *name = *english;
1558         *english = NULL;
1559     }
1560     else if (!strcmpiW( *name, *english ))
1561     {
1562         HeapFree( GetProcessHeap(), 0, *english );
1563         *english = NULL;
1564     }
1565
1566     if (vertical)
1567     {
1568         *name = prepend_at( *name );
1569         *english = prepend_at( *english );
1570     }
1571 }
1572
1573 static Family *get_family( FT_Face ft_face, BOOL vertical )
1574 {
1575     Family *family;
1576     WCHAR *name, *english_name;
1577
1578     get_family_names( ft_face, &name, &english_name, vertical );
1579
1580     family = find_family_from_name( name );
1581
1582     if (!family)
1583     {
1584         family = create_family( name, english_name );
1585         list_add_tail( &font_list, &family->entry );
1586
1587         if (english_name)
1588         {
1589             FontSubst *subst = HeapAlloc( GetProcessHeap(), 0, sizeof(*subst) );
1590             subst->from.name = strdupW( english_name );
1591             subst->from.charset = -1;
1592             subst->to.name = strdupW( name );
1593             subst->to.charset = -1;
1594             add_font_subst( &font_subst_list, subst, 0 );
1595         }
1596     }
1597     else
1598     {
1599         HeapFree( GetProcessHeap(), 0, name );
1600         HeapFree( GetProcessHeap(), 0, english_name );
1601     }
1602
1603     return family;
1604 }
1605
1606 static inline FT_Fixed get_font_version( FT_Face ft_face )
1607 {
1608     FT_Fixed version = 0;
1609     TT_Header *header;
1610
1611     header = pFT_Get_Sfnt_Table( ft_face, ft_sfnt_head );
1612     if (header) version = header->Font_Revision;
1613
1614     return version;
1615 }
1616
1617 static inline DWORD get_ntm_flags( FT_Face ft_face )
1618 {
1619     DWORD flags = 0;
1620     FT_ULong table_size = 0;
1621
1622     if (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) flags |= NTM_ITALIC;
1623     if (ft_face->style_flags & FT_STYLE_FLAG_BOLD)   flags |= NTM_BOLD;
1624     if (flags == 0) flags = NTM_REGULAR;
1625
1626     if (!pFT_Load_Sfnt_Table( ft_face, FT_MAKE_TAG( 'C','F','F',' ' ), 0, NULL, &table_size ))
1627         flags |= NTM_PS_OPENTYPE;
1628
1629     return flags;
1630 }
1631
1632 static inline int get_bitmap_internal_leading( FT_Face ft_face )
1633 {
1634     int internal_leading = 0;
1635     FT_WinFNT_HeaderRec winfnt_header;
1636
1637     if (!pFT_Get_WinFNT_Header( ft_face, &winfnt_header ))
1638         internal_leading = winfnt_header.internal_leading;
1639
1640     return internal_leading;
1641 }
1642
1643 static inline void get_fontsig( FT_Face ft_face, FONTSIGNATURE *fs )
1644 {
1645     TT_OS2 *os2;
1646     FT_UInt dummy;
1647     CHARSETINFO csi;
1648     FT_WinFNT_HeaderRec winfnt_header;
1649     int i;
1650
1651     memset( fs, 0, sizeof(*fs) );
1652
1653     os2 = pFT_Get_Sfnt_Table( ft_face, ft_sfnt_os2 );
1654     if (os2)
1655     {
1656         fs->fsUsb[0] = os2->ulUnicodeRange1;
1657         fs->fsUsb[1] = os2->ulUnicodeRange2;
1658         fs->fsUsb[2] = os2->ulUnicodeRange3;
1659         fs->fsUsb[3] = os2->ulUnicodeRange4;
1660
1661         if (os2->version == 0)
1662         {
1663             if (pFT_Get_First_Char( ft_face, &dummy ) < 0x100)
1664                 fs->fsCsb[0] = FS_LATIN1;
1665             else
1666                 fs->fsCsb[0] = FS_SYMBOL;
1667         }
1668         else
1669         {
1670             fs->fsCsb[0] = os2->ulCodePageRange1;
1671             fs->fsCsb[1] = os2->ulCodePageRange2;
1672         }
1673     }
1674     else
1675     {
1676         if (!pFT_Get_WinFNT_Header( ft_face, &winfnt_header ))
1677         {
1678             TRACE("pix_h %d charset %d dpi %dx%d pt %d\n", winfnt_header.pixel_height, winfnt_header.charset,
1679                   winfnt_header.vertical_resolution,winfnt_header.horizontal_resolution, winfnt_header.nominal_point_size);
1680             if (TranslateCharsetInfo( (DWORD*)(UINT_PTR)winfnt_header.charset, &csi, TCI_SRCCHARSET ))
1681                 *fs = csi.fs;
1682         }
1683     }
1684
1685     if (fs->fsCsb[0] == 0)
1686     {
1687         /* let's see if we can find any interesting cmaps */
1688         for (i = 0; i < ft_face->num_charmaps; i++)
1689         {
1690             switch (ft_face->charmaps[i]->encoding)
1691             {
1692             case FT_ENCODING_UNICODE:
1693             case FT_ENCODING_APPLE_ROMAN:
1694                 fs->fsCsb[0] |= FS_LATIN1;
1695                 break;
1696             case FT_ENCODING_MS_SYMBOL:
1697                 fs->fsCsb[0] |= FS_SYMBOL;
1698                 break;
1699             default:
1700                 break;
1701             }
1702         }
1703     }
1704 }
1705
1706 #define ADDFONT_EXTERNAL_FONT 0x01
1707 #define ADDFONT_FORCE_BITMAP  0x02
1708 #define ADDFONT_ADD_TO_CACHE  0x04
1709
1710 static Face *create_face( FT_Face ft_face, FT_Long face_index, const char *file, void *font_data_ptr, DWORD font_data_size,
1711                           DWORD flags, BOOL vertical )
1712 {
1713     Face *face = HeapAlloc( GetProcessHeap(), 0, sizeof(*face) );
1714     My_FT_Bitmap_Size *size = (My_FT_Bitmap_Size *)ft_face->available_sizes;
1715
1716     face->StyleName = towstr( CP_ACP, ft_face->style_name );
1717     face->FullName = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, TT_MS_LANGID_ENGLISH_UNITED_STATES );
1718     if (file)
1719     {
1720         face->file = strdupA( file );
1721         face->font_data_ptr = NULL;
1722         face->font_data_size = 0;
1723     }
1724     else
1725     {
1726         face->file = NULL;
1727         face->font_data_ptr = font_data_ptr;
1728         face->font_data_size = font_data_size;
1729     }
1730
1731     face->face_index = face_index;
1732     get_fontsig( ft_face, &face->fs );
1733     face->ntmFlags = get_ntm_flags( ft_face );
1734     face->font_version = get_font_version( ft_face );
1735
1736     if (FT_IS_SCALABLE( ft_face ))
1737     {
1738         memset( &face->size, 0, sizeof(face->size) );
1739         face->scalable = TRUE;
1740     }
1741     else
1742     {
1743         TRACE("Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld\n",
1744               size->height, size->width, size->size >> 6,
1745               size->x_ppem >> 6, size->y_ppem >> 6);
1746         face->size.height = size->height;
1747         face->size.width = size->width;
1748         face->size.size = size->size;
1749         face->size.x_ppem = size->x_ppem;
1750         face->size.y_ppem = size->y_ppem;
1751         face->size.internal_leading = get_bitmap_internal_leading( ft_face );
1752         face->scalable = FALSE;
1753     }
1754
1755     face->vertical = vertical;
1756     face->external = (flags & ADDFONT_EXTERNAL_FONT) ? TRUE : FALSE;
1757     face->family = NULL;
1758     face->cached_enum_data = NULL;
1759
1760     TRACE("fsCsb = %08x %08x/%08x %08x %08x %08x\n",
1761           face->fs.fsCsb[0], face->fs.fsCsb[1],
1762           face->fs.fsUsb[0], face->fs.fsUsb[1],
1763           face->fs.fsUsb[2], face->fs.fsUsb[3]);
1764
1765     return face;
1766 }
1767
1768 static void AddFaceToList(FT_Face ft_face, const char *file, void *font_data_ptr, DWORD font_data_size,
1769                           FT_Long face_index, DWORD flags, BOOL vertical)
1770 {
1771     Face *face;
1772     Family *family;
1773
1774     face = create_face( ft_face, face_index, file, font_data_ptr, font_data_size, flags, vertical );
1775     family = get_family( ft_face, vertical );
1776     if (!insert_face_in_family_list( face, family ))
1777     {
1778         free_face( face );
1779         return;
1780     }
1781
1782     if (flags & ADDFONT_ADD_TO_CACHE)
1783         add_face_to_cache( face );
1784
1785     TRACE("Added font %s %s\n", debugstr_w(family->FamilyName),
1786           debugstr_w(face->StyleName));
1787 }
1788
1789 static FT_Face new_ft_face( const char *file, void *font_data_ptr, DWORD font_data_size,
1790                             FT_Long face_index, BOOL allow_bitmap )
1791 {
1792     FT_Error err;
1793     TT_OS2 *pOS2;
1794     FT_Face ft_face;
1795
1796     if (file)
1797     {
1798         TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
1799         err = pFT_New_Face(library, file, face_index, &ft_face);
1800     }
1801     else
1802     {
1803         TRACE("Loading font from ptr %p size %d, index %ld\n", font_data_ptr, font_data_size, face_index);
1804         err = pFT_New_Memory_Face(library, font_data_ptr, font_data_size, face_index, &ft_face);
1805     }
1806
1807     if (err != 0)
1808     {
1809         WARN("Unable to load font %s/%p err = %x\n", debugstr_a(file), font_data_ptr, err);
1810         return NULL;
1811     }
1812
1813     /* There are too many bugs in FreeType < 2.1.9 for bitmap font support */
1814     if (!FT_IS_SCALABLE( ft_face ) && FT_SimpleVersion < ((2 << 16) | (1 << 8) | (9 << 0)))
1815     {
1816         WARN("FreeType version < 2.1.9, skipping bitmap font %s/%p\n", debugstr_a(file), font_data_ptr);
1817         goto fail;
1818     }
1819
1820     if (!FT_IS_SFNT( ft_face ))
1821     {
1822         if (FT_IS_SCALABLE( ft_face ) || !allow_bitmap )
1823         {
1824             WARN("Ignoring font %s/%p\n", debugstr_a(file), font_data_ptr);
1825             goto fail;
1826         }
1827     }
1828     else
1829     {
1830         if (!(pOS2 = pFT_Get_Sfnt_Table( ft_face, ft_sfnt_os2 )) ||
1831             !pFT_Get_Sfnt_Table( ft_face, ft_sfnt_hhea ) ||
1832             !pFT_Get_Sfnt_Table( ft_face, ft_sfnt_head ))
1833         {
1834             TRACE("Font %s/%p lacks either an OS2, HHEA or HEAD table.\n"
1835                   "Skipping this font.\n", debugstr_a(file), font_data_ptr);
1836             goto fail;
1837         }
1838
1839         /* Wine uses ttfs as an intermediate step in building its bitmap fonts;
1840            we don't want to load these. */
1841         if (!memcmp( pOS2->achVendID, "Wine", sizeof(pOS2->achVendID) ))
1842         {
1843             FT_ULong len = 0;
1844
1845             if (!pFT_Load_Sfnt_Table( ft_face, FT_MAKE_TAG('E','B','S','C'), 0, NULL, &len ))
1846             {
1847                 TRACE("Skipping Wine bitmap-only TrueType font %s\n", debugstr_a(file));
1848                 goto fail;
1849             }
1850         }
1851     }
1852
1853     if (!ft_face->family_name || !ft_face->style_name)
1854     {
1855         TRACE("Font %s/%p lacks either a family or style name\n", debugstr_a(file), font_data_ptr);
1856         goto fail;
1857     }
1858
1859     return ft_face;
1860 fail:
1861     pFT_Done_Face( ft_face );
1862     return NULL;
1863 }
1864
1865 static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_size, DWORD flags)
1866 {
1867     FT_Face ft_face;
1868     FT_Long face_index = 0, num_faces;
1869     INT ret = 0;
1870
1871     /* we always load external fonts from files - otherwise we would get a crash in update_reg_entries */
1872     assert(file || !(flags & ADDFONT_EXTERNAL_FONT));
1873
1874 #ifdef HAVE_CARBON_CARBON_H
1875     if(file)
1876     {
1877         char **mac_list = expand_mac_font(file);
1878         if(mac_list)
1879         {
1880             BOOL had_one = FALSE;
1881             char **cursor;
1882             for(cursor = mac_list; *cursor; cursor++)
1883             {
1884                 had_one = TRUE;
1885                 AddFontToList(*cursor, NULL, 0, flags);
1886                 HeapFree(GetProcessHeap(), 0, *cursor);
1887             }
1888             HeapFree(GetProcessHeap(), 0, mac_list);
1889             if(had_one)
1890                 return 1;
1891         }
1892     }
1893 #endif /* HAVE_CARBON_CARBON_H */
1894
1895     do {
1896         ft_face = new_ft_face( file, font_data_ptr, font_data_size, face_index, flags & ADDFONT_FORCE_BITMAP );
1897         if (!ft_face) return 0;
1898
1899         if(ft_face->family_name[0] == '.') /* Ignore fonts with names beginning with a dot */
1900         {
1901             TRACE("Ignoring %s since its family name begins with a dot\n", debugstr_a(file));
1902             pFT_Done_Face(ft_face);
1903             return 0;
1904         }
1905
1906         AddFaceToList(ft_face, file, font_data_ptr, font_data_size, face_index, flags, FALSE);
1907         ++ret;
1908
1909         if (FT_HAS_VERTICAL(ft_face))
1910         {
1911             AddFaceToList(ft_face, file, font_data_ptr, font_data_size, face_index, flags, TRUE);
1912             ++ret;
1913         }
1914
1915         num_faces = ft_face->num_faces;
1916         pFT_Done_Face(ft_face);
1917     } while(num_faces > ++face_index);
1918     return ret;
1919 }
1920
1921 static void DumpFontList(void)
1922 {
1923     Family *family;
1924     Face *face;
1925     struct list *family_elem_ptr, *face_elem_ptr;
1926
1927     LIST_FOR_EACH(family_elem_ptr, &font_list) {
1928         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
1929         TRACE("Family: %s\n", debugstr_w(family->FamilyName));
1930         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
1931             face = LIST_ENTRY(face_elem_ptr, Face, entry);
1932             TRACE("\t%s\t%08x", debugstr_w(face->StyleName), face->fs.fsCsb[0]);
1933             if(!face->scalable)
1934                 TRACE(" %d", face->size.height);
1935             TRACE("\n");
1936         }
1937     }
1938     return;
1939 }
1940
1941 /***********************************************************
1942  * The replacement list is a way to map an entire font
1943  * family onto another family.  For example adding
1944  *
1945  * [HKCU\Software\Wine\Fonts\Replacements]
1946  * "Wingdings"="Winedings"
1947  *
1948  * would enumerate the Winedings font both as Winedings and
1949  * Wingdings.  However if a real Wingdings font is present the
1950  * replacement does not take place.
1951  * 
1952  */
1953 static void LoadReplaceList(void)
1954 {
1955     HKEY hkey;
1956     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
1957     LPWSTR value;
1958     LPVOID data;
1959     CHAR familyA[400];
1960
1961     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\Replacements */
1962     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts\\Replacements", &hkey) == ERROR_SUCCESS)
1963     {
1964         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1965                          &valuelen, &datalen, NULL, NULL);
1966
1967         valuelen++; /* returned value doesn't include room for '\0' */
1968         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
1969         data = HeapAlloc(GetProcessHeap(), 0, datalen);
1970
1971         dlen = datalen;
1972         vlen = valuelen;
1973         while(RegEnumValueW(hkey, i++, value, &vlen, NULL, &type, data,
1974                             &dlen) == ERROR_SUCCESS) {
1975             TRACE("Got %s=%s\n", debugstr_w(value), debugstr_w(data));
1976             /* "NewName"="Oldname" */
1977             WideCharToMultiByte(CP_ACP, 0, value, -1, familyA, sizeof(familyA), NULL, NULL);
1978
1979             if(!find_family_from_any_name(value))
1980             {
1981                 Family * const family = find_family_from_any_name(data);
1982                 if (family != NULL)
1983                 {
1984                     Family * const new_family = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_family));
1985                     if (new_family != NULL)
1986                     {
1987                         TRACE("mapping %s to %s\n", debugstr_w(data), debugstr_w(value));
1988                         new_family->FamilyName = strdupW(value);
1989                         new_family->EnglishName = NULL;
1990                         list_init(&new_family->faces);
1991                         new_family->replacement = &family->faces;
1992                         list_add_tail(&font_list, &new_family->entry);
1993                     }
1994                 }
1995                 else
1996                 {
1997                     TRACE("%s is not available. Skip this replacement.\n", debugstr_w(data));
1998                 }
1999             }
2000             else
2001             {
2002                 TRACE("%s is available. Skip this replacement.\n", debugstr_w(value));
2003             }
2004             /* reset dlen and vlen */
2005             dlen = datalen;
2006             vlen = valuelen;
2007         }
2008         HeapFree(GetProcessHeap(), 0, data);
2009         HeapFree(GetProcessHeap(), 0, value);
2010         RegCloseKey(hkey);
2011     }
2012 }
2013
2014 static const WCHAR *font_links_list[] =
2015 {
2016     Lucida_Sans_Unicode,
2017     Microsoft_Sans_Serif,
2018     Tahoma
2019 };
2020
2021 static const struct font_links_defaults_list
2022 {
2023     /* Keyed off substitution for "MS Shell Dlg" */
2024     const WCHAR *shelldlg;
2025     /* Maximum of four substitutes, plus terminating NULL pointer */
2026     const WCHAR *substitutes[5];
2027 } font_links_defaults_list[] =
2028 {
2029     /* Non East-Asian */
2030     { Tahoma, /* FIXME unverified ordering */
2031       { MS_UI_Gothic, SimSun, Gulim, PMingLiU, NULL }
2032     },
2033     /* Below lists are courtesy of
2034      * http://blogs.msdn.com/michkap/archive/2005/06/18/430507.aspx
2035      */
2036     /* Japanese */
2037     { MS_UI_Gothic,
2038       { MS_UI_Gothic, PMingLiU, SimSun, Gulim, NULL }
2039     },
2040     /* Chinese Simplified */
2041     { SimSun,
2042       { SimSun, PMingLiU, MS_UI_Gothic, Batang, NULL }
2043     },
2044     /* Korean */
2045     { Gulim,
2046       { Gulim, PMingLiU, MS_UI_Gothic, SimSun, NULL }
2047     },
2048     /* Chinese Traditional */
2049     { PMingLiU,
2050       { PMingLiU, SimSun, MS_UI_Gothic, Batang, NULL }
2051     }
2052 };
2053
2054
2055 static SYSTEM_LINKS *find_font_link(const WCHAR *name)
2056 {
2057     SYSTEM_LINKS *font_link;
2058
2059     LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
2060     {
2061         if(!strcmpiW(font_link->font_name, name))
2062             return font_link;
2063     }
2064
2065     return NULL;
2066 }
2067
2068 static void populate_system_links(const WCHAR *name, const WCHAR *const *values)
2069 {
2070     const WCHAR *value;
2071     int i;
2072     FontSubst *psub;
2073     Family *family;
2074     Face *face;
2075     const char *file;
2076     WCHAR *fileW;
2077
2078     if (values)
2079     {
2080         SYSTEM_LINKS *font_link;
2081
2082         psub = get_font_subst(&font_subst_list, name, -1);
2083         /* Don't store fonts that are only substitutes for other fonts */
2084         if(psub)
2085         {
2086             TRACE("%s: Internal SystemLink entry for substituted font, ignoring\n", debugstr_w(name));
2087             return;
2088         }
2089
2090         font_link = find_font_link(name);
2091         if (font_link == NULL)
2092         {
2093             font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_link));
2094             font_link->font_name = strdupW(name);
2095             list_init(&font_link->links);
2096             list_add_tail(&system_links, &font_link->entry);
2097         }
2098
2099         memset(&font_link->fs, 0, sizeof font_link->fs);
2100         for (i = 0; values[i] != NULL; i++)
2101         {
2102             const struct list *face_list;
2103             CHILD_FONT *child_font;
2104
2105             value = values[i];
2106             if (!strcmpiW(name,value))
2107                 continue;
2108             psub = get_font_subst(&font_subst_list, value, -1);
2109             if(psub)
2110                 value = psub->to.name;
2111             family = find_family_from_name(value);
2112             if (!family)
2113                 continue;
2114             file = NULL;
2115             /* Use first extant filename for this Family */
2116             face_list = get_face_list_from_family(family);
2117             LIST_FOR_EACH_ENTRY(face, face_list, Face, entry)
2118             {
2119                 if (!face->file)
2120                     continue;
2121                 file = strrchr(face->file, '/');
2122                 if (!file)
2123                     file = face->file;
2124                 else
2125                     file++;
2126                 break;
2127             }
2128             if (!file)
2129                 continue;
2130             fileW = towstr(CP_UNIXCP, file);
2131
2132             face = find_face_from_filename(fileW, value);
2133             if(!face)
2134             {
2135                 TRACE("Unable to find file %s face name %s\n", debugstr_w(fileW), debugstr_w(value));
2136                 continue;
2137             }
2138
2139             child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
2140             child_font->face = face;
2141             child_font->font = NULL;
2142             font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
2143             font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
2144             TRACE("Adding file %s index %ld\n", child_font->face->file, child_font->face->face_index);
2145             list_add_tail(&font_link->links, &child_font->entry);
2146
2147             TRACE("added internal SystemLink for %s to %s in %s\n", debugstr_w(name), debugstr_w(value),debugstr_w(fileW));
2148             HeapFree(GetProcessHeap(), 0, fileW);
2149         }
2150     }
2151 }
2152
2153
2154 /*************************************************************
2155  * init_system_links
2156  */
2157 static BOOL init_system_links(void)
2158 {
2159     HKEY hkey;
2160     BOOL ret = FALSE;
2161     DWORD type, max_val, max_data, val_len, data_len, index;
2162     WCHAR *value, *data;
2163     WCHAR *entry, *next;
2164     SYSTEM_LINKS *font_link, *system_font_link;
2165     CHILD_FONT *child_font;
2166     static const WCHAR tahoma_ttf[] = {'t','a','h','o','m','a','.','t','t','f',0};
2167     static const WCHAR System[] = {'S','y','s','t','e','m',0};
2168     static const WCHAR MS_Shell_Dlg[] = {'M','S',' ','S','h','e','l','l',' ','D','l','g',0};
2169     Face *face;
2170     FontSubst *psub;
2171     UINT i, j;
2172
2173     if(RegOpenKeyW(HKEY_LOCAL_MACHINE, system_link, &hkey) == ERROR_SUCCESS)
2174     {
2175         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &max_val, &max_data, NULL, NULL);
2176         value = HeapAlloc(GetProcessHeap(), 0, (max_val + 1) * sizeof(WCHAR));
2177         data = HeapAlloc(GetProcessHeap(), 0, max_data);
2178         val_len = max_val + 1;
2179         data_len = max_data;
2180         index = 0;
2181         while(RegEnumValueW(hkey, index++, value, &val_len, NULL, &type, (LPBYTE)data, &data_len) == ERROR_SUCCESS)
2182         {
2183             psub = get_font_subst(&font_subst_list, value, -1);
2184             /* Don't store fonts that are only substitutes for other fonts */
2185             if(psub)
2186             {
2187                 TRACE("%s: SystemLink entry for substituted font, ignoring\n", debugstr_w(value));
2188                 goto next;
2189             }
2190             font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_link));
2191             font_link->font_name = strdupW(value);
2192             memset(&font_link->fs, 0, sizeof font_link->fs);
2193             list_init(&font_link->links);
2194             for(entry = data; (char*)entry < (char*)data + data_len && *entry != 0; entry = next)
2195             {
2196                 WCHAR *face_name;
2197                 CHILD_FONT *child_font;
2198
2199                 TRACE("%s: %s\n", debugstr_w(value), debugstr_w(entry));
2200
2201                 next = entry + strlenW(entry) + 1;
2202                 
2203                 face_name = strchrW(entry, ',');
2204                 if(face_name)
2205                 {
2206                     *face_name++ = 0;
2207                     while(isspaceW(*face_name))
2208                         face_name++;
2209
2210                     psub = get_font_subst(&font_subst_list, face_name, -1);
2211                     if(psub)
2212                         face_name = psub->to.name;
2213                 }
2214                 face = find_face_from_filename(entry, face_name);
2215                 if(!face)
2216                 {
2217                     TRACE("Unable to find file %s face name %s\n", debugstr_w(entry), debugstr_w(face_name));
2218                     continue;
2219                 }
2220
2221                 child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
2222                 child_font->face = face;
2223                 child_font->font = NULL;
2224                 font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
2225                 font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
2226                 TRACE("Adding file %s index %ld\n", child_font->face->file, child_font->face->face_index);
2227                 list_add_tail(&font_link->links, &child_font->entry);
2228             }
2229             list_add_tail(&system_links, &font_link->entry);
2230         next:
2231             val_len = max_val + 1;
2232             data_len = max_data;
2233         }
2234
2235         HeapFree(GetProcessHeap(), 0, value);
2236         HeapFree(GetProcessHeap(), 0, data);
2237         RegCloseKey(hkey);
2238     }
2239
2240
2241     psub = get_font_subst(&font_subst_list, MS_Shell_Dlg, -1);
2242     if (!psub) {
2243         WARN("could not find FontSubstitute for MS Shell Dlg\n");
2244         goto skip_internal;
2245     }
2246
2247     for (i = 0; i < sizeof(font_links_defaults_list)/sizeof(font_links_defaults_list[0]); i++)
2248     {
2249         const FontSubst *psub2;
2250         psub2 = get_font_subst(&font_subst_list, font_links_defaults_list[i].shelldlg, -1);
2251
2252         if ((!strcmpiW(font_links_defaults_list[i].shelldlg, psub->to.name) || (psub2 && !strcmpiW(psub2->to.name,psub->to.name))))
2253         {
2254             for (j = 0; j < sizeof(font_links_list)/sizeof(font_links_list[0]); j++)
2255                 populate_system_links(font_links_list[j], font_links_defaults_list[i].substitutes);
2256
2257             if (!strcmpiW(psub->to.name, font_links_defaults_list[i].substitutes[0]))
2258                 populate_system_links(psub->to.name, font_links_defaults_list[i].substitutes);
2259         }
2260         else if (strcmpiW(psub->to.name, font_links_defaults_list[i].substitutes[0]))
2261         {
2262             populate_system_links(font_links_defaults_list[i].substitutes[0], NULL);
2263         }
2264     }
2265
2266 skip_internal:
2267
2268     /* Explicitly add an entry for the system font, this links to Tahoma and any links
2269        that Tahoma has */
2270
2271     system_font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*system_font_link));
2272     system_font_link->font_name = strdupW(System);
2273     memset(&system_font_link->fs, 0, sizeof system_font_link->fs);
2274     list_init(&system_font_link->links);    
2275
2276     face = find_face_from_filename(tahoma_ttf, Tahoma);
2277     if(face)
2278     {
2279         child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
2280         child_font->face = face;
2281         child_font->font = NULL;
2282         system_font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
2283         system_font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
2284         TRACE("Found Tahoma in %s index %ld\n", child_font->face->file, child_font->face->face_index);
2285         list_add_tail(&system_font_link->links, &child_font->entry);
2286     }
2287     font_link = find_font_link(Tahoma);
2288     if (font_link != NULL)
2289     {
2290         CHILD_FONT *font_link_entry;
2291         LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
2292         {
2293             CHILD_FONT *new_child;
2294             new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
2295             new_child->face = font_link_entry->face;
2296             new_child->font = NULL;
2297             system_font_link->fs.fsCsb[0] |= font_link_entry->face->fs.fsCsb[0];
2298             system_font_link->fs.fsCsb[1] |= font_link_entry->face->fs.fsCsb[1];
2299             list_add_tail(&system_font_link->links, &new_child->entry);
2300         }
2301     }
2302     list_add_tail(&system_links, &system_font_link->entry);
2303     return ret;
2304 }
2305
2306 static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
2307 {
2308     DIR *dir;
2309     struct dirent *dent;
2310     char path[MAX_PATH];
2311
2312     TRACE("Loading fonts from %s\n", debugstr_a(dirname));
2313
2314     dir = opendir(dirname);
2315     if(!dir) {
2316         WARN("Can't open directory %s\n", debugstr_a(dirname));
2317         return FALSE;
2318     }
2319     while((dent = readdir(dir)) != NULL) {
2320         struct stat statbuf;
2321
2322         if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
2323             continue;
2324
2325         TRACE("Found %s in %s\n", debugstr_a(dent->d_name), debugstr_a(dirname));
2326
2327         sprintf(path, "%s/%s", dirname, dent->d_name);
2328
2329         if(stat(path, &statbuf) == -1)
2330         {
2331             WARN("Can't stat %s\n", debugstr_a(path));
2332             continue;
2333         }
2334         if(S_ISDIR(statbuf.st_mode))
2335             ReadFontDir(path, external_fonts);
2336         else
2337         {
2338             DWORD addfont_flags = ADDFONT_ADD_TO_CACHE;
2339             if(external_fonts) addfont_flags |= ADDFONT_EXTERNAL_FONT;
2340             AddFontToList(path, NULL, 0, addfont_flags);
2341         }
2342     }
2343     closedir(dir);
2344     return TRUE;
2345 }
2346
2347 #ifdef SONAME_LIBFONTCONFIG
2348 static void load_fontconfig_fonts(void)
2349 {
2350     void *fc_handle = NULL;
2351     FcConfig *config;
2352     FcPattern *pat;
2353     FcObjectSet *os;
2354     FcFontSet *fontset;
2355     int i, len;
2356     char *file;
2357     const char *ext;
2358
2359     fc_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0);
2360     if(!fc_handle) {
2361         TRACE("Wine cannot find the fontconfig library (%s).\n",
2362               SONAME_LIBFONTCONFIG);
2363         return;
2364     }
2365 #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;}
2366 LOAD_FUNCPTR(FcConfigGetCurrent);
2367 LOAD_FUNCPTR(FcFontList);
2368 LOAD_FUNCPTR(FcFontSetDestroy);
2369 LOAD_FUNCPTR(FcInit);
2370 LOAD_FUNCPTR(FcObjectSetAdd);
2371 LOAD_FUNCPTR(FcObjectSetCreate);
2372 LOAD_FUNCPTR(FcObjectSetDestroy);
2373 LOAD_FUNCPTR(FcPatternCreate);
2374 LOAD_FUNCPTR(FcPatternDestroy);
2375 LOAD_FUNCPTR(FcPatternGetBool);
2376 LOAD_FUNCPTR(FcPatternGetString);
2377 #undef LOAD_FUNCPTR
2378
2379     if(!pFcInit()) return;
2380     
2381     config = pFcConfigGetCurrent();
2382     pat = pFcPatternCreate();
2383     os = pFcObjectSetCreate();
2384     pFcObjectSetAdd(os, FC_FILE);
2385     pFcObjectSetAdd(os, FC_SCALABLE);
2386     fontset = pFcFontList(config, pat, os);
2387     if(!fontset) return;
2388     for(i = 0; i < fontset->nfont; i++) {
2389         FcBool scalable;
2390
2391         if(pFcPatternGetString(fontset->fonts[i], FC_FILE, 0, (FcChar8**)&file) != FcResultMatch)
2392             continue;
2393         TRACE("fontconfig: %s\n", file);
2394
2395         /* We're just interested in OT/TT fonts for now, so this hack just
2396            picks up the scalable fonts without extensions .pf[ab] to save time
2397            loading every other font */
2398
2399         if(pFcPatternGetBool(fontset->fonts[i], FC_SCALABLE, 0, &scalable) == FcResultMatch && !scalable)
2400         {
2401             TRACE("not scalable\n");
2402             continue;
2403         }
2404
2405         len = strlen( file );
2406         if(len < 4) continue;
2407         ext = &file[ len - 3 ];
2408         if(strcasecmp(ext, "pfa") && strcasecmp(ext, "pfb"))
2409             AddFontToList(file, NULL, 0, ADDFONT_EXTERNAL_FONT | ADDFONT_ADD_TO_CACHE);
2410     }
2411     pFcFontSetDestroy(fontset);
2412     pFcObjectSetDestroy(os);
2413     pFcPatternDestroy(pat);
2414  sym_not_found:
2415     return;
2416 }
2417
2418 #elif defined(HAVE_CARBON_CARBON_H)
2419
2420 static void load_mac_font_callback(const void *value, void *context)
2421 {
2422     CFStringRef pathStr = value;
2423     CFIndex len;
2424     char* path;
2425
2426     len = CFStringGetMaximumSizeOfFileSystemRepresentation(pathStr);
2427     path = HeapAlloc(GetProcessHeap(), 0, len);
2428     if (path && CFStringGetFileSystemRepresentation(pathStr, path, len))
2429     {
2430         TRACE("font file %s\n", path);
2431         AddFontToList(path, NULL, 0, ADDFONT_EXTERNAL_FONT | ADDFONT_ADD_TO_CACHE);
2432     }
2433     HeapFree(GetProcessHeap(), 0, path);
2434 }
2435
2436 static void load_mac_fonts(void)
2437 {
2438     CFStringRef removeDupesKey;
2439     CFBooleanRef removeDupesValue;
2440     CFDictionaryRef options;
2441     CTFontCollectionRef col;
2442     CFArrayRef descs;
2443     CFMutableSetRef paths;
2444     CFIndex i;
2445
2446     removeDupesKey = kCTFontCollectionRemoveDuplicatesOption;
2447     removeDupesValue = kCFBooleanTrue;
2448     options = CFDictionaryCreate(NULL, (const void**)&removeDupesKey, (const void**)&removeDupesValue, 1,
2449                                  &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2450     col = CTFontCollectionCreateFromAvailableFonts(options);
2451     if (options) CFRelease(options);
2452     if (!col)
2453     {
2454         WARN("CTFontCollectionCreateFromAvailableFonts failed\n");
2455         return;
2456     }
2457
2458     descs = CTFontCollectionCreateMatchingFontDescriptors(col);
2459     CFRelease(col);
2460     if (!descs)
2461     {
2462         WARN("CTFontCollectionCreateMatchingFontDescriptors failed\n");
2463         return;
2464     }
2465
2466     paths = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
2467     if (!paths)
2468     {
2469         WARN("CFSetCreateMutable failed\n");
2470         CFRelease(descs);
2471         return;
2472     }
2473
2474     for (i = 0; i < CFArrayGetCount(descs); i++)
2475     {
2476         CTFontDescriptorRef desc;
2477         CTFontRef font;
2478         ATSFontRef atsFont;
2479         OSStatus status;
2480         FSRef fsref;
2481         CFURLRef url;
2482         CFStringRef ext;
2483         CFStringRef path;
2484
2485         desc = CFArrayGetValueAtIndex(descs, i);
2486
2487         /* CTFontDescriptor doesn't support kCTFontURLAttribute until 10.6, so
2488            we have to go CFFontDescriptor -> CTFont -> ATSFont -> FSRef -> CFURL. */
2489         font = CTFontCreateWithFontDescriptor(desc, 0, NULL);
2490         if (!font) continue;
2491
2492         atsFont = CTFontGetPlatformFont(font, NULL);
2493         if (!atsFont)
2494         {
2495             CFRelease(font);
2496             continue;
2497         }
2498
2499         status = ATSFontGetFileReference(atsFont, &fsref);
2500         CFRelease(font);
2501         if (status != noErr) continue;
2502
2503         url = CFURLCreateFromFSRef(NULL, &fsref);
2504         if (!url) continue;
2505
2506         ext = CFURLCopyPathExtension(url);
2507         if (ext)
2508         {
2509             BOOL skip = (CFStringCompare(ext, CFSTR("pfa"), kCFCompareCaseInsensitive) == kCFCompareEqualTo ||
2510                          CFStringCompare(ext, CFSTR("pfb"), kCFCompareCaseInsensitive) == kCFCompareEqualTo);
2511             CFRelease(ext);
2512             if (skip)
2513             {
2514                 CFRelease(url);
2515                 continue;
2516             }
2517         }
2518
2519         path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
2520         CFRelease(url);
2521         if (!path) continue;
2522
2523         CFSetAddValue(paths, path);
2524         CFRelease(path);
2525     }
2526
2527     CFRelease(descs);
2528
2529     CFSetApplyFunction(paths, load_mac_font_callback, NULL);
2530     CFRelease(paths);
2531 }
2532
2533 #endif
2534
2535 static BOOL load_font_from_data_dir(LPCWSTR file)
2536 {
2537     BOOL ret = FALSE;
2538     const char *data_dir = wine_get_data_dir();
2539
2540     if (!data_dir) data_dir = wine_get_build_dir();
2541
2542     if (data_dir)
2543     {
2544         INT len;
2545         char *unix_name;
2546
2547         len = WideCharToMultiByte(CP_UNIXCP, 0, file, -1, NULL, 0, NULL, NULL);
2548
2549         unix_name = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + len + sizeof("/fonts/"));
2550
2551         strcpy(unix_name, data_dir);
2552         strcat(unix_name, "/fonts/");
2553
2554         WideCharToMultiByte(CP_UNIXCP, 0, file, -1, unix_name + strlen(unix_name), len, NULL, NULL);
2555
2556         EnterCriticalSection( &freetype_cs );
2557         ret = AddFontToList(unix_name, NULL, 0, ADDFONT_FORCE_BITMAP | ADDFONT_ADD_TO_CACHE);
2558         LeaveCriticalSection( &freetype_cs );
2559         HeapFree(GetProcessHeap(), 0, unix_name);
2560     }
2561     return ret;
2562 }
2563
2564 static BOOL load_font_from_winfonts_dir(LPCWSTR file)
2565 {
2566     static const WCHAR slashW[] = {'\\','\0'};
2567     BOOL ret = FALSE;
2568     WCHAR windowsdir[MAX_PATH];
2569     char *unixname;
2570
2571     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
2572     strcatW(windowsdir, fontsW);
2573     strcatW(windowsdir, slashW);
2574     strcatW(windowsdir, file);
2575     if ((unixname = wine_get_unix_file_name(windowsdir))) {
2576         EnterCriticalSection( &freetype_cs );
2577         ret = AddFontToList(unixname, NULL, 0, ADDFONT_FORCE_BITMAP);
2578         LeaveCriticalSection( &freetype_cs );
2579         HeapFree(GetProcessHeap(), 0, unixname);
2580     }
2581     return ret;
2582 }
2583
2584 static void load_system_fonts(void)
2585 {
2586     HKEY hkey;
2587     WCHAR data[MAX_PATH], windowsdir[MAX_PATH], pathW[MAX_PATH];
2588     const WCHAR * const *value;
2589     DWORD dlen, type;
2590     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
2591     char *unixname;
2592
2593     if(RegOpenKeyW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, &hkey) == ERROR_SUCCESS) {
2594         GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
2595         strcatW(windowsdir, fontsW);
2596         for(value = SystemFontValues; *value; value++) { 
2597             dlen = sizeof(data);
2598             if(RegQueryValueExW(hkey, *value, 0, &type, (void*)data, &dlen) == ERROR_SUCCESS &&
2599                type == REG_SZ) {
2600                 BOOL added = FALSE;
2601
2602                 sprintfW(pathW, fmtW, windowsdir, data);
2603                 if((unixname = wine_get_unix_file_name(pathW))) {
2604                     added = AddFontToList(unixname, NULL, 0, ADDFONT_FORCE_BITMAP | ADDFONT_ADD_TO_CACHE);
2605                     HeapFree(GetProcessHeap(), 0, unixname);
2606                 }
2607                 if (!added)
2608                     load_font_from_data_dir(data);
2609             }
2610         }
2611         RegCloseKey(hkey);
2612     }
2613 }
2614
2615 /*************************************************************
2616  *
2617  * This adds registry entries for any externally loaded fonts
2618  * (fonts from fontconfig or FontDirs).  It also deletes entries
2619  * of no longer existing fonts.
2620  *
2621  */
2622 static void update_reg_entries(void)
2623 {
2624     HKEY winnt_key = 0, win9x_key = 0, external_key = 0;
2625     LPWSTR valueW;
2626     DWORD len, len_fam;
2627     Family *family;
2628     Face *face;
2629     struct list *family_elem_ptr, *face_elem_ptr;
2630     WCHAR *file;
2631     static const WCHAR TrueType[] = {' ','(','T','r','u','e','T','y','p','e',')','\0'};
2632     static const WCHAR spaceW[] = {' ', '\0'};
2633     char *path;
2634
2635     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key,
2636                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &winnt_key, NULL) != ERROR_SUCCESS) {
2637         ERR("Can't create Windows font reg key\n");
2638         goto end;
2639     }
2640
2641     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key,
2642                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &win9x_key, NULL) != ERROR_SUCCESS) {
2643         ERR("Can't create Windows font reg key\n");
2644         goto end;
2645     }
2646
2647     if(RegCreateKeyExW(HKEY_CURRENT_USER, external_fonts_reg_key,
2648                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &external_key, NULL) != ERROR_SUCCESS) {
2649         ERR("Can't create external font reg key\n");
2650         goto end;
2651     }
2652
2653     /* enumerate the fonts and add external ones to the two keys */
2654
2655     LIST_FOR_EACH(family_elem_ptr, &font_list) {
2656         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
2657         len_fam = strlenW(family->FamilyName) + sizeof(TrueType) / sizeof(WCHAR) + 1;
2658         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
2659             face = LIST_ENTRY(face_elem_ptr, Face, entry);
2660             if(!face->external) continue;
2661             len = len_fam;
2662             if (!(face->ntmFlags & NTM_REGULAR))
2663                 len = len_fam + strlenW(face->StyleName) + 1;
2664             valueW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2665             strcpyW(valueW, family->FamilyName);
2666             if(len != len_fam) {
2667                 strcatW(valueW, spaceW);
2668                 strcatW(valueW, face->StyleName);
2669             }
2670             strcatW(valueW, TrueType);
2671
2672             file = wine_get_dos_file_name(face->file);
2673             if(file)
2674                 len = strlenW(file) + 1;
2675             else
2676             {
2677                 if((path = strrchr(face->file, '/')) == NULL)
2678                     path = face->file;
2679                 else
2680                     path++;
2681                 len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
2682
2683                 file = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2684                 MultiByteToWideChar(CP_ACP, 0, path, -1, file, len);
2685             }
2686             RegSetValueExW(winnt_key, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
2687             RegSetValueExW(win9x_key, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
2688             RegSetValueExW(external_key, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
2689
2690             HeapFree(GetProcessHeap(), 0, file);
2691             HeapFree(GetProcessHeap(), 0, valueW);
2692         }
2693     }
2694  end:
2695     if(external_key) RegCloseKey(external_key);
2696     if(win9x_key) RegCloseKey(win9x_key);
2697     if(winnt_key) RegCloseKey(winnt_key);
2698     return;
2699 }
2700
2701 static void delete_external_font_keys(void)
2702 {
2703     HKEY winnt_key = 0, win9x_key = 0, external_key = 0;
2704     DWORD dlen, vlen, datalen, valuelen, i, type;
2705     LPWSTR valueW;
2706     LPVOID data;
2707
2708     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key,
2709                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &winnt_key, NULL) != ERROR_SUCCESS) {
2710         ERR("Can't create Windows font reg key\n");
2711         goto end;
2712     }
2713
2714     if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key,
2715                        0, NULL, 0, KEY_ALL_ACCESS, NULL, &win9x_key, NULL) != ERROR_SUCCESS) {
2716         ERR("Can't create Windows font reg key\n");
2717         goto end;
2718     }
2719
2720     if(RegCreateKeyW(HKEY_CURRENT_USER, external_fonts_reg_key, &external_key) != ERROR_SUCCESS) {
2721         ERR("Can't create external font reg key\n");
2722         goto end;
2723     }
2724
2725     /* Delete all external fonts added last time */
2726
2727     RegQueryInfoKeyW(external_key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2728                      &valuelen, &datalen, NULL, NULL);
2729     valuelen++; /* returned value doesn't include room for '\0' */
2730     valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
2731     data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
2732
2733     dlen = datalen * sizeof(WCHAR);
2734     vlen = valuelen;
2735     i = 0;
2736     while(RegEnumValueW(external_key, i++, valueW, &vlen, NULL, &type, data,
2737                         &dlen) == ERROR_SUCCESS) {
2738
2739         RegDeleteValueW(winnt_key, valueW);
2740         RegDeleteValueW(win9x_key, valueW);
2741         /* reset dlen and vlen */
2742         dlen = datalen;
2743         vlen = valuelen;
2744     }
2745     HeapFree(GetProcessHeap(), 0, data);
2746     HeapFree(GetProcessHeap(), 0, valueW);
2747
2748     /* Delete the old external fonts key */
2749     RegCloseKey(external_key);
2750     RegDeleteKeyW(HKEY_CURRENT_USER, external_fonts_reg_key);
2751
2752  end:
2753     if(win9x_key) RegCloseKey(win9x_key);
2754     if(winnt_key) RegCloseKey(winnt_key);
2755 }
2756
2757 /*************************************************************
2758  *    WineEngAddFontResourceEx
2759  *
2760  */
2761 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
2762 {
2763     INT ret = 0;
2764
2765     GDI_CheckNotLock();
2766
2767     if (ft_handle)  /* do it only if we have freetype up and running */
2768     {
2769         char *unixname;
2770
2771         if(flags)
2772             FIXME("Ignoring flags %x\n", flags);
2773
2774         if((unixname = wine_get_unix_file_name(file)))
2775         {
2776             DWORD addfont_flags = ADDFONT_FORCE_BITMAP;
2777
2778             if(!(flags & FR_PRIVATE)) addfont_flags |= ADDFONT_ADD_TO_CACHE;
2779             EnterCriticalSection( &freetype_cs );
2780             ret = AddFontToList(unixname, NULL, 0, addfont_flags);
2781             LeaveCriticalSection( &freetype_cs );
2782             HeapFree(GetProcessHeap(), 0, unixname);
2783         }
2784         if (!ret && !strchrW(file, '\\')) {
2785             /* Try in %WINDIR%/fonts, needed for Fotobuch Designer */
2786             ret = load_font_from_winfonts_dir(file);
2787             if (!ret) {
2788                 /* Try in datadir/fonts (or builddir/fonts),
2789                  * needed for Magic the Gathering Online
2790                  */
2791                 ret = load_font_from_data_dir(file);
2792             }
2793         }
2794     }
2795    return ret;
2796 }
2797
2798 /*************************************************************
2799  *    WineEngAddFontMemResourceEx
2800  *
2801  */
2802 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
2803 {
2804     GDI_CheckNotLock();
2805
2806     if (ft_handle)  /* do it only if we have freetype up and running */
2807     {
2808         PVOID pFontCopy = HeapAlloc(GetProcessHeap(), 0, cbFont);
2809
2810         TRACE("Copying %d bytes of data from %p to %p\n", cbFont, pbFont, pFontCopy);
2811         memcpy(pFontCopy, pbFont, cbFont);
2812
2813         EnterCriticalSection( &freetype_cs );
2814         *pcFonts = AddFontToList(NULL, pFontCopy, cbFont, ADDFONT_FORCE_BITMAP);
2815         LeaveCriticalSection( &freetype_cs );
2816
2817         if (*pcFonts == 0)
2818         {
2819             TRACE("AddFontToList failed\n");
2820             HeapFree(GetProcessHeap(), 0, pFontCopy);
2821             return 0;
2822         }
2823         /* FIXME: is the handle only for use in RemoveFontMemResourceEx or should it be a true handle?
2824          * For now return something unique but quite random
2825          */
2826         TRACE("Returning handle %lx\n", ((INT_PTR)pFontCopy)^0x87654321);
2827         return (HANDLE)(((INT_PTR)pFontCopy)^0x87654321);
2828     }
2829
2830     *pcFonts = 0;
2831     return 0;
2832 }
2833
2834 /*************************************************************
2835  *    WineEngRemoveFontResourceEx
2836  *
2837  */
2838 BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
2839 {
2840     GDI_CheckNotLock();
2841     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
2842     return TRUE;
2843 }
2844
2845 static char *get_ttf_file_name( LPCWSTR font_file, LPCWSTR font_path )
2846 {
2847     WCHAR *fullname;
2848     char *unix_name;
2849     int file_len;
2850
2851     if (!font_file) return NULL;
2852
2853     file_len = strlenW( font_file );
2854
2855     if (font_path && font_path[0])
2856     {
2857         int path_len = strlenW( font_path );
2858         fullname = HeapAlloc( GetProcessHeap(), 0, (file_len + path_len + 2) * sizeof(WCHAR) );
2859         if (!fullname) return NULL;
2860         memcpy( fullname, font_path, path_len * sizeof(WCHAR) );
2861         fullname[path_len] = '\\';
2862         memcpy( fullname + path_len + 1, font_file, (file_len + 1) * sizeof(WCHAR) );
2863     }
2864     else
2865     {
2866         int len = GetFullPathNameW( font_file, 0, NULL, NULL );
2867         if (!len) return NULL;
2868         fullname = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2869         if (!fullname) return NULL;
2870         GetFullPathNameW( font_file, len, fullname, NULL );
2871     }
2872
2873     unix_name = wine_get_unix_file_name( fullname );
2874     HeapFree( GetProcessHeap(), 0, fullname );
2875     return unix_name;
2876 }
2877
2878 #include <pshpack1.h>
2879 struct fontdir
2880 {
2881     WORD   num_of_resources;
2882     WORD   res_id;
2883     WORD   dfVersion;
2884     DWORD  dfSize;
2885     CHAR   dfCopyright[60];
2886     WORD   dfType;
2887     WORD   dfPoints;
2888     WORD   dfVertRes;
2889     WORD   dfHorizRes;
2890     WORD   dfAscent;
2891     WORD   dfInternalLeading;
2892     WORD   dfExternalLeading;
2893     BYTE   dfItalic;
2894     BYTE   dfUnderline;
2895     BYTE   dfStrikeOut;
2896     WORD   dfWeight;
2897     BYTE   dfCharSet;
2898     WORD   dfPixWidth;
2899     WORD   dfPixHeight;
2900     BYTE   dfPitchAndFamily;
2901     WORD   dfAvgWidth;
2902     WORD   dfMaxWidth;
2903     BYTE   dfFirstChar;
2904     BYTE   dfLastChar;
2905     BYTE   dfDefaultChar;
2906     BYTE   dfBreakChar;
2907     WORD   dfWidthBytes;
2908     DWORD  dfDevice;
2909     DWORD  dfFace;
2910     DWORD  dfReserved;
2911     CHAR   szFaceName[LF_FACESIZE];
2912 };
2913
2914 #include <poppack.h>
2915
2916 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
2917                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype);
2918
2919 static BOOL get_fontdir( const char *unix_name, struct fontdir *fd )
2920 {
2921     FT_Face ft_face = new_ft_face( unix_name, NULL, 0, 0, FALSE );
2922     Face *face;
2923     Family *family;
2924     WCHAR *name, *english_name;
2925     ENUMLOGFONTEXW elf;
2926     NEWTEXTMETRICEXW ntm;
2927     DWORD type;
2928
2929     if (!ft_face) return FALSE;
2930     face = create_face( ft_face, 0, unix_name, NULL, 0, 0, FALSE );
2931     get_family_names( ft_face, &name, &english_name, FALSE );
2932     family = create_family( name, english_name );
2933     insert_face_in_family_list( face, family );
2934     pFT_Done_Face( ft_face );
2935
2936     GetEnumStructs( face, &elf, &ntm, &type );
2937     free_family( family );
2938
2939     if ((type & TRUETYPE_FONTTYPE) == 0) return FALSE;
2940
2941     memset( fd, 0, sizeof(*fd) );
2942
2943     fd->num_of_resources  = 1;
2944     fd->res_id            = 0;
2945     fd->dfVersion         = 0x200;
2946     fd->dfSize            = sizeof(*fd);
2947     strcpy( fd->dfCopyright, "Wine fontdir" );
2948     fd->dfType            = 0x4003;  /* 0x0080 set if private */
2949     fd->dfPoints          = ntm.ntmTm.ntmSizeEM;
2950     fd->dfVertRes         = 72;
2951     fd->dfHorizRes        = 72;
2952     fd->dfAscent          = ntm.ntmTm.tmAscent;
2953     fd->dfInternalLeading = ntm.ntmTm.tmInternalLeading;
2954     fd->dfExternalLeading = ntm.ntmTm.tmExternalLeading;
2955     fd->dfItalic          = ntm.ntmTm.tmItalic;
2956     fd->dfUnderline       = ntm.ntmTm.tmUnderlined;
2957     fd->dfStrikeOut       = ntm.ntmTm.tmStruckOut;
2958     fd->dfWeight          = ntm.ntmTm.tmWeight;
2959     fd->dfCharSet         = ntm.ntmTm.tmCharSet;
2960     fd->dfPixWidth        = 0;
2961     fd->dfPixHeight       = ntm.ntmTm.tmHeight;
2962     fd->dfPitchAndFamily  = ntm.ntmTm.tmPitchAndFamily;
2963     fd->dfAvgWidth        = ntm.ntmTm.tmAveCharWidth;
2964     fd->dfMaxWidth        = ntm.ntmTm.tmMaxCharWidth;
2965     fd->dfFirstChar       = ntm.ntmTm.tmFirstChar;
2966     fd->dfLastChar        = ntm.ntmTm.tmLastChar;
2967     fd->dfDefaultChar     = ntm.ntmTm.tmDefaultChar;
2968     fd->dfBreakChar       = ntm.ntmTm.tmBreakChar;
2969     fd->dfWidthBytes      = 0;
2970     fd->dfDevice          = 0;
2971     fd->dfFace            = FIELD_OFFSET( struct fontdir, szFaceName );
2972     fd->dfReserved        = 0;
2973     WideCharToMultiByte( CP_ACP, 0, elf.elfLogFont.lfFaceName, -1, fd->szFaceName, LF_FACESIZE, NULL, NULL );
2974
2975     return TRUE;
2976 }
2977
2978 #define NE_FFLAGS_LIBMODULE     0x8000
2979 #define NE_OSFLAGS_WINDOWS      0x02
2980
2981 static const char dos_string[0x40] = "This is a TrueType resource file";
2982 static const char FONTRES[] = {'F','O','N','T','R','E','S',':'};
2983
2984 #include <pshpack2.h>
2985
2986 struct ne_typeinfo
2987 {
2988     WORD type_id;
2989     WORD count;
2990     DWORD res;
2991 };
2992
2993 struct ne_nameinfo
2994 {
2995     WORD off;
2996     WORD len;
2997     WORD flags;
2998     WORD id;
2999     DWORD res;
3000 };
3001
3002 struct rsrc_tab
3003 {
3004     WORD align;
3005     struct ne_typeinfo fontdir_type;
3006     struct ne_nameinfo fontdir_name;
3007     struct ne_typeinfo scalable_type;
3008     struct ne_nameinfo scalable_name;
3009     WORD end_of_rsrc;
3010     BYTE fontdir_res_name[8];
3011 };
3012
3013 #include <poppack.h>
3014
3015 static BOOL create_fot( const WCHAR *resource, const WCHAR *font_file, const struct fontdir *fontdir )
3016 {
3017     BOOL ret = FALSE;
3018     HANDLE file;
3019     DWORD size, written;
3020     BYTE *ptr, *start;
3021     BYTE import_name_len, res_name_len, non_res_name_len, font_file_len;
3022     char *font_fileA, *last_part, *ext;
3023     IMAGE_DOS_HEADER dos;
3024     IMAGE_OS2_HEADER ne =
3025     {
3026         IMAGE_OS2_SIGNATURE, 5, 1, 0, 0, 0, NE_FFLAGS_LIBMODULE, 0,
3027         0, 0, 0, 0, 0, 0,
3028         0, sizeof(ne), sizeof(ne), 0, 0, 0, 0,
3029         0, 4, 2, NE_OSFLAGS_WINDOWS, 0, 0, 0, 0, 0x300
3030     };
3031     struct rsrc_tab rsrc_tab =
3032     {
3033         4,
3034         { 0x8007, 1, 0 },
3035         { 0, 0, 0x0c50, 0x2c, 0 },
3036         { 0x80cc, 1, 0 },
3037         { 0, 0, 0x0c50, 0x8001, 0 },
3038         0,
3039         { 7,'F','O','N','T','D','I','R'}
3040     };
3041
3042     memset( &dos, 0, sizeof(dos) );
3043     dos.e_magic = IMAGE_DOS_SIGNATURE;
3044     dos.e_lfanew = sizeof(dos) + sizeof(dos_string);
3045
3046     /* import name is last part\0, resident name is last part without extension
3047        non-resident name is "FONTRES:" + lfFaceName */
3048
3049     font_file_len = WideCharToMultiByte( CP_ACP, 0, font_file, -1, NULL, 0, NULL, NULL );
3050     font_fileA = HeapAlloc( GetProcessHeap(), 0, font_file_len );
3051     WideCharToMultiByte( CP_ACP, 0, font_file, -1, font_fileA, font_file_len, NULL, NULL );
3052
3053     last_part = strrchr( font_fileA, '\\' );
3054     if (last_part) last_part++;
3055     else last_part = font_fileA;
3056     import_name_len = strlen( last_part ) + 1;
3057
3058     ext = strchr( last_part, '.' );
3059     if (ext) res_name_len = ext - last_part;
3060     else res_name_len = import_name_len - 1;
3061
3062     non_res_name_len = sizeof( FONTRES ) + strlen( fontdir->szFaceName );
3063
3064     ne.ne_cbnrestab = 1 + non_res_name_len + 2 + 1; /* len + string + (WORD) ord_num + 1 byte eod */
3065     ne.ne_restab = ne.ne_rsrctab + sizeof(rsrc_tab);
3066     ne.ne_modtab = ne.ne_imptab = ne.ne_restab + 1 + res_name_len + 2 + 3; /* len + string + (WORD) ord_num + 3 bytes eod */
3067     ne.ne_enttab = ne.ne_imptab + 1 + import_name_len; /* len + string */
3068     ne.ne_cbenttab = 2;
3069     ne.ne_nrestab = ne.ne_enttab + ne.ne_cbenttab + 2 + dos.e_lfanew; /* there are 2 bytes of 0 after entry tab */
3070
3071     rsrc_tab.scalable_name.off = (ne.ne_nrestab + ne.ne_cbnrestab + 0xf) >> 4;
3072     rsrc_tab.scalable_name.len = (font_file_len + 0xf) >> 4;
3073     rsrc_tab.fontdir_name.off  = rsrc_tab.scalable_name.off + rsrc_tab.scalable_name.len;
3074     rsrc_tab.fontdir_name.len  = (fontdir->dfSize + 0xf) >> 4;
3075
3076     size = (rsrc_tab.fontdir_name.off + rsrc_tab.fontdir_name.len) << 4;
3077     start = ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
3078
3079     if (!ptr)
3080     {
3081         HeapFree( GetProcessHeap(), 0, font_fileA );
3082         return FALSE;
3083     }
3084
3085     memcpy( ptr, &dos, sizeof(dos) );
3086     memcpy( ptr + sizeof(dos), dos_string, sizeof(dos_string) );
3087     memcpy( ptr + dos.e_lfanew, &ne, sizeof(ne) );
3088
3089     ptr = start + dos.e_lfanew + ne.ne_rsrctab;
3090     memcpy( ptr, &rsrc_tab, sizeof(rsrc_tab) );
3091
3092     ptr = start + dos.e_lfanew + ne.ne_restab;
3093     *ptr++ = res_name_len;
3094     memcpy( ptr, last_part, res_name_len );
3095
3096     ptr = start + dos.e_lfanew + ne.ne_imptab;
3097     *ptr++ = import_name_len;
3098     memcpy( ptr, last_part, import_name_len );
3099
3100     ptr = start + ne.ne_nrestab;
3101     *ptr++ = non_res_name_len;
3102     memcpy( ptr, FONTRES, sizeof(FONTRES) );
3103     memcpy( ptr + sizeof(FONTRES), fontdir->szFaceName, strlen( fontdir->szFaceName ) );
3104
3105     ptr = start + (rsrc_tab.scalable_name.off << 4);
3106     memcpy( ptr, font_fileA, font_file_len );
3107
3108     ptr = start + (rsrc_tab.fontdir_name.off << 4);
3109     memcpy( ptr, fontdir, fontdir->dfSize );
3110
3111     file = CreateFileW( resource, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
3112     if (file != INVALID_HANDLE_VALUE)
3113     {
3114         if (WriteFile( file, start, size, &written, NULL ) && written == size)
3115             ret = TRUE;
3116         CloseHandle( file );
3117     }
3118
3119     HeapFree( GetProcessHeap(), 0, start );
3120     HeapFree( GetProcessHeap(), 0, font_fileA );
3121
3122     return ret;
3123 }
3124
3125 /*************************************************************
3126  *    WineEngCreateScalableFontResource
3127  *
3128  */
3129 BOOL WineEngCreateScalableFontResource( DWORD hidden, LPCWSTR resource,
3130                                         LPCWSTR font_file, LPCWSTR font_path )
3131 {
3132     char *unix_name = get_ttf_file_name( font_file, font_path );
3133     struct fontdir fontdir;
3134     BOOL ret = FALSE;
3135
3136     if (!unix_name || !get_fontdir( unix_name, &fontdir ))
3137         SetLastError( ERROR_INVALID_PARAMETER );
3138     else
3139     {
3140         if (hidden) fontdir.dfType |= 0x80;
3141         ret = create_fot( resource, font_file, &fontdir );
3142     }
3143
3144     HeapFree( GetProcessHeap(), 0, unix_name );
3145     return ret;
3146 }
3147
3148 static const struct nls_update_font_list
3149 {
3150     UINT ansi_cp, oem_cp;
3151     const char *oem, *fixed, *system;
3152     const char *courier, *serif, *small, *sserif;
3153     /* these are for font substitutes */
3154     const char *shelldlg, *tmsrmn;
3155     const char *fixed_0, *system_0, *courier_0, *serif_0, *small_0, *sserif_0,
3156                *helv_0, *tmsrmn_0;
3157     const struct subst
3158     {
3159         const char *from, *to;
3160     } arial_0, courier_new_0, times_new_roman_0;
3161 } nls_update_font_list[] =
3162 {
3163     /* Latin 1 (United States) */
3164     { 1252, 437, "vgaoem.fon", "vgafix.fon", "vgasys.fon",
3165       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
3166       "Tahoma","Times New Roman",
3167       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3168       { 0 }, { 0 }, { 0 }
3169     },
3170     /* Latin 1 (Multilingual) */
3171     { 1252, 850, "vga850.fon", "vgafix.fon", "vgasys.fon",
3172       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
3173       "Tahoma","Times New Roman",  /* FIXME unverified */
3174       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3175       { 0 }, { 0 }, { 0 }
3176     },
3177     /* Eastern Europe */
3178     { 1250, 852, "vga852.fon", "vgafixe.fon", "vgasyse.fon",
3179       "couree.fon", "serifee.fon", "smallee.fon", "sserifee.fon",
3180       "Tahoma","Times New Roman", /* FIXME unverified */
3181       "Fixedsys,238", "System,238",
3182       "Courier New,238", "MS Serif,238", "Small Fonts,238",
3183       "MS Sans Serif,238", "MS Sans Serif,238", "MS Serif,238",
3184       { "Arial CE,0", "Arial,238" },
3185       { "Courier New CE,0", "Courier New,238" },
3186       { "Times New Roman CE,0", "Times New Roman,238" }
3187     },
3188     /* Cyrillic */
3189     { 1251, 866, "vga866.fon", "vgafixr.fon", "vgasysr.fon",
3190       "courer.fon", "serifer.fon", "smaller.fon", "sserifer.fon",
3191       "Tahoma","Times New Roman", /* FIXME unverified */
3192       "Fixedsys,204", "System,204",
3193       "Courier New,204", "MS Serif,204", "Small Fonts,204",
3194       "MS Sans Serif,204", "MS Sans Serif,204", "MS Serif,204",
3195       { "Arial Cyr,0", "Arial,204" },
3196       { "Courier New Cyr,0", "Courier New,204" },
3197       { "Times New Roman Cyr,0", "Times New Roman,204" }
3198     },
3199     /* Greek */
3200     { 1253, 737, "vga869.fon", "vgafixg.fon", "vgasysg.fon",
3201       "coureg.fon", "serifeg.fon", "smalleg.fon", "sserifeg.fon",
3202       "Tahoma","Times New Roman", /* FIXME unverified */
3203       "Fixedsys,161", "System,161",
3204       "Courier New,161", "MS Serif,161", "Small Fonts,161",
3205       "MS Sans Serif,161", "MS Sans Serif,161", "MS Serif,161",
3206       { "Arial Greek,0", "Arial,161" },
3207       { "Courier New Greek,0", "Courier New,161" },
3208       { "Times New Roman Greek,0", "Times New Roman,161" }
3209     },
3210     /* Turkish */
3211     { 1254, 857, "vga857.fon", "vgafixt.fon", "vgasyst.fon",
3212       "couret.fon", "serifet.fon", "smallet.fon", "sserifet.fon",
3213       "Tahoma","Times New Roman", /* FIXME unverified */
3214       "Fixedsys,162", "System,162",
3215       "Courier New,162", "MS Serif,162", "Small Fonts,162",
3216       "MS Sans Serif,162", "MS Sans Serif,162", "MS Serif,162",
3217       { "Arial Tur,0", "Arial,162" },
3218       { "Courier New Tur,0", "Courier New,162" },
3219       { "Times New Roman Tur,0", "Times New Roman,162" }
3220     },
3221     /* Hebrew */
3222     { 1255, 862, "vgaoem.fon", "vgaf1255.fon", "vgas1255.fon",
3223       "coue1255.fon", "sere1255.fon", "smae1255.fon", "ssee1255.fon",
3224       "Tahoma","Times New Roman", /* FIXME unverified */
3225       "Fixedsys,177", "System,177",
3226       "Courier New,177", "MS Serif,177", "Small Fonts,177",
3227       "MS Sans Serif,177", "MS Sans Serif,177", "MS Serif,177",
3228       { 0 }, { 0 }, { 0 }
3229     },
3230     /* Arabic */
3231     { 1256, 720, "vgaoem.fon", "vgaf1256.fon", "vgas1256.fon",
3232       "coue1256.fon", "sere1256.fon", "smae1256.fon", "ssee1256.fon",
3233       "Tahoma","Times New Roman", /* FIXME unverified */
3234       "Fixedsys,178", "System,178",
3235       "Courier New,178", "MS Serif,178", "Small Fonts,178",
3236       "MS Sans Serif,178", "MS Sans Serif,178", "MS Serif,178",
3237       { 0 }, { 0 }, { 0 }
3238     },
3239     /* Baltic */
3240     { 1257, 775, "vga775.fon", "vgaf1257.fon", "vgas1257.fon",
3241       "coue1257.fon", "sere1257.fon", "smae1257.fon", "ssee1257.fon",
3242       "Tahoma","Times New Roman", /* FIXME unverified */
3243       "Fixedsys,186", "System,186",
3244       "Courier New,186", "MS Serif,186", "Small Fonts,186",
3245       "MS Sans Serif,186", "MS Sans Serif,186", "MS Serif,186",
3246       { "Arial Baltic,0", "Arial,186" },
3247       { "Courier New Baltic,0", "Courier New,186" },
3248       { "Times New Roman Baltic,0", "Times New Roman,186" }
3249     },
3250     /* Vietnamese */
3251     { 1258, 1258, "vga850.fon", "vgafix.fon", "vgasys.fon",
3252       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
3253       "Tahoma","Times New Roman", /* FIXME unverified */
3254       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3255       { 0 }, { 0 }, { 0 }
3256     },
3257     /* Thai */
3258     { 874, 874, "vga850.fon", "vgaf874.fon", "vgas874.fon",
3259       "coure.fon", "serife.fon", "smalle.fon", "ssee874.fon",
3260       "Tahoma","Times New Roman", /* FIXME unverified */
3261       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3262       { 0 }, { 0 }, { 0 }
3263     },
3264     /* Japanese */
3265     { 932, 932, "vga932.fon", "jvgafix.fon", "jvgasys.fon",
3266       "coure.fon", "serife.fon", "jsmalle.fon", "sserife.fon",
3267       "MS UI Gothic","MS Serif",
3268       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3269       { 0 }, { 0 }, { 0 }
3270     },
3271     /* Chinese Simplified */
3272     { 936, 936, "vga936.fon", "svgafix.fon", "svgasys.fon",
3273       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
3274       "SimSun", "NSimSun",
3275       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3276       { 0 }, { 0 }, { 0 }
3277     },
3278     /* Korean */
3279     { 949, 949, "vga949.fon", "hvgafix.fon", "hvgasys.fon",
3280       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
3281       "Gulim",  "Batang",
3282       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3283       { 0 }, { 0 }, { 0 }
3284     },
3285     /* Chinese Traditional */
3286     { 950, 950, "vga950.fon", "cvgafix.fon", "cvgasys.fon",
3287       "coure.fon", "serife.fon", "smalle.fon", "sserife.fon",
3288       "PMingLiU",  "MingLiU",
3289       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3290       { 0 }, { 0 }, { 0 }
3291     }
3292 };
3293
3294 static inline BOOL is_dbcs_ansi_cp(UINT ansi_cp)
3295 {
3296     return ( ansi_cp == 932       /* CP932 for Japanese */
3297             || ansi_cp == 936     /* CP936 for Chinese Simplified */
3298             || ansi_cp == 949     /* CP949 for Korean */
3299             || ansi_cp == 950 );  /* CP950 for Chinese Traditional */
3300 }
3301
3302 static inline HKEY create_fonts_NT_registry_key(void)
3303 {
3304     HKEY hkey = 0;
3305
3306     RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key, 0, NULL,
3307                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
3308     return hkey;
3309 }
3310
3311 static inline HKEY create_fonts_9x_registry_key(void)
3312 {
3313     HKEY hkey = 0;
3314
3315     RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key, 0, NULL,
3316                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
3317     return hkey;
3318 }
3319
3320 static inline HKEY create_config_fonts_registry_key(void)
3321 {
3322     HKEY hkey = 0;
3323
3324     RegCreateKeyExW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, 0, NULL,
3325                     0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
3326     return hkey;
3327 }
3328
3329 static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl)
3330 {
3331     RegSetValueExA(hkey, "Courier", 0, REG_SZ, (const BYTE *)fl->courier, strlen(fl->courier)+1);
3332     RegSetValueExA(hkey, "MS Serif", 0, REG_SZ, (const BYTE *)fl->serif, strlen(fl->serif)+1);
3333     RegSetValueExA(hkey, "MS Sans Serif", 0, REG_SZ, (const BYTE *)fl->sserif, strlen(fl->sserif)+1);
3334     RegSetValueExA(hkey, "Small Fonts", 0, REG_SZ, (const BYTE *)fl->small, strlen(fl->small)+1);
3335 }
3336
3337 static void set_value_key(HKEY hkey, const char *name, const char *value)
3338 {
3339     if (value)
3340         RegSetValueExA(hkey, name, 0, REG_SZ, (const BYTE *)value, strlen(value) + 1);
3341     else if (name)
3342         RegDeleteValueA(hkey, name);
3343 }
3344
3345 static void update_font_info(void)
3346 {
3347     char buf[40], cpbuf[40];
3348     DWORD len, type;
3349     HKEY hkey = 0;
3350     UINT i, ansi_cp = 0, oem_cp = 0;
3351     BOOL done = FALSE;
3352
3353     if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL) != ERROR_SUCCESS)
3354         return;
3355
3356     GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
3357                    (WCHAR *)&ansi_cp, sizeof(ansi_cp)/sizeof(WCHAR));
3358     GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTCODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
3359                    (WCHAR *)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR));
3360     sprintf( cpbuf, "%u,%u", ansi_cp, oem_cp );
3361
3362     /* Setup Default_Fallback usage for DBCS ANSI codepages */
3363     if (is_dbcs_ansi_cp(ansi_cp))
3364         use_default_fallback = TRUE;
3365
3366     len = sizeof(buf);
3367     if (RegQueryValueExA(hkey, "Codepages", 0, &type, (BYTE *)buf, &len) == ERROR_SUCCESS && type == REG_SZ)
3368     {
3369         if (!strcmp( buf, cpbuf ))  /* already set correctly */
3370         {
3371             RegCloseKey(hkey);
3372             return;
3373         }
3374         TRACE("updating registry, codepages changed %s -> %u,%u\n", buf, ansi_cp, oem_cp);
3375     }
3376     else TRACE("updating registry, codepages changed none -> %u,%u\n", ansi_cp, oem_cp);
3377
3378     RegSetValueExA(hkey, "Codepages", 0, REG_SZ, (const BYTE *)cpbuf, strlen(cpbuf)+1);
3379     RegCloseKey(hkey);
3380
3381     for (i = 0; i < sizeof(nls_update_font_list)/sizeof(nls_update_font_list[0]); i++)
3382     {
3383         HKEY hkey;
3384
3385         if (nls_update_font_list[i].ansi_cp == ansi_cp &&
3386             nls_update_font_list[i].oem_cp == oem_cp)
3387         {
3388             hkey = create_config_fonts_registry_key();
3389             RegSetValueExA(hkey, "OEMFONT.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].oem, strlen(nls_update_font_list[i].oem)+1);
3390             RegSetValueExA(hkey, "FIXEDFON.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].fixed, strlen(nls_update_font_list[i].fixed)+1);
3391             RegSetValueExA(hkey, "FONTS.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].system, strlen(nls_update_font_list[i].system)+1);
3392             RegCloseKey(hkey);
3393
3394             hkey = create_fonts_NT_registry_key();
3395             add_font_list(hkey, &nls_update_font_list[i]);
3396             RegCloseKey(hkey);
3397
3398             hkey = create_fonts_9x_registry_key();
3399             add_font_list(hkey, &nls_update_font_list[i]);
3400             RegCloseKey(hkey);
3401
3402             if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
3403             {
3404                 RegSetValueExA(hkey, "MS Shell Dlg", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].shelldlg,
3405                                strlen(nls_update_font_list[i].shelldlg)+1);
3406                 RegSetValueExA(hkey, "Tms Rmn", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].tmsrmn,
3407                                strlen(nls_update_font_list[i].tmsrmn)+1);
3408
3409                 set_value_key(hkey, "Fixedsys,0", nls_update_font_list[i].fixed_0);
3410                 set_value_key(hkey, "System,0", nls_update_font_list[i].system_0);
3411                 set_value_key(hkey, "Courier,0", nls_update_font_list[i].courier_0);
3412                 set_value_key(hkey, "MS Serif,0", nls_update_font_list[i].serif_0);
3413                 set_value_key(hkey, "Small Fonts,0", nls_update_font_list[i].small_0);
3414                 set_value_key(hkey, "MS Sans Serif,0", nls_update_font_list[i].sserif_0);
3415                 set_value_key(hkey, "Helv,0", nls_update_font_list[i].helv_0);
3416                 set_value_key(hkey, "Tms Rmn,0", nls_update_font_list[i].tmsrmn_0);
3417
3418                 set_value_key(hkey, nls_update_font_list[i].arial_0.from, nls_update_font_list[i].arial_0.to);
3419                 set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, nls_update_font_list[i].courier_new_0.to);
3420                 set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, nls_update_font_list[i].times_new_roman_0.to);
3421
3422                 RegCloseKey(hkey);
3423             }
3424             done = TRUE;
3425         }
3426         else
3427         {
3428             /* Delete the FontSubstitutes from other locales */
3429             if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
3430             {
3431                 set_value_key(hkey, nls_update_font_list[i].arial_0.from, NULL);
3432                 set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, NULL);
3433                 set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, NULL);
3434                 RegCloseKey(hkey);
3435             }
3436         }
3437     }
3438     if (!done)
3439         FIXME("there is no font defaults for codepages %u,%u\n", ansi_cp, oem_cp);
3440 }
3441
3442 static BOOL init_freetype(void)
3443 {
3444     ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0);
3445     if(!ft_handle) {
3446         WINE_MESSAGE(
3447       "Wine cannot find the FreeType font library.  To enable Wine to\n"
3448       "use TrueType fonts please install a version of FreeType greater than\n"
3449       "or equal to 2.0.5.\n"
3450       "http://www.freetype.org\n");
3451         return FALSE;
3452     }
3453
3454 #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;}
3455
3456     LOAD_FUNCPTR(FT_Done_Face)
3457     LOAD_FUNCPTR(FT_Get_Char_Index)
3458     LOAD_FUNCPTR(FT_Get_First_Char)
3459     LOAD_FUNCPTR(FT_Get_Module)
3460     LOAD_FUNCPTR(FT_Get_Next_Char)
3461     LOAD_FUNCPTR(FT_Get_Sfnt_Name)
3462     LOAD_FUNCPTR(FT_Get_Sfnt_Name_Count)
3463     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
3464     LOAD_FUNCPTR(FT_Get_WinFNT_Header)
3465     LOAD_FUNCPTR(FT_Init_FreeType)
3466     LOAD_FUNCPTR(FT_Library_Version)
3467     LOAD_FUNCPTR(FT_Load_Glyph)
3468     LOAD_FUNCPTR(FT_Load_Sfnt_Table)
3469     LOAD_FUNCPTR(FT_Matrix_Multiply)
3470 #ifndef FT_MULFIX_INLINED
3471     LOAD_FUNCPTR(FT_MulFix)
3472 #endif
3473     LOAD_FUNCPTR(FT_New_Face)
3474     LOAD_FUNCPTR(FT_New_Memory_Face)
3475     LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
3476     LOAD_FUNCPTR(FT_Outline_Transform)
3477     LOAD_FUNCPTR(FT_Outline_Translate)
3478     LOAD_FUNCPTR(FT_Render_Glyph)
3479     LOAD_FUNCPTR(FT_Select_Charmap)
3480     LOAD_FUNCPTR(FT_Set_Charmap)
3481     LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
3482     LOAD_FUNCPTR(FT_Vector_Transform)
3483     LOAD_FUNCPTR(FT_Vector_Unit)
3484 #undef LOAD_FUNCPTR
3485     /* Don't warn if these ones are missing */
3486     pFT_Get_TrueType_Engine_Type = wine_dlsym(ft_handle, "FT_Get_TrueType_Engine_Type", NULL, 0);
3487 #ifdef HAVE_FREETYPE_FTLCDFIL_H
3488     pFT_Library_SetLcdFilter = wine_dlsym(ft_handle, "FT_Library_SetLcdFilter", NULL, 0);
3489 #endif
3490
3491     if(pFT_Init_FreeType(&library) != 0) {
3492         ERR("Can't init FreeType library\n");
3493         wine_dlclose(ft_handle, NULL, 0);
3494         ft_handle = NULL;
3495         return FALSE;
3496     }
3497     pFT_Library_Version(library,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
3498
3499     TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
3500     FT_SimpleVersion = ((FT_Version.major << 16) & 0xff0000) |
3501                        ((FT_Version.minor <<  8) & 0x00ff00) |
3502                        ((FT_Version.patch      ) & 0x0000ff);
3503
3504     font_driver = &freetype_funcs;
3505     return TRUE;
3506
3507 sym_not_found:
3508     WINE_MESSAGE(
3509       "Wine cannot find certain functions that it needs inside the FreeType\n"
3510       "font library.  To enable Wine to use TrueType fonts please upgrade\n"
3511       "FreeType to at least version 2.1.4.\n"
3512       "http://www.freetype.org\n");
3513     wine_dlclose(ft_handle, NULL, 0);
3514     ft_handle = NULL;
3515     return FALSE;
3516 }
3517
3518 static void init_font_list(void)
3519 {
3520     static const WCHAR dot_fonW[] = {'.','f','o','n','\0'};
3521     static const WCHAR pathW[] = {'P','a','t','h',0};
3522     HKEY hkey;
3523     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
3524     WCHAR windowsdir[MAX_PATH];
3525     char *unixname;
3526     const char *data_dir;
3527
3528     delete_external_font_keys();
3529
3530     /* load the system bitmap fonts */
3531     load_system_fonts();
3532
3533     /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
3534     GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
3535     strcatW(windowsdir, fontsW);
3536     if((unixname = wine_get_unix_file_name(windowsdir)))
3537     {
3538         ReadFontDir(unixname, FALSE);
3539         HeapFree(GetProcessHeap(), 0, unixname);
3540     }
3541
3542     /* load the system truetype fonts */
3543     data_dir = wine_get_data_dir();
3544     if (!data_dir) data_dir = wine_get_build_dir();
3545     if (data_dir && (unixname = HeapAlloc(GetProcessHeap(), 0, strlen(data_dir) + sizeof("/fonts/"))))
3546     {
3547         strcpy(unixname, data_dir);
3548         strcat(unixname, "/fonts/");
3549         ReadFontDir(unixname, TRUE);
3550         HeapFree(GetProcessHeap(), 0, unixname);
3551     }
3552
3553     /* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
3554        for any fonts not installed in %WINDOWSDIR%\Fonts.  They will have their
3555        full path as the entry.  Also look for any .fon fonts, since ReadFontDir
3556        will skip these. */
3557     if(RegOpenKeyW(HKEY_LOCAL_MACHINE,
3558                    is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
3559                    &hkey) == ERROR_SUCCESS)
3560     {
3561         LPWSTR data, valueW;
3562         RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3563                          &valuelen, &datalen, NULL, NULL);
3564
3565         valuelen++; /* returned value doesn't include room for '\0' */
3566         valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
3567         data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
3568         if (valueW && data)
3569         {
3570             dlen = datalen * sizeof(WCHAR);
3571             vlen = valuelen;
3572             while(RegEnumValueW(hkey, i++, valueW, &vlen, NULL, &type, (LPBYTE)data,
3573                                 &dlen) == ERROR_SUCCESS)
3574             {
3575                 if(data[0] && (data[1] == ':'))
3576                 {
3577                     if((unixname = wine_get_unix_file_name(data)))
3578                     {
3579                         AddFontToList(unixname, NULL, 0, ADDFONT_FORCE_BITMAP | ADDFONT_ADD_TO_CACHE);
3580                         HeapFree(GetProcessHeap(), 0, unixname);
3581                     }
3582                 }
3583                 else if(dlen / 2 >= 6 && !strcmpiW(data + dlen / 2 - 5, dot_fonW))
3584                 {
3585                     WCHAR pathW[MAX_PATH];
3586                     static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
3587                     BOOL added = FALSE;
3588
3589                     sprintfW(pathW, fmtW, windowsdir, data);
3590                     if((unixname = wine_get_unix_file_name(pathW)))
3591                     {
3592                         added = AddFontToList(unixname, NULL, 0, ADDFONT_FORCE_BITMAP | ADDFONT_ADD_TO_CACHE);
3593                         HeapFree(GetProcessHeap(), 0, unixname);
3594                     }
3595                     if (!added)
3596                         load_font_from_data_dir(data);
3597                 }
3598                 /* reset dlen and vlen */
3599                 dlen = datalen;
3600                 vlen = valuelen;
3601             }
3602         }
3603         HeapFree(GetProcessHeap(), 0, data);
3604         HeapFree(GetProcessHeap(), 0, valueW);
3605         RegCloseKey(hkey);
3606     }
3607
3608 #ifdef SONAME_LIBFONTCONFIG
3609     load_fontconfig_fonts();
3610 #elif defined(HAVE_CARBON_CARBON_H)
3611     load_mac_fonts();
3612 #endif
3613
3614     /* then look in any directories that we've specified in the config file */
3615     /* @@ Wine registry key: HKCU\Software\Wine\Fonts */
3616     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", &hkey) == ERROR_SUCCESS)
3617     {
3618         DWORD len;
3619         LPWSTR valueW;
3620         LPSTR valueA, ptr;
3621
3622         if (RegQueryValueExW( hkey, pathW, NULL, NULL, NULL, &len ) == ERROR_SUCCESS)
3623         {
3624             len += sizeof(WCHAR);
3625             valueW = HeapAlloc( GetProcessHeap(), 0, len );
3626             if (RegQueryValueExW( hkey, pathW, NULL, NULL, (LPBYTE)valueW, &len ) == ERROR_SUCCESS)
3627             {
3628                 len = WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, NULL, 0, NULL, NULL );
3629                 valueA = HeapAlloc( GetProcessHeap(), 0, len );
3630                 WideCharToMultiByte( CP_UNIXCP, 0, valueW, -1, valueA, len, NULL, NULL );
3631                 TRACE( "got font path %s\n", debugstr_a(valueA) );
3632                 ptr = valueA;
3633                 while (ptr)
3634                 {
3635                     const char* home;
3636                     LPSTR next = strchr( ptr, ':' );
3637                     if (next) *next++ = 0;
3638                     if (ptr[0] == '~' && ptr[1] == '/' && (home = getenv( "HOME" )) &&
3639                         (unixname = HeapAlloc( GetProcessHeap(), 0, strlen(ptr) + strlen(home) )))
3640                     {
3641                         strcpy( unixname, home );
3642                         strcat( unixname, ptr + 1 );
3643                         ReadFontDir( unixname, TRUE );
3644                         HeapFree( GetProcessHeap(), 0, unixname );
3645                     }
3646                     else
3647                         ReadFontDir( ptr, TRUE );
3648                     ptr = next;
3649                 }
3650                 HeapFree( GetProcessHeap(), 0, valueA );
3651             }
3652             HeapFree( GetProcessHeap(), 0, valueW );
3653         }
3654         RegCloseKey(hkey);
3655     }
3656 }
3657
3658 static BOOL move_to_front(const WCHAR *name)
3659 {
3660     Family *family, *cursor2;
3661     LIST_FOR_EACH_ENTRY_SAFE(family, cursor2, &font_list, Family, entry)
3662     {
3663         if(!strcmpiW(family->FamilyName, name))
3664         {
3665             list_remove(&family->entry);
3666             list_add_head(&font_list, &family->entry);
3667             return TRUE;
3668         }
3669     }
3670     return FALSE;
3671 }
3672
3673 static BOOL set_default(const WCHAR **name_list)
3674 {
3675     while (*name_list)
3676     {
3677         if (move_to_front(*name_list)) return TRUE;
3678         name_list++;
3679     }
3680
3681     return FALSE;
3682 }
3683
3684 static void reorder_font_list(void)
3685 {
3686     set_default( default_serif_list );
3687     set_default( default_fixed_list );
3688     set_default( default_sans_list );
3689 }
3690
3691 /*************************************************************
3692  *    WineEngInit
3693  *
3694  * Initialize FreeType library and create a list of available faces
3695  */
3696 BOOL WineEngInit(void)
3697 {
3698     HKEY hkey_font_cache;
3699     DWORD disposition;
3700     HANDLE font_mutex;
3701
3702     /* update locale dependent font info in registry */
3703     update_font_info();
3704
3705     if(!init_freetype()) return FALSE;
3706
3707     if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL)
3708     {
3709         ERR("Failed to create font mutex\n");
3710         return FALSE;
3711     }
3712     WaitForSingleObject(font_mutex, INFINITE);
3713
3714     create_font_cache_key(&hkey_font_cache, &disposition);
3715
3716     if(disposition == REG_CREATED_NEW_KEY)
3717         init_font_list();
3718     else
3719         load_font_list_from_cache(hkey_font_cache);
3720
3721     RegCloseKey(hkey_font_cache);
3722
3723     reorder_font_list();
3724
3725     DumpFontList();
3726     LoadSubstList();
3727     DumpSubstList();
3728     LoadReplaceList();
3729
3730     if(disposition == REG_CREATED_NEW_KEY)
3731         update_reg_entries();
3732
3733     init_system_links();
3734     
3735     ReleaseMutex(font_mutex);
3736     return TRUE;
3737 }
3738
3739
3740 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
3741 {
3742     TT_OS2 *pOS2;
3743     TT_HoriHeader *pHori;
3744
3745     LONG ppem;
3746
3747     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
3748     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
3749
3750     if(height == 0) height = 16;
3751
3752     /* Calc. height of EM square:
3753      *
3754      * For +ve lfHeight we have
3755      * lfHeight = (winAscent + winDescent) * ppem / units_per_em
3756      * Re-arranging gives:
3757      * ppem = units_per_em * lfheight / (winAscent + winDescent)
3758      *
3759      * For -ve lfHeight we have
3760      * |lfHeight| = ppem
3761      * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
3762      * with il = winAscent + winDescent - units_per_em]
3763      *
3764      */
3765
3766     if(height > 0) {
3767         if(pOS2->usWinAscent + pOS2->usWinDescent == 0)
3768             ppem = MulDiv(ft_face->units_per_EM, height,
3769                           pHori->Ascender - pHori->Descender);
3770         else
3771             ppem = MulDiv(ft_face->units_per_EM, height,
3772                           pOS2->usWinAscent + pOS2->usWinDescent);
3773     }
3774     else
3775         ppem = -height;
3776
3777     return ppem;
3778 }
3779
3780 static struct font_mapping *map_font_file( const char *name )
3781 {
3782     struct font_mapping *mapping;
3783     struct stat st;
3784     int fd;
3785
3786     if ((fd = open( name, O_RDONLY )) == -1) return NULL;
3787     if (fstat( fd, &st ) == -1) goto error;
3788
3789     LIST_FOR_EACH_ENTRY( mapping, &mappings_list, struct font_mapping, entry )
3790     {
3791         if (mapping->dev == st.st_dev && mapping->ino == st.st_ino)
3792         {
3793             mapping->refcount++;
3794             close( fd );
3795             return mapping;
3796         }
3797     }
3798     if (!(mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(*mapping) )))
3799         goto error;
3800
3801     mapping->data = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
3802     close( fd );
3803
3804     if (mapping->data == MAP_FAILED)
3805     {
3806         HeapFree( GetProcessHeap(), 0, mapping );
3807         return NULL;
3808     }
3809     mapping->refcount = 1;
3810     mapping->dev = st.st_dev;
3811     mapping->ino = st.st_ino;
3812     mapping->size = st.st_size;
3813     list_add_tail( &mappings_list, &mapping->entry );
3814     return mapping;
3815
3816 error:
3817     close( fd );
3818     return NULL;
3819 }
3820
3821 static void unmap_font_file( struct font_mapping *mapping )
3822 {
3823     if (!--mapping->refcount)
3824     {
3825         list_remove( &mapping->entry );
3826         munmap( mapping->data, mapping->size );
3827         HeapFree( GetProcessHeap(), 0, mapping );
3828     }
3829 }
3830
3831 static LONG load_VDMX(GdiFont*, LONG);
3832
3833 static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height)
3834 {
3835     FT_Error err;
3836     FT_Face ft_face;
3837     void *data_ptr;
3838     DWORD data_size;
3839
3840     TRACE("%s/%p, %ld, %d x %d\n", debugstr_a(face->file), face->font_data_ptr, face->face_index, width, height);
3841
3842     if (face->file)
3843     {
3844         if (!(font->mapping = map_font_file( face->file )))
3845         {
3846             WARN("failed to map %s\n", debugstr_a(face->file));
3847             return 0;
3848         }
3849         data_ptr = font->mapping->data;
3850         data_size = font->mapping->size;
3851     }
3852     else
3853     {
3854         data_ptr = face->font_data_ptr;
3855         data_size = face->font_data_size;
3856     }
3857
3858     err = pFT_New_Memory_Face(library, data_ptr, data_size, face->face_index, &ft_face);
3859     if(err) {
3860         ERR("FT_New_Face rets %d\n", err);
3861         return 0;
3862     }
3863
3864     /* set it here, as load_VDMX needs it */
3865     font->ft_face = ft_face;
3866
3867     if(FT_IS_SCALABLE(ft_face)) {
3868         /* load the VDMX table if we have one */
3869         font->ppem = load_VDMX(font, height);
3870         if(font->ppem == 0)
3871             font->ppem = calc_ppem_for_height(ft_face, height);
3872         TRACE("height %d => ppem %d\n", height, font->ppem);
3873
3874         if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0)
3875             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", 0, font->ppem, err);
3876     } else {
3877         font->ppem = height;
3878         if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
3879             WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", width, height, err);
3880     }
3881     return ft_face;
3882 }
3883
3884
3885 static int get_nearest_charset(const WCHAR *family_name, Face *face, int *cp)
3886 {
3887   /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
3888      a single face with the requested charset.  The idea is to check if
3889      the selected font supports the current ANSI codepage, if it does
3890      return the corresponding charset, else return the first charset */
3891
3892     CHARSETINFO csi;
3893     int acp = GetACP(), i;
3894     DWORD fs0;
3895
3896     *cp = acp;
3897     if(TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE))
3898     {
3899         const SYSTEM_LINKS *font_link;
3900
3901         if (csi.fs.fsCsb[0] & face->fs.fsCsb[0])
3902             return csi.ciCharset;
3903
3904         font_link = find_font_link(family_name);
3905         if (font_link != NULL && csi.fs.fsCsb[0] & font_link->fs.fsCsb[0])
3906             return csi.ciCharset;
3907     }
3908
3909     for(i = 0; i < 32; i++) {
3910         fs0 = 1L << i;
3911         if(face->fs.fsCsb[0] & fs0) {
3912             if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG)) {
3913                 *cp = csi.ciACP;
3914                 return csi.ciCharset;
3915             }
3916             else
3917                 FIXME("TCI failing on %x\n", fs0);
3918         }
3919     }
3920
3921     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08x file = %s\n",
3922           face->fs.fsCsb[0], face->file);
3923     *cp = acp;
3924     return DEFAULT_CHARSET;
3925 }
3926
3927 static GdiFont *alloc_font(void)
3928 {
3929     GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
3930     ret->gmsize = 1;
3931     ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM*));
3932     ret->gm[0] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
3933     ret->potm = NULL;
3934     ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
3935     ret->total_kern_pairs = (DWORD)-1;
3936     ret->kern_pairs = NULL;
3937     list_init(&ret->hfontlist);
3938     list_init(&ret->child_fonts);
3939     return ret;
3940 }
3941
3942 static void free_font(GdiFont *font)
3943 {
3944     struct list *cursor, *cursor2;
3945     DWORD i;
3946
3947     LIST_FOR_EACH_SAFE(cursor, cursor2, &font->child_fonts)
3948     {
3949         CHILD_FONT *child = LIST_ENTRY(cursor, CHILD_FONT, entry);
3950         list_remove(cursor);
3951         if(child->font)
3952             free_font(child->font);
3953         HeapFree(GetProcessHeap(), 0, child);
3954     }
3955
3956     LIST_FOR_EACH_SAFE(cursor, cursor2, &font->hfontlist)
3957     {
3958         HFONTLIST *hfontlist = LIST_ENTRY(cursor, HFONTLIST, entry);
3959         DeleteObject(hfontlist->hfont);
3960         list_remove(&hfontlist->entry);
3961         HeapFree(GetProcessHeap(), 0, hfontlist);
3962     }
3963
3964     if (font->ft_face) pFT_Done_Face(font->ft_face);
3965     if (font->mapping) unmap_font_file( font->mapping );
3966     HeapFree(GetProcessHeap(), 0, font->kern_pairs);
3967     HeapFree(GetProcessHeap(), 0, font->potm);
3968     HeapFree(GetProcessHeap(), 0, font->name);
3969     for (i = 0; i < font->gmsize; i++)
3970         HeapFree(GetProcessHeap(),0,font->gm[i]);
3971     HeapFree(GetProcessHeap(), 0, font->gm);
3972     HeapFree(GetProcessHeap(), 0, font->GSUB_Table);
3973     HeapFree(GetProcessHeap(), 0, font);
3974 }
3975
3976
3977 static DWORD get_font_data( GdiFont *font, DWORD table, DWORD offset, LPVOID buf, DWORD cbData)
3978 {
3979     FT_Face ft_face = font->ft_face;
3980     FT_ULong len;
3981     FT_Error err;
3982
3983     if (!FT_IS_SFNT(ft_face)) return GDI_ERROR;
3984
3985     if(!buf)
3986         len = 0;
3987     else
3988         len = cbData;
3989
3990     table = RtlUlongByteSwap( table );  /* MS tags differ in endianness from FT ones */
3991
3992     /* make sure value of len is the value freetype says it needs */
3993     if (buf && len)
3994     {
3995         FT_ULong needed = 0;
3996         err = pFT_Load_Sfnt_Table(ft_face, table, offset, NULL, &needed);
3997         if( !err && needed < len) len = needed;
3998     }
3999     err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, &len);
4000     if (err)
4001     {
4002         TRACE("Can't find table %c%c%c%c\n",
4003               /* bytes were reversed */
4004               HIBYTE(HIWORD(table)), LOBYTE(HIWORD(table)),
4005               HIBYTE(LOWORD(table)), LOBYTE(LOWORD(table)));
4006         return GDI_ERROR;
4007     }
4008     return len;
4009 }
4010
4011 /*************************************************************
4012  * load_VDMX
4013  *
4014  * load the vdmx entry for the specified height
4015  */
4016
4017 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
4018           ( ( (FT_ULong)_x4 << 24 ) |     \
4019             ( (FT_ULong)_x3 << 16 ) |     \
4020             ( (FT_ULong)_x2 <<  8 ) |     \
4021               (FT_ULong)_x1         )
4022
4023 #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X')
4024
4025 typedef struct {
4026     BYTE bCharSet;
4027     BYTE xRatio;
4028     BYTE yStartRatio;
4029     BYTE yEndRatio;
4030 } Ratios;
4031
4032 typedef struct {
4033     WORD recs;
4034     BYTE startsz;
4035     BYTE endsz;
4036 } VDMX_group;
4037
4038 static LONG load_VDMX(GdiFont *font, LONG height)
4039 {
4040     WORD hdr[3], tmp;
4041     VDMX_group group;
4042     BYTE devXRatio, devYRatio;
4043     USHORT numRecs, numRatios;
4044     DWORD result, offset = -1;
4045     LONG ppem = 0;
4046     int i;
4047
4048     result = get_font_data(font, MS_VDMX_TAG, 0, hdr, 6);
4049
4050     if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
4051         return ppem;
4052
4053     /* FIXME: need the real device aspect ratio */
4054     devXRatio = 1;
4055     devYRatio = 1;
4056
4057     numRecs = GET_BE_WORD(hdr[1]);
4058     numRatios = GET_BE_WORD(hdr[2]);
4059
4060     TRACE("numRecs = %d numRatios = %d\n", numRecs, numRatios);
4061     for(i = 0; i < numRatios; i++) {
4062         Ratios ratio;
4063
4064         offset = (3 * 2) + (i * sizeof(Ratios));
4065         get_font_data(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
4066         offset = -1;
4067
4068         TRACE("Ratios[%d] %d  %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
4069
4070         if((ratio.xRatio == 0 &&
4071             ratio.yStartRatio == 0 &&
4072             ratio.yEndRatio == 0) ||
4073            (devXRatio == ratio.xRatio &&
4074             devYRatio >= ratio.yStartRatio &&
4075             devYRatio <= ratio.yEndRatio))
4076             {
4077                 offset = (3 * 2) + (numRatios * 4) + (i * 2);
4078                 get_font_data(font, MS_VDMX_TAG, offset, &tmp, 2);
4079                 offset = GET_BE_WORD(tmp);
4080                 break;
4081             }
4082     }
4083
4084     if(offset == -1) {
4085         FIXME("No suitable ratio found\n");
4086         return ppem;
4087     }
4088
4089     if(get_font_data(font, MS_VDMX_TAG, offset, &group, 4) != GDI_ERROR) {
4090         USHORT recs;
4091         BYTE startsz, endsz;
4092         WORD *vTable;
4093
4094         recs = GET_BE_WORD(group.recs);
4095         startsz = group.startsz;
4096         endsz = group.endsz;
4097
4098         TRACE("recs=%d  startsz=%d  endsz=%d\n", recs, startsz, endsz);
4099
4100         vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6);
4101         result = get_font_data(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6);
4102         if(result == GDI_ERROR) {
4103             FIXME("Failed to retrieve vTable\n");
4104             goto end;
4105         }
4106
4107         if(height > 0) {
4108             for(i = 0; i < recs; i++) {
4109                 SHORT yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
4110                 SHORT yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
4111                 ppem = GET_BE_WORD(vTable[i * 3]);
4112
4113                 if(yMax + -yMin == height) {
4114                     font->yMax = yMax;
4115                     font->yMin = yMin;
4116                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
4117                     break;
4118                 }
4119                 if(yMax + -yMin > height) {
4120                     if(--i < 0) {
4121                         ppem = 0;
4122                         goto end; /* failed */
4123                     }
4124                     font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
4125                     font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
4126                     ppem = GET_BE_WORD(vTable[i * 3]);
4127                     TRACE("ppem %d found; height=%d  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
4128                     break;
4129                 }
4130             }
4131             if(!font->yMax) {
4132                 ppem = 0;
4133                 TRACE("ppem not found for height %d\n", height);
4134             }
4135         }
4136         end:
4137         HeapFree(GetProcessHeap(), 0, vTable);
4138     }
4139
4140     return ppem;
4141 }
4142
4143 static BOOL fontcmp(const GdiFont *font, FONT_DESC *fd)
4144 {
4145     if(font->font_desc.hash != fd->hash) return TRUE;
4146     if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE;
4147     if(memcmp(&font->font_desc.lf, &fd->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
4148     if(!font->font_desc.can_use_bitmap != !fd->can_use_bitmap) return TRUE;
4149     return strcmpiW(font->font_desc.lf.lfFaceName, fd->lf.lfFaceName);
4150 }
4151
4152 static void calc_hash(FONT_DESC *pfd)
4153 {
4154     DWORD hash = 0, *ptr, two_chars;
4155     WORD *pwc;
4156     unsigned int i;
4157
4158     for(i = 0, ptr = (DWORD*)&pfd->matrix; i < sizeof(FMAT2)/sizeof(DWORD); i++, ptr++)
4159         hash ^= *ptr;
4160     for(i = 0, ptr = (DWORD*)&pfd->lf; i < 7; i++, ptr++)
4161         hash ^= *ptr;
4162     for(i = 0, ptr = (DWORD*)pfd->lf.lfFaceName; i < LF_FACESIZE/2; i++, ptr++) {
4163         two_chars = *ptr;
4164         pwc = (WCHAR *)&two_chars;
4165         if(!*pwc) break;
4166         *pwc = toupperW(*pwc);
4167         pwc++;
4168         *pwc = toupperW(*pwc);
4169         hash ^= two_chars;
4170         if(!*pwc) break;
4171     }
4172     hash ^= !pfd->can_use_bitmap;
4173     pfd->hash = hash;
4174     return;
4175 }
4176
4177 static GdiFont *find_in_cache(HFONT hfont, const LOGFONTW *plf, const FMAT2 *pmat, BOOL can_use_bitmap)
4178 {
4179     GdiFont *ret;
4180     FONT_DESC fd;
4181     HFONTLIST *hflist;
4182     struct list *font_elem_ptr, *hfontlist_elem_ptr;
4183
4184     fd.lf = *plf;
4185     fd.matrix = *pmat;
4186     fd.can_use_bitmap = can_use_bitmap;
4187     calc_hash(&fd);
4188
4189     /* try the child list */
4190     LIST_FOR_EACH(font_elem_ptr, &child_font_list) {
4191         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
4192         if(!fontcmp(ret, &fd)) {
4193             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
4194             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
4195                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
4196                 if(hflist->hfont == hfont)
4197                     return ret;
4198             }
4199         }
4200     }
4201
4202     /* try the in-use list */
4203     LIST_FOR_EACH(font_elem_ptr, &gdi_font_list) {
4204         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
4205         if(!fontcmp(ret, &fd)) {
4206             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
4207             LIST_FOR_EACH(hfontlist_elem_ptr, &ret->hfontlist) {
4208                 hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
4209                 if(hflist->hfont == hfont)
4210                     return ret;
4211             }
4212             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
4213             hflist->hfont = hfont;
4214             list_add_head(&ret->hfontlist, &hflist->entry);
4215             return ret;
4216         }
4217     }
4218  
4219     /* then the unused list */
4220     font_elem_ptr = list_head(&unused_gdi_font_list);
4221     while(font_elem_ptr) {
4222         ret = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
4223         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
4224         if(!fontcmp(ret, &fd)) {
4225             if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
4226             assert(list_empty(&ret->hfontlist));
4227             TRACE("Found %p in unused list\n", ret);
4228             list_remove(&ret->entry);
4229             list_add_head(&gdi_font_list, &ret->entry);
4230             hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
4231             hflist->hfont = hfont;
4232             list_add_head(&ret->hfontlist, &hflist->entry);
4233             return ret;
4234         }
4235     }
4236     return NULL;
4237 }
4238
4239 static void add_to_cache(GdiFont *font)
4240 {
4241     static DWORD cache_num = 1;
4242
4243     font->cache_num = cache_num++;
4244     list_add_head(&gdi_font_list, &font->entry);
4245 }
4246
4247 /*************************************************************
4248  * create_child_font_list
4249  */
4250 static BOOL create_child_font_list(GdiFont *font)
4251 {
4252     BOOL ret = FALSE;
4253     SYSTEM_LINKS *font_link;
4254     CHILD_FONT *font_link_entry, *new_child;
4255     FontSubst *psub;
4256     WCHAR* font_name;
4257
4258     psub = get_font_subst(&font_subst_list, font->name, -1);
4259     font_name = psub ? psub->to.name : font->name;
4260     font_link = find_font_link(font_name);
4261     if (font_link != NULL)
4262     {
4263         TRACE("found entry in system list\n");
4264         LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
4265         {
4266             new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
4267             new_child->face = font_link_entry->face;
4268             new_child->font = NULL;
4269             list_add_tail(&font->child_fonts, &new_child->entry);
4270             TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
4271         }
4272         ret = TRUE;
4273     }
4274     /*
4275      * if not SYMBOL or OEM then we also get all the fonts for Microsoft
4276      * Sans Serif.  This is how asian windows get default fallbacks for fonts
4277      */
4278     if (use_default_fallback && font->charset != SYMBOL_CHARSET &&
4279         font->charset != OEM_CHARSET &&
4280         strcmpiW(font_name,szDefaultFallbackLink) != 0)
4281     {
4282         font_link = find_font_link(szDefaultFallbackLink);
4283         if (font_link != NULL)
4284         {
4285             TRACE("found entry in default fallback list\n");
4286             LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
4287             {
4288                 new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
4289                 new_child->face = font_link_entry->face;
4290                 new_child->font = NULL;
4291                 list_add_tail(&font->child_fonts, &new_child->entry);
4292                 TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
4293             }
4294             ret = TRUE;
4295         }
4296     }
4297
4298     return ret;
4299 }
4300
4301 static BOOL select_charmap(FT_Face ft_face, FT_Encoding encoding)
4302 {
4303     FT_Error ft_err = FT_Err_Invalid_CharMap_Handle;
4304
4305     if (pFT_Set_Charmap)
4306     {
4307         FT_Int i;
4308         FT_CharMap cmap0, cmap1, cmap2, cmap3, cmap_def;
4309
4310         cmap0 = cmap1 = cmap2 = cmap3 = cmap_def = NULL;
4311
4312         for (i = 0; i < ft_face->num_charmaps; i++)
4313         {
4314             if (ft_face->charmaps[i]->encoding == encoding)
4315             {
4316                 TRACE("found cmap with platform_id %u, encoding_id %u\n",
4317                        ft_face->charmaps[i]->platform_id, ft_face->charmaps[i]->encoding_id);
4318
4319                 switch (ft_face->charmaps[i]->platform_id)
4320                 {
4321                     default:
4322                         cmap_def = ft_face->charmaps[i];
4323                         break;
4324                     case 0: /* Apple Unicode */
4325                         cmap0 = ft_face->charmaps[i];
4326                         break;
4327                     case 1: /* Macintosh */
4328                         cmap1 = ft_face->charmaps[i];
4329                         break;
4330                     case 2: /* ISO */
4331                         cmap2 = ft_face->charmaps[i];
4332                         break;
4333                     case 3: /* Microsoft */
4334                         cmap3 = ft_face->charmaps[i];
4335                         break;
4336                 }
4337             }
4338
4339             if (cmap3) /* prefer Microsoft cmap table */
4340                 ft_err = pFT_Set_Charmap(ft_face, cmap3);
4341             else if (cmap1)
4342                 ft_err = pFT_Set_Charmap(ft_face, cmap1);
4343             else if (cmap2)
4344                 ft_err = pFT_Set_Charmap(ft_face, cmap2);
4345             else if (cmap0)
4346                 ft_err = pFT_Set_Charmap(ft_face, cmap0);
4347             else if (cmap_def)
4348                 ft_err = pFT_Set_Charmap(ft_face, cmap_def);
4349         }
4350         return ft_err == FT_Err_Ok;
4351     }
4352
4353     return pFT_Select_Charmap(ft_face, encoding) == FT_Err_Ok;
4354 }
4355
4356
4357 /*************************************************************
4358  * freetype_CreateDC
4359  */
4360 static BOOL freetype_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device,
4361                                LPCWSTR output, const DEVMODEW *devmode )
4362 {
4363     struct freetype_physdev *physdev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physdev) );
4364
4365     if (!physdev) return FALSE;
4366     push_dc_driver( dev, &physdev->dev, &freetype_funcs );
4367     return TRUE;
4368 }
4369
4370
4371 /*************************************************************
4372  * freetype_DeleteDC
4373  */
4374 static BOOL freetype_DeleteDC( PHYSDEV dev )
4375 {
4376     struct freetype_physdev *physdev = get_freetype_dev( dev );
4377     HeapFree( GetProcessHeap(), 0, physdev );
4378     return TRUE;
4379 }
4380
4381
4382 /*************************************************************
4383  * freetype_SelectFont
4384  */
4385 static HFONT freetype_SelectFont( PHYSDEV dev, HFONT hfont )
4386 {
4387     struct freetype_physdev *physdev = get_freetype_dev( dev );
4388     GdiFont *ret;
4389     Face *face, *best, *best_bitmap;
4390     Family *family, *last_resort_family;
4391     const struct list *family_elem_ptr, *face_list, *face_elem_ptr;
4392     INT height, width = 0;
4393     unsigned int score = 0, new_score;
4394     signed int diff = 0, newdiff;
4395     BOOL bd, it, can_use_bitmap, want_vertical;
4396     LOGFONTW lf;
4397     CHARSETINFO csi;
4398     HFONTLIST *hflist;
4399     FMAT2 dcmat;
4400     FontSubst *psub = NULL;
4401     DC *dc = get_dc_ptr( dev->hdc );
4402     const SYSTEM_LINKS *font_link;
4403
4404     if (!hfont)  /* notification that the font has been changed by another driver */
4405     {
4406         dc->gdiFont = NULL;
4407         physdev->font = NULL;
4408         release_dc_ptr( dc );
4409         return 0;
4410     }
4411
4412     GetObjectW( hfont, sizeof(lf), &lf );
4413     lf.lfWidth = abs(lf.lfWidth);
4414
4415     can_use_bitmap = GetDeviceCaps(dev->hdc, TEXTCAPS) & TC_RA_ABLE;
4416
4417     TRACE("%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n",
4418           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
4419           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
4420           lf.lfEscapement);
4421
4422     if(dc->GraphicsMode == GM_ADVANCED)
4423     {
4424         memcpy(&dcmat, &dc->xformWorld2Vport, sizeof(FMAT2));
4425         /* Try to avoid not necessary glyph transformations */
4426         if (dcmat.eM21 == 0.0 && dcmat.eM12 == 0.0 && dcmat.eM11 == dcmat.eM22)
4427         {
4428             lf.lfHeight *= fabs(dcmat.eM11);
4429             lf.lfWidth *= fabs(dcmat.eM11);
4430             dcmat.eM11 = dcmat.eM22 = 1.0;
4431         }
4432     }
4433     else
4434     {
4435         /* Windows 3.1 compatibility mode GM_COMPATIBLE has only limited
4436            font scaling abilities. */
4437         dcmat.eM11 = dcmat.eM22 = 1.0;
4438         dcmat.eM21 = dcmat.eM12 = 0;
4439         if (dc->vport2WorldValid)
4440         {
4441             if (dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0)
4442                 lf.lfOrientation = -lf.lfOrientation;
4443             lf.lfHeight *= fabs(dc->xformWorld2Vport.eM22);
4444             lf.lfWidth *= fabs(dc->xformWorld2Vport.eM22);
4445         }
4446     }
4447
4448     TRACE("DC transform %f %f %f %f\n", dcmat.eM11, dcmat.eM12,
4449                                         dcmat.eM21, dcmat.eM22);
4450
4451     GDI_CheckNotLock();
4452     EnterCriticalSection( &freetype_cs );
4453
4454     /* check the cache first */
4455     if((ret = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap)) != NULL) {
4456         TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
4457         goto done;
4458     }
4459
4460     if(list_empty(&font_list)) /* No fonts installed */
4461     {
4462         TRACE("No fonts installed\n");
4463         goto done;
4464     }
4465
4466     TRACE("not in cache\n");
4467     ret = alloc_font();
4468
4469     ret->font_desc.matrix = dcmat;
4470     ret->font_desc.lf = lf;
4471     ret->font_desc.can_use_bitmap = can_use_bitmap;
4472     calc_hash(&ret->font_desc);
4473     hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist));
4474     hflist->hfont = hfont;
4475     list_add_head(&ret->hfontlist, &hflist->entry);
4476
4477     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
4478        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
4479        original value lfCharSet.  Note this is a special case for
4480        Symbol and doesn't happen at least for "Wingdings*" */
4481
4482     if(!strcmpiW(lf.lfFaceName, SymbolW))
4483         lf.lfCharSet = SYMBOL_CHARSET;
4484
4485     if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
4486         switch(lf.lfCharSet) {
4487         case DEFAULT_CHARSET:
4488             csi.fs.fsCsb[0] = 0;
4489             break;
4490         default:
4491             FIXME("Untranslated charset %d\n", lf.lfCharSet);
4492             csi.fs.fsCsb[0] = 0;
4493             break;
4494         }
4495     }
4496
4497     family = NULL;
4498     if(lf.lfFaceName[0] != '\0') {
4499         CHILD_FONT *font_link_entry;
4500         LPWSTR FaceName = lf.lfFaceName;
4501
4502         psub = get_font_subst(&font_subst_list, FaceName, lf.lfCharSet);
4503
4504         if(psub) {
4505             TRACE("substituting %s,%d -> %s,%d\n", debugstr_w(FaceName), lf.lfCharSet,
4506                   debugstr_w(psub->to.name), (psub->to.charset != -1) ? psub->to.charset : lf.lfCharSet);
4507             if (psub->to.charset != -1)
4508                 lf.lfCharSet = psub->to.charset;
4509         }
4510
4511         /* We want a match on name and charset or just name if
4512            charset was DEFAULT_CHARSET.  If the latter then
4513            we fixup the returned charset later in get_nearest_charset
4514            where we'll either use the charset of the current ansi codepage
4515            or if that's unavailable the first charset that the font supports.
4516         */
4517         LIST_FOR_EACH(family_elem_ptr, &font_list) {
4518             family = LIST_ENTRY(family_elem_ptr, Family, entry);
4519             if (!strcmpiW(family->FamilyName, FaceName) ||
4520                 (psub && !strcmpiW(family->FamilyName, psub->to.name)))
4521             {
4522                 font_link = find_font_link(family->FamilyName);
4523                 face_list = get_face_list_from_family(family);
4524                 LIST_FOR_EACH(face_elem_ptr, face_list) {
4525                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
4526                     if (!(face->scalable || can_use_bitmap))
4527                         continue;
4528                     if (csi.fs.fsCsb[0] & face->fs.fsCsb[0])
4529                         goto found;
4530                     if (font_link != NULL &&
4531                         csi.fs.fsCsb[0] & font_link->fs.fsCsb[0])
4532                         goto found;
4533                     if (!csi.fs.fsCsb[0])
4534                         goto found;
4535                 }
4536             }
4537         }
4538
4539         /* Search by full face name. */
4540         LIST_FOR_EACH(family_elem_ptr, &font_list) {
4541             family = LIST_ENTRY(family_elem_ptr, Family, entry);
4542             face_list = get_face_list_from_family(family);
4543             LIST_FOR_EACH(face_elem_ptr, face_list) {
4544                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
4545                 if(face->FullName && !strcmpiW(face->FullName, FaceName) &&
4546                    (face->scalable || can_use_bitmap))
4547                 {
4548                     if (csi.fs.fsCsb[0] & face->fs.fsCsb[0] || !csi.fs.fsCsb[0])
4549                         goto found_face;
4550                     font_link = find_font_link(family->FamilyName);
4551                     if (font_link != NULL &&
4552                         csi.fs.fsCsb[0] & font_link->fs.fsCsb[0])
4553                         goto found_face;
4554                 }
4555             }
4556         }
4557
4558         /*
4559          * Try check the SystemLink list first for a replacement font.
4560          * We may find good replacements there.
4561          */
4562         LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
4563         {
4564             if(!strcmpiW(font_link->font_name, FaceName) ||
4565                (psub && !strcmpiW(font_link->font_name,psub->to.name)))
4566             {
4567                 TRACE("found entry in system list\n");
4568                 LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
4569                 {
4570                     const SYSTEM_LINKS *links;
4571
4572                     face = font_link_entry->face;
4573                     if (!(face->scalable || can_use_bitmap))
4574                         continue;
4575                     family = face->family;
4576                     if (csi.fs.fsCsb[0] & face->fs.fsCsb[0] || !csi.fs.fsCsb[0])
4577                         goto found;
4578                     links = find_font_link(family->FamilyName);
4579                     if (links != NULL && csi.fs.fsCsb[0] & links->fs.fsCsb[0])
4580                         goto found;
4581                 }
4582             }
4583         }
4584     }
4585
4586     psub = NULL; /* substitution is no more relevant */
4587
4588     /* If requested charset was DEFAULT_CHARSET then try using charset
4589        corresponding to the current ansi codepage */
4590     if (!csi.fs.fsCsb[0])
4591     {
4592         INT acp = GetACP();
4593         if(!TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE)) {
4594             FIXME("TCI failed on codepage %d\n", acp);
4595             csi.fs.fsCsb[0] = 0;
4596         } else
4597             lf.lfCharSet = csi.ciCharset;
4598     }
4599
4600     want_vertical = (lf.lfFaceName[0] == '@');
4601
4602     /* Face families are in the top 4 bits of lfPitchAndFamily,
4603        so mask with 0xF0 before testing */
4604
4605     if((lf.lfPitchAndFamily & FIXED_PITCH) ||
4606        (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
4607         strcpyW(lf.lfFaceName, defFixed);
4608     else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
4609         strcpyW(lf.lfFaceName, defSerif);
4610     else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
4611         strcpyW(lf.lfFaceName, defSans);
4612     else
4613         strcpyW(lf.lfFaceName, defSans);
4614     LIST_FOR_EACH(family_elem_ptr, &font_list) {
4615         family = LIST_ENTRY(family_elem_ptr, Family, entry);
4616         if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
4617             font_link = find_font_link(family->FamilyName);
4618             face_list = get_face_list_from_family(family);
4619             LIST_FOR_EACH(face_elem_ptr, face_list) {
4620                 face = LIST_ENTRY(face_elem_ptr, Face, entry);
4621                 if (!(face->scalable || can_use_bitmap))
4622                     continue;
4623                 if (csi.fs.fsCsb[0] & face->fs.fsCsb[0])
4624                     goto found;
4625                 if (font_link != NULL && csi.fs.fsCsb[0] & font_link->fs.fsCsb[0])
4626                     goto found;
4627             }
4628         }
4629     }
4630
4631     last_resort_family = NULL;
4632     LIST_FOR_EACH(family_elem_ptr, &font_list) {
4633         family = LIST_ENTRY(family_elem_ptr, Family, entry);
4634         font_link = find_font_link(family->FamilyName);
4635         face_list = get_face_list_from_family(family);
4636         LIST_FOR_EACH(face_elem_ptr, face_list) {
4637             face = LIST_ENTRY(face_elem_ptr, Face, entry);
4638             if(face->vertical == want_vertical &&
4639                (csi.fs.fsCsb[0] & face->fs.fsCsb[0] ||
4640                 (font_link != NULL && csi.fs.fsCsb[0] & font_link->fs.fsCsb[0]))) {
4641                 if(face->scalable)
4642                     goto found;
4643                 if(can_use_bitmap && !last_resort_family)
4644                     last_resort_family = family;
4645             }            
4646         }
4647     }
4648
4649     if(last_resort_family) {
4650         family = last_resort_family;
4651         csi.fs.fsCsb[0] = 0;
4652         goto found;
4653     }
4654
4655     LIST_FOR_EACH(family_elem_ptr, &font_list) {
4656         family = LIST_ENTRY(family_elem_ptr, Family, entry);
4657         face_list = get_face_list_from_family(family);
4658         LIST_FOR_EACH(face_elem_ptr, face_list) {
4659             face = LIST_ENTRY(face_elem_ptr, Face, entry);
4660             if(face->scalable && face->vertical == want_vertical) {
4661                 csi.fs.fsCsb[0] = 0;
4662                 WARN("just using first face for now\n");
4663                 goto found;
4664             }
4665             if(can_use_bitmap && !last_resort_family)
4666                 last_resort_family = family;
4667         }
4668     }
4669     if(!last_resort_family) {
4670         FIXME("can't find a single appropriate font - bailing\n");
4671         free_font(ret);
4672         ret = NULL;
4673         goto done;
4674     }
4675
4676     WARN("could only find a bitmap font - this will probably look awful!\n");
4677     family = last_resort_family;
4678     csi.fs.fsCsb[0] = 0;
4679
4680 found:
4681     it = lf.lfItalic ? 1 : 0;
4682     bd = lf.lfWeight > 550 ? 1 : 0;
4683
4684     height = lf.lfHeight;
4685
4686     face = best = best_bitmap = NULL;
4687     font_link = find_font_link(family->FamilyName);
4688     face_list = get_face_list_from_family(family);
4689     LIST_FOR_EACH_ENTRY(face, face_list, Face, entry)
4690     {
4691         if (csi.fs.fsCsb[0] & face->fs.fsCsb[0] ||
4692             (font_link != NULL && csi.fs.fsCsb[0] & font_link->fs.fsCsb[0]) ||
4693             !csi.fs.fsCsb[0])
4694         {
4695             BOOL italic, bold;
4696
4697             italic = (face->ntmFlags & NTM_ITALIC) ? 1 : 0;
4698             bold = (face->ntmFlags & NTM_BOLD) ? 1 : 0;
4699             new_score = (italic ^ it) + (bold ^ bd);
4700             if(!best || new_score <= score)
4701             {
4702                 TRACE("(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n",
4703                       italic, bold, it, bd);
4704                 score = new_score;
4705                 best = face;
4706                 if(best->scalable  && score == 0) break;
4707                 if(!best->scalable)
4708                 {
4709                     if(height > 0)
4710                         newdiff = height - (signed int)(best->size.height);
4711                     else
4712                         newdiff = -height - ((signed int)(best->size.height) - best->size.internal_leading);
4713                     if(!best_bitmap || new_score < score ||
4714                        (diff > 0 && newdiff < diff && newdiff >= 0) || (diff < 0 && newdiff > diff))
4715                     {
4716                         TRACE("%d is better for %d diff was %d\n", best->size.height, height, diff);
4717                         diff = newdiff;
4718                         best_bitmap = best;
4719                         if(score == 0 && diff == 0) break;
4720                     }
4721                 }
4722             }
4723         }
4724     }
4725     if(best)
4726         face = best->scalable ? best : best_bitmap;
4727     ret->fake_italic = (it && !(face->ntmFlags & NTM_ITALIC));
4728     ret->fake_bold = (bd && !(face->ntmFlags & NTM_BOLD));
4729
4730 found_face:
4731     height = lf.lfHeight;
4732
4733     ret->fs = face->fs;
4734
4735     if(csi.fs.fsCsb[0]) {
4736         ret->charset = lf.lfCharSet;
4737         ret->codepage = csi.ciACP;
4738     }
4739     else
4740         ret->charset = get_nearest_charset(family->FamilyName, face, &ret->codepage);
4741
4742     TRACE("Chosen: %s %s (%s/%p:%ld)\n", debugstr_w(family->FamilyName),
4743           debugstr_w(face->StyleName), face->file, face->font_data_ptr, face->face_index);
4744
4745     ret->aveWidth = height ? lf.lfWidth : 0;
4746
4747     if(!face->scalable) {
4748         /* Windows uses integer scaling factors for bitmap fonts */
4749         INT scale, scaled_height;
4750         GdiFont *cachedfont;
4751
4752         /* FIXME: rotation of bitmap fonts is ignored */
4753         height = abs(GDI_ROUND( (double)height * ret->font_desc.matrix.eM22 ));
4754         if (ret->aveWidth)
4755             ret->aveWidth = (double)ret->aveWidth * ret->font_desc.matrix.eM11;
4756         ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
4757         dcmat.eM11 = dcmat.eM22 = 1.0;
4758         /* As we changed the matrix, we need to search the cache for the font again,
4759          * otherwise we might explode the cache. */
4760         if((cachedfont = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap)) != NULL) {
4761             TRACE("Found cached font after non-scalable matrix rescale!\n");
4762             free_font( ret );
4763             ret = cachedfont;
4764             goto done;
4765         }
4766         calc_hash(&ret->font_desc);
4767
4768         if (height != 0) height = diff;
4769         height += face->size.height;
4770
4771         scale = (height + face->size.height - 1) / face->size.height;
4772         scaled_height = scale * face->size.height;
4773         /* Only jump to the next height if the difference <= 25% original height */
4774         if (scale > 2 && scaled_height - height > face->size.height / 4) scale--;
4775         /* The jump between unscaled and doubled is delayed by 1 */
4776         else if (scale == 2 && scaled_height - height > (face->size.height / 4 - 1)) scale--;
4777         ret->scale_y = scale;
4778
4779         width = face->size.x_ppem >> 6;
4780         height = face->size.y_ppem >> 6;
4781     }
4782     else
4783         ret->scale_y = 1.0;
4784     TRACE("font scale y: %f\n", ret->scale_y);
4785
4786     ret->ft_face = OpenFontFace(ret, face, width, height);
4787
4788     if (!ret->ft_face)
4789     {
4790         free_font( ret );
4791         ret = NULL;
4792         goto done;
4793     }
4794
4795     ret->ntmFlags = face->ntmFlags;
4796
4797     if (ret->charset == SYMBOL_CHARSET && 
4798         select_charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) {
4799         /* No ops */
4800     }
4801     else if (select_charmap(ret->ft_face, FT_ENCODING_UNICODE)) {
4802         /* No ops */
4803     }
4804     else {
4805         select_charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN);
4806     }
4807
4808     ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0;
4809     ret->name = psub ? strdupW(psub->from.name) : strdupW(family->FamilyName);
4810     ret->underline = lf.lfUnderline ? 0xff : 0;
4811     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
4812     create_child_font_list(ret);
4813
4814     if (face->vertical) /* We need to try to load the GSUB table */
4815     {
4816         int length = get_font_data(ret, GSUB_TAG , 0, NULL, 0);
4817         if (length != GDI_ERROR)
4818         {
4819             ret->GSUB_Table = HeapAlloc(GetProcessHeap(),0,length);
4820             get_font_data(ret, GSUB_TAG , 0, ret->GSUB_Table, length);
4821             TRACE("Loaded GSUB table of %i bytes\n",length);
4822         }
4823     }
4824
4825     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
4826
4827     add_to_cache(ret);
4828 done:
4829     if (ret)
4830     {
4831         dc->gdiFont = ret;
4832         physdev->font = ret;
4833     }
4834     LeaveCriticalSection( &freetype_cs );
4835     release_dc_ptr( dc );
4836     return ret ? hfont : 0;
4837 }
4838
4839 static void dump_gdi_font_list(void)
4840 {
4841     GdiFont *gdiFont;
4842     struct list *elem_ptr;
4843
4844     TRACE("---------- gdiFont Cache ----------\n");
4845     LIST_FOR_EACH(elem_ptr, &gdi_font_list) {
4846         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
4847         TRACE("gdiFont=%p %s %d\n",
4848               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
4849     }
4850
4851     TRACE("---------- Unused gdiFont Cache ----------\n");
4852     LIST_FOR_EACH(elem_ptr, &unused_gdi_font_list) {
4853         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
4854         TRACE("gdiFont=%p %s %d\n",
4855               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
4856     }
4857
4858     TRACE("---------- Child gdiFont Cache ----------\n");
4859     LIST_FOR_EACH(elem_ptr, &child_font_list) {
4860         gdiFont = LIST_ENTRY(elem_ptr, struct tagGdiFont, entry);
4861         TRACE("gdiFont=%p %s %d\n",
4862               gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight);
4863     }
4864 }
4865
4866 /*************************************************************
4867  * WineEngDestroyFontInstance
4868  *
4869  * free the gdiFont associated with this handle
4870  *
4871  */
4872 BOOL WineEngDestroyFontInstance(HFONT handle)
4873 {
4874     GdiFont *gdiFont;
4875     HFONTLIST *hflist;
4876     BOOL ret = FALSE;
4877     struct list *font_elem_ptr, *hfontlist_elem_ptr;
4878     int i = 0;
4879
4880     GDI_CheckNotLock();
4881     EnterCriticalSection( &freetype_cs );
4882
4883     LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry)
4884     {
4885         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
4886         while(hfontlist_elem_ptr) {
4887             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
4888             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
4889             if(hflist->hfont == handle) {
4890                 TRACE("removing child font %p from child list\n", gdiFont);
4891                 list_remove(&gdiFont->entry);
4892                 LeaveCriticalSection( &freetype_cs );
4893                 return TRUE;
4894             }
4895         }
4896     }
4897
4898     TRACE("destroying hfont=%p\n", handle);
4899     if(TRACE_ON(font))
4900         dump_gdi_font_list();
4901
4902     font_elem_ptr = list_head(&gdi_font_list);
4903     while(font_elem_ptr) {
4904         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
4905         font_elem_ptr = list_next(&gdi_font_list, font_elem_ptr);
4906
4907         hfontlist_elem_ptr = list_head(&gdiFont->hfontlist);
4908         while(hfontlist_elem_ptr) {
4909             hflist = LIST_ENTRY(hfontlist_elem_ptr, struct tagHFONTLIST, entry);
4910             hfontlist_elem_ptr = list_next(&gdiFont->hfontlist, hfontlist_elem_ptr);
4911             if(hflist->hfont == handle) {
4912                 list_remove(&hflist->entry);
4913                 HeapFree(GetProcessHeap(), 0, hflist);
4914                 ret = TRUE;
4915             }
4916         }
4917         if(list_empty(&gdiFont->hfontlist)) {
4918             TRACE("Moving to Unused list\n");
4919             list_remove(&gdiFont->entry);
4920             list_add_head(&unused_gdi_font_list, &gdiFont->entry);
4921         }
4922     }
4923
4924
4925     font_elem_ptr = list_head(&unused_gdi_font_list);
4926     while(font_elem_ptr && i++ < UNUSED_CACHE_SIZE)
4927         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
4928     while(font_elem_ptr) {
4929         gdiFont = LIST_ENTRY(font_elem_ptr, struct tagGdiFont, entry);
4930         font_elem_ptr = list_next(&unused_gdi_font_list, font_elem_ptr);
4931         TRACE("freeing %p\n", gdiFont);
4932         list_remove(&gdiFont->entry);
4933         free_font(gdiFont);
4934     }
4935     LeaveCriticalSection( &freetype_cs );
4936     return ret;
4937 }
4938
4939 static INT load_script_name( UINT id, WCHAR buffer[LF_FACESIZE] )
4940 {
4941     HRSRC rsrc;
4942     HGLOBAL hMem;
4943     WCHAR *p;
4944     int i;
4945
4946     id += IDS_FIRST_SCRIPT;
4947     rsrc = FindResourceW( gdi32_module, (LPCWSTR)(ULONG_PTR)((id >> 4) + 1), (LPCWSTR)6 /*RT_STRING*/ );
4948     if (!rsrc) return 0;
4949     hMem = LoadResource( gdi32_module, rsrc );
4950     if (!hMem) return 0;
4951
4952     p = LockResource( hMem );
4953     id &= 0x000f;
4954     while (id--) p += *p + 1;
4955
4956     i = min(LF_FACESIZE - 1, *p);
4957     memcpy(buffer, p + 1, i * sizeof(WCHAR));
4958     buffer[i] = 0;
4959     return i;
4960 }
4961
4962
4963 /***************************************************
4964  * create_enum_charset_list
4965  *
4966  * This function creates charset enumeration list because in DEFAULT_CHARSET
4967  * case, the ANSI codepage's charset takes precedence over other charsets.
4968  * This function works as a filter other than DEFAULT_CHARSET case.
4969  */
4970 static DWORD create_enum_charset_list(DWORD charset, struct enum_charset_list *list)
4971 {
4972     CHARSETINFO csi;
4973     DWORD n = 0;
4974
4975     if (TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET) &&
4976         csi.fs.fsCsb[0] != 0) {
4977         list->element[n].mask    = csi.fs.fsCsb[0];
4978         list->element[n].charset = csi.ciCharset;
4979         load_script_name( ffs(csi.fs.fsCsb[0]) - 1, list->element[n].name );
4980         n++;
4981     }
4982     else { /* charset is DEFAULT_CHARSET or invalid. */
4983         INT acp, i;
4984
4985         /* Set the current codepage's charset as the first element. */
4986         acp = GetACP();
4987         if (TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE) &&
4988             csi.fs.fsCsb[0] != 0) {
4989             list->element[n].mask    = csi.fs.fsCsb[0];
4990             list->element[n].charset = csi.ciCharset;
4991             load_script_name( ffs(csi.fs.fsCsb[0]) - 1, list->element[n].name );
4992             n++;
4993         }
4994
4995         /* Fill out left elements. */
4996         for (i = 0; i < 32; i++) {
4997             FONTSIGNATURE fs;
4998             fs.fsCsb[0] = 1L << i;
4999             fs.fsCsb[1] = 0;
5000             if (n > 0 && fs.fsCsb[0] == list->element[0].mask)
5001                 continue; /* skip, already added. */
5002             if (!TranslateCharsetInfo(fs.fsCsb, &csi, TCI_SRCFONTSIG))
5003                 continue; /* skip, this is an invalid fsCsb bit. */
5004
5005             list->element[n].mask    = fs.fsCsb[0];
5006             list->element[n].charset = csi.ciCharset;
5007             load_script_name( i, list->element[n].name );
5008             n++;
5009         }
5010     }
5011     list->total = n;
5012
5013     return n;
5014 }
5015
5016 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
5017                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
5018 {
5019     GdiFont *font;
5020     LONG width, height;
5021
5022     if (face->cached_enum_data)
5023     {
5024         TRACE("Cached\n");
5025         *pelf = face->cached_enum_data->elf;
5026         *pntm = face->cached_enum_data->ntm;
5027         *ptype = face->cached_enum_data->type;
5028         return;
5029     }
5030
5031     font = alloc_font();
5032
5033     if(face->scalable) {
5034         height = -2048; /* 2048 is the most common em size */
5035         width = 0;
5036     } else {
5037         height = face->size.y_ppem >> 6;
5038         width = face->size.x_ppem >> 6;
5039     }
5040     font->scale_y = 1.0;
5041     
5042     if (!(font->ft_face = OpenFontFace(font, face, width, height)))
5043     {
5044         free_font(font);
5045         return;
5046     }
5047
5048     font->name = strdupW(face->family->FamilyName);
5049     font->ntmFlags = face->ntmFlags;
5050
5051     if (get_outline_text_metrics(font))
5052     {
5053         memcpy(&pntm->ntmTm, &font->potm->otmTextMetrics, sizeof(TEXTMETRICW));
5054
5055         pntm->ntmTm.ntmSizeEM = font->potm->otmEMSquare;
5056
5057         lstrcpynW(pelf->elfLogFont.lfFaceName,
5058                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFamilyName),
5059                  LF_FACESIZE);
5060         lstrcpynW(pelf->elfFullName,
5061                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpFullName),
5062                  LF_FULLFACESIZE);
5063         lstrcpynW(pelf->elfStyle,
5064                  (WCHAR*)((char*)font->potm + (ULONG_PTR)font->potm->otmpStyleName),
5065                  LF_FACESIZE);
5066     }
5067     else
5068     {
5069         get_text_metrics(font, (TEXTMETRICW *)&pntm->ntmTm);
5070
5071         pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
5072
5073         lstrcpynW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
5074         if (face->FullName)
5075             lstrcpynW(pelf->elfFullName, face->FullName, LF_FULLFACESIZE);
5076         else
5077             lstrcpynW(pelf->elfFullName, face->family->FamilyName, LF_FULLFACESIZE);
5078         lstrcpynW(pelf->elfStyle, face->StyleName, LF_FACESIZE);
5079     }
5080
5081     pntm->ntmTm.ntmFlags = face->ntmFlags;
5082     pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
5083     pntm->ntmTm.ntmAvgWidth = pntm->ntmTm.tmAveCharWidth;
5084     pntm->ntmFontSig = face->fs;
5085
5086     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
5087
5088     pelf->elfLogFont.lfEscapement = 0;
5089     pelf->elfLogFont.lfOrientation = 0;
5090     pelf->elfLogFont.lfHeight = pntm->ntmTm.tmHeight;
5091     pelf->elfLogFont.lfWidth = pntm->ntmTm.tmAveCharWidth;
5092     pelf->elfLogFont.lfWeight = pntm->ntmTm.tmWeight;
5093     pelf->elfLogFont.lfItalic = pntm->ntmTm.tmItalic;
5094     pelf->elfLogFont.lfUnderline = pntm->ntmTm.tmUnderlined;
5095     pelf->elfLogFont.lfStrikeOut = pntm->ntmTm.tmStruckOut;
5096     pelf->elfLogFont.lfCharSet = pntm->ntmTm.tmCharSet;
5097     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
5098     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
5099     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
5100     pelf->elfLogFont.lfPitchAndFamily = (pntm->ntmTm.tmPitchAndFamily & 0xf1) + 1;
5101
5102     *ptype = 0;
5103     if (pntm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE)
5104         *ptype |= TRUETYPE_FONTTYPE;
5105     if (pntm->ntmTm.tmPitchAndFamily & TMPF_DEVICE)
5106         *ptype |= DEVICE_FONTTYPE;
5107     if(!(pntm->ntmTm.tmPitchAndFamily & TMPF_VECTOR))
5108         *ptype |= RASTER_FONTTYPE;
5109
5110     face->cached_enum_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*face->cached_enum_data));
5111     if (face->cached_enum_data)
5112     {
5113         face->cached_enum_data->elf = *pelf;
5114         face->cached_enum_data->ntm = *pntm;
5115         face->cached_enum_data->type = *ptype;
5116     }
5117
5118     free_font(font);
5119 }
5120
5121 static void create_full_name(WCHAR *full_name, const WCHAR *family_name, const WCHAR *style_name)
5122 {
5123     static const WCHAR spaceW[] = { ' ', 0 };
5124
5125     strcpyW(full_name, family_name);
5126     strcatW(full_name, spaceW);
5127     strcatW(full_name, style_name);
5128 }
5129
5130 static BOOL family_matches(Family *family, const LOGFONTW *lf)
5131 {
5132     const struct list *face_list, *face_elem_ptr;
5133
5134     if (!strcmpiW(lf->lfFaceName, family->FamilyName)) return TRUE;
5135
5136     face_list = get_face_list_from_family(family);
5137     LIST_FOR_EACH(face_elem_ptr, face_list)
5138     {
5139         WCHAR full_family_name[LF_FULLFACESIZE];
5140         Face *face = LIST_ENTRY(face_elem_ptr, Face, entry);
5141
5142         if (strlenW(family->FamilyName) + strlenW(face->StyleName) + 2 > LF_FULLFACESIZE)
5143         {
5144             FIXME("Length of %s + %s + 2 is longer than LF_FULLFACESIZE\n",
5145                   debugstr_w(family->FamilyName), debugstr_w(face->StyleName));
5146             continue;
5147         }
5148
5149         create_full_name(full_family_name, family->FamilyName, face->StyleName);
5150         if (!strcmpiW(lf->lfFaceName, full_family_name)) return TRUE;
5151     }
5152
5153     return FALSE;
5154 }
5155
5156 static BOOL face_matches(const WCHAR *family_name, Face *face, const LOGFONTW *lf)
5157 {
5158     WCHAR full_family_name[LF_FULLFACESIZE];
5159
5160     if (!strcmpiW(lf->lfFaceName, family_name)) return TRUE;
5161
5162     if (strlenW(family_name) + strlenW(face->StyleName) + 2 > LF_FULLFACESIZE)
5163     {
5164         FIXME("Length of %s + %s + 2 is longer than LF_FULLFACESIZE\n",
5165               debugstr_w(family_name), debugstr_w(face->StyleName));
5166         return FALSE;
5167     }
5168
5169     create_full_name(full_family_name, family_name, face->StyleName);
5170     return !strcmpiW(lf->lfFaceName, full_family_name);
5171 }
5172
5173 static BOOL enum_face_charsets(const Family *family, Face *face, struct enum_charset_list *list,
5174                                FONTENUMPROCW proc, LPARAM lparam)
5175 {
5176     ENUMLOGFONTEXW elf;
5177     NEWTEXTMETRICEXW ntm;
5178     DWORD type = 0;
5179     int i;
5180
5181     GetEnumStructs(face, &elf, &ntm, &type);
5182     for(i = 0; i < list->total; i++) {
5183         if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
5184             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
5185             load_script_name( IDS_OEM_DOS, elf.elfScript );
5186             i = list->total; /* break out of loop after enumeration */
5187         } else if(!(face->fs.fsCsb[0] & list->element[i].mask))
5188             continue;
5189         else {
5190             elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = list->element[i].charset;
5191             strcpyW(elf.elfScript, list->element[i].name);
5192             if (!elf.elfScript[0])
5193                 FIXME("Unknown elfscript for bit %d\n", ffs(list->element[i].mask) - 1);
5194         }
5195         /* Font Replacement */
5196         if (family != face->family)
5197         {
5198             strcpyW(elf.elfLogFont.lfFaceName, family->FamilyName);
5199             create_full_name(elf.elfFullName, family->FamilyName, face->StyleName);
5200         }
5201         TRACE("enuming face %s full %s style %s charset = %d type %d script %s it %d weight %d ntmflags %08x\n",
5202               debugstr_w(elf.elfLogFont.lfFaceName),
5203               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
5204               elf.elfLogFont.lfCharSet, type, debugstr_w(elf.elfScript),
5205               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
5206               ntm.ntmTm.ntmFlags);
5207         /* release section before callback (FIXME) */
5208         LeaveCriticalSection( &freetype_cs );
5209         if (!proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam)) return FALSE;
5210         EnterCriticalSection( &freetype_cs );
5211     }
5212     return TRUE;
5213 }
5214
5215 /*************************************************************
5216  * freetype_EnumFonts
5217  */
5218 static BOOL freetype_EnumFonts( PHYSDEV dev, LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam )
5219 {
5220     Family *family;
5221     Face *face;
5222     const struct list *family_elem_ptr, *face_list, *face_elem_ptr;
5223     LOGFONTW lf;
5224     struct enum_charset_list enum_charsets;
5225
5226     if (!plf)
5227     {
5228         lf.lfCharSet = DEFAULT_CHARSET;
5229         lf.lfPitchAndFamily = 0;
5230         lf.lfFaceName[0] = 0;
5231         plf = &lf;
5232     }
5233
5234     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
5235
5236     create_enum_charset_list(plf->lfCharSet, &enum_charsets);
5237
5238     GDI_CheckNotLock();
5239     EnterCriticalSection( &freetype_cs );
5240     if(plf->lfFaceName[0]) {
5241         FontSubst *psub;
5242         psub = get_font_subst(&font_subst_list, plf->lfFaceName, plf->lfCharSet);
5243
5244         if(psub) {
5245             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
5246                   debugstr_w(psub->to.name));
5247             lf = *plf;
5248             strcpyW(lf.lfFaceName, psub->to.name);
5249             plf = &lf;
5250         }
5251
5252         LIST_FOR_EACH(family_elem_ptr, &font_list) {
5253             family = LIST_ENTRY(family_elem_ptr, Family, entry);
5254             if(family_matches(family, plf)) {
5255                 face_list = get_face_list_from_family(family);
5256                 LIST_FOR_EACH(face_elem_ptr, face_list) {
5257                     face = LIST_ENTRY(face_elem_ptr, Face, entry);
5258                     if (!face_matches(family->FamilyName, face, plf)) continue;
5259                     if (!enum_face_charsets(family, face, &enum_charsets, proc, lparam)) return FALSE;
5260                 }
5261             }
5262         }
5263     } else {
5264         LIST_FOR_EACH(family_elem_ptr, &font_list) {
5265             family = LIST_ENTRY(family_elem_ptr, Family, entry);
5266             face_list = get_face_list_from_family(family);
5267             face_elem_ptr = list_head(face_list);
5268             face = LIST_ENTRY(face_elem_ptr, Face, entry);
5269             if (!enum_face_charsets(family, face, &enum_charsets, proc, lparam)) return FALSE;
5270         }
5271     }
5272     LeaveCriticalSection( &freetype_cs );
5273     return TRUE;
5274 }
5275
5276 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
5277 {
5278     pt->x.value = vec->x >> 6;
5279     pt->x.fract = (vec->x & 0x3f) << 10;
5280     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
5281     pt->y.value = vec->y >> 6;
5282     pt->y.fract = (vec->y & 0x3f) << 10;
5283     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
5284     return;
5285 }
5286
5287 /***************************************************
5288  * According to the MSDN documentation on WideCharToMultiByte,
5289  * certain codepages cannot set the default_used parameter.
5290  * This returns TRUE if the codepage can set that parameter, false else
5291  * so that calls to WideCharToMultiByte don't fail with ERROR_INVALID_PARAMETER
5292  */
5293 static BOOL codepage_sets_default_used(UINT codepage)
5294 {
5295    switch (codepage)
5296    {
5297        case CP_UTF7:
5298        case CP_UTF8:
5299        case CP_SYMBOL:
5300            return FALSE;
5301        default:
5302            return TRUE;
5303    }
5304 }
5305
5306 /*
5307  * GSUB Table handling functions
5308  */
5309
5310 static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph)
5311 {
5312     const GSUB_CoverageFormat1* cf1;
5313
5314     cf1 = table;
5315
5316     if (GET_BE_WORD(cf1->CoverageFormat) == 1)
5317     {
5318         int count = GET_BE_WORD(cf1->GlyphCount);
5319         int i;
5320         TRACE("Coverage Format 1, %i glyphs\n",count);
5321         for (i = 0; i < count; i++)
5322             if (glyph == GET_BE_WORD(cf1->GlyphArray[i]))
5323                 return i;
5324         return -1;
5325     }
5326     else if (GET_BE_WORD(cf1->CoverageFormat) == 2)
5327     {
5328         const GSUB_CoverageFormat2* cf2;
5329         int i;
5330         int count;
5331         cf2 = (const GSUB_CoverageFormat2*)cf1;
5332
5333         count = GET_BE_WORD(cf2->RangeCount);
5334         TRACE("Coverage Format 2, %i ranges\n",count);
5335         for (i = 0; i < count; i++)
5336         {
5337             if (glyph < GET_BE_WORD(cf2->RangeRecord[i].Start))
5338                 return -1;
5339             if ((glyph >= GET_BE_WORD(cf2->RangeRecord[i].Start)) &&
5340                 (glyph <= GET_BE_WORD(cf2->RangeRecord[i].End)))
5341             {
5342                 return (GET_BE_WORD(cf2->RangeRecord[i].StartCoverageIndex) +
5343                     glyph - GET_BE_WORD(cf2->RangeRecord[i].Start));
5344             }
5345         }
5346         return -1;
5347     }
5348     else
5349         ERR("Unknown CoverageFormat %i\n",GET_BE_WORD(cf1->CoverageFormat));
5350
5351     return -1;
5352 }
5353
5354 static const GSUB_Script* GSUB_get_script_table( const GSUB_Header* header, const char* tag)
5355 {
5356     const GSUB_ScriptList *script;
5357     const GSUB_Script *deflt = NULL;
5358     int i;
5359     script = (const GSUB_ScriptList*)((const BYTE*)header + GET_BE_WORD(header->ScriptList));
5360
5361     TRACE("%i scripts in this font\n",GET_BE_WORD(script->ScriptCount));
5362     for (i = 0; i < GET_BE_WORD(script->ScriptCount); i++)
5363     {
5364         const GSUB_Script *scr;
5365         int offset;
5366
5367         offset = GET_BE_WORD(script->ScriptRecord[i].Script);
5368         scr = (const GSUB_Script*)((const BYTE*)script + offset);
5369
5370         if (strncmp(script->ScriptRecord[i].ScriptTag, tag,4)==0)
5371             return scr;
5372         if (strncmp(script->ScriptRecord[i].ScriptTag, "dflt",4)==0)
5373             deflt = scr;
5374     }
5375     return deflt;
5376 }
5377
5378 static const GSUB_LangSys* GSUB_get_lang_table( const GSUB_Script* script, const char* tag)
5379 {
5380     int i;
5381     int offset;
5382     const GSUB_LangSys *Lang;
5383
5384     TRACE("Deflang %x, LangCount %i\n",GET_BE_WORD(script->DefaultLangSys), GET_BE_WORD(script->LangSysCount));
5385
5386     for (i = 0; i < GET_BE_WORD(script->LangSysCount) ; i++)
5387     {
5388         offset = GET_BE_WORD(script->LangSysRecord[i].LangSys);
5389         Lang = (const GSUB_LangSys*)((const BYTE*)script + offset);
5390
5391         if ( strncmp(script->LangSysRecord[i].LangSysTag,tag,4)==0)
5392             return Lang;
5393     }
5394     offset = GET_BE_WORD(script->DefaultLangSys);
5395     if (offset)
5396     {
5397         Lang = (const GSUB_LangSys*)((const BYTE*)script + offset);
5398         return Lang;
5399     }
5400     return NULL;
5401 }
5402
5403 static const GSUB_Feature * GSUB_get_feature(const GSUB_Header *header, const GSUB_LangSys *lang, const char* tag)
5404 {
5405     int i;
5406     const GSUB_FeatureList *feature;
5407     feature = (const GSUB_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList));
5408
5409     TRACE("%i features\n",GET_BE_WORD(lang->FeatureCount));
5410     for (i = 0; i < GET_BE_WORD(lang->FeatureCount); i++)
5411     {
5412         int index = GET_BE_WORD(lang->FeatureIndex[i]);
5413         if (strncmp(feature->FeatureRecord[index].FeatureTag,tag,4)==0)
5414         {
5415             const GSUB_Feature *feat;
5416             feat = (const GSUB_Feature*)((const BYTE*)feature + GET_BE_WORD(feature->FeatureRecord[index].Feature));
5417             return feat;
5418         }
5419     }
5420     return NULL;
5421 }
5422
5423 static FT_UInt GSUB_apply_feature(const GSUB_Header * header, const GSUB_Feature* feature, UINT glyph)
5424 {
5425     int i;
5426     int offset;
5427     const GSUB_LookupList *lookup;
5428     lookup = (const GSUB_LookupList*)((const BYTE*)header + GET_BE_WORD(header->LookupList));
5429
5430     TRACE("%i lookups\n", GET_BE_WORD(feature->LookupCount));
5431     for (i = 0; i < GET_BE_WORD(feature->LookupCount); i++)
5432     {
5433         const GSUB_LookupTable *look;
5434         offset = GET_BE_WORD(lookup->Lookup[GET_BE_WORD(feature->LookupListIndex[i])]);
5435         look = (const GSUB_LookupTable*)((const BYTE*)lookup + offset);
5436         TRACE("type %i, flag %x, subtables %i\n",GET_BE_WORD(look->LookupType),GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount));
5437         if (GET_BE_WORD(look->LookupType) != 1)
5438             FIXME("We only handle SubType 1\n");
5439         else
5440         {
5441             int j;
5442
5443             for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
5444             {
5445                 const GSUB_SingleSubstFormat1 *ssf1;
5446                 offset = GET_BE_WORD(look->SubTable[j]);
5447                 ssf1 = (const GSUB_SingleSubstFormat1*)((const BYTE*)look+offset);
5448                 if (GET_BE_WORD(ssf1->SubstFormat) == 1)
5449                 {
5450                     int offset = GET_BE_WORD(ssf1->Coverage);
5451                     TRACE("  subtype 1, delta %i\n", GET_BE_WORD(ssf1->DeltaGlyphID));
5452                     if (GSUB_is_glyph_covered((const BYTE*)ssf1+offset, glyph) != -1)
5453                     {
5454                         TRACE("  Glyph 0x%x ->",glyph);
5455                         glyph += GET_BE_WORD(ssf1->DeltaGlyphID);
5456                         TRACE(" 0x%x\n",glyph);
5457                     }
5458                 }
5459                 else
5460                 {
5461                     const GSUB_SingleSubstFormat2 *ssf2;
5462                     INT index;
5463                     INT offset;
5464
5465                     ssf2 = (const GSUB_SingleSubstFormat2 *)ssf1;
5466                     offset = GET_BE_WORD(ssf1->Coverage);
5467                     TRACE("  subtype 2,  glyph count %i\n", GET_BE_WORD(ssf2->GlyphCount));
5468                     index = GSUB_is_glyph_covered((const BYTE*)ssf2+offset, glyph);
5469                     TRACE("  Coverage index %i\n",index);
5470                     if (index != -1)
5471                     {
5472                         TRACE("    Glyph is 0x%x ->",glyph);
5473                         glyph = GET_BE_WORD(ssf2->Substitute[index]);
5474                         TRACE("0x%x\n",glyph);
5475                     }
5476                 }
5477             }
5478         }
5479     }
5480     return glyph;
5481 }
5482
5483 static const char* get_opentype_script(const GdiFont *font)
5484 {
5485     /*
5486      * I am not sure if this is the correct way to generate our script tag
5487      */
5488
5489     switch (font->charset)
5490     {
5491         case ANSI_CHARSET: return "latn";
5492         case BALTIC_CHARSET: return "latn"; /* ?? */
5493         case CHINESEBIG5_CHARSET: return "hani";
5494         case EASTEUROPE_CHARSET: return "latn"; /* ?? */
5495         case GB2312_CHARSET: return "hani";
5496         case GREEK_CHARSET: return "grek";
5497         case HANGUL_CHARSET: return "hang";
5498         case RUSSIAN_CHARSET: return "cyrl";
5499         case SHIFTJIS_CHARSET: return "kana";
5500         case TURKISH_CHARSET: return "latn"; /* ?? */
5501         case VIETNAMESE_CHARSET: return "latn";
5502         case JOHAB_CHARSET: return "latn"; /* ?? */
5503         case ARABIC_CHARSET: return "arab";
5504         case HEBREW_CHARSET: return "hebr";
5505         case THAI_CHARSET: return "thai";
5506         default: return "latn";
5507     }
5508 }
5509
5510 static FT_UInt get_GSUB_vert_glyph(const GdiFont *font, UINT glyph)
5511 {
5512     const GSUB_Header *header;
5513     const GSUB_Script *script;
5514     const GSUB_LangSys *language;
5515     const GSUB_Feature *feature;
5516
5517     if (!font->GSUB_Table)
5518         return glyph;
5519
5520     header = font->GSUB_Table;
5521
5522     script = GSUB_get_script_table(header, get_opentype_script(font));
5523     if (!script)
5524     {
5525         TRACE("Script not found\n");
5526         return glyph;
5527     }
5528     language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
5529     if (!language)
5530     {
5531         TRACE("Language not found\n");
5532         return glyph;
5533     }
5534     feature  =  GSUB_get_feature(header, language, "vrt2");
5535     if (!feature)
5536         feature  =  GSUB_get_feature(header, language, "vert");
5537     if (!feature)
5538     {
5539         TRACE("vrt2/vert feature not found\n");
5540         return glyph;
5541     }
5542     return GSUB_apply_feature(header, feature, glyph);
5543 }
5544
5545 static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph)
5546 {
5547     FT_UInt glyphId;
5548
5549     if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
5550         WCHAR wc = (WCHAR)glyph;
5551         BOOL default_used;
5552         BOOL *default_used_pointer;
5553         FT_UInt ret;
5554         char buf;
5555         default_used_pointer = NULL;
5556         default_used = FALSE;
5557         if (codepage_sets_default_used(font->codepage))
5558             default_used_pointer = &default_used;
5559         if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
5560             ret = 0;
5561         else
5562             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
5563         TRACE("%04x (%02x) -> ret %d def_used %d\n", glyph, buf, ret, default_used);
5564         return ret;
5565     }
5566
5567     if(font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
5568     {
5569         if (glyph < 0x100) glyph += 0xf000;
5570         /* there is a number of old pre-Unicode "broken" TTFs, which
5571            do have symbols at U+00XX instead of U+f0XX */
5572         if (!(glyphId = pFT_Get_Char_Index(font->ft_face, glyph)))
5573             glyphId = pFT_Get_Char_Index(font->ft_face, glyph-0xf000);
5574     }
5575     else glyphId = pFT_Get_Char_Index(font->ft_face, glyph);
5576
5577     return glyphId;
5578 }
5579
5580 /*************************************************************
5581  * freetype_GetGlyphIndices
5582  */
5583 static DWORD freetype_GetGlyphIndices( PHYSDEV dev, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags )
5584 {
5585     struct freetype_physdev *physdev = get_freetype_dev( dev );
5586     int i;
5587     WORD default_char;
5588     BOOL got_default = FALSE;
5589
5590     if (!physdev->font)
5591     {
5592         dev = GET_NEXT_PHYSDEV( dev, pGetGlyphIndices );
5593         return dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
5594     }
5595
5596     if (flags & GGI_MARK_NONEXISTING_GLYPHS)
5597     {
5598         default_char = 0xffff;  /* XP would use 0x1f for bitmap fonts */
5599         got_default = TRUE;
5600     }
5601
5602     GDI_CheckNotLock();
5603     EnterCriticalSection( &freetype_cs );
5604
5605     for(i = 0; i < count; i++)
5606     {
5607         pgi[i] = get_glyph_index(physdev->font, lpstr[i]);
5608         if  (pgi[i] == 0)
5609         {
5610             if (!got_default)
5611             {
5612                 if (FT_IS_SFNT(physdev->font->ft_face))
5613                 {
5614                     TT_OS2 *pOS2 = pFT_Get_Sfnt_Table(physdev->font->ft_face, ft_sfnt_os2);
5615                     default_char = (pOS2->usDefaultChar ? get_glyph_index(physdev->font, pOS2->usDefaultChar) : 0);
5616                 }
5617                 else
5618                 {
5619                     TEXTMETRICW textm;
5620                     get_text_metrics(physdev->font, &textm);
5621                     default_char = textm.tmDefaultChar;
5622                 }
5623                 got_default = TRUE;
5624             }
5625             pgi[i] = default_char;
5626         }
5627     }
5628     LeaveCriticalSection( &freetype_cs );
5629     return count;
5630 }
5631
5632 static inline BOOL is_identity_FMAT2(const FMAT2 *matrix)
5633 {
5634     static const FMAT2 identity = { 1.0, 0.0, 0.0, 1.0 };
5635     return !memcmp(matrix, &identity, sizeof(FMAT2));
5636 }
5637
5638 static inline BOOL is_identity_MAT2(const MAT2 *matrix)
5639 {
5640     static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
5641     return !memcmp(matrix, &identity, sizeof(MAT2));
5642 }
5643
5644 static inline BYTE get_max_level( UINT format )
5645 {
5646     switch( format )
5647     {
5648     case GGO_GRAY2_BITMAP: return 4;
5649     case GGO_GRAY4_BITMAP: return 16;
5650     case GGO_GRAY8_BITMAP: return 64;
5651     }
5652     return 255;
5653 }
5654
5655 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5656
5657 static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
5658                                LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
5659                                const MAT2* lpmat)
5660 {
5661     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
5662     FT_Face ft_face = incoming_font->ft_face;
5663     GdiFont *font = incoming_font;
5664     FT_UInt glyph_index;
5665     DWORD width, height, pitch, needed = 0;
5666     FT_Bitmap ft_bitmap;
5667     FT_Error err;
5668     INT left, right, top = 0, bottom = 0, adv, lsb, bbx;
5669     FT_Angle angle = 0;
5670     FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
5671     double widthRatio = 1.0;
5672     FT_Matrix transMat = identityMat;
5673     FT_Matrix transMatUnrotated;
5674     BOOL needsTransform = FALSE;
5675     BOOL tategaki = (font->GSUB_Table != NULL);
5676     UINT original_index;
5677
5678     TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
5679           buflen, buf, lpmat);
5680
5681     TRACE("font transform %f %f %f %f\n",
5682           font->font_desc.matrix.eM11, font->font_desc.matrix.eM12,
5683           font->font_desc.matrix.eM21, font->font_desc.matrix.eM22);
5684
5685     if(format & GGO_GLYPH_INDEX) {
5686         glyph_index = get_GSUB_vert_glyph(incoming_font,glyph);
5687         original_index = glyph;
5688         format &= ~GGO_GLYPH_INDEX;
5689     } else {
5690         get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index);
5691         ft_face = font->ft_face;
5692         original_index = glyph_index;
5693     }
5694
5695     if(format & GGO_UNHINTED) {
5696         load_flags |= FT_LOAD_NO_HINTING;
5697         format &= ~GGO_UNHINTED;
5698     }
5699
5700     /* tategaki never appears to happen to lower glyph index */
5701     if (glyph_index < TATEGAKI_LOWER_BOUND )
5702         tategaki = FALSE;
5703
5704     if(original_index >= font->gmsize * GM_BLOCK_SIZE) {
5705         font->gmsize = (original_index / GM_BLOCK_SIZE + 1);
5706         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
5707                                font->gmsize * sizeof(GM*));
5708     } else {
5709         if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL &&
5710             FONT_GM(font,original_index)->init && is_identity_MAT2(lpmat))
5711         {
5712             *lpgm = FONT_GM(font,original_index)->gm;
5713             TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
5714                   wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
5715                   lpgm->gmCellIncX, lpgm->gmCellIncY);
5716             return 1; /* FIXME */
5717         }
5718     }
5719
5720     if (!font->gm[original_index / GM_BLOCK_SIZE])
5721         font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
5722
5723     /* Scaling factor */
5724     if (font->aveWidth)
5725     {
5726         TEXTMETRICW tm;
5727
5728         get_text_metrics(font, &tm);
5729
5730         widthRatio = (double)font->aveWidth;
5731         widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
5732     }
5733     else
5734         widthRatio = font->scale_y;
5735
5736     /* Scaling transform */
5737     if (widthRatio != 1.0 || font->scale_y != 1.0)
5738     {
5739         FT_Matrix scaleMat;
5740         scaleMat.xx = FT_FixedFromFloat(widthRatio);
5741         scaleMat.xy = 0;
5742         scaleMat.yx = 0;
5743         scaleMat.yy = FT_FixedFromFloat(font->scale_y);
5744
5745         pFT_Matrix_Multiply(&scaleMat, &transMat);
5746         needsTransform = TRUE;
5747     }
5748
5749     /* Slant transform */
5750     if (font->fake_italic) {
5751         FT_Matrix slantMat;
5752         
5753         slantMat.xx = (1 << 16);
5754         slantMat.xy = ((1 << 16) >> 2);
5755         slantMat.yx = 0;
5756         slantMat.yy = (1 << 16);
5757         pFT_Matrix_Multiply(&slantMat, &transMat);
5758         needsTransform = TRUE;
5759     }
5760
5761     /* Rotation transform */
5762     transMatUnrotated = transMat;
5763     if(font->orientation && !tategaki) {
5764         FT_Matrix rotationMat;
5765         FT_Vector vecAngle;
5766         angle = FT_FixedFromFloat((double)font->orientation / 10.0);
5767         pFT_Vector_Unit(&vecAngle, angle);
5768         rotationMat.xx = vecAngle.x;
5769         rotationMat.xy = -vecAngle.y;
5770         rotationMat.yx = -rotationMat.xy;
5771         rotationMat.yy = rotationMat.xx;
5772         
5773         pFT_Matrix_Multiply(&rotationMat, &transMat);
5774         needsTransform = TRUE;
5775     }
5776
5777     /* World transform */
5778     if (!is_identity_FMAT2(&font->font_desc.matrix))
5779     {
5780         FT_Matrix worldMat;
5781         worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11);
5782         worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM12);
5783         worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM21);
5784         worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22);
5785         pFT_Matrix_Multiply(&worldMat, &transMat);
5786         pFT_Matrix_Multiply(&worldMat, &transMatUnrotated);
5787         needsTransform = TRUE;
5788     }
5789
5790     /* Extra transformation specified by caller */
5791     if (!is_identity_MAT2(lpmat))
5792     {
5793         FT_Matrix extraMat;
5794         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
5795         extraMat.xy = FT_FixedFromFIXED(lpmat->eM12);
5796         extraMat.yx = FT_FixedFromFIXED(lpmat->eM21);
5797         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
5798         pFT_Matrix_Multiply(&extraMat, &transMat);
5799         pFT_Matrix_Multiply(&extraMat, &transMatUnrotated);
5800         needsTransform = TRUE;
5801     }
5802
5803     if (needsTransform || (format == GGO_NATIVE || format == GGO_BEZIER ||
5804                            format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
5805                            format == GGO_GRAY8_BITMAP))
5806     {
5807         load_flags |= FT_LOAD_NO_BITMAP;
5808     }
5809
5810     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
5811
5812     if(err) {
5813         WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
5814         return GDI_ERROR;
5815     }
5816
5817     if(!needsTransform) {
5818         left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64;
5819         right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64;
5820         adv = (INT)(ft_face->glyph->metrics.horiAdvance + 63) >> 6;
5821
5822         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
5823         bottom = (ft_face->glyph->metrics.horiBearingY -
5824                   ft_face->glyph->metrics.height) & -64;
5825         lpgm->gmCellIncX = adv;
5826         lpgm->gmCellIncY = 0;
5827     } else {
5828         INT xc, yc;
5829         FT_Vector vec;
5830
5831         left = right = 0;
5832
5833         for(xc = 0; xc < 2; xc++) {
5834             for(yc = 0; yc < 2; yc++) {
5835                 vec.x = (ft_face->glyph->metrics.horiBearingX +
5836                   xc * ft_face->glyph->metrics.width);
5837                 vec.y = ft_face->glyph->metrics.horiBearingY -
5838                   yc * ft_face->glyph->metrics.height;
5839                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
5840                 pFT_Vector_Transform(&vec, &transMat);
5841                 if(xc == 0 && yc == 0) {
5842                     left = right = vec.x;
5843                     top = bottom = vec.y;
5844                 } else {
5845                     if(vec.x < left) left = vec.x;
5846                     else if(vec.x > right) right = vec.x;
5847                     if(vec.y < bottom) bottom = vec.y;
5848                     else if(vec.y > top) top = vec.y;
5849                 }
5850             }
5851         }
5852         left = left & -64;
5853         right = (right + 63) & -64;
5854         bottom = bottom & -64;
5855         top = (top + 63) & -64;
5856
5857         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
5858         vec.x = ft_face->glyph->metrics.horiAdvance;
5859         vec.y = 0;
5860         pFT_Vector_Transform(&vec, &transMat);
5861         lpgm->gmCellIncX = (vec.x+63) >> 6;
5862         lpgm->gmCellIncY = -((vec.y+63) >> 6);
5863
5864         vec.x = ft_face->glyph->metrics.horiAdvance;
5865         vec.y = 0;
5866         pFT_Vector_Transform(&vec, &transMatUnrotated);
5867         adv = (vec.x+63) >> 6;
5868     }
5869
5870     lsb = left >> 6;
5871     bbx = (right - left) >> 6;
5872     lpgm->gmBlackBoxX = (right - left) >> 6;
5873     lpgm->gmBlackBoxY = (top - bottom) >> 6;
5874     lpgm->gmptGlyphOrigin.x = left >> 6;
5875     lpgm->gmptGlyphOrigin.y = top >> 6;
5876
5877     TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
5878           wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
5879           lpgm->gmCellIncX, lpgm->gmCellIncY);
5880
5881     if ((format == GGO_METRICS || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
5882         is_identity_MAT2(lpmat)) /* don't cache custom transforms */
5883     {
5884         FONT_GM(font,original_index)->gm = *lpgm;
5885         FONT_GM(font,original_index)->adv = adv;
5886         FONT_GM(font,original_index)->lsb = lsb;
5887         FONT_GM(font,original_index)->bbx = bbx;
5888         FONT_GM(font,original_index)->init = TRUE;
5889     }
5890
5891     if(format == GGO_METRICS)
5892     {
5893         return 1; /* FIXME */
5894     }
5895
5896     if(ft_face->glyph->format != ft_glyph_format_outline &&
5897        (format == GGO_NATIVE || format == GGO_BEZIER))
5898     {
5899         TRACE("loaded a bitmap\n");
5900         return GDI_ERROR;
5901     }
5902
5903     switch(format) {
5904     case GGO_BITMAP:
5905         width = lpgm->gmBlackBoxX;
5906         height = lpgm->gmBlackBoxY;
5907         pitch = ((width + 31) >> 5) << 2;
5908         needed = pitch * height;
5909
5910         if(!buf || !buflen) break;
5911
5912         switch(ft_face->glyph->format) {
5913         case ft_glyph_format_bitmap:
5914           {
5915             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
5916             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
5917             INT h = ft_face->glyph->bitmap.rows;
5918             while(h--) {
5919                 memcpy(dst, src, w);
5920                 src += ft_face->glyph->bitmap.pitch;
5921                 dst += pitch;
5922             }
5923             break;
5924           }
5925
5926         case ft_glyph_format_outline:
5927             ft_bitmap.width = width;
5928             ft_bitmap.rows = height;
5929             ft_bitmap.pitch = pitch;
5930             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
5931             ft_bitmap.buffer = buf;
5932
5933             if(needsTransform)
5934                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
5935
5936             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
5937
5938             /* Note: FreeType will only set 'black' bits for us. */
5939             memset(buf, 0, needed);
5940             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
5941             break;
5942
5943         default:
5944             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
5945             return GDI_ERROR;
5946         }
5947         break;
5948
5949     case GGO_GRAY2_BITMAP:
5950     case GGO_GRAY4_BITMAP:
5951     case GGO_GRAY8_BITMAP:
5952     case WINE_GGO_GRAY16_BITMAP:
5953       {
5954         unsigned int max_level, row, col;
5955         BYTE *start, *ptr;
5956
5957         width = lpgm->gmBlackBoxX;
5958         height = lpgm->gmBlackBoxY;
5959         pitch = (width + 3) / 4 * 4;
5960         needed = pitch * height;
5961
5962         if(!buf || !buflen) break;
5963
5964         max_level = get_max_level( format );
5965
5966         switch(ft_face->glyph->format) {
5967         case ft_glyph_format_bitmap:
5968           {
5969             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
5970             INT h = ft_face->glyph->bitmap.rows;
5971             INT x;
5972             memset( buf, 0, needed );
5973             while(h--) {
5974                 for(x = 0; x < pitch && x < ft_face->glyph->bitmap.width; x++)
5975                     if (src[x / 8] & masks[x % 8]) dst[x] = max_level;
5976                 src += ft_face->glyph->bitmap.pitch;
5977                 dst += pitch;
5978             }
5979             return needed;
5980           }
5981         case ft_glyph_format_outline:
5982           {
5983             ft_bitmap.width = width;
5984             ft_bitmap.rows = height;
5985             ft_bitmap.pitch = pitch;
5986             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
5987             ft_bitmap.buffer = buf;
5988
5989             if(needsTransform)
5990                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
5991
5992             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
5993
5994             memset(ft_bitmap.buffer, 0, buflen);
5995
5996             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
5997
5998             if (max_level != 255)
5999             {
6000                 for (row = 0, start = buf; row < height; row++)
6001                 {
6002                     for (col = 0, ptr = start; col < width; col++, ptr++)
6003                         *ptr = (((int)*ptr) * max_level + 128) / 256;
6004                     start += pitch;
6005                 }
6006             }
6007             return needed;
6008           }
6009
6010         default:
6011             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
6012             return GDI_ERROR;
6013         }
6014         break;
6015       }
6016
6017     case WINE_GGO_HRGB_BITMAP:
6018     case WINE_GGO_HBGR_BITMAP:
6019     case WINE_GGO_VRGB_BITMAP:
6020     case WINE_GGO_VBGR_BITMAP:
6021 #ifdef HAVE_FREETYPE_FTLCDFIL_H
6022       {
6023         switch (ft_face->glyph->format)
6024         {
6025         case FT_GLYPH_FORMAT_BITMAP:
6026           {
6027             BYTE *src, *dst;
6028             INT src_pitch, x;
6029
6030             width  = lpgm->gmBlackBoxX;
6031             height = lpgm->gmBlackBoxY;
6032             pitch  = width * 4;
6033             needed = pitch * height;
6034
6035             if (!buf || !buflen) break;
6036
6037             memset(buf, 0, buflen);
6038             dst = buf;
6039             src = ft_face->glyph->bitmap.buffer;
6040             src_pitch = ft_face->glyph->bitmap.pitch;
6041
6042             height = min( height, ft_face->glyph->bitmap.rows );
6043             while ( height-- )
6044             {
6045                 for (x = 0; x < width && x < ft_face->glyph->bitmap.width; x++)
6046                 {
6047                     if ( src[x / 8] & masks[x % 8] )
6048                         ((unsigned int *)dst)[x] = ~0u;
6049                 }
6050                 src += src_pitch;
6051                 dst += pitch;
6052             }
6053
6054             break;
6055           }
6056
6057         case FT_GLYPH_FORMAT_OUTLINE:
6058           {
6059             unsigned int *dst;
6060             BYTE *src;
6061             INT x, src_pitch, src_width, src_height, rgb_interval, hmul, vmul;
6062             INT x_shift, y_shift;
6063             BOOL rgb;
6064             FT_LcdFilter lcdfilter = FT_LCD_FILTER_DEFAULT;
6065             FT_Render_Mode render_mode =
6066                 (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_HBGR_BITMAP)?
6067                     FT_RENDER_MODE_LCD: FT_RENDER_MODE_LCD_V;
6068
6069             if ( lcdfilter == FT_LCD_FILTER_DEFAULT || lcdfilter == FT_LCD_FILTER_LIGHT )
6070             {
6071                 if ( render_mode == FT_RENDER_MODE_LCD)
6072                 {
6073                     lpgm->gmBlackBoxX += 2;
6074                     lpgm->gmptGlyphOrigin.x -= 1;
6075                 }
6076                 else
6077                 {
6078                     lpgm->gmBlackBoxY += 2;
6079                     lpgm->gmptGlyphOrigin.y += 1;
6080                 }
6081             }
6082
6083             width  = lpgm->gmBlackBoxX;
6084             height = lpgm->gmBlackBoxY;
6085             pitch  = width * 4;
6086             needed = pitch * height;
6087
6088             if (!buf || !buflen) break;
6089
6090             memset(buf, 0, buflen);
6091             dst = buf;
6092             rgb = (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_VRGB_BITMAP);
6093
6094             if ( needsTransform )
6095                 pFT_Outline_Transform (&ft_face->glyph->outline, &transMat);
6096
6097             if ( pFT_Library_SetLcdFilter )
6098                 pFT_Library_SetLcdFilter( library, lcdfilter );
6099             pFT_Render_Glyph (ft_face->glyph, render_mode);
6100
6101             src = ft_face->glyph->bitmap.buffer;
6102             src_pitch = ft_face->glyph->bitmap.pitch;
6103             src_width = ft_face->glyph->bitmap.width;
6104             src_height = ft_face->glyph->bitmap.rows;
6105
6106             if ( render_mode == FT_RENDER_MODE_LCD)
6107             {
6108                 rgb_interval = 1;
6109                 hmul = 3;
6110                 vmul = 1;
6111             }
6112             else
6113             {
6114                 rgb_interval = src_pitch;
6115                 hmul = 1;
6116                 vmul = 3;
6117             }
6118
6119             x_shift = ft_face->glyph->bitmap_left - lpgm->gmptGlyphOrigin.x;
6120             if ( x_shift < 0 ) x_shift = 0;
6121             if ( x_shift + (src_width / hmul) > width )
6122                 x_shift = width - (src_width / hmul);
6123
6124             y_shift = lpgm->gmptGlyphOrigin.y - ft_face->glyph->bitmap_top;
6125             if ( y_shift < 0 ) y_shift = 0;
6126             if ( y_shift + (src_height / vmul) > height )
6127                 y_shift = height - (src_height / vmul);
6128
6129             dst += x_shift + y_shift * ( pitch / 4 );
6130             while ( src_height )
6131             {
6132                 for ( x = 0; x < src_width / hmul; x++ )
6133                 {
6134                     if ( rgb )
6135                     {
6136                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 0] << 16) |
6137                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
6138                                  ((unsigned int)src[hmul * x + rgb_interval * 2] <<  0) |
6139                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
6140                     }
6141                     else
6142                     {
6143                         dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 2] << 16) |
6144                                  ((unsigned int)src[hmul * x + rgb_interval * 1] <<  8) |
6145                                  ((unsigned int)src[hmul * x + rgb_interval * 0] <<  0) |
6146                                  ((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
6147                     }
6148                 }
6149                 src += src_pitch * vmul;
6150                 dst += pitch / 4;
6151                 src_height -= vmul;
6152             }
6153
6154             break;
6155           }
6156
6157         default:
6158             FIXME ("loaded glyph format %x\n", ft_face->glyph->format);
6159             return GDI_ERROR;
6160         }
6161
6162         break;
6163       }
6164 #else
6165       return GDI_ERROR;
6166 #endif
6167
6168     case GGO_NATIVE:
6169       {
6170         int contour, point = 0, first_pt;
6171         FT_Outline *outline = &ft_face->glyph->outline;
6172         TTPOLYGONHEADER *pph;
6173         TTPOLYCURVE *ppc;
6174         DWORD pph_start, cpfx, type;
6175
6176         if(buflen == 0) buf = NULL;
6177
6178         if (needsTransform && buf) {
6179                 pFT_Outline_Transform(outline, &transMat);
6180         }
6181
6182         for(contour = 0; contour < outline->n_contours; contour++) {
6183             pph_start = needed;
6184             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
6185             first_pt = point;
6186             if(buf) {
6187                 pph->dwType = TT_POLYGON_TYPE;
6188                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
6189             }
6190             needed += sizeof(*pph);
6191             point++;
6192             while(point <= outline->contours[contour]) {
6193                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
6194                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
6195                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
6196                 cpfx = 0;
6197                 do {
6198                     if(buf)
6199                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
6200                     cpfx++;
6201                     point++;
6202                 } while(point <= outline->contours[contour] &&
6203                         (outline->tags[point] & FT_Curve_Tag_On) ==
6204                         (outline->tags[point-1] & FT_Curve_Tag_On));
6205                 /* At the end of a contour Windows adds the start point, but
6206                    only for Beziers */
6207                 if(point > outline->contours[contour] &&
6208                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
6209                     if(buf)
6210                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
6211                     cpfx++;
6212                 } else if(point <= outline->contours[contour] &&
6213                           outline->tags[point] & FT_Curve_Tag_On) {
6214                   /* add closing pt for bezier */
6215                     if(buf)
6216                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
6217                     cpfx++;
6218                     point++;
6219                 }
6220                 if(buf) {
6221                     ppc->wType = type;
6222                     ppc->cpfx = cpfx;
6223                 }
6224                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
6225             }
6226             if(buf)
6227                 pph->cb = needed - pph_start;
6228         }
6229         break;
6230       }
6231     case GGO_BEZIER:
6232       {
6233         /* Convert the quadratic Beziers to cubic Beziers.
6234            The parametric eqn for a cubic Bezier is, from PLRM:
6235            r(t) = at^3 + bt^2 + ct + r0
6236            with the control points:
6237            r1 = r0 + c/3
6238            r2 = r1 + (c + b)/3
6239            r3 = r0 + c + b + a
6240
6241            A quadratic Bezier has the form:
6242            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
6243
6244            So equating powers of t leads to:
6245            r1 = 2/3 p1 + 1/3 p0
6246            r2 = 2/3 p1 + 1/3 p2
6247            and of course r0 = p0, r3 = p2
6248         */
6249
6250         int contour, point = 0, first_pt;
6251         FT_Outline *outline = &ft_face->glyph->outline;
6252         TTPOLYGONHEADER *pph;
6253         TTPOLYCURVE *ppc;
6254         DWORD pph_start, cpfx, type;
6255         FT_Vector cubic_control[4];
6256         if(buflen == 0) buf = NULL;
6257
6258         if (needsTransform && buf) {
6259                 pFT_Outline_Transform(outline, &transMat);
6260         }
6261
6262         for(contour = 0; contour < outline->n_contours; contour++) {
6263             pph_start = needed;
6264             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
6265             first_pt = point;
6266             if(buf) {
6267                 pph->dwType = TT_POLYGON_TYPE;
6268                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
6269             }
6270             needed += sizeof(*pph);
6271             point++;
6272             while(point <= outline->contours[contour]) {
6273                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
6274                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
6275                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
6276                 cpfx = 0;
6277                 do {
6278                     if(type == TT_PRIM_LINE) {
6279                         if(buf)
6280                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
6281                         cpfx++;
6282                         point++;
6283                     } else {
6284                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
6285                          so cpfx = 3n */
6286
6287                       /* FIXME: Possible optimization in endpoint calculation
6288                          if there are two consecutive curves */
6289                         cubic_control[0] = outline->points[point-1];
6290                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
6291                             cubic_control[0].x += outline->points[point].x + 1;
6292                             cubic_control[0].y += outline->points[point].y + 1;
6293                             cubic_control[0].x >>= 1;
6294                             cubic_control[0].y >>= 1;
6295                         }
6296                         if(point+1 > outline->contours[contour])
6297                             cubic_control[3] = outline->points[first_pt];
6298                         else {
6299                             cubic_control[3] = outline->points[point+1];
6300                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
6301                                 cubic_control[3].x += outline->points[point].x + 1;
6302                                 cubic_control[3].y += outline->points[point].y + 1;
6303                                 cubic_control[3].x >>= 1;
6304                                 cubic_control[3].y >>= 1;
6305                             }
6306                         }
6307                         /* r1 = 1/3 p0 + 2/3 p1
6308                            r2 = 1/3 p2 + 2/3 p1 */
6309                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
6310                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
6311                         cubic_control[2] = cubic_control[1];
6312                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
6313                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
6314                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
6315                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
6316                         if(buf) {
6317                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
6318                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
6319                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
6320                         }
6321                         cpfx += 3;
6322                         point++;
6323                     }
6324                 } while(point <= outline->contours[contour] &&
6325                         (outline->tags[point] & FT_Curve_Tag_On) ==
6326                         (outline->tags[point-1] & FT_Curve_Tag_On));
6327                 /* At the end of a contour Windows adds the start point,
6328                    but only for Beziers and we've already done that.
6329                 */
6330                 if(point <= outline->contours[contour] &&
6331                    outline->tags[point] & FT_Curve_Tag_On) {
6332                   /* This is the closing pt of a bezier, but we've already
6333                      added it, so just inc point and carry on */
6334                     point++;
6335                 }
6336                 if(buf) {
6337                     ppc->wType = type;
6338                     ppc->cpfx = cpfx;
6339                 }
6340                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
6341             }
6342             if(buf)
6343                 pph->cb = needed - pph_start;
6344         }
6345         break;
6346       }
6347
6348     default:
6349         FIXME("Unsupported format %d\n", format);
6350         return GDI_ERROR;
6351     }
6352     return needed;
6353 }
6354
6355 static BOOL get_bitmap_text_metrics(GdiFont *font)
6356 {
6357     FT_Face ft_face = font->ft_face;
6358     FT_WinFNT_HeaderRec winfnt_header;
6359     const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller); 
6360     font->potm = HeapAlloc(GetProcessHeap(), 0, size);
6361     font->potm->otmSize = size;
6362
6363 #define TM font->potm->otmTextMetrics
6364     if(!pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
6365     {
6366         TM.tmHeight = winfnt_header.pixel_height;
6367         TM.tmAscent = winfnt_header.ascent;
6368         TM.tmDescent = TM.tmHeight - TM.tmAscent;
6369         TM.tmInternalLeading = winfnt_header.internal_leading;
6370         TM.tmExternalLeading = winfnt_header.external_leading;
6371         TM.tmAveCharWidth = winfnt_header.avg_width;
6372         TM.tmMaxCharWidth = winfnt_header.max_width;
6373         TM.tmWeight = winfnt_header.weight;
6374         TM.tmOverhang = 0;
6375         TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
6376         TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
6377         TM.tmFirstChar = winfnt_header.first_char;
6378         TM.tmLastChar = winfnt_header.last_char;
6379         TM.tmDefaultChar = winfnt_header.default_char + winfnt_header.first_char;
6380         TM.tmBreakChar = winfnt_header.break_char + winfnt_header.first_char;
6381         TM.tmItalic = winfnt_header.italic;
6382         TM.tmUnderlined = font->underline;
6383         TM.tmStruckOut = font->strikeout;
6384         TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
6385         TM.tmCharSet = winfnt_header.charset;
6386     }
6387     else
6388     {
6389         TM.tmAscent = ft_face->size->metrics.ascender >> 6;
6390         TM.tmDescent = -ft_face->size->metrics.descender >> 6;
6391         TM.tmHeight = TM.tmAscent + TM.tmDescent;
6392         TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
6393         TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
6394         TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
6395         TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
6396         TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
6397         TM.tmOverhang = 0;
6398         TM.tmDigitizedAspectX = 96; /* FIXME */
6399         TM.tmDigitizedAspectY = 96; /* FIXME */
6400         TM.tmFirstChar = 1;
6401         TM.tmLastChar = 255;
6402         TM.tmDefaultChar = 32;
6403         TM.tmBreakChar = 32;
6404         TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
6405         TM.tmUnderlined = font->underline;
6406         TM.tmStruckOut = font->strikeout;
6407         /* NB inverted meaning of TMPF_FIXED_PITCH */
6408         TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
6409         TM.tmCharSet = font->charset;
6410     }
6411 #undef TM
6412
6413     return TRUE;
6414 }
6415
6416
6417 static void scale_font_metrics(const GdiFont *font, LPTEXTMETRICW ptm)
6418 {
6419     double scale_x, scale_y;
6420
6421     if (font->aveWidth)
6422     {
6423         scale_x = (double)font->aveWidth;
6424         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
6425     }
6426     else
6427         scale_x = font->scale_y;
6428
6429     scale_x *= fabs(font->font_desc.matrix.eM11);
6430     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
6431
6432 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
6433 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
6434
6435     SCALE_Y(ptm->tmHeight);
6436     SCALE_Y(ptm->tmAscent);
6437     SCALE_Y(ptm->tmDescent);
6438     SCALE_Y(ptm->tmInternalLeading);
6439     SCALE_Y(ptm->tmExternalLeading);
6440     SCALE_Y(ptm->tmOverhang);
6441
6442     SCALE_X(ptm->tmAveCharWidth);
6443     SCALE_X(ptm->tmMaxCharWidth);
6444
6445 #undef SCALE_X
6446 #undef SCALE_Y
6447 }
6448
6449 static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *potm)
6450 {
6451     double scale_x, scale_y;
6452
6453     if (font->aveWidth)
6454     {
6455         scale_x = (double)font->aveWidth;
6456         scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
6457     }
6458     else
6459         scale_x = font->scale_y;
6460
6461     scale_x *= fabs(font->font_desc.matrix.eM11);
6462     scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22);
6463
6464     scale_font_metrics(font, &potm->otmTextMetrics);
6465
6466 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
6467 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
6468
6469     SCALE_Y(potm->otmAscent);
6470     SCALE_Y(potm->otmDescent);
6471     SCALE_Y(potm->otmLineGap);
6472     SCALE_Y(potm->otmsCapEmHeight);
6473     SCALE_Y(potm->otmsXHeight);
6474     SCALE_Y(potm->otmrcFontBox.top);
6475     SCALE_Y(potm->otmrcFontBox.bottom);
6476     SCALE_X(potm->otmrcFontBox.left);
6477     SCALE_X(potm->otmrcFontBox.right);
6478     SCALE_Y(potm->otmMacAscent);
6479     SCALE_Y(potm->otmMacDescent);
6480     SCALE_Y(potm->otmMacLineGap);
6481     SCALE_X(potm->otmptSubscriptSize.x);
6482     SCALE_Y(potm->otmptSubscriptSize.y);
6483     SCALE_X(potm->otmptSubscriptOffset.x);
6484     SCALE_Y(potm->otmptSubscriptOffset.y);
6485     SCALE_X(potm->otmptSuperscriptSize.x);
6486     SCALE_Y(potm->otmptSuperscriptSize.y);
6487     SCALE_X(potm->otmptSuperscriptOffset.x);
6488     SCALE_Y(potm->otmptSuperscriptOffset.y);
6489     SCALE_Y(potm->otmsStrikeoutSize);
6490     SCALE_Y(potm->otmsStrikeoutPosition);
6491     SCALE_Y(potm->otmsUnderscoreSize);
6492     SCALE_Y(potm->otmsUnderscorePosition);
6493
6494 #undef SCALE_X
6495 #undef SCALE_Y
6496 }
6497
6498 static BOOL get_text_metrics(GdiFont *font, LPTEXTMETRICW ptm)
6499 {
6500     if(!font->potm)
6501     {
6502         if (!get_outline_text_metrics(font) && !get_bitmap_text_metrics(font)) return FALSE;
6503
6504         /* Make sure that the font has sane width/height ratio */
6505         if (font->aveWidth)
6506         {
6507             if ((font->aveWidth + font->potm->otmTextMetrics.tmHeight - 1) / font->potm->otmTextMetrics.tmHeight > 100)
6508             {
6509                 WARN("Ignoring too large font->aveWidth %d\n", font->aveWidth);
6510                 font->aveWidth = 0;
6511             }
6512         }
6513     }
6514     *ptm = font->potm->otmTextMetrics;
6515     scale_font_metrics(font, ptm);
6516     return TRUE;
6517 }
6518
6519 static BOOL face_has_symbol_charmap(FT_Face ft_face)
6520 {
6521     int i;
6522
6523     for(i = 0; i < ft_face->num_charmaps; i++)
6524     {
6525         if(ft_face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
6526             return TRUE;
6527     }
6528     return FALSE;
6529 }
6530
6531 static BOOL get_outline_text_metrics(GdiFont *font)
6532 {
6533     BOOL ret = FALSE;
6534     FT_Face ft_face = font->ft_face;
6535     UINT needed, lenfam, lensty;
6536     TT_OS2 *pOS2;
6537     TT_HoriHeader *pHori;
6538     TT_Postscript *pPost;
6539     FT_Fixed x_scale, y_scale;
6540     WCHAR *family_nameW, *style_nameW;
6541     static const WCHAR spaceW[] = {' ', '\0'};
6542     char *cp;
6543     INT ascent, descent;
6544
6545     TRACE("font=%p\n", font);
6546
6547     if(!FT_IS_SCALABLE(ft_face))
6548         return FALSE;
6549
6550     needed = sizeof(*font->potm);
6551
6552     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
6553     family_nameW = strdupW(font->name);
6554
6555     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
6556       * sizeof(WCHAR);
6557     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
6558     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
6559                         style_nameW, lensty/sizeof(WCHAR));
6560
6561     /* These names should be read from the TT name table */
6562
6563     /* length of otmpFamilyName */
6564     needed += lenfam;
6565
6566     /* length of otmpFaceName */
6567     if ((ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) == 0) {
6568       needed += lenfam; /* just the family name */
6569     } else {
6570       needed += lenfam + lensty; /* family + " " + style */
6571     }
6572
6573     /* length of otmpStyleName */
6574     needed += lensty;
6575
6576     /* length of otmpFullName */
6577     needed += lenfam + lensty;
6578
6579
6580     x_scale = ft_face->size->metrics.x_scale;
6581     y_scale = ft_face->size->metrics.y_scale;
6582
6583     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
6584     if(!pOS2) {
6585         FIXME("Can't find OS/2 table - not TT font?\n");
6586         goto end;
6587     }
6588
6589     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
6590     if(!pHori) {
6591         FIXME("Can't find HHEA table - not TT font?\n");
6592         goto end;
6593     }
6594
6595     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
6596
6597     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",
6598           pOS2->usWinAscent, pOS2->usWinDescent,
6599           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
6600           ft_face->ascender, ft_face->descender, ft_face->height,
6601           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
6602           ft_face->bbox.yMax, ft_face->bbox.yMin);
6603
6604     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
6605     font->potm->otmSize = needed;
6606
6607 #define TM font->potm->otmTextMetrics
6608
6609     if(pOS2->usWinAscent + pOS2->usWinDescent == 0) {
6610         ascent = pHori->Ascender;
6611         descent = -pHori->Descender;
6612     } else {
6613         ascent = pOS2->usWinAscent;
6614         descent = pOS2->usWinDescent;
6615     }
6616
6617     if(font->yMax) {
6618         TM.tmAscent = font->yMax;
6619         TM.tmDescent = -font->yMin;
6620         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
6621     } else {
6622         TM.tmAscent = (pFT_MulFix(ascent, y_scale) + 32) >> 6;
6623         TM.tmDescent = (pFT_MulFix(descent, y_scale) + 32) >> 6;
6624         TM.tmInternalLeading = (pFT_MulFix(ascent + descent
6625                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
6626     }
6627
6628     TM.tmHeight = TM.tmAscent + TM.tmDescent;
6629
6630     /* MSDN says:
6631      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
6632     */
6633     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
6634                  ((ascent + descent) -
6635                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
6636
6637     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
6638     if (TM.tmAveCharWidth == 0) {
6639         TM.tmAveCharWidth = 1; 
6640     }
6641     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
6642     TM.tmWeight = FW_REGULAR;
6643     if (font->fake_bold)
6644         TM.tmWeight = FW_BOLD;
6645     else
6646     {
6647         if (ft_face->style_flags & FT_STYLE_FLAG_BOLD)
6648         {
6649             if (pOS2->usWeightClass > FW_MEDIUM)
6650                 TM.tmWeight = pOS2->usWeightClass;
6651         }
6652         else if (pOS2->usWeightClass <= FW_MEDIUM)
6653             TM.tmWeight = pOS2->usWeightClass;
6654     }
6655     TM.tmOverhang = 0;
6656     TM.tmDigitizedAspectX = 300;
6657     TM.tmDigitizedAspectY = 300;
6658     /* It appears that for fonts with SYMBOL_CHARSET Windows always sets
6659      * symbol range to 0 - f0ff
6660      */
6661
6662     if (face_has_symbol_charmap(ft_face) || (pOS2->usFirstCharIndex >= 0xf000 && pOS2->usFirstCharIndex < 0xf100))
6663     {
6664         TM.tmFirstChar = 0;
6665         switch(GetACP())
6666         {
6667         case 1257: /* Baltic */
6668             TM.tmLastChar = 0xf8fd;
6669             break;
6670         default:
6671             TM.tmLastChar = 0xf0ff;
6672         }
6673         TM.tmBreakChar = 0x20;
6674         TM.tmDefaultChar = 0x1f;
6675     }
6676     else
6677     {
6678         TM.tmFirstChar = pOS2->usFirstCharIndex; /* Should be the first char in the cmap */
6679         TM.tmLastChar = pOS2->usLastCharIndex;   /* Should be min(cmap_last, os2_last) */
6680
6681         if(pOS2->usFirstCharIndex <= 1)
6682             TM.tmBreakChar = pOS2->usFirstCharIndex + 2;
6683         else if (pOS2->usFirstCharIndex > 0xff)
6684             TM.tmBreakChar = 0x20;
6685         else
6686             TM.tmBreakChar = pOS2->usFirstCharIndex;
6687         TM.tmDefaultChar = TM.tmBreakChar - 1;
6688     }
6689     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
6690     TM.tmUnderlined = font->underline;
6691     TM.tmStruckOut = font->strikeout;
6692
6693     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
6694     if(!FT_IS_FIXED_WIDTH(ft_face) &&
6695        (pOS2->version == 0xFFFFU || 
6696         pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED))
6697         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
6698     else
6699         TM.tmPitchAndFamily = 0;
6700
6701     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX])
6702     {
6703     case PAN_FAMILY_SCRIPT:
6704         TM.tmPitchAndFamily |= FF_SCRIPT;
6705         break;
6706
6707     case PAN_FAMILY_DECORATIVE:
6708         TM.tmPitchAndFamily |= FF_DECORATIVE;
6709         break;
6710
6711     case PAN_ANY:
6712     case PAN_NO_FIT:
6713     case PAN_FAMILY_TEXT_DISPLAY:
6714     case PAN_FAMILY_PICTORIAL: /* symbol fonts get treated as if they were text */
6715                                /* which is clearly not what the panose spec says. */
6716     default:
6717         if(TM.tmPitchAndFamily == 0 || /* fixed */
6718            pOS2->panose[PAN_PROPORTION_INDEX] == PAN_PROP_MONOSPACED)
6719             TM.tmPitchAndFamily = FF_MODERN;
6720         else
6721         {
6722             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX])
6723             {
6724             case PAN_ANY:
6725             case PAN_NO_FIT:
6726             default:
6727                 TM.tmPitchAndFamily |= FF_DONTCARE;
6728                 break;
6729
6730             case PAN_SERIF_COVE:
6731             case PAN_SERIF_OBTUSE_COVE:
6732             case PAN_SERIF_SQUARE_COVE:
6733             case PAN_SERIF_OBTUSE_SQUARE_COVE:
6734             case PAN_SERIF_SQUARE:
6735             case PAN_SERIF_THIN:
6736             case PAN_SERIF_BONE:
6737             case PAN_SERIF_EXAGGERATED:
6738             case PAN_SERIF_TRIANGLE:
6739                 TM.tmPitchAndFamily |= FF_ROMAN;
6740                 break;
6741
6742             case PAN_SERIF_NORMAL_SANS:
6743             case PAN_SERIF_OBTUSE_SANS:
6744             case PAN_SERIF_PERP_SANS:
6745             case PAN_SERIF_FLARED:
6746             case PAN_SERIF_ROUNDED:
6747                 TM.tmPitchAndFamily |= FF_SWISS;
6748                 break;
6749             }
6750         }
6751         break;
6752     }
6753
6754     if(FT_IS_SCALABLE(ft_face))
6755         TM.tmPitchAndFamily |= TMPF_VECTOR;
6756
6757     if(FT_IS_SFNT(ft_face))
6758     {
6759         if (font->ntmFlags & NTM_PS_OPENTYPE)
6760             TM.tmPitchAndFamily |= TMPF_DEVICE;
6761         else
6762             TM.tmPitchAndFamily |= TMPF_TRUETYPE;
6763     }
6764
6765     TM.tmCharSet = font->charset;
6766
6767     font->potm->otmFiller = 0;
6768     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
6769     font->potm->otmfsSelection = pOS2->fsSelection;
6770     font->potm->otmfsType = pOS2->fsType;
6771     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
6772     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
6773     font->potm->otmItalicAngle = 0; /* POST table */
6774     font->potm->otmEMSquare = ft_face->units_per_EM;
6775     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
6776     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
6777     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
6778     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
6779     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
6780     font->potm->otmrcFontBox.left = (pFT_MulFix(ft_face->bbox.xMin, x_scale) + 32) >> 6;
6781     font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6;
6782     font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6;
6783     font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6;
6784     font->potm->otmMacAscent = TM.tmAscent;
6785     font->potm->otmMacDescent = -TM.tmDescent;
6786     font->potm->otmMacLineGap = font->potm->otmLineGap;
6787     font->potm->otmusMinimumPPEM = 0; /* TT Header */
6788     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
6789     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
6790     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
6791     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
6792     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
6793     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
6794     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
6795     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
6796     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
6797     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
6798     if(!pPost) {
6799         font->potm->otmsUnderscoreSize = 0;
6800         font->potm->otmsUnderscorePosition = 0;
6801     } else {
6802         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
6803         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
6804     }
6805 #undef TM
6806
6807     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
6808     cp = (char*)font->potm + sizeof(*font->potm);
6809     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
6810     strcpyW((WCHAR*)cp, family_nameW);
6811     cp += lenfam;
6812     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
6813     strcpyW((WCHAR*)cp, style_nameW);
6814     cp += lensty;
6815     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
6816     strcpyW((WCHAR*)cp, family_nameW);
6817     if (ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) {
6818         strcatW((WCHAR*)cp, spaceW);
6819         strcatW((WCHAR*)cp, style_nameW);
6820         cp += lenfam + lensty;
6821     } else
6822         cp += lenfam;
6823     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
6824     strcpyW((WCHAR*)cp, family_nameW);
6825     strcatW((WCHAR*)cp, spaceW);
6826     strcatW((WCHAR*)cp, style_nameW);
6827     ret = TRUE;
6828
6829 end:
6830     HeapFree(GetProcessHeap(), 0, style_nameW);
6831     HeapFree(GetProcessHeap(), 0, family_nameW);
6832     return ret;
6833 }
6834
6835 /*************************************************************
6836  * freetype_GetGlyphOutline
6837  */
6838 static DWORD freetype_GetGlyphOutline( PHYSDEV dev, UINT glyph, UINT format,
6839                                        LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf, const MAT2 *lpmat )
6840 {
6841     struct freetype_physdev *physdev = get_freetype_dev( dev );
6842     DWORD ret;
6843
6844     if (!physdev->font)
6845     {
6846         dev = GET_NEXT_PHYSDEV( dev, pGetGlyphOutline );
6847         return dev->funcs->pGetGlyphOutline( dev, glyph, format, lpgm, buflen, buf, lpmat );
6848     }
6849
6850     GDI_CheckNotLock();
6851     EnterCriticalSection( &freetype_cs );
6852     ret = get_glyph_outline( physdev->font, glyph, format, lpgm, buflen, buf, lpmat );
6853     LeaveCriticalSection( &freetype_cs );
6854     return ret;
6855 }
6856
6857 /*************************************************************
6858  * freetype_GetTextMetrics
6859  */
6860 static BOOL freetype_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
6861 {
6862     struct freetype_physdev *physdev = get_freetype_dev( dev );
6863     BOOL ret;
6864
6865     if (!physdev->font)
6866     {
6867         dev = GET_NEXT_PHYSDEV( dev, pGetTextMetrics );
6868         return dev->funcs->pGetTextMetrics( dev, metrics );
6869     }
6870
6871     GDI_CheckNotLock();
6872     EnterCriticalSection( &freetype_cs );
6873     ret = get_text_metrics( physdev->font, metrics );
6874     LeaveCriticalSection( &freetype_cs );
6875     return ret;
6876 }
6877
6878 /*************************************************************
6879  * freetype_GetOutlineTextMetrics
6880  */
6881 static UINT freetype_GetOutlineTextMetrics( PHYSDEV dev, UINT cbSize, OUTLINETEXTMETRICW *potm )
6882 {
6883     struct freetype_physdev *physdev = get_freetype_dev( dev );
6884     UINT ret = 0;
6885
6886     if (!physdev->font)
6887     {
6888         dev = GET_NEXT_PHYSDEV( dev, pGetOutlineTextMetrics );
6889         return dev->funcs->pGetOutlineTextMetrics( dev, cbSize, potm );
6890     }
6891
6892     TRACE("font=%p\n", physdev->font);
6893
6894     if (!FT_IS_SCALABLE( physdev->font->ft_face )) return 0;
6895
6896     GDI_CheckNotLock();
6897     EnterCriticalSection( &freetype_cs );
6898
6899     if (physdev->font->potm || get_outline_text_metrics( physdev->font ))
6900     {
6901         if(cbSize >= physdev->font->potm->otmSize)
6902         {
6903             memcpy(potm, physdev->font->potm, physdev->font->potm->otmSize);
6904             scale_outline_font_metrics(physdev->font, potm);
6905         }
6906         ret = physdev->font->potm->otmSize;
6907     }
6908     LeaveCriticalSection( &freetype_cs );
6909     return ret;
6910 }
6911
6912 static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
6913 {
6914     HFONTLIST *hfontlist;
6915     child->font = alloc_font();
6916     child->font->ft_face = OpenFontFace(child->font, child->face, 0, -font->ppem);
6917     if(!child->font->ft_face)
6918     {
6919         free_font(child->font);
6920         child->font = NULL;
6921         return FALSE;
6922     }
6923
6924     child->font->font_desc = font->font_desc;
6925     child->font->ntmFlags = child->face->ntmFlags;
6926     child->font->orientation = font->orientation;
6927     child->font->scale_y = font->scale_y;
6928     hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
6929     hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
6930     child->font->name = strdupW(child->face->family->FamilyName);
6931     list_add_head(&child->font->hfontlist, &hfontlist->entry);
6932     child->font->base_font = font;
6933     list_add_head(&child_font_list, &child->font->entry);
6934     TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
6935     return TRUE;
6936 }
6937
6938 static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph)
6939 {
6940     FT_UInt g;
6941     CHILD_FONT *child_font;
6942
6943     if(font->base_font)
6944         font = font->base_font;
6945
6946     *linked_font = font;
6947
6948     if((*glyph = get_glyph_index(font, c)))
6949     {
6950         *glyph = get_GSUB_vert_glyph(font, *glyph);
6951         return TRUE;
6952     }
6953
6954     LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
6955     {
6956         if(!child_font->font)
6957             if(!load_child_font(font, child_font))
6958                 continue;
6959
6960         if(!child_font->font->ft_face)
6961             continue;
6962         g = get_glyph_index(child_font->font, c);
6963         g = get_GSUB_vert_glyph(child_font->font, g);
6964         if(g)
6965         {
6966             *glyph = g;
6967             *linked_font = child_font->font;
6968             return TRUE;
6969         }
6970     }
6971     return FALSE;
6972 }
6973
6974 /*************************************************************
6975  * freetype_GetCharWidth
6976  */
6977 static BOOL freetype_GetCharWidth( PHYSDEV dev, UINT firstChar, UINT lastChar, LPINT buffer )
6978 {
6979     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
6980     UINT c;
6981     GLYPHMETRICS gm;
6982     FT_UInt glyph_index;
6983     GdiFont *linked_font;
6984     struct freetype_physdev *physdev = get_freetype_dev( dev );
6985
6986     if (!physdev->font)
6987     {
6988         dev = GET_NEXT_PHYSDEV( dev, pGetCharWidth );
6989         return dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
6990     }
6991
6992     TRACE("%p, %d, %d, %p\n", physdev->font, firstChar, lastChar, buffer);
6993
6994     GDI_CheckNotLock();
6995     EnterCriticalSection( &freetype_cs );
6996     for(c = firstChar; c <= lastChar; c++) {
6997         get_glyph_index_linked(physdev->font, c, &linked_font, &glyph_index);
6998         get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
6999                           &gm, 0, NULL, &identity);
7000         buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv;
7001     }
7002     LeaveCriticalSection( &freetype_cs );
7003     return TRUE;
7004 }
7005
7006 /*************************************************************
7007  * freetype_GetCharABCWidths
7008  */
7009 static BOOL freetype_GetCharABCWidths( PHYSDEV dev, UINT firstChar, UINT lastChar, LPABC buffer )
7010 {
7011     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7012     UINT c;
7013     GLYPHMETRICS gm;
7014     FT_UInt glyph_index;
7015     GdiFont *linked_font;
7016     struct freetype_physdev *physdev = get_freetype_dev( dev );
7017
7018     if (!physdev->font)
7019     {
7020         dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidths );
7021         return dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, buffer );
7022     }
7023
7024     TRACE("%p, %d, %d, %p\n", physdev->font, firstChar, lastChar, buffer);
7025
7026     GDI_CheckNotLock();
7027     EnterCriticalSection( &freetype_cs );
7028
7029     for(c = firstChar; c <= lastChar; c++) {
7030         get_glyph_index_linked(physdev->font, c, &linked_font, &glyph_index);
7031         get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
7032                           &gm, 0, NULL, &identity);
7033         buffer[c - firstChar].abcA = FONT_GM(linked_font,glyph_index)->lsb;
7034         buffer[c - firstChar].abcB = FONT_GM(linked_font,glyph_index)->bbx;
7035         buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb -
7036             FONT_GM(linked_font,glyph_index)->bbx;
7037     }
7038     LeaveCriticalSection( &freetype_cs );
7039     return TRUE;
7040 }
7041
7042 /*************************************************************
7043  * freetype_GetCharABCWidthsI
7044  */
7045 static BOOL freetype_GetCharABCWidthsI( PHYSDEV dev, UINT firstChar, UINT count, LPWORD pgi, LPABC buffer )
7046 {
7047     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7048     UINT c;
7049     GLYPHMETRICS gm;
7050     FT_UInt glyph_index;
7051     GdiFont *linked_font;
7052     struct freetype_physdev *physdev = get_freetype_dev( dev );
7053
7054     if (!physdev->font)
7055     {
7056         dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidthsI );
7057         return dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, buffer );
7058     }
7059
7060     if(!FT_HAS_HORIZONTAL(physdev->font->ft_face))
7061         return FALSE;
7062
7063     GDI_CheckNotLock();
7064     EnterCriticalSection( &freetype_cs );
7065
7066     get_glyph_index_linked(physdev->font, 'a', &linked_font, &glyph_index);
7067     if (!pgi)
7068         for(c = firstChar; c < firstChar+count; c++) {
7069             get_glyph_outline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
7070                               &gm, 0, NULL, &identity);
7071             buffer[c - firstChar].abcA = FONT_GM(linked_font,c)->lsb;
7072             buffer[c - firstChar].abcB = FONT_GM(linked_font,c)->bbx;
7073             buffer[c - firstChar].abcC = FONT_GM(linked_font,c)->adv - FONT_GM(linked_font,c)->lsb
7074                 - FONT_GM(linked_font,c)->bbx;
7075         }
7076     else
7077         for(c = 0; c < count; c++) {
7078             get_glyph_outline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
7079                               &gm, 0, NULL, &identity);
7080             buffer[c].abcA = FONT_GM(linked_font,pgi[c])->lsb;
7081             buffer[c].abcB = FONT_GM(linked_font,pgi[c])->bbx;
7082             buffer[c].abcC = FONT_GM(linked_font,pgi[c])->adv
7083                 - FONT_GM(linked_font,pgi[c])->lsb - FONT_GM(linked_font,pgi[c])->bbx;
7084         }
7085
7086     LeaveCriticalSection( &freetype_cs );
7087     return TRUE;
7088 }
7089
7090 /*************************************************************
7091  * freetype_GetTextExtentExPoint
7092  */
7093 static BOOL freetype_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR wstr, INT count,
7094                                            INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
7095 {
7096     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7097     INT idx;
7098     INT nfit = 0, ext;
7099     GLYPHMETRICS gm;
7100     TEXTMETRICW tm;
7101     FT_UInt glyph_index;
7102     GdiFont *linked_font;
7103     struct freetype_physdev *physdev = get_freetype_dev( dev );
7104
7105     if (!physdev->font)
7106     {
7107         dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPoint );
7108         return dev->funcs->pGetTextExtentExPoint( dev, wstr, count, max_ext, pnfit, dxs, size );
7109     }
7110
7111     TRACE("%p, %s, %d, %d, %p\n", physdev->font, debugstr_wn(wstr, count), count, max_ext, size);
7112
7113     GDI_CheckNotLock();
7114     EnterCriticalSection( &freetype_cs );
7115
7116     size->cx = 0;
7117     get_text_metrics( physdev->font, &tm );
7118     size->cy = tm.tmHeight;
7119
7120     for(idx = 0; idx < count; idx++) {
7121         get_glyph_index_linked( physdev->font, wstr[idx], &linked_font, &glyph_index );
7122         get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
7123                           &gm, 0, NULL, &identity);
7124         size->cx += FONT_GM(linked_font,glyph_index)->adv;
7125         ext = size->cx;
7126         if (! pnfit || ext <= max_ext) {
7127             ++nfit;
7128             if (dxs)
7129                 dxs[idx] = ext;
7130         }
7131     }
7132
7133     if (pnfit)
7134         *pnfit = nfit;
7135
7136     LeaveCriticalSection( &freetype_cs );
7137     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
7138     return TRUE;
7139 }
7140
7141 /*************************************************************
7142  * freetype_GetTextExtentExPointI
7143  */
7144 static BOOL freetype_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, INT count,
7145                                             INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size )
7146 {
7147     static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
7148     INT idx;
7149     INT nfit = 0, ext;
7150     GLYPHMETRICS gm;
7151     TEXTMETRICW tm;
7152     struct freetype_physdev *physdev = get_freetype_dev( dev );
7153
7154     if (!physdev->font)
7155     {
7156         dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPointI );
7157         return dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, pnfit, dxs, size );
7158     }
7159
7160     TRACE("%p, %p, %d, %d, %p\n", physdev->font, indices, count, max_ext, size);
7161
7162     GDI_CheckNotLock();
7163     EnterCriticalSection( &freetype_cs );
7164
7165     size->cx = 0;
7166     get_text_metrics(physdev->font, &tm);
7167     size->cy = tm.tmHeight;
7168
7169     for(idx = 0; idx < count; idx++) {
7170         get_glyph_outline(physdev->font, indices[idx], GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &identity);
7171         size->cx += FONT_GM(physdev->font,indices[idx])->adv;
7172         ext = size->cx;
7173         if (! pnfit || ext <= max_ext) {
7174             ++nfit;
7175             if (dxs)
7176                 dxs[idx] = ext;
7177         }
7178     }
7179
7180     if (pnfit)
7181         *pnfit = nfit;
7182
7183     LeaveCriticalSection( &freetype_cs );
7184     TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit);
7185     return TRUE;
7186 }
7187
7188 /*************************************************************
7189  * freetype_GetFontData
7190  */
7191 static DWORD freetype_GetFontData( PHYSDEV dev, DWORD table, DWORD offset, LPVOID buf, DWORD cbData )
7192 {
7193     struct freetype_physdev *physdev = get_freetype_dev( dev );
7194
7195     if (!physdev->font)
7196     {
7197         dev = GET_NEXT_PHYSDEV( dev, pGetFontData );
7198         return dev->funcs->pGetFontData( dev, table, offset, buf, cbData );
7199     }
7200
7201     TRACE("font=%p, table=%c%c%c%c, offset=0x%x, buf=%p, cbData=0x%x\n",
7202           physdev->font, LOBYTE(LOWORD(table)), HIBYTE(LOWORD(table)),
7203           LOBYTE(HIWORD(table)), HIBYTE(HIWORD(table)), offset, buf, cbData);
7204
7205     return get_font_data( physdev->font, table, offset, buf, cbData );
7206 }
7207
7208 /*************************************************************
7209  * freetype_GetTextFace
7210  */
7211 static INT freetype_GetTextFace( PHYSDEV dev, INT count, LPWSTR str )
7212 {
7213     INT n;
7214     struct freetype_physdev *physdev = get_freetype_dev( dev );
7215
7216     if (!physdev->font)
7217     {
7218         dev = GET_NEXT_PHYSDEV( dev, pGetTextFace );
7219         return dev->funcs->pGetTextFace( dev, count, str );
7220     }
7221
7222     n = strlenW(physdev->font->name) + 1;
7223     if (str)
7224     {
7225         lstrcpynW(str, physdev->font->name, count);
7226         n = min(count, n);
7227     }
7228     return n;
7229 }
7230
7231 /*************************************************************
7232  * freetype_GetTextCharsetInfo
7233  */
7234 static UINT freetype_GetTextCharsetInfo( PHYSDEV dev, LPFONTSIGNATURE fs, DWORD flags )
7235 {
7236     struct freetype_physdev *physdev = get_freetype_dev( dev );
7237
7238     if (!physdev->font)
7239     {
7240         dev = GET_NEXT_PHYSDEV( dev, pGetTextCharsetInfo );
7241         return dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
7242     }
7243     if (fs) *fs = physdev->font->fs;
7244     return physdev->font->charset;
7245 }
7246
7247 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
7248 {
7249     GdiFont *font = dc->gdiFont, *linked_font;
7250     struct list *first_hfont;
7251     BOOL ret;
7252
7253     GDI_CheckNotLock();
7254     EnterCriticalSection( &freetype_cs );
7255     ret = get_glyph_index_linked(font, c, &linked_font, glyph);
7256     TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
7257     if(font == linked_font)
7258         *new_hfont = dc->hFont;
7259     else
7260     {
7261         first_hfont = list_head(&linked_font->hfontlist);
7262         *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
7263     }
7264     LeaveCriticalSection( &freetype_cs );
7265     return ret;
7266 }
7267     
7268 /* Retrieve a list of supported Unicode ranges for a given font.
7269  * Can be called with NULL gs to calculate the buffer size. Returns
7270  * the number of ranges found.
7271  */
7272 static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
7273 {
7274     DWORD num_ranges = 0;
7275
7276     if (face->charmap->encoding == FT_ENCODING_UNICODE)
7277     {
7278         FT_UInt glyph_code;
7279         FT_ULong char_code, char_code_prev;
7280
7281         glyph_code = 0;
7282         char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
7283
7284         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
7285                face->num_glyphs, glyph_code, char_code);
7286
7287         if (!glyph_code) return 0;
7288
7289         if (gs)
7290         {
7291             gs->ranges[0].wcLow = (USHORT)char_code;
7292             gs->ranges[0].cGlyphs = 0;
7293             gs->cGlyphsSupported = 0;
7294         }
7295
7296         num_ranges = 1;
7297         while (glyph_code)
7298         {
7299             if (char_code < char_code_prev)
7300             {
7301                 ERR("expected increasing char code from FT_Get_Next_Char\n");
7302                 return 0;
7303             }
7304             if (char_code - char_code_prev > 1)
7305             {
7306                 num_ranges++;
7307                 if (gs)
7308                 {
7309                     gs->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
7310                     gs->ranges[num_ranges - 1].cGlyphs = 1;
7311                     gs->cGlyphsSupported++;
7312                 }
7313             }
7314             else if (gs)
7315             {
7316                 gs->ranges[num_ranges - 1].cGlyphs++;
7317                 gs->cGlyphsSupported++;
7318             }
7319             char_code_prev = char_code;
7320             char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
7321         }
7322     }
7323     else
7324         FIXME("encoding %u not supported\n", face->charmap->encoding);
7325
7326     return num_ranges;
7327 }
7328
7329 /*************************************************************
7330  * freetype_GetFontUnicodeRanges
7331  */
7332 static DWORD freetype_GetFontUnicodeRanges( PHYSDEV dev, LPGLYPHSET glyphset )
7333 {
7334     struct freetype_physdev *physdev = get_freetype_dev( dev );
7335     DWORD size, num_ranges;
7336
7337     if (!physdev->font)
7338     {
7339         dev = GET_NEXT_PHYSDEV( dev, pGetFontUnicodeRanges );
7340         return dev->funcs->pGetFontUnicodeRanges( dev, glyphset );
7341     }
7342
7343     num_ranges = get_font_unicode_ranges(physdev->font->ft_face, glyphset);
7344     size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
7345     if (glyphset)
7346     {
7347         glyphset->cbThis = size;
7348         glyphset->cRanges = num_ranges;
7349         glyphset->flAccel = 0;
7350     }
7351     return size;
7352 }
7353
7354 /*************************************************************
7355  * freetype_FontIsLinked
7356  */
7357 static BOOL freetype_FontIsLinked( PHYSDEV dev )
7358 {
7359     struct freetype_physdev *physdev = get_freetype_dev( dev );
7360     BOOL ret;
7361
7362     if (!physdev->font)
7363     {
7364         dev = GET_NEXT_PHYSDEV( dev, pFontIsLinked );
7365         return dev->funcs->pFontIsLinked( dev );
7366     }
7367
7368     GDI_CheckNotLock();
7369     EnterCriticalSection( &freetype_cs );
7370     ret = !list_empty(&physdev->font->child_fonts);
7371     LeaveCriticalSection( &freetype_cs );
7372     return ret;
7373 }
7374
7375 static BOOL is_hinting_enabled(void)
7376 {
7377     /* Use the >= 2.2.0 function if available */
7378     if(pFT_Get_TrueType_Engine_Type)
7379     {
7380         FT_TrueTypeEngineType type = pFT_Get_TrueType_Engine_Type(library);
7381         return type == FT_TRUETYPE_ENGINE_TYPE_PATENTED;
7382     }
7383 #ifdef FT_DRIVER_HAS_HINTER
7384     else
7385     {
7386         FT_Module mod;
7387
7388         /* otherwise if we've been compiled with < 2.2.0 headers 
7389            use the internal macro */
7390         mod = pFT_Get_Module(library, "truetype");
7391         if(mod && FT_DRIVER_HAS_HINTER(mod))
7392             return TRUE;
7393     }
7394 #endif
7395
7396     return FALSE;
7397 }
7398
7399 static BOOL is_subpixel_rendering_enabled( void )
7400 {
7401 #ifdef HAVE_FREETYPE_FTLCDFIL_H
7402     return pFT_Library_SetLcdFilter &&
7403            pFT_Library_SetLcdFilter( NULL, 0 ) != FT_Err_Unimplemented_Feature;
7404 #else
7405     return FALSE;
7406 #endif
7407 }
7408
7409 /*************************************************************************
7410  *             GetRasterizerCaps   (GDI32.@)
7411  */
7412 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
7413 {
7414     static int hinting = -1;
7415     static int subpixel = -1;
7416
7417     if(hinting == -1)
7418     {
7419         hinting = is_hinting_enabled();
7420         TRACE("hinting is %senabled\n", hinting ? "" : "NOT ");
7421     }
7422
7423     if ( subpixel == -1 )
7424     {
7425         subpixel = is_subpixel_rendering_enabled();
7426         TRACE("subpixel rendering is %senabled\n", subpixel ? "" : "NOT ");
7427     }
7428
7429     lprs->nSize = sizeof(RASTERIZER_STATUS);
7430     lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
7431     if ( subpixel )
7432         lprs->wFlags |= WINE_TT_SUBPIXEL_RENDERING_ENABLED;
7433     lprs->nLanguageID = 0;
7434     return TRUE;
7435 }
7436
7437 /*************************************************************
7438  * freetype_GdiRealizationInfo
7439  */
7440 static BOOL freetype_GdiRealizationInfo( PHYSDEV dev, void *ptr )
7441 {
7442     struct freetype_physdev *physdev = get_freetype_dev( dev );
7443     realization_info_t *info = ptr;
7444
7445     if (!physdev->font)
7446     {
7447         dev = GET_NEXT_PHYSDEV( dev, pGdiRealizationInfo );
7448         return dev->funcs->pGdiRealizationInfo( dev, ptr );
7449     }
7450
7451     FIXME("(%p, %p): stub!\n", physdev->font, info);
7452
7453     info->flags = 1;
7454     if(FT_IS_SCALABLE(physdev->font->ft_face))
7455         info->flags |= 2;
7456
7457     info->cache_num = physdev->font->cache_num;
7458     info->unknown2 = -1;
7459     return TRUE;
7460 }
7461
7462 /*************************************************************************
7463  * Kerning support for TrueType fonts
7464  */
7465 #define MS_KERN_TAG MS_MAKE_TAG('k', 'e', 'r', 'n')
7466
7467 struct TT_kern_table
7468 {
7469     USHORT version;
7470     USHORT nTables;
7471 };
7472
7473 struct TT_kern_subtable
7474 {
7475     USHORT version;
7476     USHORT length;
7477     union
7478     {
7479         USHORT word;
7480         struct
7481         {
7482             USHORT horizontal : 1;
7483             USHORT minimum : 1;
7484             USHORT cross_stream: 1;
7485             USHORT override : 1;
7486             USHORT reserved1 : 4;
7487             USHORT format : 8;
7488         } bits;
7489     } coverage;
7490 };
7491
7492 struct TT_format0_kern_subtable
7493 {
7494     USHORT nPairs;
7495     USHORT searchRange;
7496     USHORT entrySelector;
7497     USHORT rangeShift;
7498 };
7499
7500 struct TT_kern_pair
7501 {
7502     USHORT left;
7503     USHORT right;
7504     short  value;
7505 };
7506
7507 static DWORD parse_format0_kern_subtable(GdiFont *font,
7508                                          const struct TT_format0_kern_subtable *tt_f0_ks,
7509                                          const USHORT *glyph_to_char,
7510                                          KERNINGPAIR *kern_pair, DWORD cPairs)
7511 {
7512     USHORT i, nPairs;
7513     const struct TT_kern_pair *tt_kern_pair;
7514
7515     TRACE("font height %d, units_per_EM %d\n", font->ppem, font->ft_face->units_per_EM);
7516
7517     nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
7518
7519     TRACE("nPairs %u, searchRange %u, entrySelector %u, rangeShift %u\n",
7520            nPairs, GET_BE_WORD(tt_f0_ks->searchRange),
7521            GET_BE_WORD(tt_f0_ks->entrySelector), GET_BE_WORD(tt_f0_ks->rangeShift));
7522
7523     if (!kern_pair || !cPairs)
7524         return nPairs;
7525
7526     tt_kern_pair = (const struct TT_kern_pair *)(tt_f0_ks + 1);
7527
7528     nPairs = min(nPairs, cPairs);
7529
7530     for (i = 0; i < nPairs; i++)
7531     {
7532         kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
7533         kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
7534         /* this algorithm appears to better match what Windows does */
7535         kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
7536         if (kern_pair->iKernAmount < 0)
7537         {
7538             kern_pair->iKernAmount -= font->ft_face->units_per_EM / 2;
7539             kern_pair->iKernAmount -= font->ppem;
7540         }
7541         else if (kern_pair->iKernAmount > 0)
7542         {
7543             kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
7544             kern_pair->iKernAmount += font->ppem;
7545         }
7546         kern_pair->iKernAmount /= font->ft_face->units_per_EM;
7547
7548         TRACE("left %u right %u value %d\n",
7549                kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
7550
7551         kern_pair++;
7552     }
7553     TRACE("copied %u entries\n", nPairs);
7554     return nPairs;
7555 }
7556
7557 /*************************************************************
7558  * freetype_GetKerningPairs
7559  */
7560 static DWORD freetype_GetKerningPairs( PHYSDEV dev, DWORD cPairs, KERNINGPAIR *kern_pair )
7561 {
7562     DWORD length;
7563     void *buf;
7564     const struct TT_kern_table *tt_kern_table;
7565     const struct TT_kern_subtable *tt_kern_subtable;
7566     USHORT i, nTables;
7567     USHORT *glyph_to_char;
7568     GdiFont *font;
7569     struct freetype_physdev *physdev = get_freetype_dev( dev );
7570
7571     if (!(font = physdev->font))
7572     {
7573         dev = GET_NEXT_PHYSDEV( dev, pGetKerningPairs );
7574         return dev->funcs->pGetKerningPairs( dev, cPairs, kern_pair );
7575     }
7576
7577     GDI_CheckNotLock();
7578     EnterCriticalSection( &freetype_cs );
7579     if (font->total_kern_pairs != (DWORD)-1)
7580     {
7581         if (cPairs && kern_pair)
7582         {
7583             cPairs = min(cPairs, font->total_kern_pairs);
7584             memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
7585         }
7586         else cPairs = font->total_kern_pairs;
7587
7588         LeaveCriticalSection( &freetype_cs );
7589         return cPairs;
7590     }
7591
7592     font->total_kern_pairs = 0;
7593
7594     length = get_font_data(font, MS_KERN_TAG, 0, NULL, 0);
7595
7596     if (length == GDI_ERROR)
7597     {
7598         TRACE("no kerning data in the font\n");
7599         LeaveCriticalSection( &freetype_cs );
7600         return 0;
7601     }
7602
7603     buf = HeapAlloc(GetProcessHeap(), 0, length);
7604     if (!buf)
7605     {
7606         WARN("Out of memory\n");
7607         LeaveCriticalSection( &freetype_cs );
7608         return 0;
7609     }
7610
7611     get_font_data(font, MS_KERN_TAG, 0, buf, length);
7612
7613     /* build a glyph index to char code map */
7614     glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
7615     if (!glyph_to_char)
7616     {
7617         WARN("Out of memory allocating a glyph index to char code map\n");
7618         HeapFree(GetProcessHeap(), 0, buf);
7619         LeaveCriticalSection( &freetype_cs );
7620         return 0;
7621     }
7622
7623     if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE)
7624     {
7625         FT_UInt glyph_code;
7626         FT_ULong char_code;
7627
7628         glyph_code = 0;
7629         char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
7630
7631         TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
7632                font->ft_face->num_glyphs, glyph_code, char_code);
7633
7634         while (glyph_code)
7635         {
7636             /*TRACE("Char %04lX -> Index %u%s\n", char_code, glyph_code, glyph_to_char[glyph_code] ? "  !" : "" );*/
7637
7638             /* FIXME: This doesn't match what Windows does: it does some fancy
7639              * things with duplicate glyph index to char code mappings, while
7640              * we just avoid overriding existing entries.
7641              */
7642             if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
7643                 glyph_to_char[glyph_code] = (USHORT)char_code;
7644
7645             char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
7646         }
7647     }
7648     else
7649     {
7650         ULONG n;
7651
7652         FIXME("encoding %u not supported\n", font->ft_face->charmap->encoding);
7653         for (n = 0; n <= 65535; n++)
7654             glyph_to_char[n] = (USHORT)n;
7655     }
7656
7657     tt_kern_table = buf;
7658     nTables = GET_BE_WORD(tt_kern_table->nTables);
7659     TRACE("version %u, nTables %u\n",
7660            GET_BE_WORD(tt_kern_table->version), nTables);
7661
7662     tt_kern_subtable = (const struct TT_kern_subtable *)(tt_kern_table + 1);
7663
7664     for (i = 0; i < nTables; i++)
7665     {
7666         struct TT_kern_subtable tt_kern_subtable_copy;
7667
7668         tt_kern_subtable_copy.version = GET_BE_WORD(tt_kern_subtable->version);
7669         tt_kern_subtable_copy.length = GET_BE_WORD(tt_kern_subtable->length);
7670         tt_kern_subtable_copy.coverage.word = GET_BE_WORD(tt_kern_subtable->coverage.word);
7671
7672         TRACE("version %u, length %u, coverage %u, subtable format %u\n",
7673                tt_kern_subtable_copy.version, tt_kern_subtable_copy.length,
7674                tt_kern_subtable_copy.coverage.word, tt_kern_subtable_copy.coverage.bits.format);
7675
7676         /* According to the TrueType specification this is the only format
7677          * that will be properly interpreted by Windows and OS/2
7678          */
7679         if (tt_kern_subtable_copy.coverage.bits.format == 0)
7680         {
7681             DWORD new_chunk, old_total = font->total_kern_pairs;
7682
7683             new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
7684                                                     glyph_to_char, NULL, 0);
7685             font->total_kern_pairs += new_chunk;
7686
7687             if (!font->kern_pairs)
7688                 font->kern_pairs = HeapAlloc(GetProcessHeap(), 0,
7689                                              font->total_kern_pairs * sizeof(*font->kern_pairs));
7690             else
7691                 font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs,
7692                                                font->total_kern_pairs * sizeof(*font->kern_pairs));
7693
7694             parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1),
7695                         glyph_to_char, font->kern_pairs + old_total, new_chunk);
7696         }
7697         else
7698             TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format);
7699
7700         tt_kern_subtable = (const struct TT_kern_subtable *)((const char *)tt_kern_subtable + tt_kern_subtable_copy.length);
7701     }
7702
7703     HeapFree(GetProcessHeap(), 0, glyph_to_char);
7704     HeapFree(GetProcessHeap(), 0, buf);
7705
7706     if (cPairs && kern_pair)
7707     {
7708         cPairs = min(cPairs, font->total_kern_pairs);
7709         memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair));
7710     }
7711     else cPairs = font->total_kern_pairs;
7712
7713     LeaveCriticalSection( &freetype_cs );
7714     return cPairs;
7715 }
7716
7717 static const struct gdi_dc_funcs freetype_funcs =
7718 {
7719     NULL,                               /* pAbortDoc */
7720     NULL,                               /* pAbortPath */
7721     NULL,                               /* pAlphaBlend */
7722     NULL,                               /* pAngleArc */
7723     NULL,                               /* pArc */
7724     NULL,                               /* pArcTo */
7725     NULL,                               /* pBeginPath */
7726     NULL,                               /* pBlendImage */
7727     NULL,                               /* pChoosePixelFormat */
7728     NULL,                               /* pChord */
7729     NULL,                               /* pCloseFigure */
7730     NULL,                               /* pCopyBitmap */
7731     NULL,                               /* pCreateBitmap */
7732     NULL,                               /* pCreateCompatibleDC */
7733     freetype_CreateDC,                  /* pCreateDC */
7734     NULL,                               /* pDeleteBitmap */
7735     freetype_DeleteDC,                  /* pDeleteDC */
7736     NULL,                               /* pDeleteObject */
7737     NULL,                               /* pDescribePixelFormat */
7738     NULL,                               /* pDeviceCapabilities */
7739     NULL,                               /* pEllipse */
7740     NULL,                               /* pEndDoc */
7741     NULL,                               /* pEndPage */
7742     NULL,                               /* pEndPath */
7743     freetype_EnumFonts,                 /* pEnumFonts */
7744     NULL,                               /* pEnumICMProfiles */
7745     NULL,                               /* pExcludeClipRect */
7746     NULL,                               /* pExtDeviceMode */
7747     NULL,                               /* pExtEscape */
7748     NULL,                               /* pExtFloodFill */
7749     NULL,                               /* pExtSelectClipRgn */
7750     NULL,                               /* pExtTextOut */
7751     NULL,                               /* pFillPath */
7752     NULL,                               /* pFillRgn */
7753     NULL,                               /* pFlattenPath */
7754     freetype_FontIsLinked,              /* pFontIsLinked */
7755     NULL,                               /* pFrameRgn */
7756     NULL,                               /* pGdiComment */
7757     freetype_GdiRealizationInfo,        /* pGdiRealizationInfo */
7758     freetype_GetCharABCWidths,          /* pGetCharABCWidths */
7759     freetype_GetCharABCWidthsI,         /* pGetCharABCWidthsI */
7760     freetype_GetCharWidth,              /* pGetCharWidth */
7761     NULL,                               /* pGetDeviceCaps */
7762     NULL,                               /* pGetDeviceGammaRamp */
7763     freetype_GetFontData,               /* pGetFontData */
7764     freetype_GetFontUnicodeRanges,      /* pGetFontUnicodeRanges */
7765     freetype_GetGlyphIndices,           /* pGetGlyphIndices */
7766     freetype_GetGlyphOutline,           /* pGetGlyphOutline */
7767     NULL,                               /* pGetICMProfile */
7768     NULL,                               /* pGetImage */
7769     freetype_GetKerningPairs,           /* pGetKerningPairs */
7770     NULL,                               /* pGetNearestColor */
7771     freetype_GetOutlineTextMetrics,     /* pGetOutlineTextMetrics */
7772     NULL,                               /* pGetPixel */
7773     NULL,                               /* pGetPixelFormat */
7774     NULL,                               /* pGetSystemPaletteEntries */
7775     freetype_GetTextCharsetInfo,        /* pGetTextCharsetInfo */
7776     freetype_GetTextExtentExPoint,      /* pGetTextExtentExPoint */
7777     freetype_GetTextExtentExPointI,     /* pGetTextExtentExPointI */
7778     freetype_GetTextFace,               /* pGetTextFace */
7779     freetype_GetTextMetrics,            /* pGetTextMetrics */
7780     NULL,                               /* pGradientFill */
7781     NULL,                               /* pIntersectClipRect */
7782     NULL,                               /* pInvertRgn */
7783     NULL,                               /* pLineTo */
7784     NULL,                               /* pModifyWorldTransform */
7785     NULL,                               /* pMoveTo */
7786     NULL,                               /* pOffsetClipRgn */
7787     NULL,                               /* pOffsetViewportOrg */
7788     NULL,                               /* pOffsetWindowOrg */
7789     NULL,                               /* pPaintRgn */
7790     NULL,                               /* pPatBlt */
7791     NULL,                               /* pPie */
7792     NULL,                               /* pPolyBezier */
7793     NULL,                               /* pPolyBezierTo */
7794     NULL,                               /* pPolyDraw */
7795     NULL,                               /* pPolyPolygon */
7796     NULL,                               /* pPolyPolyline */
7797     NULL,                               /* pPolygon */
7798     NULL,                               /* pPolyline */
7799     NULL,                               /* pPolylineTo */
7800     NULL,                               /* pPutImage */
7801     NULL,                               /* pRealizeDefaultPalette */
7802     NULL,                               /* pRealizePalette */
7803     NULL,                               /* pRectangle */
7804     NULL,                               /* pResetDC */
7805     NULL,                               /* pRestoreDC */
7806     NULL,                               /* pRoundRect */
7807     NULL,                               /* pSaveDC */
7808     NULL,                               /* pScaleViewportExt */
7809     NULL,                               /* pScaleWindowExt */
7810     NULL,                               /* pSelectBitmap */
7811     NULL,                               /* pSelectBrush */
7812     NULL,                               /* pSelectClipPath */
7813     freetype_SelectFont,                /* pSelectFont */
7814     NULL,                               /* pSelectPalette */
7815     NULL,                               /* pSelectPen */
7816     NULL,                               /* pSetArcDirection */
7817     NULL,                               /* pSetBkColor */
7818     NULL,                               /* pSetBkMode */
7819     NULL,                               /* pSetDCBrushColor */
7820     NULL,                               /* pSetDCPenColor */
7821     NULL,                               /* pSetDIBColorTable */
7822     NULL,                               /* pSetDIBitsToDevice */
7823     NULL,                               /* pSetDeviceClipping */
7824     NULL,                               /* pSetDeviceGammaRamp */
7825     NULL,                               /* pSetLayout */
7826     NULL,                               /* pSetMapMode */
7827     NULL,                               /* pSetMapperFlags */
7828     NULL,                               /* pSetPixel */
7829     NULL,                               /* pSetPixelFormat */
7830     NULL,                               /* pSetPolyFillMode */
7831     NULL,                               /* pSetROP2 */
7832     NULL,                               /* pSetRelAbs */
7833     NULL,                               /* pSetStretchBltMode */
7834     NULL,                               /* pSetTextAlign */
7835     NULL,                               /* pSetTextCharacterExtra */
7836     NULL,                               /* pSetTextColor */
7837     NULL,                               /* pSetTextJustification */
7838     NULL,                               /* pSetViewportExt */
7839     NULL,                               /* pSetViewportOrg */
7840     NULL,                               /* pSetWindowExt */
7841     NULL,                               /* pSetWindowOrg */
7842     NULL,                               /* pSetWorldTransform */
7843     NULL,                               /* pStartDoc */
7844     NULL,                               /* pStartPage */
7845     NULL,                               /* pStretchBlt */
7846     NULL,                               /* pStretchDIBits */
7847     NULL,                               /* pStrokeAndFillPath */
7848     NULL,                               /* pStrokePath */
7849     NULL,                               /* pSwapBuffers */
7850     NULL,                               /* pUnrealizePalette */
7851     NULL,                               /* pWidenPath */
7852     /* OpenGL not supported */
7853 };
7854
7855 #else /* HAVE_FREETYPE */
7856
7857 /*************************************************************************/
7858
7859 BOOL WineEngInit(void)
7860 {
7861     return FALSE;
7862 }
7863 BOOL WineEngDestroyFontInstance(HFONT hfont)
7864 {
7865     return FALSE;
7866 }
7867
7868 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
7869 {
7870     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
7871     return 1;
7872 }
7873
7874 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
7875 {
7876     FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
7877     return TRUE;
7878 }
7879
7880 HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
7881 {
7882     FIXME("(%p, %u, %p, %p): stub\n", pbFont, cbFont, pdv, pcFonts);
7883     return NULL;
7884 }
7885
7886 BOOL WineEngCreateScalableFontResource( DWORD hidden, LPCWSTR resource,
7887                                         LPCWSTR font_file, LPCWSTR font_path )
7888 {
7889     FIXME("stub\n");
7890     return FALSE;
7891 }
7892
7893 BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
7894 {
7895     return FALSE;
7896 }
7897
7898 /*************************************************************************
7899  *             GetRasterizerCaps   (GDI32.@)
7900  */
7901 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
7902 {
7903     lprs->nSize = sizeof(RASTERIZER_STATUS);
7904     lprs->wFlags = 0;
7905     lprs->nLanguageID = 0;
7906     return TRUE;
7907 }
7908
7909 #endif /* HAVE_FREETYPE */