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