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