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