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