gdiplus: Add TRACE(..) to CustomLineCap.
[wine] / dlls / gdi32 / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  * Copyright 2002,2003 Shachar Shemesh
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
40
41   /* Device -> World size conversion */
42
43 /* Performs a device to world transformation on the specified width (which
44  * is in integer format).
45  */
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
47 {
48     double floatWidth;
49
50     /* Perform operation with floating point */
51     floatWidth = (double)width * dc->xformVport2World.eM11;
52     /* Round to integers */
53     return GDI_ROUND(floatWidth);
54 }
55
56 /* Performs a device to world transformation on the specified size (which
57  * is in integer format).
58  */
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
60 {
61     double floatHeight;
62
63     /* Perform operation with floating point */
64     floatHeight = (double)height * dc->xformVport2World.eM22;
65     /* Round to integers */
66     return GDI_ROUND(floatHeight);
67 }
68
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
70 {
71     POINT pt[2];
72     pt[0].x = pt[0].y = 0;
73     pt[1].x = width;
74     pt[1].y = 0;
75     LPtoDP(dc->hSelf, pt, 2);
76     return pt[1].x - pt[0].x;
77 }
78
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
80 {
81     POINT pt[2];
82     pt[0].x = pt[0].y = 0;
83     pt[1].x = 0;
84     pt[1].y = height;
85     LPtoDP(dc->hSelf, pt, 2);
86     return pt[1].y - pt[0].y;
87 }
88
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, 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)
804         {
805             res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
806             if (res == 0)
807                 res = count;
808             name[count-1] = 0;
809             /* GetTextFaceA does NOT include the nul byte in the return count.  */
810             res--;
811         }
812         else
813             res = 0;
814     }
815     else
816         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
817     HeapFree( GetProcessHeap(), 0, nameW );
818     return res;
819 }
820
821 /***********************************************************************
822  *           GetTextFaceW    (GDI32.@)
823  */
824 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
825 {
826     FONTOBJ *font;
827     INT     ret = 0;
828
829     DC * dc = get_dc_ptr( hdc );
830     if (!dc) return 0;
831
832     if(dc->gdiFont)
833         ret = WineEngGetTextFace(dc->gdiFont, count, name);
834     else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
835     {
836         INT n = strlenW(font->logfont.lfFaceName) + 1;
837         if (name)
838         {
839             lstrcpynW( name, font->logfont.lfFaceName, count );
840             ret = min(count, n);
841         }
842         else ret = n;
843         GDI_ReleaseObj( dc->hFont );
844     }
845     release_dc_ptr( dc );
846     return ret;
847 }
848
849
850 /***********************************************************************
851  *           GetTextExtentPoint32A    (GDI32.@)
852  *
853  * See GetTextExtentPoint32W.
854  */
855 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
856                                      LPSIZE size )
857 {
858     BOOL ret = FALSE;
859     INT wlen;
860     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
861
862     if (p) {
863         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
864         HeapFree( GetProcessHeap(), 0, p );
865     }
866
867     TRACE("(%p %s %d %p): returning %d x %d\n",
868           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
869     return ret;
870 }
871
872
873 /***********************************************************************
874  * GetTextExtentPoint32W [GDI32.@]
875  *
876  * Computes width/height for a string.
877  *
878  * Computes width and height of the specified string.
879  *
880  * RETURNS
881  *    Success: TRUE
882  *    Failure: FALSE
883  */
884 BOOL WINAPI GetTextExtentPoint32W(
885     HDC hdc,     /* [in]  Handle of device context */
886     LPCWSTR str,   /* [in]  Address of text string */
887     INT count,   /* [in]  Number of characters in string */
888     LPSIZE size) /* [out] Address of structure for string size */
889 {
890     return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
891 }
892
893 /***********************************************************************
894  * GetTextExtentExPointI [GDI32.@]
895  *
896  * Computes width and height of the array of glyph indices.
897  *
898  * PARAMS
899  *    hdc     [I] Handle of device context.
900  *    indices [I] Glyph index array.
901  *    count   [I] Number of glyphs in array.
902  *    max_ext [I] Maximum width in glyphs.
903  *    nfit    [O] Maximum number of characters.
904  *    dxs     [O] Partial string widths.
905  *    size    [O] Returned string size.
906  *
907  * RETURNS
908  *    Success: TRUE
909  *    Failure: FALSE
910  */
911 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
912                                    LPINT nfit, LPINT dxs, LPSIZE size )
913 {
914     BOOL ret = FALSE;
915     DC * dc = get_dc_ptr( hdc );
916     if (!dc) return FALSE;
917
918     if(dc->gdiFont) {
919         ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
920         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
921         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
922         size->cx += count * dc->charExtra;
923     }
924     else if(dc->funcs->pGetTextExtentExPoint) {
925         FIXME("calling GetTextExtentExPoint\n");
926         ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
927                                                 count, max_ext, nfit, dxs, size );
928     }
929
930     release_dc_ptr( dc );
931
932     TRACE("(%p %p %d %p): returning %d x %d\n",
933           hdc, indices, count, size, size->cx, size->cy );
934     return ret;
935 }
936
937 /***********************************************************************
938  * GetTextExtentPointI [GDI32.@]
939  *
940  * Computes width and height of the array of glyph indices.
941  *
942  * PARAMS
943  *    hdc     [I] Handle of device context.
944  *    indices [I] Glyph index array.
945  *    count   [I] Number of glyphs in array.
946  *    size    [O] Returned string size.
947  *
948  * RETURNS
949  *    Success: TRUE
950  *    Failure: FALSE
951  */
952 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
953 {
954     return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
955 }
956
957
958 /***********************************************************************
959  *           GetTextExtentPointA    (GDI32.@)
960  */
961 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
962                                           LPSIZE size )
963 {
964     TRACE("not bug compatible.\n");
965     return GetTextExtentPoint32A( hdc, str, count, size );
966 }
967
968 /***********************************************************************
969  *           GetTextExtentPointW   (GDI32.@)
970  */
971 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
972                                           LPSIZE size )
973 {
974     TRACE("not bug compatible.\n");
975     return GetTextExtentPoint32W( hdc, str, count, size );
976 }
977
978
979 /***********************************************************************
980  *           GetTextExtentExPointA    (GDI32.@)
981  */
982 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
983                                    INT maxExt, LPINT lpnFit,
984                                    LPINT alpDx, LPSIZE size )
985 {
986     BOOL ret;
987     INT wlen;
988     INT *walpDx = NULL;
989     LPWSTR p = NULL;
990     
991     if (alpDx &&
992        NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
993        return FALSE;
994     
995     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
996     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
997     if (walpDx)
998     {
999         INT n = lpnFit ? *lpnFit : wlen;
1000         INT i, j;
1001         for(i = 0, j = 0; i < n; i++, j++)
1002         {
1003             alpDx[j] = walpDx[i];
1004             if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1005         }
1006     }
1007     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1008     HeapFree( GetProcessHeap(), 0, p );
1009     HeapFree( GetProcessHeap(), 0, walpDx );
1010     return ret;
1011 }
1012
1013
1014 /***********************************************************************
1015  *           GetTextExtentExPointW    (GDI32.@)
1016  *
1017  * Return the size of the string as it would be if it was output properly by
1018  * e.g. TextOut.
1019  *
1020  * This should include
1021  * - Intercharacter spacing
1022  * - justification spacing (not yet done)
1023  * - kerning? see below
1024  *
1025  * Kerning.  Since kerning would be carried out by the rendering code it should
1026  * be done by the driver.  However they don't support it yet.  Also I am not
1027  * yet persuaded that (certainly under Win95) any kerning is actually done.
1028  *
1029  * str: According to MSDN this should be null-terminated.  That is not true; a
1030  *      null will not terminate it early.
1031  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1032  *       than count.  I have seen it be either the size of the full string or
1033  *       1 less than the size of the full string.  I have not seen it bear any
1034  *       resemblance to the portion that would fit.
1035  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1036  *         trailing intercharacter spacing and any trailing justification.
1037  *
1038  * FIXME
1039  * Currently we do this by measuring each character etc.  We should do it by
1040  * passing the request to the driver, perhaps by extending the
1041  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1042  * thinking about kerning issues and rounding issues in the justification.
1043  */
1044
1045 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1046                                    INT maxExt, LPINT lpnFit,
1047                                    LPINT alpDx, LPSIZE size )
1048 {
1049     INT nFit = 0;
1050     LPINT dxs = NULL;
1051     DC *dc;
1052     BOOL ret = FALSE;
1053     TEXTMETRICW tm;
1054
1055     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1056
1057     dc = get_dc_ptr(hdc);
1058     if (! dc)
1059         return FALSE;
1060
1061     GetTextMetricsW(hdc, &tm);
1062
1063     /* If we need to calculate nFit, then we need the partial extents even if
1064        the user hasn't provided us with an array.  */
1065     if (lpnFit)
1066     {
1067         dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1068         if (! dxs)
1069         {
1070             release_dc_ptr(dc);
1071             SetLastError(ERROR_OUTOFMEMORY);
1072             return FALSE;
1073         }
1074     }
1075     else
1076         dxs = alpDx;
1077
1078     if (dc->gdiFont)
1079         ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1080                                           0, NULL, dxs, size);
1081     else if (dc->funcs->pGetTextExtentExPoint)
1082         ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1083                                                0, NULL, dxs, size);
1084
1085     /* Perform device size to world size transformations.  */
1086     if (ret)
1087     {
1088         INT extra      = dc->charExtra,
1089         breakExtra = dc->breakExtra,
1090         breakRem   = dc->breakRem,
1091         i;
1092
1093         if (dxs)
1094         {
1095             for (i = 0; i < count; ++i)
1096             {
1097                 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1098                 dxs[i] += (i+1) * extra;
1099                 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1100                 {
1101                     dxs[i] += breakExtra;
1102                     if (breakRem > 0)
1103                     {
1104                         breakRem--;
1105                         dxs[i]++;
1106                     }
1107                 }
1108                 if (dxs[i] <= maxExt)
1109                     ++nFit;
1110             }
1111             breakRem = dc->breakRem;
1112         }
1113         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1114         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1115
1116         if (!dxs && count > 1 && (breakExtra || breakRem))
1117         {
1118             for (i = 0; i < count; i++)
1119             {
1120                 if (str[i] == tm.tmBreakChar)
1121                 {
1122                     size->cx += breakExtra;
1123                     if (breakRem > 0)
1124                     {
1125                         breakRem--;
1126                         (size->cx)++;
1127                     }
1128                 }
1129             }
1130         }
1131     }
1132
1133     if (lpnFit)
1134         *lpnFit = nFit;
1135
1136     if (! alpDx)
1137         HeapFree(GetProcessHeap(), 0, dxs);
1138
1139     release_dc_ptr( dc );
1140
1141     TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1142     return ret;
1143 }
1144
1145 /***********************************************************************
1146  *           GetTextMetricsA    (GDI32.@)
1147  */
1148 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1149 {
1150     TEXTMETRICW tm32;
1151
1152     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1153     FONT_TextMetricWToA( &tm32, metrics );
1154     return TRUE;
1155 }
1156
1157 /***********************************************************************
1158  *           GetTextMetricsW    (GDI32.@)
1159  */
1160 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1161 {
1162     BOOL ret = FALSE;
1163     DC * dc = get_dc_ptr( hdc );
1164     if (!dc) return FALSE;
1165
1166     if (dc->gdiFont)
1167         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1168     else if (dc->funcs->pGetTextMetrics)
1169         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1170
1171     if (ret)
1172     {
1173     /* device layer returns values in device units
1174      * therefore we have to convert them to logical */
1175
1176         metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1177         metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1178
1179 #define WDPTOLP(x) ((x<0)?                                      \
1180                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1181                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1182 #define HDPTOLP(y) ((y<0)?                                      \
1183                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1184                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1185
1186     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1187     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1188     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1189     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1190     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1191     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1192     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1193     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1194         ret = TRUE;
1195 #undef WDPTOLP
1196 #undef HDPTOLP
1197     TRACE("text metrics:\n"
1198           "    Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1199           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1200           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1201           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1202           "    PitchAndFamily = %02x\n"
1203           "    --------------------\n"
1204           "    InternalLeading = %i\n"
1205           "    Ascent = %i\n"
1206           "    Descent = %i\n"
1207           "    Height = %i\n",
1208           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1209           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1210           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1211           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1212           metrics->tmPitchAndFamily,
1213           metrics->tmInternalLeading,
1214           metrics->tmAscent,
1215           metrics->tmDescent,
1216           metrics->tmHeight );
1217     }
1218     release_dc_ptr( dc );
1219     return ret;
1220 }
1221
1222
1223 /***********************************************************************
1224  *              GetOutlineTextMetricsA (GDI32.@)
1225  * Gets metrics for TrueType fonts.
1226  *
1227  * NOTES
1228  *    If the supplied buffer isn't big enough Windows partially fills it up to
1229  *    its given length and returns that length.
1230  *
1231  * RETURNS
1232  *    Success: Non-zero or size of required buffer
1233  *    Failure: 0
1234  */
1235 UINT WINAPI GetOutlineTextMetricsA(
1236     HDC hdc,    /* [in]  Handle of device context */
1237     UINT cbData, /* [in]  Size of metric data array */
1238     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1239 {
1240     char buf[512], *ptr;
1241     UINT ret, needed;
1242     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1243     OUTLINETEXTMETRICA *output = lpOTM;
1244     INT left, len;
1245
1246     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1247         return 0;
1248     if(ret > sizeof(buf))
1249         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1250     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1251
1252     needed = sizeof(OUTLINETEXTMETRICA);
1253     if(lpOTMW->otmpFamilyName)
1254         needed += WideCharToMultiByte(CP_ACP, 0,
1255            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1256                                       NULL, 0, NULL, NULL);
1257     if(lpOTMW->otmpFaceName)
1258         needed += WideCharToMultiByte(CP_ACP, 0,
1259            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1260                                       NULL, 0, NULL, NULL);
1261     if(lpOTMW->otmpStyleName)
1262         needed += WideCharToMultiByte(CP_ACP, 0,
1263            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1264                                       NULL, 0, NULL, NULL);
1265     if(lpOTMW->otmpFullName)
1266         needed += WideCharToMultiByte(CP_ACP, 0,
1267            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1268                                       NULL, 0, NULL, NULL);
1269
1270     if(!lpOTM) {
1271         ret = needed;
1272         goto end;
1273     }
1274
1275     TRACE("needed = %d\n", needed);
1276     if(needed > cbData)
1277         /* Since the supplied buffer isn't big enough, we'll alloc one
1278            that is and memcpy the first cbData bytes into the lpOTM at
1279            the end. */
1280         output = HeapAlloc(GetProcessHeap(), 0, needed);
1281
1282     ret = output->otmSize = min(needed, cbData);
1283     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1284     output->otmFiller = 0;
1285     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1286     output->otmfsSelection = lpOTMW->otmfsSelection;
1287     output->otmfsType = lpOTMW->otmfsType;
1288     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1289     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1290     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1291     output->otmEMSquare = lpOTMW->otmEMSquare;
1292     output->otmAscent = lpOTMW->otmAscent;
1293     output->otmDescent = lpOTMW->otmDescent;
1294     output->otmLineGap = lpOTMW->otmLineGap;
1295     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1296     output->otmsXHeight = lpOTMW->otmsXHeight;
1297     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1298     output->otmMacAscent = lpOTMW->otmMacAscent;
1299     output->otmMacDescent = lpOTMW->otmMacDescent;
1300     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1301     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1302     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1303     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1304     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1305     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1306     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1307     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1308     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1309     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1310
1311
1312     ptr = (char*)(output + 1);
1313     left = needed - sizeof(*output);
1314
1315     if(lpOTMW->otmpFamilyName) {
1316         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1317         len = WideCharToMultiByte(CP_ACP, 0,
1318              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1319                                   ptr, left, NULL, NULL);
1320         left -= len;
1321         ptr += len;
1322     } else
1323         output->otmpFamilyName = 0;
1324
1325     if(lpOTMW->otmpFaceName) {
1326         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1327         len = WideCharToMultiByte(CP_ACP, 0,
1328              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1329                                   ptr, left, NULL, NULL);
1330         left -= len;
1331         ptr += len;
1332     } else
1333         output->otmpFaceName = 0;
1334
1335     if(lpOTMW->otmpStyleName) {
1336         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1337         len = WideCharToMultiByte(CP_ACP, 0,
1338              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1339                                   ptr, left, NULL, NULL);
1340         left -= len;
1341         ptr += len;
1342     } else
1343         output->otmpStyleName = 0;
1344
1345     if(lpOTMW->otmpFullName) {
1346         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1347         len = WideCharToMultiByte(CP_ACP, 0,
1348              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1349                                   ptr, left, NULL, NULL);
1350         left -= len;
1351     } else
1352         output->otmpFullName = 0;
1353
1354     assert(left == 0);
1355
1356     if(output != lpOTM) {
1357         memcpy(lpOTM, output, cbData);
1358         HeapFree(GetProcessHeap(), 0, output);
1359
1360         /* check if the string offsets really fit into the provided size */
1361         /* FIXME: should we check string length as well? */
1362         /* make sure that we don't read/write beyond the provided buffer */
1363         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1364         {
1365             if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1366                 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1367         }
1368
1369         /* make sure that we don't read/write beyond the provided buffer */
1370         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1371         {
1372             if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1373                 lpOTM->otmpFaceName = 0; /* doesn't fit */
1374         }
1375
1376             /* make sure that we don't read/write beyond the provided buffer */
1377         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1378         {
1379             if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1380                 lpOTM->otmpStyleName = 0; /* doesn't fit */
1381         }
1382
1383         /* make sure that we don't read/write beyond the provided buffer */
1384         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1385         {
1386             if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1387                 lpOTM->otmpFullName = 0; /* doesn't fit */
1388         }
1389     }
1390
1391 end:
1392     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1393         HeapFree(GetProcessHeap(), 0, lpOTMW);
1394
1395     return ret;
1396 }
1397
1398
1399 /***********************************************************************
1400  *           GetOutlineTextMetricsW [GDI32.@]
1401  */
1402 UINT WINAPI GetOutlineTextMetricsW(
1403     HDC hdc,    /* [in]  Handle of device context */
1404     UINT cbData, /* [in]  Size of metric data array */
1405     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1406 {
1407     DC *dc = get_dc_ptr( hdc );
1408     OUTLINETEXTMETRICW *output = lpOTM;
1409     UINT ret;
1410
1411     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1412     if(!dc) return 0;
1413
1414     if(dc->gdiFont) {
1415         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1416         if(lpOTM && ret) {
1417             if(ret > cbData) {
1418                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1419                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1420             }
1421
1422         output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1423         output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1424
1425 #define WDPTOLP(x) ((x<0)?                                      \
1426                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1427                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1428 #define HDPTOLP(y) ((y<0)?                                      \
1429                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1430                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1431
1432             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1433             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1434             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1435             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1436             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1437             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1438             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1439             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1440             output->otmAscent = HDPTOLP(output->otmAscent);
1441             output->otmDescent = HDPTOLP(output->otmDescent);
1442             output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1443             output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1444             output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1445             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1446             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1447             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1448             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1449             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1450             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1451             output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1452             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1453             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1454             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1455             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1456             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1457             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1458             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1459             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1460             output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1461             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1462             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1463             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1464 #undef WDPTOLP
1465 #undef HDPTOLP
1466             if(output != lpOTM) {
1467                 memcpy(lpOTM, output, cbData);
1468                 HeapFree(GetProcessHeap(), 0, output);
1469                 ret = cbData;
1470             }
1471         }
1472     }
1473
1474     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1475               but really this should just be a return 0. */
1476
1477         ret = sizeof(*lpOTM);
1478         if (lpOTM) {
1479             if(cbData < ret)
1480                 ret = 0;
1481             else {
1482                 memset(lpOTM, 0, ret);
1483                 lpOTM->otmSize = sizeof(*lpOTM);
1484                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1485                 /*
1486                   Further fill of the structure not implemented,
1487                   Needs real values for the structure members
1488                 */
1489             }
1490         }
1491     }
1492     release_dc_ptr(dc);
1493     return ret;
1494 }
1495
1496
1497 /***********************************************************************
1498  *           GetCharWidthW      (GDI32.@)
1499  *           GetCharWidth32W    (GDI32.@)
1500  */
1501 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1502                                LPINT buffer )
1503 {
1504     UINT i;
1505     BOOL ret = FALSE;
1506     DC * dc = get_dc_ptr( hdc );
1507     if (!dc) return FALSE;
1508
1509     if (dc->gdiFont)
1510         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1511     else if (dc->funcs->pGetCharWidth)
1512         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1513
1514     if (ret)
1515     {
1516         /* convert device units to logical */
1517         for( i = firstChar; i <= lastChar; i++, buffer++ )
1518             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1519         ret = TRUE;
1520     }
1521     release_dc_ptr( dc );
1522     return ret;
1523 }
1524
1525
1526 /***********************************************************************
1527  *           GetCharWidthA      (GDI32.@)
1528  *           GetCharWidth32A    (GDI32.@)
1529  */
1530 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1531                                LPINT buffer )
1532 {
1533     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1534     LPSTR str;
1535     LPWSTR wstr;
1536     BOOL ret = TRUE;
1537
1538     if(count <= 0) return FALSE;
1539
1540     str = HeapAlloc(GetProcessHeap(), 0, count);
1541     for(i = 0; i < count; i++)
1542         str[i] = (BYTE)(firstChar + i);
1543
1544     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1545
1546     for(i = 0; i < wlen; i++)
1547     {
1548         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1549         {
1550             ret = FALSE;
1551             break;
1552         }
1553         buffer++;
1554     }
1555
1556     HeapFree(GetProcessHeap(), 0, str);
1557     HeapFree(GetProcessHeap(), 0, wstr);
1558
1559     return ret;
1560 }
1561
1562
1563 /***********************************************************************
1564  *           ExtTextOutA    (GDI32.@)
1565  *
1566  * See ExtTextOutW.
1567  */
1568 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1569                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1570 {
1571     INT wlen;
1572     UINT codepage;
1573     LPWSTR p;
1574     BOOL ret;
1575     LPINT lpDxW = NULL;
1576
1577     if (flags & ETO_GLYPH_INDEX)
1578         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1579
1580     p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1581
1582     if (lpDx) {
1583         unsigned int i = 0, j = 0;
1584
1585         lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1586         while(i < count) {
1587             if(IsDBCSLeadByteEx(codepage, str[i])) {
1588                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1589                 i = i + 2;
1590             } else {
1591                 lpDxW[j++] = lpDx[i];
1592                 i = i + 1;
1593             }
1594         }
1595     }
1596
1597     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1598
1599     HeapFree( GetProcessHeap(), 0, p );
1600     HeapFree( GetProcessHeap(), 0, lpDxW );
1601     return ret;
1602 }
1603
1604
1605 /***********************************************************************
1606  *           ExtTextOutW    (GDI32.@)
1607  *
1608  * Draws text using the currently selected font, background color, and text color.
1609  * 
1610  * 
1611  * PARAMS
1612  *    x,y    [I] coordinates of string
1613  *    flags  [I]
1614  *        ETO_GRAYED - undocumented on MSDN
1615  *        ETO_OPAQUE - use background color for fill the rectangle
1616  *        ETO_CLIPPED - clipping text to the rectangle
1617  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1618  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1619  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1620  *                         Affects BiDi ordering
1621  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1622  *        ETO_PDY - unimplemented
1623  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1624  *                            do not translate numbers into locale representations
1625  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1626  *    lprect [I] dimensions for clipping or/and opaquing
1627  *    str    [I] text string
1628  *    count  [I] number of symbols in string
1629  *    lpDx   [I] optional parameter with distance between drawing characters
1630  *
1631  * RETURNS
1632  *    Success: TRUE
1633  *    Failure: FALSE
1634  */
1635 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1636                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1637 {
1638     BOOL ret = FALSE;
1639     LPWSTR reordered_str = (LPWSTR)str;
1640     WORD *glyphs = NULL;
1641     UINT align = GetTextAlign( hdc );
1642     POINT pt;
1643     TEXTMETRICW tm;
1644     LOGFONTW lf;
1645     double cosEsc, sinEsc;
1646     INT *deltas = NULL, char_extra;
1647     SIZE sz;
1648     RECT rc;
1649     BOOL done_extents = FALSE;
1650     INT width = 0, xwidth = 0, ywidth = 0;
1651     DWORD type;
1652     DC * dc = get_dc_ptr( hdc );
1653     INT breakRem;
1654
1655     if (!dc) return FALSE;
1656
1657     breakRem = dc->breakRem;
1658
1659     if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1660         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1661
1662     if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1663     {
1664         release_dc_ptr( dc );
1665         return ret;
1666     }
1667
1668     update_dc( dc );
1669     type = GetObjectType(hdc);
1670     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1671     {
1672         ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1673         release_dc_ptr( dc );
1674         return ret;
1675     }
1676
1677     if (!lprect)
1678         flags &= ~ETO_CLIPPED;
1679         
1680     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1681     {
1682         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1683
1684         BIDI_Reorder( str, count, GCP_REORDER,
1685                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1686                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1687                       reordered_str, count, NULL );
1688     
1689         flags |= ETO_IGNORELANGUAGE;
1690     }
1691
1692     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1693           lprect, debugstr_wn(str, count), count, lpDx);
1694
1695     if(flags & ETO_GLYPH_INDEX)
1696         glyphs = reordered_str;
1697
1698     if(lprect)
1699         TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1700               lprect->bottom);
1701     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1702
1703     if(align & TA_UPDATECP)
1704     {
1705         GetCurrentPositionEx( hdc, &pt );
1706         x = pt.x;
1707         y = pt.y;
1708     }
1709
1710     GetTextMetricsW(hdc, &tm);
1711     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1712
1713     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1714         lf.lfEscapement = 0;
1715
1716     if(lf.lfEscapement != 0)
1717     {
1718         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1719         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1720     }
1721     else
1722     {
1723         cosEsc = 1;
1724         sinEsc = 0;
1725     }
1726
1727     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1728     {
1729         if(!lprect)
1730         {
1731             if(flags & ETO_GLYPH_INDEX)
1732                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1733             else
1734                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1735
1736             done_extents = TRUE;
1737             rc.left = x;
1738             rc.top = y;
1739             rc.right = x + sz.cx;
1740             rc.bottom = y + sz.cy;
1741         }
1742         else
1743         {
1744             rc = *lprect;
1745         }
1746
1747         LPtoDP(hdc, (POINT*)&rc, 2);
1748
1749         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1750         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1751     }
1752
1753     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1754         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1755
1756     if(count == 0)
1757     {
1758         ret = TRUE;
1759         goto done;
1760     }
1761
1762     pt.x = x;
1763     pt.y = y;
1764     LPtoDP(hdc, &pt, 1);
1765     x = pt.x;
1766     y = pt.y;
1767
1768     char_extra = GetTextCharacterExtra(hdc);
1769     if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1770     {
1771         UINT i;
1772         SIZE tmpsz;
1773         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1774         for(i = 0; i < count; i++)
1775         {
1776             if(lpDx && (flags & ETO_PDY))
1777                 deltas[i] = lpDx[i*2] + char_extra;
1778             else if(lpDx)
1779                 deltas[i] = lpDx[i] + char_extra;
1780             else
1781             {
1782                 if(flags & ETO_GLYPH_INDEX)
1783                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1784                 else
1785                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1786
1787                 deltas[i] = tmpsz.cx;
1788             }
1789             
1790             if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1791             {
1792                 deltas[i] = deltas[i] + dc->breakExtra;
1793                 if (breakRem > 0)
1794                 {
1795                     breakRem--;
1796                     deltas[i]++;
1797                 }
1798             }
1799             deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1800             width += deltas[i];
1801         }
1802     }
1803     else
1804     {
1805         if(!done_extents)
1806         {
1807             if(flags & ETO_GLYPH_INDEX)
1808                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1809             else
1810                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1811             done_extents = TRUE;
1812         }
1813         width = INTERNAL_XWSTODS(dc, sz.cx);
1814     }
1815     xwidth = width * cosEsc;
1816     ywidth = width * sinEsc;
1817
1818     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1819     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1820     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1821     {
1822     case TA_LEFT:
1823         if (align & TA_UPDATECP)
1824         {
1825             pt.x = x + xwidth;
1826             pt.y = y - ywidth;
1827             DPtoLP(hdc, &pt, 1);
1828             MoveToEx(hdc, pt.x, pt.y, NULL);
1829         }
1830         break;
1831
1832     case TA_CENTER:
1833         x -= xwidth / 2;
1834         y += ywidth / 2;
1835         break;
1836
1837     case TA_RIGHT:
1838         x -= xwidth;
1839         y += ywidth;
1840         if (align & TA_UPDATECP)
1841         {
1842             pt.x = x;
1843             pt.y = y;
1844             DPtoLP(hdc, &pt, 1);
1845             MoveToEx(hdc, pt.x, pt.y, NULL);
1846         }
1847         break;
1848     }
1849
1850     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1851     {
1852     case TA_TOP:
1853         y += tm.tmAscent * cosEsc;
1854         x += tm.tmAscent * sinEsc;
1855         break;
1856
1857     case TA_BOTTOM:
1858         y -= tm.tmDescent * cosEsc;
1859         x -= tm.tmDescent * sinEsc;
1860         break;
1861
1862     case TA_BASELINE:
1863         break;
1864     }
1865
1866     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1867     {
1868         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1869         {
1870             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1871                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1872             {
1873                 RECT rc;
1874                 rc.left = x;
1875                 rc.right = x + width;
1876                 rc.top = y - tm.tmAscent;
1877                 rc.bottom = y + tm.tmDescent;
1878                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1879             }
1880         }
1881     }
1882
1883     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1884     {
1885         HFONT orig_font = dc->hFont, cur_font;
1886         UINT glyph;
1887         INT span = 0, *offsets = NULL;
1888         unsigned int i;
1889
1890         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1891         for(i = 0; i < count; i++)
1892         {
1893             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1894             if(cur_font != dc->hFont)
1895             {
1896                 if(!offsets)
1897                 {
1898                     unsigned int j;
1899                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1900                     offsets[0] = 0;
1901                     if(!deltas)
1902                     {
1903                         SIZE tmpsz;
1904                         for(j = 1; j < count; j++)
1905                         {
1906                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1907                             offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1908                         }
1909                     }
1910                     else
1911                     {
1912                         for(j = 1; j < count; j++)
1913                             offsets[j] = offsets[j-1] + deltas[j];
1914                     }
1915                 }
1916                 if(span)
1917                 {
1918                     if (PATH_IsPathOpen(dc->path))
1919                         ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1920                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1921                                               glyphs, span, deltas ? deltas + i - span : NULL);
1922                     else
1923                         dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1924                                            (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1925                                            glyphs, span, deltas ? deltas + i - span : NULL);
1926                     span = 0;
1927                 }
1928                 SelectObject(hdc, cur_font);
1929             }
1930             glyphs[span++] = glyph;
1931
1932             if(i == count - 1)
1933             {
1934                 if (PATH_IsPathOpen(dc->path))
1935                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1936                                           y - (offsets ? offsets[count - span] * sinEsc : 0),
1937                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1938                                           glyphs, span, deltas ? deltas + count - span : NULL);
1939                 else
1940                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1941                                              y - (offsets ? offsets[count - span] * sinEsc : 0),
1942                                              (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1943                                              glyphs, span, deltas ? deltas + count - span : NULL);
1944                 SelectObject(hdc, orig_font);
1945                 HeapFree(GetProcessHeap(), 0, offsets);
1946            }
1947         }
1948     }
1949     else
1950     {
1951         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1952         {
1953             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1954             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1955             flags |= ETO_GLYPH_INDEX;
1956         }
1957
1958         if (PATH_IsPathOpen(dc->path))
1959             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1960                                   glyphs ? glyphs : reordered_str, count, deltas);
1961         else
1962             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1963                                      glyphs ? glyphs : reordered_str, count, deltas);
1964     }
1965
1966 done:
1967     HeapFree(GetProcessHeap(), 0, deltas);
1968     if(glyphs != reordered_str)
1969         HeapFree(GetProcessHeap(), 0, glyphs);
1970     if(reordered_str != str)
1971         HeapFree(GetProcessHeap(), 0, reordered_str);
1972
1973     release_dc_ptr( dc );
1974
1975     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
1976     {
1977         int underlinePos, strikeoutPos;
1978         int underlineWidth, strikeoutWidth;
1979         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
1980         OUTLINETEXTMETRICW* otm = NULL;
1981
1982         if(!size)
1983         {
1984             underlinePos = 0;
1985             underlineWidth = tm.tmAscent / 20 + 1;
1986             strikeoutPos = tm.tmAscent / 2;
1987             strikeoutWidth = underlineWidth;
1988         }
1989         else
1990         {
1991             otm = HeapAlloc(GetProcessHeap(), 0, size);
1992             GetOutlineTextMetricsW(hdc, size, otm);
1993             underlinePos = otm->otmsUnderscorePosition;
1994             underlineWidth = otm->otmsUnderscoreSize;
1995             strikeoutPos = otm->otmsStrikeoutPosition;
1996             strikeoutWidth = otm->otmsStrikeoutSize;
1997             HeapFree(GetProcessHeap(), 0, otm);
1998         }
1999
2000         if (PATH_IsPathOpen(dc->path))
2001         {
2002             POINT pts[5];
2003             HPEN hpen;
2004             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2005
2006             hbrush = SelectObject(hdc, hbrush);
2007             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2008
2009             if (lf.lfUnderline)
2010             {
2011                 pts[0].x = x - underlinePos * sinEsc;
2012                 pts[0].y = y - underlinePos * cosEsc;
2013                 pts[1].x = x + xwidth - underlinePos * sinEsc;
2014                 pts[1].y = y - ywidth - underlinePos * cosEsc;
2015                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2016                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2017                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2018                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2019                 pts[4].x = pts[0].x;
2020                 pts[4].y = pts[0].y;
2021                 DPtoLP(hdc, pts, 5);
2022                 Polygon(hdc, pts, 5);
2023             }
2024
2025             if (lf.lfStrikeOut)
2026             {
2027                 pts[0].x = x - strikeoutPos * sinEsc;
2028                 pts[0].y = y - strikeoutPos * cosEsc;
2029                 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2030                 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2031                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2032                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2033                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2034                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2035                 pts[4].x = pts[0].x;
2036                 pts[4].y = pts[0].y;
2037                 DPtoLP(hdc, pts, 5);
2038                 Polygon(hdc, pts, 5);
2039             }
2040
2041             SelectObject(hdc, hpen);
2042             hbrush = SelectObject(hdc, hbrush);
2043             DeleteObject(hbrush);
2044         }
2045         else
2046         {
2047             POINT pts[2], oldpt;
2048             HPEN hpen;
2049
2050             if (lf.lfUnderline)
2051             {
2052                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2053                 hpen = SelectObject(hdc, hpen);
2054                 pts[0].x = x;
2055                 pts[0].y = y;
2056                 pts[1].x = x + xwidth;
2057                 pts[1].y = y - ywidth;
2058                 DPtoLP(hdc, pts, 2);
2059                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2060                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2061                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2062                 DeleteObject(SelectObject(hdc, hpen));
2063             }
2064
2065             if (lf.lfStrikeOut)
2066             {
2067                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2068                 hpen = SelectObject(hdc, hpen);
2069                 pts[0].x = x;
2070                 pts[0].y = y;
2071                 pts[1].x = x + xwidth;
2072                 pts[1].y = y - ywidth;
2073                 DPtoLP(hdc, pts, 2);
2074                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2075                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2076                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2077                 DeleteObject(SelectObject(hdc, hpen));
2078             }
2079         }
2080     }
2081
2082     return ret;
2083 }
2084
2085
2086 /***********************************************************************
2087  *           TextOutA    (GDI32.@)
2088  */
2089 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2090 {
2091     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2092 }
2093
2094
2095 /***********************************************************************
2096  *           TextOutW    (GDI32.@)
2097  */
2098 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2099 {
2100     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2101 }
2102
2103
2104 /***********************************************************************
2105  *              PolyTextOutA (GDI32.@)
2106  *
2107  * See PolyTextOutW.
2108  */
2109 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2110 {
2111     for (; cStrings>0; cStrings--, pptxt++)
2112         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2113             return FALSE;
2114     return TRUE;
2115 }
2116
2117
2118
2119 /***********************************************************************
2120  *              PolyTextOutW (GDI32.@)
2121  *
2122  * Draw several Strings
2123  *
2124  * RETURNS
2125  *  TRUE:  Success.
2126  *  FALSE: Failure.
2127  */
2128 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2129 {
2130     for (; cStrings>0; cStrings--, pptxt++)
2131         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2132             return FALSE;
2133     return TRUE;
2134 }
2135
2136
2137 /* FIXME: all following APIs ******************************************/
2138
2139
2140 /***********************************************************************
2141  *           SetMapperFlags    (GDI32.@)
2142  */
2143 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2144 {
2145     DC *dc = get_dc_ptr( hDC );
2146     DWORD ret = 0;
2147     if(!dc) return 0;
2148     if(dc->funcs->pSetMapperFlags)
2149     {
2150         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2151         /* FIXME: ret is just a success flag, we should return a proper value */
2152     }
2153     else
2154         FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2155     release_dc_ptr( dc );
2156     return ret;
2157 }
2158
2159 /***********************************************************************
2160  *          GetAspectRatioFilterEx  (GDI32.@)
2161  */
2162 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2163 {
2164   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2165   return FALSE;
2166 }
2167
2168
2169 /***********************************************************************
2170  *           GetCharABCWidthsA   (GDI32.@)
2171  *
2172  * See GetCharABCWidthsW.
2173  */
2174 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2175                                   LPABC abc )
2176 {
2177     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2178     LPSTR str;
2179     LPWSTR wstr;
2180     BOOL ret = TRUE;
2181
2182     if(count <= 0) return FALSE;
2183
2184     str = HeapAlloc(GetProcessHeap(), 0, count);
2185     for(i = 0; i < count; i++)
2186         str[i] = (BYTE)(firstChar + i);
2187
2188     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2189
2190     for(i = 0; i < wlen; i++)
2191     {
2192         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2193         {
2194             ret = FALSE;
2195             break;
2196         }
2197         abc++;
2198     }
2199
2200     HeapFree(GetProcessHeap(), 0, str);
2201     HeapFree(GetProcessHeap(), 0, wstr);
2202
2203     return ret;
2204 }
2205
2206
2207 /******************************************************************************
2208  * GetCharABCWidthsW [GDI32.@]
2209  *
2210  * Retrieves widths of characters in range.
2211  *
2212  * PARAMS
2213  *    hdc       [I] Handle of device context
2214  *    firstChar [I] First character in range to query
2215  *    lastChar  [I] Last character in range to query
2216  *    abc       [O] Address of character-width structure
2217  *
2218  * NOTES
2219  *    Only works with TrueType fonts
2220  *
2221  * RETURNS
2222  *    Success: TRUE
2223  *    Failure: FALSE
2224  */
2225 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2226                                    LPABC abc )
2227 {
2228     DC *dc = get_dc_ptr(hdc);
2229     unsigned int i;
2230     BOOL ret = FALSE;
2231
2232     if (!dc) return FALSE;
2233
2234     if (!abc)
2235     {
2236         release_dc_ptr( dc );
2237         return FALSE;
2238     }
2239
2240     if(dc->gdiFont)
2241         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2242     else
2243         FIXME(": stub\n");
2244
2245     if (ret)
2246     {
2247         /* convert device units to logical */
2248         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2249             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2250             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2251             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2252         }
2253         ret = TRUE;
2254     }
2255
2256     release_dc_ptr( dc );
2257     return ret;
2258 }
2259
2260
2261 /******************************************************************************
2262  * GetCharABCWidthsI [GDI32.@]
2263  *
2264  * Retrieves widths of characters in range.
2265  *
2266  * PARAMS
2267  *    hdc       [I] Handle of device context
2268  *    firstChar [I] First glyphs in range to query
2269  *    count     [I] Last glyphs in range to query
2270  *    pgi       [i] Array of glyphs to query
2271  *    abc       [O] Address of character-width structure
2272  *
2273  * NOTES
2274  *    Only works with TrueType fonts
2275  *
2276  * RETURNS
2277  *    Success: TRUE
2278  *    Failure: FALSE
2279  */
2280 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2281                                LPWORD pgi, LPABC abc)
2282 {
2283     DC *dc = get_dc_ptr(hdc);
2284     unsigned int i;
2285     BOOL ret = FALSE;
2286
2287     if (!dc) return FALSE;
2288
2289     if (!abc)
2290     {
2291         release_dc_ptr( dc );
2292         return FALSE;
2293     }
2294
2295     if(dc->gdiFont)
2296         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2297     else
2298         FIXME(": stub\n");
2299
2300     if (ret)
2301     {
2302         /* convert device units to logical */
2303         for( i = 0; i < count; i++, abc++ ) {
2304             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2305             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2306             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2307         }
2308         ret = TRUE;
2309     }
2310
2311     release_dc_ptr( dc );
2312     return ret;
2313 }
2314
2315
2316 /***********************************************************************
2317  *           GetGlyphOutlineA    (GDI32.@)
2318  */
2319 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2320                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2321                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2322 {
2323     LPWSTR p = NULL;
2324     DWORD ret;
2325     UINT c;
2326
2327     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2328         int len;
2329         char mbchs[2];
2330         if(uChar > 0xff) { /* but, 2 bytes character only */
2331             len = 2;
2332             mbchs[0] = (uChar & 0xff00) >> 8;
2333             mbchs[1] = (uChar & 0xff);
2334         } else {
2335             len = 1;
2336             mbchs[0] = (uChar & 0xff);
2337         }
2338         p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2339         c = p[0];
2340     } else
2341         c = uChar;
2342     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2343                            lpmat2);
2344     HeapFree(GetProcessHeap(), 0, p);
2345     return ret;
2346 }
2347
2348 /***********************************************************************
2349  *           GetGlyphOutlineW    (GDI32.@)
2350  */
2351 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2352                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2353                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2354 {
2355     DC *dc = get_dc_ptr(hdc);
2356     DWORD ret;
2357
2358     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2359           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2360
2361     if(!dc) return GDI_ERROR;
2362
2363     if(dc->gdiFont)
2364       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2365                                    cbBuffer, lpBuffer, lpmat2);
2366     else
2367       ret = GDI_ERROR;
2368
2369     release_dc_ptr( dc );
2370     return ret;
2371 }
2372
2373
2374 /***********************************************************************
2375  *           CreateScalableFontResourceA   (GDI32.@)
2376  */
2377 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2378                                              LPCSTR lpszResourceFile,
2379                                              LPCSTR lpszFontFile,
2380                                              LPCSTR lpszCurrentPath )
2381 {
2382     LPWSTR lpszResourceFileW = NULL;
2383     LPWSTR lpszFontFileW = NULL;
2384     LPWSTR lpszCurrentPathW = NULL;
2385     int len;
2386     BOOL ret;
2387
2388     if (lpszResourceFile)
2389     {
2390         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2391         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2392         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2393     }
2394
2395     if (lpszFontFile)
2396     {
2397         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2398         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2399         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2400     }
2401
2402     if (lpszCurrentPath)
2403     {
2404         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2405         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2406         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2407     }
2408
2409     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2410             lpszFontFileW, lpszCurrentPathW);
2411
2412     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2413     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2414     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2415
2416     return ret;
2417 }
2418
2419 /***********************************************************************
2420  *           CreateScalableFontResourceW   (GDI32.@)
2421  */
2422 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2423                                              LPCWSTR lpszResourceFile,
2424                                              LPCWSTR lpszFontFile,
2425                                              LPCWSTR lpszCurrentPath )
2426 {
2427     HANDLE f;
2428     FIXME("(%d,%s,%s,%s): stub\n",
2429           fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2430           debugstr_w(lpszCurrentPath) );
2431
2432     /* fHidden=1 - only visible for the calling app, read-only, not
2433      * enumerated with EnumFonts/EnumFontFamilies
2434      * lpszCurrentPath can be NULL
2435      */
2436
2437     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2438     if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2439         CloseHandle(f);
2440         SetLastError(ERROR_FILE_EXISTS);
2441         return FALSE;
2442     }
2443     return FALSE; /* create failed */
2444 }
2445
2446 /*************************************************************************
2447  *             GetKerningPairsA   (GDI32.@)
2448  */
2449 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2450                                LPKERNINGPAIR kern_pairA )
2451 {
2452     INT charset;
2453     CHARSETINFO csi;
2454     CPINFO cpi;
2455     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2456     KERNINGPAIR *kern_pairW;
2457
2458     if (!cPairs && kern_pairA)
2459     {
2460         SetLastError(ERROR_INVALID_PARAMETER);
2461         return 0;
2462     }
2463
2464     charset = GetTextCharset(hDC);
2465     if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2466     {
2467         FIXME("Can't find codepage for charset %d\n", charset);
2468         return 0;
2469     }
2470     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2471      * to fail on an invalid character for CP_SYMBOL.
2472      */
2473     cpi.DefaultChar[0] = 0;
2474     if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2475     {
2476         FIXME("Can't find codepage %u info\n", csi.ciACP);
2477         return 0;
2478     }
2479     TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2480
2481     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2482     if (!total_kern_pairs) return 0;
2483
2484     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2485     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2486
2487     for (i = 0; i < total_kern_pairs; i++)
2488     {
2489         char first, second;
2490
2491         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2492             continue;
2493
2494         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2495             continue;
2496
2497         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2498             continue;
2499
2500         if (kern_pairA)
2501         {
2502             if (kern_pairs_copied >= cPairs) break;
2503
2504             kern_pairA->wFirst = (BYTE)first;
2505             kern_pairA->wSecond = (BYTE)second;
2506             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2507             kern_pairA++;
2508         }
2509         kern_pairs_copied++;
2510     }
2511
2512     HeapFree(GetProcessHeap(), 0, kern_pairW);
2513
2514     return kern_pairs_copied;
2515 }
2516
2517 /*************************************************************************
2518  *             GetKerningPairsW   (GDI32.@)
2519  */
2520 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2521                                  LPKERNINGPAIR lpKerningPairs )
2522 {
2523     DC *dc;
2524     DWORD ret = 0;
2525
2526     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2527
2528     if (!cPairs && lpKerningPairs)
2529     {
2530         SetLastError(ERROR_INVALID_PARAMETER);
2531         return 0;
2532     }
2533
2534     dc = get_dc_ptr(hDC);
2535     if (!dc) return 0;
2536
2537     if (dc->gdiFont)
2538         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2539
2540     release_dc_ptr( dc );
2541     return ret;
2542 }
2543
2544 /*************************************************************************
2545  * TranslateCharsetInfo [GDI32.@]
2546  *
2547  * Fills a CHARSETINFO structure for a character set, code page, or
2548  * font. This allows making the correspondence between different labels
2549  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2550  * of the same encoding.
2551  *
2552  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2553  * only one codepage should be set in *lpSrc.
2554  *
2555  * RETURNS
2556  *   TRUE on success, FALSE on failure.
2557  *
2558  */
2559 BOOL WINAPI TranslateCharsetInfo(
2560   LPDWORD lpSrc, /* [in]
2561        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2562        if flags == TCI_SRCCHARSET: a character set value
2563        if flags == TCI_SRCCODEPAGE: a code page value
2564                  */
2565   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2566   DWORD flags /* [in] determines interpretation of lpSrc */)
2567 {
2568     int index = 0;
2569     switch (flags) {
2570     case TCI_SRCFONTSIG:
2571         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2572       break;
2573     case TCI_SRCCODEPAGE:
2574       while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2575       break;
2576     case TCI_SRCCHARSET:
2577       while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2578       break;
2579     default:
2580       return FALSE;
2581     }
2582     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2583     *lpCs = FONT_tci[index];
2584     return TRUE;
2585 }
2586
2587 /*************************************************************************
2588  *             GetFontLanguageInfo   (GDI32.@)
2589  */
2590 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2591 {
2592         FONTSIGNATURE fontsig;
2593         static const DWORD GCP_DBCS_MASK=0x003F0000,
2594                 GCP_DIACRITIC_MASK=0x00000000,
2595                 FLI_GLYPHS_MASK=0x00000000,
2596                 GCP_GLYPHSHAPE_MASK=0x00000040,
2597                 GCP_KASHIDA_MASK=0x00000000,
2598                 GCP_LIGATE_MASK=0x00000000,
2599                 GCP_USEKERNING_MASK=0x00000000,
2600                 GCP_REORDER_MASK=0x00000060;
2601
2602         DWORD result=0;
2603
2604         GetTextCharsetInfo( hdc, &fontsig, 0 );
2605         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2606
2607         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2608                 result|=GCP_DBCS;
2609
2610         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2611                 result|=GCP_DIACRITIC;
2612
2613         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2614                 result|=FLI_GLYPHS;
2615
2616         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2617                 result|=GCP_GLYPHSHAPE;
2618
2619         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2620                 result|=GCP_KASHIDA;
2621
2622         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2623                 result|=GCP_LIGATE;
2624
2625         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2626                 result|=GCP_USEKERNING;
2627
2628         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2629         if( GetTextAlign( hdc) & TA_RTLREADING )
2630             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2631                     result|=GCP_REORDER;
2632
2633         return result;
2634 }
2635
2636
2637 /*************************************************************************
2638  * GetFontData [GDI32.@]
2639  *
2640  * Retrieve data for TrueType font.
2641  *
2642  * RETURNS
2643  *
2644  * success: Number of bytes returned
2645  * failure: GDI_ERROR
2646  *
2647  * NOTES
2648  *
2649  * Calls SetLastError()
2650  *
2651  */
2652 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2653     LPVOID buffer, DWORD length)
2654 {
2655     DC *dc = get_dc_ptr(hdc);
2656     DWORD ret = GDI_ERROR;
2657
2658     if(!dc) return GDI_ERROR;
2659
2660     if(dc->gdiFont)
2661       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2662
2663     release_dc_ptr( dc );
2664     return ret;
2665 }
2666
2667 /*************************************************************************
2668  * GetGlyphIndicesA [GDI32.@]
2669  */
2670 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2671                               LPWORD pgi, DWORD flags)
2672 {
2673     DWORD ret;
2674     WCHAR *lpstrW;
2675     INT countW;
2676
2677     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2678           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2679
2680     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2681     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2682     HeapFree(GetProcessHeap(), 0, lpstrW);
2683
2684     return ret;
2685 }
2686
2687 /*************************************************************************
2688  * GetGlyphIndicesW [GDI32.@]
2689  */
2690 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2691                               LPWORD pgi, DWORD flags)
2692 {
2693     DC *dc = get_dc_ptr(hdc);
2694     DWORD ret = GDI_ERROR;
2695
2696     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2697           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2698
2699     if(!dc) return GDI_ERROR;
2700
2701     if(dc->gdiFont)
2702         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2703
2704     release_dc_ptr( dc );
2705     return ret;
2706 }
2707
2708 /*************************************************************************
2709  * GetCharacterPlacementA [GDI32.@]
2710  *
2711  * See GetCharacterPlacementW.
2712  *
2713  * NOTES:
2714  *  the web browser control of ie4 calls this with dwFlags=0
2715  */
2716 DWORD WINAPI
2717 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2718                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2719                          DWORD dwFlags)
2720 {
2721     WCHAR *lpStringW;
2722     INT uCountW;
2723     GCP_RESULTSW resultsW;
2724     DWORD ret;
2725     UINT font_cp;
2726
2727     TRACE("%s, %d, %d, 0x%08x\n",
2728           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2729
2730     /* both structs are equal in size */
2731     memcpy(&resultsW, lpResults, sizeof(resultsW));
2732
2733     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2734     if(lpResults->lpOutString)
2735         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2736
2737     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2738
2739     lpResults->nGlyphs = resultsW.nGlyphs;
2740     lpResults->nMaxFit = resultsW.nMaxFit;
2741
2742     if(lpResults->lpOutString) {
2743         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2744                             lpResults->lpOutString, uCount, NULL, NULL );
2745     }
2746
2747     HeapFree(GetProcessHeap(), 0, lpStringW);
2748     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2749
2750     return ret;
2751 }
2752
2753 /*************************************************************************
2754  * GetCharacterPlacementW [GDI32.@]
2755  *
2756  *   Retrieve information about a string. This includes the width, reordering,
2757  *   Glyphing and so on.
2758  *
2759  * RETURNS
2760  *
2761  *   The width and height of the string if successful, 0 if failed.
2762  *
2763  * BUGS
2764  *
2765  *   All flags except GCP_REORDER are not yet implemented.
2766  *   Reordering is not 100% compliant to the Windows BiDi method.
2767  *   Caret positioning is not yet implemented for BiDi.
2768  *   Classes are not yet implemented.
2769  *
2770  */
2771 DWORD WINAPI
2772 GetCharacterPlacementW(
2773                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2774                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2775                 INT uCount,             /* [in] Number of WORDS in string. */
2776                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2777                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2778                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2779                 )
2780 {
2781     DWORD ret=0;
2782     SIZE size;
2783     UINT i, nSet;
2784
2785     TRACE("%s, %d, %d, 0x%08x\n",
2786           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2787
2788     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2789           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2790             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2791             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2792             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2793
2794     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
2795     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2796     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2797         FIXME("Caret positions for complex scripts not implemented\n");
2798
2799         nSet = (UINT)uCount;
2800         if(nSet > lpResults->nGlyphs)
2801                 nSet = lpResults->nGlyphs;
2802
2803         /* return number of initialized fields */
2804         lpResults->nGlyphs = nSet;
2805
2806         if((dwFlags&GCP_REORDER)==0 )
2807         {
2808                 /* Treat the case where no special handling was requested in a fastpath way */
2809                 /* copy will do if the GCP_REORDER flag is not set */
2810                 if(lpResults->lpOutString)
2811                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2812
2813                 if(lpResults->lpOrder)
2814                 {
2815                         for(i = 0; i < nSet; i++)
2816                                 lpResults->lpOrder[i] = i;
2817                 }
2818         } else
2819         {
2820             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2821                           nSet, lpResults->lpOrder );
2822         }
2823
2824         /* FIXME: Will use the placement chars */
2825         if (lpResults->lpDx)
2826         {
2827                 int c;
2828                 for (i = 0; i < nSet; i++)
2829                 {
2830                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2831                                 lpResults->lpDx[i]= c;
2832                 }
2833         }
2834
2835     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2836     {
2837         int pos = 0;
2838        
2839         lpResults->lpCaretPos[0] = 0;
2840         for (i = 1; i < nSet; i++)
2841             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2842                 lpResults->lpCaretPos[i] = (pos += size.cx);
2843     }
2844    
2845     if(lpResults->lpGlyphs)
2846         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2847
2848     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2849       ret = MAKELONG(size.cx, size.cy);
2850
2851     return ret;
2852 }
2853
2854 /*************************************************************************
2855  *      GetCharABCWidthsFloatA [GDI32.@]
2856  *
2857  * See GetCharABCWidthsFloatW.
2858  */
2859 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2860 {
2861     INT i, wlen, count = (INT)(last - first + 1);
2862     LPSTR str;
2863     LPWSTR wstr;
2864     BOOL ret = TRUE;
2865
2866     if (count <= 0) return FALSE;
2867
2868     str = HeapAlloc(GetProcessHeap(), 0, count);
2869
2870     for(i = 0; i < count; i++)
2871         str[i] = (BYTE)(first + i);
2872
2873     wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2874
2875     for (i = 0; i < wlen; i++)
2876     {
2877         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2878         {
2879             ret = FALSE;
2880             break;
2881         }
2882         abcf++;
2883     }
2884
2885     HeapFree( GetProcessHeap(), 0, str );
2886     HeapFree( GetProcessHeap(), 0, wstr );
2887
2888     return ret;
2889 }
2890
2891 /*************************************************************************
2892  *      GetCharABCWidthsFloatW [GDI32.@]
2893  *
2894  * Retrieves widths of a range of characters.
2895  *
2896  * PARAMS
2897  *    hdc   [I] Handle to device context.
2898  *    first [I] First character in range to query.
2899  *    last  [I] Last character in range to query.
2900  *    abcf  [O] Array of LPABCFLOAT structures.
2901  *
2902  * RETURNS
2903  *    Success: TRUE
2904  *    Failure: FALSE
2905  *
2906  * BUGS
2907  *    Only works with TrueType fonts. It also doesn't return real
2908  *    floats but converted integers because it's implemented on
2909  *    top of GetCharABCWidthsW.
2910  */
2911 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2912 {
2913     ABC *abc, *abc_base;
2914     unsigned int i, size = sizeof(ABC) * (last - first + 1);
2915     BOOL ret;
2916
2917     TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2918
2919     abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2920     if (!abc) return FALSE;
2921
2922     ret = GetCharABCWidthsW( hdc, first, last, abc );
2923     if (ret)
2924     {
2925         for (i = first; i <= last; i++, abc++, abcf++)
2926         {
2927             abcf->abcfA = abc->abcA;
2928             abcf->abcfB = abc->abcB;
2929             abcf->abcfC = abc->abcC;
2930         }
2931     }
2932     HeapFree( GetProcessHeap(), 0, abc_base );
2933     return ret;
2934 }
2935
2936 /*************************************************************************
2937  *      GetCharWidthFloatA [GDI32.@]
2938  */
2939 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2940                                     UINT iLastChar, PFLOAT pxBuffer)
2941 {
2942     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2943     return 0;
2944 }
2945
2946 /*************************************************************************
2947  *      GetCharWidthFloatW [GDI32.@]
2948  */
2949 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2950                                     UINT iLastChar, PFLOAT pxBuffer)
2951 {
2952     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2953     return 0;
2954 }
2955
2956
2957 /***********************************************************************
2958  *                                                                     *
2959  *           Font Resource API                                         *
2960  *                                                                     *
2961  ***********************************************************************/
2962
2963 /***********************************************************************
2964  *           AddFontResourceA    (GDI32.@)
2965  */
2966 INT WINAPI AddFontResourceA( LPCSTR str )
2967 {
2968     return AddFontResourceExA( str, 0, NULL);
2969 }
2970
2971 /***********************************************************************
2972  *           AddFontResourceW    (GDI32.@)
2973  */
2974 INT WINAPI AddFontResourceW( LPCWSTR str )
2975 {
2976     return AddFontResourceExW(str, 0, NULL);
2977 }
2978
2979
2980 /***********************************************************************
2981  *           AddFontResourceExA    (GDI32.@)
2982  */
2983 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2984 {
2985     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2986     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2987     INT ret;
2988
2989     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2990     ret = AddFontResourceExW(strW, fl, pdv);
2991     HeapFree(GetProcessHeap(), 0, strW);
2992     return ret;
2993 }
2994
2995 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
2996 {
2997     HRSRC rsrc = FindResourceW(hModule, name, type);
2998     HGLOBAL hMem = LoadResource(hModule, rsrc);
2999     LPVOID *pMem = LockResource(hMem);
3000     int *num_total = (int *)lParam;
3001     DWORD num_in_res;
3002
3003     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3004     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3005     {
3006         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3007         return FALSE;
3008     }
3009
3010     *num_total += num_in_res;
3011     return TRUE;
3012 }
3013
3014 /***********************************************************************
3015  *           AddFontResourceExW    (GDI32.@)
3016  */
3017 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3018 {
3019     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3020     if (ret == 0)
3021     {
3022         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3023         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3024         if (hModule != NULL)
3025         {
3026             int num_resources = 0;
3027             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3028
3029             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3030                 wine_dbgstr_w(str));
3031             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3032                 ret = num_resources;
3033             FreeLibrary(hModule);
3034         }
3035     }
3036     return ret;
3037 }
3038
3039 /***********************************************************************
3040  *           RemoveFontResourceA    (GDI32.@)
3041  */
3042 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3043 {
3044     return RemoveFontResourceExA(str, 0, 0);
3045 }
3046
3047 /***********************************************************************
3048  *           RemoveFontResourceW    (GDI32.@)
3049  */
3050 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3051 {
3052     return RemoveFontResourceExW(str, 0, 0);
3053 }
3054
3055 /***********************************************************************
3056  *           AddFontMemResourceEx    (GDI32.@)
3057  */
3058 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3059 {
3060     return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3061 }
3062
3063 /***********************************************************************
3064  *           RemoveFontMemResourceEx    (GDI32.@)
3065  */
3066 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3067 {
3068     FIXME("(%p) stub\n", fh);
3069     return TRUE;
3070 }
3071
3072 /***********************************************************************
3073  *           RemoveFontResourceExA    (GDI32.@)
3074  */
3075 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3076 {
3077     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3078     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3079     INT ret;
3080
3081     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3082     ret = RemoveFontResourceExW(strW, fl, pdv);
3083     HeapFree(GetProcessHeap(), 0, strW);
3084     return ret;
3085 }
3086
3087 /***********************************************************************
3088  *           RemoveFontResourceExW    (GDI32.@)
3089  */
3090 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3091 {
3092     return WineEngRemoveFontResourceEx(str, fl, pdv);
3093 }
3094
3095 /***********************************************************************
3096  *           GetTextCharset    (GDI32.@)
3097  */
3098 UINT WINAPI GetTextCharset(HDC hdc)
3099 {
3100     /* MSDN docs say this is equivalent */
3101     return GetTextCharsetInfo(hdc, NULL, 0);
3102 }
3103
3104 /***********************************************************************
3105  *           GetTextCharsetInfo    (GDI32.@)
3106  */
3107 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3108 {
3109     UINT ret = DEFAULT_CHARSET;
3110     DC *dc = get_dc_ptr(hdc);
3111
3112     if (dc)
3113     {
3114         if (dc->gdiFont)
3115             ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3116
3117         release_dc_ptr( dc );
3118     }
3119
3120     if (ret == DEFAULT_CHARSET && fs)
3121         memset(fs, 0, sizeof(FONTSIGNATURE));
3122     return ret;
3123 }
3124
3125 /***********************************************************************
3126  *           GdiGetCharDimensions    (GDI32.@)
3127  *
3128  * Gets the average width of the characters in the English alphabet.
3129  *
3130  * PARAMS
3131  *  hdc    [I] Handle to the device context to measure on.
3132  *  lptm   [O] Pointer to memory to store the text metrics into.
3133  *  height [O] On exit, the maximum height of characters in the English alphabet.
3134  *
3135  * RETURNS
3136  *  The average width of characters in the English alphabet.
3137  *
3138  * NOTES
3139  *  This function is used by the dialog manager to get the size of a dialog
3140  *  unit. It should also be used by other pieces of code that need to know
3141  *  the size of a dialog unit in logical units without having access to the
3142  *  window handle of the dialog.
3143  *  Windows caches the font metrics from this function, but we don't and
3144  *  there doesn't appear to be an immediate advantage to do so.
3145  *
3146  * SEE ALSO
3147  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3148  */
3149 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3150 {
3151     SIZE sz;
3152     static const WCHAR alphabet[] = {
3153         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3154         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3155         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3156
3157     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3158
3159     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3160
3161     if (height) *height = sz.cy;
3162     return (sz.cx / 26 + 1) / 2;
3163 }
3164
3165 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3166 {
3167     FIXME("(%d): stub\n", fEnableEUDC);
3168     return FALSE;
3169 }
3170
3171 /***********************************************************************
3172  *           GetCharWidthI    (GDI32.@)
3173  *
3174  * Retrieve widths of characters.
3175  *
3176  * PARAMS
3177  *  hdc    [I] Handle to a device context.
3178  *  first  [I] First glyph in range to query.
3179  *  count  [I] Number of glyph indices to query.
3180  *  glyphs [I] Array of glyphs to query.
3181  *  buffer [O] Buffer to receive character widths.
3182  *
3183  * NOTES
3184  *  Only works with TrueType fonts.
3185  *
3186  * RETURNS
3187  *  Success: TRUE
3188  *  Failure: FALSE
3189  */
3190 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3191 {
3192     ABC *abc;
3193     unsigned int i;
3194
3195     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3196
3197     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3198         return FALSE;
3199
3200     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3201     {
3202         HeapFree(GetProcessHeap(), 0, abc);
3203         return FALSE;
3204     }
3205
3206     for (i = 0; i < count; i++)
3207         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3208
3209     HeapFree(GetProcessHeap(), 0, abc);
3210     return TRUE;
3211 }
3212
3213 /***********************************************************************
3214  *           GetFontUnicodeRanges    (GDI32.@)
3215  *
3216  *  Retrieve a list of supported Unicode characters in a font.
3217  *
3218  *  PARAMS
3219  *   hdc  [I] Handle to a device context.
3220  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3221  *
3222  *  RETURNS
3223  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3224  *   Failure: 0
3225  *
3226  */
3227 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3228 {
3229     DWORD ret = 0;
3230     DC *dc = get_dc_ptr(hdc);
3231
3232     TRACE("(%p, %p)\n", hdc, lpgs);
3233
3234     if (!dc) return 0;
3235
3236     if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3237     release_dc_ptr(dc);
3238     return ret;
3239 }
3240
3241
3242 /*************************************************************
3243  *           FontIsLinked    (GDI32.@)
3244  */
3245 BOOL WINAPI FontIsLinked(HDC hdc)
3246 {
3247     DC *dc = get_dc_ptr(hdc);
3248     BOOL ret = FALSE;
3249
3250     if (!dc) return FALSE;
3251     if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3252     release_dc_ptr(dc);
3253     TRACE("returning %d\n", ret);
3254     return ret;
3255 }
3256
3257 /*************************************************************
3258  *           GdiRealizationInfo    (GDI32.@)
3259  *
3260  * Returns a structure that contains some font information.
3261  */
3262 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3263 {
3264     DC *dc = get_dc_ptr(hdc);
3265     BOOL ret = FALSE;
3266
3267     if (!dc) return FALSE;
3268     if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3269     release_dc_ptr(dc);
3270
3271     return ret;
3272 }