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