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