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