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