~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/gdi32/font.c

Version: ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.