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