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