gdi32: Add more parameter checks in GdiGradientFill.
[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         RECT clip;
1867
1868         dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
1869         src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
1870         if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
1871         if (get_clip_box( dc, &clip )) intersect_rect( &src.visrect, &src.visrect, &clip );
1872         if (is_rect_empty( &src.visrect )) return TRUE;
1873
1874         /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1875         src.x = src.visrect.left;
1876         src.y = src.visrect.top;
1877         src.width = src.visrect.right - src.visrect.left;
1878         src.height = src.visrect.bottom - src.visrect.top;
1879         dst = src;
1880         if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
1881             (src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
1882         {
1883             /* we can avoid the GetImage, just query the needed format */
1884             memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
1885             info->bmiHeader.biSize   = sizeof(info->bmiHeader);
1886             info->bmiHeader.biWidth  = src.width;
1887             info->bmiHeader.biHeight = -src.height;
1888             err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, NULL, NULL, NULL, 0 );
1889             if (!err || err == ERROR_BAD_FORMAT)
1890             {
1891                 /* make the source rectangle relative to the source bits */
1892                 src.x = src.y = 0;
1893                 src.visrect.left = src.visrect.top = 0;
1894                 src.visrect.right = src.width;
1895                 src.visrect.bottom = src.height;
1896
1897                 bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1898                 if (!bits.ptr) return ERROR_OUTOFMEMORY;
1899                 bits.is_copy = TRUE;
1900                 bits.free = free_heap_bits;
1901                 err = ERROR_SUCCESS;
1902             }
1903         }
1904         else
1905         {
1906             PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
1907             err = src_dev->funcs->pGetImage( src_dev, 0, info, &bits, &src );
1908             if (!err && !bits.is_copy)
1909             {
1910                 void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1911                 if (!ptr)
1912                 {
1913                     if (bits.free) bits.free( &bits );
1914                     return ERROR_OUTOFMEMORY;
1915                 }
1916                 memcpy( ptr, bits.ptr, get_dib_image_size( info ));
1917                 if (bits.free) bits.free( &bits );
1918                 bits.ptr = ptr;
1919                 bits.is_copy = TRUE;
1920                 bits.free = free_heap_bits;
1921             }
1922         }
1923         if (!err)
1924         {
1925             /* make x,y relative to the image bits */
1926             x += src.visrect.left - dst.visrect.left;
1927             y += src.visrect.top - dst.visrect.top;
1928             render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
1929                                        aa_flags, str, count, dx );
1930             err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, &bits, &src, &dst, SRCCOPY );
1931             if (bits.free) bits.free( &bits );
1932             return !err;
1933         }
1934     }
1935
1936     pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
1937     orig = SelectObject( dev->hdc, pen );
1938
1939     for (i = 0; i < count; i++)
1940     {
1941         GLYPHMETRICS metrics;
1942         struct gdi_image_bits image;
1943
1944         err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
1945         if (err) continue;
1946
1947         if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
1948         if (image.free) image.free( &image );
1949
1950         if (dx)
1951         {
1952             if (flags & ETO_PDY)
1953             {
1954                 x += dx[ i * 2 ];
1955                 y += dx[ i * 2 + 1];
1956             }
1957             else x += dx[ i ];
1958         }
1959         else
1960         {
1961             x += metrics.gmCellIncX;
1962             y += metrics.gmCellIncY;
1963         }
1964     }
1965
1966     SelectObject( dev->hdc, orig );
1967     DeleteObject( pen );
1968     return TRUE;
1969 }
1970
1971
1972 /***********************************************************************
1973  *           ExtTextOutA    (GDI32.@)
1974  *
1975  * See ExtTextOutW.
1976  */
1977 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1978                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1979 {
1980     INT wlen;
1981     UINT codepage;
1982     LPWSTR p;
1983     BOOL ret;
1984     LPINT lpDxW = NULL;
1985
1986     if (flags & ETO_GLYPH_INDEX)
1987         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1988
1989     p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1990
1991     if (lpDx) {
1992         unsigned int i = 0, j = 0;
1993
1994         /* allocate enough for a ETO_PDY */
1995         lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1996         while(i < count) {
1997             if(IsDBCSLeadByteEx(codepage, str[i]))
1998             {
1999                 if(flags & ETO_PDY)
2000                 {
2001                     lpDxW[j++] = lpDx[i * 2]     + lpDx[(i + 1) * 2];
2002                     lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
2003                 }
2004                 else
2005                     lpDxW[j++] = lpDx[i] + lpDx[i + 1];
2006                 i = i + 2;
2007             }
2008             else
2009             {
2010                 if(flags & ETO_PDY)
2011                 {
2012                     lpDxW[j++] = lpDx[i * 2];
2013                     lpDxW[j++] = lpDx[i * 2 + 1];
2014                 }
2015                 else
2016                     lpDxW[j++] = lpDx[i];
2017                 i = i + 1;
2018             }
2019         }
2020     }
2021
2022     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
2023
2024     HeapFree( GetProcessHeap(), 0, p );
2025     HeapFree( GetProcessHeap(), 0, lpDxW );
2026     return ret;
2027 }
2028
2029
2030 /***********************************************************************
2031  *           ExtTextOutW    (GDI32.@)
2032  *
2033  * Draws text using the currently selected font, background color, and text color.
2034  * 
2035  * 
2036  * PARAMS
2037  *    x,y    [I] coordinates of string
2038  *    flags  [I]
2039  *        ETO_GRAYED - undocumented on MSDN
2040  *        ETO_OPAQUE - use background color for fill the rectangle
2041  *        ETO_CLIPPED - clipping text to the rectangle
2042  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2043  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
2044  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2045  *                         Affects BiDi ordering
2046  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2047  *        ETO_PDY - unimplemented
2048  *        ETO_NUMERICSLATIN - unimplemented always assumed -
2049  *                            do not translate numbers into locale representations
2050  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2051  *    lprect [I] dimensions for clipping or/and opaquing
2052  *    str    [I] text string
2053  *    count  [I] number of symbols in string
2054  *    lpDx   [I] optional parameter with distance between drawing characters
2055  *
2056  * RETURNS
2057  *    Success: TRUE
2058  *    Failure: FALSE
2059  */
2060 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
2061                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
2062 {
2063     BOOL ret = FALSE;
2064     LPWSTR reordered_str = (LPWSTR)str;
2065     WORD *glyphs = NULL;
2066     UINT align = GetTextAlign( hdc );
2067     DWORD layout = GetLayout( hdc );
2068     POINT pt;
2069     TEXTMETRICW tm;
2070     LOGFONTW lf;
2071     double cosEsc, sinEsc;
2072     INT char_extra;
2073     SIZE sz;
2074     RECT rc;
2075     BOOL done_extents = FALSE;
2076     POINT *deltas = NULL, width = {0, 0};
2077     DWORD type;
2078     DC * dc = get_dc_ptr( hdc );
2079     PHYSDEV physdev;
2080     INT breakRem;
2081     static int quietfixme = 0;
2082
2083     if (!dc) return FALSE;
2084
2085     breakRem = dc->breakRem;
2086
2087     if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
2088     {
2089         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2090         quietfixme = 1;
2091     }
2092
2093     update_dc( dc );
2094     physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
2095     type = GetObjectType(hdc);
2096     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
2097     {
2098         ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
2099         release_dc_ptr( dc );
2100         return ret;
2101     }
2102
2103     if (!lprect)
2104         flags &= ~ETO_CLIPPED;
2105
2106     if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
2107     if (layout & LAYOUT_RTL)
2108     {
2109         if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
2110         align ^= TA_RTLREADING;
2111     }
2112
2113     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
2114     {
2115         INT cGlyphs;
2116         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
2117
2118         BIDI_Reorder( hdc, str, count, GCP_REORDER,
2119                       (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
2120                       reordered_str, count, NULL, &glyphs, &cGlyphs);
2121
2122         flags |= ETO_IGNORELANGUAGE;
2123         if (glyphs)
2124         {
2125             flags |= ETO_GLYPH_INDEX;
2126             if (cGlyphs != count)
2127                 count = cGlyphs;
2128         }
2129     }
2130     else if(flags & ETO_GLYPH_INDEX)
2131         glyphs = reordered_str;
2132
2133     TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
2134           wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
2135     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
2136
2137     if(align & TA_UPDATECP)
2138     {
2139         GetCurrentPositionEx( hdc, &pt );
2140         x = pt.x;
2141         y = pt.y;
2142     }
2143
2144     GetTextMetricsW(hdc, &tm);
2145     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
2146
2147     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
2148         lf.lfEscapement = 0;
2149
2150     if(lf.lfEscapement != 0)
2151     {
2152         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2153         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2154     }
2155     else
2156     {
2157         cosEsc = 1;
2158         sinEsc = 0;
2159     }
2160
2161     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2162     {
2163         if(!lprect)
2164         {
2165             if(flags & ETO_GLYPH_INDEX)
2166                 GetTextExtentPointI(hdc, glyphs, count, &sz);
2167             else
2168                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2169
2170             done_extents = TRUE;
2171             rc.left = x;
2172             rc.top = y;
2173             rc.right = x + sz.cx;
2174             rc.bottom = y + sz.cy;
2175         }
2176         else
2177         {
2178             rc = *lprect;
2179         }
2180
2181         LPtoDP(hdc, (POINT*)&rc, 2);
2182
2183         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2184         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2185     }
2186
2187     if (flags & ETO_OPAQUE)
2188         physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2189
2190     if(count == 0)
2191     {
2192         ret = TRUE;
2193         goto done;
2194     }
2195
2196     pt.x = x;
2197     pt.y = y;
2198     LPtoDP(hdc, &pt, 1);
2199     x = pt.x;
2200     y = pt.y;
2201
2202     char_extra = GetTextCharacterExtra(hdc);
2203     if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2204     {
2205         UINT i;
2206         SIZE tmpsz;
2207         POINT total = {0, 0}, desired[2];
2208
2209         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2210         for(i = 0; i < count; i++)
2211         {
2212             if(lpDx)
2213             {
2214                 if(flags & ETO_PDY)
2215                 {
2216                     deltas[i].x = lpDx[i * 2] + char_extra;
2217                     deltas[i].y = -lpDx[i * 2 + 1];
2218                 }
2219                 else
2220                 {
2221                     deltas[i].x = lpDx[i] + char_extra;
2222                     deltas[i].y = 0;
2223                 }
2224
2225             }
2226             else
2227             {
2228                 if(flags & ETO_GLYPH_INDEX)
2229                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2230                 else
2231                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2232
2233                 deltas[i].x = tmpsz.cx;
2234                 deltas[i].y = 0;
2235             }
2236             
2237             if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2238             {
2239                 deltas[i].x = deltas[i].x + dc->breakExtra;
2240                 if (breakRem > 0)
2241                 {
2242                     breakRem--;
2243                     deltas[i].x++;
2244                 }
2245             }
2246             total.x += deltas[i].x;
2247             total.y += deltas[i].y;
2248
2249             desired[0].x = desired[0].y = 0;
2250
2251             desired[1].x =  cosEsc * total.x + sinEsc * total.y;
2252             desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2253
2254             LPtoDP(hdc, desired, 2);
2255             desired[1].x -= desired[0].x;
2256             desired[1].y -= desired[0].y;
2257             if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2258
2259             deltas[i].x = desired[1].x - width.x;
2260             deltas[i].y = desired[1].y - width.y;
2261
2262             width = desired[1];
2263         }
2264         flags |= ETO_PDY;
2265     }
2266     else
2267     {
2268         if(!done_extents)
2269         {
2270             if(flags & ETO_GLYPH_INDEX)
2271                 GetTextExtentPointI(hdc, glyphs, count, &sz);
2272             else
2273                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2274             done_extents = TRUE;
2275         }
2276         width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2277         width.y = 0;
2278     }
2279
2280     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2281     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2282     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2283     {
2284     case TA_LEFT:
2285         if (align & TA_UPDATECP)
2286         {
2287             pt.x = x + width.x;
2288             pt.y = y + width.y;
2289             DPtoLP(hdc, &pt, 1);
2290             MoveToEx(hdc, pt.x, pt.y, NULL);
2291         }
2292         break;
2293
2294     case TA_CENTER:
2295         x -= width.x / 2;
2296         y -= width.y / 2;
2297         break;
2298
2299     case TA_RIGHT:
2300         x -= width.x;
2301         y -= width.y;
2302         if (align & TA_UPDATECP)
2303         {
2304             pt.x = x;
2305             pt.y = y;
2306             DPtoLP(hdc, &pt, 1);
2307             MoveToEx(hdc, pt.x, pt.y, NULL);
2308         }
2309         break;
2310     }
2311
2312     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2313     {
2314     case TA_TOP:
2315         y += tm.tmAscent * cosEsc;
2316         x += tm.tmAscent * sinEsc;
2317         break;
2318
2319     case TA_BOTTOM:
2320         y -= tm.tmDescent * cosEsc;
2321         x -= tm.tmDescent * sinEsc;
2322         break;
2323
2324     case TA_BASELINE:
2325         break;
2326     }
2327
2328     if (GetBkMode(hdc) != TRANSPARENT)
2329     {
2330         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2331         {
2332             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2333                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2334             {
2335                 RECT rc;
2336                 rc.left = x;
2337                 rc.right = x + width.x;
2338                 rc.top = y - tm.tmAscent;
2339                 rc.bottom = y + tm.tmDescent;
2340
2341                 if(flags & ETO_CLIPPED)
2342                 {
2343                     rc.left = max(lprect->left, rc.left);
2344                     rc.right = min(lprect->right, rc.right);
2345                     rc.top = max(lprect->top, rc.top);
2346                     rc.bottom = min(lprect->bottom, rc.bottom);
2347                 }
2348                 if(rc.left < rc.right && rc.top < rc.bottom)
2349                     physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2350             }
2351         }
2352     }
2353
2354     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2355     {
2356         HFONT orig_font = dc->hFont, cur_font;
2357         UINT glyph;
2358         INT span = 0;
2359         POINT *offsets = NULL;
2360         unsigned int i;
2361
2362         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2363         for(i = 0; i < count; i++)
2364         {
2365             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2366             if(cur_font != dc->hFont)
2367             {
2368                 if(!offsets)
2369                 {
2370                     unsigned int j;
2371                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2372                     offsets[0].x = offsets[0].y = 0;
2373
2374                     if(!deltas)
2375                     {
2376                         SIZE tmpsz;
2377                         for(j = 1; j < count; j++)
2378                         {
2379                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2380                             offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2381                             offsets[j].y = 0;
2382                         }
2383                     }
2384                     else
2385                     {
2386                         for(j = 1; j < count; j++)
2387                         {
2388                             offsets[j].x = offsets[j - 1].x + deltas[j].x;
2389                             offsets[j].y = offsets[j - 1].y + deltas[j].y;
2390                         }
2391                     }
2392                 }
2393                 if(span)
2394                 {
2395                     physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2396                                                  y + offsets[i - span].y,
2397                                                  (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2398                                                  span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2399                     span = 0;
2400                 }
2401                 SelectObject(hdc, cur_font);
2402             }
2403             glyphs[span++] = glyph;
2404
2405             if(i == count - 1)
2406             {
2407                 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2408                                                   y + (offsets ? offsets[count - span].y : 0),
2409                                                   (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2410                                                   span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2411                 SelectObject(hdc, orig_font);
2412                 HeapFree(GetProcessHeap(), 0, offsets);
2413            }
2414         }
2415     }
2416     else
2417     {
2418         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2419         {
2420             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2421             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2422             flags |= ETO_GLYPH_INDEX;
2423         }
2424         ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2425                                            glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2426     }
2427
2428 done:
2429     HeapFree(GetProcessHeap(), 0, deltas);
2430     if(glyphs != reordered_str)
2431         HeapFree(GetProcessHeap(), 0, glyphs);
2432     if(reordered_str != str)
2433         HeapFree(GetProcessHeap(), 0, reordered_str);
2434
2435     release_dc_ptr( dc );
2436
2437     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2438     {
2439         int underlinePos, strikeoutPos;
2440         int underlineWidth, strikeoutWidth;
2441         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2442         OUTLINETEXTMETRICW* otm = NULL;
2443         POINT pts[5];
2444         HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2445         HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2446
2447         hbrush = SelectObject(hdc, hbrush);
2448
2449         if(!size)
2450         {
2451             underlinePos = 0;
2452             underlineWidth = tm.tmAscent / 20 + 1;
2453             strikeoutPos = tm.tmAscent / 2;
2454             strikeoutWidth = underlineWidth;
2455         }
2456         else
2457         {
2458             otm = HeapAlloc(GetProcessHeap(), 0, size);
2459             GetOutlineTextMetricsW(hdc, size, otm);
2460             underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2461             if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2462             underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2463             if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2464             strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2465             if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2466             strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2467             HeapFree(GetProcessHeap(), 0, otm);
2468         }
2469
2470
2471         if (lf.lfUnderline)
2472         {
2473             pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2474             pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2475             pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2476             pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2477             pts[2].x = pts[1].x + underlineWidth * sinEsc;
2478             pts[2].y = pts[1].y + underlineWidth * cosEsc;
2479             pts[3].x = pts[0].x + underlineWidth * sinEsc;
2480             pts[3].y = pts[0].y + underlineWidth * cosEsc;
2481             pts[4].x = pts[0].x;
2482             pts[4].y = pts[0].y;
2483             DPtoLP(hdc, pts, 5);
2484             Polygon(hdc, pts, 5);
2485         }
2486
2487         if (lf.lfStrikeOut)
2488         {
2489             pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2490             pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2491             pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2492             pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2493             pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2494             pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2495             pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2496             pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2497             pts[4].x = pts[0].x;
2498             pts[4].y = pts[0].y;
2499             DPtoLP(hdc, pts, 5);
2500             Polygon(hdc, pts, 5);
2501         }
2502
2503         SelectObject(hdc, hpen);
2504         hbrush = SelectObject(hdc, hbrush);
2505         DeleteObject(hbrush);
2506     }
2507
2508     return ret;
2509 }
2510
2511
2512 /***********************************************************************
2513  *           TextOutA    (GDI32.@)
2514  */
2515 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2516 {
2517     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2518 }
2519
2520
2521 /***********************************************************************
2522  *           TextOutW    (GDI32.@)
2523  */
2524 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2525 {
2526     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2527 }
2528
2529
2530 /***********************************************************************
2531  *              PolyTextOutA (GDI32.@)
2532  *
2533  * See PolyTextOutW.
2534  */
2535 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2536 {
2537     for (; cStrings>0; cStrings--, pptxt++)
2538         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2539             return FALSE;
2540     return TRUE;
2541 }
2542
2543
2544
2545 /***********************************************************************
2546  *              PolyTextOutW (GDI32.@)
2547  *
2548  * Draw several Strings
2549  *
2550  * RETURNS
2551  *  TRUE:  Success.
2552  *  FALSE: Failure.
2553  */
2554 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2555 {
2556     for (; cStrings>0; cStrings--, pptxt++)
2557         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2558             return FALSE;
2559     return TRUE;
2560 }
2561
2562
2563 /***********************************************************************
2564  *           SetMapperFlags    (GDI32.@)
2565  */
2566 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2567 {
2568     DC *dc = get_dc_ptr( hdc );
2569     DWORD ret = GDI_ERROR;
2570
2571     if (dc)
2572     {
2573         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2574         flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2575         if (flags != GDI_ERROR)
2576         {
2577             ret = dc->mapperFlags;
2578             dc->mapperFlags = flags;
2579         }
2580         release_dc_ptr( dc );
2581     }
2582     return ret;
2583 }
2584
2585 /***********************************************************************
2586  *          GetAspectRatioFilterEx  (GDI32.@)
2587  */
2588 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2589 {
2590   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2591   return FALSE;
2592 }
2593
2594
2595 /***********************************************************************
2596  *           GetCharABCWidthsA   (GDI32.@)
2597  *
2598  * See GetCharABCWidthsW.
2599  */
2600 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2601                                   LPABC abc )
2602 {
2603     INT i, wlen;
2604     LPSTR str;
2605     LPWSTR wstr;
2606     BOOL ret = TRUE;
2607
2608     str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2609     if (str == NULL)
2610         return FALSE;
2611
2612     wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2613     if (wstr == NULL)
2614     {
2615         HeapFree(GetProcessHeap(), 0, str);
2616         return FALSE;
2617     }
2618
2619     for(i = 0; i < wlen; i++)
2620     {
2621         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2622         {
2623             ret = FALSE;
2624             break;
2625         }
2626         abc++;
2627     }
2628
2629     HeapFree(GetProcessHeap(), 0, str);
2630     HeapFree(GetProcessHeap(), 0, wstr);
2631
2632     return ret;
2633 }
2634
2635
2636 /******************************************************************************
2637  * GetCharABCWidthsW [GDI32.@]
2638  *
2639  * Retrieves widths of characters in range.
2640  *
2641  * PARAMS
2642  *    hdc       [I] Handle of device context
2643  *    firstChar [I] First character in range to query
2644  *    lastChar  [I] Last character in range to query
2645  *    abc       [O] Address of character-width structure
2646  *
2647  * NOTES
2648  *    Only works with TrueType fonts
2649  *
2650  * RETURNS
2651  *    Success: TRUE
2652  *    Failure: FALSE
2653  */
2654 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2655                                    LPABC abc )
2656 {
2657     DC *dc = get_dc_ptr(hdc);
2658     PHYSDEV dev;
2659     unsigned int i;
2660     BOOL ret;
2661
2662     if (!dc) return FALSE;
2663
2664     if (!abc)
2665     {
2666         release_dc_ptr( dc );
2667         return FALSE;
2668     }
2669
2670     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2671     ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2672     if (ret)
2673     {
2674         /* convert device units to logical */
2675         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2676             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2677             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2678             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2679         }
2680     }
2681
2682     release_dc_ptr( dc );
2683     return ret;
2684 }
2685
2686
2687 /******************************************************************************
2688  * GetCharABCWidthsI [GDI32.@]
2689  *
2690  * Retrieves widths of characters in range.
2691  *
2692  * PARAMS
2693  *    hdc       [I] Handle of device context
2694  *    firstChar [I] First glyphs in range to query
2695  *    count     [I] Last glyphs in range to query
2696  *    pgi       [i] Array of glyphs to query
2697  *    abc       [O] Address of character-width structure
2698  *
2699  * NOTES
2700  *    Only works with TrueType fonts
2701  *
2702  * RETURNS
2703  *    Success: TRUE
2704  *    Failure: FALSE
2705  */
2706 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2707                                LPWORD pgi, LPABC abc)
2708 {
2709     DC *dc = get_dc_ptr(hdc);
2710     PHYSDEV dev;
2711     unsigned int i;
2712     BOOL ret;
2713
2714     if (!dc) return FALSE;
2715
2716     if (!abc)
2717     {
2718         release_dc_ptr( dc );
2719         return FALSE;
2720     }
2721
2722     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2723     ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2724     if (ret)
2725     {
2726         /* convert device units to logical */
2727         for( i = 0; i < count; i++, abc++ ) {
2728             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2729             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2730             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2731         }
2732     }
2733
2734     release_dc_ptr( dc );
2735     return ret;
2736 }
2737
2738
2739 /***********************************************************************
2740  *           GetGlyphOutlineA    (GDI32.@)
2741  */
2742 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2743                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2744                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2745 {
2746     if (!lpmat2) return GDI_ERROR;
2747
2748     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2749         UINT cp;
2750         int len;
2751         char mbchs[2];
2752
2753         cp = GdiGetCodePage(hdc);
2754         if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2755             len = 2;
2756             mbchs[0] = (uChar & 0xff00) >> 8;
2757             mbchs[1] = (uChar & 0xff);
2758         } else {
2759             len = 1;
2760             mbchs[0] = (uChar & 0xff);
2761         }
2762         uChar = 0;
2763         MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2764     }
2765
2766     return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2767                             lpmat2);
2768 }
2769
2770 /***********************************************************************
2771  *           GetGlyphOutlineW    (GDI32.@)
2772  */
2773 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2774                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2775                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2776 {
2777     DC *dc;
2778     DWORD ret;
2779     PHYSDEV dev;
2780
2781     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2782           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2783
2784     if (!lpmat2) return GDI_ERROR;
2785
2786     dc = get_dc_ptr(hdc);
2787     if(!dc) return GDI_ERROR;
2788
2789     dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2790     ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2791     release_dc_ptr( dc );
2792     return ret;
2793 }
2794
2795
2796 /***********************************************************************
2797  *           CreateScalableFontResourceA   (GDI32.@)
2798  */
2799 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2800                                              LPCSTR lpszResourceFile,
2801                                              LPCSTR lpszFontFile,
2802                                              LPCSTR lpszCurrentPath )
2803 {
2804     LPWSTR lpszResourceFileW = NULL;
2805     LPWSTR lpszFontFileW = NULL;
2806     LPWSTR lpszCurrentPathW = NULL;
2807     int len;
2808     BOOL ret;
2809
2810     if (lpszResourceFile)
2811     {
2812         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2813         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2814         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2815     }
2816
2817     if (lpszFontFile)
2818     {
2819         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2820         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2821         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2822     }
2823
2824     if (lpszCurrentPath)
2825     {
2826         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2827         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2828         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2829     }
2830
2831     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2832             lpszFontFileW, lpszCurrentPathW);
2833
2834     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2835     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2836     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2837
2838     return ret;
2839 }
2840
2841 /***********************************************************************
2842  *           CreateScalableFontResourceW   (GDI32.@)
2843  */
2844 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2845                                              LPCWSTR lpszResourceFile,
2846                                              LPCWSTR lpszFontFile,
2847                                              LPCWSTR lpszCurrentPath )
2848 {
2849     HANDLE f;
2850     FIXME("(%d,%s,%s,%s): stub\n",
2851           fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2852           debugstr_w(lpszCurrentPath) );
2853
2854     /* fHidden=1 - only visible for the calling app, read-only, not
2855      * enumerated with EnumFonts/EnumFontFamilies
2856      * lpszCurrentPath can be NULL
2857      */
2858
2859     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2860     if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2861         CloseHandle(f);
2862         SetLastError(ERROR_FILE_EXISTS);
2863         return FALSE;
2864     }
2865     return FALSE; /* create failed */
2866 }
2867
2868 /*************************************************************************
2869  *             GetKerningPairsA   (GDI32.@)
2870  */
2871 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2872                                LPKERNINGPAIR kern_pairA )
2873 {
2874     UINT cp;
2875     CPINFO cpi;
2876     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2877     KERNINGPAIR *kern_pairW;
2878
2879     if (!cPairs && kern_pairA)
2880     {
2881         SetLastError(ERROR_INVALID_PARAMETER);
2882         return 0;
2883     }
2884
2885     cp = GdiGetCodePage(hDC);
2886
2887     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2888      * to fail on an invalid character for CP_SYMBOL.
2889      */
2890     cpi.DefaultChar[0] = 0;
2891     if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2892     {
2893         FIXME("Can't find codepage %u info\n", cp);
2894         return 0;
2895     }
2896
2897     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2898     if (!total_kern_pairs) return 0;
2899
2900     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2901     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2902
2903     for (i = 0; i < total_kern_pairs; i++)
2904     {
2905         char first, second;
2906
2907         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2908             continue;
2909
2910         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2911             continue;
2912
2913         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2914             continue;
2915
2916         if (kern_pairA)
2917         {
2918             if (kern_pairs_copied >= cPairs) break;
2919
2920             kern_pairA->wFirst = (BYTE)first;
2921             kern_pairA->wSecond = (BYTE)second;
2922             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2923             kern_pairA++;
2924         }
2925         kern_pairs_copied++;
2926     }
2927
2928     HeapFree(GetProcessHeap(), 0, kern_pairW);
2929
2930     return kern_pairs_copied;
2931 }
2932
2933 /*************************************************************************
2934  *             GetKerningPairsW   (GDI32.@)
2935  */
2936 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2937                                  LPKERNINGPAIR lpKerningPairs )
2938 {
2939     DC *dc;
2940     DWORD ret;
2941     PHYSDEV dev;
2942
2943     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2944
2945     if (!cPairs && lpKerningPairs)
2946     {
2947         SetLastError(ERROR_INVALID_PARAMETER);
2948         return 0;
2949     }
2950
2951     dc = get_dc_ptr(hDC);
2952     if (!dc) return 0;
2953
2954     dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2955     ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2956     release_dc_ptr( dc );
2957     return ret;
2958 }
2959
2960 /*************************************************************************
2961  * TranslateCharsetInfo [GDI32.@]
2962  *
2963  * Fills a CHARSETINFO structure for a character set, code page, or
2964  * font. This allows making the correspondence between different labels
2965  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2966  * of the same encoding.
2967  *
2968  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2969  * only one codepage should be set in *lpSrc.
2970  *
2971  * RETURNS
2972  *   TRUE on success, FALSE on failure.
2973  *
2974  */
2975 BOOL WINAPI TranslateCharsetInfo(
2976   LPDWORD lpSrc, /* [in]
2977        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2978        if flags == TCI_SRCCHARSET: a character set value
2979        if flags == TCI_SRCCODEPAGE: a code page value
2980                  */
2981   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2982   DWORD flags /* [in] determines interpretation of lpSrc */)
2983 {
2984     int index = 0;
2985     switch (flags) {
2986     case TCI_SRCFONTSIG:
2987       while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2988       break;
2989     case TCI_SRCCODEPAGE:
2990       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2991       break;
2992     case TCI_SRCCHARSET:
2993       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2994       break;
2995     default:
2996       return FALSE;
2997     }
2998     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2999     *lpCs = FONT_tci[index];
3000     return TRUE;
3001 }
3002
3003 /*************************************************************************
3004  *             GetFontLanguageInfo   (GDI32.@)
3005  */
3006 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
3007 {
3008         FONTSIGNATURE fontsig;
3009         static const DWORD GCP_DBCS_MASK=0x003F0000,
3010                 GCP_DIACRITIC_MASK=0x00000000,
3011                 FLI_GLYPHS_MASK=0x00000000,
3012                 GCP_GLYPHSHAPE_MASK=0x00000040,
3013                 GCP_KASHIDA_MASK=0x00000000,
3014                 GCP_LIGATE_MASK=0x00000000,
3015                 GCP_USEKERNING_MASK=0x00000000,
3016                 GCP_REORDER_MASK=0x00000060;
3017
3018         DWORD result=0;
3019
3020         GetTextCharsetInfo( hdc, &fontsig, 0 );
3021         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3022
3023         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
3024                 result|=GCP_DBCS;
3025
3026         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
3027                 result|=GCP_DIACRITIC;
3028
3029         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
3030                 result|=FLI_GLYPHS;
3031
3032         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
3033                 result|=GCP_GLYPHSHAPE;
3034
3035         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
3036                 result|=GCP_KASHIDA;
3037
3038         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
3039                 result|=GCP_LIGATE;
3040
3041         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
3042                 result|=GCP_USEKERNING;
3043
3044         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3045         if( GetTextAlign( hdc) & TA_RTLREADING )
3046             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
3047                     result|=GCP_REORDER;
3048
3049         return result;
3050 }
3051
3052
3053 /*************************************************************************
3054  * GetFontData [GDI32.@]
3055  *
3056  * Retrieve data for TrueType font.
3057  *
3058  * RETURNS
3059  *
3060  * success: Number of bytes returned
3061  * failure: GDI_ERROR
3062  *
3063  * NOTES
3064  *
3065  * Calls SetLastError()
3066  *
3067  */
3068 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
3069     LPVOID buffer, DWORD length)
3070 {
3071     DC *dc = get_dc_ptr(hdc);
3072     PHYSDEV dev;
3073     DWORD ret;
3074
3075     if(!dc) return GDI_ERROR;
3076
3077     dev = GET_DC_PHYSDEV( dc, pGetFontData );
3078     ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3079     release_dc_ptr( dc );
3080     return ret;
3081 }
3082
3083 /*************************************************************************
3084  * GetGlyphIndicesA [GDI32.@]
3085  */
3086 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3087                               LPWORD pgi, DWORD flags)
3088 {
3089     DWORD ret;
3090     WCHAR *lpstrW;
3091     INT countW;
3092
3093     TRACE("(%p, %s, %d, %p, 0x%x)\n",
3094           hdc, debugstr_an(lpstr, count), count, pgi, flags);
3095
3096     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3097     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3098     HeapFree(GetProcessHeap(), 0, lpstrW);
3099
3100     return ret;
3101 }
3102
3103 /*************************************************************************
3104  * GetGlyphIndicesW [GDI32.@]
3105  */
3106 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3107                               LPWORD pgi, DWORD flags)
3108 {
3109     DC *dc = get_dc_ptr(hdc);
3110     PHYSDEV dev;
3111     DWORD ret;
3112
3113     TRACE("(%p, %s, %d, %p, 0x%x)\n",
3114           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3115
3116     if(!dc) return GDI_ERROR;
3117
3118     dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3119     ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3120     release_dc_ptr( dc );
3121     return ret;
3122 }
3123
3124 /*************************************************************************
3125  * GetCharacterPlacementA [GDI32.@]
3126  *
3127  * See GetCharacterPlacementW.
3128  *
3129  * NOTES:
3130  *  the web browser control of ie4 calls this with dwFlags=0
3131  */
3132 DWORD WINAPI
3133 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3134                          INT nMaxExtent, GCP_RESULTSA *lpResults,
3135                          DWORD dwFlags)
3136 {
3137     WCHAR *lpStringW;
3138     INT uCountW;
3139     GCP_RESULTSW resultsW;
3140     DWORD ret;
3141     UINT font_cp;
3142
3143     TRACE("%s, %d, %d, 0x%08x\n",
3144           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3145
3146     /* both structs are equal in size */
3147     memcpy(&resultsW, lpResults, sizeof(resultsW));
3148
3149     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3150     if(lpResults->lpOutString)
3151         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3152
3153     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3154
3155     lpResults->nGlyphs = resultsW.nGlyphs;
3156     lpResults->nMaxFit = resultsW.nMaxFit;
3157
3158     if(lpResults->lpOutString) {
3159         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3160                             lpResults->lpOutString, uCount, NULL, NULL );
3161     }
3162
3163     HeapFree(GetProcessHeap(), 0, lpStringW);
3164     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3165
3166     return ret;
3167 }
3168
3169 /*************************************************************************
3170  * GetCharacterPlacementW [GDI32.@]
3171  *
3172  *   Retrieve information about a string. This includes the width, reordering,
3173  *   Glyphing and so on.
3174  *
3175  * RETURNS
3176  *
3177  *   The width and height of the string if successful, 0 if failed.
3178  *
3179  * BUGS
3180  *
3181  *   All flags except GCP_REORDER are not yet implemented.
3182  *   Reordering is not 100% compliant to the Windows BiDi method.
3183  *   Caret positioning is not yet implemented for BiDi.
3184  *   Classes are not yet implemented.
3185  *
3186  */
3187 DWORD WINAPI
3188 GetCharacterPlacementW(
3189                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
3190                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
3191                 INT uCount,             /* [in] Number of WORDS in string. */
3192                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
3193                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3194                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
3195                 )
3196 {
3197     DWORD ret=0;
3198     SIZE size;
3199     UINT i, nSet;
3200
3201     TRACE("%s, %d, %d, 0x%08x\n",
3202           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3203
3204     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3205           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3206             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3207             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3208             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3209
3210     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
3211     if(lpResults->lpClass)      FIXME("classes not implemented\n");
3212     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3213         FIXME("Caret positions for complex scripts not implemented\n");
3214
3215         nSet = (UINT)uCount;
3216         if(nSet > lpResults->nGlyphs)
3217                 nSet = lpResults->nGlyphs;
3218
3219         /* return number of initialized fields */
3220         lpResults->nGlyphs = nSet;
3221
3222         if((dwFlags&GCP_REORDER)==0 )
3223         {
3224                 /* Treat the case where no special handling was requested in a fastpath way */
3225                 /* copy will do if the GCP_REORDER flag is not set */
3226                 if(lpResults->lpOutString)
3227                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3228
3229                 if(lpResults->lpOrder)
3230                 {
3231                         for(i = 0; i < nSet; i++)
3232                                 lpResults->lpOrder[i] = i;
3233                 }
3234         } else
3235         {
3236             BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3237                           nSet, lpResults->lpOrder, NULL, NULL );
3238         }
3239
3240         /* FIXME: Will use the placement chars */
3241         if (lpResults->lpDx)
3242         {
3243                 int c;
3244                 for (i = 0; i < nSet; i++)
3245                 {
3246                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3247                                 lpResults->lpDx[i]= c;
3248                 }
3249         }
3250
3251     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3252     {
3253         int pos = 0;
3254        
3255         lpResults->lpCaretPos[0] = 0;
3256         for (i = 1; i < nSet; i++)
3257             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3258                 lpResults->lpCaretPos[i] = (pos += size.cx);
3259     }
3260    
3261     if(lpResults->lpGlyphs)
3262         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3263
3264     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3265       ret = MAKELONG(size.cx, size.cy);
3266
3267     return ret;
3268 }
3269
3270 /*************************************************************************
3271  *      GetCharABCWidthsFloatA [GDI32.@]
3272  *
3273  * See GetCharABCWidthsFloatW.
3274  */
3275 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3276 {
3277     INT i, wlen;
3278     LPSTR str;
3279     LPWSTR wstr;
3280     BOOL ret = TRUE;
3281
3282     str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3283     if (str == NULL)
3284         return FALSE;
3285
3286     wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3287
3288     for (i = 0; i < wlen; i++)
3289     {
3290         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3291         {
3292             ret = FALSE;
3293             break;
3294         }
3295         abcf++;
3296     }
3297
3298     HeapFree( GetProcessHeap(), 0, str );
3299     HeapFree( GetProcessHeap(), 0, wstr );
3300
3301     return ret;
3302 }
3303
3304 /*************************************************************************
3305  *      GetCharABCWidthsFloatW [GDI32.@]
3306  *
3307  * Retrieves widths of a range of characters.
3308  *
3309  * PARAMS
3310  *    hdc   [I] Handle to device context.
3311  *    first [I] First character in range to query.
3312  *    last  [I] Last character in range to query.
3313  *    abcf  [O] Array of LPABCFLOAT structures.
3314  *
3315  * RETURNS
3316  *    Success: TRUE
3317  *    Failure: FALSE
3318  */
3319 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3320 {
3321     UINT i;
3322     ABC *abc;
3323     PHYSDEV dev;
3324     BOOL ret = FALSE;
3325     DC *dc = get_dc_ptr( hdc );
3326
3327     TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3328
3329     if (!dc) return FALSE;
3330
3331     if (!abcf) goto done;
3332     if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3333
3334     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3335     ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3336     if (ret)
3337     {
3338         /* convert device units to logical */
3339         for (i = first; i <= last; i++, abcf++)
3340         {
3341             abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
3342             abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
3343             abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
3344         }
3345     }
3346     HeapFree( GetProcessHeap(), 0, abc );
3347
3348 done:
3349     release_dc_ptr( dc );
3350     return ret;
3351 }
3352
3353 /*************************************************************************
3354  *      GetCharWidthFloatA [GDI32.@]
3355  */
3356 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3357                                     UINT iLastChar, PFLOAT pxBuffer)
3358 {
3359     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3360     return 0;
3361 }
3362
3363 /*************************************************************************
3364  *      GetCharWidthFloatW [GDI32.@]
3365  */
3366 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3367                                     UINT iLastChar, PFLOAT pxBuffer)
3368 {
3369     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3370     return 0;
3371 }
3372
3373
3374 /***********************************************************************
3375  *                                                                     *
3376  *           Font Resource API                                         *
3377  *                                                                     *
3378  ***********************************************************************/
3379
3380 /***********************************************************************
3381  *           AddFontResourceA    (GDI32.@)
3382  */
3383 INT WINAPI AddFontResourceA( LPCSTR str )
3384 {
3385     return AddFontResourceExA( str, 0, NULL);
3386 }
3387
3388 /***********************************************************************
3389  *           AddFontResourceW    (GDI32.@)
3390  */
3391 INT WINAPI AddFontResourceW( LPCWSTR str )
3392 {
3393     return AddFontResourceExW(str, 0, NULL);
3394 }
3395
3396
3397 /***********************************************************************
3398  *           AddFontResourceExA    (GDI32.@)
3399  */
3400 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3401 {
3402     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3403     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3404     INT ret;
3405
3406     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3407     ret = AddFontResourceExW(strW, fl, pdv);
3408     HeapFree(GetProcessHeap(), 0, strW);
3409     return ret;
3410 }
3411
3412 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3413 {
3414     HRSRC rsrc = FindResourceW(hModule, name, type);
3415     HGLOBAL hMem = LoadResource(hModule, rsrc);
3416     LPVOID *pMem = LockResource(hMem);
3417     int *num_total = (int *)lParam;
3418     DWORD num_in_res;
3419
3420     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3421     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3422     {
3423         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3424         return FALSE;
3425     }
3426
3427     *num_total += num_in_res;
3428     return TRUE;
3429 }
3430
3431 /***********************************************************************
3432  *           AddFontResourceExW    (GDI32.@)
3433  */
3434 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3435 {
3436     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3437     if (ret == 0)
3438     {
3439         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3440         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3441         if (hModule != NULL)
3442         {
3443             int num_resources = 0;
3444             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3445
3446             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3447                 wine_dbgstr_w(str));
3448             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3449                 ret = num_resources;
3450             FreeLibrary(hModule);
3451         }
3452     }
3453     return ret;
3454 }
3455
3456 /***********************************************************************
3457  *           RemoveFontResourceA    (GDI32.@)
3458  */
3459 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3460 {
3461     return RemoveFontResourceExA(str, 0, 0);
3462 }
3463
3464 /***********************************************************************
3465  *           RemoveFontResourceW    (GDI32.@)
3466  */
3467 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3468 {
3469     return RemoveFontResourceExW(str, 0, 0);
3470 }
3471
3472 /***********************************************************************
3473  *           AddFontMemResourceEx    (GDI32.@)
3474  */
3475 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3476 {
3477     HANDLE ret;
3478     DWORD num_fonts;
3479
3480     if (!pbFont || !cbFont || !pcFonts)
3481     {
3482         SetLastError(ERROR_INVALID_PARAMETER);
3483         return NULL;
3484     }
3485
3486     ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3487     if (ret)
3488     {
3489         __TRY
3490         {
3491             *pcFonts = num_fonts;
3492         }
3493         __EXCEPT_PAGE_FAULT
3494         {
3495             WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3496             RemoveFontMemResourceEx(ret);
3497             ret = 0;
3498         }
3499         __ENDTRY
3500     }
3501     return ret;
3502 }
3503
3504 /***********************************************************************
3505  *           RemoveFontMemResourceEx    (GDI32.@)
3506  */
3507 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3508 {
3509     FIXME("(%p) stub\n", fh);
3510     return TRUE;
3511 }
3512
3513 /***********************************************************************
3514  *           RemoveFontResourceExA    (GDI32.@)
3515  */
3516 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3517 {
3518     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3519     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3520     INT ret;
3521
3522     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3523     ret = RemoveFontResourceExW(strW, fl, pdv);
3524     HeapFree(GetProcessHeap(), 0, strW);
3525     return ret;
3526 }
3527
3528 /***********************************************************************
3529  *           RemoveFontResourceExW    (GDI32.@)
3530  */
3531 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3532 {
3533     return WineEngRemoveFontResourceEx(str, fl, pdv);
3534 }
3535
3536 /***********************************************************************
3537  *           GetTextCharset    (GDI32.@)
3538  */
3539 UINT WINAPI GetTextCharset(HDC hdc)
3540 {
3541     /* MSDN docs say this is equivalent */
3542     return GetTextCharsetInfo(hdc, NULL, 0);
3543 }
3544
3545 /***********************************************************************
3546  *           GetTextCharsetInfo    (GDI32.@)
3547  */
3548 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3549 {
3550     UINT ret = DEFAULT_CHARSET;
3551     DC *dc = get_dc_ptr(hdc);
3552     PHYSDEV dev;
3553
3554     if (dc)
3555     {
3556         dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3557         ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3558         release_dc_ptr( dc );
3559     }
3560
3561     if (ret == DEFAULT_CHARSET && fs)
3562         memset(fs, 0, sizeof(FONTSIGNATURE));
3563     return ret;
3564 }
3565
3566 /***********************************************************************
3567  *           GdiGetCharDimensions    (GDI32.@)
3568  *
3569  * Gets the average width of the characters in the English alphabet.
3570  *
3571  * PARAMS
3572  *  hdc    [I] Handle to the device context to measure on.
3573  *  lptm   [O] Pointer to memory to store the text metrics into.
3574  *  height [O] On exit, the maximum height of characters in the English alphabet.
3575  *
3576  * RETURNS
3577  *  The average width of characters in the English alphabet.
3578  *
3579  * NOTES
3580  *  This function is used by the dialog manager to get the size of a dialog
3581  *  unit. It should also be used by other pieces of code that need to know
3582  *  the size of a dialog unit in logical units without having access to the
3583  *  window handle of the dialog.
3584  *  Windows caches the font metrics from this function, but we don't and
3585  *  there doesn't appear to be an immediate advantage to do so.
3586  *
3587  * SEE ALSO
3588  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3589  */
3590 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3591 {
3592     SIZE sz;
3593     static const WCHAR alphabet[] = {
3594         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3595         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3596         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3597
3598     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3599
3600     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3601
3602     if (height) *height = sz.cy;
3603     return (sz.cx / 26 + 1) / 2;
3604 }
3605
3606 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3607 {
3608     FIXME("(%d): stub\n", fEnableEUDC);
3609     return FALSE;
3610 }
3611
3612 /***********************************************************************
3613  *           GetCharWidthI    (GDI32.@)
3614  *
3615  * Retrieve widths of characters.
3616  *
3617  * PARAMS
3618  *  hdc    [I] Handle to a device context.
3619  *  first  [I] First glyph in range to query.
3620  *  count  [I] Number of glyph indices to query.
3621  *  glyphs [I] Array of glyphs to query.
3622  *  buffer [O] Buffer to receive character widths.
3623  *
3624  * NOTES
3625  *  Only works with TrueType fonts.
3626  *
3627  * RETURNS
3628  *  Success: TRUE
3629  *  Failure: FALSE
3630  */
3631 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3632 {
3633     ABC *abc;
3634     unsigned int i;
3635
3636     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3637
3638     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3639         return FALSE;
3640
3641     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3642     {
3643         HeapFree(GetProcessHeap(), 0, abc);
3644         return FALSE;
3645     }
3646
3647     for (i = 0; i < count; i++)
3648         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3649
3650     HeapFree(GetProcessHeap(), 0, abc);
3651     return TRUE;
3652 }
3653
3654 /***********************************************************************
3655  *           GetFontUnicodeRanges    (GDI32.@)
3656  *
3657  *  Retrieve a list of supported Unicode characters in a font.
3658  *
3659  *  PARAMS
3660  *   hdc  [I] Handle to a device context.
3661  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3662  *
3663  *  RETURNS
3664  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3665  *   Failure: 0
3666  *
3667  */
3668 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3669 {
3670     DWORD ret;
3671     PHYSDEV dev;
3672     DC *dc = get_dc_ptr(hdc);
3673
3674     TRACE("(%p, %p)\n", hdc, lpgs);
3675
3676     if (!dc) return 0;
3677
3678     dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3679     ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3680     release_dc_ptr(dc);
3681     return ret;
3682 }
3683
3684
3685 /*************************************************************
3686  *           FontIsLinked    (GDI32.@)
3687  */
3688 BOOL WINAPI FontIsLinked(HDC hdc)
3689 {
3690     DC *dc = get_dc_ptr(hdc);
3691     PHYSDEV dev;
3692     BOOL ret;
3693
3694     if (!dc) return FALSE;
3695     dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3696     ret = dev->funcs->pFontIsLinked( dev );
3697     release_dc_ptr(dc);
3698     TRACE("returning %d\n", ret);
3699     return ret;
3700 }
3701
3702 /*************************************************************
3703  *           GdiRealizationInfo    (GDI32.@)
3704  *
3705  * Returns a structure that contains some font information.
3706  */
3707 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3708 {
3709     DC *dc = get_dc_ptr(hdc);
3710     PHYSDEV dev;
3711     BOOL ret;
3712
3713     if (!dc) return FALSE;
3714     dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3715     ret = dev->funcs->pGdiRealizationInfo( dev, info );
3716     release_dc_ptr(dc);
3717     return ret;
3718 }