gdi32: Add a string table resource for the translation.
[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 = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2099             if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2100             underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2101             if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2102             strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2103             if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2104             strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2105             HeapFree(GetProcessHeap(), 0, otm);
2106         }
2107
2108
2109         if (lf.lfUnderline)
2110         {
2111             pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2112             pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2113             pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2114             pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2115             pts[2].x = pts[1].x + underlineWidth * sinEsc;
2116             pts[2].y = pts[1].y + underlineWidth * cosEsc;
2117             pts[3].x = pts[0].x + underlineWidth * sinEsc;
2118             pts[3].y = pts[0].y + underlineWidth * cosEsc;
2119             pts[4].x = pts[0].x;
2120             pts[4].y = pts[0].y;
2121             DPtoLP(hdc, pts, 5);
2122             Polygon(hdc, pts, 5);
2123         }
2124
2125         if (lf.lfStrikeOut)
2126         {
2127             pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2128             pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2129             pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2130             pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2131             pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2132             pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2133             pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2134             pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2135             pts[4].x = pts[0].x;
2136             pts[4].y = pts[0].y;
2137             DPtoLP(hdc, pts, 5);
2138             Polygon(hdc, pts, 5);
2139         }
2140
2141         SelectObject(hdc, hpen);
2142         hbrush = SelectObject(hdc, hbrush);
2143         DeleteObject(hbrush);
2144     }
2145
2146     return ret;
2147 }
2148
2149
2150 /***********************************************************************
2151  *           TextOutA    (GDI32.@)
2152  */
2153 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2154 {
2155     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2156 }
2157
2158
2159 /***********************************************************************
2160  *           TextOutW    (GDI32.@)
2161  */
2162 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2163 {
2164     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2165 }
2166
2167
2168 /***********************************************************************
2169  *              PolyTextOutA (GDI32.@)
2170  *
2171  * See PolyTextOutW.
2172  */
2173 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2174 {
2175     for (; cStrings>0; cStrings--, pptxt++)
2176         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2177             return FALSE;
2178     return TRUE;
2179 }
2180
2181
2182
2183 /***********************************************************************
2184  *              PolyTextOutW (GDI32.@)
2185  *
2186  * Draw several Strings
2187  *
2188  * RETURNS
2189  *  TRUE:  Success.
2190  *  FALSE: Failure.
2191  */
2192 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2193 {
2194     for (; cStrings>0; cStrings--, pptxt++)
2195         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2196             return FALSE;
2197     return TRUE;
2198 }
2199
2200
2201 /***********************************************************************
2202  *           SetMapperFlags    (GDI32.@)
2203  */
2204 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2205 {
2206     DC *dc = get_dc_ptr( hdc );
2207     DWORD ret = GDI_ERROR;
2208
2209     if (dc)
2210     {
2211         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2212         flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2213         if (flags != GDI_ERROR)
2214         {
2215             ret = dc->mapperFlags;
2216             dc->mapperFlags = flags;
2217         }
2218         release_dc_ptr( dc );
2219     }
2220     return ret;
2221 }
2222
2223 /***********************************************************************
2224  *          GetAspectRatioFilterEx  (GDI32.@)
2225  */
2226 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2227 {
2228   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2229   return FALSE;
2230 }
2231
2232
2233 /***********************************************************************
2234  *           GetCharABCWidthsA   (GDI32.@)
2235  *
2236  * See GetCharABCWidthsW.
2237  */
2238 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2239                                   LPABC abc )
2240 {
2241     INT i, wlen;
2242     LPSTR str;
2243     LPWSTR wstr;
2244     BOOL ret = TRUE;
2245
2246     str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2247     if (str == NULL)
2248         return FALSE;
2249
2250     wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2251     if (wstr == NULL)
2252     {
2253         HeapFree(GetProcessHeap(), 0, str);
2254         return FALSE;
2255     }
2256
2257     for(i = 0; i < wlen; i++)
2258     {
2259         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2260         {
2261             ret = FALSE;
2262             break;
2263         }
2264         abc++;
2265     }
2266
2267     HeapFree(GetProcessHeap(), 0, str);
2268     HeapFree(GetProcessHeap(), 0, wstr);
2269
2270     return ret;
2271 }
2272
2273
2274 /******************************************************************************
2275  * GetCharABCWidthsW [GDI32.@]
2276  *
2277  * Retrieves widths of characters in range.
2278  *
2279  * PARAMS
2280  *    hdc       [I] Handle of device context
2281  *    firstChar [I] First character in range to query
2282  *    lastChar  [I] Last character in range to query
2283  *    abc       [O] Address of character-width structure
2284  *
2285  * NOTES
2286  *    Only works with TrueType fonts
2287  *
2288  * RETURNS
2289  *    Success: TRUE
2290  *    Failure: FALSE
2291  */
2292 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2293                                    LPABC abc )
2294 {
2295     DC *dc = get_dc_ptr(hdc);
2296     PHYSDEV dev;
2297     unsigned int i;
2298     BOOL ret;
2299
2300     if (!dc) return FALSE;
2301
2302     if (!abc)
2303     {
2304         release_dc_ptr( dc );
2305         return FALSE;
2306     }
2307
2308     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2309     ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2310     if (ret)
2311     {
2312         /* convert device units to logical */
2313         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2314             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2315             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2316             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2317         }
2318     }
2319
2320     release_dc_ptr( dc );
2321     return ret;
2322 }
2323
2324
2325 /******************************************************************************
2326  * GetCharABCWidthsI [GDI32.@]
2327  *
2328  * Retrieves widths of characters in range.
2329  *
2330  * PARAMS
2331  *    hdc       [I] Handle of device context
2332  *    firstChar [I] First glyphs in range to query
2333  *    count     [I] Last glyphs in range to query
2334  *    pgi       [i] Array of glyphs to query
2335  *    abc       [O] Address of character-width structure
2336  *
2337  * NOTES
2338  *    Only works with TrueType fonts
2339  *
2340  * RETURNS
2341  *    Success: TRUE
2342  *    Failure: FALSE
2343  */
2344 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2345                                LPWORD pgi, LPABC abc)
2346 {
2347     DC *dc = get_dc_ptr(hdc);
2348     PHYSDEV dev;
2349     unsigned int i;
2350     BOOL ret;
2351
2352     if (!dc) return FALSE;
2353
2354     if (!abc)
2355     {
2356         release_dc_ptr( dc );
2357         return FALSE;
2358     }
2359
2360     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2361     ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2362     if (ret)
2363     {
2364         /* convert device units to logical */
2365         for( i = 0; i < count; i++, abc++ ) {
2366             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2367             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2368             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2369         }
2370     }
2371
2372     release_dc_ptr( dc );
2373     return ret;
2374 }
2375
2376
2377 /***********************************************************************
2378  *           GetGlyphOutlineA    (GDI32.@)
2379  */
2380 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2381                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2382                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2383 {
2384     if (!lpmat2) return GDI_ERROR;
2385
2386     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2387         UINT cp;
2388         int len;
2389         char mbchs[2];
2390
2391         cp = GdiGetCodePage(hdc);
2392         if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2393             len = 2;
2394             mbchs[0] = (uChar & 0xff00) >> 8;
2395             mbchs[1] = (uChar & 0xff);
2396         } else {
2397             len = 1;
2398             mbchs[0] = (uChar & 0xff);
2399         }
2400         uChar = 0;
2401         MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2402     }
2403
2404     return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2405                             lpmat2);
2406 }
2407
2408 /***********************************************************************
2409  *           GetGlyphOutlineW    (GDI32.@)
2410  */
2411 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2412                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2413                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2414 {
2415     DC *dc;
2416     DWORD ret;
2417     PHYSDEV dev;
2418
2419     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2420           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2421
2422     if (!lpmat2) return GDI_ERROR;
2423
2424     dc = get_dc_ptr(hdc);
2425     if(!dc) return GDI_ERROR;
2426
2427     dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2428     ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2429     release_dc_ptr( dc );
2430     return ret;
2431 }
2432
2433
2434 /***********************************************************************
2435  *           CreateScalableFontResourceA   (GDI32.@)
2436  */
2437 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2438                                              LPCSTR lpszResourceFile,
2439                                              LPCSTR lpszFontFile,
2440                                              LPCSTR lpszCurrentPath )
2441 {
2442     LPWSTR lpszResourceFileW = NULL;
2443     LPWSTR lpszFontFileW = NULL;
2444     LPWSTR lpszCurrentPathW = NULL;
2445     int len;
2446     BOOL ret;
2447
2448     if (lpszResourceFile)
2449     {
2450         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2451         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2452         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2453     }
2454
2455     if (lpszFontFile)
2456     {
2457         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2458         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2459         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2460     }
2461
2462     if (lpszCurrentPath)
2463     {
2464         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2465         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2466         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2467     }
2468
2469     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2470             lpszFontFileW, lpszCurrentPathW);
2471
2472     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2473     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2474     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2475
2476     return ret;
2477 }
2478
2479 /***********************************************************************
2480  *           CreateScalableFontResourceW   (GDI32.@)
2481  */
2482 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2483                                              LPCWSTR lpszResourceFile,
2484                                              LPCWSTR lpszFontFile,
2485                                              LPCWSTR lpszCurrentPath )
2486 {
2487     HANDLE f;
2488     FIXME("(%d,%s,%s,%s): stub\n",
2489           fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2490           debugstr_w(lpszCurrentPath) );
2491
2492     /* fHidden=1 - only visible for the calling app, read-only, not
2493      * enumerated with EnumFonts/EnumFontFamilies
2494      * lpszCurrentPath can be NULL
2495      */
2496
2497     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2498     if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2499         CloseHandle(f);
2500         SetLastError(ERROR_FILE_EXISTS);
2501         return FALSE;
2502     }
2503     return FALSE; /* create failed */
2504 }
2505
2506 /*************************************************************************
2507  *             GetKerningPairsA   (GDI32.@)
2508  */
2509 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2510                                LPKERNINGPAIR kern_pairA )
2511 {
2512     UINT cp;
2513     CPINFO cpi;
2514     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2515     KERNINGPAIR *kern_pairW;
2516
2517     if (!cPairs && kern_pairA)
2518     {
2519         SetLastError(ERROR_INVALID_PARAMETER);
2520         return 0;
2521     }
2522
2523     cp = GdiGetCodePage(hDC);
2524
2525     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2526      * to fail on an invalid character for CP_SYMBOL.
2527      */
2528     cpi.DefaultChar[0] = 0;
2529     if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2530     {
2531         FIXME("Can't find codepage %u info\n", cp);
2532         return 0;
2533     }
2534
2535     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2536     if (!total_kern_pairs) return 0;
2537
2538     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2539     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2540
2541     for (i = 0; i < total_kern_pairs; i++)
2542     {
2543         char first, second;
2544
2545         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2546             continue;
2547
2548         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2549             continue;
2550
2551         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2552             continue;
2553
2554         if (kern_pairA)
2555         {
2556             if (kern_pairs_copied >= cPairs) break;
2557
2558             kern_pairA->wFirst = (BYTE)first;
2559             kern_pairA->wSecond = (BYTE)second;
2560             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2561             kern_pairA++;
2562         }
2563         kern_pairs_copied++;
2564     }
2565
2566     HeapFree(GetProcessHeap(), 0, kern_pairW);
2567
2568     return kern_pairs_copied;
2569 }
2570
2571 /*************************************************************************
2572  *             GetKerningPairsW   (GDI32.@)
2573  */
2574 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2575                                  LPKERNINGPAIR lpKerningPairs )
2576 {
2577     DC *dc;
2578     DWORD ret;
2579     PHYSDEV dev;
2580
2581     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2582
2583     if (!cPairs && lpKerningPairs)
2584     {
2585         SetLastError(ERROR_INVALID_PARAMETER);
2586         return 0;
2587     }
2588
2589     dc = get_dc_ptr(hDC);
2590     if (!dc) return 0;
2591
2592     dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2593     ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2594     release_dc_ptr( dc );
2595     return ret;
2596 }
2597
2598 /*************************************************************************
2599  * TranslateCharsetInfo [GDI32.@]
2600  *
2601  * Fills a CHARSETINFO structure for a character set, code page, or
2602  * font. This allows making the correspondence between different labels
2603  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2604  * of the same encoding.
2605  *
2606  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2607  * only one codepage should be set in *lpSrc.
2608  *
2609  * RETURNS
2610  *   TRUE on success, FALSE on failure.
2611  *
2612  */
2613 BOOL WINAPI TranslateCharsetInfo(
2614   LPDWORD lpSrc, /* [in]
2615        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2616        if flags == TCI_SRCCHARSET: a character set value
2617        if flags == TCI_SRCCODEPAGE: a code page value
2618                  */
2619   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2620   DWORD flags /* [in] determines interpretation of lpSrc */)
2621 {
2622     int index = 0;
2623     switch (flags) {
2624     case TCI_SRCFONTSIG:
2625       while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2626       break;
2627     case TCI_SRCCODEPAGE:
2628       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2629       break;
2630     case TCI_SRCCHARSET:
2631       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2632       break;
2633     default:
2634       return FALSE;
2635     }
2636     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2637     *lpCs = FONT_tci[index];
2638     return TRUE;
2639 }
2640
2641 /*************************************************************************
2642  *             GetFontLanguageInfo   (GDI32.@)
2643  */
2644 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2645 {
2646         FONTSIGNATURE fontsig;
2647         static const DWORD GCP_DBCS_MASK=0x003F0000,
2648                 GCP_DIACRITIC_MASK=0x00000000,
2649                 FLI_GLYPHS_MASK=0x00000000,
2650                 GCP_GLYPHSHAPE_MASK=0x00000040,
2651                 GCP_KASHIDA_MASK=0x00000000,
2652                 GCP_LIGATE_MASK=0x00000000,
2653                 GCP_USEKERNING_MASK=0x00000000,
2654                 GCP_REORDER_MASK=0x00000060;
2655
2656         DWORD result=0;
2657
2658         GetTextCharsetInfo( hdc, &fontsig, 0 );
2659         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2660
2661         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2662                 result|=GCP_DBCS;
2663
2664         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2665                 result|=GCP_DIACRITIC;
2666
2667         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2668                 result|=FLI_GLYPHS;
2669
2670         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2671                 result|=GCP_GLYPHSHAPE;
2672
2673         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2674                 result|=GCP_KASHIDA;
2675
2676         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2677                 result|=GCP_LIGATE;
2678
2679         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2680                 result|=GCP_USEKERNING;
2681
2682         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2683         if( GetTextAlign( hdc) & TA_RTLREADING )
2684             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2685                     result|=GCP_REORDER;
2686
2687         return result;
2688 }
2689
2690
2691 /*************************************************************************
2692  * GetFontData [GDI32.@]
2693  *
2694  * Retrieve data for TrueType font.
2695  *
2696  * RETURNS
2697  *
2698  * success: Number of bytes returned
2699  * failure: GDI_ERROR
2700  *
2701  * NOTES
2702  *
2703  * Calls SetLastError()
2704  *
2705  */
2706 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2707     LPVOID buffer, DWORD length)
2708 {
2709     DC *dc = get_dc_ptr(hdc);
2710     PHYSDEV dev;
2711     DWORD ret;
2712
2713     if(!dc) return GDI_ERROR;
2714
2715     dev = GET_DC_PHYSDEV( dc, pGetFontData );
2716     ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
2717     release_dc_ptr( dc );
2718     return ret;
2719 }
2720
2721 /*************************************************************************
2722  * GetGlyphIndicesA [GDI32.@]
2723  */
2724 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2725                               LPWORD pgi, DWORD flags)
2726 {
2727     DWORD ret;
2728     WCHAR *lpstrW;
2729     INT countW;
2730
2731     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2732           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2733
2734     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2735     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2736     HeapFree(GetProcessHeap(), 0, lpstrW);
2737
2738     return ret;
2739 }
2740
2741 /*************************************************************************
2742  * GetGlyphIndicesW [GDI32.@]
2743  */
2744 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2745                               LPWORD pgi, DWORD flags)
2746 {
2747     DC *dc = get_dc_ptr(hdc);
2748     PHYSDEV dev;
2749     DWORD ret;
2750
2751     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2752           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2753
2754     if(!dc) return GDI_ERROR;
2755
2756     dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
2757     ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
2758     release_dc_ptr( dc );
2759     return ret;
2760 }
2761
2762 /*************************************************************************
2763  * GetCharacterPlacementA [GDI32.@]
2764  *
2765  * See GetCharacterPlacementW.
2766  *
2767  * NOTES:
2768  *  the web browser control of ie4 calls this with dwFlags=0
2769  */
2770 DWORD WINAPI
2771 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2772                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2773                          DWORD dwFlags)
2774 {
2775     WCHAR *lpStringW;
2776     INT uCountW;
2777     GCP_RESULTSW resultsW;
2778     DWORD ret;
2779     UINT font_cp;
2780
2781     TRACE("%s, %d, %d, 0x%08x\n",
2782           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2783
2784     /* both structs are equal in size */
2785     memcpy(&resultsW, lpResults, sizeof(resultsW));
2786
2787     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2788     if(lpResults->lpOutString)
2789         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2790
2791     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2792
2793     lpResults->nGlyphs = resultsW.nGlyphs;
2794     lpResults->nMaxFit = resultsW.nMaxFit;
2795
2796     if(lpResults->lpOutString) {
2797         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2798                             lpResults->lpOutString, uCount, NULL, NULL );
2799     }
2800
2801     HeapFree(GetProcessHeap(), 0, lpStringW);
2802     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2803
2804     return ret;
2805 }
2806
2807 /*************************************************************************
2808  * GetCharacterPlacementW [GDI32.@]
2809  *
2810  *   Retrieve information about a string. This includes the width, reordering,
2811  *   Glyphing and so on.
2812  *
2813  * RETURNS
2814  *
2815  *   The width and height of the string if successful, 0 if failed.
2816  *
2817  * BUGS
2818  *
2819  *   All flags except GCP_REORDER are not yet implemented.
2820  *   Reordering is not 100% compliant to the Windows BiDi method.
2821  *   Caret positioning is not yet implemented for BiDi.
2822  *   Classes are not yet implemented.
2823  *
2824  */
2825 DWORD WINAPI
2826 GetCharacterPlacementW(
2827                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2828                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2829                 INT uCount,             /* [in] Number of WORDS in string. */
2830                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2831                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2832                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2833                 )
2834 {
2835     DWORD ret=0;
2836     SIZE size;
2837     UINT i, nSet;
2838
2839     TRACE("%s, %d, %d, 0x%08x\n",
2840           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2841
2842     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2843           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2844             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2845             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2846             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2847
2848     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
2849     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2850     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2851         FIXME("Caret positions for complex scripts not implemented\n");
2852
2853         nSet = (UINT)uCount;
2854         if(nSet > lpResults->nGlyphs)
2855                 nSet = lpResults->nGlyphs;
2856
2857         /* return number of initialized fields */
2858         lpResults->nGlyphs = nSet;
2859
2860         if((dwFlags&GCP_REORDER)==0 )
2861         {
2862                 /* Treat the case where no special handling was requested in a fastpath way */
2863                 /* copy will do if the GCP_REORDER flag is not set */
2864                 if(lpResults->lpOutString)
2865                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2866
2867                 if(lpResults->lpOrder)
2868                 {
2869                         for(i = 0; i < nSet; i++)
2870                                 lpResults->lpOrder[i] = i;
2871                 }
2872         } else
2873         {
2874             BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2875                           nSet, lpResults->lpOrder, NULL, NULL );
2876         }
2877
2878         /* FIXME: Will use the placement chars */
2879         if (lpResults->lpDx)
2880         {
2881                 int c;
2882                 for (i = 0; i < nSet; i++)
2883                 {
2884                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2885                                 lpResults->lpDx[i]= c;
2886                 }
2887         }
2888
2889     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2890     {
2891         int pos = 0;
2892        
2893         lpResults->lpCaretPos[0] = 0;
2894         for (i = 1; i < nSet; i++)
2895             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2896                 lpResults->lpCaretPos[i] = (pos += size.cx);
2897     }
2898    
2899     if(lpResults->lpGlyphs)
2900         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2901
2902     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2903       ret = MAKELONG(size.cx, size.cy);
2904
2905     return ret;
2906 }
2907
2908 /*************************************************************************
2909  *      GetCharABCWidthsFloatA [GDI32.@]
2910  *
2911  * See GetCharABCWidthsFloatW.
2912  */
2913 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2914 {
2915     INT i, wlen;
2916     LPSTR str;
2917     LPWSTR wstr;
2918     BOOL ret = TRUE;
2919
2920     str = FONT_GetCharsByRangeA(hdc, first, last, &i);
2921     if (str == NULL)
2922         return FALSE;
2923
2924     wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
2925
2926     for (i = 0; i < wlen; i++)
2927     {
2928         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2929         {
2930             ret = FALSE;
2931             break;
2932         }
2933         abcf++;
2934     }
2935
2936     HeapFree( GetProcessHeap(), 0, str );
2937     HeapFree( GetProcessHeap(), 0, wstr );
2938
2939     return ret;
2940 }
2941
2942 /*************************************************************************
2943  *      GetCharABCWidthsFloatW [GDI32.@]
2944  *
2945  * Retrieves widths of a range of characters.
2946  *
2947  * PARAMS
2948  *    hdc   [I] Handle to device context.
2949  *    first [I] First character in range to query.
2950  *    last  [I] Last character in range to query.
2951  *    abcf  [O] Array of LPABCFLOAT structures.
2952  *
2953  * RETURNS
2954  *    Success: TRUE
2955  *    Failure: FALSE
2956  */
2957 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2958 {
2959     UINT i;
2960     ABC *abc;
2961     PHYSDEV dev;
2962     BOOL ret = FALSE;
2963     DC *dc = get_dc_ptr( hdc );
2964
2965     TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
2966
2967     if (!dc) return FALSE;
2968
2969     if (!abcf) goto done;
2970     if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
2971
2972     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2973     ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
2974     if (ret)
2975     {
2976         /* convert device units to logical */
2977         for (i = first; i <= last; i++, abcf++)
2978         {
2979             abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
2980             abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
2981             abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
2982         }
2983     }
2984     HeapFree( GetProcessHeap(), 0, abc );
2985
2986 done:
2987     release_dc_ptr( dc );
2988     return ret;
2989 }
2990
2991 /*************************************************************************
2992  *      GetCharWidthFloatA [GDI32.@]
2993  */
2994 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2995                                     UINT iLastChar, PFLOAT pxBuffer)
2996 {
2997     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2998     return 0;
2999 }
3000
3001 /*************************************************************************
3002  *      GetCharWidthFloatW [GDI32.@]
3003  */
3004 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3005                                     UINT iLastChar, PFLOAT pxBuffer)
3006 {
3007     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3008     return 0;
3009 }
3010
3011
3012 /***********************************************************************
3013  *                                                                     *
3014  *           Font Resource API                                         *
3015  *                                                                     *
3016  ***********************************************************************/
3017
3018 /***********************************************************************
3019  *           AddFontResourceA    (GDI32.@)
3020  */
3021 INT WINAPI AddFontResourceA( LPCSTR str )
3022 {
3023     return AddFontResourceExA( str, 0, NULL);
3024 }
3025
3026 /***********************************************************************
3027  *           AddFontResourceW    (GDI32.@)
3028  */
3029 INT WINAPI AddFontResourceW( LPCWSTR str )
3030 {
3031     return AddFontResourceExW(str, 0, NULL);
3032 }
3033
3034
3035 /***********************************************************************
3036  *           AddFontResourceExA    (GDI32.@)
3037  */
3038 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3039 {
3040     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3041     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3042     INT ret;
3043
3044     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3045     ret = AddFontResourceExW(strW, fl, pdv);
3046     HeapFree(GetProcessHeap(), 0, strW);
3047     return ret;
3048 }
3049
3050 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3051 {
3052     HRSRC rsrc = FindResourceW(hModule, name, type);
3053     HGLOBAL hMem = LoadResource(hModule, rsrc);
3054     LPVOID *pMem = LockResource(hMem);
3055     int *num_total = (int *)lParam;
3056     DWORD num_in_res;
3057
3058     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3059     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3060     {
3061         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3062         return FALSE;
3063     }
3064
3065     *num_total += num_in_res;
3066     return TRUE;
3067 }
3068
3069 /***********************************************************************
3070  *           AddFontResourceExW    (GDI32.@)
3071  */
3072 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3073 {
3074     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3075     if (ret == 0)
3076     {
3077         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3078         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3079         if (hModule != NULL)
3080         {
3081             int num_resources = 0;
3082             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3083
3084             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3085                 wine_dbgstr_w(str));
3086             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3087                 ret = num_resources;
3088             FreeLibrary(hModule);
3089         }
3090     }
3091     return ret;
3092 }
3093
3094 /***********************************************************************
3095  *           RemoveFontResourceA    (GDI32.@)
3096  */
3097 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3098 {
3099     return RemoveFontResourceExA(str, 0, 0);
3100 }
3101
3102 /***********************************************************************
3103  *           RemoveFontResourceW    (GDI32.@)
3104  */
3105 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3106 {
3107     return RemoveFontResourceExW(str, 0, 0);
3108 }
3109
3110 /***********************************************************************
3111  *           AddFontMemResourceEx    (GDI32.@)
3112  */
3113 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3114 {
3115     HANDLE ret;
3116     DWORD num_fonts;
3117
3118     if (!pbFont || !cbFont || !pcFonts)
3119     {
3120         SetLastError(ERROR_INVALID_PARAMETER);
3121         return NULL;
3122     }
3123
3124     ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3125     if (ret)
3126     {
3127         __TRY
3128         {
3129             *pcFonts = num_fonts;
3130         }
3131         __EXCEPT_PAGE_FAULT
3132         {
3133             WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3134             RemoveFontMemResourceEx(ret);
3135             ret = 0;
3136         }
3137         __ENDTRY
3138     }
3139     return ret;
3140 }
3141
3142 /***********************************************************************
3143  *           RemoveFontMemResourceEx    (GDI32.@)
3144  */
3145 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3146 {
3147     FIXME("(%p) stub\n", fh);
3148     return TRUE;
3149 }
3150
3151 /***********************************************************************
3152  *           RemoveFontResourceExA    (GDI32.@)
3153  */
3154 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3155 {
3156     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3157     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3158     INT ret;
3159
3160     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3161     ret = RemoveFontResourceExW(strW, fl, pdv);
3162     HeapFree(GetProcessHeap(), 0, strW);
3163     return ret;
3164 }
3165
3166 /***********************************************************************
3167  *           RemoveFontResourceExW    (GDI32.@)
3168  */
3169 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3170 {
3171     return WineEngRemoveFontResourceEx(str, fl, pdv);
3172 }
3173
3174 /***********************************************************************
3175  *           GetTextCharset    (GDI32.@)
3176  */
3177 UINT WINAPI GetTextCharset(HDC hdc)
3178 {
3179     /* MSDN docs say this is equivalent */
3180     return GetTextCharsetInfo(hdc, NULL, 0);
3181 }
3182
3183 /***********************************************************************
3184  *           GetTextCharsetInfo    (GDI32.@)
3185  */
3186 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3187 {
3188     UINT ret = DEFAULT_CHARSET;
3189     DC *dc = get_dc_ptr(hdc);
3190     PHYSDEV dev;
3191
3192     if (dc)
3193     {
3194         dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3195         ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3196         release_dc_ptr( dc );
3197     }
3198
3199     if (ret == DEFAULT_CHARSET && fs)
3200         memset(fs, 0, sizeof(FONTSIGNATURE));
3201     return ret;
3202 }
3203
3204 /***********************************************************************
3205  *           GdiGetCharDimensions    (GDI32.@)
3206  *
3207  * Gets the average width of the characters in the English alphabet.
3208  *
3209  * PARAMS
3210  *  hdc    [I] Handle to the device context to measure on.
3211  *  lptm   [O] Pointer to memory to store the text metrics into.
3212  *  height [O] On exit, the maximum height of characters in the English alphabet.
3213  *
3214  * RETURNS
3215  *  The average width of characters in the English alphabet.
3216  *
3217  * NOTES
3218  *  This function is used by the dialog manager to get the size of a dialog
3219  *  unit. It should also be used by other pieces of code that need to know
3220  *  the size of a dialog unit in logical units without having access to the
3221  *  window handle of the dialog.
3222  *  Windows caches the font metrics from this function, but we don't and
3223  *  there doesn't appear to be an immediate advantage to do so.
3224  *
3225  * SEE ALSO
3226  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3227  */
3228 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3229 {
3230     SIZE sz;
3231     static const WCHAR alphabet[] = {
3232         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3233         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3234         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3235
3236     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3237
3238     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3239
3240     if (height) *height = sz.cy;
3241     return (sz.cx / 26 + 1) / 2;
3242 }
3243
3244 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3245 {
3246     FIXME("(%d): stub\n", fEnableEUDC);
3247     return FALSE;
3248 }
3249
3250 /***********************************************************************
3251  *           GetCharWidthI    (GDI32.@)
3252  *
3253  * Retrieve widths of characters.
3254  *
3255  * PARAMS
3256  *  hdc    [I] Handle to a device context.
3257  *  first  [I] First glyph in range to query.
3258  *  count  [I] Number of glyph indices to query.
3259  *  glyphs [I] Array of glyphs to query.
3260  *  buffer [O] Buffer to receive character widths.
3261  *
3262  * NOTES
3263  *  Only works with TrueType fonts.
3264  *
3265  * RETURNS
3266  *  Success: TRUE
3267  *  Failure: FALSE
3268  */
3269 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3270 {
3271     ABC *abc;
3272     unsigned int i;
3273
3274     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3275
3276     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3277         return FALSE;
3278
3279     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3280     {
3281         HeapFree(GetProcessHeap(), 0, abc);
3282         return FALSE;
3283     }
3284
3285     for (i = 0; i < count; i++)
3286         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3287
3288     HeapFree(GetProcessHeap(), 0, abc);
3289     return TRUE;
3290 }
3291
3292 /***********************************************************************
3293  *           GetFontUnicodeRanges    (GDI32.@)
3294  *
3295  *  Retrieve a list of supported Unicode characters in a font.
3296  *
3297  *  PARAMS
3298  *   hdc  [I] Handle to a device context.
3299  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3300  *
3301  *  RETURNS
3302  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3303  *   Failure: 0
3304  *
3305  */
3306 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3307 {
3308     DWORD ret;
3309     PHYSDEV dev;
3310     DC *dc = get_dc_ptr(hdc);
3311
3312     TRACE("(%p, %p)\n", hdc, lpgs);
3313
3314     if (!dc) return 0;
3315
3316     dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3317     ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3318     release_dc_ptr(dc);
3319     return ret;
3320 }
3321
3322
3323 /*************************************************************
3324  *           FontIsLinked    (GDI32.@)
3325  */
3326 BOOL WINAPI FontIsLinked(HDC hdc)
3327 {
3328     DC *dc = get_dc_ptr(hdc);
3329     PHYSDEV dev;
3330     BOOL ret;
3331
3332     if (!dc) return FALSE;
3333     dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3334     ret = dev->funcs->pFontIsLinked( dev );
3335     release_dc_ptr(dc);
3336     TRACE("returning %d\n", ret);
3337     return ret;
3338 }
3339
3340 /*************************************************************
3341  *           GdiRealizationInfo    (GDI32.@)
3342  *
3343  * Returns a structure that contains some font information.
3344  */
3345 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3346 {
3347     DC *dc = get_dc_ptr(hdc);
3348     PHYSDEV dev;
3349     BOOL ret;
3350
3351     if (!dc) return FALSE;
3352     dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3353     ret = dev->funcs->pGdiRealizationInfo( dev, info );
3354     release_dc_ptr(dc);
3355     return ret;
3356 }