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