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