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