mshtml: Fix pointer cast warnings on 64-bit.
[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 (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
488     {
489         FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
490         dc->gdiFont = WineEngCreateFontInstance( dc, handle );
491         if (font) GDI_ReleaseObj( handle );
492     }
493
494     if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
495
496     if (ret && dc->gdiFont) dc->gdiFont = 0;
497
498     if (ret == HGDI_ERROR)
499     {
500         GDI_dec_ref_count( handle );
501         ret = 0; /* SelectObject returns 0 on error */
502     }
503     else
504     {
505         ret = dc->hFont;
506         dc->hFont = handle;
507         GDI_dec_ref_count( ret );
508     }
509     release_dc_ptr( dc );
510     return ret;
511 }
512
513
514 /***********************************************************************
515  *           FONT_GetObjectA
516  */
517 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
518 {
519     FONTOBJ *font = obj;
520     LOGFONTA lfA;
521
522     if(!buffer)
523         return sizeof(lfA);
524     FONT_LogFontWToA( &font->logfont, &lfA );
525
526     if (count > sizeof(lfA)) count = sizeof(lfA);
527     memcpy( buffer, &lfA, count );
528     return count;
529 }
530
531 /***********************************************************************
532  *           FONT_GetObjectW
533  */
534 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
535 {
536     FONTOBJ *font = obj;
537     if(!buffer)
538         return sizeof(LOGFONTW);
539     if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
540     memcpy( buffer, &font->logfont, count );
541     return count;
542 }
543
544
545 /***********************************************************************
546  *           FONT_DeleteObject
547  */
548 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
549 {
550     WineEngDestroyFontInstance( handle );
551     return GDI_FreeObject( handle, obj );
552 }
553
554
555 /***********************************************************************
556  *              FONT_EnumInstance
557  *
558  * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
559  *       We have to use other types because of the FONTENUMPROCW definition.
560  */
561 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
562                                        DWORD fType, LPARAM lp )
563 {
564     fontEnum32 *pfe = (fontEnum32*)lp;
565     INT ret = 1;
566
567     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
568     if ((!pfe->lpLogFontParam ||
569         pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
570         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
571        (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
572     {
573         /* convert font metrics */
574         ENUMLOGFONTEXA logfont;
575         NEWTEXTMETRICEXA tmA;
576
577         pfe->dwFlags |= ENUM_CALLED;
578         if (!(pfe->dwFlags & ENUM_UNICODE))
579         {
580             FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
581             FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
582             plf = (LOGFONTW *)&logfont.elfLogFont;
583             ptm = (TEXTMETRICW *)&tmA;
584         }
585
586         ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
587     }
588     return ret;
589 }
590
591 /***********************************************************************
592  *              FONT_EnumFontFamiliesEx
593  */
594 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
595                                     FONTENUMPROCW efproc,
596                                     LPARAM lParam, DWORD dwUnicode)
597 {
598     INT ret = 1, ret2;
599     DC *dc = get_dc_ptr( hDC );
600     fontEnum32 fe32;
601     BOOL enum_gdi_fonts;
602
603     if (!dc) return 0;
604
605     if (plf)
606         TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
607             plf->lfCharSet);
608     fe32.lpLogFontParam = plf;
609     fe32.lpEnumFunc = efproc;
610     fe32.lpData = lParam;
611     fe32.dwFlags = dwUnicode;
612     fe32.hdc = hDC;
613
614     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
615
616     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
617     {
618         ret = 0;
619         goto done;
620     }
621
622     if (enum_gdi_fonts)
623         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
624     fe32.dwFlags &= ~ENUM_CALLED;
625     if (ret && dc->funcs->pEnumDeviceFonts) {
626         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
627         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
628             ret = ret2;
629     }
630  done:
631     release_dc_ptr( dc );
632     return ret;
633 }
634
635 /***********************************************************************
636  *              EnumFontFamiliesExW     (GDI32.@)
637  */
638 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
639                                     FONTENUMPROCW efproc,
640                                     LPARAM lParam, DWORD dwFlags )
641 {
642     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
643 }
644
645 /***********************************************************************
646  *              EnumFontFamiliesExA     (GDI32.@)
647  */
648 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
649                                     FONTENUMPROCA efproc,
650                                     LPARAM lParam, DWORD dwFlags)
651 {
652     LOGFONTW lfW, *plfW;
653
654     if (plf)
655     {
656         FONT_LogFontAToW( plf, &lfW );
657         plfW = &lfW;
658     }
659     else plfW = NULL;
660
661     return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
662 }
663
664 /***********************************************************************
665  *              EnumFontFamiliesA       (GDI32.@)
666  */
667 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
668                                   FONTENUMPROCA efproc, LPARAM lpData )
669 {
670     LOGFONTA lf, *plf;
671
672     if (lpFamily)
673     {
674         if (!*lpFamily) return 1;
675         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
676         lf.lfCharSet = DEFAULT_CHARSET;
677         lf.lfPitchAndFamily = 0;
678         plf = &lf;
679     }
680     else plf = NULL;
681
682     return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
683 }
684
685 /***********************************************************************
686  *              EnumFontFamiliesW       (GDI32.@)
687  */
688 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
689                                   FONTENUMPROCW efproc, LPARAM lpData )
690 {
691     LOGFONTW lf, *plf;
692
693     if (lpFamily)
694     {
695         if (!*lpFamily) return 1;
696         lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
697         lf.lfCharSet = DEFAULT_CHARSET;
698         lf.lfPitchAndFamily = 0;
699         plf = &lf;
700     }
701     else plf = NULL;
702
703     return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
704 }
705
706 /***********************************************************************
707  *              EnumFontsA              (GDI32.@)
708  */
709 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
710                            LPARAM lpData )
711 {
712     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
713 }
714
715 /***********************************************************************
716  *              EnumFontsW              (GDI32.@)
717  */
718 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
719                            LPARAM lpData )
720 {
721     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
722 }
723
724
725 /***********************************************************************
726  *           GetTextCharacterExtra    (GDI32.@)
727  */
728 INT WINAPI GetTextCharacterExtra( HDC hdc )
729 {
730     INT ret;
731     DC *dc = get_dc_ptr( hdc );
732     if (!dc) return 0x80000000;
733     ret = dc->charExtra;
734     release_dc_ptr( dc );
735     return ret;
736 }
737
738
739 /***********************************************************************
740  *           SetTextCharacterExtra    (GDI32.@)
741  */
742 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
743 {
744     INT prev;
745     DC * dc = get_dc_ptr( hdc );
746     if (!dc) return 0x80000000;
747     if (dc->funcs->pSetTextCharacterExtra)
748         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
749     else
750     {
751         prev = dc->charExtra;
752         dc->charExtra = extra;
753     }
754     release_dc_ptr( dc );
755     return prev;
756 }
757
758
759 /***********************************************************************
760  *           SetTextJustification    (GDI32.@)
761  */
762 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
763 {
764     BOOL ret = TRUE;
765     DC * dc = get_dc_ptr( hdc );
766     if (!dc) return FALSE;
767     if (dc->funcs->pSetTextJustification)
768         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
769     else
770     {
771         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
772         if (!extra) breaks = 0;
773         if (breaks)
774         {
775             dc->breakExtra = extra / breaks;
776             dc->breakRem   = extra - (breaks * dc->breakExtra);
777         }
778         else
779         {
780             dc->breakExtra = 0;
781             dc->breakRem   = 0;
782         }
783     }
784     release_dc_ptr( dc );
785     return ret;
786 }
787
788
789 /***********************************************************************
790  *           GetTextFaceA    (GDI32.@)
791  */
792 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
793 {
794     INT res = GetTextFaceW(hdc, 0, NULL);
795     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
796     GetTextFaceW( hdc, res, nameW );
797
798     if (name)
799     {
800         if (count)
801         {
802             res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
803             if (res == 0)
804                 res = count;
805             name[count-1] = 0;
806             /* GetTextFaceA does NOT include the nul byte in the return count.  */
807             res--;
808         }
809         else
810             res = 0;
811     }
812     else
813         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
814     HeapFree( GetProcessHeap(), 0, nameW );
815     return res;
816 }
817
818 /***********************************************************************
819  *           GetTextFaceW    (GDI32.@)
820  */
821 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
822 {
823     FONTOBJ *font;
824     INT     ret = 0;
825
826     DC * dc = get_dc_ptr( hdc );
827     if (!dc) return 0;
828
829     if(dc->gdiFont)
830         ret = WineEngGetTextFace(dc->gdiFont, count, name);
831     else if ((font = GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
832     {
833         INT n = strlenW(font->logfont.lfFaceName) + 1;
834         if (name)
835         {
836             lstrcpynW( name, font->logfont.lfFaceName, count );
837             ret = min(count, n);
838         }
839         else ret = n;
840         GDI_ReleaseObj( dc->hFont );
841     }
842     release_dc_ptr( dc );
843     return ret;
844 }
845
846
847 /***********************************************************************
848  *           GetTextExtentPoint32A    (GDI32.@)
849  *
850  * See GetTextExtentPoint32W.
851  */
852 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
853                                      LPSIZE size )
854 {
855     BOOL ret = FALSE;
856     INT wlen;
857     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
858
859     if (p) {
860         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
861         HeapFree( GetProcessHeap(), 0, p );
862     }
863
864     TRACE("(%p %s %d %p): returning %d x %d\n",
865           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
866     return ret;
867 }
868
869
870 /***********************************************************************
871  * GetTextExtentPoint32W [GDI32.@]
872  *
873  * Computes width/height for a string.
874  *
875  * Computes width and height of the specified string.
876  *
877  * RETURNS
878  *    Success: TRUE
879  *    Failure: FALSE
880  */
881 BOOL WINAPI GetTextExtentPoint32W(
882     HDC hdc,     /* [in]  Handle of device context */
883     LPCWSTR str,   /* [in]  Address of text string */
884     INT count,   /* [in]  Number of characters in string */
885     LPSIZE size) /* [out] Address of structure for string size */
886 {
887     return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
888 }
889
890 /***********************************************************************
891  * GetTextExtentExPointI [GDI32.@]
892  *
893  * Computes width and height of the array of glyph indices.
894  *
895  * PARAMS
896  *    hdc     [I] Handle of device context.
897  *    indices [I] Glyph index array.
898  *    count   [I] Number of glyphs in array.
899  *    max_ext [I] Maximum width in glyphs.
900  *    nfit    [O] Maximum number of characters.
901  *    dxs     [O] Partial string widths.
902  *    size    [O] Returned string size.
903  *
904  * RETURNS
905  *    Success: TRUE
906  *    Failure: FALSE
907  */
908 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
909                                    LPINT nfit, LPINT dxs, LPSIZE size )
910 {
911     BOOL ret = FALSE;
912     DC * dc = get_dc_ptr( hdc );
913     if (!dc) return FALSE;
914
915     if(dc->gdiFont) {
916         ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
917         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
918         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
919         size->cx += count * dc->charExtra;
920     }
921     else if(dc->funcs->pGetTextExtentExPoint) {
922         FIXME("calling GetTextExtentExPoint\n");
923         ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
924                                                 count, max_ext, nfit, dxs, size );
925     }
926
927     release_dc_ptr( dc );
928
929     TRACE("(%p %p %d %p): returning %d x %d\n",
930           hdc, indices, count, size, size->cx, size->cy );
931     return ret;
932 }
933
934 /***********************************************************************
935  * GetTextExtentPointI [GDI32.@]
936  *
937  * Computes width and height of the array of glyph indices.
938  *
939  * PARAMS
940  *    hdc     [I] Handle of device context.
941  *    indices [I] Glyph index array.
942  *    count   [I] Number of glyphs in array.
943  *    size    [O] Returned string size.
944  *
945  * RETURNS
946  *    Success: TRUE
947  *    Failure: FALSE
948  */
949 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
950 {
951     return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
952 }
953
954
955 /***********************************************************************
956  *           GetTextExtentPointA    (GDI32.@)
957  */
958 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
959                                           LPSIZE size )
960 {
961     TRACE("not bug compatible.\n");
962     return GetTextExtentPoint32A( hdc, str, count, size );
963 }
964
965 /***********************************************************************
966  *           GetTextExtentPointW   (GDI32.@)
967  */
968 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
969                                           LPSIZE size )
970 {
971     TRACE("not bug compatible.\n");
972     return GetTextExtentPoint32W( hdc, str, count, size );
973 }
974
975
976 /***********************************************************************
977  *           GetTextExtentExPointA    (GDI32.@)
978  */
979 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
980                                    INT maxExt, LPINT lpnFit,
981                                    LPINT alpDx, LPSIZE size )
982 {
983     BOOL ret;
984     INT wlen;
985     INT *walpDx = NULL;
986     LPWSTR p = NULL;
987     
988     if (alpDx &&
989        NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
990        return FALSE;
991     
992     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
993     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
994     if (walpDx)
995     {
996         INT n = lpnFit ? *lpnFit : wlen;
997         INT i, j;
998         for(i = 0, j = 0; i < n; i++, j++)
999         {
1000             alpDx[j] = walpDx[i];
1001             if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1002         }
1003     }
1004     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1005     HeapFree( GetProcessHeap(), 0, p );
1006     HeapFree( GetProcessHeap(), 0, walpDx );
1007     return ret;
1008 }
1009
1010
1011 /***********************************************************************
1012  *           GetTextExtentExPointW    (GDI32.@)
1013  *
1014  * Return the size of the string as it would be if it was output properly by
1015  * e.g. TextOut.
1016  *
1017  * This should include
1018  * - Intercharacter spacing
1019  * - justification spacing (not yet done)
1020  * - kerning? see below
1021  *
1022  * Kerning.  Since kerning would be carried out by the rendering code it should
1023  * be done by the driver.  However they don't support it yet.  Also I am not
1024  * yet persuaded that (certainly under Win95) any kerning is actually done.
1025  *
1026  * str: According to MSDN this should be null-terminated.  That is not true; a
1027  *      null will not terminate it early.
1028  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1029  *       than count.  I have seen it be either the size of the full string or
1030  *       1 less than the size of the full string.  I have not seen it bear any
1031  *       resemblance to the portion that would fit.
1032  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1033  *         trailing intercharacter spacing and any trailing justification.
1034  *
1035  * FIXME
1036  * Currently we do this by measuring each character etc.  We should do it by
1037  * passing the request to the driver, perhaps by extending the
1038  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1039  * thinking about kerning issues and rounding issues in the justification.
1040  */
1041
1042 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1043                                    INT maxExt, LPINT lpnFit,
1044                                    LPINT alpDx, LPSIZE size )
1045 {
1046     INT nFit = 0;
1047     LPINT dxs = NULL;
1048     DC *dc;
1049     BOOL ret = FALSE;
1050     TEXTMETRICW tm;
1051
1052     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1053
1054     dc = get_dc_ptr(hdc);
1055     if (! dc)
1056         return FALSE;
1057
1058     GetTextMetricsW(hdc, &tm);
1059
1060     /* If we need to calculate nFit, then we need the partial extents even if
1061        the user hasn't provided us with an array.  */
1062     if (lpnFit)
1063     {
1064         dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1065         if (! dxs)
1066         {
1067             release_dc_ptr(dc);
1068             SetLastError(ERROR_OUTOFMEMORY);
1069             return FALSE;
1070         }
1071     }
1072     else
1073         dxs = alpDx;
1074
1075     if (dc->gdiFont)
1076         ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1077                                           0, NULL, dxs, size);
1078     else if (dc->funcs->pGetTextExtentExPoint)
1079         ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1080                                                0, NULL, dxs, size);
1081
1082     /* Perform device size to world size transformations.  */
1083     if (ret)
1084     {
1085         INT extra      = dc->charExtra,
1086         breakExtra = dc->breakExtra,
1087         breakRem   = dc->breakRem,
1088         i;
1089
1090         if (dxs)
1091         {
1092             for (i = 0; i < count; ++i)
1093             {
1094                 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1095                 dxs[i] += (i+1) * extra;
1096                 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1097                 {
1098                     dxs[i] += breakExtra;
1099                     if (breakRem > 0)
1100                     {
1101                         breakRem--;
1102                         dxs[i]++;
1103                     }
1104                 }
1105                 if (dxs[i] <= maxExt)
1106                     ++nFit;
1107             }
1108             breakRem = dc->breakRem;
1109         }
1110         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1111         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1112
1113         if (!dxs && count > 1 && (breakExtra || breakRem))
1114         {
1115             for (i = 0; i < count; i++)
1116             {
1117                 if (str[i] == tm.tmBreakChar)
1118                 {
1119                     size->cx += breakExtra;
1120                     if (breakRem > 0)
1121                     {
1122                         breakRem--;
1123                         (size->cx)++;
1124                     }
1125                 }
1126             }
1127         }
1128     }
1129
1130     if (lpnFit)
1131         *lpnFit = nFit;
1132
1133     if (! alpDx)
1134         HeapFree(GetProcessHeap(), 0, dxs);
1135
1136     release_dc_ptr( dc );
1137
1138     TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1139     return ret;
1140 }
1141
1142 /***********************************************************************
1143  *           GetTextMetricsA    (GDI32.@)
1144  */
1145 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1146 {
1147     TEXTMETRICW tm32;
1148
1149     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1150     FONT_TextMetricWToA( &tm32, metrics );
1151     return TRUE;
1152 }
1153
1154 /***********************************************************************
1155  *           GetTextMetricsW    (GDI32.@)
1156  */
1157 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1158 {
1159     BOOL ret = FALSE;
1160     DC * dc = get_dc_ptr( hdc );
1161     if (!dc) return FALSE;
1162
1163     if (dc->gdiFont)
1164         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1165     else if (dc->funcs->pGetTextMetrics)
1166         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1167
1168     if (ret)
1169     {
1170     /* device layer returns values in device units
1171      * therefore we have to convert them to logical */
1172
1173         metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1174         metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1175
1176 #define WDPTOLP(x) ((x<0)?                                      \
1177                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1178                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1179 #define HDPTOLP(y) ((y<0)?                                      \
1180                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1181                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1182
1183     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1184     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1185     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1186     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1187     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1188     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1189     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1190     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1191         ret = TRUE;
1192 #undef WDPTOLP
1193 #undef HDPTOLP
1194     TRACE("text metrics:\n"
1195           "    Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1196           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1197           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1198           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1199           "    PitchAndFamily = %02x\n"
1200           "    --------------------\n"
1201           "    InternalLeading = %i\n"
1202           "    Ascent = %i\n"
1203           "    Descent = %i\n"
1204           "    Height = %i\n",
1205           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1206           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1207           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1208           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1209           metrics->tmPitchAndFamily,
1210           metrics->tmInternalLeading,
1211           metrics->tmAscent,
1212           metrics->tmDescent,
1213           metrics->tmHeight );
1214     }
1215     release_dc_ptr( dc );
1216     return ret;
1217 }
1218
1219
1220 /***********************************************************************
1221  *              GetOutlineTextMetricsA (GDI32.@)
1222  * Gets metrics for TrueType fonts.
1223  *
1224  * NOTES
1225  *    If the supplied buffer isn't big enough Windows partially fills it up to
1226  *    its given length and returns that length.
1227  *
1228  * RETURNS
1229  *    Success: Non-zero or size of required buffer
1230  *    Failure: 0
1231  */
1232 UINT WINAPI GetOutlineTextMetricsA(
1233     HDC hdc,    /* [in]  Handle of device context */
1234     UINT cbData, /* [in]  Size of metric data array */
1235     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1236 {
1237     char buf[512], *ptr;
1238     UINT ret, needed;
1239     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1240     OUTLINETEXTMETRICA *output = lpOTM;
1241     INT left, len;
1242
1243     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1244         return 0;
1245     if(ret > sizeof(buf))
1246         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1247     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1248
1249     needed = sizeof(OUTLINETEXTMETRICA);
1250     if(lpOTMW->otmpFamilyName)
1251         needed += WideCharToMultiByte(CP_ACP, 0,
1252            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1253                                       NULL, 0, NULL, NULL);
1254     if(lpOTMW->otmpFaceName)
1255         needed += WideCharToMultiByte(CP_ACP, 0,
1256            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1257                                       NULL, 0, NULL, NULL);
1258     if(lpOTMW->otmpStyleName)
1259         needed += WideCharToMultiByte(CP_ACP, 0,
1260            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1261                                       NULL, 0, NULL, NULL);
1262     if(lpOTMW->otmpFullName)
1263         needed += WideCharToMultiByte(CP_ACP, 0,
1264            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1265                                       NULL, 0, NULL, NULL);
1266
1267     if(!lpOTM) {
1268         ret = needed;
1269         goto end;
1270     }
1271
1272     TRACE("needed = %d\n", needed);
1273     if(needed > cbData)
1274         /* Since the supplied buffer isn't big enough, we'll alloc one
1275            that is and memcpy the first cbData bytes into the lpOTM at
1276            the end. */
1277         output = HeapAlloc(GetProcessHeap(), 0, needed);
1278
1279     ret = output->otmSize = min(needed, cbData);
1280     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1281     output->otmFiller = 0;
1282     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1283     output->otmfsSelection = lpOTMW->otmfsSelection;
1284     output->otmfsType = lpOTMW->otmfsType;
1285     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1286     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1287     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1288     output->otmEMSquare = lpOTMW->otmEMSquare;
1289     output->otmAscent = lpOTMW->otmAscent;
1290     output->otmDescent = lpOTMW->otmDescent;
1291     output->otmLineGap = lpOTMW->otmLineGap;
1292     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1293     output->otmsXHeight = lpOTMW->otmsXHeight;
1294     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1295     output->otmMacAscent = lpOTMW->otmMacAscent;
1296     output->otmMacDescent = lpOTMW->otmMacDescent;
1297     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1298     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1299     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1300     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1301     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1302     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1303     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1304     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1305     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1306     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1307
1308
1309     ptr = (char*)(output + 1);
1310     left = needed - sizeof(*output);
1311
1312     if(lpOTMW->otmpFamilyName) {
1313         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1314         len = WideCharToMultiByte(CP_ACP, 0,
1315              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1316                                   ptr, left, NULL, NULL);
1317         left -= len;
1318         ptr += len;
1319     } else
1320         output->otmpFamilyName = 0;
1321
1322     if(lpOTMW->otmpFaceName) {
1323         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1324         len = WideCharToMultiByte(CP_ACP, 0,
1325              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1326                                   ptr, left, NULL, NULL);
1327         left -= len;
1328         ptr += len;
1329     } else
1330         output->otmpFaceName = 0;
1331
1332     if(lpOTMW->otmpStyleName) {
1333         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1334         len = WideCharToMultiByte(CP_ACP, 0,
1335              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1336                                   ptr, left, NULL, NULL);
1337         left -= len;
1338         ptr += len;
1339     } else
1340         output->otmpStyleName = 0;
1341
1342     if(lpOTMW->otmpFullName) {
1343         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1344         len = WideCharToMultiByte(CP_ACP, 0,
1345              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1346                                   ptr, left, NULL, NULL);
1347         left -= len;
1348     } else
1349         output->otmpFullName = 0;
1350
1351     assert(left == 0);
1352
1353     if(output != lpOTM) {
1354         memcpy(lpOTM, output, cbData);
1355         HeapFree(GetProcessHeap(), 0, output);
1356
1357         /* check if the string offsets really fit into the provided size */
1358         /* FIXME: should we check string length as well? */
1359         /* make sure that we don't read/write beyond the provided buffer */
1360         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1361         {
1362             if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1363                 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1364         }
1365
1366         /* make sure that we don't read/write beyond the provided buffer */
1367         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1368         {
1369             if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1370                 lpOTM->otmpFaceName = 0; /* doesn't fit */
1371         }
1372
1373             /* make sure that we don't read/write beyond the provided buffer */
1374         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1375         {
1376             if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1377                 lpOTM->otmpStyleName = 0; /* doesn't fit */
1378         }
1379
1380         /* make sure that we don't read/write beyond the provided buffer */
1381         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1382         {
1383             if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1384                 lpOTM->otmpFullName = 0; /* doesn't fit */
1385         }
1386     }
1387
1388 end:
1389     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1390         HeapFree(GetProcessHeap(), 0, lpOTMW);
1391
1392     return ret;
1393 }
1394
1395
1396 /***********************************************************************
1397  *           GetOutlineTextMetricsW [GDI32.@]
1398  */
1399 UINT WINAPI GetOutlineTextMetricsW(
1400     HDC hdc,    /* [in]  Handle of device context */
1401     UINT cbData, /* [in]  Size of metric data array */
1402     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1403 {
1404     DC *dc = get_dc_ptr( hdc );
1405     OUTLINETEXTMETRICW *output = lpOTM;
1406     UINT ret;
1407
1408     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1409     if(!dc) return 0;
1410
1411     if(dc->gdiFont) {
1412         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1413         if(lpOTM && ret) {
1414             if(ret > cbData) {
1415                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1416                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1417             }
1418
1419         output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1420         output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1421
1422 #define WDPTOLP(x) ((x<0)?                                      \
1423                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1424                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1425 #define HDPTOLP(y) ((y<0)?                                      \
1426                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1427                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1428
1429             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1430             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1431             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1432             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1433             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1434             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1435             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1436             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1437             output->otmAscent = HDPTOLP(output->otmAscent);
1438             output->otmDescent = HDPTOLP(output->otmDescent);
1439             output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1440             output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1441             output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1442             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1443             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1444             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1445             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1446             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1447             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1448             output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1449             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1450             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1451             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1452             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1453             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1454             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1455             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1456             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1457             output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1458             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1459             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1460             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1461 #undef WDPTOLP
1462 #undef HDPTOLP
1463             if(output != lpOTM) {
1464                 memcpy(lpOTM, output, cbData);
1465                 HeapFree(GetProcessHeap(), 0, output);
1466                 ret = cbData;
1467             }
1468         }
1469     }
1470
1471     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1472               but really this should just be a return 0. */
1473
1474         ret = sizeof(*lpOTM);
1475         if (lpOTM) {
1476             if(cbData < ret)
1477                 ret = 0;
1478             else {
1479                 memset(lpOTM, 0, ret);
1480                 lpOTM->otmSize = sizeof(*lpOTM);
1481                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1482                 /*
1483                   Further fill of the structure not implemented,
1484                   Needs real values for the structure members
1485                 */
1486             }
1487         }
1488     }
1489     release_dc_ptr(dc);
1490     return ret;
1491 }
1492
1493
1494 /***********************************************************************
1495  *           GetCharWidthW      (GDI32.@)
1496  *           GetCharWidth32W    (GDI32.@)
1497  */
1498 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1499                                LPINT buffer )
1500 {
1501     UINT i;
1502     BOOL ret = FALSE;
1503     DC * dc = get_dc_ptr( hdc );
1504     if (!dc) return FALSE;
1505
1506     if (dc->gdiFont)
1507         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1508     else if (dc->funcs->pGetCharWidth)
1509         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1510
1511     if (ret)
1512     {
1513         /* convert device units to logical */
1514         for( i = firstChar; i <= lastChar; i++, buffer++ )
1515             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1516         ret = TRUE;
1517     }
1518     release_dc_ptr( dc );
1519     return ret;
1520 }
1521
1522
1523 /***********************************************************************
1524  *           GetCharWidthA      (GDI32.@)
1525  *           GetCharWidth32A    (GDI32.@)
1526  */
1527 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1528                                LPINT buffer )
1529 {
1530     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1531     LPSTR str;
1532     LPWSTR wstr;
1533     BOOL ret = TRUE;
1534
1535     if(count <= 0) return FALSE;
1536
1537     str = HeapAlloc(GetProcessHeap(), 0, count);
1538     for(i = 0; i < count; i++)
1539         str[i] = (BYTE)(firstChar + i);
1540
1541     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1542
1543     for(i = 0; i < wlen; i++)
1544     {
1545         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1546         {
1547             ret = FALSE;
1548             break;
1549         }
1550         buffer++;
1551     }
1552
1553     HeapFree(GetProcessHeap(), 0, str);
1554     HeapFree(GetProcessHeap(), 0, wstr);
1555
1556     return ret;
1557 }
1558
1559
1560 /***********************************************************************
1561  *           ExtTextOutA    (GDI32.@)
1562  *
1563  * See ExtTextOutW.
1564  */
1565 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1566                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1567 {
1568     INT wlen;
1569     UINT codepage;
1570     LPWSTR p;
1571     BOOL ret;
1572     LPINT lpDxW = NULL;
1573
1574     if (flags & ETO_GLYPH_INDEX)
1575         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1576
1577     p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1578
1579     if (lpDx) {
1580         unsigned int i = 0, j = 0;
1581
1582         lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1583         while(i < count) {
1584             if(IsDBCSLeadByteEx(codepage, str[i])) {
1585                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1586                 i = i + 2;
1587             } else {
1588                 lpDxW[j++] = lpDx[i];
1589                 i = i + 1;
1590             }
1591         }
1592     }
1593
1594     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1595
1596     HeapFree( GetProcessHeap(), 0, p );
1597     HeapFree( GetProcessHeap(), 0, lpDxW );
1598     return ret;
1599 }
1600
1601
1602 /***********************************************************************
1603  *           ExtTextOutW    (GDI32.@)
1604  *
1605  * Draws text using the currently selected font, background color, and text color.
1606  * 
1607  * 
1608  * PARAMS
1609  *    x,y    [I] coordinates of string
1610  *    flags  [I]
1611  *        ETO_GRAYED - undocumented on MSDN
1612  *        ETO_OPAQUE - use background color for fill the rectangle
1613  *        ETO_CLIPPED - clipping text to the rectangle
1614  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1615  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1616  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1617  *                         Affects BiDi ordering
1618  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1619  *        ETO_PDY - unimplemented
1620  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1621  *                            do not translate numbers into locale representations
1622  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1623  *    lprect [I] dimensions for clipping or/and opaquing
1624  *    str    [I] text string
1625  *    count  [I] number of symbols in string
1626  *    lpDx   [I] optional parameter with distance between drawing characters
1627  *
1628  * RETURNS
1629  *    Success: TRUE
1630  *    Failure: FALSE
1631  */
1632 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1633                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1634 {
1635     BOOL ret = FALSE;
1636     LPWSTR reordered_str = (LPWSTR)str;
1637     WORD *glyphs = NULL;
1638     UINT align = GetTextAlign( hdc );
1639     POINT pt;
1640     TEXTMETRICW tm;
1641     LOGFONTW lf;
1642     double cosEsc, sinEsc;
1643     INT *deltas = NULL, char_extra;
1644     SIZE sz;
1645     RECT rc;
1646     BOOL done_extents = FALSE;
1647     INT width = 0, xwidth = 0, ywidth = 0;
1648     DWORD type;
1649     DC * dc = get_dc_ptr( hdc );
1650     INT breakRem;
1651     static int quietfixme = 0;
1652
1653     if (!dc) return FALSE;
1654
1655     breakRem = dc->breakRem;
1656
1657     if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1658     {
1659         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1660         quietfixme = 1;
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 }