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