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