comctl32: Only support an alpha channel for 32-bpp DIB-based imagelists.
[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         /* allocate enough for a ETO_PDY */
1590         lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1591         while(i < count) {
1592             if(IsDBCSLeadByteEx(codepage, str[i]))
1593             {
1594                 if(flags & ETO_PDY)
1595                 {
1596                     lpDxW[j++] = lpDx[i * 2]     + lpDx[(i + 1) * 2];
1597                     lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1598                 }
1599                 else
1600                     lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1601                 i = i + 2;
1602             }
1603             else
1604             {
1605                 if(flags & ETO_PDY)
1606                 {
1607                     lpDxW[j++] = lpDx[i * 2];
1608                     lpDxW[j++] = lpDx[i * 2 + 1];
1609                 }
1610                 else
1611                     lpDxW[j++] = lpDx[i];
1612                 i = i + 1;
1613             }
1614         }
1615     }
1616
1617     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1618
1619     HeapFree( GetProcessHeap(), 0, p );
1620     HeapFree( GetProcessHeap(), 0, lpDxW );
1621     return ret;
1622 }
1623
1624
1625 /***********************************************************************
1626  *           ExtTextOutW    (GDI32.@)
1627  *
1628  * Draws text using the currently selected font, background color, and text color.
1629  * 
1630  * 
1631  * PARAMS
1632  *    x,y    [I] coordinates of string
1633  *    flags  [I]
1634  *        ETO_GRAYED - undocumented on MSDN
1635  *        ETO_OPAQUE - use background color for fill the rectangle
1636  *        ETO_CLIPPED - clipping text to the rectangle
1637  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1638  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1639  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1640  *                         Affects BiDi ordering
1641  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1642  *        ETO_PDY - unimplemented
1643  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1644  *                            do not translate numbers into locale representations
1645  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1646  *    lprect [I] dimensions for clipping or/and opaquing
1647  *    str    [I] text string
1648  *    count  [I] number of symbols in string
1649  *    lpDx   [I] optional parameter with distance between drawing characters
1650  *
1651  * RETURNS
1652  *    Success: TRUE
1653  *    Failure: FALSE
1654  */
1655 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1656                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1657 {
1658     BOOL ret = FALSE;
1659     LPWSTR reordered_str = (LPWSTR)str;
1660     WORD *glyphs = NULL;
1661     UINT align = GetTextAlign( hdc );
1662     POINT pt;
1663     TEXTMETRICW tm;
1664     LOGFONTW lf;
1665     double cosEsc, sinEsc;
1666     INT char_extra;
1667     SIZE sz;
1668     RECT rc;
1669     BOOL done_extents = FALSE;
1670     POINT *deltas = NULL, width = {0, 0};
1671     DWORD type;
1672     DC * dc = get_dc_ptr( hdc );
1673     INT breakRem;
1674     static int quietfixme = 0;
1675
1676     if (!dc) return FALSE;
1677
1678     breakRem = dc->breakRem;
1679
1680     if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1681     {
1682         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1683         quietfixme = 1;
1684     }
1685     if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1686     {
1687         release_dc_ptr( dc );
1688         return ret;
1689     }
1690
1691     update_dc( dc );
1692     type = GetObjectType(hdc);
1693     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1694     {
1695         ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1696         release_dc_ptr( dc );
1697         return ret;
1698     }
1699
1700     if (!lprect)
1701         flags &= ~ETO_CLIPPED;
1702         
1703     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1704     {
1705         INT cGlyphs;
1706         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1707
1708         BIDI_Reorder( hdc, str, count, GCP_REORDER,
1709                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1710                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1711                       reordered_str, count, NULL, &glyphs, &cGlyphs);
1712     
1713         flags |= ETO_IGNORELANGUAGE;
1714         if (glyphs)
1715         {
1716             flags |= ETO_GLYPH_INDEX;
1717             if (cGlyphs != count)
1718                 count = cGlyphs;
1719         }
1720     }
1721     else if(flags & ETO_GLYPH_INDEX)
1722         glyphs = reordered_str;
1723
1724     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1725           lprect, debugstr_wn(str, count), count, lpDx);
1726
1727     if(lprect)
1728         TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1729               lprect->bottom);
1730     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1731
1732     if(align & TA_UPDATECP)
1733     {
1734         GetCurrentPositionEx( hdc, &pt );
1735         x = pt.x;
1736         y = pt.y;
1737     }
1738
1739     GetTextMetricsW(hdc, &tm);
1740     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1741
1742     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1743         lf.lfEscapement = 0;
1744
1745     if(lf.lfEscapement != 0)
1746     {
1747         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1748         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1749     }
1750     else
1751     {
1752         cosEsc = 1;
1753         sinEsc = 0;
1754     }
1755
1756     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1757     {
1758         if(!lprect)
1759         {
1760             if(flags & ETO_GLYPH_INDEX)
1761                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1762             else
1763                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1764
1765             done_extents = TRUE;
1766             rc.left = x;
1767             rc.top = y;
1768             rc.right = x + sz.cx;
1769             rc.bottom = y + sz.cy;
1770         }
1771         else
1772         {
1773             rc = *lprect;
1774         }
1775
1776         LPtoDP(hdc, (POINT*)&rc, 2);
1777
1778         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1779         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1780     }
1781
1782     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1783         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1784
1785     if(count == 0)
1786     {
1787         ret = TRUE;
1788         goto done;
1789     }
1790
1791     pt.x = x;
1792     pt.y = y;
1793     LPtoDP(hdc, &pt, 1);
1794     x = pt.x;
1795     y = pt.y;
1796
1797     char_extra = GetTextCharacterExtra(hdc);
1798     if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1799     {
1800         UINT i;
1801         SIZE tmpsz;
1802         POINT total = {0, 0}, desired[2];
1803
1804         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1805         for(i = 0; i < count; i++)
1806         {
1807             if(lpDx)
1808             {
1809                 if(flags & ETO_PDY)
1810                 {
1811                     deltas[i].x = lpDx[i * 2] + char_extra;
1812                     deltas[i].y = -lpDx[i * 2 + 1];
1813                 }
1814                 else
1815                 {
1816                     deltas[i].x = lpDx[i] + char_extra;
1817                     deltas[i].y = 0;
1818                 }
1819
1820             }
1821             else
1822             {
1823                 if(flags & ETO_GLYPH_INDEX)
1824                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1825                 else
1826                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1827
1828                 deltas[i].x = tmpsz.cx;
1829                 deltas[i].y = 0;
1830             }
1831             
1832             if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1833             {
1834                 deltas[i].x = deltas[i].x + dc->breakExtra;
1835                 if (breakRem > 0)
1836                 {
1837                     breakRem--;
1838                     deltas[i].x++;
1839                 }
1840             }
1841             total.x += deltas[i].x;
1842             total.y += deltas[i].y;
1843
1844             desired[0].x = desired[0].y = 0;
1845
1846             desired[1].x =  cosEsc * total.x + sinEsc * total.y;
1847             desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1848
1849             LPtoDP(hdc, desired, 2);
1850             desired[1].x -= desired[0].x;
1851             desired[1].y -= desired[0].y;
1852
1853             deltas[i].x = desired[1].x - width.x;
1854             deltas[i].y = desired[1].y - width.y;
1855
1856             width = desired[1];
1857         }
1858         flags |= ETO_PDY;
1859     }
1860     else
1861     {
1862         if(!done_extents)
1863         {
1864             if(flags & ETO_GLYPH_INDEX)
1865                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1866             else
1867                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1868             done_extents = TRUE;
1869         }
1870         width.x = INTERNAL_XWSTODS(dc, sz.cx);
1871         width.y = 0;
1872     }
1873
1874     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1875     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1876     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1877     {
1878     case TA_LEFT:
1879         if (align & TA_UPDATECP)
1880         {
1881             pt.x = x + width.x;
1882             pt.y = y - width.y;
1883             DPtoLP(hdc, &pt, 1);
1884             MoveToEx(hdc, pt.x, pt.y, NULL);
1885         }
1886         break;
1887
1888     case TA_CENTER:
1889         x -= width.x / 2;
1890         y += width.y / 2;
1891         break;
1892
1893     case TA_RIGHT:
1894         x -= width.x;
1895         y += width.y;
1896         if (align & TA_UPDATECP)
1897         {
1898             pt.x = x;
1899             pt.y = y;
1900             DPtoLP(hdc, &pt, 1);
1901             MoveToEx(hdc, pt.x, pt.y, NULL);
1902         }
1903         break;
1904     }
1905
1906     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1907     {
1908     case TA_TOP:
1909         y += tm.tmAscent * cosEsc;
1910         x += tm.tmAscent * sinEsc;
1911         break;
1912
1913     case TA_BOTTOM:
1914         y -= tm.tmDescent * cosEsc;
1915         x -= tm.tmDescent * sinEsc;
1916         break;
1917
1918     case TA_BASELINE:
1919         break;
1920     }
1921
1922     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1923     {
1924         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1925         {
1926             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
1927                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1928             {
1929                 RECT rc;
1930                 rc.left = x;
1931                 rc.right = x + width.x;
1932                 rc.top = y - tm.tmAscent;
1933                 rc.bottom = y + tm.tmDescent;
1934                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1935             }
1936         }
1937     }
1938
1939     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1940     {
1941         HFONT orig_font = dc->hFont, cur_font;
1942         UINT glyph;
1943         INT span = 0;
1944         POINT *offsets = NULL;
1945         unsigned int i;
1946
1947         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1948         for(i = 0; i < count; i++)
1949         {
1950             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1951             if(cur_font != dc->hFont)
1952             {
1953                 if(!offsets)
1954                 {
1955                     unsigned int j;
1956                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1957                     offsets[0].x = offsets[0].y = 0;
1958
1959                     if(!deltas)
1960                     {
1961                         SIZE tmpsz;
1962                         for(j = 1; j < count; j++)
1963                         {
1964                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1965                             offsets[j].x = offsets[j - 1].x + INTERNAL_XWSTODS(dc, tmpsz.cx);
1966                             offsets[j].y = 0;
1967                         }
1968                     }
1969                     else
1970                     {
1971                         for(j = 1; j < count; j++)
1972                         {
1973                             offsets[j].x = offsets[j - 1].x + deltas[j].x;
1974                             offsets[j].y = offsets[j - 1].y + deltas[j].y;
1975                         }
1976                     }
1977                 }
1978                 if(span)
1979                 {
1980                     if (PATH_IsPathOpen(dc->path))
1981                         ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
1982                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1983                                               glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
1984                     else
1985                         dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span].x, y + offsets[i - span].y,
1986                                                (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1987                                                glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
1988                     span = 0;
1989                 }
1990                 SelectObject(hdc, cur_font);
1991             }
1992             glyphs[span++] = glyph;
1993
1994             if(i == count - 1)
1995             {
1996                 if (PATH_IsPathOpen(dc->path))
1997                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
1998                                           y + (offsets ? offsets[count - span].y : 0),
1999                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2000                                           glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2001                 else
2002                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span].x : 0),
2003                                                  y + (offsets ? offsets[count - span].y : 0),
2004                                                  (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2005                                                  glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2006                 SelectObject(hdc, orig_font);
2007                 HeapFree(GetProcessHeap(), 0, offsets);
2008            }
2009         }
2010     }
2011     else
2012     {
2013         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2014         {
2015             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2016             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2017             flags |= ETO_GLYPH_INDEX;
2018         }
2019
2020         if (PATH_IsPathOpen(dc->path))
2021             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2022                                   glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2023         else
2024             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2025                                          glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2026     }
2027
2028 done:
2029     HeapFree(GetProcessHeap(), 0, deltas);
2030     if(glyphs != reordered_str)
2031         HeapFree(GetProcessHeap(), 0, glyphs);
2032     if(reordered_str != str)
2033         HeapFree(GetProcessHeap(), 0, reordered_str);
2034
2035     release_dc_ptr( dc );
2036
2037     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2038     {
2039         int underlinePos, strikeoutPos;
2040         int underlineWidth, strikeoutWidth;
2041         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2042         OUTLINETEXTMETRICW* otm = NULL;
2043
2044         if(!size)
2045         {
2046             underlinePos = 0;
2047             underlineWidth = tm.tmAscent / 20 + 1;
2048             strikeoutPos = tm.tmAscent / 2;
2049             strikeoutWidth = underlineWidth;
2050         }
2051         else
2052         {
2053             otm = HeapAlloc(GetProcessHeap(), 0, size);
2054             GetOutlineTextMetricsW(hdc, size, otm);
2055             underlinePos = otm->otmsUnderscorePosition;
2056             underlineWidth = otm->otmsUnderscoreSize;
2057             strikeoutPos = otm->otmsStrikeoutPosition;
2058             strikeoutWidth = otm->otmsStrikeoutSize;
2059             HeapFree(GetProcessHeap(), 0, otm);
2060         }
2061
2062         if (PATH_IsPathOpen(dc->path))
2063         {
2064             POINT pts[5];
2065             HPEN hpen;
2066             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2067
2068             hbrush = SelectObject(hdc, hbrush);
2069             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2070
2071             if (lf.lfUnderline)
2072             {
2073                 pts[0].x = x - underlinePos * sinEsc;
2074                 pts[0].y = y - underlinePos * cosEsc;
2075                 pts[1].x = x + width.x - underlinePos * sinEsc;
2076                 pts[1].y = y - width.y - underlinePos * cosEsc;
2077                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2078                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2079                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2080                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2081                 pts[4].x = pts[0].x;
2082                 pts[4].y = pts[0].y;
2083                 DPtoLP(hdc, pts, 5);
2084                 Polygon(hdc, pts, 5);
2085             }
2086
2087             if (lf.lfStrikeOut)
2088             {
2089                 pts[0].x = x - strikeoutPos * sinEsc;
2090                 pts[0].y = y - strikeoutPos * cosEsc;
2091                 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2092                 pts[1].y = y - width.y - strikeoutPos * cosEsc;
2093                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2094                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2095                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2096                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2097                 pts[4].x = pts[0].x;
2098                 pts[4].y = pts[0].y;
2099                 DPtoLP(hdc, pts, 5);
2100                 Polygon(hdc, pts, 5);
2101             }
2102
2103             SelectObject(hdc, hpen);
2104             hbrush = SelectObject(hdc, hbrush);
2105             DeleteObject(hbrush);
2106         }
2107         else
2108         {
2109             POINT pts[2], oldpt;
2110             HPEN hpen;
2111
2112             if (lf.lfUnderline)
2113             {
2114                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2115                 hpen = SelectObject(hdc, hpen);
2116                 pts[0].x = x;
2117                 pts[0].y = y;
2118                 pts[1].x = x + width.x;
2119                 pts[1].y = y - width.y;
2120                 DPtoLP(hdc, pts, 2);
2121                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2122                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2123                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2124                 DeleteObject(SelectObject(hdc, hpen));
2125             }
2126
2127             if (lf.lfStrikeOut)
2128             {
2129                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2130                 hpen = SelectObject(hdc, hpen);
2131                 pts[0].x = x;
2132                 pts[0].y = y;
2133                 pts[1].x = x + width.x;
2134                 pts[1].y = y - width.y;
2135                 DPtoLP(hdc, pts, 2);
2136                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2137                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2138                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2139                 DeleteObject(SelectObject(hdc, hpen));
2140             }
2141         }
2142     }
2143
2144     return ret;
2145 }
2146
2147
2148 /***********************************************************************
2149  *           TextOutA    (GDI32.@)
2150  */
2151 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2152 {
2153     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2154 }
2155
2156
2157 /***********************************************************************
2158  *           TextOutW    (GDI32.@)
2159  */
2160 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2161 {
2162     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2163 }
2164
2165
2166 /***********************************************************************
2167  *              PolyTextOutA (GDI32.@)
2168  *
2169  * See PolyTextOutW.
2170  */
2171 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2172 {
2173     for (; cStrings>0; cStrings--, pptxt++)
2174         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2175             return FALSE;
2176     return TRUE;
2177 }
2178
2179
2180
2181 /***********************************************************************
2182  *              PolyTextOutW (GDI32.@)
2183  *
2184  * Draw several Strings
2185  *
2186  * RETURNS
2187  *  TRUE:  Success.
2188  *  FALSE: Failure.
2189  */
2190 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2191 {
2192     for (; cStrings>0; cStrings--, pptxt++)
2193         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2194             return FALSE;
2195     return TRUE;
2196 }
2197
2198
2199 /* FIXME: all following APIs ******************************************/
2200
2201
2202 /***********************************************************************
2203  *           SetMapperFlags    (GDI32.@)
2204  */
2205 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2206 {
2207     DC *dc = get_dc_ptr( hDC );
2208     DWORD ret = 0;
2209     if(!dc) return 0;
2210     if(dc->funcs->pSetMapperFlags)
2211     {
2212         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2213         /* FIXME: ret is just a success flag, we should return a proper value */
2214     }
2215     else
2216         FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2217     release_dc_ptr( dc );
2218     return ret;
2219 }
2220
2221 /***********************************************************************
2222  *          GetAspectRatioFilterEx  (GDI32.@)
2223  */
2224 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2225 {
2226   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2227   return FALSE;
2228 }
2229
2230
2231 /***********************************************************************
2232  *           GetCharABCWidthsA   (GDI32.@)
2233  *
2234  * See GetCharABCWidthsW.
2235  */
2236 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2237                                   LPABC abc )
2238 {
2239     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2240     LPSTR str;
2241     LPWSTR wstr;
2242     BOOL ret = TRUE;
2243
2244     if(count <= 0) return FALSE;
2245
2246     str = HeapAlloc(GetProcessHeap(), 0, count);
2247     for(i = 0; i < count; i++)
2248         str[i] = (BYTE)(firstChar + i);
2249
2250     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2251
2252     for(i = 0; i < wlen; i++)
2253     {
2254         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2255         {
2256             ret = FALSE;
2257             break;
2258         }
2259         abc++;
2260     }
2261
2262     HeapFree(GetProcessHeap(), 0, str);
2263     HeapFree(GetProcessHeap(), 0, wstr);
2264
2265     return ret;
2266 }
2267
2268
2269 /******************************************************************************
2270  * GetCharABCWidthsW [GDI32.@]
2271  *
2272  * Retrieves widths of characters in range.
2273  *
2274  * PARAMS
2275  *    hdc       [I] Handle of device context
2276  *    firstChar [I] First character in range to query
2277  *    lastChar  [I] Last character in range 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 GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2288                                    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 = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2304     else
2305         FIXME(": stub\n");
2306
2307     if (ret)
2308     {
2309         /* convert device units to logical */
2310         for( i = firstChar; i <= lastChar; 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  * GetCharABCWidthsI [GDI32.@]
2325  *
2326  * Retrieves widths of characters in range.
2327  *
2328  * PARAMS
2329  *    hdc       [I] Handle of device context
2330  *    firstChar [I] First glyphs in range to query
2331  *    count     [I] Last glyphs in range to query
2332  *    pgi       [i] Array of glyphs to query
2333  *    abc       [O] Address of character-width structure
2334  *
2335  * NOTES
2336  *    Only works with TrueType fonts
2337  *
2338  * RETURNS
2339  *    Success: TRUE
2340  *    Failure: FALSE
2341  */
2342 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2343                                LPWORD pgi, LPABC abc)
2344 {
2345     DC *dc = get_dc_ptr(hdc);
2346     unsigned int i;
2347     BOOL ret = FALSE;
2348
2349     if (!dc) return FALSE;
2350
2351     if (!abc)
2352     {
2353         release_dc_ptr( dc );
2354         return FALSE;
2355     }
2356
2357     if(dc->gdiFont)
2358         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2359     else
2360         FIXME(": stub\n");
2361
2362     if (ret)
2363     {
2364         /* convert device units to logical */
2365         for( i = 0; i < count; i++, abc++ ) {
2366             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2367             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2368             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2369         }
2370         ret = TRUE;
2371     }
2372
2373     release_dc_ptr( dc );
2374     return ret;
2375 }
2376
2377
2378 /***********************************************************************
2379  *           GetGlyphOutlineA    (GDI32.@)
2380  */
2381 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2382                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2383                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2384 {
2385     LPWSTR p = NULL;
2386     DWORD ret;
2387     UINT c;
2388
2389     if (!lpmat2) return GDI_ERROR;
2390
2391     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2392         int len;
2393         char mbchs[2];
2394         if(uChar > 0xff) { /* but, 2 bytes character only */
2395             len = 2;
2396             mbchs[0] = (uChar & 0xff00) >> 8;
2397             mbchs[1] = (uChar & 0xff);
2398         } else {
2399             len = 1;
2400             mbchs[0] = (uChar & 0xff);
2401         }
2402         p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2403         c = p[0];
2404     } else
2405         c = uChar;
2406     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2407                            lpmat2);
2408     HeapFree(GetProcessHeap(), 0, p);
2409     return ret;
2410 }
2411
2412 /***********************************************************************
2413  *           GetGlyphOutlineW    (GDI32.@)
2414  */
2415 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2416                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2417                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2418 {
2419     DC *dc;
2420     DWORD ret;
2421
2422     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2423           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2424
2425     if (!lpmat2) return GDI_ERROR;
2426
2427     dc = get_dc_ptr(hdc);
2428     if(!dc) return GDI_ERROR;
2429
2430     if(dc->gdiFont)
2431       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2432                                    cbBuffer, lpBuffer, lpmat2);
2433     else
2434       ret = GDI_ERROR;
2435
2436     release_dc_ptr( dc );
2437     return ret;
2438 }
2439
2440
2441 /***********************************************************************
2442  *           CreateScalableFontResourceA   (GDI32.@)
2443  */
2444 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2445                                              LPCSTR lpszResourceFile,
2446                                              LPCSTR lpszFontFile,
2447                                              LPCSTR lpszCurrentPath )
2448 {
2449     LPWSTR lpszResourceFileW = NULL;
2450     LPWSTR lpszFontFileW = NULL;
2451     LPWSTR lpszCurrentPathW = NULL;
2452     int len;
2453     BOOL ret;
2454
2455     if (lpszResourceFile)
2456     {
2457         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2458         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2459         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2460     }
2461
2462     if (lpszFontFile)
2463     {
2464         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2465         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2466         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2467     }
2468
2469     if (lpszCurrentPath)
2470     {
2471         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2472         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2473         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2474     }
2475
2476     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2477             lpszFontFileW, lpszCurrentPathW);
2478
2479     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2480     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2481     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2482
2483     return ret;
2484 }
2485
2486 /***********************************************************************
2487  *           CreateScalableFontResourceW   (GDI32.@)
2488  */
2489 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2490                                              LPCWSTR lpszResourceFile,
2491                                              LPCWSTR lpszFontFile,
2492                                              LPCWSTR lpszCurrentPath )
2493 {
2494     HANDLE f;
2495     FIXME("(%d,%s,%s,%s): stub\n",
2496           fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2497           debugstr_w(lpszCurrentPath) );
2498
2499     /* fHidden=1 - only visible for the calling app, read-only, not
2500      * enumerated with EnumFonts/EnumFontFamilies
2501      * lpszCurrentPath can be NULL
2502      */
2503
2504     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2505     if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2506         CloseHandle(f);
2507         SetLastError(ERROR_FILE_EXISTS);
2508         return FALSE;
2509     }
2510     return FALSE; /* create failed */
2511 }
2512
2513 /*************************************************************************
2514  *             GetKerningPairsA   (GDI32.@)
2515  */
2516 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2517                                LPKERNINGPAIR kern_pairA )
2518 {
2519     UINT cp;
2520     CPINFO cpi;
2521     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2522     KERNINGPAIR *kern_pairW;
2523
2524     if (!cPairs && kern_pairA)
2525     {
2526         SetLastError(ERROR_INVALID_PARAMETER);
2527         return 0;
2528     }
2529
2530     cp = GdiGetCodePage(hDC);
2531
2532     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2533      * to fail on an invalid character for CP_SYMBOL.
2534      */
2535     cpi.DefaultChar[0] = 0;
2536     if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2537     {
2538         FIXME("Can't find codepage %u info\n", cp);
2539         return 0;
2540     }
2541
2542     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2543     if (!total_kern_pairs) return 0;
2544
2545     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2546     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2547
2548     for (i = 0; i < total_kern_pairs; i++)
2549     {
2550         char first, second;
2551
2552         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2553             continue;
2554
2555         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2556             continue;
2557
2558         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2559             continue;
2560
2561         if (kern_pairA)
2562         {
2563             if (kern_pairs_copied >= cPairs) break;
2564
2565             kern_pairA->wFirst = (BYTE)first;
2566             kern_pairA->wSecond = (BYTE)second;
2567             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2568             kern_pairA++;
2569         }
2570         kern_pairs_copied++;
2571     }
2572
2573     HeapFree(GetProcessHeap(), 0, kern_pairW);
2574
2575     return kern_pairs_copied;
2576 }
2577
2578 /*************************************************************************
2579  *             GetKerningPairsW   (GDI32.@)
2580  */
2581 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2582                                  LPKERNINGPAIR lpKerningPairs )
2583 {
2584     DC *dc;
2585     DWORD ret = 0;
2586
2587     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2588
2589     if (!cPairs && lpKerningPairs)
2590     {
2591         SetLastError(ERROR_INVALID_PARAMETER);
2592         return 0;
2593     }
2594
2595     dc = get_dc_ptr(hDC);
2596     if (!dc) return 0;
2597
2598     if (dc->gdiFont)
2599         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2600
2601     release_dc_ptr( dc );
2602     return ret;
2603 }
2604
2605 /*************************************************************************
2606  * TranslateCharsetInfo [GDI32.@]
2607  *
2608  * Fills a CHARSETINFO structure for a character set, code page, or
2609  * font. This allows making the correspondence between different labels
2610  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2611  * of the same encoding.
2612  *
2613  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2614  * only one codepage should be set in *lpSrc.
2615  *
2616  * RETURNS
2617  *   TRUE on success, FALSE on failure.
2618  *
2619  */
2620 BOOL WINAPI TranslateCharsetInfo(
2621   LPDWORD lpSrc, /* [in]
2622        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2623        if flags == TCI_SRCCHARSET: a character set value
2624        if flags == TCI_SRCCODEPAGE: a code page value
2625                  */
2626   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2627   DWORD flags /* [in] determines interpretation of lpSrc */)
2628 {
2629     int index = 0;
2630     switch (flags) {
2631     case TCI_SRCFONTSIG:
2632       while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2633       break;
2634     case TCI_SRCCODEPAGE:
2635       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2636       break;
2637     case TCI_SRCCHARSET:
2638       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2639       break;
2640     default:
2641       return FALSE;
2642     }
2643     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2644     *lpCs = FONT_tci[index];
2645     return TRUE;
2646 }
2647
2648 /*************************************************************************
2649  *             GetFontLanguageInfo   (GDI32.@)
2650  */
2651 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2652 {
2653         FONTSIGNATURE fontsig;
2654         static const DWORD GCP_DBCS_MASK=0x003F0000,
2655                 GCP_DIACRITIC_MASK=0x00000000,
2656                 FLI_GLYPHS_MASK=0x00000000,
2657                 GCP_GLYPHSHAPE_MASK=0x00000040,
2658                 GCP_KASHIDA_MASK=0x00000000,
2659                 GCP_LIGATE_MASK=0x00000000,
2660                 GCP_USEKERNING_MASK=0x00000000,
2661                 GCP_REORDER_MASK=0x00000060;
2662
2663         DWORD result=0;
2664
2665         GetTextCharsetInfo( hdc, &fontsig, 0 );
2666         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2667
2668         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2669                 result|=GCP_DBCS;
2670
2671         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2672                 result|=GCP_DIACRITIC;
2673
2674         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2675                 result|=FLI_GLYPHS;
2676
2677         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2678                 result|=GCP_GLYPHSHAPE;
2679
2680         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2681                 result|=GCP_KASHIDA;
2682
2683         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2684                 result|=GCP_LIGATE;
2685
2686         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2687                 result|=GCP_USEKERNING;
2688
2689         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2690         if( GetTextAlign( hdc) & TA_RTLREADING )
2691             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2692                     result|=GCP_REORDER;
2693
2694         return result;
2695 }
2696
2697
2698 /*************************************************************************
2699  * GetFontData [GDI32.@]
2700  *
2701  * Retrieve data for TrueType font.
2702  *
2703  * RETURNS
2704  *
2705  * success: Number of bytes returned
2706  * failure: GDI_ERROR
2707  *
2708  * NOTES
2709  *
2710  * Calls SetLastError()
2711  *
2712  */
2713 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2714     LPVOID buffer, DWORD length)
2715 {
2716     DC *dc = get_dc_ptr(hdc);
2717     DWORD ret = GDI_ERROR;
2718
2719     if(!dc) return GDI_ERROR;
2720
2721     if(dc->gdiFont)
2722       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2723
2724     release_dc_ptr( dc );
2725     return ret;
2726 }
2727
2728 /*************************************************************************
2729  * GetGlyphIndicesA [GDI32.@]
2730  */
2731 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2732                               LPWORD pgi, DWORD flags)
2733 {
2734     DWORD ret;
2735     WCHAR *lpstrW;
2736     INT countW;
2737
2738     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2739           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2740
2741     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2742     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2743     HeapFree(GetProcessHeap(), 0, lpstrW);
2744
2745     return ret;
2746 }
2747
2748 /*************************************************************************
2749  * GetGlyphIndicesW [GDI32.@]
2750  */
2751 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2752                               LPWORD pgi, DWORD flags)
2753 {
2754     DC *dc = get_dc_ptr(hdc);
2755     DWORD ret = GDI_ERROR;
2756
2757     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2758           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2759
2760     if(!dc) return GDI_ERROR;
2761
2762     if(dc->gdiFont)
2763         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2764
2765     release_dc_ptr( dc );
2766     return ret;
2767 }
2768
2769 /*************************************************************************
2770  * GetCharacterPlacementA [GDI32.@]
2771  *
2772  * See GetCharacterPlacementW.
2773  *
2774  * NOTES:
2775  *  the web browser control of ie4 calls this with dwFlags=0
2776  */
2777 DWORD WINAPI
2778 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2779                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2780                          DWORD dwFlags)
2781 {
2782     WCHAR *lpStringW;
2783     INT uCountW;
2784     GCP_RESULTSW resultsW;
2785     DWORD ret;
2786     UINT font_cp;
2787
2788     TRACE("%s, %d, %d, 0x%08x\n",
2789           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2790
2791     /* both structs are equal in size */
2792     memcpy(&resultsW, lpResults, sizeof(resultsW));
2793
2794     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2795     if(lpResults->lpOutString)
2796         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2797
2798     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2799
2800     lpResults->nGlyphs = resultsW.nGlyphs;
2801     lpResults->nMaxFit = resultsW.nMaxFit;
2802
2803     if(lpResults->lpOutString) {
2804         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2805                             lpResults->lpOutString, uCount, NULL, NULL );
2806     }
2807
2808     HeapFree(GetProcessHeap(), 0, lpStringW);
2809     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2810
2811     return ret;
2812 }
2813
2814 /*************************************************************************
2815  * GetCharacterPlacementW [GDI32.@]
2816  *
2817  *   Retrieve information about a string. This includes the width, reordering,
2818  *   Glyphing and so on.
2819  *
2820  * RETURNS
2821  *
2822  *   The width and height of the string if successful, 0 if failed.
2823  *
2824  * BUGS
2825  *
2826  *   All flags except GCP_REORDER are not yet implemented.
2827  *   Reordering is not 100% compliant to the Windows BiDi method.
2828  *   Caret positioning is not yet implemented for BiDi.
2829  *   Classes are not yet implemented.
2830  *
2831  */
2832 DWORD WINAPI
2833 GetCharacterPlacementW(
2834                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2835                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2836                 INT uCount,             /* [in] Number of WORDS in string. */
2837                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2838                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2839                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2840                 )
2841 {
2842     DWORD ret=0;
2843     SIZE size;
2844     UINT i, nSet;
2845
2846     TRACE("%s, %d, %d, 0x%08x\n",
2847           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2848
2849     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2850           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2851             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2852             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2853             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2854
2855     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
2856     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2857     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2858         FIXME("Caret positions for complex scripts not implemented\n");
2859
2860         nSet = (UINT)uCount;
2861         if(nSet > lpResults->nGlyphs)
2862                 nSet = lpResults->nGlyphs;
2863
2864         /* return number of initialized fields */
2865         lpResults->nGlyphs = nSet;
2866
2867         if((dwFlags&GCP_REORDER)==0 )
2868         {
2869                 /* Treat the case where no special handling was requested in a fastpath way */
2870                 /* copy will do if the GCP_REORDER flag is not set */
2871                 if(lpResults->lpOutString)
2872                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2873
2874                 if(lpResults->lpOrder)
2875                 {
2876                         for(i = 0; i < nSet; i++)
2877                                 lpResults->lpOrder[i] = i;
2878                 }
2879         } else
2880         {
2881             BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2882                           nSet, lpResults->lpOrder, NULL, NULL );
2883         }
2884
2885         /* FIXME: Will use the placement chars */
2886         if (lpResults->lpDx)
2887         {
2888                 int c;
2889                 for (i = 0; i < nSet; i++)
2890                 {
2891                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2892                                 lpResults->lpDx[i]= c;
2893                 }
2894         }
2895
2896     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2897     {
2898         int pos = 0;
2899        
2900         lpResults->lpCaretPos[0] = 0;
2901         for (i = 1; i < nSet; i++)
2902             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2903                 lpResults->lpCaretPos[i] = (pos += size.cx);
2904     }
2905    
2906     if(lpResults->lpGlyphs)
2907         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2908
2909     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2910       ret = MAKELONG(size.cx, size.cy);
2911
2912     return ret;
2913 }
2914
2915 /*************************************************************************
2916  *      GetCharABCWidthsFloatA [GDI32.@]
2917  *
2918  * See GetCharABCWidthsFloatW.
2919  */
2920 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2921 {
2922     INT i, wlen, count = (INT)(last - first + 1);
2923     LPSTR str;
2924     LPWSTR wstr;
2925     BOOL ret = TRUE;
2926
2927     if (count <= 0) return FALSE;
2928
2929     str = HeapAlloc(GetProcessHeap(), 0, count);
2930
2931     for(i = 0; i < count; i++)
2932         str[i] = (BYTE)(first + i);
2933
2934     wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2935
2936     for (i = 0; i < wlen; i++)
2937     {
2938         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2939         {
2940             ret = FALSE;
2941             break;
2942         }
2943         abcf++;
2944     }
2945
2946     HeapFree( GetProcessHeap(), 0, str );
2947     HeapFree( GetProcessHeap(), 0, wstr );
2948
2949     return ret;
2950 }
2951
2952 /*************************************************************************
2953  *      GetCharABCWidthsFloatW [GDI32.@]
2954  *
2955  * Retrieves widths of a range of characters.
2956  *
2957  * PARAMS
2958  *    hdc   [I] Handle to device context.
2959  *    first [I] First character in range to query.
2960  *    last  [I] Last character in range to query.
2961  *    abcf  [O] Array of LPABCFLOAT structures.
2962  *
2963  * RETURNS
2964  *    Success: TRUE
2965  *    Failure: FALSE
2966  */
2967 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2968 {
2969     UINT i;
2970     BOOL ret = FALSE;
2971     DC *dc = get_dc_ptr( hdc );
2972
2973     TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
2974
2975     if (!dc) return FALSE;
2976
2977     if (!abcf)
2978     {
2979         release_dc_ptr( dc );
2980         return FALSE;
2981     }
2982
2983     if (dc->gdiFont)
2984         ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
2985     else
2986         FIXME("stub\n");
2987
2988     if (ret)
2989     {
2990         /* convert device units to logical */
2991         for (i = first; i <= last; i++, abcf++)
2992         {
2993             abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
2994             abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
2995             abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
2996         }
2997     }
2998
2999     release_dc_ptr( dc );
3000     return ret;
3001 }
3002
3003 /*************************************************************************
3004  *      GetCharWidthFloatA [GDI32.@]
3005  */
3006 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3007                                     UINT iLastChar, PFLOAT pxBuffer)
3008 {
3009     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3010     return 0;
3011 }
3012
3013 /*************************************************************************
3014  *      GetCharWidthFloatW [GDI32.@]
3015  */
3016 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3017                                     UINT iLastChar, PFLOAT pxBuffer)
3018 {
3019     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3020     return 0;
3021 }
3022
3023
3024 /***********************************************************************
3025  *                                                                     *
3026  *           Font Resource API                                         *
3027  *                                                                     *
3028  ***********************************************************************/
3029
3030 /***********************************************************************
3031  *           AddFontResourceA    (GDI32.@)
3032  */
3033 INT WINAPI AddFontResourceA( LPCSTR str )
3034 {
3035     return AddFontResourceExA( str, 0, NULL);
3036 }
3037
3038 /***********************************************************************
3039  *           AddFontResourceW    (GDI32.@)
3040  */
3041 INT WINAPI AddFontResourceW( LPCWSTR str )
3042 {
3043     return AddFontResourceExW(str, 0, NULL);
3044 }
3045
3046
3047 /***********************************************************************
3048  *           AddFontResourceExA    (GDI32.@)
3049  */
3050 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3051 {
3052     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3053     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3054     INT ret;
3055
3056     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3057     ret = AddFontResourceExW(strW, fl, pdv);
3058     HeapFree(GetProcessHeap(), 0, strW);
3059     return ret;
3060 }
3061
3062 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3063 {
3064     HRSRC rsrc = FindResourceW(hModule, name, type);
3065     HGLOBAL hMem = LoadResource(hModule, rsrc);
3066     LPVOID *pMem = LockResource(hMem);
3067     int *num_total = (int *)lParam;
3068     DWORD num_in_res;
3069
3070     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3071     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3072     {
3073         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3074         return FALSE;
3075     }
3076
3077     *num_total += num_in_res;
3078     return TRUE;
3079 }
3080
3081 /***********************************************************************
3082  *           AddFontResourceExW    (GDI32.@)
3083  */
3084 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3085 {
3086     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3087     if (ret == 0)
3088     {
3089         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3090         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3091         if (hModule != NULL)
3092         {
3093             int num_resources = 0;
3094             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3095
3096             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3097                 wine_dbgstr_w(str));
3098             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3099                 ret = num_resources;
3100             FreeLibrary(hModule);
3101         }
3102     }
3103     return ret;
3104 }
3105
3106 /***********************************************************************
3107  *           RemoveFontResourceA    (GDI32.@)
3108  */
3109 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3110 {
3111     return RemoveFontResourceExA(str, 0, 0);
3112 }
3113
3114 /***********************************************************************
3115  *           RemoveFontResourceW    (GDI32.@)
3116  */
3117 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3118 {
3119     return RemoveFontResourceExW(str, 0, 0);
3120 }
3121
3122 /***********************************************************************
3123  *           AddFontMemResourceEx    (GDI32.@)
3124  */
3125 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3126 {
3127     return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3128 }
3129
3130 /***********************************************************************
3131  *           RemoveFontMemResourceEx    (GDI32.@)
3132  */
3133 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3134 {
3135     FIXME("(%p) stub\n", fh);
3136     return TRUE;
3137 }
3138
3139 /***********************************************************************
3140  *           RemoveFontResourceExA    (GDI32.@)
3141  */
3142 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3143 {
3144     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3145     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3146     INT ret;
3147
3148     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3149     ret = RemoveFontResourceExW(strW, fl, pdv);
3150     HeapFree(GetProcessHeap(), 0, strW);
3151     return ret;
3152 }
3153
3154 /***********************************************************************
3155  *           RemoveFontResourceExW    (GDI32.@)
3156  */
3157 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3158 {
3159     return WineEngRemoveFontResourceEx(str, fl, pdv);
3160 }
3161
3162 /***********************************************************************
3163  *           GetTextCharset    (GDI32.@)
3164  */
3165 UINT WINAPI GetTextCharset(HDC hdc)
3166 {
3167     /* MSDN docs say this is equivalent */
3168     return GetTextCharsetInfo(hdc, NULL, 0);
3169 }
3170
3171 /***********************************************************************
3172  *           GetTextCharsetInfo    (GDI32.@)
3173  */
3174 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3175 {
3176     UINT ret = DEFAULT_CHARSET;
3177     DC *dc = get_dc_ptr(hdc);
3178
3179     if (dc)
3180     {
3181         if (dc->gdiFont)
3182             ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3183
3184         release_dc_ptr( dc );
3185     }
3186
3187     if (ret == DEFAULT_CHARSET && fs)
3188         memset(fs, 0, sizeof(FONTSIGNATURE));
3189     return ret;
3190 }
3191
3192 /***********************************************************************
3193  *           GdiGetCharDimensions    (GDI32.@)
3194  *
3195  * Gets the average width of the characters in the English alphabet.
3196  *
3197  * PARAMS
3198  *  hdc    [I] Handle to the device context to measure on.
3199  *  lptm   [O] Pointer to memory to store the text metrics into.
3200  *  height [O] On exit, the maximum height of characters in the English alphabet.
3201  *
3202  * RETURNS
3203  *  The average width of characters in the English alphabet.
3204  *
3205  * NOTES
3206  *  This function is used by the dialog manager to get the size of a dialog
3207  *  unit. It should also be used by other pieces of code that need to know
3208  *  the size of a dialog unit in logical units without having access to the
3209  *  window handle of the dialog.
3210  *  Windows caches the font metrics from this function, but we don't and
3211  *  there doesn't appear to be an immediate advantage to do so.
3212  *
3213  * SEE ALSO
3214  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3215  */
3216 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3217 {
3218     SIZE sz;
3219     static const WCHAR alphabet[] = {
3220         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3221         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3222         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3223
3224     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3225
3226     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3227
3228     if (height) *height = sz.cy;
3229     return (sz.cx / 26 + 1) / 2;
3230 }
3231
3232 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3233 {
3234     FIXME("(%d): stub\n", fEnableEUDC);
3235     return FALSE;
3236 }
3237
3238 /***********************************************************************
3239  *           GetCharWidthI    (GDI32.@)
3240  *
3241  * Retrieve widths of characters.
3242  *
3243  * PARAMS
3244  *  hdc    [I] Handle to a device context.
3245  *  first  [I] First glyph in range to query.
3246  *  count  [I] Number of glyph indices to query.
3247  *  glyphs [I] Array of glyphs to query.
3248  *  buffer [O] Buffer to receive character widths.
3249  *
3250  * NOTES
3251  *  Only works with TrueType fonts.
3252  *
3253  * RETURNS
3254  *  Success: TRUE
3255  *  Failure: FALSE
3256  */
3257 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3258 {
3259     ABC *abc;
3260     unsigned int i;
3261
3262     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3263
3264     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3265         return FALSE;
3266
3267     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3268     {
3269         HeapFree(GetProcessHeap(), 0, abc);
3270         return FALSE;
3271     }
3272
3273     for (i = 0; i < count; i++)
3274         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3275
3276     HeapFree(GetProcessHeap(), 0, abc);
3277     return TRUE;
3278 }
3279
3280 /***********************************************************************
3281  *           GetFontUnicodeRanges    (GDI32.@)
3282  *
3283  *  Retrieve a list of supported Unicode characters in a font.
3284  *
3285  *  PARAMS
3286  *   hdc  [I] Handle to a device context.
3287  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3288  *
3289  *  RETURNS
3290  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3291  *   Failure: 0
3292  *
3293  */
3294 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3295 {
3296     DWORD ret = 0;
3297     DC *dc = get_dc_ptr(hdc);
3298
3299     TRACE("(%p, %p)\n", hdc, lpgs);
3300
3301     if (!dc) return 0;
3302
3303     if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3304     release_dc_ptr(dc);
3305     return ret;
3306 }
3307
3308
3309 /*************************************************************
3310  *           FontIsLinked    (GDI32.@)
3311  */
3312 BOOL WINAPI FontIsLinked(HDC hdc)
3313 {
3314     DC *dc = get_dc_ptr(hdc);
3315     BOOL ret = FALSE;
3316
3317     if (!dc) return FALSE;
3318     if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3319     release_dc_ptr(dc);
3320     TRACE("returning %d\n", ret);
3321     return ret;
3322 }
3323
3324 /*************************************************************
3325  *           GdiRealizationInfo    (GDI32.@)
3326  *
3327  * Returns a structure that contains some font information.
3328  */
3329 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3330 {
3331     DC *dc = get_dc_ptr(hdc);
3332     BOOL ret = FALSE;
3333
3334     if (!dc) return FALSE;
3335     if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3336     release_dc_ptr(dc);
3337
3338     return ret;
3339 }