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