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