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