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