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