Some fixes in dmband loading.
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  * Copyright 2002,2003 Shachar Shemesh
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
40 WINE_DECLARE_DEBUG_CHANNEL(gdi);
41
42 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
43 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
44 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
45 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
46 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
47
48 static const struct gdi_obj_funcs font_funcs =
49 {
50     FONT_SelectObject,  /* pSelectObject */
51     FONT_GetObject16,   /* pGetObject16 */
52     FONT_GetObjectA,    /* pGetObjectA */
53     FONT_GetObjectW,    /* pGetObjectW */
54     NULL,               /* pUnrealizeObject */
55     FONT_DeleteObject   /* pDeleteObject */
56 };
57
58 #define ENUM_UNICODE    0x00000001
59 #define ENUM_CALLED     0x00000002
60
61 typedef struct
62 {
63     GDIOBJHDR   header;
64     LOGFONTW    logfont;
65 } FONTOBJ;
66
67 typedef struct
68 {
69   LPLOGFONT16           lpLogFontParam;
70   FONTENUMPROC16        lpEnumFunc;
71   LPARAM                lpData;
72
73   LPNEWTEXTMETRICEX16   lpTextMetric;
74   LPENUMLOGFONTEX16     lpLogFont;
75   SEGPTR                segTextMetric;
76   SEGPTR                segLogFont;
77   DWORD                 dwFlags;
78   HDC                   hdc;
79   DC                   *dc;
80   PHYSDEV               physDev;
81 } fontEnum16;
82
83 typedef struct
84 {
85   LPLOGFONTW          lpLogFontParam;
86   FONTENUMPROCW       lpEnumFunc;
87   LPARAM              lpData;
88   DWORD               dwFlags;
89   HDC                 hdc;
90   DC                 *dc;
91   PHYSDEV             physDev;
92 } fontEnum32;
93
94 /*
95  *  For TranslateCharsetInfo
96  */
97 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
98 #define MAXTCIINDEX 32
99 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
100   /* ANSI */
101   { ANSI_CHARSET, 1252, FS(0)},
102   { EASTEUROPE_CHARSET, 1250, FS(1)},
103   { RUSSIAN_CHARSET, 1251, FS(2)},
104   { GREEK_CHARSET, 1253, FS(3)},
105   { TURKISH_CHARSET, 1254, FS(4)},
106   { HEBREW_CHARSET, 1255, FS(5)},
107   { ARABIC_CHARSET, 1256, FS(6)},
108   { BALTIC_CHARSET, 1257, FS(7)},
109   { VIETNAMESE_CHARSET, 1258, FS(8)},
110   /* reserved by ANSI */
111   { DEFAULT_CHARSET, 0, FS(0)},
112   { DEFAULT_CHARSET, 0, FS(0)},
113   { DEFAULT_CHARSET, 0, FS(0)},
114   { DEFAULT_CHARSET, 0, FS(0)},
115   { DEFAULT_CHARSET, 0, FS(0)},
116   { DEFAULT_CHARSET, 0, FS(0)},
117   { DEFAULT_CHARSET, 0, FS(0)},
118   /* ANSI and OEM */
119   { THAI_CHARSET,  874,  FS(16)},
120   { SHIFTJIS_CHARSET, 932, FS(17)},
121   { GB2312_CHARSET, 936, FS(18)},
122   { HANGEUL_CHARSET, 949, FS(19)},
123   { CHINESEBIG5_CHARSET, 950, FS(20)},
124   { JOHAB_CHARSET, 1361, FS(21)},
125   /* reserved for alternate ANSI and OEM */
126   { DEFAULT_CHARSET, 0, FS(0)},
127   { DEFAULT_CHARSET, 0, FS(0)},
128   { DEFAULT_CHARSET, 0, FS(0)},
129   { DEFAULT_CHARSET, 0, FS(0)},
130   { DEFAULT_CHARSET, 0, FS(0)},
131   { DEFAULT_CHARSET, 0, FS(0)},
132   { DEFAULT_CHARSET, 0, FS(0)},
133   { DEFAULT_CHARSET, 0, FS(0)},
134   /* reserved for system */
135   { DEFAULT_CHARSET, 0, FS(0)},
136   { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
137 };
138
139 /***********************************************************************
140  *              LOGFONT conversion functions.
141  */
142 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
143 {
144     font16->lfHeight = font32->lfHeight;
145     font16->lfWidth = font32->lfWidth;
146     font16->lfEscapement = font32->lfEscapement;
147     font16->lfOrientation = font32->lfOrientation;
148     font16->lfWeight = font32->lfWeight;
149     font16->lfItalic = font32->lfItalic;
150     font16->lfUnderline = font32->lfUnderline;
151     font16->lfStrikeOut = font32->lfStrikeOut;
152     font16->lfCharSet = font32->lfCharSet;
153     font16->lfOutPrecision = font32->lfOutPrecision;
154     font16->lfClipPrecision = font32->lfClipPrecision;
155     font16->lfQuality = font32->lfQuality;
156     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
157     WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
158                          font16->lfFaceName, LF_FACESIZE, NULL, NULL );
159     font16->lfFaceName[LF_FACESIZE-1] = 0;
160 }
161
162 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
163 {
164     font32->lfHeight = font16->lfHeight;
165     font32->lfWidth = font16->lfWidth;
166     font32->lfEscapement = font16->lfEscapement;
167     font32->lfOrientation = font16->lfOrientation;
168     font32->lfWeight = font16->lfWeight;
169     font32->lfItalic = font16->lfItalic;
170     font32->lfUnderline = font16->lfUnderline;
171     font32->lfStrikeOut = font16->lfStrikeOut;
172     font32->lfCharSet = font16->lfCharSet;
173     font32->lfOutPrecision = font16->lfOutPrecision;
174     font32->lfClipPrecision = font16->lfClipPrecision;
175     font32->lfQuality = font16->lfQuality;
176     font32->lfPitchAndFamily = font16->lfPitchAndFamily;
177     MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
178     font32->lfFaceName[LF_FACESIZE-1] = 0;
179 }
180
181 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
182 {
183     memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
184     MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
185                         LF_FACESIZE);
186 }
187
188 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
189 {
190     memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
191     WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
192                         LF_FACESIZE, NULL, NULL);
193 }
194
195 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
196 {
197     FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
198
199     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
200                          font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
201     font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
202     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
203                          font16->elfStyle, LF_FACESIZE, NULL, NULL );
204     font16->elfStyle[LF_FACESIZE-1] = '\0';
205     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
206                          font16->elfScript, LF_FACESIZE, NULL, NULL );
207     font16->elfScript[LF_FACESIZE-1] = '\0';
208 }
209
210 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
211 {
212     FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
213
214     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
215                          fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
216     fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
217     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
218                          fontA->elfStyle, LF_FACESIZE, NULL, NULL );
219     fontA->elfStyle[LF_FACESIZE-1] = '\0';
220     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
221                          fontA->elfScript, LF_FACESIZE, NULL, NULL );
222     fontA->elfScript[LF_FACESIZE-1] = '\0';
223 }
224
225 /***********************************************************************
226  *              TEXTMETRIC conversion functions.
227  */
228 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
229 {
230     ptmA->tmHeight = ptmW->tmHeight;
231     ptmA->tmAscent = ptmW->tmAscent;
232     ptmA->tmDescent = ptmW->tmDescent;
233     ptmA->tmInternalLeading = ptmW->tmInternalLeading;
234     ptmA->tmExternalLeading = ptmW->tmExternalLeading;
235     ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
236     ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
237     ptmA->tmWeight = ptmW->tmWeight;
238     ptmA->tmOverhang = ptmW->tmOverhang;
239     ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
240     ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
241     ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
242     ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
243     ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
244     ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
245     ptmA->tmItalic = ptmW->tmItalic;
246     ptmA->tmUnderlined = ptmW->tmUnderlined;
247     ptmA->tmStruckOut = ptmW->tmStruckOut;
248     ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
249     ptmA->tmCharSet = ptmW->tmCharSet;
250 }
251
252
253 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
254 {
255     ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
256     ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
257     ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
258     ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
259     ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
260     ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
261     ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
262     ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
263     ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
264     ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
265     ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
266     ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
267     ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
268     ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
269     ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
270     ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
271     ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
272     ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
273     ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
274     ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
275     ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
276     ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
277     ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
278     ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
279     memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
280 }
281
282 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
283 {
284     FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
285     ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
286     ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
287     ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
288     ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
289     memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
290 }
291
292 /***********************************************************************
293  *           CreateFontIndirectA   (GDI32.@)
294  */
295 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
296 {
297     LOGFONTW lfW;
298
299     if (plfA) {
300         FONT_LogFontAToW( plfA, &lfW );
301         return CreateFontIndirectW( &lfW );
302      } else
303         return CreateFontIndirectW( NULL );
304
305 }
306
307 /***********************************************************************
308  *           CreateFontIndirectW   (GDI32.@)
309  */
310 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
311 {
312     HFONT hFont = 0;
313
314     if (plf)
315     {
316         FONTOBJ* fontPtr;
317         if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
318                                         (HGDIOBJ *)&hFont, &font_funcs )))
319         {
320             static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
321             static const WCHAR BoldW[]   = {' ','B','o','l','d','\0'};
322             WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
323             WCHAR* pFaceNameSuffix = NULL;
324
325             memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
326
327             TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s => %p\n",
328                   plf->lfHeight, plf->lfWidth,
329                   plf->lfEscapement, plf->lfOrientation,
330                   plf->lfPitchAndFamily,
331                   plf->lfOutPrecision, plf->lfClipPrecision,
332                   plf->lfQuality, plf->lfCharSet,
333                   debugstr_w(plf->lfFaceName),
334                   plf->lfWeight > 400 ? "Bold" : "",
335                   plf->lfItalic ? "Italic" : "", hFont);
336
337             if (plf->lfEscapement != plf->lfOrientation) {
338               /* this should really depend on whether GM_ADVANCED is set */
339               fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
340               WARN("orientation angle %f set to "
341                    "escapement angle %f for new font %p\n",
342                    plf->lfOrientation/10., plf->lfEscapement/10., hFont);
343             }
344
345             pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
346             if (pFaceNameItalicSuffix) {
347                 fontPtr->logfont.lfItalic = TRUE;
348                 pFaceNameSuffix = pFaceNameItalicSuffix;
349             }
350
351             pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
352             if (pFaceNameBoldSuffix) {
353                 if (fontPtr->logfont.lfWeight < FW_BOLD) {
354                     fontPtr->logfont.lfWeight = FW_BOLD;
355                 }
356                 if (!pFaceNameSuffix ||
357                     (pFaceNameBoldSuffix < pFaceNameSuffix)) {
358                     pFaceNameSuffix = pFaceNameBoldSuffix;
359                 }
360             }
361
362             if (pFaceNameSuffix) *pFaceNameSuffix = 0;
363
364             GDI_ReleaseObj( hFont );
365         }
366     }
367     else WARN("(NULL) => NULL\n");
368
369     return hFont;
370 }
371
372 /*************************************************************************
373  *           CreateFontA    (GDI32.@)
374  */
375 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
376                               INT orient, INT weight, DWORD italic,
377                               DWORD underline, DWORD strikeout, DWORD charset,
378                               DWORD outpres, DWORD clippres, DWORD quality,
379                               DWORD pitch, LPCSTR name )
380 {
381     LOGFONTA logfont;
382
383     logfont.lfHeight = height;
384     logfont.lfWidth = width;
385     logfont.lfEscapement = esc;
386     logfont.lfOrientation = orient;
387     logfont.lfWeight = weight;
388     logfont.lfItalic = italic;
389     logfont.lfUnderline = underline;
390     logfont.lfStrikeOut = strikeout;
391     logfont.lfCharSet = charset;
392     logfont.lfOutPrecision = outpres;
393     logfont.lfClipPrecision = clippres;
394     logfont.lfQuality = quality;
395     logfont.lfPitchAndFamily = pitch;
396
397     if (name)
398         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
399     else
400         logfont.lfFaceName[0] = '\0';
401
402     return CreateFontIndirectA( &logfont );
403 }
404
405 /*************************************************************************
406  *           CreateFontW    (GDI32.@)
407  */
408 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
409                               INT orient, INT weight, DWORD italic,
410                               DWORD underline, DWORD strikeout, DWORD charset,
411                               DWORD outpres, DWORD clippres, DWORD quality,
412                               DWORD pitch, LPCWSTR name )
413 {
414     LOGFONTW logfont;
415
416     logfont.lfHeight = height;
417     logfont.lfWidth = width;
418     logfont.lfEscapement = esc;
419     logfont.lfOrientation = orient;
420     logfont.lfWeight = weight;
421     logfont.lfItalic = italic;
422     logfont.lfUnderline = underline;
423     logfont.lfStrikeOut = strikeout;
424     logfont.lfCharSet = charset;
425     logfont.lfOutPrecision = outpres;
426     logfont.lfClipPrecision = clippres;
427     logfont.lfQuality = quality;
428     logfont.lfPitchAndFamily = pitch;
429
430     if (name)
431         lstrcpynW(logfont.lfFaceName, name,
432                   sizeof(logfont.lfFaceName) / sizeof(WCHAR));
433     else
434         logfont.lfFaceName[0] = '\0';
435
436     return CreateFontIndirectW( &logfont );
437 }
438
439
440 /***********************************************************************
441  *           FONT_SelectObject
442  *
443  * If the driver supports vector fonts we create a gdi font first and
444  * then call the driver to give it a chance to supply its own device
445  * font.  If the driver wants to do this it returns TRUE and we can
446  * delete the gdi font, if the driver wants to use the gdi font it
447  * should return FALSE, to signal an error return GDI_ERROR.  For
448  * drivers that don't support vector fonts they must supply their own
449  * font.
450  */
451 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
452 {
453     HGDIOBJ ret = 0;
454     DC *dc = DC_GetDCPtr( hdc );
455
456     if (!dc) return 0;
457
458     if (dc->hFont != handle || dc->gdiFont == NULL)
459     {
460         if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
461             dc->gdiFont = WineEngCreateFontInstance(dc, handle);
462     }
463
464     if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle );
465
466     if (ret && dc->gdiFont) dc->gdiFont = 0;
467
468     if (ret == HGDI_ERROR)
469         ret = 0; /* SelectObject returns 0 on error */
470     else
471     {
472         ret = dc->hFont;
473         dc->hFont = handle;
474     }
475     GDI_ReleaseObj( hdc );
476     return ret;
477 }
478
479
480 /***********************************************************************
481  *           FONT_GetObject16
482  */
483 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
484 {
485     FONTOBJ *font = obj;
486     LOGFONT16 lf16;
487
488     FONT_LogFontWTo16( &font->logfont, &lf16 );
489
490     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
491     memcpy( buffer, &lf16, count );
492     return count;
493 }
494
495 /***********************************************************************
496  *           FONT_GetObjectA
497  */
498 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
499 {
500     FONTOBJ *font = obj;
501     LOGFONTA lfA;
502
503     if(!buffer)
504         return sizeof(lfA);
505     FONT_LogFontWToA( &font->logfont, &lfA );
506
507     if (count > sizeof(lfA)) count = sizeof(lfA);
508     memcpy( buffer, &lfA, count );
509     return count;
510 }
511
512 /***********************************************************************
513  *           FONT_GetObjectW
514  */
515 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
516 {
517     FONTOBJ *font = obj;
518     if(!buffer)
519         return sizeof(LOGFONTW);
520     if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
521     memcpy( buffer, &font->logfont, count );
522     return count;
523 }
524
525
526 /***********************************************************************
527  *           FONT_DeleteObject
528  */
529 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
530 {
531     WineEngDestroyFontInstance( handle );
532     return GDI_FreeObject( handle, obj );
533 }
534
535
536 /***********************************************************************
537  *              FONT_EnumInstance16
538  *
539  * Called by the device driver layer to pass font info
540  * down to the application.
541  */
542 static INT FONT_EnumInstance16( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
543                                 DWORD fType, LPARAM lp )
544 {
545     fontEnum16 *pfe = (fontEnum16*)lp;
546     INT ret = 1;
547     DC *dc;
548
549     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
550         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
551     {
552         WORD args[7];
553         DWORD result;
554
555         FONT_EnumLogFontExWTo16(plf, pfe->lpLogFont);
556         FONT_NewTextMetricExWTo16(ptm, pfe->lpTextMetric);
557         pfe->dwFlags |= ENUM_CALLED;
558         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
559
560         args[6] = SELECTOROF(pfe->segLogFont);
561         args[5] = OFFSETOF(pfe->segLogFont);
562         args[4] = SELECTOROF(pfe->segTextMetric);
563         args[3] = OFFSETOF(pfe->segTextMetric);
564         args[2] = fType;
565         args[1] = HIWORD(pfe->lpData);
566         args[0] = LOWORD(pfe->lpData);
567         WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
568         ret = LOWORD(result);
569
570         /* get the lock again and make sure the DC is still valid */
571         dc = DC_GetDCPtr( pfe->hdc );
572         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
573         {
574             if (dc) GDI_ReleaseObj( pfe->hdc );
575             pfe->hdc = 0;  /* make sure we don't try to release it later on */
576             ret = 0;
577         }
578     }
579     return ret;
580 }
581
582 /***********************************************************************
583  *              FONT_EnumInstance
584  */
585 static INT FONT_EnumInstance( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
586                               DWORD fType, LPARAM lp )
587 {
588     fontEnum32 *pfe = (fontEnum32*)lp;
589     INT ret = 1;
590     DC *dc;
591
592     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
593     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
594         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
595     {
596         /* convert font metrics */
597         ENUMLOGFONTEXA logfont;
598         NEWTEXTMETRICEXA tmA;
599
600         pfe->dwFlags |= ENUM_CALLED;
601         if (!(pfe->dwFlags & ENUM_UNICODE))
602         {
603             FONT_EnumLogFontExWToA( plf, &logfont);
604             FONT_NewTextMetricExWToA( ptm, &tmA );
605             plf = (LPENUMLOGFONTEXW)&logfont;
606             ptm = (NEWTEXTMETRICEXW *)&tmA;
607         }
608         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
609
610         ret = pfe->lpEnumFunc( &plf->elfLogFont, (TEXTMETRICW *)ptm, fType, pfe->lpData );
611
612         /* get the lock again and make sure the DC is still valid */
613         dc = DC_GetDCPtr( pfe->hdc );
614         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
615         {
616             if (dc) GDI_ReleaseObj( pfe->hdc );
617             pfe->hdc = 0;  /* make sure we don't try to release it later on */
618             ret = 0;
619         }
620     }
621     return ret;
622 }
623
624 /***********************************************************************
625  *              EnumFontFamiliesEx      (GDI.613)
626  */
627 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
628                                    FONTENUMPROC16 efproc, LPARAM lParam,
629                                    DWORD dwFlags)
630 {
631     fontEnum16 fe16;
632     INT16       ret = 1, ret2;
633     DC*         dc = DC_GetDCPtr( HDC_32(hDC) );
634     NEWTEXTMETRICEX16 tm16;
635     ENUMLOGFONTEX16 lf16;
636     LOGFONTW lfW;
637     BOOL enum_gdi_fonts;
638
639     if (!dc) return 0;
640     FONT_LogFont16ToW(plf, &lfW);
641
642     fe16.hdc = HDC_32(hDC);
643     fe16.dc = dc;
644     fe16.physDev = dc->physDev;
645     fe16.lpLogFontParam = plf;
646     fe16.lpEnumFunc = efproc;
647     fe16.lpData = lParam;
648     fe16.lpTextMetric = &tm16;
649     fe16.lpLogFont = &lf16;
650     fe16.segTextMetric = MapLS( &tm16 );
651     fe16.segLogFont = MapLS( &lf16 );
652     fe16.dwFlags = 0;
653
654     enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
655
656     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
657     {
658         ret = 0;
659         goto done;
660     }
661
662     if (enum_gdi_fonts)
663         ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
664     fe16.dwFlags &= ~ENUM_CALLED;
665     if (ret && dc->funcs->pEnumDeviceFonts) {
666         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
667         if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
668             ret = ret2;
669     }
670 done:
671     UnMapLS( fe16.segTextMetric );
672     UnMapLS( fe16.segLogFont );
673     if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
674     return ret;
675 }
676
677 /***********************************************************************
678  *              FONT_EnumFontFamiliesEx
679  */
680 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
681                                     FONTENUMPROCW efproc,
682                                     LPARAM lParam, DWORD dwUnicode)
683 {
684     INT ret = 1, ret2;
685     DC *dc = DC_GetDCPtr( hDC );
686     fontEnum32 fe32;
687     BOOL enum_gdi_fonts;
688
689     if (!dc) return 0;
690
691     TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
692           plf->lfCharSet);
693     fe32.lpLogFontParam = plf;
694     fe32.lpEnumFunc = efproc;
695     fe32.lpData = lParam;
696     fe32.dwFlags = dwUnicode;
697     fe32.hdc = hDC;
698     fe32.dc = dc;
699     fe32.physDev = dc->physDev;
700
701     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
702
703     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
704     {
705         ret = 0;
706         goto done;
707     }
708
709     if (enum_gdi_fonts)
710         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
711     fe32.dwFlags &= ~ENUM_CALLED;
712     if (ret && dc->funcs->pEnumDeviceFonts) {
713         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
714         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
715             ret = ret2;
716     }
717  done:
718     if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
719     return ret;
720 }
721
722 /***********************************************************************
723  *              EnumFontFamiliesExW     (GDI32.@)
724  */
725 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
726                                     FONTENUMPROCW efproc,
727                                     LPARAM lParam, DWORD dwFlags )
728 {
729     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
730 }
731
732 /***********************************************************************
733  *              EnumFontFamiliesExA     (GDI32.@)
734  */
735 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
736                                     FONTENUMPROCA efproc,
737                                     LPARAM lParam, DWORD dwFlags)
738 {
739     LOGFONTW lfW;
740     FONT_LogFontAToW( plf, &lfW );
741
742     return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
743 }
744
745 /***********************************************************************
746  *              EnumFontFamilies        (GDI.330)
747  */
748 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
749                                  FONTENUMPROC16 efproc, LPARAM lpData )
750 {
751     LOGFONT16   lf;
752
753     lf.lfCharSet = DEFAULT_CHARSET;
754     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
755     else lf.lfFaceName[0] = '\0';
756
757     return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
758 }
759
760 /***********************************************************************
761  *              EnumFontFamiliesA       (GDI32.@)
762  */
763 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
764                                   FONTENUMPROCA efproc, LPARAM lpData )
765 {
766     LOGFONTA    lf;
767
768     lf.lfCharSet = DEFAULT_CHARSET;
769     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
770     else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
771
772     return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
773 }
774
775 /***********************************************************************
776  *              EnumFontFamiliesW       (GDI32.@)
777  */
778 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
779                                   FONTENUMPROCW efproc, LPARAM lpData )
780 {
781     LOGFONTW  lf;
782
783     lf.lfCharSet = DEFAULT_CHARSET;
784     if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
785     else lf.lfFaceName[0] = 0;
786
787     return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
788 }
789
790 /***********************************************************************
791  *              EnumFonts               (GDI.70)
792  */
793 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
794                           LPARAM lpData )
795 {
796     return EnumFontFamilies16( hDC, lpName, efproc, lpData );
797 }
798
799 /***********************************************************************
800  *              EnumFontsA              (GDI32.@)
801  */
802 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
803                            LPARAM lpData )
804 {
805     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
806 }
807
808 /***********************************************************************
809  *              EnumFontsW              (GDI32.@)
810  */
811 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
812                            LPARAM lpData )
813 {
814     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
815 }
816
817
818 /***********************************************************************
819  *           GetTextCharacterExtra    (GDI32.@)
820  */
821 INT WINAPI GetTextCharacterExtra( HDC hdc )
822 {
823     INT ret;
824     DC *dc = DC_GetDCPtr( hdc );
825     if (!dc) return 0x80000000;
826     ret = dc->charExtra;
827     GDI_ReleaseObj( hdc );
828     return ret;
829 }
830
831
832 /***********************************************************************
833  *           SetTextCharacterExtra    (GDI32.@)
834  */
835 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
836 {
837     INT prev;
838     DC * dc = DC_GetDCPtr( hdc );
839     if (!dc) return 0x80000000;
840     if (dc->funcs->pSetTextCharacterExtra)
841         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
842     else
843     {
844         prev = dc->charExtra;
845         dc->charExtra = extra;
846     }
847     GDI_ReleaseObj( hdc );
848     return prev;
849 }
850
851
852 /***********************************************************************
853  *           SetTextJustification    (GDI32.@)
854  */
855 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
856 {
857     BOOL ret = TRUE;
858     DC * dc = DC_GetDCPtr( hdc );
859     if (!dc) return FALSE;
860     if (dc->funcs->pSetTextJustification)
861         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
862     else
863     {
864         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
865         if (!extra) breaks = 0;
866         dc->breakTotalExtra = extra;
867         dc->breakCount = breaks;
868         if (breaks)
869         {
870             dc->breakExtra = extra / breaks;
871             dc->breakRem   = extra - (dc->breakCount * dc->breakExtra);
872         }
873         else
874         {
875             dc->breakExtra = 0;
876             dc->breakRem   = 0;
877         }
878     }
879     GDI_ReleaseObj( hdc );
880     return ret;
881 }
882
883
884 /***********************************************************************
885  *           GetTextFaceA    (GDI32.@)
886  */
887 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
888 {
889     INT res = GetTextFaceW(hdc, 0, NULL);
890     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
891     GetTextFaceW( hdc, res, nameW );
892
893     if (name)
894     {
895         if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
896             name[count-1] = 0;
897         res = strlen(name);
898     }
899     else
900         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
901     HeapFree( GetProcessHeap(), 0, nameW );
902     return res;
903 }
904
905 /***********************************************************************
906  *           GetTextFaceW    (GDI32.@)
907  */
908 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
909 {
910     FONTOBJ *font;
911     INT     ret = 0;
912
913     DC * dc = DC_GetDCPtr( hdc );
914     if (!dc) return 0;
915
916     if(dc->gdiFont)
917         ret = WineEngGetTextFace(dc->gdiFont, count, name);
918     else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
919     {
920         if (name)
921         {
922             lstrcpynW( name, font->logfont.lfFaceName, count );
923             ret = strlenW(name);
924         }
925         else ret = strlenW(font->logfont.lfFaceName) + 1;
926         GDI_ReleaseObj( dc->hFont );
927     }
928     GDI_ReleaseObj( hdc );
929     return ret;
930 }
931
932
933 /***********************************************************************
934  *           GetTextExtentPoint32A    (GDI32.@)
935  */
936 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
937                                      LPSIZE size )
938 {
939     BOOL ret = FALSE;
940     INT wlen;
941     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
942
943     if (p) {
944         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
945         HeapFree( GetProcessHeap(), 0, p );
946     }
947
948     TRACE("(%p %s %d %p): returning %ld x %ld\n",
949           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
950     return ret;
951 }
952
953
954 /***********************************************************************
955  * GetTextExtentPoint32W [GDI32.@]  Computes width/height for a string
956  *
957  * Computes width and height of the specified string.
958  *
959  * RETURNS
960  *    Success: TRUE
961  *    Failure: FALSE
962  */
963 BOOL WINAPI GetTextExtentPoint32W(
964     HDC hdc,     /* [in]  Handle of device context */
965     LPCWSTR str,   /* [in]  Address of text string */
966     INT count,   /* [in]  Number of characters in string */
967     LPSIZE size) /* [out] Address of structure for string size */
968 {
969     BOOL ret = FALSE;
970     DC * dc = DC_GetDCPtr( hdc );
971     if (!dc) return FALSE;
972
973     if(dc->gdiFont) {
974         ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
975         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
976         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
977     }
978     else if(dc->funcs->pGetTextExtentPoint)
979         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
980
981     GDI_ReleaseObj( hdc );
982
983     TRACE("(%p %s %d %p): returning %ld x %ld\n",
984           hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
985     return ret;
986 }
987
988 /***********************************************************************
989  * GetTextExtentPointI [GDI32.@]
990  *
991  * Computes width and height of the array of glyph indices.
992  *
993  * RETURNS
994  *    Success: TRUE
995  *    Failure: FALSE
996  */
997 BOOL WINAPI GetTextExtentPointI(
998     HDC hdc,     /* [in]  Handle of device context */
999     const WORD *indices,   /* [in]  Address of glyph index array */
1000     INT count,   /* [in]  Number of glyphs in array */
1001     LPSIZE size) /* [out] Address of structure for string size */
1002 {
1003     BOOL ret = FALSE;
1004     DC * dc = DC_GetDCPtr( hdc );
1005     if (!dc) return FALSE;
1006
1007     if(dc->gdiFont) {
1008         ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1009         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1010         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1011     }
1012     else if(dc->funcs->pGetTextExtentPoint) {
1013         FIXME("calling GetTextExtentPoint\n");
1014         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1015     }
1016
1017     GDI_ReleaseObj( hdc );
1018
1019     TRACE("(%p %p %d %p): returning %ld x %ld\n",
1020           hdc, indices, count, size, size->cx, size->cy );
1021     return ret;
1022 }
1023
1024
1025 /***********************************************************************
1026  *           GetTextExtentPointA    (GDI32.@)
1027  */
1028 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1029                                           LPSIZE size )
1030 {
1031     TRACE("not bug compatible.\n");
1032     return GetTextExtentPoint32A( hdc, str, count, size );
1033 }
1034
1035 /***********************************************************************
1036  *           GetTextExtentPointW   (GDI32.@)
1037  */
1038 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1039                                           LPSIZE size )
1040 {
1041     TRACE("not bug compatible.\n");
1042     return GetTextExtentPoint32W( hdc, str, count, size );
1043 }
1044
1045
1046 /***********************************************************************
1047  *           GetTextExtentExPointA    (GDI32.@)
1048  */
1049 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1050                                    INT maxExt, LPINT lpnFit,
1051                                    LPINT alpDx, LPSIZE size )
1052 {
1053     BOOL ret;
1054     INT wlen;
1055     LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1056     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1057     HeapFree( GetProcessHeap(), 0, p );
1058     return ret;
1059 }
1060
1061
1062 /***********************************************************************
1063  *           GetTextExtentExPointW    (GDI32.@)
1064  *
1065  * Return the size of the string as it would be if it was output properly by
1066  * e.g. TextOut.
1067  *
1068  * This should include
1069  * - Intercharacter spacing
1070  * - justification spacing (not yet done)
1071  * - kerning? see below
1072  *
1073  * Kerning.  Since kerning would be carried out by the rendering code it should
1074  * be done by the driver.  However they don't support it yet.  Also I am not
1075  * yet persuaded that (certainly under Win95) any kerning is actually done.
1076  *
1077  * str: According to MSDN this should be null-terminated.  That is not true; a
1078  *      null will not terminate it early.
1079  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1080  *       than count.  I have seen it be either the size of the full string or
1081  *       1 less than the size of the full string.  I have not seen it bear any
1082  *       resemblance to the portion that would fit.
1083  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1084  *         trailing intercharacter spacing and any trailing justification.
1085  *
1086  * FIXME
1087  * Currently we do this by measuring each character etc.  We should do it by
1088  * passing the request to the driver, perhaps by extending the
1089  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1090  * thinking about kerning issues and rounding issues in the justification.
1091  */
1092
1093 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1094                                    INT maxExt, LPINT lpnFit,
1095                                    LPINT alpDx, LPSIZE size )
1096 {
1097     int index, nFit, extent;
1098     SIZE tSize;
1099     BOOL ret = FALSE;
1100
1101     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1102
1103     size->cx = size->cy = nFit = extent = 0;
1104     for(index = 0; index < count; index++)
1105     {
1106         if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1107         /* GetTextExtentPoint includes intercharacter spacing. */
1108         /* FIXME - justification needs doing yet.  Remember that the base
1109          * data will not be in logical coordinates.
1110          */
1111         extent += tSize.cx;
1112         if( !lpnFit || extent <= maxExt )
1113         /* It is allowed to be equal. */
1114         {
1115             nFit++;
1116             if( alpDx ) alpDx[index] = extent;
1117         }
1118         if( tSize.cy > size->cy ) size->cy = tSize.cy;
1119         str++;
1120     }
1121     size->cx = extent;
1122     if(lpnFit) *lpnFit = nFit;
1123     ret = TRUE;
1124
1125     TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1126
1127 done:
1128     return ret;
1129 }
1130
1131 /***********************************************************************
1132  *           GetTextMetricsA    (GDI32.@)
1133  */
1134 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1135 {
1136     TEXTMETRICW tm32;
1137
1138     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1139     FONT_TextMetricWToA( &tm32, metrics );
1140     return TRUE;
1141 }
1142
1143 /***********************************************************************
1144  *           GetTextMetricsW    (GDI32.@)
1145  */
1146 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1147 {
1148     BOOL ret = FALSE;
1149     DC * dc = DC_GetDCPtr( hdc );
1150     if (!dc) return FALSE;
1151
1152     if (dc->gdiFont)
1153         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1154     else if (dc->funcs->pGetTextMetrics)
1155         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1156
1157     if (ret)
1158     {
1159     /* device layer returns values in device units
1160      * therefore we have to convert them to logical */
1161
1162 #define WDPTOLP(x) ((x<0)?                                      \
1163                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1164                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1165 #define HDPTOLP(y) ((y<0)?                                      \
1166                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1167                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1168
1169     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1170     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1171     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1172     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1173     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1174     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1175     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1176     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1177         ret = TRUE;
1178 #undef WDPTOLP
1179 #undef HDPTOLP
1180     TRACE("text metrics:\n"
1181           "    Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1182           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1183           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1184           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1185           "    PitchAndFamily = %02x\n"
1186           "    --------------------\n"
1187           "    InternalLeading = %li\n"
1188           "    Ascent = %li\n"
1189           "    Descent = %li\n"
1190           "    Height = %li\n",
1191           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1192           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1193           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1194           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1195           metrics->tmPitchAndFamily,
1196           metrics->tmInternalLeading,
1197           metrics->tmAscent,
1198           metrics->tmDescent,
1199           metrics->tmHeight );
1200     }
1201     GDI_ReleaseObj( hdc );
1202     return ret;
1203 }
1204
1205
1206 /***********************************************************************
1207  * GetOutlineTextMetrics [GDI.308]  Gets metrics for TrueType fonts.
1208  *
1209  * NOTES
1210  *    lpOTM should be LPOUTLINETEXTMETRIC
1211  *
1212  * RETURNS
1213  *    Success: Non-zero or size of required buffer
1214  *    Failure: 0
1215  */
1216 UINT16 WINAPI GetOutlineTextMetrics16(
1217     HDC16 hdc,    /* [in]  Handle of device context */
1218     UINT16 cbData, /* [in]  Size of metric data array */
1219     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1220 {
1221     FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1222     return 0;
1223 }
1224
1225
1226 /***********************************************************************
1227  *              GetOutlineTextMetricsA (GDI32.@)
1228  * Gets metrics for TrueType fonts.
1229  *
1230  *
1231  * RETURNS
1232  *    Success: Non-zero or size of required buffer
1233  *    Failure: 0
1234  */
1235 UINT WINAPI GetOutlineTextMetricsA(
1236     HDC hdc,    /* [in]  Handle of device context */
1237     UINT cbData, /* [in]  Size of metric data array */
1238     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1239 {
1240     char buf[512], *ptr;
1241     UINT ret, needed;
1242     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1243     INT left, len;
1244
1245     if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) {
1246         if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1247             return 0;
1248         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1249         GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1250     }
1251
1252     needed = sizeof(OUTLINETEXTMETRICA);
1253     if(lpOTMW->otmpFamilyName)
1254         needed += WideCharToMultiByte(CP_ACP, 0,
1255            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1256                                       NULL, 0, NULL, NULL);
1257     if(lpOTMW->otmpFaceName)
1258         needed += WideCharToMultiByte(CP_ACP, 0,
1259            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1260                                       NULL, 0, NULL, NULL);
1261     if(lpOTMW->otmpStyleName)
1262         needed += WideCharToMultiByte(CP_ACP, 0,
1263            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1264                                       NULL, 0, NULL, NULL);
1265     if(lpOTMW->otmpFullName)
1266         needed += WideCharToMultiByte(CP_ACP, 0,
1267            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1268                                       NULL, 0, NULL, NULL);
1269
1270     if(!lpOTM) {
1271         ret = needed;
1272         goto end;
1273     }
1274
1275     if(needed > cbData) {
1276         ret = 0;
1277         goto end;
1278     }
1279
1280
1281     lpOTM->otmSize = needed;
1282     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics );
1283     lpOTM->otmFiller = 0;
1284     lpOTM->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1285     lpOTM->otmfsSelection = lpOTMW->otmfsSelection;
1286     lpOTM->otmfsType = lpOTMW->otmfsType;
1287     lpOTM->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1288     lpOTM->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1289     lpOTM->otmItalicAngle = lpOTMW->otmItalicAngle;
1290     lpOTM->otmEMSquare = lpOTMW->otmEMSquare;
1291     lpOTM->otmAscent = lpOTMW->otmAscent;
1292     lpOTM->otmDescent = lpOTMW->otmDescent;
1293     lpOTM->otmLineGap = lpOTMW->otmLineGap;
1294     lpOTM->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1295     lpOTM->otmsXHeight = lpOTMW->otmsXHeight;
1296     lpOTM->otmrcFontBox = lpOTMW->otmrcFontBox;
1297     lpOTM->otmMacAscent = lpOTMW->otmMacAscent;
1298     lpOTM->otmMacDescent = lpOTMW->otmMacDescent;
1299     lpOTM->otmMacLineGap = lpOTMW->otmMacLineGap;
1300     lpOTM->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1301     lpOTM->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1302     lpOTM->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1303     lpOTM->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1304     lpOTM->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1305     lpOTM->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1306     lpOTM->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1307     lpOTM->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1308     lpOTM->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1309
1310
1311     ptr = (char*)(lpOTM + 1);
1312     left = needed - sizeof(*lpOTM);
1313
1314     if(lpOTMW->otmpFamilyName) {
1315         lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM);
1316         len = WideCharToMultiByte(CP_ACP, 0,
1317              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1318                                   ptr, left, NULL, NULL);
1319         left -= len;
1320         ptr += len;
1321     } else
1322         lpOTM->otmpFamilyName = 0;
1323
1324     if(lpOTMW->otmpFaceName) {
1325         lpOTM->otmpFaceName = (LPSTR)(ptr - (char*)lpOTM);
1326         len = WideCharToMultiByte(CP_ACP, 0,
1327              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1328                                   ptr, left, NULL, NULL);
1329         left -= len;
1330         ptr += len;
1331     } else
1332         lpOTM->otmpFaceName = 0;
1333
1334     if(lpOTMW->otmpStyleName) {
1335         lpOTM->otmpStyleName = (LPSTR)(ptr - (char*)lpOTM);
1336         len = WideCharToMultiByte(CP_ACP, 0,
1337              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1338                                   ptr, left, NULL, NULL);
1339         left -= len;
1340         ptr += len;
1341     } else
1342         lpOTM->otmpStyleName = 0;
1343
1344     if(lpOTMW->otmpFullName) {
1345         lpOTM->otmpFullName = (LPSTR)(ptr - (char*)lpOTM);
1346         len = WideCharToMultiByte(CP_ACP, 0,
1347              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1348                                   ptr, left, NULL, NULL);
1349         left -= len;
1350     } else
1351         lpOTM->otmpFullName = 0;
1352
1353     assert(left == 0);
1354
1355     ret = needed;
1356
1357 end:
1358     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1359         HeapFree(GetProcessHeap(), 0, lpOTMW);
1360
1361     return ret;
1362 }
1363
1364
1365 /***********************************************************************
1366  *           GetOutlineTextMetricsW [GDI32.@]
1367  */
1368 UINT WINAPI GetOutlineTextMetricsW(
1369     HDC hdc,    /* [in]  Handle of device context */
1370     UINT cbData, /* [in]  Size of metric data array */
1371     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1372 {
1373     DC *dc = DC_GetDCPtr( hdc );
1374     UINT ret;
1375
1376     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1377     if(!dc) return 0;
1378
1379     if(dc->gdiFont) {
1380         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, lpOTM);
1381         if(ret && ret <= cbData) {
1382 #define WDPTOLP(x) ((x<0)?                                      \
1383                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1384                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1385 #define HDPTOLP(y) ((y<0)?                                      \
1386                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1387                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1388
1389             lpOTM->otmTextMetrics.tmHeight           = HDPTOLP(lpOTM->otmTextMetrics.tmHeight);
1390             lpOTM->otmTextMetrics.tmAscent           = HDPTOLP(lpOTM->otmTextMetrics.tmAscent);
1391             lpOTM->otmTextMetrics.tmDescent          = HDPTOLP(lpOTM->otmTextMetrics.tmDescent);
1392             lpOTM->otmTextMetrics.tmInternalLeading  = HDPTOLP(lpOTM->otmTextMetrics.tmInternalLeading);
1393             lpOTM->otmTextMetrics.tmExternalLeading  = HDPTOLP(lpOTM->otmTextMetrics.tmExternalLeading);
1394             lpOTM->otmTextMetrics.tmAveCharWidth     = WDPTOLP(lpOTM->otmTextMetrics.tmAveCharWidth);
1395             lpOTM->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(lpOTM->otmTextMetrics.tmMaxCharWidth);
1396             lpOTM->otmTextMetrics.tmOverhang         = WDPTOLP(lpOTM->otmTextMetrics.tmOverhang);
1397             lpOTM->otmAscent = HDPTOLP(lpOTM->otmAscent);
1398             lpOTM->otmDescent = HDPTOLP(lpOTM->otmDescent);
1399             lpOTM->otmLineGap = HDPTOLP(lpOTM->otmLineGap);
1400             lpOTM->otmsCapEmHeight = HDPTOLP(lpOTM->otmsCapEmHeight);
1401             lpOTM->otmsXHeight = HDPTOLP(lpOTM->otmsXHeight);
1402             lpOTM->otmrcFontBox.top = HDPTOLP(lpOTM->otmrcFontBox.top);
1403             lpOTM->otmrcFontBox.bottom = HDPTOLP(lpOTM->otmrcFontBox.bottom);
1404             lpOTM->otmrcFontBox.left = WDPTOLP(lpOTM->otmrcFontBox.left);
1405             lpOTM->otmrcFontBox.right = WDPTOLP(lpOTM->otmrcFontBox.right);
1406             lpOTM->otmMacAscent = HDPTOLP(lpOTM->otmMacAscent);
1407             lpOTM->otmMacDescent = HDPTOLP(lpOTM->otmMacDescent);
1408             lpOTM->otmMacLineGap = HDPTOLP(lpOTM->otmMacLineGap);
1409             lpOTM->otmptSubscriptSize.x = WDPTOLP(lpOTM->otmptSubscriptSize.x);
1410             lpOTM->otmptSubscriptSize.y = HDPTOLP(lpOTM->otmptSubscriptSize.y);
1411             lpOTM->otmptSubscriptOffset.x = WDPTOLP(lpOTM->otmptSubscriptOffset.x);
1412             lpOTM->otmptSubscriptOffset.y = HDPTOLP(lpOTM->otmptSubscriptOffset.y);
1413             lpOTM->otmptSuperscriptSize.x = WDPTOLP(lpOTM->otmptSuperscriptSize.x);
1414             lpOTM->otmptSuperscriptSize.y = HDPTOLP(lpOTM->otmptSuperscriptSize.y);
1415             lpOTM->otmptSuperscriptOffset.x = WDPTOLP(lpOTM->otmptSuperscriptOffset.x);
1416             lpOTM->otmptSuperscriptOffset.y = HDPTOLP(lpOTM->otmptSuperscriptOffset.y);
1417             lpOTM->otmsStrikeoutSize = HDPTOLP(lpOTM->otmsStrikeoutSize);
1418             lpOTM->otmsStrikeoutPosition = HDPTOLP(lpOTM->otmsStrikeoutPosition);
1419             lpOTM->otmsUnderscoreSize = HDPTOLP(lpOTM->otmsUnderscoreSize);
1420             lpOTM->otmsUnderscorePosition = HDPTOLP(lpOTM->otmsUnderscorePosition);
1421 #undef WDPTOLP
1422 #undef HDPTOLP
1423         }
1424     }
1425
1426     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1427               but really this should just be a return 0. */
1428
1429         ret = sizeof(*lpOTM);
1430         if (lpOTM) {
1431             if(cbData < ret)
1432                 ret = 0;
1433             else {
1434                 memset(lpOTM, 0, ret);
1435                 lpOTM->otmSize = sizeof(*lpOTM);
1436                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1437                 /*
1438                   Further fill of the structure not implemented,
1439                   Needs real values for the structure members
1440                 */
1441             }
1442         }
1443     }
1444     GDI_ReleaseObj(hdc);
1445     return ret;
1446 }
1447
1448
1449 /***********************************************************************
1450  *           GetCharWidthW      (GDI32.@)
1451  *           GetCharWidth32W    (GDI32.@)
1452  */
1453 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1454                                LPINT buffer )
1455 {
1456     UINT i;
1457     BOOL ret = FALSE;
1458     DC * dc = DC_GetDCPtr( hdc );
1459     if (!dc) return FALSE;
1460
1461     if (dc->gdiFont)
1462         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1463     else if (dc->funcs->pGetCharWidth)
1464         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1465
1466     if (ret)
1467     {
1468         /* convert device units to logical */
1469         for( i = firstChar; i <= lastChar; i++, buffer++ )
1470             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1471         ret = TRUE;
1472     }
1473     GDI_ReleaseObj( hdc );
1474     return ret;
1475 }
1476
1477
1478 /***********************************************************************
1479  *           GetCharWidthA      (GDI32.@)
1480  *           GetCharWidth32A    (GDI32.@)
1481  */
1482 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1483                                LPINT buffer )
1484 {
1485     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1486     LPSTR str;
1487     LPWSTR wstr;
1488     BOOL ret = TRUE;
1489
1490     if(count <= 0) return FALSE;
1491
1492     str = HeapAlloc(GetProcessHeap(), 0, count);
1493     for(i = 0; i < count; i++)
1494         str[i] = (BYTE)(firstChar + i);
1495
1496     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1497
1498     for(i = 0; i < wlen; i++)
1499     {
1500         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1501         {
1502             ret = FALSE;
1503             break;
1504         }
1505         buffer++;
1506     }
1507
1508     HeapFree(GetProcessHeap(), 0, str);
1509     HeapFree(GetProcessHeap(), 0, wstr);
1510
1511     return ret;
1512 }
1513
1514
1515 /* FIXME: all following APIs ******************************************/
1516
1517
1518 /***********************************************************************
1519  *           SetMapperFlags    (GDI32.@)
1520  */
1521 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1522 {
1523     DC *dc = DC_GetDCPtr( hDC );
1524     DWORD ret = 0;
1525     if(!dc) return 0;
1526     if(dc->funcs->pSetMapperFlags)
1527         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1528     else
1529         FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1530     GDI_ReleaseObj( hDC );
1531     return ret;
1532 }
1533
1534 /***********************************************************************
1535  *          GetAspectRatioFilterEx  (GDI.486)
1536  */
1537 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1538 {
1539   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1540   return FALSE;
1541 }
1542
1543 /***********************************************************************
1544  *          GetAspectRatioFilterEx  (GDI32.@)
1545  */
1546 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1547 {
1548   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1549   return FALSE;
1550 }
1551
1552
1553 /***********************************************************************
1554  *           GetCharABCWidthsA   (GDI32.@)
1555  */
1556 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1557                                   LPABC abc )
1558 {
1559     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1560     LPSTR str;
1561     LPWSTR wstr;
1562     BOOL ret = TRUE;
1563
1564     if(count <= 0) return FALSE;
1565
1566     str = HeapAlloc(GetProcessHeap(), 0, count);
1567     for(i = 0; i < count; i++)
1568         str[i] = (BYTE)(firstChar + i);
1569
1570     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1571
1572     for(i = 0; i < wlen; i++)
1573     {
1574         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1575         {
1576             ret = FALSE;
1577             break;
1578         }
1579         abc++;
1580     }
1581
1582     HeapFree(GetProcessHeap(), 0, str);
1583     HeapFree(GetProcessHeap(), 0, wstr);
1584
1585     return ret;
1586 }
1587
1588
1589 /******************************************************************************
1590  * GetCharABCWidthsW [GDI32.@]  Retrieves widths of characters in range
1591  *
1592  * PARAMS
1593  *    hdc       [I] Handle of device context
1594  *    firstChar [I] First character in range to query
1595  *    lastChar  [I] Last character in range to query
1596  *    abc       [O] Address of character-width structure
1597  *
1598  * NOTES
1599  *    Only works with TrueType fonts
1600  *
1601  * RETURNS
1602  *    Success: TRUE
1603  *    Failure: FALSE
1604  */
1605 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1606                                    LPABC abc )
1607 {
1608     DC *dc = DC_GetDCPtr(hdc);
1609     int         i;
1610     GLYPHMETRICS gm;
1611     BOOL ret = FALSE;
1612
1613     if(dc->gdiFont) {
1614         for (i=firstChar;i<=lastChar;i++) {
1615             GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL);
1616             abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x;
1617             abc[i-firstChar].abcB = gm.gmBlackBoxX;
1618             abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX;
1619         }
1620         ret = TRUE;
1621     }
1622     GDI_ReleaseObj(hdc);
1623     return ret;
1624 }
1625
1626
1627 /***********************************************************************
1628  *           GetGlyphOutline    (GDI.309)
1629  */
1630 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1631                                 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1632                                 LPVOID lpBuffer, const MAT2 *lpmat2 )
1633 {
1634     FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1635           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1636     return (DWORD)-1; /* failure */
1637 }
1638
1639
1640 /***********************************************************************
1641  *           GetGlyphOutlineA    (GDI32.@)
1642  */
1643 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1644                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1645                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1646 {
1647     LPWSTR p = NULL;
1648     DWORD ret;
1649     UINT c;
1650
1651     if(!(fuFormat & GGO_GLYPH_INDEX)) {
1652         p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1653         c = p[0];
1654     } else
1655         c = uChar;
1656     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1657                            lpmat2);
1658     if(p)
1659         HeapFree(GetProcessHeap(), 0, p);
1660     return ret;
1661 }
1662
1663 /***********************************************************************
1664  *           GetGlyphOutlineW    (GDI32.@)
1665  */
1666 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1667                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1668                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1669 {
1670     DC *dc = DC_GetDCPtr(hdc);
1671     DWORD ret;
1672
1673     TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1674           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1675
1676     if(!dc) return GDI_ERROR;
1677
1678     if(dc->gdiFont)
1679       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1680                                    cbBuffer, lpBuffer, lpmat2);
1681     else
1682       ret = GDI_ERROR;
1683
1684     GDI_ReleaseObj(hdc);
1685     return ret;
1686 }
1687
1688
1689 /***********************************************************************
1690  *           CreateScalableFontResourceA   (GDI32.@)
1691  */
1692 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1693                                              LPCSTR lpszResourceFile,
1694                                              LPCSTR lpszFontFile,
1695                                              LPCSTR lpszCurrentPath )
1696 {
1697     HANDLE f;
1698
1699     /* fHidden=1 - only visible for the calling app, read-only, not
1700      * enumbered with EnumFonts/EnumFontFamilies
1701      * lpszCurrentPath can be NULL
1702      */
1703     FIXME("(%ld,%s,%s,%s): stub\n",
1704           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1705           debugstr_a(lpszCurrentPath) );
1706
1707     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1708     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1709         CloseHandle(f);
1710         SetLastError(ERROR_FILE_EXISTS);
1711         return FALSE;
1712     }
1713     return FALSE; /* create failed */
1714 }
1715
1716 /***********************************************************************
1717  *           CreateScalableFontResourceW   (GDI32.@)
1718  */
1719 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1720                                              LPCWSTR lpszResourceFile,
1721                                              LPCWSTR lpszFontFile,
1722                                              LPCWSTR lpszCurrentPath )
1723 {
1724     FIXME("(%ld,%p,%p,%p): stub\n",
1725           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1726     return FALSE; /* create failed */
1727 }
1728
1729
1730 /*************************************************************************
1731  *             GetRasterizerCaps   (GDI32.@)
1732  */
1733 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1734 {
1735   lprs->nSize = sizeof(RASTERIZER_STATUS);
1736   lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1737   lprs->nLanguageID = 0;
1738   return TRUE;
1739 }
1740
1741
1742 /*************************************************************************
1743  *             GetKerningPairsA   (GDI32.@)
1744  */
1745 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1746                                LPKERNINGPAIR lpKerningPairs )
1747 {
1748     return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1749 }
1750
1751
1752 /*************************************************************************
1753  *             GetKerningPairsW   (GDI32.@)
1754  */
1755 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1756                                  LPKERNINGPAIR lpKerningPairs )
1757 {
1758     int i;
1759     FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1760     for (i = 0; i < cPairs; i++)
1761         lpKerningPairs[i].iKernAmount = 0;
1762     return 0;
1763 }
1764
1765 /*************************************************************************
1766  * TranslateCharsetInfo [GDI32.@]
1767  *
1768  * Fills a CHARSETINFO structure for a character set, code page, or
1769  * font. This allows making the correspondance between different labelings
1770  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1771  * of the same encoding.
1772  *
1773  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1774  * only one codepage should be set in *lpSrc.
1775  *
1776  * RETURNS
1777  *   TRUE on success, FALSE on failure.
1778  *
1779  */
1780 BOOL WINAPI TranslateCharsetInfo(
1781   LPDWORD lpSrc, /* [in]
1782        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1783        if flags == TCI_SRCCHARSET: a character set value
1784        if flags == TCI_SRCCODEPAGE: a code page value
1785                  */
1786   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1787   DWORD flags /* [in] determines interpretation of lpSrc */
1788 ) {
1789     int index = 0;
1790     switch (flags) {
1791     case TCI_SRCFONTSIG:
1792         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1793       break;
1794     case TCI_SRCCODEPAGE:
1795       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1796       break;
1797     case TCI_SRCCHARSET:
1798       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1799       break;
1800     default:
1801       return FALSE;
1802     }
1803     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1804     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1805     return TRUE;
1806 }
1807
1808 /*************************************************************************
1809  *             GetFontLanguageInfo   (GDI32.@)
1810  */
1811 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1812 {
1813         FONTSIGNATURE fontsig;
1814         static const DWORD GCP_DBCS_MASK=0x003F0000,
1815                 GCP_DIACRITIC_MASK=0x00000000,
1816                 FLI_GLYPHS_MASK=0x00000000,
1817                 GCP_GLYPHSHAPE_MASK=0x00000040,
1818                 GCP_KASHIDA_MASK=0x00000000,
1819                 GCP_LIGATE_MASK=0x00000000,
1820                 GCP_USEKERNING_MASK=0x00000000,
1821                 GCP_REORDER_MASK=0x00000060;
1822
1823         DWORD result=0;
1824
1825         GetTextCharsetInfo( hdc, &fontsig, 0 );
1826         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1827
1828         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1829                 result|=GCP_DBCS;
1830
1831         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1832                 result|=GCP_DIACRITIC;
1833
1834         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1835                 result|=FLI_GLYPHS;
1836
1837         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1838                 result|=GCP_GLYPHSHAPE;
1839
1840         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1841                 result|=GCP_KASHIDA;
1842
1843         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1844                 result|=GCP_LIGATE;
1845
1846         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1847                 result|=GCP_USEKERNING;
1848
1849         if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1850                 result|=GCP_REORDER;
1851
1852         return result;
1853 }
1854
1855
1856 /*************************************************************************
1857  * GetFontData [GDI32.@] Retrieve data for TrueType font
1858  *
1859  * RETURNS
1860  *
1861  * success: Number of bytes returned
1862  * failure: GDI_ERROR
1863  *
1864  * NOTES
1865  *
1866  * Calls SetLastError()
1867  *
1868  */
1869 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1870     LPVOID buffer, DWORD length)
1871 {
1872     DC *dc = DC_GetDCPtr(hdc);
1873     DWORD ret = GDI_ERROR;
1874
1875     if(!dc) return GDI_ERROR;
1876
1877     if(dc->gdiFont)
1878       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1879
1880     GDI_ReleaseObj(hdc);
1881     return ret;
1882 }
1883
1884 /*************************************************************************
1885  * GetGlyphIndicesA [GDI32.@]
1886  */
1887 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1888                               LPWORD pgi, DWORD flags)
1889 {
1890     DWORD ret;
1891     WCHAR *lpstrW;
1892     INT countW;
1893
1894     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1895           hdc, debugstr_an(lpstr, count), count, pgi, flags);
1896
1897     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1898     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1899     HeapFree(GetProcessHeap(), 0, lpstrW);
1900
1901     return ret;
1902 }
1903
1904 /*************************************************************************
1905  * GetGlyphIndicesW [GDI32.@]
1906  */
1907 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1908                               LPWORD pgi, DWORD flags)
1909 {
1910     DC *dc = DC_GetDCPtr(hdc);
1911     DWORD ret = GDI_ERROR;
1912
1913     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1914           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1915
1916     if(!dc) return GDI_ERROR;
1917
1918     if(dc->gdiFont)
1919         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1920
1921     GDI_ReleaseObj(hdc);
1922     return ret;
1923 }
1924
1925 /*************************************************************************
1926  * GetCharacterPlacementA [GDI32.@]
1927  *
1928  * NOTES:
1929  *  the web browser control of ie4 calls this with dwFlags=0
1930  */
1931 DWORD WINAPI
1932 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1933                          INT nMaxExtent, GCP_RESULTSA *lpResults,
1934                          DWORD dwFlags)
1935 {
1936     WCHAR *lpStringW;
1937     INT uCountW, i;
1938     GCP_RESULTSW resultsW;
1939     DWORD ret;
1940     UINT font_cp;
1941
1942     TRACE("%s, %d, %d, 0x%08lx\n",
1943           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
1944
1945     /* both structs are equal in size */
1946     memcpy(&resultsW, lpResults, sizeof(resultsW));
1947
1948     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
1949     if(lpResults->lpOutString)
1950         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
1951
1952     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
1953
1954     if(lpResults->lpOutString) {
1955         if(font_cp != CP_SYMBOL)
1956             WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
1957                                 lpResults->lpOutString, uCount, NULL, NULL );
1958         else
1959             for(i = 0; i < uCount; i++)
1960                 lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
1961     }
1962
1963     HeapFree(GetProcessHeap(), 0, lpStringW);
1964     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
1965
1966     return ret;
1967 }
1968
1969 /*************************************************************************
1970  * GetCharacterPlacementW [GDI32.@]
1971  *
1972  *   Retrieve information about a string. This includes the width, reordering,
1973  *   Glyphing and so on.
1974  *
1975  * RETURNS
1976  *
1977  *   The width and height of the string if successful, 0 if failed.
1978  *
1979  * BUGS
1980  *
1981  *   All flags except GCP_REORDER are not yet implemented.
1982  *   Reordering is not 100% complient to the Windows BiDi method.
1983  *   Caret positioning is not yet implemented.
1984  *   Classes are not yet implemented.
1985  *
1986  */
1987 DWORD WINAPI
1988 GetCharacterPlacementW(
1989                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
1990                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
1991                 INT uCount,             /* [in] Number of WORDS in string. */
1992                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
1993                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
1994                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
1995                 )
1996 {
1997     DWORD ret=0;
1998     SIZE size;
1999     UINT i, nSet;
2000
2001     TRACE("%s, %d, %d, 0x%08lx\n",
2002           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2003
2004     TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2005           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2006             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2007             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2008             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2009
2010     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08lx ignored\n", dwFlags);
2011     if(lpResults->lpCaretPos)   FIXME("caret positions not implemented\n");
2012     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2013
2014         nSet = (UINT)uCount;
2015         if(nSet > lpResults->nGlyphs)
2016                 nSet = lpResults->nGlyphs;
2017
2018         /* return number of initialized fields */
2019         lpResults->nGlyphs = nSet;
2020
2021         if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2022         {
2023                 /* Treat the case where no special handling was requested in a fastpath way */
2024                 /* copy will do if the GCP_REORDER flag is not set */
2025                 if(lpResults->lpOutString)
2026                     strncpyW( lpResults->lpOutString, lpString, nSet );
2027
2028                 if(lpResults->lpOrder)
2029                 {
2030                         for(i = 0; i < nSet; i++)
2031                                 lpResults->lpOrder[i] = i;
2032                 }
2033         } else
2034         {
2035             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2036                           nSet, lpResults->lpOrder );
2037         }
2038
2039         /* FIXME: Will use the placement chars */
2040         if (lpResults->lpDx)
2041         {
2042                 int c;
2043                 for (i = 0; i < nSet; i++)
2044                 {
2045                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2046                                 lpResults->lpDx[i]= c;
2047                 }
2048         }
2049
2050     if(lpResults->lpGlyphs)
2051         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2052
2053     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2054       ret = MAKELONG(size.cx, size.cy);
2055
2056     return ret;
2057 }
2058
2059 /*************************************************************************
2060  *      GetCharABCWidthsFloatA [GDI32.@]
2061  */
2062 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2063                                         LPABCFLOAT lpABCF)
2064 {
2065        FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2066        return 0;
2067 }
2068
2069 /*************************************************************************
2070  *      GetCharABCWidthsFloatW [GDI32.@]
2071  */
2072 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2073                                         UINT iLastChar, LPABCFLOAT lpABCF)
2074 {
2075        FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2076        return 0;
2077 }
2078
2079 /*************************************************************************
2080  *      GetCharWidthFloatA [GDI32.@]
2081  */
2082 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2083                                     UINT iLastChar, PFLOAT pxBuffer)
2084 {
2085        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2086        return 0;
2087 }
2088
2089 /*************************************************************************
2090  *      GetCharWidthFloatW [GDI32.@]
2091  */
2092 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2093                                     UINT iLastChar, PFLOAT pxBuffer)
2094 {
2095        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2096        return 0;
2097 }
2098
2099
2100 /***********************************************************************
2101  *                                                                     *
2102  *           Font Resource API                                         *
2103  *                                                                     *
2104  ***********************************************************************/
2105
2106 /***********************************************************************
2107  *           AddFontResourceA    (GDI32.@)
2108  */
2109 INT WINAPI AddFontResourceA( LPCSTR str )
2110 {
2111     return AddFontResourceExA( str, 0, NULL);
2112 }
2113
2114 /***********************************************************************
2115  *           AddFontResourceW    (GDI32.@)
2116  */
2117 INT WINAPI AddFontResourceW( LPCWSTR str )
2118 {
2119     return AddFontResourceExW(str, 0, NULL);
2120 }
2121
2122
2123 /***********************************************************************
2124  *           AddFontResourceExA    (GDI32.@)
2125  */
2126 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2127 {
2128     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2129     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2130     INT ret;
2131
2132     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2133     ret = AddFontResourceExW(strW, fl, pdv);
2134     HeapFree(GetProcessHeap(), 0, strW);
2135     return ret;
2136 }
2137
2138 /***********************************************************************
2139  *           AddFontResourceExW    (GDI32.@)
2140  */
2141 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2142 {
2143     return WineEngAddFontResourceEx(str, fl, pdv);
2144 }
2145
2146 /***********************************************************************
2147  *           RemoveFontResourceA    (GDI32.@)
2148  */
2149 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2150 {
2151     return RemoveFontResourceExA(str, 0, 0);
2152 }
2153
2154 /***********************************************************************
2155  *           RemoveFontResourceW    (GDI32.@)
2156  */
2157 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2158 {
2159     return RemoveFontResourceExW(str, 0, 0);
2160 }
2161
2162 /***********************************************************************
2163  *           RemoveFontResourceExA    (GDI32.@)
2164  */
2165 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2166 {
2167     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2168     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2169     INT ret;
2170
2171     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2172     ret = RemoveFontResourceExW(strW, fl, pdv);
2173     HeapFree(GetProcessHeap(), 0, strW);
2174     return ret;
2175 }
2176
2177 /***********************************************************************
2178  *           RemoveFontResourceExW    (GDI32.@)
2179  */
2180 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2181 {
2182     return WineEngRemoveFontResourceEx(str, fl, pdv);
2183 }
2184
2185 /***********************************************************************
2186  *           GetTextCharset    (GDI32.@)
2187  */
2188 UINT WINAPI GetTextCharset(HDC hdc)
2189 {
2190     /* MSDN docs say this is equivalent */
2191     return GetTextCharsetInfo(hdc, NULL, 0);
2192 }
2193
2194 /***********************************************************************
2195  *           GetTextCharsetInfo    (GDI32.@)
2196  */
2197 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2198 {
2199     UINT ret = DEFAULT_CHARSET;
2200     DC *dc = DC_GetDCPtr(hdc);
2201
2202     if (!dc) goto done;
2203
2204     if (dc->gdiFont)
2205         ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2206
2207     GDI_ReleaseObj(hdc);
2208
2209 done:
2210     if (ret == DEFAULT_CHARSET && fs)
2211         memset(fs, 0, sizeof(FONTSIGNATURE));
2212     return ret;
2213 }