gdi32/tests: Fixed typo in localized name tests.
[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     LOGFONTW    logfont;
114 } FONTOBJ;
115
116 struct font_enum
117 {
118   LPLOGFONTW          lpLogFontParam;
119   FONTENUMPROCW       lpEnumFunc;
120   LPARAM              lpData;
121   BOOL                unicode;
122   HDC                 hdc;
123   INT                 retval;
124 };
125
126 /*
127  *  For TranslateCharsetInfo
128  */
129 #define MAXTCIINDEX 32
130 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
131   /* ANSI */
132   { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
133   { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
134   { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
135   { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
136   { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
137   { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
138   { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
139   { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
140   { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
141   /* reserved by ANSI */
142   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
146   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
147   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
148   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
149   /* ANSI and OEM */
150   { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
151   { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
152   { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
153   { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
154   { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
155   { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
156   /* reserved for alternate ANSI and OEM */
157   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
161   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
163   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
164   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
165   /* reserved for system */
166   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
167   { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
168 };
169
170 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
171 {
172     memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
173     MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
174                         LF_FACESIZE);
175     fontW->lfFaceName[LF_FACESIZE-1] = 0;
176 }
177
178 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
179 {
180     memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
181     WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
182                         LF_FACESIZE, NULL, NULL);
183     fontA->lfFaceName[LF_FACESIZE-1] = 0;
184 }
185
186 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
187 {
188     FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
189
190     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
191                          (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
192     fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
193     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
194                          (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
195     fontA->elfStyle[LF_FACESIZE-1] = '\0';
196     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
197                          (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
198     fontA->elfScript[LF_FACESIZE-1] = '\0';
199 }
200
201 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
202 {
203     FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
204
205     MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
206                          fontW->elfFullName, LF_FULLFACESIZE );
207     fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
208     MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
209                          fontW->elfStyle, LF_FACESIZE );
210     fontW->elfStyle[LF_FACESIZE-1] = '\0';
211     MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
212                          fontW->elfScript, LF_FACESIZE );
213     fontW->elfScript[LF_FACESIZE-1] = '\0';
214 }
215
216 /***********************************************************************
217  *              TEXTMETRIC conversion functions.
218  */
219 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
220 {
221     ptmA->tmHeight = ptmW->tmHeight;
222     ptmA->tmAscent = ptmW->tmAscent;
223     ptmA->tmDescent = ptmW->tmDescent;
224     ptmA->tmInternalLeading = ptmW->tmInternalLeading;
225     ptmA->tmExternalLeading = ptmW->tmExternalLeading;
226     ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
227     ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
228     ptmA->tmWeight = ptmW->tmWeight;
229     ptmA->tmOverhang = ptmW->tmOverhang;
230     ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
231     ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
232     ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
233     if (ptmW->tmCharSet == SYMBOL_CHARSET)
234     {
235         ptmA->tmFirstChar = 0x1e;
236         ptmA->tmLastChar = 0xff;  /* win9x behaviour - we need the OS2 table data to calculate correctly */
237     }
238     else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
239     {
240         ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
241         ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
242     }
243     else
244     {
245         ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
246         ptmA->tmLastChar  = min(ptmW->tmLastChar,  0xff);
247     }
248     ptmA->tmDefaultChar = ptmW->tmDefaultChar;
249     ptmA->tmBreakChar = ptmW->tmBreakChar;
250     ptmA->tmItalic = ptmW->tmItalic;
251     ptmA->tmUnderlined = ptmW->tmUnderlined;
252     ptmA->tmStruckOut = ptmW->tmStruckOut;
253     ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
254     ptmA->tmCharSet = ptmW->tmCharSet;
255 }
256
257
258 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
259 {
260     FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
261     ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
262     ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
263     ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
264     ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
265     memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
266 }
267
268 static DWORD get_font_ppem( HDC hdc )
269 {
270     TEXTMETRICW tm;
271     DWORD ppem;
272     DC *dc = get_dc_ptr( hdc );
273
274     if (!dc) return GDI_ERROR;
275
276     GetTextMetricsW( hdc, &tm );
277     ppem = abs( INTERNAL_YWSTODS( dc, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading ) );
278     release_dc_ptr( dc );
279     return ppem;
280 }
281
282 #define GASP_GRIDFIT 0x01
283 #define GASP_DOGRAY  0x02
284
285 static BOOL get_gasp_flags( HDC hdc, WORD *flags )
286 {
287     DWORD size, gasp_tag = 0x70736167;
288     WORD buf[16]; /* Enough for seven ranges before we need to alloc */
289     WORD *alloced = NULL, *ptr = buf;
290     WORD num_recs, version;
291     DWORD ppem = get_font_ppem( hdc );
292     BOOL ret = FALSE;
293
294     *flags = 0;
295     if (ppem == GDI_ERROR) return FALSE;
296
297     size = GetFontData( hdc, gasp_tag,  0, NULL, 0 );
298     if (size == GDI_ERROR) return FALSE;
299     if (size < 4 * sizeof(WORD)) return FALSE;
300     if (size > sizeof(buf))
301     {
302         ptr = alloced = HeapAlloc( GetProcessHeap(), 0, size );
303         if (!ptr) return FALSE;
304     }
305
306     GetFontData( hdc, gasp_tag, 0, ptr, size );
307
308     version  = get_be_word( *ptr++ );
309     num_recs = get_be_word( *ptr++ );
310
311     if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD))
312     {
313         FIXME( "Unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs );
314         goto done;
315     }
316
317     while (num_recs--)
318     {
319         *flags = get_be_word( *(ptr + 1) );
320         if (ppem <= get_be_word( *ptr )) break;
321         ptr += 2;
322     }
323     TRACE( "got flags %04x for ppem %d\n", *flags, ppem );
324     ret = TRUE;
325
326 done:
327     HeapFree( GetProcessHeap(), 0, alloced );
328     return ret;
329 }
330
331 UINT get_font_aa_flags( HDC hdc )
332 {
333     LOGFONTW lf;
334     WORD gasp_flags;
335
336     if (GetObjectType( hdc ) == OBJ_MEMDC)
337     {
338         BITMAP bm;
339         GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(bm), &bm );
340         if (bm.bmBitsPixel <= 8) return GGO_BITMAP;
341     }
342     else if (GetDeviceCaps( hdc, BITSPIXEL ) <= 8) return GGO_BITMAP;
343
344     GetObjectW( GetCurrentObject( hdc, OBJ_FONT ), sizeof(lf), &lf );
345     if (lf.lfQuality == NONANTIALIASED_QUALITY) return GGO_BITMAP;
346
347     if (get_gasp_flags( hdc, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY))
348         return GGO_BITMAP;
349
350     /* FIXME, check user prefs */
351     return GGO_GRAY4_BITMAP;
352 }
353
354 /***********************************************************************
355  *           GdiGetCodePage   (GDI32.@)
356  */
357 DWORD WINAPI GdiGetCodePage( HDC hdc )
358 {
359     UINT cp = CP_ACP;
360     DC *dc = get_dc_ptr( hdc );
361
362     if (dc)
363     {
364         cp = dc->font_code_page;
365         release_dc_ptr( dc );
366     }
367     return cp;
368 }
369
370 /***********************************************************************
371  *           FONT_mbtowc
372  *
373  * Returns a Unicode translation of str using the charset of the
374  * currently selected font in hdc.  If count is -1 then str is assumed
375  * to be '\0' terminated, otherwise it contains the number of bytes to
376  * convert.  If plenW is non-NULL, on return it will point to the
377  * number of WCHARs that have been written.  If pCP is non-NULL, on
378  * return it will point to the codepage used in the conversion.  The
379  * caller should free the returned LPWSTR from the process heap
380  * itself.
381  */
382 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
383 {
384     UINT cp;
385     INT lenW;
386     LPWSTR strW;
387
388     cp = GdiGetCodePage( hdc );
389
390     if(count == -1) count = strlen(str);
391     lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
392     strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
393     MultiByteToWideChar(cp, 0, str, count, strW, lenW);
394     TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
395     if(plenW) *plenW = lenW;
396     if(pCP) *pCP = cp;
397     return strW;
398 }
399
400 /***********************************************************************
401  *           CreateFontIndirectExA   (GDI32.@)
402  */
403 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
404 {
405     ENUMLOGFONTEXDVW enumexW;
406
407     if (!penumexA) return 0;
408
409     FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
410     enumexW.elfDesignVector = penumexA->elfDesignVector;
411     return CreateFontIndirectExW( &enumexW );
412 }
413
414 /***********************************************************************
415  *           CreateFontIndirectExW   (GDI32.@)
416  */
417 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
418 {
419     HFONT hFont;
420     FONTOBJ *fontPtr;
421     const LOGFONTW *plf;
422
423     if (!penumex) return 0;
424
425     if (penumex->elfEnumLogfontEx.elfFullName[0] ||
426         penumex->elfEnumLogfontEx.elfStyle[0] ||
427         penumex->elfEnumLogfontEx.elfScript[0])
428     {
429         FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
430             debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
431             debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
432             debugstr_w(penumex->elfEnumLogfontEx.elfScript));
433     }
434
435     plf = &penumex->elfEnumLogfontEx.elfLogFont;
436     if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
437
438     fontPtr->logfont = *plf;
439
440     if (plf->lfEscapement != plf->lfOrientation)
441     {
442         /* this should really depend on whether GM_ADVANCED is set */
443         fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
444         WARN("orientation angle %f set to "
445              "escapement angle %f for new font %p\n",
446              plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
447     }
448
449     if (!(hFont = alloc_gdi_handle( fontPtr, OBJ_FONT, &font_funcs )))
450     {
451         HeapFree( GetProcessHeap(), 0, fontPtr );
452         return 0;
453     }
454
455     TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
456           plf->lfHeight, plf->lfWidth,
457           plf->lfEscapement, plf->lfOrientation,
458           plf->lfPitchAndFamily,
459           plf->lfOutPrecision, plf->lfClipPrecision,
460           plf->lfQuality, plf->lfCharSet,
461           debugstr_w(plf->lfFaceName),
462           plf->lfWeight > 400 ? "Bold" : "",
463           plf->lfItalic ? "Italic" : "",
464           plf->lfUnderline ? "Underline" : "", hFont);
465
466     return hFont;
467 }
468
469 /***********************************************************************
470  *           CreateFontIndirectA   (GDI32.@)
471  */
472 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
473 {
474     LOGFONTW lfW;
475
476     if (!plfA) return 0;
477
478     FONT_LogFontAToW( plfA, &lfW );
479     return CreateFontIndirectW( &lfW );
480 }
481
482 /***********************************************************************
483  *           CreateFontIndirectW   (GDI32.@)
484  */
485 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
486 {
487     ENUMLOGFONTEXDVW exdv;
488
489     if (!plf) return 0;
490
491     exdv.elfEnumLogfontEx.elfLogFont = *plf;
492     exdv.elfEnumLogfontEx.elfFullName[0] = 0;
493     exdv.elfEnumLogfontEx.elfStyle[0] = 0;
494     exdv.elfEnumLogfontEx.elfScript[0] = 0;
495     return CreateFontIndirectExW( &exdv );
496 }
497
498 /*************************************************************************
499  *           CreateFontA    (GDI32.@)
500  */
501 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
502                               INT orient, INT weight, DWORD italic,
503                               DWORD underline, DWORD strikeout, DWORD charset,
504                               DWORD outpres, DWORD clippres, DWORD quality,
505                               DWORD pitch, LPCSTR name )
506 {
507     LOGFONTA logfont;
508
509     logfont.lfHeight = height;
510     logfont.lfWidth = width;
511     logfont.lfEscapement = esc;
512     logfont.lfOrientation = orient;
513     logfont.lfWeight = weight;
514     logfont.lfItalic = italic;
515     logfont.lfUnderline = underline;
516     logfont.lfStrikeOut = strikeout;
517     logfont.lfCharSet = charset;
518     logfont.lfOutPrecision = outpres;
519     logfont.lfClipPrecision = clippres;
520     logfont.lfQuality = quality;
521     logfont.lfPitchAndFamily = pitch;
522
523     if (name)
524         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
525     else
526         logfont.lfFaceName[0] = '\0';
527
528     return CreateFontIndirectA( &logfont );
529 }
530
531 /*************************************************************************
532  *           CreateFontW    (GDI32.@)
533  */
534 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
535                               INT orient, INT weight, DWORD italic,
536                               DWORD underline, DWORD strikeout, DWORD charset,
537                               DWORD outpres, DWORD clippres, DWORD quality,
538                               DWORD pitch, LPCWSTR name )
539 {
540     LOGFONTW logfont;
541
542     logfont.lfHeight = height;
543     logfont.lfWidth = width;
544     logfont.lfEscapement = esc;
545     logfont.lfOrientation = orient;
546     logfont.lfWeight = weight;
547     logfont.lfItalic = italic;
548     logfont.lfUnderline = underline;
549     logfont.lfStrikeOut = strikeout;
550     logfont.lfCharSet = charset;
551     logfont.lfOutPrecision = outpres;
552     logfont.lfClipPrecision = clippres;
553     logfont.lfQuality = quality;
554     logfont.lfPitchAndFamily = pitch;
555
556     if (name)
557         lstrcpynW(logfont.lfFaceName, name,
558                   sizeof(logfont.lfFaceName) / sizeof(WCHAR));
559     else
560         logfont.lfFaceName[0] = '\0';
561
562     return CreateFontIndirectW( &logfont );
563 }
564
565 static void update_font_code_page( DC *dc )
566 {
567     CHARSETINFO csi;
568     int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
569
570     /* Hmm, nicely designed api this one! */
571     if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
572         dc->font_code_page = csi.ciACP;
573     else {
574         switch(charset) {
575         case OEM_CHARSET:
576             dc->font_code_page = GetOEMCP();
577             break;
578         case DEFAULT_CHARSET:
579             dc->font_code_page = GetACP();
580             break;
581
582         case VISCII_CHARSET:
583         case TCVN_CHARSET:
584         case KOI8_CHARSET:
585         case ISO3_CHARSET:
586         case ISO4_CHARSET:
587         case ISO10_CHARSET:
588         case CELTIC_CHARSET:
589             /* FIXME: These have no place here, but because x11drv
590                enumerates fonts with these (made up) charsets some apps
591                might use them and then the FIXME below would become
592                annoying.  Now we could pick the intended codepage for
593                each of these, but since it's broken anyway we'll just
594                use CP_ACP and hope it'll go away...
595             */
596             dc->font_code_page = CP_ACP;
597             break;
598
599         default:
600             FIXME("Can't find codepage for charset %d\n", charset);
601             dc->font_code_page = CP_ACP;
602             break;
603         }
604     }
605
606     TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
607 }
608
609 /***********************************************************************
610  *           FONT_SelectObject
611  */
612 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
613 {
614     HGDIOBJ ret = 0;
615     DC *dc = get_dc_ptr( hdc );
616     PHYSDEV physdev;
617
618     if (!dc) return 0;
619
620     if (!GDI_inc_ref_count( handle ))
621     {
622         release_dc_ptr( dc );
623         return 0;
624     }
625
626     physdev = GET_DC_PHYSDEV( dc, pSelectFont );
627     if (physdev->funcs->pSelectFont( physdev, handle ))
628     {
629         ret = dc->hFont;
630         dc->hFont = handle;
631         update_font_code_page( dc );
632         GDI_dec_ref_count( ret );
633     }
634     else GDI_dec_ref_count( handle );
635
636     release_dc_ptr( dc );
637     return ret;
638 }
639
640
641 /***********************************************************************
642  *           FONT_GetObjectA
643  */
644 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
645 {
646     FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
647     LOGFONTA lfA;
648
649     if (!font) return 0;
650     if (buffer)
651     {
652         FONT_LogFontWToA( &font->logfont, &lfA );
653         if (count > sizeof(lfA)) count = sizeof(lfA);
654         memcpy( buffer, &lfA, count );
655     }
656     else count = sizeof(lfA);
657     GDI_ReleaseObj( handle );
658     return count;
659 }
660
661 /***********************************************************************
662  *           FONT_GetObjectW
663  */
664 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
665 {
666     FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
667
668     if (!font) return 0;
669     if (buffer)
670     {
671         if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
672         memcpy( buffer, &font->logfont, count );
673     }
674     else count = sizeof(LOGFONTW);
675     GDI_ReleaseObj( handle );
676     return count;
677 }
678
679
680 /***********************************************************************
681  *           FONT_DeleteObject
682  */
683 static BOOL FONT_DeleteObject( HGDIOBJ handle )
684 {
685     FONTOBJ *obj;
686
687     WineEngDestroyFontInstance( handle );
688
689     if (!(obj = free_gdi_handle( handle ))) return FALSE;
690     return HeapFree( GetProcessHeap(), 0, obj );
691 }
692
693
694 /***********************************************************************
695  *              FONT_EnumInstance
696  *
697  * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
698  *       We have to use other types because of the FONTENUMPROCW definition.
699  */
700 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
701                                        DWORD fType, LPARAM lp )
702 {
703     struct font_enum *pfe = (struct font_enum *)lp;
704     INT ret = 1;
705
706     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
707     if ((!pfe->lpLogFontParam ||
708         pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
709         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
710        (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
711     {
712         /* convert font metrics */
713         ENUMLOGFONTEXA logfont;
714         NEWTEXTMETRICEXA tmA;
715
716         if (!pfe->unicode)
717         {
718             FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
719             FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
720             plf = (LOGFONTW *)&logfont.elfLogFont;
721             ptm = (TEXTMETRICW *)&tmA;
722         }
723         ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
724         pfe->retval = ret;
725     }
726     return ret;
727 }
728
729 /***********************************************************************
730  *              FONT_EnumFontFamiliesEx
731  */
732 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
733                                     LPARAM lParam, BOOL unicode )
734 {
735     INT ret = 0;
736     DC *dc = get_dc_ptr( hDC );
737     struct font_enum fe;
738
739     if (dc)
740     {
741         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
742
743         if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
744         fe.lpLogFontParam = plf;
745         fe.lpEnumFunc = efproc;
746         fe.lpData = lParam;
747         fe.unicode = unicode;
748         fe.hdc = hDC;
749         fe.retval = 1;
750         ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
751         release_dc_ptr( dc );
752     }
753     return ret ? fe.retval : 0;
754 }
755
756 /***********************************************************************
757  *              EnumFontFamiliesExW     (GDI32.@)
758  */
759 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
760                                     FONTENUMPROCW efproc,
761                                     LPARAM lParam, DWORD dwFlags )
762 {
763     return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
764 }
765
766 /***********************************************************************
767  *              EnumFontFamiliesExA     (GDI32.@)
768  */
769 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
770                                     FONTENUMPROCA efproc,
771                                     LPARAM lParam, DWORD dwFlags)
772 {
773     LOGFONTW lfW, *plfW;
774
775     if (plf)
776     {
777         FONT_LogFontAToW( plf, &lfW );
778         plfW = &lfW;
779     }
780     else plfW = NULL;
781
782     return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
783 }
784
785 /***********************************************************************
786  *              EnumFontFamiliesA       (GDI32.@)
787  */
788 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
789                                   FONTENUMPROCA efproc, LPARAM lpData )
790 {
791     LOGFONTA lf, *plf;
792
793     if (lpFamily)
794     {
795         if (!*lpFamily) return 1;
796         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
797         lf.lfCharSet = DEFAULT_CHARSET;
798         lf.lfPitchAndFamily = 0;
799         plf = &lf;
800     }
801     else plf = NULL;
802
803     return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
804 }
805
806 /***********************************************************************
807  *              EnumFontFamiliesW       (GDI32.@)
808  */
809 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
810                                   FONTENUMPROCW efproc, LPARAM lpData )
811 {
812     LOGFONTW lf, *plf;
813
814     if (lpFamily)
815     {
816         if (!*lpFamily) return 1;
817         lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
818         lf.lfCharSet = DEFAULT_CHARSET;
819         lf.lfPitchAndFamily = 0;
820         plf = &lf;
821     }
822     else plf = NULL;
823
824     return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
825 }
826
827 /***********************************************************************
828  *              EnumFontsA              (GDI32.@)
829  */
830 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
831                            LPARAM lpData )
832 {
833     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
834 }
835
836 /***********************************************************************
837  *              EnumFontsW              (GDI32.@)
838  */
839 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
840                            LPARAM lpData )
841 {
842     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
843 }
844
845
846 /***********************************************************************
847  *           GetTextCharacterExtra    (GDI32.@)
848  */
849 INT WINAPI GetTextCharacterExtra( HDC hdc )
850 {
851     INT ret;
852     DC *dc = get_dc_ptr( hdc );
853     if (!dc) return 0x80000000;
854     ret = dc->charExtra;
855     release_dc_ptr( dc );
856     return ret;
857 }
858
859
860 /***********************************************************************
861  *           SetTextCharacterExtra    (GDI32.@)
862  */
863 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
864 {
865     INT ret = 0x80000000;
866     DC * dc = get_dc_ptr( hdc );
867
868     if (dc)
869     {
870         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
871         extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
872         if (extra != 0x80000000)
873         {
874             ret = dc->charExtra;
875             dc->charExtra = extra;
876         }
877         release_dc_ptr( dc );
878     }
879     return ret;
880 }
881
882
883 /***********************************************************************
884  *           SetTextJustification    (GDI32.@)
885  */
886 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
887 {
888     BOOL ret;
889     PHYSDEV physdev;
890     DC * dc = get_dc_ptr( hdc );
891
892     if (!dc) return FALSE;
893
894     physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
895     ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
896     if (ret)
897     {
898         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
899         if (!extra) breaks = 0;
900         if (breaks)
901         {
902             dc->breakExtra = extra / breaks;
903             dc->breakRem   = extra - (breaks * dc->breakExtra);
904         }
905         else
906         {
907             dc->breakExtra = 0;
908             dc->breakRem   = 0;
909         }
910     }
911     release_dc_ptr( dc );
912     return ret;
913 }
914
915
916 /***********************************************************************
917  *           GetTextFaceA    (GDI32.@)
918  */
919 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
920 {
921     INT res = GetTextFaceW(hdc, 0, NULL);
922     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
923     GetTextFaceW( hdc, res, nameW );
924
925     if (name)
926     {
927         if (count)
928         {
929             res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
930             if (res == 0)
931                 res = count;
932             name[count-1] = 0;
933             /* GetTextFaceA does NOT include the nul byte in the return count.  */
934             res--;
935         }
936         else
937             res = 0;
938     }
939     else
940         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
941     HeapFree( GetProcessHeap(), 0, nameW );
942     return res;
943 }
944
945 /***********************************************************************
946  *           GetTextFaceW    (GDI32.@)
947  */
948 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
949 {
950     PHYSDEV dev;
951     INT ret;
952
953     DC * dc = get_dc_ptr( hdc );
954     if (!dc) return 0;
955
956     dev = GET_DC_PHYSDEV( dc, pGetTextFace );
957     ret = dev->funcs->pGetTextFace( dev, count, name );
958     release_dc_ptr( dc );
959     return ret;
960 }
961
962
963 /***********************************************************************
964  *           GetTextExtentPoint32A    (GDI32.@)
965  *
966  * See GetTextExtentPoint32W.
967  */
968 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
969                                      LPSIZE size )
970 {
971     BOOL ret = FALSE;
972     INT wlen;
973     LPWSTR p;
974
975     if (count < 0) return FALSE;
976
977     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
978
979     if (p)
980     {
981         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
982         HeapFree( GetProcessHeap(), 0, p );
983     }
984
985     TRACE("(%p %s %d %p): returning %d x %d\n",
986           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
987     return ret;
988 }
989
990
991 /***********************************************************************
992  * GetTextExtentPoint32W [GDI32.@]
993  *
994  * Computes width/height for a string.
995  *
996  * Computes width and height of the specified string.
997  *
998  * RETURNS
999  *    Success: TRUE
1000  *    Failure: FALSE
1001  */
1002 BOOL WINAPI GetTextExtentPoint32W(
1003     HDC hdc,     /* [in]  Handle of device context */
1004     LPCWSTR str,   /* [in]  Address of text string */
1005     INT count,   /* [in]  Number of characters in string */
1006     LPSIZE size) /* [out] Address of structure for string size */
1007 {
1008     return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1009 }
1010
1011 /***********************************************************************
1012  * GetTextExtentExPointI [GDI32.@]
1013  *
1014  * Computes width and height of the array of glyph indices.
1015  *
1016  * PARAMS
1017  *    hdc     [I] Handle of device context.
1018  *    indices [I] Glyph index array.
1019  *    count   [I] Number of glyphs in array.
1020  *    max_ext [I] Maximum width in glyphs.
1021  *    nfit    [O] Maximum number of characters.
1022  *    dxs     [O] Partial string widths.
1023  *    size    [O] Returned string size.
1024  *
1025  * RETURNS
1026  *    Success: TRUE
1027  *    Failure: FALSE
1028  */
1029 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1030                                    LPINT nfit, LPINT dxs, LPSIZE size )
1031 {
1032     PHYSDEV dev;
1033     BOOL ret;
1034     DC *dc;
1035
1036     if (count < 0) return FALSE;
1037
1038     dc = get_dc_ptr( hdc );
1039     if (!dc) return FALSE;
1040
1041     dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
1042     ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
1043     size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1044     size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1045     size->cx += count * dc->charExtra;
1046     release_dc_ptr( dc );
1047
1048     TRACE("(%p %p %d %p): returning %d x %d\n",
1049           hdc, indices, count, size, size->cx, size->cy );
1050     return ret;
1051 }
1052
1053 /***********************************************************************
1054  * GetTextExtentPointI [GDI32.@]
1055  *
1056  * Computes width and height of the array of glyph indices.
1057  *
1058  * PARAMS
1059  *    hdc     [I] Handle of device context.
1060  *    indices [I] Glyph index array.
1061  *    count   [I] Number of glyphs in array.
1062  *    size    [O] Returned string size.
1063  *
1064  * RETURNS
1065  *    Success: TRUE
1066  *    Failure: FALSE
1067  */
1068 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1069 {
1070     return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1071 }
1072
1073
1074 /***********************************************************************
1075  *           GetTextExtentPointA    (GDI32.@)
1076  */
1077 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1078                                           LPSIZE size )
1079 {
1080     TRACE("not bug compatible.\n");
1081     return GetTextExtentPoint32A( hdc, str, count, size );
1082 }
1083
1084 /***********************************************************************
1085  *           GetTextExtentPointW   (GDI32.@)
1086  */
1087 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1088                                           LPSIZE size )
1089 {
1090     TRACE("not bug compatible.\n");
1091     return GetTextExtentPoint32W( hdc, str, count, size );
1092 }
1093
1094
1095 /***********************************************************************
1096  *           GetTextExtentExPointA    (GDI32.@)
1097  */
1098 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1099                                    INT maxExt, LPINT lpnFit,
1100                                    LPINT alpDx, LPSIZE size )
1101 {
1102     BOOL ret;
1103     INT wlen;
1104     INT *walpDx = NULL;
1105     LPWSTR p = NULL;
1106
1107     if (count < 0) return FALSE;
1108
1109     if (alpDx)
1110     {
1111         walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1112         if (!walpDx) return FALSE;
1113     }
1114
1115     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1116     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1117     if (walpDx)
1118     {
1119         INT n = lpnFit ? *lpnFit : wlen;
1120         INT i, j;
1121         for(i = 0, j = 0; i < n; i++, j++)
1122         {
1123             alpDx[j] = walpDx[i];
1124             if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1125         }
1126     }
1127     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1128     HeapFree( GetProcessHeap(), 0, p );
1129     HeapFree( GetProcessHeap(), 0, walpDx );
1130     return ret;
1131 }
1132
1133
1134 /***********************************************************************
1135  *           GetTextExtentExPointW    (GDI32.@)
1136  *
1137  * Return the size of the string as it would be if it was output properly by
1138  * e.g. TextOut.
1139  *
1140  * This should include
1141  * - Intercharacter spacing
1142  * - justification spacing (not yet done)
1143  * - kerning? see below
1144  *
1145  * Kerning.  Since kerning would be carried out by the rendering code it should
1146  * be done by the driver.  However they don't support it yet.  Also I am not
1147  * yet persuaded that (certainly under Win95) any kerning is actually done.
1148  *
1149  * str: According to MSDN this should be null-terminated.  That is not true; a
1150  *      null will not terminate it early.
1151  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1152  *       than count.  I have seen it be either the size of the full string or
1153  *       1 less than the size of the full string.  I have not seen it bear any
1154  *       resemblance to the portion that would fit.
1155  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1156  *         trailing intercharacter spacing and any trailing justification.
1157  *
1158  * FIXME
1159  * Currently we do this by measuring each character etc.  We should do it by
1160  * passing the request to the driver, perhaps by extending the
1161  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1162  * thinking about kerning issues and rounding issues in the justification.
1163  */
1164
1165 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1166                                    INT maxExt, LPINT lpnFit,
1167                                    LPINT alpDx, LPSIZE size )
1168 {
1169     INT nFit = 0;
1170     LPINT dxs = NULL;
1171     DC *dc;
1172     BOOL ret = FALSE;
1173     TEXTMETRICW tm;
1174     PHYSDEV dev;
1175
1176     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1177
1178     if (count < 0) return FALSE;
1179
1180     dc = get_dc_ptr(hdc);
1181     if (!dc) return FALSE;
1182
1183     GetTextMetricsW(hdc, &tm);
1184
1185     /* If we need to calculate nFit, then we need the partial extents even if
1186        the user hasn't provided us with an array.  */
1187     if (lpnFit)
1188     {
1189         dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1190         if (! dxs)
1191         {
1192             release_dc_ptr(dc);
1193             SetLastError(ERROR_OUTOFMEMORY);
1194             return FALSE;
1195         }
1196     }
1197     else
1198         dxs = alpDx;
1199
1200     dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1201     ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1202
1203     /* Perform device size to world size transformations.  */
1204     if (ret)
1205     {
1206         INT extra      = dc->charExtra,
1207         breakExtra = dc->breakExtra,
1208         breakRem   = dc->breakRem,
1209         i;
1210
1211         if (dxs)
1212         {
1213             for (i = 0; i < count; ++i)
1214             {
1215                 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1216                 dxs[i] += (i+1) * extra;
1217                 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1218                 {
1219                     dxs[i] += breakExtra;
1220                     if (breakRem > 0)
1221                     {
1222                         breakRem--;
1223                         dxs[i]++;
1224                     }
1225                 }
1226                 if (dxs[i] <= maxExt)
1227                     ++nFit;
1228             }
1229             breakRem = dc->breakRem;
1230         }
1231         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1232         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1233
1234         if (!dxs && count > 1 && (breakExtra || breakRem))
1235         {
1236             for (i = 0; i < count; i++)
1237             {
1238                 if (str[i] == tm.tmBreakChar)
1239                 {
1240                     size->cx += breakExtra;
1241                     if (breakRem > 0)
1242                     {
1243                         breakRem--;
1244                         (size->cx)++;
1245                     }
1246                 }
1247             }
1248         }
1249     }
1250
1251     if (lpnFit)
1252         *lpnFit = nFit;
1253
1254     if (! alpDx)
1255         HeapFree(GetProcessHeap(), 0, dxs);
1256
1257     release_dc_ptr( dc );
1258
1259     TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1260     return ret;
1261 }
1262
1263 /***********************************************************************
1264  *           GetTextMetricsA    (GDI32.@)
1265  */
1266 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1267 {
1268     TEXTMETRICW tm32;
1269
1270     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1271     FONT_TextMetricWToA( &tm32, metrics );
1272     return TRUE;
1273 }
1274
1275 /***********************************************************************
1276  *           GetTextMetricsW    (GDI32.@)
1277  */
1278 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1279 {
1280     PHYSDEV physdev;
1281     BOOL ret = FALSE;
1282     DC * dc = get_dc_ptr( hdc );
1283     if (!dc) return FALSE;
1284
1285     physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1286     ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1287
1288     if (ret)
1289     {
1290     /* device layer returns values in device units
1291      * therefore we have to convert them to logical */
1292
1293         metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1294         metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1295
1296 #define WDPTOLP(x) ((x<0)?                                      \
1297                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1298                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1299 #define HDPTOLP(y) ((y<0)?                                      \
1300                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1301                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1302
1303         metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1304         metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1305         metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1306         metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1307         metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1308         metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1309         metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1310         metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1311         ret = TRUE;
1312 #undef WDPTOLP
1313 #undef HDPTOLP
1314     TRACE("text metrics:\n"
1315           "    Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1316           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1317           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1318           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1319           "    PitchAndFamily = %02x\n"
1320           "    --------------------\n"
1321           "    InternalLeading = %i\n"
1322           "    Ascent = %i\n"
1323           "    Descent = %i\n"
1324           "    Height = %i\n",
1325           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1326           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1327           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1328           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1329           metrics->tmPitchAndFamily,
1330           metrics->tmInternalLeading,
1331           metrics->tmAscent,
1332           metrics->tmDescent,
1333           metrics->tmHeight );
1334     }
1335     release_dc_ptr( dc );
1336     return ret;
1337 }
1338
1339
1340 /***********************************************************************
1341  *              GetOutlineTextMetricsA (GDI32.@)
1342  * Gets metrics for TrueType fonts.
1343  *
1344  * NOTES
1345  *    If the supplied buffer isn't big enough Windows partially fills it up to
1346  *    its given length and returns that length.
1347  *
1348  * RETURNS
1349  *    Success: Non-zero or size of required buffer
1350  *    Failure: 0
1351  */
1352 UINT WINAPI GetOutlineTextMetricsA(
1353     HDC hdc,    /* [in]  Handle of device context */
1354     UINT cbData, /* [in]  Size of metric data array */
1355     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1356 {
1357     char buf[512], *ptr;
1358     UINT ret, needed;
1359     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1360     OUTLINETEXTMETRICA *output = lpOTM;
1361     INT left, len;
1362
1363     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1364         return 0;
1365     if(ret > sizeof(buf))
1366         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1367     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1368
1369     needed = sizeof(OUTLINETEXTMETRICA);
1370     if(lpOTMW->otmpFamilyName)
1371         needed += WideCharToMultiByte(CP_ACP, 0,
1372            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1373                                       NULL, 0, NULL, NULL);
1374     if(lpOTMW->otmpFaceName)
1375         needed += WideCharToMultiByte(CP_ACP, 0,
1376            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1377                                       NULL, 0, NULL, NULL);
1378     if(lpOTMW->otmpStyleName)
1379         needed += WideCharToMultiByte(CP_ACP, 0,
1380            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1381                                       NULL, 0, NULL, NULL);
1382     if(lpOTMW->otmpFullName)
1383         needed += WideCharToMultiByte(CP_ACP, 0,
1384            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1385                                       NULL, 0, NULL, NULL);
1386
1387     if(!lpOTM) {
1388         ret = needed;
1389         goto end;
1390     }
1391
1392     TRACE("needed = %d\n", needed);
1393     if(needed > cbData)
1394         /* Since the supplied buffer isn't big enough, we'll alloc one
1395            that is and memcpy the first cbData bytes into the lpOTM at
1396            the end. */
1397         output = HeapAlloc(GetProcessHeap(), 0, needed);
1398
1399     ret = output->otmSize = min(needed, cbData);
1400     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1401     output->otmFiller = 0;
1402     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1403     output->otmfsSelection = lpOTMW->otmfsSelection;
1404     output->otmfsType = lpOTMW->otmfsType;
1405     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1406     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1407     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1408     output->otmEMSquare = lpOTMW->otmEMSquare;
1409     output->otmAscent = lpOTMW->otmAscent;
1410     output->otmDescent = lpOTMW->otmDescent;
1411     output->otmLineGap = lpOTMW->otmLineGap;
1412     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1413     output->otmsXHeight = lpOTMW->otmsXHeight;
1414     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1415     output->otmMacAscent = lpOTMW->otmMacAscent;
1416     output->otmMacDescent = lpOTMW->otmMacDescent;
1417     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1418     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1419     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1420     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1421     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1422     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1423     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1424     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1425     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1426     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1427
1428
1429     ptr = (char*)(output + 1);
1430     left = needed - sizeof(*output);
1431
1432     if(lpOTMW->otmpFamilyName) {
1433         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1434         len = WideCharToMultiByte(CP_ACP, 0,
1435              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1436                                   ptr, left, NULL, NULL);
1437         left -= len;
1438         ptr += len;
1439     } else
1440         output->otmpFamilyName = 0;
1441
1442     if(lpOTMW->otmpFaceName) {
1443         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1444         len = WideCharToMultiByte(CP_ACP, 0,
1445              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1446                                   ptr, left, NULL, NULL);
1447         left -= len;
1448         ptr += len;
1449     } else
1450         output->otmpFaceName = 0;
1451
1452     if(lpOTMW->otmpStyleName) {
1453         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1454         len = WideCharToMultiByte(CP_ACP, 0,
1455              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1456                                   ptr, left, NULL, NULL);
1457         left -= len;
1458         ptr += len;
1459     } else
1460         output->otmpStyleName = 0;
1461
1462     if(lpOTMW->otmpFullName) {
1463         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1464         len = WideCharToMultiByte(CP_ACP, 0,
1465              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1466                                   ptr, left, NULL, NULL);
1467         left -= len;
1468     } else
1469         output->otmpFullName = 0;
1470
1471     assert(left == 0);
1472
1473     if(output != lpOTM) {
1474         memcpy(lpOTM, output, cbData);
1475         HeapFree(GetProcessHeap(), 0, output);
1476
1477         /* check if the string offsets really fit into the provided size */
1478         /* FIXME: should we check string length as well? */
1479         /* make sure that we don't read/write beyond the provided buffer */
1480         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1481         {
1482             if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1483                 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1484         }
1485
1486         /* make sure that we don't read/write beyond the provided buffer */
1487         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1488         {
1489             if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1490                 lpOTM->otmpFaceName = 0; /* doesn't fit */
1491         }
1492
1493             /* make sure that we don't read/write beyond the provided buffer */
1494         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1495         {
1496             if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1497                 lpOTM->otmpStyleName = 0; /* doesn't fit */
1498         }
1499
1500         /* make sure that we don't read/write beyond the provided buffer */
1501         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1502         {
1503             if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1504                 lpOTM->otmpFullName = 0; /* doesn't fit */
1505         }
1506     }
1507
1508 end:
1509     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1510         HeapFree(GetProcessHeap(), 0, lpOTMW);
1511
1512     return ret;
1513 }
1514
1515
1516 /***********************************************************************
1517  *           GetOutlineTextMetricsW [GDI32.@]
1518  */
1519 UINT WINAPI GetOutlineTextMetricsW(
1520     HDC hdc,    /* [in]  Handle of device context */
1521     UINT cbData, /* [in]  Size of metric data array */
1522     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1523 {
1524     DC *dc = get_dc_ptr( hdc );
1525     OUTLINETEXTMETRICW *output = lpOTM;
1526     PHYSDEV dev;
1527     UINT ret;
1528
1529     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1530     if(!dc) return 0;
1531
1532     dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1533     ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1534
1535     if (lpOTM && ret > cbData)
1536     {
1537         output = HeapAlloc(GetProcessHeap(), 0, ret);
1538         ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1539     }
1540
1541     if (lpOTM && ret)
1542     {
1543         output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1544         output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1545
1546 #define WDPTOLP(x) ((x<0)?                                      \
1547                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1548                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1549 #define HDPTOLP(y) ((y<0)?                                      \
1550                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1551                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1552
1553         output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1554         output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1555         output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1556         output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1557         output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1558         output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1559         output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1560         output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1561         output->otmAscent = HDPTOLP(output->otmAscent);
1562         output->otmDescent = HDPTOLP(output->otmDescent);
1563         output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1564         output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1565         output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1566         output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1567         output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1568         output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1569         output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1570         output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1571         output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1572         output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1573         output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1574         output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1575         output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1576         output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1577         output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1578         output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1579         output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1580         output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1581         output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1582         output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1583         output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1584         output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1585 #undef WDPTOLP
1586 #undef HDPTOLP
1587         if(output != lpOTM)
1588         {
1589             memcpy(lpOTM, output, cbData);
1590             HeapFree(GetProcessHeap(), 0, output);
1591             ret = cbData;
1592         }
1593     }
1594     release_dc_ptr(dc);
1595     return ret;
1596 }
1597
1598 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1599 {
1600     INT i, count = lastChar - firstChar + 1;
1601     UINT mbcp;
1602     UINT c;
1603     LPSTR str;
1604
1605     if (count <= 0)
1606         return NULL;
1607
1608     mbcp = GdiGetCodePage(hdc);
1609     switch (mbcp)
1610     {
1611     case 932:
1612     case 936:
1613     case 949:
1614     case 950:
1615     case 1361:
1616         if (lastChar > 0xffff)
1617             return NULL;
1618         if ((firstChar ^ lastChar) > 0xff)
1619             return NULL;
1620         break;
1621     default:
1622         if (lastChar > 0xff)
1623             return NULL;
1624         mbcp = 0;
1625         break;
1626     }
1627
1628     str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1629     if (str == NULL)
1630         return NULL;
1631
1632     for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1633     {
1634         if (mbcp) {
1635             if (c > 0xff)
1636                 str[i++] = (BYTE)(c >> 8);
1637             if (c <= 0xff && IsDBCSLeadByteEx(mbcp, c))
1638                 str[i] = 0x1f; /* FIXME: use default character */
1639             else
1640                 str[i] = (BYTE)c;
1641         }
1642         else
1643             str[i] = (BYTE)c;
1644     }
1645     str[i] = '\0';
1646
1647     *pByteLen = i;
1648
1649     return str;
1650 }
1651
1652 /***********************************************************************
1653  *           GetCharWidthW      (GDI32.@)
1654  *           GetCharWidth32W    (GDI32.@)
1655  */
1656 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1657                                LPINT buffer )
1658 {
1659     UINT i;
1660     BOOL ret;
1661     PHYSDEV dev;
1662     DC * dc = get_dc_ptr( hdc );
1663
1664     if (!dc) return FALSE;
1665
1666     dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1667     ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1668
1669     if (ret)
1670     {
1671         /* convert device units to logical */
1672         for( i = firstChar; i <= lastChar; i++, buffer++ )
1673             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1674     }
1675     release_dc_ptr( dc );
1676     return ret;
1677 }
1678
1679
1680 /***********************************************************************
1681  *           GetCharWidthA      (GDI32.@)
1682  *           GetCharWidth32A    (GDI32.@)
1683  */
1684 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1685                                LPINT buffer )
1686 {
1687     INT i, wlen;
1688     LPSTR str;
1689     LPWSTR wstr;
1690     BOOL ret = TRUE;
1691
1692     str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1693     if(str == NULL)
1694         return FALSE;
1695
1696     wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1697
1698     for(i = 0; i < wlen; i++)
1699     {
1700         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1701         {
1702             ret = FALSE;
1703             break;
1704         }
1705         buffer++;
1706     }
1707
1708     HeapFree(GetProcessHeap(), 0, str);
1709     HeapFree(GetProcessHeap(), 0, wstr);
1710
1711     return ret;
1712 }
1713
1714
1715 /* helper for nulldrv_ExtTextOut */
1716 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1717                                GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1718 {
1719     UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1720     static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1721     UINT indices[3] = {0, 0, 0x20};
1722     int i;
1723     DWORD ret, size;
1724     int stride;
1725
1726     indices[0] = index;
1727
1728     for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
1729     {
1730         index = indices[i];
1731         ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1732         if (ret != GDI_ERROR) break;
1733     }
1734
1735     if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1736     if (!image) return ERROR_SUCCESS;
1737
1738     image->ptr = NULL;
1739     image->free = NULL;
1740     if (!ret) return ERROR_SUCCESS; /* empty glyph */
1741
1742     stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1743     size = metrics->gmBlackBoxY * stride;
1744
1745     if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1746     image->is_copy = TRUE;
1747     image->free = free_heap_bits;
1748
1749     ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1750     if (ret == GDI_ERROR)
1751     {
1752         HeapFree( GetProcessHeap(), 0, image->ptr );
1753         return ERROR_NOT_FOUND;
1754     }
1755     return ERROR_SUCCESS;
1756 }
1757
1758 /* helper for nulldrv_ExtTextOut */
1759 static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
1760                                LPCWSTR str, UINT count, const INT *dx )
1761 {
1762     int i;
1763     RECT rect, bounds;
1764
1765     reset_bounds( &bounds );
1766     for (i = 0; i < count; i++)
1767     {
1768         GLYPHMETRICS metrics;
1769
1770         if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue;
1771
1772         rect.left   = x + metrics.gmptGlyphOrigin.x;
1773         rect.top    = y - metrics.gmptGlyphOrigin.y;
1774         rect.right  = rect.left + metrics.gmBlackBoxX;
1775         rect.bottom = rect.top  + metrics.gmBlackBoxY;
1776         add_bounds_rect( &bounds, &rect );
1777
1778         if (dx)
1779         {
1780             if (flags & ETO_PDY)
1781             {
1782                 x += dx[ i * 2 ];
1783                 y += dx[ i * 2 + 1];
1784             }
1785             else x += dx[ i ];
1786         }
1787         else
1788         {
1789             x += metrics.gmCellIncX;
1790             y += metrics.gmCellIncY;
1791         }
1792     }
1793     return bounds;
1794 }
1795
1796 /* helper for nulldrv_ExtTextOut */
1797 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1798                         const struct gdi_image_bits *image, const RECT *clip )
1799 {
1800     static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1801     UINT x, y, i, count, max_count;
1802     BYTE *ptr = image->ptr;
1803     int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1804     POINT *pts;
1805     RECT rect, clipped_rect;
1806
1807     rect.left   = origin_x  + metrics->gmptGlyphOrigin.x;
1808     rect.top    = origin_y  - metrics->gmptGlyphOrigin.y;
1809     rect.right  = rect.left + metrics->gmBlackBoxX;
1810     rect.bottom = rect.top  + metrics->gmBlackBoxY;
1811     if (!clip) clipped_rect = rect;
1812     else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1813
1814     max_count = (metrics->gmBlackBoxX + 1) * metrics->gmBlackBoxY;
1815     pts = HeapAlloc( GetProcessHeap(), 0, max_count * sizeof(*pts) );
1816     if (!pts) return;
1817
1818     count = 0;
1819     ptr += (clipped_rect.top - rect.top) * stride;
1820     for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1821     {
1822         for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1823         {
1824             while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1825             pts[count].x = rect.left + x;
1826             while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1827             pts[count + 1].x = rect.left + x;
1828             if (pts[count + 1].x > pts[count].x)
1829             {
1830                 pts[count].y = pts[count + 1].y = y;
1831                 count += 2;
1832             }
1833         }
1834     }
1835     assert( count <= max_count );
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, 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, 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, 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-scalable fonts */
2695     dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
2696     if (!dev->funcs->pGetTextMetrics( dev, &tm ) || !(tm.tmPitchAndFamily & TMPF_VECTOR))
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 hidden, LPCWSTR resource_file,
2877                                          LPCWSTR font_file, LPCWSTR font_path )
2878 {
2879     TRACE("(%d, %s, %s, %s)\n", hidden, debugstr_w(resource_file),
2880           debugstr_w(font_file), debugstr_w(font_path) );
2881
2882     return WineEngCreateScalableFontResource( hidden, resource_file,
2883                                               font_file, font_path );
2884 }
2885
2886 /*************************************************************************
2887  *             GetKerningPairsA   (GDI32.@)
2888  */
2889 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2890                                LPKERNINGPAIR kern_pairA )
2891 {
2892     UINT cp;
2893     CPINFO cpi;
2894     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2895     KERNINGPAIR *kern_pairW;
2896
2897     if (!cPairs && kern_pairA)
2898     {
2899         SetLastError(ERROR_INVALID_PARAMETER);
2900         return 0;
2901     }
2902
2903     cp = GdiGetCodePage(hDC);
2904
2905     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2906      * to fail on an invalid character for CP_SYMBOL.
2907      */
2908     cpi.DefaultChar[0] = 0;
2909     if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2910     {
2911         FIXME("Can't find codepage %u info\n", cp);
2912         return 0;
2913     }
2914
2915     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2916     if (!total_kern_pairs) return 0;
2917
2918     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2919     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2920
2921     for (i = 0; i < total_kern_pairs; i++)
2922     {
2923         char first, second;
2924
2925         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2926             continue;
2927
2928         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2929             continue;
2930
2931         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2932             continue;
2933
2934         if (kern_pairA)
2935         {
2936             if (kern_pairs_copied >= cPairs) break;
2937
2938             kern_pairA->wFirst = (BYTE)first;
2939             kern_pairA->wSecond = (BYTE)second;
2940             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2941             kern_pairA++;
2942         }
2943         kern_pairs_copied++;
2944     }
2945
2946     HeapFree(GetProcessHeap(), 0, kern_pairW);
2947
2948     return kern_pairs_copied;
2949 }
2950
2951 /*************************************************************************
2952  *             GetKerningPairsW   (GDI32.@)
2953  */
2954 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2955                                  LPKERNINGPAIR lpKerningPairs )
2956 {
2957     DC *dc;
2958     DWORD ret;
2959     PHYSDEV dev;
2960
2961     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2962
2963     if (!cPairs && lpKerningPairs)
2964     {
2965         SetLastError(ERROR_INVALID_PARAMETER);
2966         return 0;
2967     }
2968
2969     dc = get_dc_ptr(hDC);
2970     if (!dc) return 0;
2971
2972     dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2973     ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2974     release_dc_ptr( dc );
2975     return ret;
2976 }
2977
2978 /*************************************************************************
2979  * TranslateCharsetInfo [GDI32.@]
2980  *
2981  * Fills a CHARSETINFO structure for a character set, code page, or
2982  * font. This allows making the correspondence between different labels
2983  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2984  * of the same encoding.
2985  *
2986  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2987  * only one codepage should be set in *lpSrc.
2988  *
2989  * RETURNS
2990  *   TRUE on success, FALSE on failure.
2991  *
2992  */
2993 BOOL WINAPI TranslateCharsetInfo(
2994   LPDWORD lpSrc, /* [in]
2995        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2996        if flags == TCI_SRCCHARSET: a character set value
2997        if flags == TCI_SRCCODEPAGE: a code page value
2998                  */
2999   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
3000   DWORD flags /* [in] determines interpretation of lpSrc */)
3001 {
3002     int index = 0;
3003     switch (flags) {
3004     case TCI_SRCFONTSIG:
3005       while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
3006       break;
3007     case TCI_SRCCODEPAGE:
3008       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
3009       break;
3010     case TCI_SRCCHARSET:
3011       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
3012       break;
3013     default:
3014       return FALSE;
3015     }
3016     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
3017     *lpCs = FONT_tci[index];
3018     return TRUE;
3019 }
3020
3021 /*************************************************************************
3022  *             GetFontLanguageInfo   (GDI32.@)
3023  */
3024 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
3025 {
3026         FONTSIGNATURE fontsig;
3027         static const DWORD GCP_DBCS_MASK=0x003F0000,
3028                 GCP_DIACRITIC_MASK=0x00000000,
3029                 FLI_GLYPHS_MASK=0x00000000,
3030                 GCP_GLYPHSHAPE_MASK=0x00000040,
3031                 GCP_KASHIDA_MASK=0x00000000,
3032                 GCP_LIGATE_MASK=0x00000000,
3033                 GCP_USEKERNING_MASK=0x00000000,
3034                 GCP_REORDER_MASK=0x00000060;
3035
3036         DWORD result=0;
3037
3038         GetTextCharsetInfo( hdc, &fontsig, 0 );
3039         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3040
3041         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
3042                 result|=GCP_DBCS;
3043
3044         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
3045                 result|=GCP_DIACRITIC;
3046
3047         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
3048                 result|=FLI_GLYPHS;
3049
3050         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
3051                 result|=GCP_GLYPHSHAPE;
3052
3053         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
3054                 result|=GCP_KASHIDA;
3055
3056         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
3057                 result|=GCP_LIGATE;
3058
3059         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
3060                 result|=GCP_USEKERNING;
3061
3062         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3063         if( GetTextAlign( hdc) & TA_RTLREADING )
3064             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
3065                     result|=GCP_REORDER;
3066
3067         return result;
3068 }
3069
3070
3071 /*************************************************************************
3072  * GetFontData [GDI32.@]
3073  *
3074  * Retrieve data for TrueType font.
3075  *
3076  * RETURNS
3077  *
3078  * success: Number of bytes returned
3079  * failure: GDI_ERROR
3080  *
3081  * NOTES
3082  *
3083  * Calls SetLastError()
3084  *
3085  */
3086 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
3087     LPVOID buffer, DWORD length)
3088 {
3089     DC *dc = get_dc_ptr(hdc);
3090     PHYSDEV dev;
3091     DWORD ret;
3092
3093     if(!dc) return GDI_ERROR;
3094
3095     dev = GET_DC_PHYSDEV( dc, pGetFontData );
3096     ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3097     release_dc_ptr( dc );
3098     return ret;
3099 }
3100
3101 /*************************************************************************
3102  * GetGlyphIndicesA [GDI32.@]
3103  */
3104 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3105                               LPWORD pgi, DWORD flags)
3106 {
3107     DWORD ret;
3108     WCHAR *lpstrW;
3109     INT countW;
3110
3111     TRACE("(%p, %s, %d, %p, 0x%x)\n",
3112           hdc, debugstr_an(lpstr, count), count, pgi, flags);
3113
3114     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3115     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3116     HeapFree(GetProcessHeap(), 0, lpstrW);
3117
3118     return ret;
3119 }
3120
3121 /*************************************************************************
3122  * GetGlyphIndicesW [GDI32.@]
3123  */
3124 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3125                               LPWORD pgi, DWORD flags)
3126 {
3127     DC *dc = get_dc_ptr(hdc);
3128     PHYSDEV dev;
3129     DWORD ret;
3130
3131     TRACE("(%p, %s, %d, %p, 0x%x)\n",
3132           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3133
3134     if(!dc) return GDI_ERROR;
3135
3136     dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3137     ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3138     release_dc_ptr( dc );
3139     return ret;
3140 }
3141
3142 /*************************************************************************
3143  * GetCharacterPlacementA [GDI32.@]
3144  *
3145  * See GetCharacterPlacementW.
3146  *
3147  * NOTES:
3148  *  the web browser control of ie4 calls this with dwFlags=0
3149  */
3150 DWORD WINAPI
3151 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3152                          INT nMaxExtent, GCP_RESULTSA *lpResults,
3153                          DWORD dwFlags)
3154 {
3155     WCHAR *lpStringW;
3156     INT uCountW;
3157     GCP_RESULTSW resultsW;
3158     DWORD ret;
3159     UINT font_cp;
3160
3161     TRACE("%s, %d, %d, 0x%08x\n",
3162           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3163
3164     /* both structs are equal in size */
3165     memcpy(&resultsW, lpResults, sizeof(resultsW));
3166
3167     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3168     if(lpResults->lpOutString)
3169         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3170
3171     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3172
3173     lpResults->nGlyphs = resultsW.nGlyphs;
3174     lpResults->nMaxFit = resultsW.nMaxFit;
3175
3176     if(lpResults->lpOutString) {
3177         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3178                             lpResults->lpOutString, uCount, NULL, NULL );
3179     }
3180
3181     HeapFree(GetProcessHeap(), 0, lpStringW);
3182     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3183
3184     return ret;
3185 }
3186
3187 /*************************************************************************
3188  * GetCharacterPlacementW [GDI32.@]
3189  *
3190  *   Retrieve information about a string. This includes the width, reordering,
3191  *   Glyphing and so on.
3192  *
3193  * RETURNS
3194  *
3195  *   The width and height of the string if successful, 0 if failed.
3196  *
3197  * BUGS
3198  *
3199  *   All flags except GCP_REORDER are not yet implemented.
3200  *   Reordering is not 100% compliant to the Windows BiDi method.
3201  *   Caret positioning is not yet implemented for BiDi.
3202  *   Classes are not yet implemented.
3203  *
3204  */
3205 DWORD WINAPI
3206 GetCharacterPlacementW(
3207                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
3208                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
3209                 INT uCount,             /* [in] Number of WORDS in string. */
3210                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
3211                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3212                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
3213                 )
3214 {
3215     DWORD ret=0;
3216     SIZE size;
3217     UINT i, nSet;
3218
3219     TRACE("%s, %d, %d, 0x%08x\n",
3220           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3221
3222     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3223           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3224             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3225             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3226             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3227
3228     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
3229     if(lpResults->lpClass)      FIXME("classes not implemented\n");
3230     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3231         FIXME("Caret positions for complex scripts not implemented\n");
3232
3233         nSet = (UINT)uCount;
3234         if(nSet > lpResults->nGlyphs)
3235                 nSet = lpResults->nGlyphs;
3236
3237         /* return number of initialized fields */
3238         lpResults->nGlyphs = nSet;
3239
3240         if((dwFlags&GCP_REORDER)==0 )
3241         {
3242                 /* Treat the case where no special handling was requested in a fastpath way */
3243                 /* copy will do if the GCP_REORDER flag is not set */
3244                 if(lpResults->lpOutString)
3245                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3246
3247                 if(lpResults->lpOrder)
3248                 {
3249                         for(i = 0; i < nSet; i++)
3250                                 lpResults->lpOrder[i] = i;
3251                 }
3252         } else
3253         {
3254             BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3255                           nSet, lpResults->lpOrder, NULL, NULL );
3256         }
3257
3258         /* FIXME: Will use the placement chars */
3259         if (lpResults->lpDx)
3260         {
3261                 int c;
3262                 for (i = 0; i < nSet; i++)
3263                 {
3264                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3265                                 lpResults->lpDx[i]= c;
3266                 }
3267         }
3268
3269     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3270     {
3271         int pos = 0;
3272        
3273         lpResults->lpCaretPos[0] = 0;
3274         for (i = 1; i < nSet; i++)
3275             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3276                 lpResults->lpCaretPos[i] = (pos += size.cx);
3277     }
3278    
3279     if(lpResults->lpGlyphs)
3280         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3281
3282     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3283       ret = MAKELONG(size.cx, size.cy);
3284
3285     return ret;
3286 }
3287
3288 /*************************************************************************
3289  *      GetCharABCWidthsFloatA [GDI32.@]
3290  *
3291  * See GetCharABCWidthsFloatW.
3292  */
3293 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3294 {
3295     INT i, wlen;
3296     LPSTR str;
3297     LPWSTR wstr;
3298     BOOL ret = TRUE;
3299
3300     str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3301     if (str == NULL)
3302         return FALSE;
3303
3304     wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3305
3306     for (i = 0; i < wlen; i++)
3307     {
3308         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3309         {
3310             ret = FALSE;
3311             break;
3312         }
3313         abcf++;
3314     }
3315
3316     HeapFree( GetProcessHeap(), 0, str );
3317     HeapFree( GetProcessHeap(), 0, wstr );
3318
3319     return ret;
3320 }
3321
3322 /*************************************************************************
3323  *      GetCharABCWidthsFloatW [GDI32.@]
3324  *
3325  * Retrieves widths of a range of characters.
3326  *
3327  * PARAMS
3328  *    hdc   [I] Handle to device context.
3329  *    first [I] First character in range to query.
3330  *    last  [I] Last character in range to query.
3331  *    abcf  [O] Array of LPABCFLOAT structures.
3332  *
3333  * RETURNS
3334  *    Success: TRUE
3335  *    Failure: FALSE
3336  */
3337 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3338 {
3339     UINT i;
3340     ABC *abc;
3341     PHYSDEV dev;
3342     BOOL ret = FALSE;
3343     DC *dc = get_dc_ptr( hdc );
3344
3345     TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3346
3347     if (!dc) return FALSE;
3348
3349     if (!abcf) goto done;
3350     if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3351
3352     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3353     ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3354     if (ret)
3355     {
3356         /* convert device units to logical */
3357         for (i = first; i <= last; i++, abcf++)
3358         {
3359             abcf->abcfA = abc[i - first].abcA * dc->xformVport2World.eM11;
3360             abcf->abcfB = abc[i - first].abcB * dc->xformVport2World.eM11;
3361             abcf->abcfC = abc[i - first].abcC * dc->xformVport2World.eM11;
3362         }
3363     }
3364     HeapFree( GetProcessHeap(), 0, abc );
3365
3366 done:
3367     release_dc_ptr( dc );
3368     return ret;
3369 }
3370
3371 /*************************************************************************
3372  *      GetCharWidthFloatA [GDI32.@]
3373  */
3374 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3375                                     UINT iLastChar, PFLOAT pxBuffer)
3376 {
3377     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3378     return 0;
3379 }
3380
3381 /*************************************************************************
3382  *      GetCharWidthFloatW [GDI32.@]
3383  */
3384 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3385                                     UINT iLastChar, PFLOAT pxBuffer)
3386 {
3387     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3388     return 0;
3389 }
3390
3391
3392 /***********************************************************************
3393  *                                                                     *
3394  *           Font Resource API                                         *
3395  *                                                                     *
3396  ***********************************************************************/
3397
3398 /***********************************************************************
3399  *           AddFontResourceA    (GDI32.@)
3400  */
3401 INT WINAPI AddFontResourceA( LPCSTR str )
3402 {
3403     return AddFontResourceExA( str, 0, NULL);
3404 }
3405
3406 /***********************************************************************
3407  *           AddFontResourceW    (GDI32.@)
3408  */
3409 INT WINAPI AddFontResourceW( LPCWSTR str )
3410 {
3411     return AddFontResourceExW(str, 0, NULL);
3412 }
3413
3414
3415 /***********************************************************************
3416  *           AddFontResourceExA    (GDI32.@)
3417  */
3418 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3419 {
3420     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3421     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3422     INT ret;
3423
3424     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3425     ret = AddFontResourceExW(strW, fl, pdv);
3426     HeapFree(GetProcessHeap(), 0, strW);
3427     return ret;
3428 }
3429
3430 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3431 {
3432     HRSRC rsrc = FindResourceW(hModule, name, type);
3433     HGLOBAL hMem = LoadResource(hModule, rsrc);
3434     LPVOID *pMem = LockResource(hMem);
3435     int *num_total = (int *)lParam;
3436     DWORD num_in_res;
3437
3438     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3439     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3440     {
3441         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3442         return FALSE;
3443     }
3444
3445     *num_total += num_in_res;
3446     return TRUE;
3447 }
3448
3449 static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
3450 {
3451     HANDLE file, mapping;
3452     void *ptr;
3453
3454     file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
3455     if (file == INVALID_HANDLE_VALUE) return NULL;
3456
3457     if (!GetFileSizeEx( file, size ) || size->u.HighPart)
3458     {
3459         CloseHandle( file );
3460         return NULL;
3461     }
3462
3463     mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
3464     CloseHandle( file );
3465     if (!mapping) return NULL;
3466
3467     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
3468     CloseHandle( mapping );
3469
3470     return ptr;
3471 }
3472
3473 static WCHAR *get_scalable_filename( const WCHAR *res )
3474 {
3475     LARGE_INTEGER size;
3476     BYTE *ptr = map_file( res, &size );
3477     const IMAGE_DOS_HEADER *dos;
3478     const IMAGE_OS2_HEADER *ne;
3479     WCHAR *name = NULL;
3480     WORD rsrc_off, align, type_id, count;
3481     DWORD res_off, res_len, i;
3482     int len;
3483
3484     if (!ptr) return NULL;
3485
3486     if (size.u.LowPart < sizeof( *dos )) goto fail;
3487     dos = (const IMAGE_DOS_HEADER *)ptr;
3488     if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
3489     if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
3490     ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
3491     rsrc_off = dos->e_lfanew + ne->ne_rsrctab;
3492     if (size.u.LowPart < rsrc_off + 10) goto fail;
3493     align = *(WORD *)(ptr + rsrc_off);
3494     rsrc_off += 2;
3495     type_id = *(WORD *)(ptr + rsrc_off);
3496     while (type_id && type_id != 0x80cc)
3497     {
3498         count = *(WORD *)(ptr + rsrc_off + 2);
3499         rsrc_off += 8 + count * 12;
3500         if (size.u.LowPart < rsrc_off + 8) goto fail;
3501         type_id = *(WORD *)(ptr + rsrc_off);
3502     }
3503     if (!type_id) goto fail;
3504     count = *(WORD *)(ptr + rsrc_off + 2);
3505     if (size.u.LowPart < rsrc_off + 8 + count * 12) goto fail;
3506
3507     res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
3508     res_len = *(WORD *)(ptr + rsrc_off + 10) << align;
3509     if (size.u.LowPart < res_off + res_len) goto fail;
3510
3511     for (i = 0; i < res_len; i++)
3512         if (ptr[ res_off + i ] == 0) break;
3513     if (i == res_len) goto fail;
3514
3515     len = MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, NULL, 0 );
3516     name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3517     if (name) MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, name, len );
3518
3519 fail:
3520     UnmapViewOfFile( ptr );
3521     return name;
3522 }
3523
3524 /***********************************************************************
3525  *           AddFontResourceExW    (GDI32.@)
3526  */
3527 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3528 {
3529     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3530     WCHAR *filename;
3531
3532     if (ret == 0)
3533     {
3534         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3535         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3536         if (hModule != NULL)
3537         {
3538             int num_resources = 0;
3539             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3540
3541             TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3542                 wine_dbgstr_w(str));
3543             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3544                 ret = num_resources;
3545             FreeLibrary(hModule);
3546         }
3547         else if ((filename = get_scalable_filename( str )) != NULL)
3548         {
3549             ret = WineEngAddFontResourceEx( filename, fl, pdv );
3550             HeapFree( GetProcessHeap(), 0, filename );
3551         }
3552     }
3553     return ret;
3554 }
3555
3556 /***********************************************************************
3557  *           RemoveFontResourceA    (GDI32.@)
3558  */
3559 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3560 {
3561     return RemoveFontResourceExA(str, 0, 0);
3562 }
3563
3564 /***********************************************************************
3565  *           RemoveFontResourceW    (GDI32.@)
3566  */
3567 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3568 {
3569     return RemoveFontResourceExW(str, 0, 0);
3570 }
3571
3572 /***********************************************************************
3573  *           AddFontMemResourceEx    (GDI32.@)
3574  */
3575 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3576 {
3577     HANDLE ret;
3578     DWORD num_fonts;
3579
3580     if (!pbFont || !cbFont || !pcFonts)
3581     {
3582         SetLastError(ERROR_INVALID_PARAMETER);
3583         return NULL;
3584     }
3585
3586     ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3587     if (ret)
3588     {
3589         __TRY
3590         {
3591             *pcFonts = num_fonts;
3592         }
3593         __EXCEPT_PAGE_FAULT
3594         {
3595             WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3596             RemoveFontMemResourceEx(ret);
3597             ret = 0;
3598         }
3599         __ENDTRY
3600     }
3601     return ret;
3602 }
3603
3604 /***********************************************************************
3605  *           RemoveFontMemResourceEx    (GDI32.@)
3606  */
3607 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3608 {
3609     FIXME("(%p) stub\n", fh);
3610     return TRUE;
3611 }
3612
3613 /***********************************************************************
3614  *           RemoveFontResourceExA    (GDI32.@)
3615  */
3616 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3617 {
3618     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3619     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3620     INT ret;
3621
3622     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3623     ret = RemoveFontResourceExW(strW, fl, pdv);
3624     HeapFree(GetProcessHeap(), 0, strW);
3625     return ret;
3626 }
3627
3628 /***********************************************************************
3629  *           RemoveFontResourceExW    (GDI32.@)
3630  */
3631 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3632 {
3633     return WineEngRemoveFontResourceEx(str, fl, pdv);
3634 }
3635
3636 /***********************************************************************
3637  *           GetTextCharset    (GDI32.@)
3638  */
3639 UINT WINAPI GetTextCharset(HDC hdc)
3640 {
3641     /* MSDN docs say this is equivalent */
3642     return GetTextCharsetInfo(hdc, NULL, 0);
3643 }
3644
3645 /***********************************************************************
3646  *           GetTextCharsetInfo    (GDI32.@)
3647  */
3648 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3649 {
3650     UINT ret = DEFAULT_CHARSET;
3651     DC *dc = get_dc_ptr(hdc);
3652     PHYSDEV dev;
3653
3654     if (dc)
3655     {
3656         dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3657         ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3658         release_dc_ptr( dc );
3659     }
3660
3661     if (ret == DEFAULT_CHARSET && fs)
3662         memset(fs, 0, sizeof(FONTSIGNATURE));
3663     return ret;
3664 }
3665
3666 /***********************************************************************
3667  *           GdiGetCharDimensions    (GDI32.@)
3668  *
3669  * Gets the average width of the characters in the English alphabet.
3670  *
3671  * PARAMS
3672  *  hdc    [I] Handle to the device context to measure on.
3673  *  lptm   [O] Pointer to memory to store the text metrics into.
3674  *  height [O] On exit, the maximum height of characters in the English alphabet.
3675  *
3676  * RETURNS
3677  *  The average width of characters in the English alphabet.
3678  *
3679  * NOTES
3680  *  This function is used by the dialog manager to get the size of a dialog
3681  *  unit. It should also be used by other pieces of code that need to know
3682  *  the size of a dialog unit in logical units without having access to the
3683  *  window handle of the dialog.
3684  *  Windows caches the font metrics from this function, but we don't and
3685  *  there doesn't appear to be an immediate advantage to do so.
3686  *
3687  * SEE ALSO
3688  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3689  */
3690 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3691 {
3692     SIZE sz;
3693     static const WCHAR alphabet[] = {
3694         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3695         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3696         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3697
3698     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3699
3700     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3701
3702     if (height) *height = sz.cy;
3703     return (sz.cx / 26 + 1) / 2;
3704 }
3705
3706 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3707 {
3708     FIXME("(%d): stub\n", fEnableEUDC);
3709     return FALSE;
3710 }
3711
3712 /***********************************************************************
3713  *           GetCharWidthI    (GDI32.@)
3714  *
3715  * Retrieve widths of characters.
3716  *
3717  * PARAMS
3718  *  hdc    [I] Handle to a device context.
3719  *  first  [I] First glyph in range to query.
3720  *  count  [I] Number of glyph indices to query.
3721  *  glyphs [I] Array of glyphs to query.
3722  *  buffer [O] Buffer to receive character widths.
3723  *
3724  * NOTES
3725  *  Only works with TrueType fonts.
3726  *
3727  * RETURNS
3728  *  Success: TRUE
3729  *  Failure: FALSE
3730  */
3731 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3732 {
3733     ABC *abc;
3734     unsigned int i;
3735
3736     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3737
3738     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3739         return FALSE;
3740
3741     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3742     {
3743         HeapFree(GetProcessHeap(), 0, abc);
3744         return FALSE;
3745     }
3746
3747     for (i = 0; i < count; i++)
3748         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3749
3750     HeapFree(GetProcessHeap(), 0, abc);
3751     return TRUE;
3752 }
3753
3754 /***********************************************************************
3755  *           GetFontUnicodeRanges    (GDI32.@)
3756  *
3757  *  Retrieve a list of supported Unicode characters in a font.
3758  *
3759  *  PARAMS
3760  *   hdc  [I] Handle to a device context.
3761  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3762  *
3763  *  RETURNS
3764  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3765  *   Failure: 0
3766  *
3767  */
3768 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3769 {
3770     DWORD ret;
3771     PHYSDEV dev;
3772     DC *dc = get_dc_ptr(hdc);
3773
3774     TRACE("(%p, %p)\n", hdc, lpgs);
3775
3776     if (!dc) return 0;
3777
3778     dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3779     ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3780     release_dc_ptr(dc);
3781     return ret;
3782 }
3783
3784
3785 /*************************************************************
3786  *           FontIsLinked    (GDI32.@)
3787  */
3788 BOOL WINAPI FontIsLinked(HDC hdc)
3789 {
3790     DC *dc = get_dc_ptr(hdc);
3791     PHYSDEV dev;
3792     BOOL ret;
3793
3794     if (!dc) return FALSE;
3795     dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3796     ret = dev->funcs->pFontIsLinked( dev );
3797     release_dc_ptr(dc);
3798     TRACE("returning %d\n", ret);
3799     return ret;
3800 }
3801
3802 /*************************************************************
3803  *           GdiRealizationInfo    (GDI32.@)
3804  *
3805  * Returns a structure that contains some font information.
3806  */
3807 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3808 {
3809     DC *dc = get_dc_ptr(hdc);
3810     PHYSDEV dev;
3811     BOOL ret;
3812
3813     if (!dc) return FALSE;
3814     dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3815     ret = dev->funcs->pGdiRealizationInfo( dev, info );
3816     release_dc_ptr(dc);
3817     return ret;
3818 }