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