cryptnet: Test CertDllVerifyRevocation.
[wine] / dlls / gdi32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
40
41   /* Device -> World size conversion */
42
43 /* Performs a device to world transformation on the specified width (which
44  * is in integer format).
45  */
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
47 {
48     double floatWidth;
49
50     /* Perform operation with floating point */
51     floatWidth = (double)width * dc->xformVport2World.eM11;
52     /* Round to integers */
53     return GDI_ROUND(floatWidth);
54 }
55
56 /* Performs a device to world transformation on the specified size (which
57  * is in integer format).
58  */
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
60 {
61     double floatHeight;
62
63     /* Perform operation with floating point */
64     floatHeight = (double)height * dc->xformVport2World.eM22;
65     /* Round to integers */
66     return GDI_ROUND(floatHeight);
67 }
68
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
70 {
71     POINT pt[2];
72     pt[0].x = pt[0].y = 0;
73     pt[1].x = width;
74     pt[1].y = 0;
75     LPtoDP(dc->hSelf, pt, 2);
76     return pt[1].x - pt[0].x;
77 }
78
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
80 {
81     POINT pt[2];
82     pt[0].x = pt[0].y = 0;
83     pt[1].x = 0;
84     pt[1].y = height;
85     LPtoDP(dc->hSelf, pt, 2);
86     return pt[1].y - pt[0].y;
87 }
88
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
93
94 static const struct gdi_obj_funcs font_funcs =
95 {
96     FONT_SelectObject,  /* pSelectObject */
97     FONT_GetObjectA,    /* pGetObjectA */
98     FONT_GetObjectW,    /* pGetObjectW */
99     NULL,               /* pUnrealizeObject */
100     FONT_DeleteObject   /* pDeleteObject */
101 };
102
103 #define ENUM_UNICODE    0x00000001
104 #define ENUM_CALLED     0x00000002
105
106 typedef struct
107 {
108     GDIOBJHDR   header;
109     LOGFONTW    logfont;
110 } FONTOBJ;
111
112 typedef struct
113 {
114   LPLOGFONTW          lpLogFontParam;
115   FONTENUMPROCW       lpEnumFunc;
116   LPARAM              lpData;
117   DWORD               dwFlags;
118   HDC                 hdc;
119 } fontEnum32;
120
121 /*
122  *  For TranslateCharsetInfo
123  */
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
126   /* ANSI */
127   { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128   { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129   { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130   { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131   { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132   { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133   { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134   { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135   { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136   /* reserved by ANSI */
137   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144   /* ANSI and OEM */
145   { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146   { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147   { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148   { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149   { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150   { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151   /* reserved for alternate ANSI and OEM */
152   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160   /* reserved for system */
161   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162   { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
163 };
164
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
166 {
167     memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168     MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
169                         LF_FACESIZE);
170     fontW->lfFaceName[LF_FACESIZE-1] = 0;
171 }
172
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
174 {
175     memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176     WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177                         LF_FACESIZE, NULL, NULL);
178     fontA->lfFaceName[LF_FACESIZE-1] = 0;
179 }
180
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
182 {
183     FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
184
185     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186                          (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187     fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189                          (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190     fontA->elfStyle[LF_FACESIZE-1] = '\0';
191     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192                          (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193     fontA->elfScript[LF_FACESIZE-1] = '\0';
194 }
195
196 /***********************************************************************
197  *              TEXTMETRIC conversion functions.
198  */
199 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
200 {
201     ptmA->tmHeight = ptmW->tmHeight;
202     ptmA->tmAscent = ptmW->tmAscent;
203     ptmA->tmDescent = ptmW->tmDescent;
204     ptmA->tmInternalLeading = ptmW->tmInternalLeading;
205     ptmA->tmExternalLeading = ptmW->tmExternalLeading;
206     ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
207     ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
208     ptmA->tmWeight = ptmW->tmWeight;
209     ptmA->tmOverhang = ptmW->tmOverhang;
210     ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
211     ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
212     ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
213     if (ptmW->tmCharSet == SYMBOL_CHARSET)
214     {
215         ptmA->tmFirstChar = 0x1e;
216         ptmA->tmLastChar = 0xff;  /* win9x behaviour - we need the OS2 table data to calculate correctly */
217     }
218     else
219     {
220         ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
221         ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
222     }
223     ptmA->tmDefaultChar = ptmW->tmDefaultChar;
224     ptmA->tmBreakChar = ptmW->tmBreakChar;
225     ptmA->tmItalic = ptmW->tmItalic;
226     ptmA->tmUnderlined = ptmW->tmUnderlined;
227     ptmA->tmStruckOut = ptmW->tmStruckOut;
228     ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
229     ptmA->tmCharSet = ptmW->tmCharSet;
230 }
231
232
233 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
234 {
235     FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
236     ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
237     ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
238     ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
239     ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
240     memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
241 }
242
243
244 /***********************************************************************
245  *           GdiGetCodePage   (GDI32.@)
246  */
247 DWORD WINAPI GdiGetCodePage( HDC hdc )
248 {
249     UINT cp = CP_ACP;
250     DC *dc = get_dc_ptr( hdc );
251
252     if (dc)
253     {
254         cp = dc->font_code_page;
255         release_dc_ptr( dc );
256     }
257     return cp;
258 }
259
260 /***********************************************************************
261  *           FONT_mbtowc
262  *
263  * Returns a Unicode translation of str using the charset of the
264  * currently selected font in hdc.  If count is -1 then str is assumed
265  * to be '\0' terminated, otherwise it contains the number of bytes to
266  * convert.  If plenW is non-NULL, on return it will point to the
267  * number of WCHARs that have been written.  If pCP is non-NULL, on
268  * return it will point to the codepage used in the conversion.  The
269  * caller should free the returned LPWSTR from the process heap
270  * itself.
271  */
272 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
273 {
274     UINT cp;
275     INT lenW;
276     LPWSTR strW;
277
278     cp = GdiGetCodePage( hdc );
279
280     if(count == -1) count = strlen(str);
281     lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
282     strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
283     MultiByteToWideChar(cp, 0, str, count, strW, lenW);
284     TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
285     if(plenW) *plenW = lenW;
286     if(pCP) *pCP = cp;
287     return strW;
288 }
289
290
291 /***********************************************************************
292  *           CreateFontIndirectA   (GDI32.@)
293  */
294 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
295 {
296     LOGFONTW lfW;
297
298     if (!plfA) return 0;
299
300     FONT_LogFontAToW( plfA, &lfW );
301     return CreateFontIndirectW( &lfW );
302 }
303
304 /***********************************************************************
305  *           CreateFontIndirectW   (GDI32.@)
306  */
307 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
308 {
309     HFONT hFont;
310     FONTOBJ *fontPtr;
311
312     if (!plf) return 0;
313
314     if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
315
316     fontPtr->logfont = *plf;
317
318     if (plf->lfEscapement != plf->lfOrientation)
319     {
320         /* this should really depend on whether GM_ADVANCED is set */
321         fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
322         WARN("orientation angle %f set to "
323              "escapement angle %f for new font %p\n",
324              plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
325     }
326
327     if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
328     {
329         HeapFree( GetProcessHeap(), 0, fontPtr );
330         return 0;
331     }
332
333     TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
334           plf->lfHeight, plf->lfWidth,
335           plf->lfEscapement, plf->lfOrientation,
336           plf->lfPitchAndFamily,
337           plf->lfOutPrecision, plf->lfClipPrecision,
338           plf->lfQuality, plf->lfCharSet,
339           debugstr_w(plf->lfFaceName),
340           plf->lfWeight > 400 ? "Bold" : "",
341           plf->lfItalic ? "Italic" : "",
342           plf->lfUnderline ? "Underline" : "", hFont);
343
344     return hFont;
345 }
346
347 /*************************************************************************
348  *           CreateFontA    (GDI32.@)
349  */
350 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
351                               INT orient, INT weight, DWORD italic,
352                               DWORD underline, DWORD strikeout, DWORD charset,
353                               DWORD outpres, DWORD clippres, DWORD quality,
354                               DWORD pitch, LPCSTR name )
355 {
356     LOGFONTA logfont;
357
358     logfont.lfHeight = height;
359     logfont.lfWidth = width;
360     logfont.lfEscapement = esc;
361     logfont.lfOrientation = orient;
362     logfont.lfWeight = weight;
363     logfont.lfItalic = italic;
364     logfont.lfUnderline = underline;
365     logfont.lfStrikeOut = strikeout;
366     logfont.lfCharSet = charset;
367     logfont.lfOutPrecision = outpres;
368     logfont.lfClipPrecision = clippres;
369     logfont.lfQuality = quality;
370     logfont.lfPitchAndFamily = pitch;
371
372     if (name)
373         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
374     else
375         logfont.lfFaceName[0] = '\0';
376
377     return CreateFontIndirectA( &logfont );
378 }
379
380 /*************************************************************************
381  *           CreateFontW    (GDI32.@)
382  */
383 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
384                               INT orient, INT weight, DWORD italic,
385                               DWORD underline, DWORD strikeout, DWORD charset,
386                               DWORD outpres, DWORD clippres, DWORD quality,
387                               DWORD pitch, LPCWSTR name )
388 {
389     LOGFONTW logfont;
390
391     logfont.lfHeight = height;
392     logfont.lfWidth = width;
393     logfont.lfEscapement = esc;
394     logfont.lfOrientation = orient;
395     logfont.lfWeight = weight;
396     logfont.lfItalic = italic;
397     logfont.lfUnderline = underline;
398     logfont.lfStrikeOut = strikeout;
399     logfont.lfCharSet = charset;
400     logfont.lfOutPrecision = outpres;
401     logfont.lfClipPrecision = clippres;
402     logfont.lfQuality = quality;
403     logfont.lfPitchAndFamily = pitch;
404
405     if (name)
406         lstrcpynW(logfont.lfFaceName, name,
407                   sizeof(logfont.lfFaceName) / sizeof(WCHAR));
408     else
409         logfont.lfFaceName[0] = '\0';
410
411     return CreateFontIndirectW( &logfont );
412 }
413
414 static void update_font_code_page( DC *dc )
415 {
416     CHARSETINFO csi;
417     int charset = DEFAULT_CHARSET;
418
419     if (dc->gdiFont)
420         charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
421
422     /* Hmm, nicely designed api this one! */
423     if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
424         dc->font_code_page = csi.ciACP;
425     else {
426         switch(charset) {
427         case OEM_CHARSET:
428             dc->font_code_page = GetOEMCP();
429             break;
430         case DEFAULT_CHARSET:
431             dc->font_code_page = GetACP();
432             break;
433
434         case VISCII_CHARSET:
435         case TCVN_CHARSET:
436         case KOI8_CHARSET:
437         case ISO3_CHARSET:
438         case ISO4_CHARSET:
439         case ISO10_CHARSET:
440         case CELTIC_CHARSET:
441             /* FIXME: These have no place here, but because x11drv
442                enumerates fonts with these (made up) charsets some apps
443                might use them and then the FIXME below would become
444                annoying.  Now we could pick the intended codepage for
445                each of these, but since it's broken anyway we'll just
446                use CP_ACP and hope it'll go away...
447             */
448             dc->font_code_page = CP_ACP;
449             break;
450
451         default:
452             FIXME("Can't find codepage for charset %d\n", charset);
453             dc->font_code_page = CP_ACP;
454             break;
455         }
456     }
457
458     TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
459 }
460
461 /***********************************************************************
462  *           FONT_SelectObject
463  *
464  * If the driver supports vector fonts we create a gdi font first and
465  * then call the driver to give it a chance to supply its own device
466  * font.  If the driver wants to do this it returns TRUE and we can
467  * delete the gdi font, if the driver wants to use the gdi font it
468  * should return FALSE, to signal an error return GDI_ERROR.  For
469  * drivers that don't support vector fonts they must supply their own
470  * font.
471  */
472 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
473 {
474     HGDIOBJ ret = 0;
475     DC *dc = get_dc_ptr( hdc );
476
477     if (!dc) return 0;
478
479     if (!GDI_inc_ref_count( handle ))
480     {
481         release_dc_ptr( dc );
482         return 0;
483     }
484
485     if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
486         dc->gdiFont = WineEngCreateFontInstance( dc, handle );
487
488     if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
489
490     if (ret && dc->gdiFont) dc->gdiFont = 0;
491
492     if (ret == HGDI_ERROR)
493     {
494         GDI_dec_ref_count( handle );
495         ret = 0; /* SelectObject returns 0 on error */
496     }
497     else
498     {
499         ret = dc->hFont;
500         dc->hFont = handle;
501         update_font_code_page( dc );
502         GDI_dec_ref_count( ret );
503     }
504     release_dc_ptr( dc );
505     return ret;
506 }
507
508
509 /***********************************************************************
510  *           FONT_GetObjectA
511  */
512 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
513 {
514     FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
515     LOGFONTA lfA;
516
517     if (!font) return 0;
518     if (buffer)
519     {
520         FONT_LogFontWToA( &font->logfont, &lfA );
521         if (count > sizeof(lfA)) count = sizeof(lfA);
522         memcpy( buffer, &lfA, count );
523     }
524     else count = sizeof(lfA);
525     GDI_ReleaseObj( handle );
526     return count;
527 }
528
529 /***********************************************************************
530  *           FONT_GetObjectW
531  */
532 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
533 {
534     FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
535
536     if (!font) return 0;
537     if (buffer)
538     {
539         if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
540         memcpy( buffer, &font->logfont, count );
541     }
542     else count = sizeof(LOGFONTW);
543     GDI_ReleaseObj( handle );
544     return count;
545 }
546
547
548 /***********************************************************************
549  *           FONT_DeleteObject
550  */
551 static BOOL FONT_DeleteObject( HGDIOBJ handle )
552 {
553     FONTOBJ *obj;
554
555     WineEngDestroyFontInstance( handle );
556
557     if (!(obj = free_gdi_handle( handle ))) return FALSE;
558     return HeapFree( GetProcessHeap(), 0, obj );
559 }
560
561
562 /***********************************************************************
563  *              FONT_EnumInstance
564  *
565  * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
566  *       We have to use other types because of the FONTENUMPROCW definition.
567  */
568 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
569                                        DWORD fType, LPARAM lp )
570 {
571     fontEnum32 *pfe = (fontEnum32*)lp;
572     INT ret = 1;
573
574     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
575     if ((!pfe->lpLogFontParam ||
576         pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
577         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
578        (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
579     {
580         /* convert font metrics */
581         ENUMLOGFONTEXA logfont;
582         NEWTEXTMETRICEXA tmA;
583
584         pfe->dwFlags |= ENUM_CALLED;
585         if (!(pfe->dwFlags & ENUM_UNICODE))
586         {
587             FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
588             FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
589             plf = (LOGFONTW *)&logfont.elfLogFont;
590             ptm = (TEXTMETRICW *)&tmA;
591         }
592
593         ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
594     }
595     return ret;
596 }
597
598 /***********************************************************************
599  *              FONT_EnumFontFamiliesEx
600  */
601 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
602                                     FONTENUMPROCW efproc,
603                                     LPARAM lParam, DWORD dwUnicode)
604 {
605     INT ret = 1, ret2;
606     DC *dc = get_dc_ptr( hDC );
607     fontEnum32 fe32;
608     BOOL enum_gdi_fonts;
609
610     if (!dc) return 0;
611
612     if (plf)
613         TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
614             plf->lfCharSet);
615     fe32.lpLogFontParam = plf;
616     fe32.lpEnumFunc = efproc;
617     fe32.lpData = lParam;
618     fe32.dwFlags = dwUnicode;
619     fe32.hdc = hDC;
620
621     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
622
623     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
624     {
625         ret = 0;
626         goto done;
627     }
628
629     if (enum_gdi_fonts)
630         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
631     fe32.dwFlags &= ~ENUM_CALLED;
632     if (ret && dc->funcs->pEnumDeviceFonts) {
633         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
634         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
635             ret = ret2;
636     }
637  done:
638     release_dc_ptr( dc );
639     return ret;
640 }
641
642 /***********************************************************************
643  *              EnumFontFamiliesExW     (GDI32.@)
644  */
645 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
646                                     FONTENUMPROCW efproc,
647                                     LPARAM lParam, DWORD dwFlags )
648 {
649     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
650 }
651
652 /***********************************************************************
653  *              EnumFontFamiliesExA     (GDI32.@)
654  */
655 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
656                                     FONTENUMPROCA efproc,
657                                     LPARAM lParam, DWORD dwFlags)
658 {
659     LOGFONTW lfW, *plfW;
660
661     if (plf)
662     {
663         FONT_LogFontAToW( plf, &lfW );
664         plfW = &lfW;
665     }
666     else plfW = NULL;
667
668     return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
669 }
670
671 /***********************************************************************
672  *              EnumFontFamiliesA       (GDI32.@)
673  */
674 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
675                                   FONTENUMPROCA efproc, LPARAM lpData )
676 {
677     LOGFONTA lf, *plf;
678
679     if (lpFamily)
680     {
681         if (!*lpFamily) return 1;
682         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
683         lf.lfCharSet = DEFAULT_CHARSET;
684         lf.lfPitchAndFamily = 0;
685         plf = &lf;
686     }
687     else plf = NULL;
688
689     return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
690 }
691
692 /***********************************************************************
693  *              EnumFontFamiliesW       (GDI32.@)
694  */
695 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
696                                   FONTENUMPROCW efproc, LPARAM lpData )
697 {
698     LOGFONTW lf, *plf;
699
700     if (lpFamily)
701     {
702         if (!*lpFamily) return 1;
703         lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
704         lf.lfCharSet = DEFAULT_CHARSET;
705         lf.lfPitchAndFamily = 0;
706         plf = &lf;
707     }
708     else plf = NULL;
709
710     return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
711 }
712
713 /***********************************************************************
714  *              EnumFontsA              (GDI32.@)
715  */
716 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
717                            LPARAM lpData )
718 {
719     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
720 }
721
722 /***********************************************************************
723  *              EnumFontsW              (GDI32.@)
724  */
725 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
726                            LPARAM lpData )
727 {
728     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
729 }
730
731
732 /***********************************************************************
733  *           GetTextCharacterExtra    (GDI32.@)
734  */
735 INT WINAPI GetTextCharacterExtra( HDC hdc )
736 {
737     INT ret;
738     DC *dc = get_dc_ptr( hdc );
739     if (!dc) return 0x80000000;
740     ret = dc->charExtra;
741     release_dc_ptr( dc );
742     return ret;
743 }
744
745
746 /***********************************************************************
747  *           SetTextCharacterExtra    (GDI32.@)
748  */
749 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
750 {
751     INT prev;
752     DC * dc = get_dc_ptr( hdc );
753     if (!dc) return 0x80000000;
754     if (dc->funcs->pSetTextCharacterExtra)
755         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
756     else
757     {
758         prev = dc->charExtra;
759         dc->charExtra = extra;
760     }
761     release_dc_ptr( dc );
762     return prev;
763 }
764
765
766 /***********************************************************************
767  *           SetTextJustification    (GDI32.@)
768  */
769 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
770 {
771     BOOL ret = TRUE;
772     DC * dc = get_dc_ptr( hdc );
773     if (!dc) return FALSE;
774     if (dc->funcs->pSetTextJustification)
775         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
776     else
777     {
778         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
779         if (!extra) breaks = 0;
780         if (breaks)
781         {
782             dc->breakExtra = extra / breaks;
783             dc->breakRem   = extra - (breaks * dc->breakExtra);
784         }
785         else
786         {
787             dc->breakExtra = 0;
788             dc->breakRem   = 0;
789         }
790     }
791     release_dc_ptr( dc );
792     return ret;
793 }
794
795
796 /***********************************************************************
797  *           GetTextFaceA    (GDI32.@)
798  */
799 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
800 {
801     INT res = GetTextFaceW(hdc, 0, NULL);
802     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
803     GetTextFaceW( hdc, res, nameW );
804
805     if (name)
806     {
807         if (count)
808         {
809             res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
810             if (res == 0)
811                 res = count;
812             name[count-1] = 0;
813             /* GetTextFaceA does NOT include the nul byte in the return count.  */
814             res--;
815         }
816         else
817             res = 0;
818     }
819     else
820         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
821     HeapFree( GetProcessHeap(), 0, nameW );
822     return res;
823 }
824
825 /***********************************************************************
826  *           GetTextFaceW    (GDI32.@)
827  */
828 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
829 {
830     FONTOBJ *font;
831     INT     ret = 0;
832
833     DC * dc = get_dc_ptr( hdc );
834     if (!dc) return 0;
835
836     if(dc->gdiFont)
837         ret = WineEngGetTextFace(dc->gdiFont, count, name);
838     else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
839     {
840         INT n = strlenW(font->logfont.lfFaceName) + 1;
841         if (name)
842         {
843             lstrcpynW( name, font->logfont.lfFaceName, count );
844             ret = min(count, n);
845         }
846         else ret = n;
847         GDI_ReleaseObj( dc->hFont );
848     }
849     release_dc_ptr( dc );
850     return ret;
851 }
852
853
854 /***********************************************************************
855  *           GetTextExtentPoint32A    (GDI32.@)
856  *
857  * See GetTextExtentPoint32W.
858  */
859 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
860                                      LPSIZE size )
861 {
862     BOOL ret = FALSE;
863     INT wlen;
864     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
865
866     if (p) {
867         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
868         HeapFree( GetProcessHeap(), 0, p );
869     }
870
871     TRACE("(%p %s %d %p): returning %d x %d\n",
872           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
873     return ret;
874 }
875
876
877 /***********************************************************************
878  * GetTextExtentPoint32W [GDI32.@]
879  *
880  * Computes width/height for a string.
881  *
882  * Computes width and height of the specified string.
883  *
884  * RETURNS
885  *    Success: TRUE
886  *    Failure: FALSE
887  */
888 BOOL WINAPI GetTextExtentPoint32W(
889     HDC hdc,     /* [in]  Handle of device context */
890     LPCWSTR str,   /* [in]  Address of text string */
891     INT count,   /* [in]  Number of characters in string */
892     LPSIZE size) /* [out] Address of structure for string size */
893 {
894     return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
895 }
896
897 /***********************************************************************
898  * GetTextExtentExPointI [GDI32.@]
899  *
900  * Computes width and height of the array of glyph indices.
901  *
902  * PARAMS
903  *    hdc     [I] Handle of device context.
904  *    indices [I] Glyph index array.
905  *    count   [I] Number of glyphs in array.
906  *    max_ext [I] Maximum width in glyphs.
907  *    nfit    [O] Maximum number of characters.
908  *    dxs     [O] Partial string widths.
909  *    size    [O] Returned string size.
910  *
911  * RETURNS
912  *    Success: TRUE
913  *    Failure: FALSE
914  */
915 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
916                                    LPINT nfit, LPINT dxs, LPSIZE size )
917 {
918     BOOL ret = FALSE;
919     DC * dc = get_dc_ptr( hdc );
920     if (!dc) return FALSE;
921
922     if(dc->gdiFont) {
923         ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
924         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
925         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
926         size->cx += count * dc->charExtra;
927     }
928     else if(dc->funcs->pGetTextExtentExPoint) {
929         FIXME("calling GetTextExtentExPoint\n");
930         ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, indices, count,
931                                                 max_ext, nfit, dxs, size );
932     }
933
934     release_dc_ptr( dc );
935
936     TRACE("(%p %p %d %p): returning %d x %d\n",
937           hdc, indices, count, size, size->cx, size->cy );
938     return ret;
939 }
940
941 /***********************************************************************
942  * GetTextExtentPointI [GDI32.@]
943  *
944  * Computes width and height of the array of glyph indices.
945  *
946  * PARAMS
947  *    hdc     [I] Handle of device context.
948  *    indices [I] Glyph index array.
949  *    count   [I] Number of glyphs in array.
950  *    size    [O] Returned string size.
951  *
952  * RETURNS
953  *    Success: TRUE
954  *    Failure: FALSE
955  */
956 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
957 {
958     return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
959 }
960
961
962 /***********************************************************************
963  *           GetTextExtentPointA    (GDI32.@)
964  */
965 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
966                                           LPSIZE size )
967 {
968     TRACE("not bug compatible.\n");
969     return GetTextExtentPoint32A( hdc, str, count, size );
970 }
971
972 /***********************************************************************
973  *           GetTextExtentPointW   (GDI32.@)
974  */
975 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
976                                           LPSIZE size )
977 {
978     TRACE("not bug compatible.\n");
979     return GetTextExtentPoint32W( hdc, str, count, size );
980 }
981
982
983 /***********************************************************************
984  *           GetTextExtentExPointA    (GDI32.@)
985  */
986 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
987                                    INT maxExt, LPINT lpnFit,
988                                    LPINT alpDx, LPSIZE size )
989 {
990     BOOL ret;
991     INT wlen;
992     INT *walpDx = NULL;
993     LPWSTR p = NULL;
994     
995     if (alpDx &&
996        NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
997        return FALSE;
998     
999     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1000     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1001     if (walpDx)
1002     {
1003         INT n = lpnFit ? *lpnFit : wlen;
1004         INT i, j;
1005         for(i = 0, j = 0; i < n; i++, j++)
1006         {
1007             alpDx[j] = walpDx[i];
1008             if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1009         }
1010     }
1011     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1012     HeapFree( GetProcessHeap(), 0, p );
1013     HeapFree( GetProcessHeap(), 0, walpDx );
1014     return ret;
1015 }
1016
1017
1018 /***********************************************************************
1019  *           GetTextExtentExPointW    (GDI32.@)
1020  *
1021  * Return the size of the string as it would be if it was output properly by
1022  * e.g. TextOut.
1023  *
1024  * This should include
1025  * - Intercharacter spacing
1026  * - justification spacing (not yet done)
1027  * - kerning? see below
1028  *
1029  * Kerning.  Since kerning would be carried out by the rendering code it should
1030  * be done by the driver.  However they don't support it yet.  Also I am not
1031  * yet persuaded that (certainly under Win95) any kerning is actually done.
1032  *
1033  * str: According to MSDN this should be null-terminated.  That is not true; a
1034  *      null will not terminate it early.
1035  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1036  *       than count.  I have seen it be either the size of the full string or
1037  *       1 less than the size of the full string.  I have not seen it bear any
1038  *       resemblance to the portion that would fit.
1039  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1040  *         trailing intercharacter spacing and any trailing justification.
1041  *
1042  * FIXME
1043  * Currently we do this by measuring each character etc.  We should do it by
1044  * passing the request to the driver, perhaps by extending the
1045  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1046  * thinking about kerning issues and rounding issues in the justification.
1047  */
1048
1049 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1050                                    INT maxExt, LPINT lpnFit,
1051                                    LPINT alpDx, LPSIZE size )
1052 {
1053     INT nFit = 0;
1054     LPINT dxs = NULL;
1055     DC *dc;
1056     BOOL ret = FALSE;
1057     TEXTMETRICW tm;
1058
1059     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1060
1061     dc = get_dc_ptr(hdc);
1062     if (! dc)
1063         return FALSE;
1064
1065     GetTextMetricsW(hdc, &tm);
1066
1067     /* If we need to calculate nFit, then we need the partial extents even if
1068        the user hasn't provided us with an array.  */
1069     if (lpnFit)
1070     {
1071         dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1072         if (! dxs)
1073         {
1074             release_dc_ptr(dc);
1075             SetLastError(ERROR_OUTOFMEMORY);
1076             return FALSE;
1077         }
1078     }
1079     else
1080         dxs = alpDx;
1081
1082     if (dc->gdiFont)
1083         ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1084                                           0, NULL, dxs, size);
1085     else if (dc->funcs->pGetTextExtentExPoint)
1086         ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1087                                                0, NULL, dxs, size);
1088
1089     /* Perform device size to world size transformations.  */
1090     if (ret)
1091     {
1092         INT extra      = dc->charExtra,
1093         breakExtra = dc->breakExtra,
1094         breakRem   = dc->breakRem,
1095         i;
1096
1097         if (dxs)
1098         {
1099             for (i = 0; i < count; ++i)
1100             {
1101                 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1102                 dxs[i] += (i+1) * extra;
1103                 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1104                 {
1105                     dxs[i] += breakExtra;
1106                     if (breakRem > 0)
1107                     {
1108                         breakRem--;
1109                         dxs[i]++;
1110                     }
1111                 }
1112                 if (dxs[i] <= maxExt)
1113                     ++nFit;
1114             }
1115             breakRem = dc->breakRem;
1116         }
1117         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1118         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1119
1120         if (!dxs && count > 1 && (breakExtra || breakRem))
1121         {
1122             for (i = 0; i < count; i++)
1123             {
1124                 if (str[i] == tm.tmBreakChar)
1125                 {
1126                     size->cx += breakExtra;
1127                     if (breakRem > 0)
1128                     {
1129                         breakRem--;
1130                         (size->cx)++;
1131                     }
1132                 }
1133             }
1134         }
1135     }
1136
1137     if (lpnFit)
1138         *lpnFit = nFit;
1139
1140     if (! alpDx)
1141         HeapFree(GetProcessHeap(), 0, dxs);
1142
1143     release_dc_ptr( dc );
1144
1145     TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1146     return ret;
1147 }
1148
1149 /***********************************************************************
1150  *           GetTextMetricsA    (GDI32.@)
1151  */
1152 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1153 {
1154     TEXTMETRICW tm32;
1155
1156     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1157     FONT_TextMetricWToA( &tm32, metrics );
1158     return TRUE;
1159 }
1160
1161 /***********************************************************************
1162  *           GetTextMetricsW    (GDI32.@)
1163  */
1164 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1165 {
1166     BOOL ret = FALSE;
1167     DC * dc = get_dc_ptr( hdc );
1168     if (!dc) return FALSE;
1169
1170     if (dc->gdiFont)
1171         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1172     else if (dc->funcs->pGetTextMetrics)
1173         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1174
1175     if (ret)
1176     {
1177     /* device layer returns values in device units
1178      * therefore we have to convert them to logical */
1179
1180         metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1181         metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1182
1183 #define WDPTOLP(x) ((x<0)?                                      \
1184                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1185                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1186 #define HDPTOLP(y) ((y<0)?                                      \
1187                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1188                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1189
1190     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1191     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1192     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1193     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1194     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1195     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1196     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1197     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1198         ret = TRUE;
1199 #undef WDPTOLP
1200 #undef HDPTOLP
1201     TRACE("text metrics:\n"
1202           "    Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1203           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1204           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1205           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1206           "    PitchAndFamily = %02x\n"
1207           "    --------------------\n"
1208           "    InternalLeading = %i\n"
1209           "    Ascent = %i\n"
1210           "    Descent = %i\n"
1211           "    Height = %i\n",
1212           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1213           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1214           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1215           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1216           metrics->tmPitchAndFamily,
1217           metrics->tmInternalLeading,
1218           metrics->tmAscent,
1219           metrics->tmDescent,
1220           metrics->tmHeight );
1221     }
1222     release_dc_ptr( dc );
1223     return ret;
1224 }
1225
1226
1227 /***********************************************************************
1228  *              GetOutlineTextMetricsA (GDI32.@)
1229  * Gets metrics for TrueType fonts.
1230  *
1231  * NOTES
1232  *    If the supplied buffer isn't big enough Windows partially fills it up to
1233  *    its given length and returns that length.
1234  *
1235  * RETURNS
1236  *    Success: Non-zero or size of required buffer
1237  *    Failure: 0
1238  */
1239 UINT WINAPI GetOutlineTextMetricsA(
1240     HDC hdc,    /* [in]  Handle of device context */
1241     UINT cbData, /* [in]  Size of metric data array */
1242     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1243 {
1244     char buf[512], *ptr;
1245     UINT ret, needed;
1246     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1247     OUTLINETEXTMETRICA *output = lpOTM;
1248     INT left, len;
1249
1250     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1251         return 0;
1252     if(ret > sizeof(buf))
1253         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1254     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1255
1256     needed = sizeof(OUTLINETEXTMETRICA);
1257     if(lpOTMW->otmpFamilyName)
1258         needed += WideCharToMultiByte(CP_ACP, 0,
1259            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1260                                       NULL, 0, NULL, NULL);
1261     if(lpOTMW->otmpFaceName)
1262         needed += WideCharToMultiByte(CP_ACP, 0,
1263            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1264                                       NULL, 0, NULL, NULL);
1265     if(lpOTMW->otmpStyleName)
1266         needed += WideCharToMultiByte(CP_ACP, 0,
1267            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1268                                       NULL, 0, NULL, NULL);
1269     if(lpOTMW->otmpFullName)
1270         needed += WideCharToMultiByte(CP_ACP, 0,
1271            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1272                                       NULL, 0, NULL, NULL);
1273
1274     if(!lpOTM) {
1275         ret = needed;
1276         goto end;
1277     }
1278
1279     TRACE("needed = %d\n", needed);
1280     if(needed > cbData)
1281         /* Since the supplied buffer isn't big enough, we'll alloc one
1282            that is and memcpy the first cbData bytes into the lpOTM at
1283            the end. */
1284         output = HeapAlloc(GetProcessHeap(), 0, needed);
1285
1286     ret = output->otmSize = min(needed, cbData);
1287     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1288     output->otmFiller = 0;
1289     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1290     output->otmfsSelection = lpOTMW->otmfsSelection;
1291     output->otmfsType = lpOTMW->otmfsType;
1292     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1293     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1294     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1295     output->otmEMSquare = lpOTMW->otmEMSquare;
1296     output->otmAscent = lpOTMW->otmAscent;
1297     output->otmDescent = lpOTMW->otmDescent;
1298     output->otmLineGap = lpOTMW->otmLineGap;
1299     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1300     output->otmsXHeight = lpOTMW->otmsXHeight;
1301     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1302     output->otmMacAscent = lpOTMW->otmMacAscent;
1303     output->otmMacDescent = lpOTMW->otmMacDescent;
1304     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1305     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1306     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1307     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1308     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1309     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1310     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1311     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1312     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1313     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1314
1315
1316     ptr = (char*)(output + 1);
1317     left = needed - sizeof(*output);
1318
1319     if(lpOTMW->otmpFamilyName) {
1320         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1321         len = WideCharToMultiByte(CP_ACP, 0,
1322              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1323                                   ptr, left, NULL, NULL);
1324         left -= len;
1325         ptr += len;
1326     } else
1327         output->otmpFamilyName = 0;
1328
1329     if(lpOTMW->otmpFaceName) {
1330         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1331         len = WideCharToMultiByte(CP_ACP, 0,
1332              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1333                                   ptr, left, NULL, NULL);
1334         left -= len;
1335         ptr += len;
1336     } else
1337         output->otmpFaceName = 0;
1338
1339     if(lpOTMW->otmpStyleName) {
1340         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1341         len = WideCharToMultiByte(CP_ACP, 0,
1342              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1343                                   ptr, left, NULL, NULL);
1344         left -= len;
1345         ptr += len;
1346     } else
1347         output->otmpStyleName = 0;
1348
1349     if(lpOTMW->otmpFullName) {
1350         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1351         len = WideCharToMultiByte(CP_ACP, 0,
1352              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1353                                   ptr, left, NULL, NULL);
1354         left -= len;
1355     } else
1356         output->otmpFullName = 0;
1357
1358     assert(left == 0);
1359
1360     if(output != lpOTM) {
1361         memcpy(lpOTM, output, cbData);
1362         HeapFree(GetProcessHeap(), 0, output);
1363
1364         /* check if the string offsets really fit into the provided size */
1365         /* FIXME: should we check string length as well? */
1366         /* make sure that we don't read/write beyond the provided buffer */
1367         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1368         {
1369             if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1370                 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1371         }
1372
1373         /* make sure that we don't read/write beyond the provided buffer */
1374         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1375         {
1376             if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1377                 lpOTM->otmpFaceName = 0; /* doesn't fit */
1378         }
1379
1380             /* make sure that we don't read/write beyond the provided buffer */
1381         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1382         {
1383             if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1384                 lpOTM->otmpStyleName = 0; /* doesn't fit */
1385         }
1386
1387         /* make sure that we don't read/write beyond the provided buffer */
1388         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1389         {
1390             if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1391                 lpOTM->otmpFullName = 0; /* doesn't fit */
1392         }
1393     }
1394
1395 end:
1396     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1397         HeapFree(GetProcessHeap(), 0, lpOTMW);
1398
1399     return ret;
1400 }
1401
1402
1403 /***********************************************************************
1404  *           GetOutlineTextMetricsW [GDI32.@]
1405  */
1406 UINT WINAPI GetOutlineTextMetricsW(
1407     HDC hdc,    /* [in]  Handle of device context */
1408     UINT cbData, /* [in]  Size of metric data array */
1409     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1410 {
1411     DC *dc = get_dc_ptr( hdc );
1412     OUTLINETEXTMETRICW *output = lpOTM;
1413     UINT ret;
1414
1415     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1416     if(!dc) return 0;
1417
1418     if(dc->gdiFont) {
1419         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1420         if(lpOTM && ret) {
1421             if(ret > cbData) {
1422                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1423                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1424             }
1425
1426         output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1427         output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1428
1429 #define WDPTOLP(x) ((x<0)?                                      \
1430                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1431                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1432 #define HDPTOLP(y) ((y<0)?                                      \
1433                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1434                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1435
1436             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1437             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1438             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1439             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1440             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1441             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1442             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1443             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1444             output->otmAscent = HDPTOLP(output->otmAscent);
1445             output->otmDescent = HDPTOLP(output->otmDescent);
1446             output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1447             output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1448             output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1449             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1450             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1451             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1452             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1453             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1454             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1455             output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1456             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1457             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1458             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1459             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1460             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1461             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1462             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1463             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1464             output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1465             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1466             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1467             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1468 #undef WDPTOLP
1469 #undef HDPTOLP
1470             if(output != lpOTM) {
1471                 memcpy(lpOTM, output, cbData);
1472                 HeapFree(GetProcessHeap(), 0, output);
1473                 ret = cbData;
1474             }
1475         }
1476     }
1477
1478     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1479               but really this should just be a return 0. */
1480
1481         ret = sizeof(*lpOTM);
1482         if (lpOTM) {
1483             if(cbData < ret)
1484                 ret = 0;
1485             else {
1486                 memset(lpOTM, 0, ret);
1487                 lpOTM->otmSize = sizeof(*lpOTM);
1488                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1489                 /*
1490                   Further fill of the structure not implemented,
1491                   Needs real values for the structure members
1492                 */
1493             }
1494         }
1495     }
1496     release_dc_ptr(dc);
1497     return ret;
1498 }
1499
1500
1501 /***********************************************************************
1502  *           GetCharWidthW      (GDI32.@)
1503  *           GetCharWidth32W    (GDI32.@)
1504  */
1505 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1506                                LPINT buffer )
1507 {
1508     UINT i;
1509     BOOL ret = FALSE;
1510     DC * dc = get_dc_ptr( hdc );
1511     if (!dc) return FALSE;
1512
1513     if (dc->gdiFont)
1514         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1515     else if (dc->funcs->pGetCharWidth)
1516         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1517
1518     if (ret)
1519     {
1520         /* convert device units to logical */
1521         for( i = firstChar; i <= lastChar; i++, buffer++ )
1522             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1523         ret = TRUE;
1524     }
1525     release_dc_ptr( dc );
1526     return ret;
1527 }
1528
1529
1530 /***********************************************************************
1531  *           GetCharWidthA      (GDI32.@)
1532  *           GetCharWidth32A    (GDI32.@)
1533  */
1534 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1535                                LPINT buffer )
1536 {
1537     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1538     LPSTR str;
1539     LPWSTR wstr;
1540     BOOL ret = TRUE;
1541
1542     if(count <= 0) return FALSE;
1543
1544     str = HeapAlloc(GetProcessHeap(), 0, count);
1545     for(i = 0; i < count; i++)
1546         str[i] = (BYTE)(firstChar + i);
1547
1548     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1549
1550     for(i = 0; i < wlen; i++)
1551     {
1552         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1553         {
1554             ret = FALSE;
1555             break;
1556         }
1557         buffer++;
1558     }
1559
1560     HeapFree(GetProcessHeap(), 0, str);
1561     HeapFree(GetProcessHeap(), 0, wstr);
1562
1563     return ret;
1564 }
1565
1566
1567 /***********************************************************************
1568  *           ExtTextOutA    (GDI32.@)
1569  *
1570  * See ExtTextOutW.
1571  */
1572 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1573                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1574 {
1575     INT wlen;
1576     UINT codepage;
1577     LPWSTR p;
1578     BOOL ret;
1579     LPINT lpDxW = NULL;
1580
1581     if (flags & ETO_GLYPH_INDEX)
1582         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1583
1584     p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1585
1586     if (lpDx) {
1587         unsigned int i = 0, j = 0;
1588
1589         lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1590         while(i < count) {
1591             if(IsDBCSLeadByteEx(codepage, str[i])) {
1592                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1593                 i = i + 2;
1594             } else {
1595                 lpDxW[j++] = lpDx[i];
1596                 i = i + 1;
1597             }
1598         }
1599     }
1600
1601     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1602
1603     HeapFree( GetProcessHeap(), 0, p );
1604     HeapFree( GetProcessHeap(), 0, lpDxW );
1605     return ret;
1606 }
1607
1608
1609 /***********************************************************************
1610  *           ExtTextOutW    (GDI32.@)
1611  *
1612  * Draws text using the currently selected font, background color, and text color.
1613  * 
1614  * 
1615  * PARAMS
1616  *    x,y    [I] coordinates of string
1617  *    flags  [I]
1618  *        ETO_GRAYED - undocumented on MSDN
1619  *        ETO_OPAQUE - use background color for fill the rectangle
1620  *        ETO_CLIPPED - clipping text to the rectangle
1621  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1622  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1623  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1624  *                         Affects BiDi ordering
1625  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1626  *        ETO_PDY - unimplemented
1627  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1628  *                            do not translate numbers into locale representations
1629  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1630  *    lprect [I] dimensions for clipping or/and opaquing
1631  *    str    [I] text string
1632  *    count  [I] number of symbols in string
1633  *    lpDx   [I] optional parameter with distance between drawing characters
1634  *
1635  * RETURNS
1636  *    Success: TRUE
1637  *    Failure: FALSE
1638  */
1639 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1640                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1641 {
1642     BOOL ret = FALSE;
1643     LPWSTR reordered_str = (LPWSTR)str;
1644     WORD *glyphs = NULL;
1645     UINT align = GetTextAlign( hdc );
1646     POINT pt;
1647     TEXTMETRICW tm;
1648     LOGFONTW lf;
1649     double cosEsc, sinEsc;
1650     INT *deltas = NULL, char_extra;
1651     SIZE sz;
1652     RECT rc;
1653     BOOL done_extents = FALSE;
1654     INT width = 0, xwidth = 0, ywidth = 0;
1655     DWORD type;
1656     DC * dc = get_dc_ptr( hdc );
1657     INT breakRem;
1658     static int quietfixme = 0;
1659
1660     if (!dc) return FALSE;
1661
1662     breakRem = dc->breakRem;
1663
1664     if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1665     {
1666         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1667         quietfixme = 1;
1668     }
1669     if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1670     {
1671         release_dc_ptr( dc );
1672         return ret;
1673     }
1674
1675     update_dc( dc );
1676     type = GetObjectType(hdc);
1677     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1678     {
1679         ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1680         release_dc_ptr( dc );
1681         return ret;
1682     }
1683
1684     if (!lprect)
1685         flags &= ~ETO_CLIPPED;
1686         
1687     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1688     {
1689         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1690
1691         BIDI_Reorder( str, count, GCP_REORDER,
1692                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1693                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1694                       reordered_str, count, NULL );
1695     
1696         flags |= ETO_IGNORELANGUAGE;
1697     }
1698
1699     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1700           lprect, debugstr_wn(str, count), count, lpDx);
1701
1702     if(flags & ETO_GLYPH_INDEX)
1703         glyphs = reordered_str;
1704
1705     if(lprect)
1706         TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1707               lprect->bottom);
1708     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1709
1710     if(align & TA_UPDATECP)
1711     {
1712         GetCurrentPositionEx( hdc, &pt );
1713         x = pt.x;
1714         y = pt.y;
1715     }
1716
1717     GetTextMetricsW(hdc, &tm);
1718     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1719
1720     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1721         lf.lfEscapement = 0;
1722
1723     if(lf.lfEscapement != 0)
1724     {
1725         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1726         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1727     }
1728     else
1729     {
1730         cosEsc = 1;
1731         sinEsc = 0;
1732     }
1733
1734     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1735     {
1736         if(!lprect)
1737         {
1738             if(flags & ETO_GLYPH_INDEX)
1739                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1740             else
1741                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1742
1743             done_extents = TRUE;
1744             rc.left = x;
1745             rc.top = y;
1746             rc.right = x + sz.cx;
1747             rc.bottom = y + sz.cy;
1748         }
1749         else
1750         {
1751             rc = *lprect;
1752         }
1753
1754         LPtoDP(hdc, (POINT*)&rc, 2);
1755
1756         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1757         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1758     }
1759
1760     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1761         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1762
1763     if(count == 0)
1764     {
1765         ret = TRUE;
1766         goto done;
1767     }
1768
1769     pt.x = x;
1770     pt.y = y;
1771     LPtoDP(hdc, &pt, 1);
1772     x = pt.x;
1773     y = pt.y;
1774
1775     char_extra = GetTextCharacterExtra(hdc);
1776     if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1777     {
1778         UINT i;
1779         SIZE tmpsz;
1780         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1781         for(i = 0; i < count; i++)
1782         {
1783             if(lpDx && (flags & ETO_PDY))
1784                 deltas[i] = lpDx[i*2] + char_extra;
1785             else if(lpDx)
1786                 deltas[i] = lpDx[i] + char_extra;
1787             else
1788             {
1789                 if(flags & ETO_GLYPH_INDEX)
1790                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1791                 else
1792                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1793
1794                 deltas[i] = tmpsz.cx;
1795             }
1796             
1797             if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1798             {
1799                 deltas[i] = deltas[i] + dc->breakExtra;
1800                 if (breakRem > 0)
1801                 {
1802                     breakRem--;
1803                     deltas[i]++;
1804                 }
1805             }
1806             deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1807             width += deltas[i];
1808         }
1809     }
1810     else
1811     {
1812         if(!done_extents)
1813         {
1814             if(flags & ETO_GLYPH_INDEX)
1815                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1816             else
1817                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1818             done_extents = TRUE;
1819         }
1820         width = INTERNAL_XWSTODS(dc, sz.cx);
1821     }
1822     xwidth = width * cosEsc;
1823     ywidth = width * sinEsc;
1824
1825     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1826     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1827     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1828     {
1829     case TA_LEFT:
1830         if (align & TA_UPDATECP)
1831         {
1832             pt.x = x + xwidth;
1833             pt.y = y - ywidth;
1834             DPtoLP(hdc, &pt, 1);
1835             MoveToEx(hdc, pt.x, pt.y, NULL);
1836         }
1837         break;
1838
1839     case TA_CENTER:
1840         x -= xwidth / 2;
1841         y += ywidth / 2;
1842         break;
1843
1844     case TA_RIGHT:
1845         x -= xwidth;
1846         y += ywidth;
1847         if (align & TA_UPDATECP)
1848         {
1849             pt.x = x;
1850             pt.y = y;
1851             DPtoLP(hdc, &pt, 1);
1852             MoveToEx(hdc, pt.x, pt.y, NULL);
1853         }
1854         break;
1855     }
1856
1857     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1858     {
1859     case TA_TOP:
1860         y += tm.tmAscent * cosEsc;
1861         x += tm.tmAscent * sinEsc;
1862         break;
1863
1864     case TA_BOTTOM:
1865         y -= tm.tmDescent * cosEsc;
1866         x -= tm.tmDescent * sinEsc;
1867         break;
1868
1869     case TA_BASELINE:
1870         break;
1871     }
1872
1873     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1874     {
1875         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1876         {
1877             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1878                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1879             {
1880                 RECT rc;
1881                 rc.left = x;
1882                 rc.right = x + width;
1883                 rc.top = y - tm.tmAscent;
1884                 rc.bottom = y + tm.tmDescent;
1885                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1886             }
1887         }
1888     }
1889
1890     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1891     {
1892         HFONT orig_font = dc->hFont, cur_font;
1893         UINT glyph;
1894         INT span = 0, *offsets = NULL;
1895         unsigned int i;
1896
1897         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1898         for(i = 0; i < count; i++)
1899         {
1900             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1901             if(cur_font != dc->hFont)
1902             {
1903                 if(!offsets)
1904                 {
1905                     unsigned int j;
1906                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1907                     offsets[0] = 0;
1908                     if(!deltas)
1909                     {
1910                         SIZE tmpsz;
1911                         for(j = 1; j < count; j++)
1912                         {
1913                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1914                             offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1915                         }
1916                     }
1917                     else
1918                     {
1919                         for(j = 1; j < count; j++)
1920                             offsets[j] = offsets[j-1] + deltas[j];
1921                     }
1922                 }
1923                 if(span)
1924                 {
1925                     if (PATH_IsPathOpen(dc->path))
1926                         ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1927                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1928                                               glyphs, span, deltas ? deltas + i - span : NULL);
1929                     else
1930                         dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1931                                            (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1932                                            glyphs, span, deltas ? deltas + i - span : NULL);
1933                     span = 0;
1934                 }
1935                 SelectObject(hdc, cur_font);
1936             }
1937             glyphs[span++] = glyph;
1938
1939             if(i == count - 1)
1940             {
1941                 if (PATH_IsPathOpen(dc->path))
1942                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1943                                           y - (offsets ? offsets[count - span] * sinEsc : 0),
1944                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1945                                           glyphs, span, deltas ? deltas + count - span : NULL);
1946                 else
1947                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1948                                              y - (offsets ? offsets[count - span] * sinEsc : 0),
1949                                              (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1950                                              glyphs, span, deltas ? deltas + count - span : NULL);
1951                 SelectObject(hdc, orig_font);
1952                 HeapFree(GetProcessHeap(), 0, offsets);
1953            }
1954         }
1955     }
1956     else
1957     {
1958         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1959         {
1960             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1961             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1962             flags |= ETO_GLYPH_INDEX;
1963         }
1964
1965         if (PATH_IsPathOpen(dc->path))
1966             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1967                                   glyphs ? glyphs : reordered_str, count, deltas);
1968         else
1969             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1970                                      glyphs ? glyphs : reordered_str, count, deltas);
1971     }
1972
1973 done:
1974     HeapFree(GetProcessHeap(), 0, deltas);
1975     if(glyphs != reordered_str)
1976         HeapFree(GetProcessHeap(), 0, glyphs);
1977     if(reordered_str != str)
1978         HeapFree(GetProcessHeap(), 0, reordered_str);
1979
1980     release_dc_ptr( dc );
1981
1982     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
1983     {
1984         int underlinePos, strikeoutPos;
1985         int underlineWidth, strikeoutWidth;
1986         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
1987         OUTLINETEXTMETRICW* otm = NULL;
1988
1989         if(!size)
1990         {
1991             underlinePos = 0;
1992             underlineWidth = tm.tmAscent / 20 + 1;
1993             strikeoutPos = tm.tmAscent / 2;
1994             strikeoutWidth = underlineWidth;
1995         }
1996         else
1997         {
1998             otm = HeapAlloc(GetProcessHeap(), 0, size);
1999             GetOutlineTextMetricsW(hdc, size, otm);
2000             underlinePos = otm->otmsUnderscorePosition;
2001             underlineWidth = otm->otmsUnderscoreSize;
2002             strikeoutPos = otm->otmsStrikeoutPosition;
2003             strikeoutWidth = otm->otmsStrikeoutSize;
2004             HeapFree(GetProcessHeap(), 0, otm);
2005         }
2006
2007         if (PATH_IsPathOpen(dc->path))
2008         {
2009             POINT pts[5];
2010             HPEN hpen;
2011             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2012
2013             hbrush = SelectObject(hdc, hbrush);
2014             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2015
2016             if (lf.lfUnderline)
2017             {
2018                 pts[0].x = x - underlinePos * sinEsc;
2019                 pts[0].y = y - underlinePos * cosEsc;
2020                 pts[1].x = x + xwidth - underlinePos * sinEsc;
2021                 pts[1].y = y - ywidth - underlinePos * cosEsc;
2022                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2023                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2024                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2025                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2026                 pts[4].x = pts[0].x;
2027                 pts[4].y = pts[0].y;
2028                 DPtoLP(hdc, pts, 5);
2029                 Polygon(hdc, pts, 5);
2030             }
2031
2032             if (lf.lfStrikeOut)
2033             {
2034                 pts[0].x = x - strikeoutPos * sinEsc;
2035                 pts[0].y = y - strikeoutPos * cosEsc;
2036                 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2037                 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2038                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2039                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2040                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2041                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2042                 pts[4].x = pts[0].x;
2043                 pts[4].y = pts[0].y;
2044                 DPtoLP(hdc, pts, 5);
2045                 Polygon(hdc, pts, 5);
2046             }
2047
2048             SelectObject(hdc, hpen);
2049             hbrush = SelectObject(hdc, hbrush);
2050             DeleteObject(hbrush);
2051         }
2052         else
2053         {
2054             POINT pts[2], oldpt;
2055             HPEN hpen;
2056
2057             if (lf.lfUnderline)
2058             {
2059                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2060                 hpen = SelectObject(hdc, hpen);
2061                 pts[0].x = x;
2062                 pts[0].y = y;
2063                 pts[1].x = x + xwidth;
2064                 pts[1].y = y - ywidth;
2065                 DPtoLP(hdc, pts, 2);
2066                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2067                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2068                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2069                 DeleteObject(SelectObject(hdc, hpen));
2070             }
2071
2072             if (lf.lfStrikeOut)
2073             {
2074                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2075                 hpen = SelectObject(hdc, hpen);
2076                 pts[0].x = x;
2077                 pts[0].y = y;
2078                 pts[1].x = x + xwidth;
2079                 pts[1].y = y - ywidth;
2080                 DPtoLP(hdc, pts, 2);
2081                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2082                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2083                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2084                 DeleteObject(SelectObject(hdc, hpen));
2085             }
2086         }
2087     }
2088
2089     return ret;
2090 }
2091
2092
2093 /***********************************************************************
2094  *           TextOutA    (GDI32.@)
2095  */
2096 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2097 {
2098     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2099 }
2100
2101
2102 /***********************************************************************
2103  *           TextOutW    (GDI32.@)
2104  */
2105 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2106 {
2107     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2108 }
2109
2110
2111 /***********************************************************************
2112  *              PolyTextOutA (GDI32.@)
2113  *
2114  * See PolyTextOutW.
2115  */
2116 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2117 {
2118     for (; cStrings>0; cStrings--, pptxt++)
2119         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2120             return FALSE;
2121     return TRUE;
2122 }
2123
2124
2125
2126 /***********************************************************************
2127  *              PolyTextOutW (GDI32.@)
2128  *
2129  * Draw several Strings
2130  *
2131  * RETURNS
2132  *  TRUE:  Success.
2133  *  FALSE: Failure.
2134  */
2135 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2136 {
2137     for (; cStrings>0; cStrings--, pptxt++)
2138         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2139             return FALSE;
2140     return TRUE;
2141 }
2142
2143
2144 /* FIXME: all following APIs ******************************************/
2145
2146
2147 /***********************************************************************
2148  *           SetMapperFlags    (GDI32.@)
2149  */
2150 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2151 {
2152     DC *dc = get_dc_ptr( hDC );
2153     DWORD ret = 0;
2154     if(!dc) return 0;
2155     if(dc->funcs->pSetMapperFlags)
2156     {
2157         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2158         /* FIXME: ret is just a success flag, we should return a proper value */
2159     }
2160     else
2161         FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2162     release_dc_ptr( dc );
2163     return ret;
2164 }
2165
2166 /***********************************************************************
2167  *          GetAspectRatioFilterEx  (GDI32.@)
2168  */
2169 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2170 {
2171   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2172   return FALSE;
2173 }
2174
2175
2176 /***********************************************************************
2177  *           GetCharABCWidthsA   (GDI32.@)
2178  *
2179  * See GetCharABCWidthsW.
2180  */
2181 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2182                                   LPABC abc )
2183 {
2184     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2185     LPSTR str;
2186     LPWSTR wstr;
2187     BOOL ret = TRUE;
2188
2189     if(count <= 0) return FALSE;
2190
2191     str = HeapAlloc(GetProcessHeap(), 0, count);
2192     for(i = 0; i < count; i++)
2193         str[i] = (BYTE)(firstChar + i);
2194
2195     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2196
2197     for(i = 0; i < wlen; i++)
2198     {
2199         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2200         {
2201             ret = FALSE;
2202             break;
2203         }
2204         abc++;
2205     }
2206
2207     HeapFree(GetProcessHeap(), 0, str);
2208     HeapFree(GetProcessHeap(), 0, wstr);
2209
2210     return ret;
2211 }
2212
2213
2214 /******************************************************************************
2215  * GetCharABCWidthsW [GDI32.@]
2216  *
2217  * Retrieves widths of characters in range.
2218  *
2219  * PARAMS
2220  *    hdc       [I] Handle of device context
2221  *    firstChar [I] First character in range to query
2222  *    lastChar  [I] Last character in range to query
2223  *    abc       [O] Address of character-width structure
2224  *
2225  * NOTES
2226  *    Only works with TrueType fonts
2227  *
2228  * RETURNS
2229  *    Success: TRUE
2230  *    Failure: FALSE
2231  */
2232 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2233                                    LPABC abc )
2234 {
2235     DC *dc = get_dc_ptr(hdc);
2236     unsigned int i;
2237     BOOL ret = FALSE;
2238
2239     if (!dc) return FALSE;
2240
2241     if (!abc)
2242     {
2243         release_dc_ptr( dc );
2244         return FALSE;
2245     }
2246
2247     if(dc->gdiFont)
2248         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2249     else
2250         FIXME(": stub\n");
2251
2252     if (ret)
2253     {
2254         /* convert device units to logical */
2255         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2256             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2257             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2258             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2259         }
2260         ret = TRUE;
2261     }
2262
2263     release_dc_ptr( dc );
2264     return ret;
2265 }
2266
2267
2268 /******************************************************************************
2269  * GetCharABCWidthsI [GDI32.@]
2270  *
2271  * Retrieves widths of characters in range.
2272  *
2273  * PARAMS
2274  *    hdc       [I] Handle of device context
2275  *    firstChar [I] First glyphs in range to query
2276  *    count     [I] Last glyphs in range to query
2277  *    pgi       [i] Array of glyphs to query
2278  *    abc       [O] Address of character-width structure
2279  *
2280  * NOTES
2281  *    Only works with TrueType fonts
2282  *
2283  * RETURNS
2284  *    Success: TRUE
2285  *    Failure: FALSE
2286  */
2287 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2288                                LPWORD pgi, LPABC abc)
2289 {
2290     DC *dc = get_dc_ptr(hdc);
2291     unsigned int i;
2292     BOOL ret = FALSE;
2293
2294     if (!dc) return FALSE;
2295
2296     if (!abc)
2297     {
2298         release_dc_ptr( dc );
2299         return FALSE;
2300     }
2301
2302     if(dc->gdiFont)
2303         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2304     else
2305         FIXME(": stub\n");
2306
2307     if (ret)
2308     {
2309         /* convert device units to logical */
2310         for( i = 0; i < count; i++, abc++ ) {
2311             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2312             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2313             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2314         }
2315         ret = TRUE;
2316     }
2317
2318     release_dc_ptr( dc );
2319     return ret;
2320 }
2321
2322
2323 /***********************************************************************
2324  *           GetGlyphOutlineA    (GDI32.@)
2325  */
2326 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2327                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2328                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2329 {
2330     LPWSTR p = NULL;
2331     DWORD ret;
2332     UINT c;
2333
2334     if (!lpmat2) return GDI_ERROR;
2335
2336     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2337         int len;
2338         char mbchs[2];
2339         if(uChar > 0xff) { /* but, 2 bytes character only */
2340             len = 2;
2341             mbchs[0] = (uChar & 0xff00) >> 8;
2342             mbchs[1] = (uChar & 0xff);
2343         } else {
2344             len = 1;
2345             mbchs[0] = (uChar & 0xff);
2346         }
2347         p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2348         c = p[0];
2349     } else
2350         c = uChar;
2351     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2352                            lpmat2);
2353     HeapFree(GetProcessHeap(), 0, p);
2354     return ret;
2355 }
2356
2357 /***********************************************************************
2358  *           GetGlyphOutlineW    (GDI32.@)
2359  */
2360 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2361                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2362                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2363 {
2364     DC *dc;
2365     DWORD ret;
2366
2367     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2368           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2369
2370     if (!lpmat2) return GDI_ERROR;
2371
2372     dc = get_dc_ptr(hdc);
2373     if(!dc) return GDI_ERROR;
2374
2375     if(dc->gdiFont)
2376       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2377                                    cbBuffer, lpBuffer, lpmat2);
2378     else
2379       ret = GDI_ERROR;
2380
2381     release_dc_ptr( dc );
2382     return ret;
2383 }
2384
2385
2386 /***********************************************************************
2387  *           CreateScalableFontResourceA   (GDI32.@)
2388  */
2389 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2390                                              LPCSTR lpszResourceFile,
2391                                              LPCSTR lpszFontFile,
2392                                              LPCSTR lpszCurrentPath )
2393 {
2394     LPWSTR lpszResourceFileW = NULL;
2395     LPWSTR lpszFontFileW = NULL;
2396     LPWSTR lpszCurrentPathW = NULL;
2397     int len;
2398     BOOL ret;
2399
2400     if (lpszResourceFile)
2401     {
2402         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2403         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2404         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2405     }
2406
2407     if (lpszFontFile)
2408     {
2409         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2410         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2411         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2412     }
2413
2414     if (lpszCurrentPath)
2415     {
2416         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2417         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2418         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2419     }
2420
2421     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2422             lpszFontFileW, lpszCurrentPathW);
2423
2424     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2425     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2426     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2427
2428     return ret;
2429 }
2430
2431 /***********************************************************************
2432  *           CreateScalableFontResourceW   (GDI32.@)
2433  */
2434 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2435                                              LPCWSTR lpszResourceFile,
2436                                              LPCWSTR lpszFontFile,
2437                                              LPCWSTR lpszCurrentPath )
2438 {
2439     HANDLE f;
2440     FIXME("(%d,%s,%s,%s): stub\n",
2441           fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2442           debugstr_w(lpszCurrentPath) );
2443
2444     /* fHidden=1 - only visible for the calling app, read-only, not
2445      * enumerated with EnumFonts/EnumFontFamilies
2446      * lpszCurrentPath can be NULL
2447      */
2448
2449     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2450     if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2451         CloseHandle(f);
2452         SetLastError(ERROR_FILE_EXISTS);
2453         return FALSE;
2454     }
2455     return FALSE; /* create failed */
2456 }
2457
2458 /*************************************************************************
2459  *             GetKerningPairsA   (GDI32.@)
2460  */
2461 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2462                                LPKERNINGPAIR kern_pairA )
2463 {
2464     UINT cp;
2465     CPINFO cpi;
2466     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2467     KERNINGPAIR *kern_pairW;
2468
2469     if (!cPairs && kern_pairA)
2470     {
2471         SetLastError(ERROR_INVALID_PARAMETER);
2472         return 0;
2473     }
2474
2475     cp = GdiGetCodePage(hDC);
2476
2477     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2478      * to fail on an invalid character for CP_SYMBOL.
2479      */
2480     cpi.DefaultChar[0] = 0;
2481     if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2482     {
2483         FIXME("Can't find codepage %u info\n", cp);
2484         return 0;
2485     }
2486
2487     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2488     if (!total_kern_pairs) return 0;
2489
2490     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2491     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2492
2493     for (i = 0; i < total_kern_pairs; i++)
2494     {
2495         char first, second;
2496
2497         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2498             continue;
2499
2500         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2501             continue;
2502
2503         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2504             continue;
2505
2506         if (kern_pairA)
2507         {
2508             if (kern_pairs_copied >= cPairs) break;
2509
2510             kern_pairA->wFirst = (BYTE)first;
2511             kern_pairA->wSecond = (BYTE)second;
2512             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2513             kern_pairA++;
2514         }
2515         kern_pairs_copied++;
2516     }
2517
2518     HeapFree(GetProcessHeap(), 0, kern_pairW);
2519
2520     return kern_pairs_copied;
2521 }
2522
2523 /*************************************************************************
2524  *             GetKerningPairsW   (GDI32.@)
2525  */
2526 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2527                                  LPKERNINGPAIR lpKerningPairs )
2528 {
2529     DC *dc;
2530     DWORD ret = 0;
2531
2532     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2533
2534     if (!cPairs && lpKerningPairs)
2535     {
2536         SetLastError(ERROR_INVALID_PARAMETER);
2537         return 0;
2538     }
2539
2540     dc = get_dc_ptr(hDC);
2541     if (!dc) return 0;
2542
2543     if (dc->gdiFont)
2544         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2545
2546     release_dc_ptr( dc );
2547     return ret;
2548 }
2549
2550 /*************************************************************************
2551  * TranslateCharsetInfo [GDI32.@]
2552  *
2553  * Fills a CHARSETINFO structure for a character set, code page, or
2554  * font. This allows making the correspondence between different labels
2555  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2556  * of the same encoding.
2557  *
2558  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2559  * only one codepage should be set in *lpSrc.
2560  *
2561  * RETURNS
2562  *   TRUE on success, FALSE on failure.
2563  *
2564  */
2565 BOOL WINAPI TranslateCharsetInfo(
2566   LPDWORD lpSrc, /* [in]
2567        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2568        if flags == TCI_SRCCHARSET: a character set value
2569        if flags == TCI_SRCCODEPAGE: a code page value
2570                  */
2571   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2572   DWORD flags /* [in] determines interpretation of lpSrc */)
2573 {
2574     int index = 0;
2575     switch (flags) {
2576     case TCI_SRCFONTSIG:
2577       while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2578       break;
2579     case TCI_SRCCODEPAGE:
2580       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2581       break;
2582     case TCI_SRCCHARSET:
2583       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2584       break;
2585     default:
2586       return FALSE;
2587     }
2588     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2589     *lpCs = FONT_tci[index];
2590     return TRUE;
2591 }
2592
2593 /*************************************************************************
2594  *             GetFontLanguageInfo   (GDI32.@)
2595  */
2596 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2597 {
2598         FONTSIGNATURE fontsig;
2599         static const DWORD GCP_DBCS_MASK=0x003F0000,
2600                 GCP_DIACRITIC_MASK=0x00000000,
2601                 FLI_GLYPHS_MASK=0x00000000,
2602                 GCP_GLYPHSHAPE_MASK=0x00000040,
2603                 GCP_KASHIDA_MASK=0x00000000,
2604                 GCP_LIGATE_MASK=0x00000000,
2605                 GCP_USEKERNING_MASK=0x00000000,
2606                 GCP_REORDER_MASK=0x00000060;
2607
2608         DWORD result=0;
2609
2610         GetTextCharsetInfo( hdc, &fontsig, 0 );
2611         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2612
2613         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2614                 result|=GCP_DBCS;
2615
2616         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2617                 result|=GCP_DIACRITIC;
2618
2619         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2620                 result|=FLI_GLYPHS;
2621
2622         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2623                 result|=GCP_GLYPHSHAPE;
2624
2625         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2626                 result|=GCP_KASHIDA;
2627
2628         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2629                 result|=GCP_LIGATE;
2630
2631         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2632                 result|=GCP_USEKERNING;
2633
2634         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2635         if( GetTextAlign( hdc) & TA_RTLREADING )
2636             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2637                     result|=GCP_REORDER;
2638
2639         return result;
2640 }
2641
2642
2643 /*************************************************************************
2644  * GetFontData [GDI32.@]
2645  *
2646  * Retrieve data for TrueType font.
2647  *
2648  * RETURNS
2649  *
2650  * success: Number of bytes returned
2651  * failure: GDI_ERROR
2652  *
2653  * NOTES
2654  *
2655  * Calls SetLastError()
2656  *
2657  */
2658 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2659     LPVOID buffer, DWORD length)
2660 {
2661     DC *dc = get_dc_ptr(hdc);
2662     DWORD ret = GDI_ERROR;
2663
2664     if(!dc) return GDI_ERROR;
2665
2666     if(dc->gdiFont)
2667       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2668
2669     release_dc_ptr( dc );
2670     return ret;
2671 }
2672
2673 /*************************************************************************
2674  * GetGlyphIndicesA [GDI32.@]
2675  */
2676 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2677                               LPWORD pgi, DWORD flags)
2678 {
2679     DWORD ret;
2680     WCHAR *lpstrW;
2681     INT countW;
2682
2683     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2684           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2685
2686     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2687     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2688     HeapFree(GetProcessHeap(), 0, lpstrW);
2689
2690     return ret;
2691 }
2692
2693 /*************************************************************************
2694  * GetGlyphIndicesW [GDI32.@]
2695  */
2696 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2697                               LPWORD pgi, DWORD flags)
2698 {
2699     DC *dc = get_dc_ptr(hdc);
2700     DWORD ret = GDI_ERROR;
2701
2702     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2703           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2704
2705     if(!dc) return GDI_ERROR;
2706
2707     if(dc->gdiFont)
2708         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2709
2710     release_dc_ptr( dc );
2711     return ret;
2712 }
2713
2714 /*************************************************************************
2715  * GetCharacterPlacementA [GDI32.@]
2716  *
2717  * See GetCharacterPlacementW.
2718  *
2719  * NOTES:
2720  *  the web browser control of ie4 calls this with dwFlags=0
2721  */
2722 DWORD WINAPI
2723 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2724                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2725                          DWORD dwFlags)
2726 {
2727     WCHAR *lpStringW;
2728     INT uCountW;
2729     GCP_RESULTSW resultsW;
2730     DWORD ret;
2731     UINT font_cp;
2732
2733     TRACE("%s, %d, %d, 0x%08x\n",
2734           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2735
2736     /* both structs are equal in size */
2737     memcpy(&resultsW, lpResults, sizeof(resultsW));
2738
2739     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2740     if(lpResults->lpOutString)
2741         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2742
2743     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2744
2745     lpResults->nGlyphs = resultsW.nGlyphs;
2746     lpResults->nMaxFit = resultsW.nMaxFit;
2747
2748     if(lpResults->lpOutString) {
2749         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2750                             lpResults->lpOutString, uCount, NULL, NULL );
2751     }
2752
2753     HeapFree(GetProcessHeap(), 0, lpStringW);
2754     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2755
2756     return ret;
2757 }
2758
2759 /*************************************************************************
2760  * GetCharacterPlacementW [GDI32.@]
2761  *
2762  *   Retrieve information about a string. This includes the width, reordering,
2763  *   Glyphing and so on.
2764  *
2765  * RETURNS
2766  *
2767  *   The width and height of the string if successful, 0 if failed.
2768  *
2769  * BUGS
2770  *
2771  *   All flags except GCP_REORDER are not yet implemented.
2772  *   Reordering is not 100% compliant to the Windows BiDi method.
2773  *   Caret positioning is not yet implemented for BiDi.
2774  *   Classes are not yet implemented.
2775  *
2776  */
2777 DWORD WINAPI
2778 GetCharacterPlacementW(
2779                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2780                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2781                 INT uCount,             /* [in] Number of WORDS in string. */
2782                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2783                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2784                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2785                 )
2786 {
2787     DWORD ret=0;
2788     SIZE size;
2789     UINT i, nSet;
2790
2791     TRACE("%s, %d, %d, 0x%08x\n",
2792           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2793
2794     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2795           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2796             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2797             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2798             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2799
2800     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
2801     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2802     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2803         FIXME("Caret positions for complex scripts not implemented\n");
2804
2805         nSet = (UINT)uCount;
2806         if(nSet > lpResults->nGlyphs)
2807                 nSet = lpResults->nGlyphs;
2808
2809         /* return number of initialized fields */
2810         lpResults->nGlyphs = nSet;
2811
2812         if((dwFlags&GCP_REORDER)==0 )
2813         {
2814                 /* Treat the case where no special handling was requested in a fastpath way */
2815                 /* copy will do if the GCP_REORDER flag is not set */
2816                 if(lpResults->lpOutString)
2817                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2818
2819                 if(lpResults->lpOrder)
2820                 {
2821                         for(i = 0; i < nSet; i++)
2822                                 lpResults->lpOrder[i] = i;
2823                 }
2824         } else
2825         {
2826             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2827                           nSet, lpResults->lpOrder );
2828         }
2829
2830         /* FIXME: Will use the placement chars */
2831         if (lpResults->lpDx)
2832         {
2833                 int c;
2834                 for (i = 0; i < nSet; i++)
2835                 {
2836                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2837                                 lpResults->lpDx[i]= c;
2838                 }
2839         }
2840
2841     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2842     {
2843         int pos = 0;
2844        
2845         lpResults->lpCaretPos[0] = 0;
2846         for (i = 1; i < nSet; i++)
2847             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2848                 lpResults->lpCaretPos[i] = (pos += size.cx);
2849     }
2850    
2851     if(lpResults->lpGlyphs)
2852         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2853
2854     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2855       ret = MAKELONG(size.cx, size.cy);
2856
2857     return ret;
2858 }
2859
2860 /*************************************************************************
2861  *      GetCharABCWidthsFloatA [GDI32.@]
2862  *
2863  * See GetCharABCWidthsFloatW.
2864  */
2865 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2866 {
2867     INT i, wlen, count = (INT)(last - first + 1);
2868     LPSTR str;
2869     LPWSTR wstr;
2870     BOOL ret = TRUE;
2871
2872     if (count <= 0) return FALSE;
2873
2874     str = HeapAlloc(GetProcessHeap(), 0, count);
2875
2876     for(i = 0; i < count; i++)
2877         str[i] = (BYTE)(first + i);
2878
2879     wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2880
2881     for (i = 0; i < wlen; i++)
2882     {
2883         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2884         {
2885             ret = FALSE;
2886             break;
2887         }
2888         abcf++;
2889     }
2890
2891     HeapFree( GetProcessHeap(), 0, str );
2892     HeapFree( GetProcessHeap(), 0, wstr );
2893
2894     return ret;
2895 }
2896
2897 /*************************************************************************
2898  *      GetCharABCWidthsFloatW [GDI32.@]
2899  *
2900  * Retrieves widths of a range of characters.
2901  *
2902  * PARAMS
2903  *    hdc   [I] Handle to device context.
2904  *    first [I] First character in range to query.
2905  *    last  [I] Last character in range to query.
2906  *    abcf  [O] Array of LPABCFLOAT structures.
2907  *
2908  * RETURNS
2909  *    Success: TRUE
2910  *    Failure: FALSE
2911  *
2912  * BUGS
2913  *    Only works with TrueType fonts. It also doesn't return real
2914  *    floats but converted integers because it's implemented on
2915  *    top of GetCharABCWidthsW.
2916  */
2917 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2918 {
2919     ABC *abc, *abc_base;
2920     unsigned int i, size = sizeof(ABC) * (last - first + 1);
2921     BOOL ret;
2922
2923     TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2924
2925     abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2926     if (!abc) return FALSE;
2927
2928     ret = GetCharABCWidthsW( hdc, first, last, abc );
2929     if (ret)
2930     {
2931         for (i = first; i <= last; i++, abc++, abcf++)
2932         {
2933             abcf->abcfA = abc->abcA;
2934             abcf->abcfB = abc->abcB;
2935             abcf->abcfC = abc->abcC;
2936         }
2937     }
2938     HeapFree( GetProcessHeap(), 0, abc_base );
2939     return ret;
2940 }
2941
2942 /*************************************************************************
2943  *      GetCharWidthFloatA [GDI32.@]
2944  */
2945 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2946                                     UINT iLastChar, PFLOAT pxBuffer)
2947 {
2948     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2949     return 0;
2950 }
2951
2952 /*************************************************************************
2953  *      GetCharWidthFloatW [GDI32.@]
2954  */
2955 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2956                                     UINT iLastChar, PFLOAT pxBuffer)
2957 {
2958     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2959     return 0;
2960 }
2961
2962
2963 /***********************************************************************
2964  *                                                                     *
2965  *           Font Resource API                                         *
2966  *                                                                     *
2967  ***********************************************************************/
2968
2969 /***********************************************************************
2970  *           AddFontResourceA    (GDI32.@)
2971  */
2972 INT WINAPI AddFontResourceA( LPCSTR str )
2973 {
2974     return AddFontResourceExA( str, 0, NULL);
2975 }
2976
2977 /***********************************************************************
2978  *           AddFontResourceW    (GDI32.@)
2979  */
2980 INT WINAPI AddFontResourceW( LPCWSTR str )
2981 {
2982     return AddFontResourceExW(str, 0, NULL);
2983 }
2984
2985
2986 /***********************************************************************
2987  *           AddFontResourceExA    (GDI32.@)
2988  */
2989 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2990 {
2991     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2992     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2993     INT ret;
2994
2995     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2996     ret = AddFontResourceExW(strW, fl, pdv);
2997     HeapFree(GetProcessHeap(), 0, strW);
2998     return ret;
2999 }
3000
3001 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3002 {
3003     HRSRC rsrc = FindResourceW(hModule, name, type);
3004     HGLOBAL hMem = LoadResource(hModule, rsrc);
3005     LPVOID *pMem = LockResource(hMem);
3006     int *num_total = (int *)lParam;
3007     DWORD num_in_res;
3008
3009     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3010     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3011     {
3012         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3013         return FALSE;
3014     }
3015
3016     *num_total += num_in_res;
3017     return TRUE;
3018 }
3019
3020 /***********************************************************************
3021  *           AddFontResourceExW    (GDI32.@)
3022  */
3023 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3024 {
3025     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3026     if (ret == 0)
3027     {
3028         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3029         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3030         if (hModule != NULL)
3031         {
3032             int num_resources = 0;
3033             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3034
3035             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3036                 wine_dbgstr_w(str));
3037             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3038                 ret = num_resources;
3039             FreeLibrary(hModule);
3040         }
3041     }
3042     return ret;
3043 }
3044
3045 /***********************************************************************
3046  *           RemoveFontResourceA    (GDI32.@)
3047  */
3048 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3049 {
3050     return RemoveFontResourceExA(str, 0, 0);
3051 }
3052
3053 /***********************************************************************
3054  *           RemoveFontResourceW    (GDI32.@)
3055  */
3056 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3057 {
3058     return RemoveFontResourceExW(str, 0, 0);
3059 }
3060
3061 /***********************************************************************
3062  *           AddFontMemResourceEx    (GDI32.@)
3063  */
3064 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3065 {
3066     return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3067 }
3068
3069 /***********************************************************************
3070  *           RemoveFontMemResourceEx    (GDI32.@)
3071  */
3072 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3073 {
3074     FIXME("(%p) stub\n", fh);
3075     return TRUE;
3076 }
3077
3078 /***********************************************************************
3079  *           RemoveFontResourceExA    (GDI32.@)
3080  */
3081 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3082 {
3083     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3084     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3085     INT ret;
3086
3087     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3088     ret = RemoveFontResourceExW(strW, fl, pdv);
3089     HeapFree(GetProcessHeap(), 0, strW);
3090     return ret;
3091 }
3092
3093 /***********************************************************************
3094  *           RemoveFontResourceExW    (GDI32.@)
3095  */
3096 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3097 {
3098     return WineEngRemoveFontResourceEx(str, fl, pdv);
3099 }
3100
3101 /***********************************************************************
3102  *           GetTextCharset    (GDI32.@)
3103  */
3104 UINT WINAPI GetTextCharset(HDC hdc)
3105 {
3106     /* MSDN docs say this is equivalent */
3107     return GetTextCharsetInfo(hdc, NULL, 0);
3108 }
3109
3110 /***********************************************************************
3111  *           GetTextCharsetInfo    (GDI32.@)
3112  */
3113 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3114 {
3115     UINT ret = DEFAULT_CHARSET;
3116     DC *dc = get_dc_ptr(hdc);
3117
3118     if (dc)
3119     {
3120         if (dc->gdiFont)
3121             ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3122
3123         release_dc_ptr( dc );
3124     }
3125
3126     if (ret == DEFAULT_CHARSET && fs)
3127         memset(fs, 0, sizeof(FONTSIGNATURE));
3128     return ret;
3129 }
3130
3131 /***********************************************************************
3132  *           GdiGetCharDimensions    (GDI32.@)
3133  *
3134  * Gets the average width of the characters in the English alphabet.
3135  *
3136  * PARAMS
3137  *  hdc    [I] Handle to the device context to measure on.
3138  *  lptm   [O] Pointer to memory to store the text metrics into.
3139  *  height [O] On exit, the maximum height of characters in the English alphabet.
3140  *
3141  * RETURNS
3142  *  The average width of characters in the English alphabet.
3143  *
3144  * NOTES
3145  *  This function is used by the dialog manager to get the size of a dialog
3146  *  unit. It should also be used by other pieces of code that need to know
3147  *  the size of a dialog unit in logical units without having access to the
3148  *  window handle of the dialog.
3149  *  Windows caches the font metrics from this function, but we don't and
3150  *  there doesn't appear to be an immediate advantage to do so.
3151  *
3152  * SEE ALSO
3153  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3154  */
3155 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3156 {
3157     SIZE sz;
3158     static const WCHAR alphabet[] = {
3159         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3160         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3161         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3162
3163     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3164
3165     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3166
3167     if (height) *height = sz.cy;
3168     return (sz.cx / 26 + 1) / 2;
3169 }
3170
3171 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3172 {
3173     FIXME("(%d): stub\n", fEnableEUDC);
3174     return FALSE;
3175 }
3176
3177 /***********************************************************************
3178  *           GetCharWidthI    (GDI32.@)
3179  *
3180  * Retrieve widths of characters.
3181  *
3182  * PARAMS
3183  *  hdc    [I] Handle to a device context.
3184  *  first  [I] First glyph in range to query.
3185  *  count  [I] Number of glyph indices to query.
3186  *  glyphs [I] Array of glyphs to query.
3187  *  buffer [O] Buffer to receive character widths.
3188  *
3189  * NOTES
3190  *  Only works with TrueType fonts.
3191  *
3192  * RETURNS
3193  *  Success: TRUE
3194  *  Failure: FALSE
3195  */
3196 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3197 {
3198     ABC *abc;
3199     unsigned int i;
3200
3201     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3202
3203     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3204         return FALSE;
3205
3206     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3207     {
3208         HeapFree(GetProcessHeap(), 0, abc);
3209         return FALSE;
3210     }
3211
3212     for (i = 0; i < count; i++)
3213         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3214
3215     HeapFree(GetProcessHeap(), 0, abc);
3216     return TRUE;
3217 }
3218
3219 /***********************************************************************
3220  *           GetFontUnicodeRanges    (GDI32.@)
3221  *
3222  *  Retrieve a list of supported Unicode characters in a font.
3223  *
3224  *  PARAMS
3225  *   hdc  [I] Handle to a device context.
3226  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3227  *
3228  *  RETURNS
3229  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3230  *   Failure: 0
3231  *
3232  */
3233 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3234 {
3235     DWORD ret = 0;
3236     DC *dc = get_dc_ptr(hdc);
3237
3238     TRACE("(%p, %p)\n", hdc, lpgs);
3239
3240     if (!dc) return 0;
3241
3242     if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3243     release_dc_ptr(dc);
3244     return ret;
3245 }
3246
3247
3248 /*************************************************************
3249  *           FontIsLinked    (GDI32.@)
3250  */
3251 BOOL WINAPI FontIsLinked(HDC hdc)
3252 {
3253     DC *dc = get_dc_ptr(hdc);
3254     BOOL ret = FALSE;
3255
3256     if (!dc) return FALSE;
3257     if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3258     release_dc_ptr(dc);
3259     TRACE("returning %d\n", ret);
3260     return ret;
3261 }
3262
3263 /*************************************************************
3264  *           GdiRealizationInfo    (GDI32.@)
3265  *
3266  * Returns a structure that contains some font information.
3267  */
3268 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3269 {
3270     DC *dc = get_dc_ptr(hdc);
3271     BOOL ret = FALSE;
3272
3273     if (!dc) return FALSE;
3274     if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3275     release_dc_ptr(dc);
3276
3277     return ret;
3278 }