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