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