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