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