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