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