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