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