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