Load any TrueType fonts that fontconfig knows about.
[wine] / dlls / gdi / freetype.c
1 /*
2  * FreeType font engine interface
3  *
4  * Copyright 2001 Huw D M Davies for CodeWeavers.
5  *
6  * This file contains the WineEng* functions.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23
24 #include "config.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <sys/stat.h>
29 #include <string.h>
30 #include <dirent.h>
31 #include <stdio.h>
32 #include <assert.h>
33
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "winreg.h"
38 #include "wingdi.h"
39 #include "wine/unicode.h"
40 #include "wine/port.h"
41 #include "wine/debug.h"
42 #include "gdi.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(font);
45
46 #ifdef HAVE_FREETYPE
47
48 #ifdef HAVE_FREETYPE_FREETYPE_H
49 #include <freetype/freetype.h>
50 #endif
51 #ifdef HAVE_FREETYPE_FTGLYPH_H
52 #include <freetype/ftglyph.h>
53 #endif
54 #ifdef HAVE_FREETYPE_TTTABLES_H
55 #include <freetype/tttables.h>
56 #endif
57 #ifdef HAVE_FREETYPE_FTSNAMES_H
58 #include <freetype/ftsnames.h>
59 #else
60 # ifdef HAVE_FREETYPE_FTNAMES_H
61 # include <freetype/ftnames.h>
62 # endif
63 #endif
64 #ifdef HAVE_FREETYPE_TTNAMEID_H
65 #include <freetype/ttnameid.h>
66 #endif
67 #ifdef HAVE_FREETYPE_FTOUTLN_H
68 #include <freetype/ftoutln.h>
69 #endif
70 #ifdef HAVE_FREETYPE_INTERNAL_SFNT_H
71 #include <freetype/internal/sfnt.h>
72 #endif
73 #ifdef HAVE_FREETYPE_FTTRIGON_H
74 #include <freetype/fttrigon.h>
75 #endif
76
77 #ifndef SONAME_LIBFREETYPE
78 #define SONAME_LIBFREETYPE "libfreetype.so"
79 #endif
80
81 static FT_Library library = 0;
82 typedef struct
83 {
84     FT_Int major;
85     FT_Int minor;
86     FT_Int patch;
87 } FT_Version_t;
88 static FT_Version_t FT_Version;
89
90 static void *ft_handle = NULL;
91
92 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
93 MAKE_FUNCPTR(FT_Vector_Unit);
94 MAKE_FUNCPTR(FT_Done_Face);
95 MAKE_FUNCPTR(FT_Get_Char_Index);
96 MAKE_FUNCPTR(FT_Get_Sfnt_Table);
97 MAKE_FUNCPTR(FT_Init_FreeType);
98 MAKE_FUNCPTR(FT_Load_Glyph);
99 MAKE_FUNCPTR(FT_Matrix_Multiply);
100 MAKE_FUNCPTR(FT_MulFix);
101 MAKE_FUNCPTR(FT_New_Face);
102 MAKE_FUNCPTR(FT_Outline_Get_Bitmap);
103 MAKE_FUNCPTR(FT_Outline_Transform);
104 MAKE_FUNCPTR(FT_Outline_Translate);
105 MAKE_FUNCPTR(FT_Select_Charmap);
106 MAKE_FUNCPTR(FT_Set_Pixel_Sizes);
107 MAKE_FUNCPTR(FT_Vector_Transform);
108 static void (*pFT_Library_Version)(FT_Library,FT_Int*,FT_Int*,FT_Int*);
109 static FT_Error (*pFT_Load_Sfnt_Table)(FT_Face,FT_ULong,FT_Long,FT_Byte*,FT_ULong*);
110
111 #ifdef HAVE_FONTCONFIG_FONTCONFIG_H
112 #include <fontconfig/fontconfig.h>
113 MAKE_FUNCPTR(FcConfigGetCurrent);
114 MAKE_FUNCPTR(FcFontList);
115 MAKE_FUNCPTR(FcFontSetDestroy);
116 MAKE_FUNCPTR(FcInit);
117 MAKE_FUNCPTR(FcObjectSetAdd);
118 MAKE_FUNCPTR(FcObjectSetCreate);
119 MAKE_FUNCPTR(FcObjectSetDestroy);
120 MAKE_FUNCPTR(FcPatternCreate);
121 MAKE_FUNCPTR(FcPatternDestroy);
122 MAKE_FUNCPTR(FcPatternGet);
123 #ifndef SONAME_LIBFONTCONFIG
124 #define SONAME_LIBFONTCONFIG "libfontconfig.so"
125 #endif
126 #endif
127
128 #undef MAKE_FUNCPTR
129
130
131 #define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
132
133 typedef struct tagFace {
134     WCHAR *StyleName;
135     char *file;
136     FT_Long face_index;
137     BOOL Italic;
138     BOOL Bold;
139     FONTSIGNATURE fs;
140     FT_Fixed font_version;
141     struct tagFace *next;
142     struct tagFamily *family;
143 } Face;
144
145 typedef struct tagFamily {
146     WCHAR *FamilyName;
147     Face *FirstFace;
148     struct tagFamily *next;
149 } Family;
150
151 typedef struct {
152     GLYPHMETRICS gm;
153     INT adv; /* These three hold to widths of the unrotated chars */
154     INT lsb;
155     INT bbx;
156     BOOL init;
157 } GM;
158
159 struct tagGdiFont {
160     FT_Face ft_face;
161     XFORM xform;
162     LPWSTR name;
163     int charset;
164     BOOL fake_italic;
165     BOOL fake_bold;
166     INT orientation;
167     GM *gm;
168     DWORD gmsize;
169     HFONT hfont;
170     LONG aveWidth;
171     SHORT yMax;
172     SHORT yMin;
173     OUTLINETEXTMETRICW *potm;
174     FONTSIGNATURE fs;
175     struct tagGdiFont *next;
176 };
177
178 #define INIT_GM_SIZE 128
179
180 static GdiFont GdiFontList = NULL;
181
182 static Family *FontList = NULL;
183
184 static WCHAR defSerif[] = {'T','i','m','e','s',' ','N','e','w',' ',
185                            'R','o','m','a','n','\0'};
186 static WCHAR defSans[] = {'A','r','i','a','l','\0'};
187 static WCHAR defFixed[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'};
188
189 static WCHAR defSystem[] = {'A','r','i','a','l','\0'};
190 static WCHAR SystemW[] = {'S','y','s','t','e','m','\0'};
191 static WCHAR MSSansSerifW[] = {'M','S',' ','S','a','n','s',' ',
192                                'S','e','r','i','f','\0'};
193 static WCHAR HelvW[] = {'H','e','l','v','\0'};
194
195 static WCHAR ArabicW[] = {'A','r','a','b','i','c','\0'};
196 static WCHAR BalticW[] = {'B','a','l','t','i','c','\0'};
197 static WCHAR CHINESE_BIG5W[] = {'C','H','I','N','E','S','E','_','B','I','G','5','\0'};
198 static WCHAR CHINESE_GB2312W[] = {'C','H','I','N','E','S','E','_','G','B','2','3','1','2','\0'};
199 static WCHAR Central_EuropeanW[] = {'C','e','n','t','r','a','l',' ',
200                                     'E','u','r','o','p','e','a','n','\0'};
201 static WCHAR CyrillicW[] = {'C','y','r','i','l','l','i','c','\0'};
202 static WCHAR GreekW[] = {'G','r','e','e','k','\0'};
203 static WCHAR HangulW[] = {'H','a','n','g','u','l','\0'};
204 static WCHAR Hangul_Johab_W[] = {'H','a','n','g','u','l','(','J','o','h','a','b',')','\0'};
205 static WCHAR HebrewW[] = {'H','e','b','r','e','w','\0'};
206 static WCHAR JapaneseW[] = {'J','a','p','a','n','e','s','e','\0'};
207 static WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
208 static WCHAR ThaiW[] = {'T','h','a','i','\0'};
209 static WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'};
210 static WCHAR VietnameseW[] = {'V','i','e','t','n','a','m','e','s','e','\0'};
211 static WCHAR WesternW[] = {'W','e','s','t','e','r','n','\0'};
212
213 static WCHAR *ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits */
214     WesternW, /*00*/
215     Central_EuropeanW,
216     CyrillicW,
217     GreekW,
218     TurkishW,
219     HebrewW,
220     ArabicW,
221     BalticW,
222     VietnameseW, /*08*/
223     NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/
224     ThaiW,
225     JapaneseW,
226     CHINESE_GB2312W,
227     HangulW,
228     CHINESE_BIG5W,
229     Hangul_Johab_W,
230     NULL, NULL, /*23*/
231     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
232     SymbolW /*31*/
233 };
234
235 typedef struct {
236   WCHAR *name;
237   INT charset;
238 } NameCs;
239
240 typedef struct tagFontSubst {
241   NameCs from;
242   NameCs to;
243   struct tagFontSubst *next;
244 } FontSubst;
245
246 static FontSubst *substlist = NULL;
247 static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail if this is still FALSE */
248
249 /* 
250    This function builds an FT_Fixed from a float. It puts the integer part
251    in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed.
252    It fails if the integer part of the float number is greater than SHORT_MAX.
253 */
254 static inline FT_Fixed FT_FixedFromFloat(float f)
255 {
256         short value = f;
257         unsigned short fract = (f - value) * 0xFFFF;
258         return (FT_Fixed)((long)value << 16 | (unsigned long)fract);
259 }
260
261 /* 
262    This function builds an FT_Fixed from a FIXED. It simply put f.value 
263    in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
264 */
265 static inline FT_Fixed FT_FixedFromFIXED(FIXED f)
266 {
267         return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
268 }
269
270 static BOOL AddFontFileToList(const char *file, char *fake_family)
271 {
272     FT_Face ft_face;
273     TT_OS2 *pOS2;
274     TT_Header *pHeader;
275     WCHAR *FamilyW, *StyleW;
276     DWORD len;
277     Family *family = FontList;
278     Family **insert = &FontList;
279     Face **insertface, *next;
280     FT_Error err;
281     FT_Long face_index = 0, num_faces;
282     int i;
283
284     do {
285         char *family_name = fake_family;
286
287         TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
288         if((err = pFT_New_Face(library, file, face_index, &ft_face)) != 0) {
289             WARN("Unable to load font file %s err = %x\n", debugstr_a(file), err);
290             return FALSE;
291         }
292
293         if(!FT_IS_SFNT(ft_face)) { /* for now we'll skip everything but TT/OT */
294             pFT_Done_Face(ft_face);
295             return FALSE;
296         }
297         if(!pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2) ||
298            !pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea) ||
299            !(pHeader = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_head))) {
300             TRACE("Font file %s lacks either an OS2, HHEA or HEAD table.\n"
301                   "Skipping this font.\n", debugstr_a(file));
302             pFT_Done_Face(ft_face);
303             return FALSE;
304         }
305
306         if(!ft_face->family_name || !ft_face->style_name) {
307             TRACE("Font file %s lacks either a family or style name\n", debugstr_a(file));
308             pFT_Done_Face(ft_face);
309             return FALSE;
310         }
311
312         if(!family_name)
313             family_name = ft_face->family_name;
314
315         len = MultiByteToWideChar(CP_ACP, 0, family_name, -1, NULL, 0);
316         FamilyW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
317         MultiByteToWideChar(CP_ACP, 0, family_name, -1, FamilyW, len);
318
319         while(family) {
320             if(!strcmpW(family->FamilyName, FamilyW))
321                 break;
322             insert = &family->next;
323             family = family->next;
324         }
325         if(!family) {
326             family = *insert = HeapAlloc(GetProcessHeap(), 0, sizeof(*family));
327             family->FamilyName = FamilyW;
328             family->FirstFace = NULL;
329             family->next = NULL;
330         } else {
331             HeapFree(GetProcessHeap(), 0, FamilyW);
332         }
333
334         len = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0);
335         StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
336         MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
337
338         next = NULL;
339         for(insertface = &family->FirstFace; *insertface;
340             insertface = &(*insertface)->next) {
341             if(!strcmpW((*insertface)->StyleName, StyleW)) {
342                 TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
343                       debugstr_w(family->FamilyName), debugstr_w(StyleW),
344                       (*insertface)->font_version,  pHeader->Font_Revision);
345
346                 if(fake_family) {
347                     TRACE("This font is a replacement but the original really exists, so we'll skip the replacement\n");
348                     HeapFree(GetProcessHeap(), 0, StyleW);
349                     pFT_Done_Face(ft_face);
350                     return FALSE;
351                 }
352                 if(pHeader->Font_Revision <= (*insertface)->font_version) {
353                     TRACE("Original font is newer so skipping this one\n");
354                     HeapFree(GetProcessHeap(), 0, StyleW);
355                     pFT_Done_Face(ft_face);
356                     return FALSE;
357                 } else {
358                     TRACE("Replacing original with this one\n");
359                     next = (*insertface)->next;
360                     HeapFree(GetProcessHeap(), 0, (*insertface)->file);
361                     HeapFree(GetProcessHeap(), 0, (*insertface)->StyleName);
362                     HeapFree(GetProcessHeap(), 0, *insertface);
363                     break;
364                 }
365             }
366         }
367         *insertface = HeapAlloc(GetProcessHeap(), 0, sizeof(**insertface));
368         (*insertface)->StyleName = StyleW;
369         (*insertface)->file = HeapAlloc(GetProcessHeap(),0,strlen(file)+1);
370         strcpy((*insertface)->file, file);
371         (*insertface)->face_index = face_index;
372         (*insertface)->next = next;
373         (*insertface)->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
374         (*insertface)->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0;
375         (*insertface)->font_version = pHeader->Font_Revision;
376         (*insertface)->family = family;
377
378         pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
379         if(pOS2) {
380             (*insertface)->fs.fsCsb[0] = pOS2->ulCodePageRange1;
381             (*insertface)->fs.fsCsb[1] = pOS2->ulCodePageRange2;
382             (*insertface)->fs.fsUsb[0] = pOS2->ulUnicodeRange1;
383             (*insertface)->fs.fsUsb[1] = pOS2->ulUnicodeRange2;
384             (*insertface)->fs.fsUsb[2] = pOS2->ulUnicodeRange3;
385             (*insertface)->fs.fsUsb[3] = pOS2->ulUnicodeRange4;
386         } else {
387             (*insertface)->fs.fsCsb[0] = (*insertface)->fs.fsCsb[1] = 0;
388             (*insertface)->fs.fsUsb[0] = 0;
389             (*insertface)->fs.fsUsb[1] = 0;
390             (*insertface)->fs.fsUsb[2] = 0;
391             (*insertface)->fs.fsUsb[3] = 0;
392         }
393         TRACE("fsCsb = %08lx %08lx/%08lx %08lx %08lx %08lx\n",
394               (*insertface)->fs.fsCsb[0], (*insertface)->fs.fsCsb[1],
395               (*insertface)->fs.fsUsb[0], (*insertface)->fs.fsUsb[1],
396               (*insertface)->fs.fsUsb[2], (*insertface)->fs.fsUsb[3]);
397
398         if((*insertface)->fs.fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */
399             for(i = 0; i < ft_face->num_charmaps; i++) {
400                 switch(ft_face->charmaps[i]->encoding) {
401                 case ft_encoding_unicode:
402                 case ft_encoding_apple_roman:
403                         (*insertface)->fs.fsCsb[0] |= 1;
404                     break;
405                 case ft_encoding_symbol:
406                     (*insertface)->fs.fsCsb[0] |= 1L << 31;
407                     break;
408                 default:
409                     break;
410                 }
411             }
412         }
413
414         if((*insertface)->fs.fsCsb[0] & ~(1L << 31))
415             have_installed_roman_font = TRUE;
416
417         num_faces = ft_face->num_faces;
418         pFT_Done_Face(ft_face);
419         TRACE("Added font %s %s\n", debugstr_w(family->FamilyName),
420               debugstr_w(StyleW));
421     } while(num_faces > ++face_index);
422     return TRUE;
423 }
424
425 static void DumpFontList(void)
426 {
427     Family *family;
428     Face *face;
429
430     for(family = FontList; family; family = family->next) {
431         TRACE("Family: %s\n", debugstr_w(family->FamilyName));
432         for(face = family->FirstFace; face; face = face->next) {
433             TRACE("\t%s\n", debugstr_w(face->StyleName));
434         }
435     }
436     return;
437 }
438
439 static void DumpSubstList(void)
440 {
441     FontSubst *psub;
442
443     for(psub = substlist; psub; psub = psub->next)
444         if(psub->from.charset != -1 || psub->to.charset != -1)
445             TRACE("%s:%d -> %s:%d\n", debugstr_w(psub->from.name),
446               psub->from.charset, debugstr_w(psub->to.name), psub->to.charset);
447         else
448             TRACE("%s -> %s\n", debugstr_w(psub->from.name),
449                   debugstr_w(psub->to.name));
450     return;
451 }
452
453 static LPWSTR strdupW(LPWSTR p)
454 {
455     LPWSTR ret;
456     DWORD len = (strlenW(p) + 1) * sizeof(WCHAR);
457     ret = HeapAlloc(GetProcessHeap(), 0, len);
458     memcpy(ret, p, len);
459     return ret;
460 }
461
462 static void split_subst_info(NameCs *nc, LPSTR str)
463 {
464     CHAR *p = strrchr(str, ',');
465     DWORD len;
466
467     nc->charset = -1;
468     if(p && *(p+1)) {
469         nc->charset = strtol(p+1, NULL, 10);
470         *p = '\0';
471     }
472     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
473     nc->name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
474     MultiByteToWideChar(CP_ACP, 0, str, -1, nc->name, len);
475 }
476
477 static void LoadSubstList(void)
478 {
479     FontSubst *psub, **ppsub;
480     HKEY hkey;
481     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
482     LPSTR value;
483     LPVOID data;
484
485     if(substlist) {
486         for(psub = substlist; psub;) {
487             FontSubst *ptmp;
488             HeapFree(GetProcessHeap(), 0, psub->to.name);
489             HeapFree(GetProcessHeap(), 0, psub->from.name);
490             ptmp = psub;
491             psub = psub->next;
492             HeapFree(GetProcessHeap(), 0, ptmp);
493         }
494         substlist = NULL;
495     }
496
497     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
498                    "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes",
499                    &hkey) == ERROR_SUCCESS) {
500
501         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
502                          &valuelen, &datalen, NULL, NULL);
503
504         valuelen++; /* returned value doesn't include room for '\0' */
505         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
506         data = HeapAlloc(GetProcessHeap(), 0, datalen);
507
508         dlen = datalen;
509         vlen = valuelen;
510         ppsub = &substlist;
511         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
512                             &dlen) == ERROR_SUCCESS) {
513             TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
514
515             *ppsub = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppsub));
516             (*ppsub)->next = NULL;
517             split_subst_info(&((*ppsub)->from), value);
518             split_subst_info(&((*ppsub)->to), data);
519
520             /* Win 2000 doesn't allow mapping between different charsets
521                or mapping of DEFAULT_CHARSET */
522             if(((*ppsub)->to.charset != (*ppsub)->from.charset) ||
523                (*ppsub)->to.charset == DEFAULT_CHARSET) {
524                 HeapFree(GetProcessHeap(), 0, (*ppsub)->to.name);
525                 HeapFree(GetProcessHeap(), 0, (*ppsub)->from.name);
526                 HeapFree(GetProcessHeap(), 0, *ppsub);
527                 *ppsub = NULL;
528             } else {
529                 ppsub = &((*ppsub)->next);
530             }
531             /* reset dlen and vlen */
532             dlen = datalen;
533             vlen = valuelen;
534         }
535         HeapFree(GetProcessHeap(), 0, data);
536         HeapFree(GetProcessHeap(), 0, value);
537         RegCloseKey(hkey);
538     }
539 }
540
541 /***********************************************************
542  * The replacement list is a way to map an entire font
543  * family onto another family.  For example adding
544  *
545  * [HKLM\Software\Wine\Wine\FontReplacements]
546  * "Wingdings"="Winedings"
547  *
548  * would enumerate the Winedings font both as Winedings and
549  * Wingdings.  However if a real Wingdings font is present the
550  * replacement does not take place.
551  * 
552  */
553 static void LoadReplaceList(void)
554 {
555     HKEY hkey;
556     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
557     LPSTR value;
558     LPVOID data;
559     Family *family;
560     Face *face;
561     WCHAR old_nameW[200];
562
563     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
564                    "Software\\Wine\\Wine\\FontReplacements",
565                    &hkey) == ERROR_SUCCESS) {
566
567         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
568                          &valuelen, &datalen, NULL, NULL);
569
570         valuelen++; /* returned value doesn't include room for '\0' */
571         value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
572         data = HeapAlloc(GetProcessHeap(), 0, datalen);
573
574         dlen = datalen;
575         vlen = valuelen;
576         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
577                             &dlen) == ERROR_SUCCESS) {
578             TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
579             /* "NewName"="Oldname" */
580             if(!MultiByteToWideChar(CP_ACP, 0, data, -1, old_nameW, sizeof(old_nameW)))
581                 break;
582
583             /* Find the old family and hence all of the font files
584                in that family */
585             for(family = FontList; family; family = family->next) {
586                 if(!strcmpiW(family->FamilyName, old_nameW)) {
587                     for(face = family->FirstFace; face; face = face->next) {
588                         TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName),
589                               debugstr_w(face->StyleName), value);
590                         /* Now add a new entry with the new family name */
591                         AddFontFileToList(face->file, value);
592                     }
593                     break;
594                 }
595             }
596             /* reset dlen and vlen */
597             dlen = datalen;
598             vlen = valuelen;
599         }
600         HeapFree(GetProcessHeap(), 0, data);
601         HeapFree(GetProcessHeap(), 0, value);
602         RegCloseKey(hkey);
603     }
604 }
605
606
607 static BOOL ReadFontDir(char *dirname)
608 {
609     DIR *dir;
610     struct dirent *dent;
611     char path[MAX_PATH];
612
613     TRACE("Loading fonts from %s\n", debugstr_a(dirname));
614
615     dir = opendir(dirname);
616     if(!dir) {
617         ERR("Can't open directory %s\n", debugstr_a(dirname));
618         return FALSE;
619     }
620     while((dent = readdir(dir)) != NULL) {
621         struct stat statbuf;
622
623         if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
624             continue;
625
626         TRACE("Found %s in %s\n", debugstr_a(dent->d_name), debugstr_a(dirname));
627
628         sprintf(path, "%s/%s", dirname, dent->d_name);
629
630         if(stat(path, &statbuf) == -1)
631         {
632             WARN("Can't stat %s\n", debugstr_a(path));
633             continue;
634         }
635         if(S_ISDIR(statbuf.st_mode))
636             ReadFontDir(path);
637         else
638             AddFontFileToList(path, NULL);
639     }
640     closedir(dir);
641     return TRUE;
642 }
643
644 static void load_fontconfig_fonts(void)
645 {
646 #ifdef HAVE_FONTCONFIG_FONTCONFIG_H
647     void *fc_handle = NULL;
648     FcConfig *config;
649     FcPattern *pat;
650     FcObjectSet *os;
651     FcFontSet *fontset;
652     FcValue v;
653     int i, len;
654     const char *ext;
655
656     fc_handle = wine_dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW, NULL, 0);
657     if(!fc_handle) {
658         TRACE("Wine cannot find the fontconfig library (%s).\n",
659               SONAME_LIBFONTCONFIG);
660         return;
661     }
662 #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;}
663 LOAD_FUNCPTR(FcConfigGetCurrent);
664 LOAD_FUNCPTR(FcFontList);
665 LOAD_FUNCPTR(FcFontSetDestroy);
666 LOAD_FUNCPTR(FcInit);
667 LOAD_FUNCPTR(FcObjectSetAdd);
668 LOAD_FUNCPTR(FcObjectSetCreate);
669 LOAD_FUNCPTR(FcObjectSetDestroy);
670 LOAD_FUNCPTR(FcPatternCreate);
671 LOAD_FUNCPTR(FcPatternDestroy);
672 LOAD_FUNCPTR(FcPatternGet);
673 #undef LOAD_FUNCPTR
674
675     if(!pFcInit()) return;
676     
677     config = pFcConfigGetCurrent();
678     pat = pFcPatternCreate();
679     os = pFcObjectSetCreate();
680     pFcObjectSetAdd(os, FC_FILE);
681     fontset = pFcFontList(config, pat, os);
682     if(!fontset) return;
683     for(i = 0; i < fontset->nfont; i++) {
684         if(pFcPatternGet(fontset->fonts[i], FC_FILE, 0, &v) != FcResultMatch)
685             continue;
686         if(v.type != FcTypeString) continue;
687         TRACE("fontconfig: %s\n", v.u.s);
688
689         /* We're just interested in OT/TT fonts for now, so this hack just
690            picks up the standard extensions to save time loading every other
691            font */
692         len = strlen(v.u.s);
693         if(len < 4) continue;
694         ext = v.u.s + len - 3;
695         if(!strcasecmp(ext, "ttf") || !strcasecmp(ext, "ttc") || !strcasecmp(ext, "otf"))
696             AddFontFileToList(v.u.s, NULL);
697     }
698     pFcFontSetDestroy(fontset);
699     pFcObjectSetDestroy(os);
700     pFcPatternDestroy(pat);
701  sym_not_found:
702 #endif
703     return;
704 }
705 /*************************************************************
706  *    WineEngAddFontResourceEx
707  *
708  */
709 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
710 {
711     if (ft_handle)  /* do it only if we have freetype up and running */
712     {
713         DWORD len = WideCharToMultiByte(CP_ACP, 0, file, -1, NULL, 0, NULL, NULL);
714         LPSTR fileA = HeapAlloc(GetProcessHeap(), 0, len);
715         char unixname[MAX_PATH];
716         WideCharToMultiByte(CP_ACP, 0, file, -1, fileA, len, NULL, NULL);
717
718         if(flags)
719             FIXME("Ignoring flags %lx\n", flags);
720
721         if(wine_get_unix_file_name(fileA, unixname, sizeof(unixname)))
722             AddFontFileToList(unixname, NULL);
723         HeapFree(GetProcessHeap(), 0, fileA);
724     }
725     return 1;
726 }
727
728 /*************************************************************
729  *    WineEngRemoveFontResourceEx
730  *
731  */
732 BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
733 {
734     FIXME(":stub\n");
735     return TRUE;
736 }
737
738 /*************************************************************
739  *    WineEngInit
740  *
741  * Initialize FreeType library and create a list of available faces
742  */
743 BOOL WineEngInit(void)
744 {
745     HKEY hkey;
746     DWORD valuelen, datalen, i = 0, type, dlen, vlen;
747     LPSTR value;
748     LPVOID data;
749     char windowsdir[MAX_PATH];
750     char unixname[MAX_PATH];
751
752     TRACE("\n");
753
754     ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0);
755     if(!ft_handle) {
756         WINE_MESSAGE(
757       "Wine cannot find the FreeType font library.  To enable Wine to\n"
758       "use TrueType fonts please install a version of FreeType greater than\n"
759       "or equal to 2.0.5.\n"
760       "http://www.freetype.org\n");
761         return FALSE;
762     }
763
764 #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;}
765
766     LOAD_FUNCPTR(FT_Vector_Unit)
767     LOAD_FUNCPTR(FT_Done_Face)
768     LOAD_FUNCPTR(FT_Get_Char_Index)
769     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
770     LOAD_FUNCPTR(FT_Init_FreeType)
771     LOAD_FUNCPTR(FT_Load_Glyph)
772     LOAD_FUNCPTR(FT_Matrix_Multiply)
773     LOAD_FUNCPTR(FT_MulFix)
774     LOAD_FUNCPTR(FT_New_Face)
775     LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
776     LOAD_FUNCPTR(FT_Outline_Transform)
777     LOAD_FUNCPTR(FT_Outline_Translate)
778     LOAD_FUNCPTR(FT_Select_Charmap)
779     LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
780     LOAD_FUNCPTR(FT_Vector_Transform)
781
782 #undef LOAD_FUNCPTR
783     /* Don't warn if this one is missing */
784     pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0);
785     pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0);
786
787       if(!wine_dlsym(ft_handle, "FT_Get_Postscript_Name", NULL, 0) &&
788          !wine_dlsym(ft_handle, "FT_Sqrt64", NULL, 0)) {
789         /* try to avoid 2.0.4: >= 2.0.5 has FT_Get_Postscript_Name and
790            <= 2.0.3 has FT_Sqrt64 */
791           goto sym_not_found;
792       }
793
794     if(pFT_Init_FreeType(&library) != 0) {
795         ERR("Can't init FreeType library\n");
796         wine_dlclose(ft_handle, NULL, 0);
797         ft_handle = NULL;
798         return FALSE;
799     }
800     FT_Version.major=FT_Version.minor=FT_Version.patch=-1;
801     if (pFT_Library_Version)
802     {
803         pFT_Library_Version(library,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
804     }
805     if (FT_Version.major<=0)
806     {
807         FT_Version.major=2;
808         FT_Version.minor=0;
809         FT_Version.patch=5;
810     }
811     TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
812
813     /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
814     GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
815     strcat(windowsdir, "\\Fonts");
816     if(wine_get_unix_file_name(windowsdir, unixname, sizeof(unixname)))
817         ReadFontDir(unixname);
818
819     /* now look under HKLM\Software\Microsoft\Windows\CurrentVersion\Fonts
820        for any fonts not installed in %WINDOWSDIR%\Fonts.  They will have their
821        full path as the entry */
822     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
823                    "Software\\Microsoft\\Windows\\CurrentVersion\\Fonts",
824                    &hkey) == ERROR_SUCCESS) {
825         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
826                          &valuelen, &datalen, NULL, NULL);
827
828         valuelen++; /* returned value doesn't include room for '\0' */
829         value = HeapAlloc(GetProcessHeap(), 0, valuelen);
830         data = HeapAlloc(GetProcessHeap(), 0, datalen);
831
832         dlen = datalen;
833         vlen = valuelen;
834         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
835                             &dlen) == ERROR_SUCCESS) {
836             if(((LPSTR)data)[0] && ((LPSTR)data)[1] == ':')
837                 if(wine_get_unix_file_name((LPSTR)data, unixname, sizeof(unixname)))
838                     AddFontFileToList(unixname, NULL);
839
840             /* reset dlen and vlen */
841             dlen = datalen;
842             vlen = valuelen;
843         }
844         HeapFree(GetProcessHeap(), 0, data);
845         HeapFree(GetProcessHeap(), 0, value);
846         RegCloseKey(hkey);
847     }
848
849     load_fontconfig_fonts();
850
851     /* then look in any directories that we've specified in the config file */
852     if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
853                    "Software\\Wine\\Wine\\Config\\FontDirs",
854                    &hkey) == ERROR_SUCCESS) {
855
856         RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
857                          &valuelen, &datalen, NULL, NULL);
858
859         valuelen++; /* returned value doesn't include room for '\0' */
860         value = HeapAlloc(GetProcessHeap(), 0, valuelen);
861         data = HeapAlloc(GetProcessHeap(), 0, datalen);
862
863         dlen = datalen;
864         vlen = valuelen;
865         i = 0;
866         while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
867                             &dlen) == ERROR_SUCCESS) {
868             TRACE("Got %s=%s\n", value, (LPSTR)data);
869             ReadFontDir((LPSTR)data);
870             /* reset dlen and vlen */
871             dlen = datalen;
872             vlen = valuelen;
873         }
874         HeapFree(GetProcessHeap(), 0, data);
875         HeapFree(GetProcessHeap(), 0, value);
876         RegCloseKey(hkey);
877     }
878
879     DumpFontList();
880     LoadSubstList();
881     DumpSubstList();
882     LoadReplaceList();
883     return TRUE;
884 sym_not_found:
885     WINE_MESSAGE(
886       "Wine cannot find certain functions that it needs inside the FreeType\n"
887       "font library.  To enable Wine to use TrueType fonts please upgrade\n"
888       "FreeType to at least version 2.0.5.\n"
889       "http://www.freetype.org\n");
890     wine_dlclose(ft_handle, NULL, 0);
891     ft_handle = NULL;
892     return FALSE;
893 }
894
895
896 static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
897 {
898     TT_OS2 *pOS2;
899     LONG ppem;
900
901     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
902
903     if(height == 0) height = 16;
904
905     /* Calc. height of EM square:
906      *
907      * For +ve lfHeight we have
908      * lfHeight = (winAscent + winDescent) * ppem / units_per_em
909      * Re-arranging gives:
910      * ppem = units_per_em * lfheight / (winAscent + winDescent)
911      *
912      * For -ve lfHeight we have
913      * |lfHeight| = ppem
914      * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em
915      * with il = winAscent + winDescent - units_per_em]
916      *
917      */
918
919     if(height > 0)
920         ppem = ft_face->units_per_EM * height /
921             (pOS2->usWinAscent + pOS2->usWinDescent);
922     else
923         ppem = -height;
924
925     return ppem;
926 }
927
928 static LONG load_VDMX(GdiFont, LONG);
929
930 static FT_Face OpenFontFile(GdiFont font, char *file, FT_Long face_index, LONG height)
931 {
932     FT_Error err;
933     FT_Face ft_face;
934     LONG ppem;
935
936     err = pFT_New_Face(library, file, face_index, &ft_face);
937     if(err) {
938         ERR("FT_New_Face rets %d\n", err);
939         return 0;
940     }
941
942     /* set it here, as load_VDMX needs it */
943     font->ft_face = ft_face;
944
945     /* load the VDMX table if we have one */
946     ppem = load_VDMX(font, height);
947     if(ppem == 0)
948         ppem = calc_ppem_for_height(ft_face, height);
949
950     pFT_Set_Pixel_Sizes(ft_face, 0, ppem);
951
952     return ft_face;
953 }
954
955
956 static int get_nearest_charset(Face *face)
957 {
958   /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
959      a single face with the requested charset.  The idea is to check if
960      the selected font supports the current ANSI codepage, if it does
961      return the corresponding charset, else return the first charset */
962
963     CHARSETINFO csi;
964     int acp = GetACP(), i;
965     DWORD fs0;
966
967     if(TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE))
968         if(csi.fs.fsCsb[0] & face->fs.fsCsb[0])
969             return csi.ciCharset;
970
971     for(i = 0; i < 32; i++) {
972         fs0 = 1L << i;
973         if(face->fs.fsCsb[0] & fs0) {
974             if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG))
975                 return csi.ciCharset;
976             else
977                 FIXME("TCI failing on %lx\n", fs0);
978         }
979     }
980
981     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08lx file = %s\n",
982           face->fs.fsCsb[0], face->file);
983     return DEFAULT_CHARSET;
984 }
985
986 static GdiFont alloc_font(void)
987 {
988     GdiFont ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
989     ret->gmsize = INIT_GM_SIZE;
990     ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
991                         ret->gmsize * sizeof(*ret->gm));
992     ret->next = NULL;
993     ret->potm = NULL;
994     ret->xform.eM11 = ret->xform.eM22 = 1.0;
995     return ret;
996 }
997
998 static void free_font(GdiFont font)
999 {
1000     if (font->ft_face) pFT_Done_Face(font->ft_face);
1001     if (font->potm) HeapFree(GetProcessHeap(), 0, font->potm);
1002     if (font->name) HeapFree(GetProcessHeap(), 0, font->name);
1003     HeapFree(GetProcessHeap(), 0, font->gm);
1004     HeapFree(GetProcessHeap(), 0, font);
1005 }
1006
1007
1008 /*************************************************************
1009  * load_VDMX
1010  *
1011  * load the vdmx entry for the specified height
1012  */
1013
1014 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
1015           ( ( (FT_ULong)_x4 << 24 ) |     \
1016             ( (FT_ULong)_x3 << 16 ) |     \
1017             ( (FT_ULong)_x2 <<  8 ) |     \
1018               (FT_ULong)_x1         )
1019
1020 #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X')
1021
1022 typedef struct {
1023     BYTE bCharSet;
1024     BYTE xRatio;
1025     BYTE yStartRatio;
1026     BYTE yEndRatio;
1027 } Ratios;
1028
1029
1030 static LONG load_VDMX(GdiFont font, LONG height)
1031 {
1032     BYTE hdr[6], tmp[2], group[4];
1033     BYTE devXRatio, devYRatio;
1034     USHORT numRecs, numRatios;
1035     DWORD offset = -1;
1036     LONG ppem = 0;
1037     int i, result;
1038
1039     result = WineEngGetFontData(font, MS_VDMX_TAG, 0, hdr, 6);
1040
1041     if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
1042         return ppem;
1043
1044     /* FIXME: need the real device aspect ratio */
1045     devXRatio = 1;
1046     devYRatio = 1;
1047
1048     numRecs = GET_BE_WORD(&hdr[2]);
1049     numRatios = GET_BE_WORD(&hdr[4]);
1050
1051     TRACE("numRecs = %d numRatios = %d\n", numRecs, numRatios);
1052     for(i = 0; i < numRatios; i++) {
1053         Ratios ratio;
1054
1055         offset = (3 * 2) + (i * sizeof(Ratios));
1056         WineEngGetFontData(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
1057         offset = -1;
1058
1059         TRACE("Ratios[%d] %d  %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
1060
1061         if(ratio.bCharSet != 1)
1062             continue;
1063
1064         if((ratio.xRatio == 0 &&
1065             ratio.yStartRatio == 0 &&
1066             ratio.yEndRatio == 0) ||
1067            (devXRatio == ratio.xRatio &&
1068             devYRatio >= ratio.yStartRatio &&
1069             devYRatio <= ratio.yEndRatio))
1070             {
1071                 offset = (3 * 2) + (numRatios * 4) + (i * 2);
1072                 WineEngGetFontData(font, MS_VDMX_TAG, offset, tmp, 2);
1073                 offset = GET_BE_WORD(tmp);
1074                 break;
1075             }
1076     }
1077
1078     if(offset < 0) {
1079         FIXME("No suitable ratio found\n");
1080         return ppem;
1081     }
1082
1083     if(WineEngGetFontData(font, MS_VDMX_TAG, offset, group, 4) != GDI_ERROR) {
1084         USHORT recs;
1085         BYTE startsz, endsz;
1086         BYTE *vTable;
1087
1088         recs = GET_BE_WORD(group);
1089         startsz = group[2];
1090         endsz = group[3];
1091
1092         TRACE("recs=%d  startsz=%d  endsz=%d\n", recs, startsz, endsz);
1093
1094         vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6);
1095         result = WineEngGetFontData(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6);
1096         if(result == GDI_ERROR) {
1097             FIXME("Failed to retrieve vTable\n");
1098             goto end;
1099         }
1100
1101         if(height > 0) {
1102             for(i = 0; i < recs; i++) {
1103                 SHORT yMax = GET_BE_WORD(&vTable[(i * 6) + 2]);
1104                 SHORT yMin = GET_BE_WORD(&vTable[(i * 6) + 4]);
1105                 ppem = GET_BE_WORD(&vTable[i * 6]);
1106
1107                 if(yMax + -yMin == height) {
1108                     font->yMax = yMax;
1109                     font->yMin = yMin;
1110                     TRACE("ppem %ld found; height=%ld  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
1111                     break;
1112                 }
1113                 if(yMax + -yMin > height) {
1114                     if(--i < 0) {
1115                         ppem = 0;
1116                         goto end; /* failed */
1117                     }
1118                     font->yMax = GET_BE_WORD(&vTable[(i * 6) + 2]);
1119                     font->yMin = GET_BE_WORD(&vTable[(i * 6) + 4]);
1120                     TRACE("ppem %ld found; height=%ld  yMax=%d  yMin=%d\n", ppem, height, font->yMax, font->yMin);
1121                     break;
1122                 }
1123             }
1124             if(!font->yMax) {
1125                 ppem = 0;
1126                 TRACE("ppem not found for height %ld\n", height);
1127             }
1128         } else {
1129             ppem = -height;
1130             if(ppem < startsz || ppem > endsz)
1131                 goto end;
1132
1133             for(i = 0; i < recs; i++) {
1134                 USHORT yPelHeight;
1135                 yPelHeight = GET_BE_WORD(&vTable[i * 6]);
1136
1137                 if(yPelHeight > ppem)
1138                     break; /* failed */
1139
1140                 if(yPelHeight == ppem) {
1141                     font->yMax = GET_BE_WORD(&vTable[(i * 6) + 2]);
1142                     font->yMin = GET_BE_WORD(&vTable[(i * 6) + 4]);
1143                     TRACE("ppem %ld found; yMax=%d  yMin=%d\n", ppem, font->yMax, font->yMin);
1144                     break;
1145                 }
1146             }
1147         }
1148         end:
1149         HeapFree(GetProcessHeap(), 0, vTable);
1150     }
1151
1152     return ppem;
1153 }
1154
1155
1156 /*************************************************************
1157  * WineEngCreateFontInstance
1158  *
1159  */
1160 GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
1161 {
1162     GdiFont ret;
1163     Face *face;
1164     Family *family = NULL;
1165     BOOL bd, it;
1166     LOGFONTW lf;
1167     CHARSETINFO csi;
1168
1169     if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
1170
1171     TRACE("%s, h=%ld, it=%d, weight=%ld, PandF=%02x, charset=%d orient %ld escapement %ld\n",
1172           debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
1173           lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
1174           lf.lfEscapement);
1175
1176     /* check the cache first */
1177     for(ret = GdiFontList; ret; ret = ret->next) {
1178         if(ret->hfont == hfont && !memcmp(&ret->xform, &dc->xformWorld2Vport, offsetof(XFORM, eDx))) {
1179             TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
1180             return ret;
1181         }
1182     }
1183
1184     if(!FontList || !have_installed_roman_font) /* No fonts installed */
1185     {
1186         TRACE("No fonts installed\n");
1187         return NULL;
1188     }
1189
1190     ret = alloc_font();
1191     memcpy(&ret->xform, &dc->xformWorld2Vport, sizeof(XFORM));
1192
1193     /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
1194        SYMBOL_CHARSET so that Symbol gets picked irrespective of the
1195        original value lfCharSet.  Note this is a special case for
1196        Symbol and doesn't happen at least for "Wingdings*" */
1197
1198     if(!strcmpiW(lf.lfFaceName, SymbolW))
1199         lf.lfCharSet = SYMBOL_CHARSET;
1200
1201     if(!TranslateCharsetInfo((DWORD*)(INT)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
1202         switch(lf.lfCharSet) {
1203         case DEFAULT_CHARSET:
1204             csi.fs.fsCsb[0] = 0;
1205             break;
1206         default:
1207             FIXME("Untranslated charset %d\n", lf.lfCharSet);
1208             csi.fs.fsCsb[0] = 0;
1209             break;
1210         }
1211     }
1212
1213     if(lf.lfFaceName[0] != '\0') {
1214         FontSubst *psub;
1215         for(psub = substlist; psub; psub = psub->next)
1216             if(!strcmpiW(lf.lfFaceName, psub->from.name) &&
1217                (psub->from.charset == -1 ||
1218                 psub->from.charset == lf.lfCharSet))
1219               break;
1220         if(psub) {
1221             TRACE("substituting %s -> %s\n", debugstr_w(lf.lfFaceName),
1222                   debugstr_w(psub->to.name));
1223             strcpyW(lf.lfFaceName, psub->to.name);
1224         }
1225
1226         /* We want a match on name and charset or just name if
1227            charset was DEFAULT_CHARSET.  If the latter then
1228            we fixup the returned charset later in get_nearest_charset
1229            where we'll either use the charset of the current ansi codepage
1230            or if that's unavailable the first charset that the font supports.
1231         */
1232         for(family = FontList; family; family = family->next) {
1233             if(!strcmpiW(family->FamilyName, lf.lfFaceName))
1234                 if((csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) || !csi.fs.fsCsb[0])
1235                     break;
1236         }
1237
1238         if(!family) { /* do other aliases here */
1239             if(!strcmpiW(lf.lfFaceName, SystemW))
1240                 strcpyW(lf.lfFaceName, defSystem);
1241             else if(!strcmpiW(lf.lfFaceName, MSSansSerifW))
1242                 strcpyW(lf.lfFaceName, defSans);
1243             else if(!strcmpiW(lf.lfFaceName, HelvW))
1244                 strcpyW(lf.lfFaceName, defSans);
1245             else
1246                 goto not_found;
1247
1248             for(family = FontList; family; family = family->next) {
1249                 if(!strcmpiW(family->FamilyName, lf.lfFaceName))
1250                   if((csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) || !csi.fs.fsCsb[0])
1251                       break;
1252             }
1253         }
1254     }
1255
1256 not_found:
1257     if(!family) {
1258       /* If requested charset was DEFAULT_CHARSET then try using charset
1259          corresponding to the current ansi codepage */
1260         if(!csi.fs.fsCsb[0]) {
1261             INT acp = GetACP();
1262             if(!TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE)) {
1263                 FIXME("TCI failed on codepage %d\n", acp);
1264                 csi.fs.fsCsb[0] = 0;
1265             } else
1266                 lf.lfCharSet = csi.ciCharset;
1267         }
1268
1269                 /* Face families are in the top 4 bits of lfPitchAndFamily,
1270                    so mask with 0xF0 before testing */
1271
1272         if((lf.lfPitchAndFamily & FIXED_PITCH) ||
1273            (lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
1274           strcpyW(lf.lfFaceName, defFixed);
1275         else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
1276           strcpyW(lf.lfFaceName, defSerif);
1277         else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
1278           strcpyW(lf.lfFaceName, defSans);
1279         else
1280           strcpyW(lf.lfFaceName, defSans);
1281         for(family = FontList; family; family = family->next) {
1282             if(!strcmpiW(family->FamilyName, lf.lfFaceName) &&
1283                (csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]))
1284                 break;
1285         }
1286     }
1287
1288     if(!family) {
1289         for(family = FontList; family; family = family->next) {
1290             if(csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0])
1291                 break;
1292         }
1293     }
1294
1295     if(!family) {
1296         family = FontList;
1297         csi.fs.fsCsb[0] = 0;
1298         FIXME("just using first face for now\n");
1299     }
1300
1301     it = lf.lfItalic ? 1 : 0;
1302     bd = lf.lfWeight > 550 ? 1 : 0;
1303
1304     for(face = family->FirstFace; face; face = face->next) {
1305       if(!(face->Italic ^ it) && !(face->Bold ^ bd))
1306         break;
1307     }
1308     if(!face) {
1309         face = family->FirstFace;
1310         if(it && !face->Italic) ret->fake_italic = TRUE;
1311         if(bd && !face->Bold) ret->fake_bold = TRUE;
1312     }
1313
1314     memcpy(&ret->fs, &face->fs, sizeof(FONTSIGNATURE));
1315
1316     if(csi.fs.fsCsb[0])
1317         ret->charset = lf.lfCharSet;
1318     else
1319         ret->charset = get_nearest_charset(face);
1320
1321     TRACE("Chosen: %s %s\n", debugstr_w(family->FamilyName),
1322           debugstr_w(face->StyleName));
1323
1324     ret->ft_face = OpenFontFile(ret, face->file, face->face_index,
1325                                 lf.lfHeight < 0 ?
1326                                 -abs(INTERNAL_YWSTODS(dc,lf.lfHeight)) :
1327                                 abs(INTERNAL_YWSTODS(dc, lf.lfHeight)));
1328     if (!ret->ft_face)
1329     {
1330         free_font( ret );
1331         return 0;
1332     }
1333
1334     if (ret->charset == SYMBOL_CHARSET && 
1335         !pFT_Select_Charmap(ret->ft_face, ft_encoding_symbol)) {
1336         /* No ops */
1337     }
1338     else if (!pFT_Select_Charmap(ret->ft_face, ft_encoding_unicode)) {
1339         /* No ops */
1340     }
1341     else {
1342         pFT_Select_Charmap(ret->ft_face, ft_encoding_apple_roman);
1343     }
1344
1345     ret->orientation = lf.lfOrientation;
1346     ret->name = strdupW(family->FamilyName);
1347
1348     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
1349     ret->hfont = hfont;
1350     ret->aveWidth= lf.lfWidth;
1351     ret->next = GdiFontList;
1352     GdiFontList = ret;
1353
1354     return ret;
1355 }
1356
1357 static void DumpGdiFontList(void)
1358 {
1359     GdiFont gdiFont;
1360
1361     TRACE("---------- gdiFont Cache ----------\n");
1362     for(gdiFont = GdiFontList; gdiFont; gdiFont = gdiFont->next) {
1363         LOGFONTW lf;
1364         GetObjectW( gdiFont->hfont, sizeof(lf), &lf );
1365         TRACE("gdiFont=%p  hfont=%p (%s)\n",
1366                gdiFont, gdiFont->hfont, debugstr_w(lf.lfFaceName));
1367     }
1368 }
1369
1370 /*************************************************************
1371  * WineEngDestroyFontInstance
1372  *
1373  * free the gdiFont associated with this handle
1374  *
1375  */
1376 BOOL WineEngDestroyFontInstance(HFONT handle)
1377 {
1378     GdiFont gdiFont;
1379     GdiFont gdiPrev = NULL;
1380     BOOL ret = FALSE;
1381
1382     TRACE("destroying hfont=%p\n", handle);
1383     if(TRACE_ON(font))
1384         DumpGdiFontList();
1385
1386     gdiFont = GdiFontList;
1387     while(gdiFont) {
1388         if(gdiFont->hfont == handle) {
1389             if(gdiPrev) {
1390                 gdiPrev->next = gdiFont->next;
1391                 free_font(gdiFont);
1392                 gdiFont = gdiPrev->next;
1393             } else {
1394                 GdiFontList = gdiFont->next;
1395                 free_font(gdiFont);
1396                 gdiFont = GdiFontList;
1397             }
1398             ret = TRUE;
1399         } else {
1400             gdiPrev = gdiFont;
1401             gdiFont = gdiFont->next;
1402         }
1403     }
1404     return ret;
1405 }
1406
1407 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
1408                            NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
1409 {
1410     OUTLINETEXTMETRICW *potm;
1411     UINT size;
1412     GdiFont font = alloc_font();
1413
1414     if (!(font->ft_face = OpenFontFile(font, face->file, face->face_index, 100)))
1415     {
1416         free_font(font);
1417         return;
1418     }
1419
1420     font->name = strdupW(face->family->FamilyName);
1421
1422     memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
1423
1424     size = WineEngGetOutlineTextMetrics(font, 0, NULL);
1425     potm = HeapAlloc(GetProcessHeap(), 0, size);
1426     WineEngGetOutlineTextMetrics(font, size, potm);
1427
1428 #define TM potm->otmTextMetrics
1429
1430     pntm->ntmTm.tmHeight = pelf->elfLogFont.lfHeight = TM.tmHeight;
1431     pntm->ntmTm.tmAscent = TM.tmAscent;
1432     pntm->ntmTm.tmDescent = TM.tmDescent;
1433     pntm->ntmTm.tmInternalLeading = TM.tmInternalLeading;
1434     pntm->ntmTm.tmExternalLeading = TM.tmExternalLeading;
1435     pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWidth = TM.tmAveCharWidth;
1436     pntm->ntmTm.tmMaxCharWidth = TM.tmMaxCharWidth;
1437     pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = TM.tmWeight;
1438     pntm->ntmTm.tmOverhang = TM.tmOverhang;
1439     pntm->ntmTm.tmDigitizedAspectX = TM.tmDigitizedAspectX;
1440     pntm->ntmTm.tmDigitizedAspectY = TM.tmDigitizedAspectY;
1441     pntm->ntmTm.tmFirstChar = TM.tmFirstChar;
1442     pntm->ntmTm.tmLastChar = TM.tmLastChar;
1443     pntm->ntmTm.tmDefaultChar = TM.tmDefaultChar;
1444     pntm->ntmTm.tmBreakChar = TM.tmBreakChar;
1445     pntm->ntmTm.tmItalic = pelf->elfLogFont.lfItalic = TM.tmItalic;
1446     pntm->ntmTm.tmUnderlined = pelf->elfLogFont.lfUnderline = TM.tmUnderlined;
1447     pntm->ntmTm.tmStruckOut = pelf->elfLogFont.lfStrikeOut = TM.tmStruckOut;
1448     pntm->ntmTm.tmPitchAndFamily = TM.tmPitchAndFamily;
1449     pelf->elfLogFont.lfPitchAndFamily = (TM.tmPitchAndFamily & 0xf1) + 1;
1450     pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = TM.tmCharSet;
1451     pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
1452     pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
1453     pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
1454
1455     pntm->ntmTm.ntmFlags = TM.tmItalic ? NTM_ITALIC : 0;
1456     if(TM.tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD;
1457     if(pntm->ntmTm.ntmFlags == 0) pntm->ntmTm.ntmFlags = NTM_REGULAR;
1458
1459     pntm->ntmTm.ntmSizeEM = potm->otmEMSquare;
1460     pntm->ntmTm.ntmCellHeight = 0;
1461     pntm->ntmTm.ntmAvgWidth = 0;
1462
1463     *ptype = TM.tmPitchAndFamily & TMPF_TRUETYPE ? TRUETYPE_FONTTYPE : 0;
1464     if(!(TM.tmPitchAndFamily & TMPF_VECTOR))
1465         *ptype |= RASTER_FONTTYPE;
1466
1467 #undef TM
1468     memset(&pntm->ntmFontSig, 0, sizeof(FONTSIGNATURE));
1469
1470     strncpyW(pelf->elfLogFont.lfFaceName,
1471              (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFamilyName),
1472              LF_FACESIZE);
1473     strncpyW(pelf->elfFullName,
1474              (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFaceName),
1475              LF_FULLFACESIZE);
1476     strncpyW(pelf->elfStyle,
1477              (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName),
1478              LF_FACESIZE);
1479     pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
1480
1481     HeapFree(GetProcessHeap(), 0, potm);
1482     free_font(font);
1483     return;
1484 }
1485
1486 /*************************************************************
1487  * WineEngEnumFonts
1488  *
1489  */
1490 DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc,
1491                        LPARAM lparam)
1492 {
1493     Family *family;
1494     Face *face;
1495     ENUMLOGFONTEXW elf;
1496     NEWTEXTMETRICEXW ntm;
1497     DWORD type, ret = 1;
1498     FONTSIGNATURE fs;
1499     CHARSETINFO csi;
1500     LOGFONTW lf;
1501     int i;
1502
1503     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
1504
1505     if(plf->lfFaceName[0]) {
1506         FontSubst *psub;
1507         for(psub = substlist; psub; psub = psub->next)
1508             if(!strcmpiW(plf->lfFaceName, psub->from.name) &&
1509                (psub->from.charset == -1 ||
1510                 psub->from.charset == plf->lfCharSet))
1511                 break;
1512         if(psub) {
1513             TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
1514                   debugstr_w(psub->to.name));
1515             memcpy(&lf, plf, sizeof(lf));
1516             strcpyW(lf.lfFaceName, psub->to.name);
1517             plf = &lf;
1518         }
1519         for(family = FontList; family; family = family->next) {
1520             if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
1521                 for(face = family->FirstFace; face; face = face->next) {
1522                     GetEnumStructs(face, &elf, &ntm, &type);
1523                     for(i = 0; i < 32; i++) {
1524                         if(face->fs.fsCsb[0] & (1L << i)) {
1525                             fs.fsCsb[0] = 1L << i;
1526                             fs.fsCsb[1] = 0;
1527                             if(!TranslateCharsetInfo(fs.fsCsb, &csi,
1528                                                      TCI_SRCFONTSIG))
1529                                 csi.ciCharset = DEFAULT_CHARSET;
1530                             if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
1531                             if(csi.ciCharset != DEFAULT_CHARSET) {
1532                                 elf.elfLogFont.lfCharSet =
1533                                   ntm.ntmTm.tmCharSet = csi.ciCharset;
1534                                 if(ElfScriptsW[i])
1535                                     strcpyW(elf.elfScript, ElfScriptsW[i]);
1536                                 else
1537                                     FIXME("Unknown elfscript for bit %d\n", i);
1538                                 TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
1539                                       debugstr_w(elf.elfLogFont.lfFaceName),
1540                                       debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
1541                                       csi.ciCharset, type, debugstr_w(elf.elfScript),
1542                                       elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
1543                                       ntm.ntmTm.ntmFlags);
1544                                 ret = proc(&elf, &ntm, type, lparam);
1545                                 if(!ret) goto end;
1546                             }
1547                         }
1548                     }
1549                 }
1550             }
1551         }
1552     } else {
1553         for(family = FontList; family; family = family->next) {
1554             GetEnumStructs(family->FirstFace, &elf, &ntm, &type);
1555             for(i = 0; i < 32; i++) {
1556                 if(family->FirstFace->fs.fsCsb[0] & (1L << i)) {
1557                     fs.fsCsb[0] = 1L << i;
1558                     fs.fsCsb[1] = 0;
1559                     if(!TranslateCharsetInfo(fs.fsCsb, &csi,
1560                                              TCI_SRCFONTSIG))
1561                         csi.ciCharset = DEFAULT_CHARSET;
1562                     if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
1563                     if(csi.ciCharset != DEFAULT_CHARSET) {
1564                         elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet =
1565                           csi.ciCharset;
1566                           if(ElfScriptsW[i])
1567                               strcpyW(elf.elfScript, ElfScriptsW[i]);
1568                           else
1569                               FIXME("Unknown elfscript for bit %d\n", i);
1570                         TRACE("enuming face %s full %s style %s charset = %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
1571                               debugstr_w(elf.elfLogFont.lfFaceName),
1572                               debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
1573                               csi.ciCharset, type, debugstr_w(elf.elfScript),
1574                               elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
1575                               ntm.ntmTm.ntmFlags);
1576                         ret = proc(&elf, &ntm, type, lparam);
1577                         if(!ret) goto end;
1578                     }
1579                 }
1580             }
1581         }
1582     }
1583 end:
1584     return ret;
1585 }
1586
1587 static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
1588 {
1589     pt->x.value = vec->x >> 6;
1590     pt->x.fract = (vec->x & 0x3f) << 10;
1591     pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
1592     pt->y.value = vec->y >> 6;
1593     pt->y.fract = (vec->y & 0x3f) << 10;
1594     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
1595     return;
1596 }
1597
1598 static FT_UInt get_glyph_index(GdiFont font, UINT glyph)
1599 {
1600     if(font->charset == SYMBOL_CHARSET && glyph < 0x100)
1601         glyph = glyph + 0xf000;
1602     return pFT_Get_Char_Index(font->ft_face, glyph);
1603 }
1604
1605 /*************************************************************
1606  * WineEngGetGlyphIndices
1607  *
1608  * FIXME: add support for GGI_MARK_NONEXISTING_GLYPHS
1609  */
1610 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
1611                                 LPWORD pgi, DWORD flags)
1612 {
1613     INT i;
1614
1615     for(i = 0; i < count; i++)
1616         pgi[i] = get_glyph_index(font, lpstr[i]);
1617
1618     return count;
1619 }
1620
1621 /*************************************************************
1622  * WineEngGetGlyphOutline
1623  *
1624  * Behaves in exactly the same way as the win32 api GetGlyphOutline
1625  * except that the first parameter is the HWINEENGFONT of the font in
1626  * question rather than an HDC.
1627  *
1628  */
1629 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
1630                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
1631                              const MAT2* lpmat)
1632 {
1633     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
1634     FT_Face ft_face = font->ft_face;
1635     FT_UInt glyph_index;
1636     DWORD width, height, pitch, needed = 0;
1637     FT_Bitmap ft_bitmap;
1638     FT_Error err;
1639     INT left, right, top = 0, bottom = 0;
1640     FT_Angle angle = 0;
1641     FT_Int load_flags = FT_LOAD_DEFAULT;
1642     float widthRatio = 1.0;     
1643     FT_Matrix transMat = identityMat;
1644     BOOL needsTransform = FALSE;
1645
1646
1647     TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm,
1648           buflen, buf, lpmat);
1649
1650     if(format & GGO_GLYPH_INDEX) {
1651         glyph_index = glyph;
1652         format &= ~GGO_GLYPH_INDEX;
1653     } else
1654         glyph_index = get_glyph_index(font, glyph);
1655
1656     if(glyph_index >= font->gmsize) {
1657         font->gmsize = (glyph_index / INIT_GM_SIZE + 1) * INIT_GM_SIZE;
1658         font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
1659                                font->gmsize * sizeof(*font->gm));
1660     } else {
1661         if(format == GGO_METRICS && font->gm[glyph_index].init) {
1662             memcpy(lpgm, &font->gm[glyph_index].gm, sizeof(*lpgm));
1663             return 1; /* FIXME */
1664         }
1665     }
1666
1667     if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP) || font->aveWidth || lpmat)
1668         load_flags |= FT_LOAD_NO_BITMAP;
1669
1670     err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
1671
1672     if(err) {
1673         FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
1674         return GDI_ERROR;
1675     }
1676         
1677     /* Scaling factor */
1678     if (font->aveWidth && font->potm) {
1679              widthRatio = (float)font->aveWidth * font->xform.eM11 / (float) font->potm->otmTextMetrics.tmAveCharWidth;
1680     }
1681
1682     left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
1683     right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
1684
1685     font->gm[glyph_index].adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
1686     font->gm[glyph_index].lsb = left >> 6;
1687     font->gm[glyph_index].bbx = (right - left) >> 6;
1688
1689     /* Scaling transform */
1690     if(font->aveWidth) {
1691         FT_Matrix scaleMat;
1692         scaleMat.xx = FT_FixedFromFloat(widthRatio);
1693         scaleMat.xy = 0;
1694         scaleMat.yx = 0;
1695         scaleMat.yy = (1 << 16);
1696
1697         pFT_Matrix_Multiply(&scaleMat, &transMat);
1698         needsTransform = TRUE;
1699     }
1700
1701     /* Rotation transform */
1702     if(font->orientation) {
1703         FT_Matrix rotationMat;
1704         FT_Vector vecAngle;
1705         angle = FT_FixedFromFloat((float)font->orientation / 10.0);
1706         pFT_Vector_Unit(&vecAngle, angle);
1707         rotationMat.xx = vecAngle.x;
1708         rotationMat.xy = -vecAngle.y;
1709         rotationMat.yx = -rotationMat.xy;
1710         rotationMat.yy = rotationMat.xx;
1711         
1712         pFT_Matrix_Multiply(&rotationMat, &transMat);
1713         needsTransform = TRUE;
1714     }
1715
1716     /* Extra transformation specified by caller */
1717     if (lpmat) {
1718         FT_Matrix extraMat;
1719         extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
1720         extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
1721         extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
1722         extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
1723         pFT_Matrix_Multiply(&extraMat, &transMat);
1724         needsTransform = TRUE;
1725     }
1726
1727     if(!needsTransform) {
1728         top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
1729         bottom = (ft_face->glyph->metrics.horiBearingY -
1730                   ft_face->glyph->metrics.height) & -64;
1731         lpgm->gmCellIncX = font->gm[glyph_index].adv;
1732         lpgm->gmCellIncY = 0;
1733     } else {
1734         INT xc, yc;
1735         FT_Vector vec;
1736         for(xc = 0; xc < 2; xc++) {
1737             for(yc = 0; yc < 2; yc++) {
1738                 vec.x = (ft_face->glyph->metrics.horiBearingX +
1739                   xc * ft_face->glyph->metrics.width);
1740                 vec.y = ft_face->glyph->metrics.horiBearingY -
1741                   yc * ft_face->glyph->metrics.height;
1742                 TRACE("Vec %ld,%ld\n", vec.x, vec.y);
1743                 pFT_Vector_Transform(&vec, &transMat);
1744                 if(xc == 0 && yc == 0) {
1745                     left = right = vec.x;
1746                     top = bottom = vec.y;
1747                 } else {
1748                     if(vec.x < left) left = vec.x;
1749                     else if(vec.x > right) right = vec.x;
1750                     if(vec.y < bottom) bottom = vec.y;
1751                     else if(vec.y > top) top = vec.y;
1752                 }
1753             }
1754         }
1755         left = left & -64;
1756         right = (right + 63) & -64;
1757         bottom = bottom & -64;
1758         top = (top + 63) & -64;
1759
1760         TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
1761         vec.x = ft_face->glyph->metrics.horiAdvance;
1762         vec.y = 0;
1763         pFT_Vector_Transform(&vec, &transMat);
1764         lpgm->gmCellIncX = (vec.x+63) >> 6;
1765         lpgm->gmCellIncY = -((vec.y+63) >> 6);
1766     }
1767     lpgm->gmBlackBoxX = (right - left) >> 6;
1768     lpgm->gmBlackBoxY = (top - bottom) >> 6;
1769     lpgm->gmptGlyphOrigin.x = left >> 6;
1770     lpgm->gmptGlyphOrigin.y = top >> 6;
1771
1772     memcpy(&font->gm[glyph_index].gm, lpgm, sizeof(*lpgm));
1773     font->gm[glyph_index].init = TRUE;
1774
1775     if(format == GGO_METRICS)
1776         return 1; /* FIXME */
1777
1778     if (buf && !buflen){
1779         return GDI_ERROR;
1780     }
1781
1782     if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) {
1783         FIXME("loaded a bitmap\n");
1784         return GDI_ERROR;
1785     }
1786
1787     switch(format) {
1788     case GGO_BITMAP:
1789         width = lpgm->gmBlackBoxX;
1790         height = lpgm->gmBlackBoxY;
1791         pitch = ((width + 31) >> 5) << 2;
1792         needed = pitch * height;
1793
1794         if(!buf || !buflen) break;
1795
1796         switch(ft_face->glyph->format) {
1797         case ft_glyph_format_bitmap:
1798           {
1799             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
1800             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
1801             INT h = ft_face->glyph->bitmap.rows;
1802             while(h--) {
1803                 memcpy(dst, src, w);
1804                 src += ft_face->glyph->bitmap.pitch;
1805                 dst += pitch;
1806             }
1807             break;
1808           }
1809
1810         case ft_glyph_format_outline:
1811             ft_bitmap.width = width;
1812             ft_bitmap.rows = height;
1813             ft_bitmap.pitch = pitch;
1814             ft_bitmap.pixel_mode = ft_pixel_mode_mono;
1815             ft_bitmap.buffer = buf;
1816
1817                 if(needsTransform) {
1818                         pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
1819             }
1820
1821             pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
1822
1823             /* Note: FreeType will only set 'black' bits for us. */
1824             memset(buf, 0, needed);
1825             pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
1826             break;
1827
1828         default:
1829             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
1830             return GDI_ERROR;
1831         }
1832         break;
1833
1834     case GGO_GRAY2_BITMAP:
1835     case GGO_GRAY4_BITMAP:
1836     case GGO_GRAY8_BITMAP:
1837     case WINE_GGO_GRAY16_BITMAP:
1838       {
1839         int mult, row, col;
1840         BYTE *start, *ptr;
1841
1842         width = lpgm->gmBlackBoxX;
1843         height = lpgm->gmBlackBoxY;
1844         pitch = (width + 3) / 4 * 4;
1845         needed = pitch * height;
1846
1847         if(!buf || !buflen) break;
1848         ft_bitmap.width = width;
1849         ft_bitmap.rows = height;
1850         ft_bitmap.pitch = pitch;
1851         ft_bitmap.pixel_mode = ft_pixel_mode_grays;
1852         ft_bitmap.buffer = buf;
1853
1854         if(needsTransform) {
1855                 pFT_Outline_Transform(&ft_face->glyph->outline, &transMat);
1856         }
1857
1858         pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
1859
1860         pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
1861
1862         if(format == GGO_GRAY2_BITMAP)
1863             mult = 5;
1864         else if(format == GGO_GRAY4_BITMAP)
1865             mult = 17;
1866         else if(format == GGO_GRAY8_BITMAP)
1867             mult = 65;
1868         else if(format == WINE_GGO_GRAY16_BITMAP)
1869             break;
1870         else {
1871             assert(0);
1872             break;
1873         }
1874
1875         start = buf;
1876         for(row = 0; row < height; row++) {
1877             ptr = start;
1878             for(col = 0; col < width; col++, ptr++) {
1879                 *ptr = (*(unsigned int*)ptr * mult + 128) / 256;
1880             }
1881             start += pitch;
1882         }
1883         break;
1884       }
1885
1886     case GGO_NATIVE:
1887       {
1888         int contour, point = 0, first_pt;
1889         FT_Outline *outline = &ft_face->glyph->outline;
1890         TTPOLYGONHEADER *pph;
1891         TTPOLYCURVE *ppc;
1892         DWORD pph_start, cpfx, type;
1893
1894         if(buflen == 0) buf = NULL;
1895
1896         if (needsTransform && buf) {
1897                 pFT_Outline_Transform(outline, &transMat);
1898         }
1899
1900         for(contour = 0; contour < outline->n_contours; contour++) {
1901             pph_start = needed;
1902             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
1903             first_pt = point;
1904             if(buf) {
1905                 pph->dwType = TT_POLYGON_TYPE;
1906                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
1907             }
1908             needed += sizeof(*pph);
1909             point++;
1910             while(point <= outline->contours[contour]) {
1911                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
1912                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
1913                   TT_PRIM_LINE : TT_PRIM_QSPLINE;
1914                 cpfx = 0;
1915                 do {
1916                     if(buf)
1917                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
1918                     cpfx++;
1919                     point++;
1920                 } while(point <= outline->contours[contour] &&
1921                         (outline->tags[point] & FT_Curve_Tag_On) ==
1922                         (outline->tags[point-1] & FT_Curve_Tag_On));
1923                 /* At the end of a contour Windows adds the start point, but
1924                    only for Beziers */
1925                 if(point > outline->contours[contour] &&
1926                    !(outline->tags[point-1] & FT_Curve_Tag_On)) {
1927                     if(buf)
1928                         FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
1929                     cpfx++;
1930                 } else if(point <= outline->contours[contour] &&
1931                           outline->tags[point] & FT_Curve_Tag_On) {
1932                   /* add closing pt for bezier */
1933                     if(buf)
1934                         FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
1935                     cpfx++;
1936                     point++;
1937                 }
1938                 if(buf) {
1939                     ppc->wType = type;
1940                     ppc->cpfx = cpfx;
1941                 }
1942                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
1943             }
1944             if(buf)
1945                 pph->cb = needed - pph_start;
1946         }
1947         break;
1948       }
1949     case GGO_BEZIER:
1950       {
1951         /* Convert the quadratic Beziers to cubic Beziers.
1952            The parametric eqn for a cubic Bezier is, from PLRM:
1953            r(t) = at^3 + bt^2 + ct + r0
1954            with the control points:
1955            r1 = r0 + c/3
1956            r2 = r1 + (c + b)/3
1957            r3 = r0 + c + b + a
1958
1959            A quadratic Beizer has the form:
1960            p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
1961
1962            So equating powers of t leads to:
1963            r1 = 2/3 p1 + 1/3 p0
1964            r2 = 2/3 p1 + 1/3 p2
1965            and of course r0 = p0, r3 = p2
1966         */
1967
1968         int contour, point = 0, first_pt;
1969         FT_Outline *outline = &ft_face->glyph->outline;
1970         TTPOLYGONHEADER *pph;
1971         TTPOLYCURVE *ppc;
1972         DWORD pph_start, cpfx, type;
1973         FT_Vector cubic_control[4];
1974         if(buflen == 0) buf = NULL;
1975
1976         if (needsTransform && buf) {
1977                 pFT_Outline_Transform(outline, &transMat);
1978         }
1979
1980         for(contour = 0; contour < outline->n_contours; contour++) {
1981             pph_start = needed;
1982             pph = (TTPOLYGONHEADER *)((char *)buf + needed);
1983             first_pt = point;
1984             if(buf) {
1985                 pph->dwType = TT_POLYGON_TYPE;
1986                 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
1987             }
1988             needed += sizeof(*pph);
1989             point++;
1990             while(point <= outline->contours[contour]) {
1991                 ppc = (TTPOLYCURVE *)((char *)buf + needed);
1992                 type = (outline->tags[point] & FT_Curve_Tag_On) ?
1993                   TT_PRIM_LINE : TT_PRIM_CSPLINE;
1994                 cpfx = 0;
1995                 do {
1996                     if(type == TT_PRIM_LINE) {
1997                         if(buf)
1998                             FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
1999                         cpfx++;
2000                         point++;
2001                     } else {
2002                       /* Unlike QSPLINEs, CSPLINEs always have their endpoint
2003                          so cpfx = 3n */
2004
2005                       /* FIXME: Possible optimization in endpoint calculation
2006                          if there are two consecutive curves */
2007                         cubic_control[0] = outline->points[point-1];
2008                         if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
2009                             cubic_control[0].x += outline->points[point].x + 1;
2010                             cubic_control[0].y += outline->points[point].y + 1;
2011                             cubic_control[0].x >>= 1;
2012                             cubic_control[0].y >>= 1;
2013                         }
2014                         if(point+1 > outline->contours[contour])
2015                             cubic_control[3] = outline->points[first_pt];
2016                         else {
2017                             cubic_control[3] = outline->points[point+1];
2018                             if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
2019                                 cubic_control[3].x += outline->points[point].x + 1;
2020                                 cubic_control[3].y += outline->points[point].y + 1;
2021                                 cubic_control[3].x >>= 1;
2022                                 cubic_control[3].y >>= 1;
2023                             }
2024                         }
2025                         /* r1 = 1/3 p0 + 2/3 p1
2026                            r2 = 1/3 p2 + 2/3 p1 */
2027                         cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
2028                         cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
2029                         cubic_control[2] = cubic_control[1];
2030                         cubic_control[1].x += (cubic_control[0].x + 1) / 3;
2031                         cubic_control[1].y += (cubic_control[0].y + 1) / 3;
2032                         cubic_control[2].x += (cubic_control[3].x + 1) / 3;
2033                         cubic_control[2].y += (cubic_control[3].y + 1) / 3;
2034                         if(buf) {
2035                             FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
2036                             FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
2037                             FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
2038                         }
2039                         cpfx += 3;
2040                         point++;
2041                     }
2042                 } while(point <= outline->contours[contour] &&
2043                         (outline->tags[point] & FT_Curve_Tag_On) ==
2044                         (outline->tags[point-1] & FT_Curve_Tag_On));
2045                 /* At the end of a contour Windows adds the start point,
2046                    but only for Beziers and we've already done that.
2047                 */
2048                 if(point <= outline->contours[contour] &&
2049                    outline->tags[point] & FT_Curve_Tag_On) {
2050                   /* This is the closing pt of a bezier, but we've already
2051                      added it, so just inc point and carry on */
2052                     point++;
2053                 }
2054                 if(buf) {
2055                     ppc->wType = type;
2056                     ppc->cpfx = cpfx;
2057                 }
2058                 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
2059             }
2060             if(buf)
2061                 pph->cb = needed - pph_start;
2062         }
2063         break;
2064       }
2065
2066     default:
2067         FIXME("Unsupported format %d\n", format);
2068         return GDI_ERROR;
2069     }
2070     return needed;
2071 }
2072
2073 /*************************************************************
2074  * WineEngGetTextMetrics
2075  *
2076  */
2077 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
2078 {
2079     if(!font->potm) {
2080         if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
2081             return FALSE;
2082     }
2083     if(!font->potm) return FALSE;
2084     memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm));
2085
2086     if (font->aveWidth) {
2087              ptm->tmAveCharWidth = font->aveWidth * font->xform.eM11;
2088     }
2089     return TRUE;
2090 }
2091
2092
2093 /*************************************************************
2094  * WineEngGetOutlineTextMetrics
2095  *
2096  */
2097 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
2098                                   OUTLINETEXTMETRICW *potm)
2099 {
2100     FT_Face ft_face = font->ft_face;
2101     UINT needed, lenfam, lensty, ret;
2102     TT_OS2 *pOS2;
2103     TT_HoriHeader *pHori;
2104     TT_Postscript *pPost;
2105     FT_Fixed x_scale, y_scale;
2106     WCHAR *family_nameW, *style_nameW;
2107     WCHAR spaceW[] = {' ', '\0'};
2108     char *cp;
2109
2110     TRACE("font=%p\n", font);
2111
2112     if(font->potm) {
2113         if(cbSize >= font->potm->otmSize)
2114             memcpy(potm, font->potm, font->potm->otmSize);
2115         return font->potm->otmSize;
2116     }
2117
2118     needed = sizeof(*potm);
2119
2120     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
2121     family_nameW = strdupW(font->name);
2122
2123     lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
2124       * sizeof(WCHAR);
2125     style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
2126     MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
2127                         style_nameW, lensty);
2128
2129     /* These names should be read from the TT name table */
2130
2131     /* length of otmpFamilyName */
2132     needed += lenfam;
2133
2134     /* length of otmpFaceName */
2135     if(!strcasecmp(ft_face->style_name, "regular")) {
2136       needed += lenfam; /* just the family name */
2137     } else {
2138       needed += lenfam + lensty; /* family + " " + style */
2139     }
2140
2141     /* length of otmpStyleName */
2142     needed += lensty;
2143
2144     /* length of otmpFullName */
2145     needed += lenfam + lensty;
2146
2147
2148     x_scale = ft_face->size->metrics.x_scale;
2149     y_scale = ft_face->size->metrics.y_scale;
2150
2151     pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
2152     if(!pOS2) {
2153         FIXME("Can't find OS/2 table - not TT font?\n");
2154         ret = 0;
2155         goto end;
2156     }
2157
2158     pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
2159     if(!pHori) {
2160         FIXME("Can't find HHEA table - not TT font?\n");
2161         ret = 0;
2162         goto end;
2163     }
2164
2165     pPost = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_post); /* we can live with this failing */
2166
2167     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",
2168           pOS2->usWinAscent, pOS2->usWinDescent,
2169           pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
2170           ft_face->ascender, ft_face->descender, ft_face->height,
2171           pHori->Ascender, pHori->Descender, pHori->Line_Gap,
2172           ft_face->bbox.yMax, ft_face->bbox.yMin);
2173
2174     font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
2175     font->potm->otmSize = needed;
2176
2177 #define TM font->potm->otmTextMetrics
2178
2179     if(font->yMax) {
2180         TM.tmAscent = font->yMax;
2181         TM.tmDescent = -font->yMin;
2182         TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
2183     } else {
2184         TM.tmAscent = (pFT_MulFix(pOS2->usWinAscent, y_scale) + 32) >> 6;
2185         TM.tmDescent = (pFT_MulFix(pOS2->usWinDescent, y_scale) + 32) >> 6;
2186         TM.tmInternalLeading = (pFT_MulFix(pOS2->usWinAscent + pOS2->usWinDescent
2187                                             - ft_face->units_per_EM, y_scale) + 32) >> 6;
2188     }
2189
2190     TM.tmHeight = TM.tmAscent + TM.tmDescent;
2191
2192     /* MSDN says:
2193      el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
2194     */
2195     TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
2196                  ((pOS2->usWinAscent + pOS2->usWinDescent) -
2197                   (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
2198
2199     TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
2200     if (TM.tmAveCharWidth == 0) {
2201         TM.tmAveCharWidth = 1; 
2202     }
2203     TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
2204     TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
2205     TM.tmOverhang = 0;
2206     TM.tmDigitizedAspectX = 300;
2207     TM.tmDigitizedAspectY = 300;
2208     TM.tmFirstChar = pOS2->usFirstCharIndex;
2209     TM.tmLastChar = pOS2->usLastCharIndex;
2210     TM.tmDefaultChar = pOS2->usDefaultChar;
2211     TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
2212     TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
2213     TM.tmUnderlined = 0; /* entry in OS2 table */
2214     TM.tmStruckOut = 0; /* entry in OS2 table */
2215
2216     /* Yes TPMF_FIXED_PITCH is correct; braindead api */
2217     if(!FT_IS_FIXED_WIDTH(ft_face))
2218         TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
2219     else
2220         TM.tmPitchAndFamily = 0;
2221
2222     switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
2223     case PAN_FAMILY_SCRIPT:
2224         TM.tmPitchAndFamily |= FF_SCRIPT;
2225         break;
2226     case PAN_FAMILY_DECORATIVE:
2227     case PAN_FAMILY_PICTORIAL:
2228         TM.tmPitchAndFamily |= FF_DECORATIVE;
2229         break;
2230     case PAN_FAMILY_TEXT_DISPLAY:
2231         if(TM.tmPitchAndFamily == 0) /* fixed */
2232             TM.tmPitchAndFamily = FF_MODERN;
2233         else {
2234             switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
2235             case PAN_SERIF_NORMAL_SANS:
2236             case PAN_SERIF_OBTUSE_SANS:
2237             case PAN_SERIF_PERP_SANS:
2238                 TM.tmPitchAndFamily |= FF_SWISS;
2239                 break;
2240             default:
2241                 TM.tmPitchAndFamily |= FF_ROMAN;
2242             }
2243         }
2244         break;
2245     default:
2246         TM.tmPitchAndFamily |= FF_DONTCARE;
2247     }
2248
2249     if(FT_IS_SCALABLE(ft_face))
2250         TM.tmPitchAndFamily |= TMPF_VECTOR;
2251     if(FT_IS_SFNT(ft_face))
2252         TM.tmPitchAndFamily |= TMPF_TRUETYPE;
2253
2254     TM.tmCharSet = font->charset;
2255 #undef TM
2256
2257     font->potm->otmFiller = 0;
2258     memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
2259     font->potm->otmfsSelection = pOS2->fsSelection;
2260     font->potm->otmfsType = pOS2->fsType;
2261     font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
2262     font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
2263     font->potm->otmItalicAngle = 0; /* POST table */
2264     font->potm->otmEMSquare = ft_face->units_per_EM;
2265     font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
2266     font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
2267     font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
2268     font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
2269     font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
2270     font->potm->otmrcFontBox.left = ft_face->bbox.xMin;
2271     font->potm->otmrcFontBox.right = ft_face->bbox.xMax;
2272     font->potm->otmrcFontBox.top = ft_face->bbox.yMin;
2273     font->potm->otmrcFontBox.bottom = ft_face->bbox.yMax;
2274     font->potm->otmMacAscent = 0; /* where do these come from ? */
2275     font->potm->otmMacDescent = 0;
2276     font->potm->otmMacLineGap = 0;
2277     font->potm->otmusMinimumPPEM = 0; /* TT Header */
2278     font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
2279     font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
2280     font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
2281     font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
2282     font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
2283     font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
2284     font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
2285     font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
2286     font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
2287     font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
2288     if(!pPost) {
2289         font->potm->otmsUnderscoreSize = 0;
2290         font->potm->otmsUnderscorePosition = 0;
2291     } else {
2292         font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6;
2293         font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6;
2294     }
2295
2296     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
2297     cp = (char*)font->potm + sizeof(*font->potm);
2298     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
2299     strcpyW((WCHAR*)cp, family_nameW);
2300     cp += lenfam;
2301     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
2302     strcpyW((WCHAR*)cp, style_nameW);
2303     cp += lensty;
2304     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
2305     strcpyW((WCHAR*)cp, family_nameW);
2306     if(strcasecmp(ft_face->style_name, "regular")) {
2307         strcatW((WCHAR*)cp, spaceW);
2308         strcatW((WCHAR*)cp, style_nameW);
2309         cp += lenfam + lensty;
2310     } else
2311         cp += lenfam;
2312     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
2313     strcpyW((WCHAR*)cp, family_nameW);
2314     strcatW((WCHAR*)cp, spaceW);
2315     strcatW((WCHAR*)cp, style_nameW);
2316     ret = needed;
2317
2318     if(potm && needed <= cbSize)
2319         memcpy(potm, font->potm, font->potm->otmSize);
2320
2321 end:
2322     HeapFree(GetProcessHeap(), 0, style_nameW);
2323     HeapFree(GetProcessHeap(), 0, family_nameW);
2324
2325     return ret;
2326 }
2327
2328
2329 /*************************************************************
2330  * WineEngGetCharWidth
2331  *
2332  */
2333 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
2334                          LPINT buffer)
2335 {
2336     UINT c;
2337     GLYPHMETRICS gm;
2338     FT_UInt glyph_index;
2339
2340     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
2341
2342     for(c = firstChar; c <= lastChar; c++) {
2343         glyph_index = get_glyph_index(font, c);
2344         WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
2345                                &gm, 0, NULL, NULL);
2346         buffer[c - firstChar] = font->gm[glyph_index].adv;
2347     }
2348     return TRUE;
2349 }
2350
2351 /*************************************************************
2352  * WineEngGetTextExtentPoint
2353  *
2354  */
2355 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
2356                                LPSIZE size)
2357 {
2358     INT idx;
2359     GLYPHMETRICS gm;
2360     TEXTMETRICW tm;
2361     FT_UInt glyph_index;
2362
2363     TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count,
2364           size);
2365
2366     size->cx = 0;
2367     WineEngGetTextMetrics(font, &tm);
2368     size->cy = tm.tmHeight;
2369
2370     for(idx = 0; idx < count; idx++) {
2371         glyph_index = get_glyph_index(font, wstr[idx]);
2372         WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
2373                                &gm, 0, NULL, NULL);
2374         size->cx += font->gm[glyph_index].adv;
2375     }
2376     TRACE("return %ld,%ld\n", size->cx, size->cy);
2377     return TRUE;
2378 }
2379
2380 /*************************************************************
2381  * WineEngGetTextExtentPointI
2382  *
2383  */
2384 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
2385                                 LPSIZE size)
2386 {
2387     INT idx;
2388     GLYPHMETRICS gm;
2389     TEXTMETRICW tm;
2390
2391     TRACE("%p, %p, %d, %p\n", font, indices, count, size);
2392
2393     size->cx = 0;
2394     WineEngGetTextMetrics(font, &tm);
2395     size->cy = tm.tmHeight;
2396
2397    for(idx = 0; idx < count; idx++) {
2398         WineEngGetGlyphOutline(font, indices[idx],
2399                                GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
2400                                NULL);
2401         size->cx += font->gm[indices[idx]].adv;
2402     }
2403     TRACE("return %ld,%ld\n", size->cx, size->cy);
2404     return TRUE;
2405 }
2406
2407 /*************************************************************
2408  * WineEngGetFontData
2409  *
2410  */
2411 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
2412                          DWORD cbData)
2413 {
2414     FT_Face ft_face = font->ft_face;
2415     DWORD len;
2416     FT_Error err;
2417
2418     TRACE("font=%p, table=%08lx, offset=%08lx, buf=%p, cbData=%lx\n",
2419         font, table, offset, buf, cbData);
2420
2421     if(!FT_IS_SFNT(ft_face))
2422         return GDI_ERROR;
2423
2424     if(!buf || !cbData)
2425         len = 0;
2426     else
2427         len = cbData;
2428
2429     if(table) { /* MS tags differ in endidness from FT ones */
2430         table = table >> 24 | table << 24 |
2431           (table >> 8 & 0xff00) | (table << 8 & 0xff0000);
2432     }
2433
2434     /* If the FT_Load_Sfnt_Table function is there we'll use it */
2435     if(pFT_Load_Sfnt_Table)
2436         err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, &len);
2437     else { /* Do it the hard way */
2438         TT_Face tt_face = (TT_Face) ft_face;
2439         SFNT_Interface *sfnt;
2440         if (FT_Version.major==2 && FT_Version.minor==0)
2441         {
2442             /* 2.0.x */
2443             sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
2444         }
2445         else
2446         {
2447             /* A field was added in the middle of the structure in 2.1.x */
2448             sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
2449         }
2450         err = sfnt->load_any(tt_face, table, offset, buf, &len);
2451     }
2452     if(err) {
2453         TRACE("Can't find table %08lx.\n", table);
2454         return GDI_ERROR;
2455     }
2456     return len;
2457 }
2458
2459 /*************************************************************
2460  * WineEngGetTextFace
2461  *
2462  */
2463 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
2464 {
2465     if(str) {
2466         lstrcpynW(str, font->name, count);
2467         return strlenW(font->name);
2468     } else
2469         return strlenW(font->name) + 1;
2470 }
2471
2472 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
2473 {
2474     if (fs) memcpy(fs, &font->fs, sizeof(FONTSIGNATURE));
2475     return font->charset;
2476 }
2477
2478 #else /* HAVE_FREETYPE */
2479
2480 BOOL WineEngInit(void)
2481 {
2482     return FALSE;
2483 }
2484 GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
2485 {
2486     return NULL;
2487 }
2488 BOOL WineEngDestroyFontInstance(HFONT hfont)
2489 {
2490     return FALSE;
2491 }
2492
2493 DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc, LPARAM lparam)
2494 {
2495     return 1;
2496 }
2497
2498 DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
2499                                 LPWORD pgi, DWORD flags)
2500 {
2501     return GDI_ERROR;
2502 }
2503
2504 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
2505                              LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
2506                              const MAT2* lpmat)
2507 {
2508     ERR("called but we don't have FreeType\n");
2509     return GDI_ERROR;
2510 }
2511
2512 BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
2513 {
2514     ERR("called but we don't have FreeType\n");
2515     return FALSE;
2516 }
2517
2518 UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
2519                                   OUTLINETEXTMETRICW *potm)
2520 {
2521     ERR("called but we don't have FreeType\n");
2522     return 0;
2523 }
2524
2525 BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
2526                          LPINT buffer)
2527 {
2528     ERR("called but we don't have FreeType\n");
2529     return FALSE;
2530 }
2531
2532 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
2533                                LPSIZE size)
2534 {
2535     ERR("called but we don't have FreeType\n");
2536     return FALSE;
2537 }
2538
2539 BOOL WineEngGetTextExtentPointI(GdiFont font, const WORD *indices, INT count,
2540                                 LPSIZE size)
2541 {
2542     ERR("called but we don't have FreeType\n");
2543     return FALSE;
2544 }
2545
2546 DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
2547                          DWORD cbData)
2548 {
2549     ERR("called but we don't have FreeType\n");
2550     return GDI_ERROR;
2551 }
2552
2553 INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
2554 {
2555     ERR("called but we don't have FreeType\n");
2556     return 0;
2557 }
2558
2559 INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
2560 {
2561     FIXME(":stub\n");
2562     return 1;
2563 }
2564
2565 INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
2566 {
2567     FIXME(":stub\n");
2568     return TRUE;
2569 }
2570
2571 UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
2572 {
2573     FIXME(":stub\n");
2574     return DEFAULT_CHARSET;
2575 }
2576
2577 #endif /* HAVE_FREETYPE */