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