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