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