comctl32/imagelist: Use proper color format for merged image lists.
[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 || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2270     {
2271         UINT i;
2272         POINT total = {0, 0}, desired[2];
2273
2274         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2275         if (lpDx)
2276         {
2277             if (flags & ETO_PDY)
2278             {
2279                 for (i = 0; i < count; i++)
2280                 {
2281                     deltas[i].x = lpDx[i * 2] + char_extra;
2282                     deltas[i].y = -lpDx[i * 2 + 1];
2283                 }
2284             }
2285             else
2286             {
2287                 for (i = 0; i < count; i++)
2288                 {
2289                     deltas[i].x = lpDx[i] + char_extra;
2290                     deltas[i].y = 0;
2291                 }
2292             }
2293         }
2294         else
2295         {
2296             INT *dx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*dx) );
2297
2298             if (flags & ETO_GLYPH_INDEX)
2299                 GetTextExtentExPointI( hdc, glyphs, count, -1, NULL, dx, &sz );
2300             else
2301                 GetTextExtentExPointW( hdc, reordered_str, count, -1, NULL, dx, &sz );
2302
2303             deltas[0].x = dx[0];
2304             deltas[0].y = 0;
2305             for (i = 1; i < count; i++)
2306             {
2307                 deltas[i].x = dx[i] - dx[i - 1];
2308                 deltas[i].y = 0;
2309             }
2310             HeapFree( GetProcessHeap(), 0, dx );
2311         }
2312
2313         for(i = 0; i < count; i++)
2314         {
2315             total.x += deltas[i].x;
2316             total.y += deltas[i].y;
2317
2318             desired[0].x = desired[0].y = 0;
2319
2320             desired[1].x =  cosEsc * total.x + sinEsc * total.y;
2321             desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2322
2323             LPtoDP(hdc, desired, 2);
2324             desired[1].x -= desired[0].x;
2325             desired[1].y -= desired[0].y;
2326
2327             if (dc->GraphicsMode == GM_COMPATIBLE)
2328             {
2329                 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
2330                     desired[1].x = -desired[1].x;
2331                 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
2332                     desired[1].y = -desired[1].y;
2333             }
2334
2335             deltas[i].x = desired[1].x - width.x;
2336             deltas[i].y = desired[1].y - width.y;
2337
2338             width = desired[1];
2339         }
2340         flags |= ETO_PDY;
2341     }
2342     else
2343     {
2344         POINT desired[2];
2345
2346         if(flags & ETO_GLYPH_INDEX)
2347             GetTextExtentPointI(hdc, glyphs, count, &sz);
2348         else
2349             GetTextExtentPointW(hdc, reordered_str, count, &sz);
2350         desired[0].x = desired[0].y = 0;
2351         desired[1].x = sz.cx;
2352         desired[1].y = 0;
2353         LPtoDP(hdc, desired, 2);
2354         desired[1].x -= desired[0].x;
2355         desired[1].y -= desired[0].y;
2356
2357         if (dc->GraphicsMode == GM_COMPATIBLE)
2358         {
2359             if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
2360                 desired[1].x = -desired[1].x;
2361             if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
2362                 desired[1].y = -desired[1].y;
2363         }
2364         width = desired[1];
2365     }
2366
2367     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2368     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2369     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2370     {
2371     case TA_LEFT:
2372         if (align & TA_UPDATECP)
2373         {
2374             pt.x = x + width.x;
2375             pt.y = y + width.y;
2376             DPtoLP(hdc, &pt, 1);
2377             MoveToEx(hdc, pt.x, pt.y, NULL);
2378         }
2379         break;
2380
2381     case TA_CENTER:
2382         x -= width.x / 2;
2383         y -= width.y / 2;
2384         break;
2385
2386     case TA_RIGHT:
2387         x -= width.x;
2388         y -= width.y;
2389         if (align & TA_UPDATECP)
2390         {
2391             pt.x = x;
2392             pt.y = y;
2393             DPtoLP(hdc, &pt, 1);
2394             MoveToEx(hdc, pt.x, pt.y, NULL);
2395         }
2396         break;
2397     }
2398
2399     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2400     {
2401     case TA_TOP:
2402         y += tm.tmAscent * cosEsc;
2403         x += tm.tmAscent * sinEsc;
2404         break;
2405
2406     case TA_BOTTOM:
2407         y -= tm.tmDescent * cosEsc;
2408         x -= tm.tmDescent * sinEsc;
2409         break;
2410
2411     case TA_BASELINE:
2412         break;
2413     }
2414
2415     if (GetBkMode(hdc) != TRANSPARENT)
2416     {
2417         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2418         {
2419             if(!(flags & ETO_OPAQUE) || !lprect ||
2420                x < rc.left || x + width.x >= rc.right ||
2421                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2422             {
2423                 RECT text_box;
2424                 text_box.left = x;
2425                 text_box.right = x + width.x;
2426                 text_box.top = y - tm.tmAscent;
2427                 text_box.bottom = y + tm.tmDescent;
2428
2429                 if (flags & ETO_CLIPPED) intersect_rect( &text_box, &text_box, &rc );
2430                 if (!is_rect_empty( &text_box ))
2431                     physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &text_box, NULL, 0, NULL );
2432             }
2433         }
2434     }
2435
2436     ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2437                                        glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2438
2439 done:
2440     HeapFree(GetProcessHeap(), 0, deltas);
2441     if(glyphs != reordered_str)
2442         HeapFree(GetProcessHeap(), 0, glyphs);
2443     if(reordered_str != str)
2444         HeapFree(GetProcessHeap(), 0, reordered_str);
2445
2446     release_dc_ptr( dc );
2447
2448     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2449     {
2450         int underlinePos, strikeoutPos;
2451         int underlineWidth, strikeoutWidth;
2452         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2453         OUTLINETEXTMETRICW* otm = NULL;
2454         POINT pts[5];
2455         HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2456         HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2457
2458         hbrush = SelectObject(hdc, hbrush);
2459
2460         if(!size)
2461         {
2462             underlinePos = 0;
2463             underlineWidth = tm.tmAscent / 20 + 1;
2464             strikeoutPos = tm.tmAscent / 2;
2465             strikeoutWidth = underlineWidth;
2466         }
2467         else
2468         {
2469             otm = HeapAlloc(GetProcessHeap(), 0, size);
2470             GetOutlineTextMetricsW(hdc, size, otm);
2471             underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2472             if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2473             underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2474             if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2475             strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2476             if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2477             strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2478             HeapFree(GetProcessHeap(), 0, otm);
2479         }
2480
2481
2482         if (lf.lfUnderline)
2483         {
2484             pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2485             pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2486             pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2487             pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2488             pts[2].x = pts[1].x + underlineWidth * sinEsc;
2489             pts[2].y = pts[1].y + underlineWidth * cosEsc;
2490             pts[3].x = pts[0].x + underlineWidth * sinEsc;
2491             pts[3].y = pts[0].y + underlineWidth * cosEsc;
2492             pts[4].x = pts[0].x;
2493             pts[4].y = pts[0].y;
2494             DPtoLP(hdc, pts, 5);
2495             Polygon(hdc, pts, 5);
2496         }
2497
2498         if (lf.lfStrikeOut)
2499         {
2500             pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2501             pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2502             pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2503             pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2504             pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2505             pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2506             pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2507             pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2508             pts[4].x = pts[0].x;
2509             pts[4].y = pts[0].y;
2510             DPtoLP(hdc, pts, 5);
2511             Polygon(hdc, pts, 5);
2512         }
2513
2514         SelectObject(hdc, hpen);
2515         hbrush = SelectObject(hdc, hbrush);
2516         DeleteObject(hbrush);
2517     }
2518
2519     return ret;
2520 }
2521
2522
2523 /***********************************************************************
2524  *           TextOutA    (GDI32.@)
2525  */
2526 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2527 {
2528     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2529 }
2530
2531
2532 /***********************************************************************
2533  *           TextOutW    (GDI32.@)
2534  */
2535 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2536 {
2537     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2538 }
2539
2540
2541 /***********************************************************************
2542  *              PolyTextOutA (GDI32.@)
2543  *
2544  * See PolyTextOutW.
2545  */
2546 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2547 {
2548     for (; cStrings>0; cStrings--, pptxt++)
2549         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2550             return FALSE;
2551     return TRUE;
2552 }
2553
2554
2555
2556 /***********************************************************************
2557  *              PolyTextOutW (GDI32.@)
2558  *
2559  * Draw several Strings
2560  *
2561  * RETURNS
2562  *  TRUE:  Success.
2563  *  FALSE: Failure.
2564  */
2565 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2566 {
2567     for (; cStrings>0; cStrings--, pptxt++)
2568         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2569             return FALSE;
2570     return TRUE;
2571 }
2572
2573
2574 /***********************************************************************
2575  *           SetMapperFlags    (GDI32.@)
2576  */
2577 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2578 {
2579     DC *dc = get_dc_ptr( hdc );
2580     DWORD ret = GDI_ERROR;
2581
2582     if (dc)
2583     {
2584         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2585         flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2586         if (flags != GDI_ERROR)
2587         {
2588             ret = dc->mapperFlags;
2589             dc->mapperFlags = flags;
2590         }
2591         release_dc_ptr( dc );
2592     }
2593     return ret;
2594 }
2595
2596 /***********************************************************************
2597  *          GetAspectRatioFilterEx  (GDI32.@)
2598  */
2599 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2600 {
2601   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2602   return FALSE;
2603 }
2604
2605
2606 /***********************************************************************
2607  *           GetCharABCWidthsA   (GDI32.@)
2608  *
2609  * See GetCharABCWidthsW.
2610  */
2611 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2612                                   LPABC abc )
2613 {
2614     INT i, wlen;
2615     LPSTR str;
2616     LPWSTR wstr;
2617     BOOL ret = TRUE;
2618
2619     str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2620     if (str == NULL)
2621         return FALSE;
2622
2623     wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2624     if (wstr == NULL)
2625     {
2626         HeapFree(GetProcessHeap(), 0, str);
2627         return FALSE;
2628     }
2629
2630     for(i = 0; i < wlen; i++)
2631     {
2632         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2633         {
2634             ret = FALSE;
2635             break;
2636         }
2637         abc++;
2638     }
2639
2640     HeapFree(GetProcessHeap(), 0, str);
2641     HeapFree(GetProcessHeap(), 0, wstr);
2642
2643     return ret;
2644 }
2645
2646
2647 /******************************************************************************
2648  * GetCharABCWidthsW [GDI32.@]
2649  *
2650  * Retrieves widths of characters in range.
2651  *
2652  * PARAMS
2653  *    hdc       [I] Handle of device context
2654  *    firstChar [I] First character in range to query
2655  *    lastChar  [I] Last character in range to query
2656  *    abc       [O] Address of character-width structure
2657  *
2658  * NOTES
2659  *    Only works with TrueType fonts
2660  *
2661  * RETURNS
2662  *    Success: TRUE
2663  *    Failure: FALSE
2664  */
2665 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2666                                    LPABC abc )
2667 {
2668     DC *dc = get_dc_ptr(hdc);
2669     PHYSDEV dev;
2670     unsigned int i;
2671     BOOL ret;
2672     TEXTMETRICW tm;
2673
2674     if (!dc) return FALSE;
2675
2676     if (!abc)
2677     {
2678         release_dc_ptr( dc );
2679         return FALSE;
2680     }
2681
2682     /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-scalable fonts */
2683     dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
2684     if (!dev->funcs->pGetTextMetrics( dev, &tm ) || !(tm.tmPitchAndFamily & TMPF_VECTOR))
2685     {
2686         release_dc_ptr( dc );
2687         return FALSE;
2688     }
2689
2690     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2691     ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2692     if (ret)
2693     {
2694         /* convert device units to logical */
2695         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2696             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2697             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2698             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2699         }
2700     }
2701
2702     release_dc_ptr( dc );
2703     return ret;
2704 }
2705
2706
2707 /******************************************************************************
2708  * GetCharABCWidthsI [GDI32.@]
2709  *
2710  * Retrieves widths of characters in range.
2711  *
2712  * PARAMS
2713  *    hdc       [I] Handle of device context
2714  *    firstChar [I] First glyphs in range to query
2715  *    count     [I] Last glyphs in range to query
2716  *    pgi       [i] Array of glyphs to query
2717  *    abc       [O] Address of character-width structure
2718  *
2719  * NOTES
2720  *    Only works with TrueType fonts
2721  *
2722  * RETURNS
2723  *    Success: TRUE
2724  *    Failure: FALSE
2725  */
2726 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2727                                LPWORD pgi, LPABC abc)
2728 {
2729     DC *dc = get_dc_ptr(hdc);
2730     PHYSDEV dev;
2731     unsigned int i;
2732     BOOL ret;
2733
2734     if (!dc) return FALSE;
2735
2736     if (!abc)
2737     {
2738         release_dc_ptr( dc );
2739         return FALSE;
2740     }
2741
2742     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2743     ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2744     if (ret)
2745     {
2746         /* convert device units to logical */
2747         for( i = 0; i < count; i++, abc++ ) {
2748             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2749             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2750             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2751         }
2752     }
2753
2754     release_dc_ptr( dc );
2755     return ret;
2756 }
2757
2758
2759 /***********************************************************************
2760  *           GetGlyphOutlineA    (GDI32.@)
2761  */
2762 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2763                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2764                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2765 {
2766     if (!lpmat2) return GDI_ERROR;
2767
2768     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2769         UINT cp;
2770         int len;
2771         char mbchs[2];
2772
2773         cp = GdiGetCodePage(hdc);
2774         if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2775             len = 2;
2776             mbchs[0] = (uChar & 0xff00) >> 8;
2777             mbchs[1] = (uChar & 0xff);
2778         } else {
2779             len = 1;
2780             mbchs[0] = (uChar & 0xff);
2781         }
2782         uChar = 0;
2783         MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2784     }
2785
2786     return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2787                             lpmat2);
2788 }
2789
2790 /***********************************************************************
2791  *           GetGlyphOutlineW    (GDI32.@)
2792  */
2793 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2794                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2795                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2796 {
2797     DC *dc;
2798     DWORD ret;
2799     PHYSDEV dev;
2800
2801     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2802           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2803
2804     if (!lpmat2) return GDI_ERROR;
2805
2806     dc = get_dc_ptr(hdc);
2807     if(!dc) return GDI_ERROR;
2808
2809     dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2810     ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2811     release_dc_ptr( dc );
2812     return ret;
2813 }
2814
2815
2816 /***********************************************************************
2817  *           CreateScalableFontResourceA   (GDI32.@)
2818  */
2819 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2820                                              LPCSTR lpszResourceFile,
2821                                              LPCSTR lpszFontFile,
2822                                              LPCSTR lpszCurrentPath )
2823 {
2824     LPWSTR lpszResourceFileW = NULL;
2825     LPWSTR lpszFontFileW = NULL;
2826     LPWSTR lpszCurrentPathW = NULL;
2827     int len;
2828     BOOL ret;
2829
2830     if (lpszResourceFile)
2831     {
2832         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2833         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2834         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2835     }
2836
2837     if (lpszFontFile)
2838     {
2839         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2840         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2841         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2842     }
2843
2844     if (lpszCurrentPath)
2845     {
2846         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2847         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2848         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2849     }
2850
2851     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2852             lpszFontFileW, lpszCurrentPathW);
2853
2854     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2855     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2856     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2857
2858     return ret;
2859 }
2860
2861 /***********************************************************************
2862  *           CreateScalableFontResourceW   (GDI32.@)
2863  */
2864 BOOL WINAPI CreateScalableFontResourceW( DWORD hidden, LPCWSTR resource_file,
2865                                          LPCWSTR font_file, LPCWSTR font_path )
2866 {
2867     TRACE("(%d, %s, %s, %s)\n", hidden, debugstr_w(resource_file),
2868           debugstr_w(font_file), debugstr_w(font_path) );
2869
2870     return WineEngCreateScalableFontResource( hidden, resource_file,
2871                                               font_file, font_path );
2872 }
2873
2874 /*************************************************************************
2875  *             GetKerningPairsA   (GDI32.@)
2876  */
2877 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2878                                LPKERNINGPAIR kern_pairA )
2879 {
2880     UINT cp;
2881     CPINFO cpi;
2882     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2883     KERNINGPAIR *kern_pairW;
2884
2885     if (!cPairs && kern_pairA)
2886     {
2887         SetLastError(ERROR_INVALID_PARAMETER);
2888         return 0;
2889     }
2890
2891     cp = GdiGetCodePage(hDC);
2892
2893     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2894      * to fail on an invalid character for CP_SYMBOL.
2895      */
2896     cpi.DefaultChar[0] = 0;
2897     if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2898     {
2899         FIXME("Can't find codepage %u info\n", cp);
2900         return 0;
2901     }
2902
2903     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2904     if (!total_kern_pairs) return 0;
2905
2906     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2907     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2908
2909     for (i = 0; i < total_kern_pairs; i++)
2910     {
2911         char first, second;
2912
2913         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2914             continue;
2915
2916         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2917             continue;
2918
2919         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2920             continue;
2921
2922         if (kern_pairA)
2923         {
2924             if (kern_pairs_copied >= cPairs) break;
2925
2926             kern_pairA->wFirst = (BYTE)first;
2927             kern_pairA->wSecond = (BYTE)second;
2928             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2929             kern_pairA++;
2930         }
2931         kern_pairs_copied++;
2932     }
2933
2934     HeapFree(GetProcessHeap(), 0, kern_pairW);
2935
2936     return kern_pairs_copied;
2937 }
2938
2939 /*************************************************************************
2940  *             GetKerningPairsW   (GDI32.@)
2941  */
2942 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2943                                  LPKERNINGPAIR lpKerningPairs )
2944 {
2945     DC *dc;
2946     DWORD ret;
2947     PHYSDEV dev;
2948
2949     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2950
2951     if (!cPairs && lpKerningPairs)
2952     {
2953         SetLastError(ERROR_INVALID_PARAMETER);
2954         return 0;
2955     }
2956
2957     dc = get_dc_ptr(hDC);
2958     if (!dc) return 0;
2959
2960     dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2961     ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2962     release_dc_ptr( dc );
2963     return ret;
2964 }
2965
2966 /*************************************************************************
2967  * TranslateCharsetInfo [GDI32.@]
2968  *
2969  * Fills a CHARSETINFO structure for a character set, code page, or
2970  * font. This allows making the correspondence between different labels
2971  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2972  * of the same encoding.
2973  *
2974  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2975  * only one codepage should be set in *lpSrc.
2976  *
2977  * RETURNS
2978  *   TRUE on success, FALSE on failure.
2979  *
2980  */
2981 BOOL WINAPI TranslateCharsetInfo(
2982   LPDWORD lpSrc, /* [in]
2983        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2984        if flags == TCI_SRCCHARSET: a character set value
2985        if flags == TCI_SRCCODEPAGE: a code page value
2986                  */
2987   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2988   DWORD flags /* [in] determines interpretation of lpSrc */)
2989 {
2990     int index = 0;
2991     switch (flags) {
2992     case TCI_SRCFONTSIG:
2993       while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2994       break;
2995     case TCI_SRCCODEPAGE:
2996       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2997       break;
2998     case TCI_SRCCHARSET:
2999       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
3000       break;
3001     default:
3002       return FALSE;
3003     }
3004     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
3005     *lpCs = FONT_tci[index];
3006     return TRUE;
3007 }
3008
3009 /*************************************************************************
3010  *             GetFontLanguageInfo   (GDI32.@)
3011  */
3012 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
3013 {
3014         FONTSIGNATURE fontsig;
3015         static const DWORD GCP_DBCS_MASK=0x003F0000,
3016                 GCP_DIACRITIC_MASK=0x00000000,
3017                 FLI_GLYPHS_MASK=0x00000000,
3018                 GCP_GLYPHSHAPE_MASK=0x00000040,
3019                 GCP_KASHIDA_MASK=0x00000000,
3020                 GCP_LIGATE_MASK=0x00000000,
3021                 GCP_USEKERNING_MASK=0x00000000,
3022                 GCP_REORDER_MASK=0x00000060;
3023
3024         DWORD result=0;
3025
3026         GetTextCharsetInfo( hdc, &fontsig, 0 );
3027         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3028
3029         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
3030                 result|=GCP_DBCS;
3031
3032         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
3033                 result|=GCP_DIACRITIC;
3034
3035         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
3036                 result|=FLI_GLYPHS;
3037
3038         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
3039                 result|=GCP_GLYPHSHAPE;
3040
3041         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
3042                 result|=GCP_KASHIDA;
3043
3044         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
3045                 result|=GCP_LIGATE;
3046
3047         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
3048                 result|=GCP_USEKERNING;
3049
3050         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3051         if( GetTextAlign( hdc) & TA_RTLREADING )
3052             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
3053                     result|=GCP_REORDER;
3054
3055         return result;
3056 }
3057
3058
3059 /*************************************************************************
3060  * GetFontData [GDI32.@]
3061  *
3062  * Retrieve data for TrueType font.
3063  *
3064  * RETURNS
3065  *
3066  * success: Number of bytes returned
3067  * failure: GDI_ERROR
3068  *
3069  * NOTES
3070  *
3071  * Calls SetLastError()
3072  *
3073  */
3074 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
3075     LPVOID buffer, DWORD length)
3076 {
3077     DC *dc = get_dc_ptr(hdc);
3078     PHYSDEV dev;
3079     DWORD ret;
3080
3081     if(!dc) return GDI_ERROR;
3082
3083     dev = GET_DC_PHYSDEV( dc, pGetFontData );
3084     ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3085     release_dc_ptr( dc );
3086     return ret;
3087 }
3088
3089 /*************************************************************************
3090  * GetGlyphIndicesA [GDI32.@]
3091  */
3092 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3093                               LPWORD pgi, DWORD flags)
3094 {
3095     DWORD ret;
3096     WCHAR *lpstrW;
3097     INT countW;
3098
3099     TRACE("(%p, %s, %d, %p, 0x%x)\n",
3100           hdc, debugstr_an(lpstr, count), count, pgi, flags);
3101
3102     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3103     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3104     HeapFree(GetProcessHeap(), 0, lpstrW);
3105
3106     return ret;
3107 }
3108
3109 /*************************************************************************
3110  * GetGlyphIndicesW [GDI32.@]
3111  */
3112 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3113                               LPWORD pgi, DWORD flags)
3114 {
3115     DC *dc = get_dc_ptr(hdc);
3116     PHYSDEV dev;
3117     DWORD ret;
3118
3119     TRACE("(%p, %s, %d, %p, 0x%x)\n",
3120           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3121
3122     if(!dc) return GDI_ERROR;
3123
3124     dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3125     ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3126     release_dc_ptr( dc );
3127     return ret;
3128 }
3129
3130 /*************************************************************************
3131  * GetCharacterPlacementA [GDI32.@]
3132  *
3133  * See GetCharacterPlacementW.
3134  *
3135  * NOTES:
3136  *  the web browser control of ie4 calls this with dwFlags=0
3137  */
3138 DWORD WINAPI
3139 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3140                          INT nMaxExtent, GCP_RESULTSA *lpResults,
3141                          DWORD dwFlags)
3142 {
3143     WCHAR *lpStringW;
3144     INT uCountW;
3145     GCP_RESULTSW resultsW;
3146     DWORD ret;
3147     UINT font_cp;
3148
3149     TRACE("%s, %d, %d, 0x%08x\n",
3150           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3151
3152     /* both structs are equal in size */
3153     memcpy(&resultsW, lpResults, sizeof(resultsW));
3154
3155     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3156     if(lpResults->lpOutString)
3157         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3158
3159     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3160
3161     lpResults->nGlyphs = resultsW.nGlyphs;
3162     lpResults->nMaxFit = resultsW.nMaxFit;
3163
3164     if(lpResults->lpOutString) {
3165         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3166                             lpResults->lpOutString, uCount, NULL, NULL );
3167     }
3168
3169     HeapFree(GetProcessHeap(), 0, lpStringW);
3170     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3171
3172     return ret;
3173 }
3174
3175 /*************************************************************************
3176  * GetCharacterPlacementW [GDI32.@]
3177  *
3178  *   Retrieve information about a string. This includes the width, reordering,
3179  *   Glyphing and so on.
3180  *
3181  * RETURNS
3182  *
3183  *   The width and height of the string if successful, 0 if failed.
3184  *
3185  * BUGS
3186  *
3187  *   All flags except GCP_REORDER are not yet implemented.
3188  *   Reordering is not 100% compliant to the Windows BiDi method.
3189  *   Caret positioning is not yet implemented for BiDi.
3190  *   Classes are not yet implemented.
3191  *
3192  */
3193 DWORD WINAPI
3194 GetCharacterPlacementW(
3195         HDC hdc,                    /* [in] Device context for which the rendering is to be done */
3196         LPCWSTR lpString,           /* [in] The string for which information is to be returned */
3197         INT uCount,                 /* [in] Number of WORDS in string. */
3198         INT nMaxExtent,             /* [in] Maximum extent the string is to take (in HDC logical units) */
3199         GCP_RESULTSW *lpResults,    /* [in/out] A pointer to a GCP_RESULTSW struct */
3200         DWORD dwFlags               /* [in] Flags specifying how to process the string */
3201         )
3202 {
3203     DWORD ret=0;
3204     SIZE size;
3205     UINT i, nSet;
3206
3207     TRACE("%s, %d, %d, 0x%08x\n",
3208           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3209
3210     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3211           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3212           lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3213           lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3214           lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3215
3216     if(dwFlags&(~GCP_REORDER))
3217         FIXME("flags 0x%08x ignored\n", dwFlags);
3218     if(lpResults->lpClass)
3219         FIXME("classes not implemented\n");
3220     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3221         FIXME("Caret positions for complex scripts not implemented\n");
3222
3223     nSet = (UINT)uCount;
3224     if(nSet > lpResults->nGlyphs)
3225         nSet = lpResults->nGlyphs;
3226
3227     /* return number of initialized fields */
3228     lpResults->nGlyphs = nSet;
3229
3230     if((dwFlags&GCP_REORDER)==0 )
3231     {
3232         /* Treat the case where no special handling was requested in a fastpath way */
3233         /* copy will do if the GCP_REORDER flag is not set */
3234         if(lpResults->lpOutString)
3235             memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3236
3237         if(lpResults->lpOrder)
3238         {
3239             for(i = 0; i < nSet; i++)
3240                 lpResults->lpOrder[i] = i;
3241         }
3242     }
3243     else
3244     {
3245         BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3246                      nSet, lpResults->lpOrder, NULL, NULL );
3247     }
3248
3249     /* FIXME: Will use the placement chars */
3250     if (lpResults->lpDx)
3251     {
3252         int c;
3253         for (i = 0; i < nSet; i++)
3254         {
3255             if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3256                 lpResults->lpDx[i]= c;
3257         }
3258     }
3259
3260     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3261     {
3262         int pos = 0;
3263
3264         lpResults->lpCaretPos[0] = 0;
3265         for (i = 1; i < nSet; i++)
3266             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3267                 lpResults->lpCaretPos[i] = (pos += size.cx);
3268     }
3269
3270     if(lpResults->lpGlyphs)
3271         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3272
3273     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3274         ret = MAKELONG(size.cx, size.cy);
3275
3276     return ret;
3277 }
3278
3279 /*************************************************************************
3280  *      GetCharABCWidthsFloatA [GDI32.@]
3281  *
3282  * See GetCharABCWidthsFloatW.
3283  */
3284 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3285 {
3286     INT i, wlen;
3287     LPSTR str;
3288     LPWSTR wstr;
3289     BOOL ret = TRUE;
3290
3291     str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3292     if (str == NULL)
3293         return FALSE;
3294
3295     wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3296
3297     for (i = 0; i < wlen; i++)
3298     {
3299         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3300         {
3301             ret = FALSE;
3302             break;
3303         }
3304         abcf++;
3305     }
3306
3307     HeapFree( GetProcessHeap(), 0, str );
3308     HeapFree( GetProcessHeap(), 0, wstr );
3309
3310     return ret;
3311 }
3312
3313 /*************************************************************************
3314  *      GetCharABCWidthsFloatW [GDI32.@]
3315  *
3316  * Retrieves widths of a range of characters.
3317  *
3318  * PARAMS
3319  *    hdc   [I] Handle to device context.
3320  *    first [I] First character in range to query.
3321  *    last  [I] Last character in range to query.
3322  *    abcf  [O] Array of LPABCFLOAT structures.
3323  *
3324  * RETURNS
3325  *    Success: TRUE
3326  *    Failure: FALSE
3327  */
3328 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3329 {
3330     UINT i;
3331     ABC *abc;
3332     PHYSDEV dev;
3333     BOOL ret = FALSE;
3334     DC *dc = get_dc_ptr( hdc );
3335
3336     TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3337
3338     if (!dc) return FALSE;
3339
3340     if (!abcf) goto done;
3341     if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3342
3343     dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3344     ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3345     if (ret)
3346     {
3347         /* convert device units to logical */
3348         for (i = first; i <= last; i++, abcf++)
3349         {
3350             abcf->abcfA = abc[i - first].abcA * dc->xformVport2World.eM11;
3351             abcf->abcfB = abc[i - first].abcB * dc->xformVport2World.eM11;
3352             abcf->abcfC = abc[i - first].abcC * dc->xformVport2World.eM11;
3353         }
3354     }
3355     HeapFree( GetProcessHeap(), 0, abc );
3356
3357 done:
3358     release_dc_ptr( dc );
3359     return ret;
3360 }
3361
3362 /*************************************************************************
3363  *      GetCharWidthFloatA [GDI32.@]
3364  */
3365 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3366                                     UINT iLastChar, PFLOAT pxBuffer)
3367 {
3368     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3369     return 0;
3370 }
3371
3372 /*************************************************************************
3373  *      GetCharWidthFloatW [GDI32.@]
3374  */
3375 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3376                                     UINT iLastChar, PFLOAT pxBuffer)
3377 {
3378     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3379     return 0;
3380 }
3381
3382
3383 /***********************************************************************
3384  *                                                                     *
3385  *           Font Resource API                                         *
3386  *                                                                     *
3387  ***********************************************************************/
3388
3389 /***********************************************************************
3390  *           AddFontResourceA    (GDI32.@)
3391  */
3392 INT WINAPI AddFontResourceA( LPCSTR str )
3393 {
3394     return AddFontResourceExA( str, 0, NULL);
3395 }
3396
3397 /***********************************************************************
3398  *           AddFontResourceW    (GDI32.@)
3399  */
3400 INT WINAPI AddFontResourceW( LPCWSTR str )
3401 {
3402     return AddFontResourceExW(str, 0, NULL);
3403 }
3404
3405
3406 /***********************************************************************
3407  *           AddFontResourceExA    (GDI32.@)
3408  */
3409 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3410 {
3411     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3412     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3413     INT ret;
3414
3415     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3416     ret = AddFontResourceExW(strW, fl, pdv);
3417     HeapFree(GetProcessHeap(), 0, strW);
3418     return ret;
3419 }
3420
3421 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3422 {
3423     HRSRC rsrc = FindResourceW(hModule, name, type);
3424     HGLOBAL hMem = LoadResource(hModule, rsrc);
3425     LPVOID *pMem = LockResource(hMem);
3426     int *num_total = (int *)lParam;
3427     DWORD num_in_res;
3428
3429     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3430     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3431     {
3432         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3433         return FALSE;
3434     }
3435
3436     *num_total += num_in_res;
3437     return TRUE;
3438 }
3439
3440 static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
3441 {
3442     HANDLE file, mapping;
3443     void *ptr;
3444
3445     file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
3446     if (file == INVALID_HANDLE_VALUE) return NULL;
3447
3448     if (!GetFileSizeEx( file, size ) || size->u.HighPart)
3449     {
3450         CloseHandle( file );
3451         return NULL;
3452     }
3453
3454     mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
3455     CloseHandle( file );
3456     if (!mapping) return NULL;
3457
3458     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
3459     CloseHandle( mapping );
3460
3461     return ptr;
3462 }
3463
3464 static void *find_resource( BYTE *ptr, WORD type, DWORD rsrc_off, DWORD size, DWORD *len )
3465 {
3466     WORD align, type_id, count;
3467     DWORD res_off;
3468
3469     if (size < rsrc_off + 10) return NULL;
3470     align = *(WORD *)(ptr + rsrc_off);
3471     rsrc_off += 2;
3472     type_id = *(WORD *)(ptr + rsrc_off);
3473     while (type_id && type_id != type)
3474     {
3475         count = *(WORD *)(ptr + rsrc_off + 2);
3476         rsrc_off += 8 + count * 12;
3477         if (size < rsrc_off + 8) return NULL;
3478         type_id = *(WORD *)(ptr + rsrc_off);
3479     }
3480     if (!type_id) return NULL;
3481     count = *(WORD *)(ptr + rsrc_off + 2);
3482     if (size < rsrc_off + 8 + count * 12) return NULL;
3483     res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
3484     *len = *(WORD *)(ptr + rsrc_off + 10) << align;
3485     if (size < res_off + *len) return NULL;
3486     return ptr + res_off;
3487 }
3488
3489 static WCHAR *get_scalable_filename( const WCHAR *res, BOOL *hidden )
3490 {
3491     LARGE_INTEGER size;
3492     BYTE *ptr = map_file( res, &size );
3493     const IMAGE_DOS_HEADER *dos;
3494     const IMAGE_OS2_HEADER *ne;
3495     WORD *fontdir;
3496     char *data;
3497     WCHAR *name = NULL;
3498     DWORD len;
3499
3500     if (!ptr) return NULL;
3501
3502     if (size.u.LowPart < sizeof( *dos )) goto fail;
3503     dos = (const IMAGE_DOS_HEADER *)ptr;
3504     if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
3505     if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
3506     ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
3507
3508     fontdir = find_resource( ptr, 0x8007, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
3509     if (!fontdir) goto fail;
3510     *hidden = (fontdir[35] & 0x80) != 0;  /* fontdir->dfType */
3511
3512     data = find_resource( ptr, 0x80cc, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
3513     if (!data) goto fail;
3514     if (!memchr( data, 0, len )) goto fail;
3515
3516     len = MultiByteToWideChar( CP_ACP, 0, data, -1, NULL, 0 );
3517     name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3518     if (name) MultiByteToWideChar( CP_ACP, 0, data, -1, name, len );
3519
3520 fail:
3521     UnmapViewOfFile( ptr );
3522     return name;
3523 }
3524
3525 /***********************************************************************
3526  *           AddFontResourceExW    (GDI32.@)
3527  */
3528 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3529 {
3530     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3531     WCHAR *filename;
3532     BOOL hidden;
3533
3534     if (ret == 0)
3535     {
3536         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3537         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3538         if (hModule != NULL)
3539         {
3540             int num_resources = 0;
3541             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3542
3543             TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3544                 wine_dbgstr_w(str));
3545             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3546                 ret = num_resources;
3547             FreeLibrary(hModule);
3548         }
3549         else if ((filename = get_scalable_filename( str, &hidden )) != NULL)
3550         {
3551             if (hidden) fl |= FR_PRIVATE | FR_NOT_ENUM;
3552             ret = WineEngAddFontResourceEx( filename, fl, pdv );
3553             HeapFree( GetProcessHeap(), 0, filename );
3554         }
3555     }
3556     return ret;
3557 }
3558
3559 /***********************************************************************
3560  *           RemoveFontResourceA    (GDI32.@)
3561  */
3562 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3563 {
3564     return RemoveFontResourceExA(str, 0, 0);
3565 }
3566
3567 /***********************************************************************
3568  *           RemoveFontResourceW    (GDI32.@)
3569  */
3570 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3571 {
3572     return RemoveFontResourceExW(str, 0, 0);
3573 }
3574
3575 /***********************************************************************
3576  *           AddFontMemResourceEx    (GDI32.@)
3577  */
3578 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3579 {
3580     HANDLE ret;
3581     DWORD num_fonts;
3582
3583     if (!pbFont || !cbFont || !pcFonts)
3584     {
3585         SetLastError(ERROR_INVALID_PARAMETER);
3586         return NULL;
3587     }
3588
3589     ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3590     if (ret)
3591     {
3592         __TRY
3593         {
3594             *pcFonts = num_fonts;
3595         }
3596         __EXCEPT_PAGE_FAULT
3597         {
3598             WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3599             RemoveFontMemResourceEx(ret);
3600             ret = 0;
3601         }
3602         __ENDTRY
3603     }
3604     return ret;
3605 }
3606
3607 /***********************************************************************
3608  *           RemoveFontMemResourceEx    (GDI32.@)
3609  */
3610 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3611 {
3612     FIXME("(%p) stub\n", fh);
3613     return TRUE;
3614 }
3615
3616 /***********************************************************************
3617  *           RemoveFontResourceExA    (GDI32.@)
3618  */
3619 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3620 {
3621     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3622     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3623     INT ret;
3624
3625     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3626     ret = RemoveFontResourceExW(strW, fl, pdv);
3627     HeapFree(GetProcessHeap(), 0, strW);
3628     return ret;
3629 }
3630
3631 /***********************************************************************
3632  *           RemoveFontResourceExW    (GDI32.@)
3633  */
3634 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3635 {
3636     int ret = WineEngRemoveFontResourceEx( str, fl, pdv );
3637     WCHAR *filename;
3638     BOOL hidden;
3639
3640     if (ret == 0)
3641     {
3642         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3643         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3644         if (hModule != NULL)
3645         {
3646             WARN("Can't unload resources from PE file %s\n", wine_dbgstr_w(str));
3647             FreeLibrary(hModule);
3648         }
3649         else if ((filename = get_scalable_filename( str, &hidden )) != NULL)
3650         {
3651             if (hidden) fl |= FR_PRIVATE | FR_NOT_ENUM;
3652             ret = WineEngRemoveFontResourceEx( filename, fl, pdv );
3653             HeapFree( GetProcessHeap(), 0, filename );
3654         }
3655     }
3656     return ret;
3657 }
3658
3659 /***********************************************************************
3660  *           GetFontResourceInfoW    (GDI32.@)
3661  */
3662 BOOL WINAPI GetFontResourceInfoW( LPCWSTR str, LPDWORD size, PVOID buffer, DWORD type )
3663 {
3664     FIXME("%s %p(%d) %p %d\n", debugstr_w(str), size, size ? *size : 0, buffer, type);
3665     return FALSE;
3666 }
3667
3668 /***********************************************************************
3669  *           GetTextCharset    (GDI32.@)
3670  */
3671 UINT WINAPI GetTextCharset(HDC hdc)
3672 {
3673     /* MSDN docs say this is equivalent */
3674     return GetTextCharsetInfo(hdc, NULL, 0);
3675 }
3676
3677 /***********************************************************************
3678  *           GetTextCharsetInfo    (GDI32.@)
3679  */
3680 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3681 {
3682     UINT ret = DEFAULT_CHARSET;
3683     DC *dc = get_dc_ptr(hdc);
3684     PHYSDEV dev;
3685
3686     if (dc)
3687     {
3688         dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3689         ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3690         release_dc_ptr( dc );
3691     }
3692
3693     if (ret == DEFAULT_CHARSET && fs)
3694         memset(fs, 0, sizeof(FONTSIGNATURE));
3695     return ret;
3696 }
3697
3698 /***********************************************************************
3699  *           GdiGetCharDimensions    (GDI32.@)
3700  *
3701  * Gets the average width of the characters in the English alphabet.
3702  *
3703  * PARAMS
3704  *  hdc    [I] Handle to the device context to measure on.
3705  *  lptm   [O] Pointer to memory to store the text metrics into.
3706  *  height [O] On exit, the maximum height of characters in the English alphabet.
3707  *
3708  * RETURNS
3709  *  The average width of characters in the English alphabet.
3710  *
3711  * NOTES
3712  *  This function is used by the dialog manager to get the size of a dialog
3713  *  unit. It should also be used by other pieces of code that need to know
3714  *  the size of a dialog unit in logical units without having access to the
3715  *  window handle of the dialog.
3716  *  Windows caches the font metrics from this function, but we don't and
3717  *  there doesn't appear to be an immediate advantage to do so.
3718  *
3719  * SEE ALSO
3720  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3721  */
3722 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3723 {
3724     SIZE sz;
3725     static const WCHAR alphabet[] = {
3726         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3727         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3728         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3729
3730     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3731
3732     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3733
3734     if (height) *height = sz.cy;
3735     return (sz.cx / 26 + 1) / 2;
3736 }
3737
3738 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3739 {
3740     FIXME("(%d): stub\n", fEnableEUDC);
3741     return FALSE;
3742 }
3743
3744 /***********************************************************************
3745  *           GetCharWidthI    (GDI32.@)
3746  *
3747  * Retrieve widths of characters.
3748  *
3749  * PARAMS
3750  *  hdc    [I] Handle to a device context.
3751  *  first  [I] First glyph in range to query.
3752  *  count  [I] Number of glyph indices to query.
3753  *  glyphs [I] Array of glyphs to query.
3754  *  buffer [O] Buffer to receive character widths.
3755  *
3756  * NOTES
3757  *  Only works with TrueType fonts.
3758  *
3759  * RETURNS
3760  *  Success: TRUE
3761  *  Failure: FALSE
3762  */
3763 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3764 {
3765     ABC *abc;
3766     unsigned int i;
3767
3768     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3769
3770     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3771         return FALSE;
3772
3773     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3774     {
3775         HeapFree(GetProcessHeap(), 0, abc);
3776         return FALSE;
3777     }
3778
3779     for (i = 0; i < count; i++)
3780         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3781
3782     HeapFree(GetProcessHeap(), 0, abc);
3783     return TRUE;
3784 }
3785
3786 /***********************************************************************
3787  *           GetFontUnicodeRanges    (GDI32.@)
3788  *
3789  *  Retrieve a list of supported Unicode characters in a font.
3790  *
3791  *  PARAMS
3792  *   hdc  [I] Handle to a device context.
3793  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3794  *
3795  *  RETURNS
3796  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3797  *   Failure: 0
3798  *
3799  */
3800 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3801 {
3802     DWORD ret;
3803     PHYSDEV dev;
3804     DC *dc = get_dc_ptr(hdc);
3805
3806     TRACE("(%p, %p)\n", hdc, lpgs);
3807
3808     if (!dc) return 0;
3809
3810     dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3811     ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3812     release_dc_ptr(dc);
3813     return ret;
3814 }
3815
3816
3817 /*************************************************************
3818  *           FontIsLinked    (GDI32.@)
3819  */
3820 BOOL WINAPI FontIsLinked(HDC hdc)
3821 {
3822     DC *dc = get_dc_ptr(hdc);
3823     PHYSDEV dev;
3824     BOOL ret;
3825
3826     if (!dc) return FALSE;
3827     dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3828     ret = dev->funcs->pFontIsLinked( dev );
3829     release_dc_ptr(dc);
3830     TRACE("returning %d\n", ret);
3831     return ret;
3832 }
3833
3834 /*************************************************************
3835  *           GdiRealizationInfo    (GDI32.@)
3836  *
3837  * Returns a structure that contains some font information.
3838  */
3839 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3840 {
3841     DC *dc = get_dc_ptr(hdc);
3842     PHYSDEV dev;
3843     BOOL ret;
3844
3845     if (!dc) return FALSE;
3846     dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3847     ret = dev->funcs->pGdiRealizationInfo( dev, info );
3848     release_dc_ptr(dc);
3849     return ret;
3850 }