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