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