4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
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.
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.
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
24 #include "wine/port.h"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 /* Perform operation with floating point */
51 floatWidth = (double)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 /* Perform operation with floating point */
64 floatHeight = (double)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 pt[0].x = pt[0].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 pt[0].x = pt[0].y = 0;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
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 );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
111 LPLOGFONTW lpLogFontParam;
112 FONTENUMPROCW lpEnumFunc;
119 * For TranslateCharsetInfo
121 #define MAXTCIINDEX 32
122 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
124 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
125 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
126 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
127 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
128 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
129 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
130 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
131 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
132 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
133 /* reserved by ANSI */
134 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
135 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
136 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
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}} },
142 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
143 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
144 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
145 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
146 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
147 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
148 /* reserved for alternate ANSI and OEM */
149 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
150 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
151 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 /* reserved for system */
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
162 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
164 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
165 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
167 fontW->lfFaceName[LF_FACESIZE-1] = 0;
170 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
172 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
173 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
174 LF_FACESIZE, NULL, NULL);
175 fontA->lfFaceName[LF_FACESIZE-1] = 0;
178 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
180 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
182 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
183 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
184 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
186 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
187 fontA->elfStyle[LF_FACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
189 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
190 fontA->elfScript[LF_FACESIZE-1] = '\0';
193 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
195 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
197 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
198 fontW->elfFullName, LF_FULLFACESIZE );
199 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
201 fontW->elfStyle, LF_FACESIZE );
202 fontW->elfStyle[LF_FACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
204 fontW->elfScript, LF_FACESIZE );
205 fontW->elfScript[LF_FACESIZE-1] = '\0';
208 /***********************************************************************
209 * TEXTMETRIC conversion functions.
211 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
213 ptmA->tmHeight = ptmW->tmHeight;
214 ptmA->tmAscent = ptmW->tmAscent;
215 ptmA->tmDescent = ptmW->tmDescent;
216 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
217 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
218 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
219 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
220 ptmA->tmWeight = ptmW->tmWeight;
221 ptmA->tmOverhang = ptmW->tmOverhang;
222 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
223 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
224 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
225 if (ptmW->tmCharSet == SYMBOL_CHARSET)
227 ptmA->tmFirstChar = 0x1e;
228 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
230 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
232 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
233 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
237 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
238 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
240 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
241 ptmA->tmBreakChar = ptmW->tmBreakChar;
242 ptmA->tmItalic = ptmW->tmItalic;
243 ptmA->tmUnderlined = ptmW->tmUnderlined;
244 ptmA->tmStruckOut = ptmW->tmStruckOut;
245 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
246 ptmA->tmCharSet = ptmW->tmCharSet;
250 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
252 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
253 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
254 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
255 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
256 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
257 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
261 UINT get_font_aa_flags( HDC hdc )
265 if (GetObjectType( hdc ) == OBJ_MEMDC)
268 GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(bm), &bm );
269 if (bm.bmBitsPixel <= 8) return GGO_BITMAP;
271 else if (GetDeviceCaps( hdc, BITSPIXEL ) <= 8) return GGO_BITMAP;
273 GetObjectW( GetCurrentObject( hdc, OBJ_FONT ), sizeof(lf), &lf );
274 if (lf.lfQuality == NONANTIALIASED_QUALITY) return GGO_BITMAP;
276 /* FIXME, check gasp and user prefs */
277 return GGO_GRAY4_BITMAP;
280 /***********************************************************************
281 * GdiGetCodePage (GDI32.@)
283 DWORD WINAPI GdiGetCodePage( HDC hdc )
286 DC *dc = get_dc_ptr( hdc );
290 cp = dc->font_code_page;
291 release_dc_ptr( dc );
296 /***********************************************************************
299 * Returns a Unicode translation of str using the charset of the
300 * currently selected font in hdc. If count is -1 then str is assumed
301 * to be '\0' terminated, otherwise it contains the number of bytes to
302 * convert. If plenW is non-NULL, on return it will point to the
303 * number of WCHARs that have been written. If pCP is non-NULL, on
304 * return it will point to the codepage used in the conversion. The
305 * caller should free the returned LPWSTR from the process heap
308 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
314 cp = GdiGetCodePage( hdc );
316 if(count == -1) count = strlen(str);
317 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
318 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
319 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
320 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
321 if(plenW) *plenW = lenW;
326 /***********************************************************************
327 * CreateFontIndirectExA (GDI32.@)
329 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
331 ENUMLOGFONTEXDVW enumexW;
333 if (!penumexA) return 0;
335 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
336 enumexW.elfDesignVector = penumexA->elfDesignVector;
337 return CreateFontIndirectExW( &enumexW );
340 /***********************************************************************
341 * CreateFontIndirectExW (GDI32.@)
343 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
349 if (!penumex) return 0;
351 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
352 penumex->elfEnumLogfontEx.elfStyle[0] ||
353 penumex->elfEnumLogfontEx.elfScript[0])
355 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
356 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
357 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
358 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
361 plf = &penumex->elfEnumLogfontEx.elfLogFont;
362 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
364 fontPtr->logfont = *plf;
366 if (plf->lfEscapement != plf->lfOrientation)
368 /* this should really depend on whether GM_ADVANCED is set */
369 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
370 WARN("orientation angle %f set to "
371 "escapement angle %f for new font %p\n",
372 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
375 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
377 HeapFree( GetProcessHeap(), 0, fontPtr );
381 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
382 plf->lfHeight, plf->lfWidth,
383 plf->lfEscapement, plf->lfOrientation,
384 plf->lfPitchAndFamily,
385 plf->lfOutPrecision, plf->lfClipPrecision,
386 plf->lfQuality, plf->lfCharSet,
387 debugstr_w(plf->lfFaceName),
388 plf->lfWeight > 400 ? "Bold" : "",
389 plf->lfItalic ? "Italic" : "",
390 plf->lfUnderline ? "Underline" : "", hFont);
395 /***********************************************************************
396 * CreateFontIndirectA (GDI32.@)
398 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
404 FONT_LogFontAToW( plfA, &lfW );
405 return CreateFontIndirectW( &lfW );
408 /***********************************************************************
409 * CreateFontIndirectW (GDI32.@)
411 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
413 ENUMLOGFONTEXDVW exdv;
417 exdv.elfEnumLogfontEx.elfLogFont = *plf;
418 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
419 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
420 exdv.elfEnumLogfontEx.elfScript[0] = 0;
421 return CreateFontIndirectExW( &exdv );
424 /*************************************************************************
425 * CreateFontA (GDI32.@)
427 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
428 INT orient, INT weight, DWORD italic,
429 DWORD underline, DWORD strikeout, DWORD charset,
430 DWORD outpres, DWORD clippres, DWORD quality,
431 DWORD pitch, LPCSTR name )
435 logfont.lfHeight = height;
436 logfont.lfWidth = width;
437 logfont.lfEscapement = esc;
438 logfont.lfOrientation = orient;
439 logfont.lfWeight = weight;
440 logfont.lfItalic = italic;
441 logfont.lfUnderline = underline;
442 logfont.lfStrikeOut = strikeout;
443 logfont.lfCharSet = charset;
444 logfont.lfOutPrecision = outpres;
445 logfont.lfClipPrecision = clippres;
446 logfont.lfQuality = quality;
447 logfont.lfPitchAndFamily = pitch;
450 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
452 logfont.lfFaceName[0] = '\0';
454 return CreateFontIndirectA( &logfont );
457 /*************************************************************************
458 * CreateFontW (GDI32.@)
460 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
461 INT orient, INT weight, DWORD italic,
462 DWORD underline, DWORD strikeout, DWORD charset,
463 DWORD outpres, DWORD clippres, DWORD quality,
464 DWORD pitch, LPCWSTR name )
468 logfont.lfHeight = height;
469 logfont.lfWidth = width;
470 logfont.lfEscapement = esc;
471 logfont.lfOrientation = orient;
472 logfont.lfWeight = weight;
473 logfont.lfItalic = italic;
474 logfont.lfUnderline = underline;
475 logfont.lfStrikeOut = strikeout;
476 logfont.lfCharSet = charset;
477 logfont.lfOutPrecision = outpres;
478 logfont.lfClipPrecision = clippres;
479 logfont.lfQuality = quality;
480 logfont.lfPitchAndFamily = pitch;
483 lstrcpynW(logfont.lfFaceName, name,
484 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
486 logfont.lfFaceName[0] = '\0';
488 return CreateFontIndirectW( &logfont );
491 static void update_font_code_page( DC *dc )
494 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
496 /* Hmm, nicely designed api this one! */
497 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
498 dc->font_code_page = csi.ciACP;
502 dc->font_code_page = GetOEMCP();
504 case DEFAULT_CHARSET:
505 dc->font_code_page = GetACP();
515 /* FIXME: These have no place here, but because x11drv
516 enumerates fonts with these (made up) charsets some apps
517 might use them and then the FIXME below would become
518 annoying. Now we could pick the intended codepage for
519 each of these, but since it's broken anyway we'll just
520 use CP_ACP and hope it'll go away...
522 dc->font_code_page = CP_ACP;
526 FIXME("Can't find codepage for charset %d\n", charset);
527 dc->font_code_page = CP_ACP;
532 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
535 /***********************************************************************
538 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
541 DC *dc = get_dc_ptr( hdc );
546 if (!GDI_inc_ref_count( handle ))
548 release_dc_ptr( dc );
552 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
553 if (physdev->funcs->pSelectFont( physdev, handle ))
557 update_font_code_page( dc );
558 GDI_dec_ref_count( ret );
560 else GDI_dec_ref_count( handle );
562 release_dc_ptr( dc );
567 /***********************************************************************
570 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
572 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
578 FONT_LogFontWToA( &font->logfont, &lfA );
579 if (count > sizeof(lfA)) count = sizeof(lfA);
580 memcpy( buffer, &lfA, count );
582 else count = sizeof(lfA);
583 GDI_ReleaseObj( handle );
587 /***********************************************************************
590 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
592 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
597 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
598 memcpy( buffer, &font->logfont, count );
600 else count = sizeof(LOGFONTW);
601 GDI_ReleaseObj( handle );
606 /***********************************************************************
609 static BOOL FONT_DeleteObject( HGDIOBJ handle )
613 WineEngDestroyFontInstance( handle );
615 if (!(obj = free_gdi_handle( handle ))) return FALSE;
616 return HeapFree( GetProcessHeap(), 0, obj );
620 /***********************************************************************
623 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
624 * We have to use other types because of the FONTENUMPROCW definition.
626 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
627 DWORD fType, LPARAM lp )
629 struct font_enum *pfe = (struct font_enum *)lp;
632 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
633 if ((!pfe->lpLogFontParam ||
634 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
635 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
636 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
638 /* convert font metrics */
639 ENUMLOGFONTEXA logfont;
640 NEWTEXTMETRICEXA tmA;
644 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
645 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
646 plf = (LOGFONTW *)&logfont.elfLogFont;
647 ptm = (TEXTMETRICW *)&tmA;
649 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
654 /***********************************************************************
655 * FONT_EnumFontFamiliesEx
657 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
658 LPARAM lParam, BOOL unicode )
661 DC *dc = get_dc_ptr( hDC );
666 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
668 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
669 fe.lpLogFontParam = plf;
670 fe.lpEnumFunc = efproc;
672 fe.unicode = unicode;
674 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
675 release_dc_ptr( dc );
680 /***********************************************************************
681 * EnumFontFamiliesExW (GDI32.@)
683 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
684 FONTENUMPROCW efproc,
685 LPARAM lParam, DWORD dwFlags )
687 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
690 /***********************************************************************
691 * EnumFontFamiliesExA (GDI32.@)
693 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
694 FONTENUMPROCA efproc,
695 LPARAM lParam, DWORD dwFlags)
701 FONT_LogFontAToW( plf, &lfW );
706 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
709 /***********************************************************************
710 * EnumFontFamiliesA (GDI32.@)
712 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
713 FONTENUMPROCA efproc, LPARAM lpData )
719 if (!*lpFamily) return 1;
720 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
721 lf.lfCharSet = DEFAULT_CHARSET;
722 lf.lfPitchAndFamily = 0;
727 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
730 /***********************************************************************
731 * EnumFontFamiliesW (GDI32.@)
733 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
734 FONTENUMPROCW efproc, LPARAM lpData )
740 if (!*lpFamily) return 1;
741 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
742 lf.lfCharSet = DEFAULT_CHARSET;
743 lf.lfPitchAndFamily = 0;
748 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
751 /***********************************************************************
752 * EnumFontsA (GDI32.@)
754 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
757 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
760 /***********************************************************************
761 * EnumFontsW (GDI32.@)
763 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
766 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
770 /***********************************************************************
771 * GetTextCharacterExtra (GDI32.@)
773 INT WINAPI GetTextCharacterExtra( HDC hdc )
776 DC *dc = get_dc_ptr( hdc );
777 if (!dc) return 0x80000000;
779 release_dc_ptr( dc );
784 /***********************************************************************
785 * SetTextCharacterExtra (GDI32.@)
787 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
789 INT ret = 0x80000000;
790 DC * dc = get_dc_ptr( hdc );
794 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
795 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
796 if (extra != 0x80000000)
799 dc->charExtra = extra;
801 release_dc_ptr( dc );
807 /***********************************************************************
808 * SetTextJustification (GDI32.@)
810 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
814 DC * dc = get_dc_ptr( hdc );
816 if (!dc) return FALSE;
818 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
819 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
822 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
823 if (!extra) breaks = 0;
826 dc->breakExtra = extra / breaks;
827 dc->breakRem = extra - (breaks * dc->breakExtra);
835 release_dc_ptr( dc );
840 /***********************************************************************
841 * GetTextFaceA (GDI32.@)
843 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
845 INT res = GetTextFaceW(hdc, 0, NULL);
846 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
847 GetTextFaceW( hdc, res, nameW );
853 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
857 /* GetTextFaceA does NOT include the nul byte in the return count. */
864 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
865 HeapFree( GetProcessHeap(), 0, nameW );
869 /***********************************************************************
870 * GetTextFaceW (GDI32.@)
872 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
877 DC * dc = get_dc_ptr( hdc );
880 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
881 ret = dev->funcs->pGetTextFace( dev, count, name );
882 release_dc_ptr( dc );
887 /***********************************************************************
888 * GetTextExtentPoint32A (GDI32.@)
890 * See GetTextExtentPoint32W.
892 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
899 if (count < 0) return FALSE;
901 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
905 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
906 HeapFree( GetProcessHeap(), 0, p );
909 TRACE("(%p %s %d %p): returning %d x %d\n",
910 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
915 /***********************************************************************
916 * GetTextExtentPoint32W [GDI32.@]
918 * Computes width/height for a string.
920 * Computes width and height of the specified string.
926 BOOL WINAPI GetTextExtentPoint32W(
927 HDC hdc, /* [in] Handle of device context */
928 LPCWSTR str, /* [in] Address of text string */
929 INT count, /* [in] Number of characters in string */
930 LPSIZE size) /* [out] Address of structure for string size */
932 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
935 /***********************************************************************
936 * GetTextExtentExPointI [GDI32.@]
938 * Computes width and height of the array of glyph indices.
941 * hdc [I] Handle of device context.
942 * indices [I] Glyph index array.
943 * count [I] Number of glyphs in array.
944 * max_ext [I] Maximum width in glyphs.
945 * nfit [O] Maximum number of characters.
946 * dxs [O] Partial string widths.
947 * size [O] Returned string size.
953 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
954 LPINT nfit, LPINT dxs, LPSIZE size )
960 if (count < 0) return FALSE;
962 dc = get_dc_ptr( hdc );
963 if (!dc) return FALSE;
965 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
966 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
967 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
968 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
969 size->cx += count * dc->charExtra;
970 release_dc_ptr( dc );
972 TRACE("(%p %p %d %p): returning %d x %d\n",
973 hdc, indices, count, size, size->cx, size->cy );
977 /***********************************************************************
978 * GetTextExtentPointI [GDI32.@]
980 * Computes width and height of the array of glyph indices.
983 * hdc [I] Handle of device context.
984 * indices [I] Glyph index array.
985 * count [I] Number of glyphs in array.
986 * size [O] Returned string size.
992 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
994 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
998 /***********************************************************************
999 * GetTextExtentPointA (GDI32.@)
1001 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1004 TRACE("not bug compatible.\n");
1005 return GetTextExtentPoint32A( hdc, str, count, size );
1008 /***********************************************************************
1009 * GetTextExtentPointW (GDI32.@)
1011 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1014 TRACE("not bug compatible.\n");
1015 return GetTextExtentPoint32W( hdc, str, count, size );
1019 /***********************************************************************
1020 * GetTextExtentExPointA (GDI32.@)
1022 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1023 INT maxExt, LPINT lpnFit,
1024 LPINT alpDx, LPSIZE size )
1031 if (count < 0) return FALSE;
1035 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1036 if (!walpDx) return FALSE;
1039 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1040 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1043 INT n = lpnFit ? *lpnFit : wlen;
1045 for(i = 0, j = 0; i < n; i++, j++)
1047 alpDx[j] = walpDx[i];
1048 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1051 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1052 HeapFree( GetProcessHeap(), 0, p );
1053 HeapFree( GetProcessHeap(), 0, walpDx );
1058 /***********************************************************************
1059 * GetTextExtentExPointW (GDI32.@)
1061 * Return the size of the string as it would be if it was output properly by
1064 * This should include
1065 * - Intercharacter spacing
1066 * - justification spacing (not yet done)
1067 * - kerning? see below
1069 * Kerning. Since kerning would be carried out by the rendering code it should
1070 * be done by the driver. However they don't support it yet. Also I am not
1071 * yet persuaded that (certainly under Win95) any kerning is actually done.
1073 * str: According to MSDN this should be null-terminated. That is not true; a
1074 * null will not terminate it early.
1075 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1076 * than count. I have seen it be either the size of the full string or
1077 * 1 less than the size of the full string. I have not seen it bear any
1078 * resemblance to the portion that would fit.
1079 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1080 * trailing intercharacter spacing and any trailing justification.
1083 * Currently we do this by measuring each character etc. We should do it by
1084 * passing the request to the driver, perhaps by extending the
1085 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1086 * thinking about kerning issues and rounding issues in the justification.
1089 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1090 INT maxExt, LPINT lpnFit,
1091 LPINT alpDx, LPSIZE size )
1100 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1102 if (count < 0) return FALSE;
1104 dc = get_dc_ptr(hdc);
1105 if (!dc) return FALSE;
1107 GetTextMetricsW(hdc, &tm);
1109 /* If we need to calculate nFit, then we need the partial extents even if
1110 the user hasn't provided us with an array. */
1113 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1117 SetLastError(ERROR_OUTOFMEMORY);
1124 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1125 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1127 /* Perform device size to world size transformations. */
1130 INT extra = dc->charExtra,
1131 breakExtra = dc->breakExtra,
1132 breakRem = dc->breakRem,
1137 for (i = 0; i < count; ++i)
1139 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1140 dxs[i] += (i+1) * extra;
1141 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1143 dxs[i] += breakExtra;
1150 if (dxs[i] <= maxExt)
1153 breakRem = dc->breakRem;
1155 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1156 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1158 if (!dxs && count > 1 && (breakExtra || breakRem))
1160 for (i = 0; i < count; i++)
1162 if (str[i] == tm.tmBreakChar)
1164 size->cx += breakExtra;
1179 HeapFree(GetProcessHeap(), 0, dxs);
1181 release_dc_ptr( dc );
1183 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1187 /***********************************************************************
1188 * GetTextMetricsA (GDI32.@)
1190 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1194 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1195 FONT_TextMetricWToA( &tm32, metrics );
1199 /***********************************************************************
1200 * GetTextMetricsW (GDI32.@)
1202 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1206 DC * dc = get_dc_ptr( hdc );
1207 if (!dc) return FALSE;
1209 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1210 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1214 /* device layer returns values in device units
1215 * therefore we have to convert them to logical */
1217 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1218 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1220 #define WDPTOLP(x) ((x<0)? \
1221 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1222 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1223 #define HDPTOLP(y) ((y<0)? \
1224 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1225 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1227 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1228 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1229 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1230 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1231 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1232 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1233 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1234 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1238 TRACE("text metrics:\n"
1239 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1240 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1241 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1242 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1243 " PitchAndFamily = %02x\n"
1244 " --------------------\n"
1245 " InternalLeading = %i\n"
1249 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1250 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1251 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1252 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1253 metrics->tmPitchAndFamily,
1254 metrics->tmInternalLeading,
1257 metrics->tmHeight );
1259 release_dc_ptr( dc );
1264 /***********************************************************************
1265 * GetOutlineTextMetricsA (GDI32.@)
1266 * Gets metrics for TrueType fonts.
1269 * If the supplied buffer isn't big enough Windows partially fills it up to
1270 * its given length and returns that length.
1273 * Success: Non-zero or size of required buffer
1276 UINT WINAPI GetOutlineTextMetricsA(
1277 HDC hdc, /* [in] Handle of device context */
1278 UINT cbData, /* [in] Size of metric data array */
1279 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1281 char buf[512], *ptr;
1283 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1284 OUTLINETEXTMETRICA *output = lpOTM;
1287 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1289 if(ret > sizeof(buf))
1290 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1291 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1293 needed = sizeof(OUTLINETEXTMETRICA);
1294 if(lpOTMW->otmpFamilyName)
1295 needed += WideCharToMultiByte(CP_ACP, 0,
1296 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1297 NULL, 0, NULL, NULL);
1298 if(lpOTMW->otmpFaceName)
1299 needed += WideCharToMultiByte(CP_ACP, 0,
1300 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1301 NULL, 0, NULL, NULL);
1302 if(lpOTMW->otmpStyleName)
1303 needed += WideCharToMultiByte(CP_ACP, 0,
1304 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1305 NULL, 0, NULL, NULL);
1306 if(lpOTMW->otmpFullName)
1307 needed += WideCharToMultiByte(CP_ACP, 0,
1308 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1309 NULL, 0, NULL, NULL);
1316 TRACE("needed = %d\n", needed);
1318 /* Since the supplied buffer isn't big enough, we'll alloc one
1319 that is and memcpy the first cbData bytes into the lpOTM at
1321 output = HeapAlloc(GetProcessHeap(), 0, needed);
1323 ret = output->otmSize = min(needed, cbData);
1324 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1325 output->otmFiller = 0;
1326 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1327 output->otmfsSelection = lpOTMW->otmfsSelection;
1328 output->otmfsType = lpOTMW->otmfsType;
1329 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1330 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1331 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1332 output->otmEMSquare = lpOTMW->otmEMSquare;
1333 output->otmAscent = lpOTMW->otmAscent;
1334 output->otmDescent = lpOTMW->otmDescent;
1335 output->otmLineGap = lpOTMW->otmLineGap;
1336 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1337 output->otmsXHeight = lpOTMW->otmsXHeight;
1338 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1339 output->otmMacAscent = lpOTMW->otmMacAscent;
1340 output->otmMacDescent = lpOTMW->otmMacDescent;
1341 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1342 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1343 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1344 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1345 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1346 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1347 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1348 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1349 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1350 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1353 ptr = (char*)(output + 1);
1354 left = needed - sizeof(*output);
1356 if(lpOTMW->otmpFamilyName) {
1357 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1358 len = WideCharToMultiByte(CP_ACP, 0,
1359 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1360 ptr, left, NULL, NULL);
1364 output->otmpFamilyName = 0;
1366 if(lpOTMW->otmpFaceName) {
1367 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1368 len = WideCharToMultiByte(CP_ACP, 0,
1369 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1370 ptr, left, NULL, NULL);
1374 output->otmpFaceName = 0;
1376 if(lpOTMW->otmpStyleName) {
1377 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1378 len = WideCharToMultiByte(CP_ACP, 0,
1379 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1380 ptr, left, NULL, NULL);
1384 output->otmpStyleName = 0;
1386 if(lpOTMW->otmpFullName) {
1387 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1388 len = WideCharToMultiByte(CP_ACP, 0,
1389 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1390 ptr, left, NULL, NULL);
1393 output->otmpFullName = 0;
1397 if(output != lpOTM) {
1398 memcpy(lpOTM, output, cbData);
1399 HeapFree(GetProcessHeap(), 0, output);
1401 /* check if the string offsets really fit into the provided size */
1402 /* FIXME: should we check string length as well? */
1403 /* make sure that we don't read/write beyond the provided buffer */
1404 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1406 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1407 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1410 /* make sure that we don't read/write beyond the provided buffer */
1411 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1413 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1414 lpOTM->otmpFaceName = 0; /* doesn't fit */
1417 /* make sure that we don't read/write beyond the provided buffer */
1418 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1420 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1421 lpOTM->otmpStyleName = 0; /* doesn't fit */
1424 /* make sure that we don't read/write beyond the provided buffer */
1425 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1427 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1428 lpOTM->otmpFullName = 0; /* doesn't fit */
1433 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1434 HeapFree(GetProcessHeap(), 0, lpOTMW);
1440 /***********************************************************************
1441 * GetOutlineTextMetricsW [GDI32.@]
1443 UINT WINAPI GetOutlineTextMetricsW(
1444 HDC hdc, /* [in] Handle of device context */
1445 UINT cbData, /* [in] Size of metric data array */
1446 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1448 DC *dc = get_dc_ptr( hdc );
1449 OUTLINETEXTMETRICW *output = lpOTM;
1453 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1456 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1457 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1459 if (lpOTM && ret > cbData)
1461 output = HeapAlloc(GetProcessHeap(), 0, ret);
1462 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1467 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1468 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1470 #define WDPTOLP(x) ((x<0)? \
1471 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1472 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1473 #define HDPTOLP(y) ((y<0)? \
1474 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1475 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1477 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1478 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1479 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1480 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1481 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1482 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1483 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1484 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1485 output->otmAscent = HDPTOLP(output->otmAscent);
1486 output->otmDescent = HDPTOLP(output->otmDescent);
1487 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1488 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1489 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1490 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1491 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1492 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1493 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1494 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1495 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1496 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1497 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1498 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1499 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1500 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1501 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1502 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1503 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1504 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1505 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1506 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1507 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1508 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1513 memcpy(lpOTM, output, cbData);
1514 HeapFree(GetProcessHeap(), 0, output);
1522 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1524 INT i, count = lastChar - firstChar + 1;
1531 switch (GdiGetCodePage(hdc))
1538 if (lastChar > 0xffff)
1540 if ((firstChar ^ lastChar) > 0xff)
1544 if (lastChar > 0xff)
1549 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1553 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1556 str[i++] = (BYTE)(c >> 8);
1566 /***********************************************************************
1567 * GetCharWidthW (GDI32.@)
1568 * GetCharWidth32W (GDI32.@)
1570 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1576 DC * dc = get_dc_ptr( hdc );
1578 if (!dc) return FALSE;
1580 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1581 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1585 /* convert device units to logical */
1586 for( i = firstChar; i <= lastChar; i++, buffer++ )
1587 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1589 release_dc_ptr( dc );
1594 /***********************************************************************
1595 * GetCharWidthA (GDI32.@)
1596 * GetCharWidth32A (GDI32.@)
1598 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1606 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1610 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1612 for(i = 0; i < wlen; i++)
1614 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1622 HeapFree(GetProcessHeap(), 0, str);
1623 HeapFree(GetProcessHeap(), 0, wstr);
1629 /* helper for nulldrv_ExtTextOut */
1630 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1631 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1633 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1634 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1635 UINT indices[3] = {0, 0, 0x20};
1642 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); index = indices[++i])
1644 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1645 if (ret != GDI_ERROR) break;
1648 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1649 if (!image) return ERROR_SUCCESS;
1653 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1655 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1656 size = metrics->gmBlackBoxY * stride;
1658 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1659 image->is_copy = TRUE;
1660 image->free = free_heap_bits;
1662 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1663 if (ret == GDI_ERROR)
1665 HeapFree( GetProcessHeap(), 0, image->ptr );
1666 return ERROR_NOT_FOUND;
1668 return ERROR_SUCCESS;
1671 /* helper for nulldrv_ExtTextOut */
1672 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1673 const struct gdi_image_bits *image, const RECT *clip )
1675 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1676 UINT x, y, i, count;
1677 BYTE *ptr = image->ptr;
1678 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1680 RECT rect, clipped_rect;
1682 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1683 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1684 rect.right = rect.left + metrics->gmBlackBoxX;
1685 rect.bottom = rect.top + metrics->gmBlackBoxY;
1686 if (!clip) clipped_rect = rect;
1687 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1689 pts = HeapAlloc( GetProcessHeap(), 0,
1690 max(2,metrics->gmBlackBoxX) * metrics->gmBlackBoxY * sizeof(*pts) );
1694 ptr += (clipped_rect.top - rect.top) * stride;
1695 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1697 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1699 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1700 pts[count].x = rect.left + x;
1701 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1702 pts[count + 1].x = rect.left + x;
1703 if (pts[count + 1].x > pts[count].x)
1705 pts[count].y = pts[count + 1].y = y;
1710 DPtoLP( hdc, pts, count );
1711 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1712 HeapFree( GetProcessHeap(), 0, pts );
1715 /***********************************************************************
1716 * nulldrv_ExtTextOut
1718 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1719 LPCWSTR str, UINT count, const INT *dx )
1726 if (flags & ETO_OPAQUE)
1729 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1733 orig = SelectObject( dev->hdc, brush );
1734 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1735 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1736 SelectObject( dev->hdc, orig );
1737 DeleteObject( brush );
1741 if (!count) return TRUE;
1743 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
1744 orig = SelectObject( dev->hdc, pen );
1746 for (i = 0; i < count; i++)
1748 GLYPHMETRICS metrics;
1749 struct gdi_image_bits image;
1751 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
1754 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
1755 if (image.free) image.free( &image );
1759 if (flags & ETO_PDY)
1762 y += dx[ i * 2 + 1];
1768 x += metrics.gmCellIncX;
1769 y += metrics.gmCellIncY;
1773 SelectObject( dev->hdc, orig );
1774 DeleteObject( pen );
1779 /***********************************************************************
1780 * ExtTextOutA (GDI32.@)
1784 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1785 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1793 if (flags & ETO_GLYPH_INDEX)
1794 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1796 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1799 unsigned int i = 0, j = 0;
1801 /* allocate enough for a ETO_PDY */
1802 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1804 if(IsDBCSLeadByteEx(codepage, str[i]))
1808 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1809 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1812 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1819 lpDxW[j++] = lpDx[i * 2];
1820 lpDxW[j++] = lpDx[i * 2 + 1];
1823 lpDxW[j++] = lpDx[i];
1829 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1831 HeapFree( GetProcessHeap(), 0, p );
1832 HeapFree( GetProcessHeap(), 0, lpDxW );
1837 /***********************************************************************
1838 * ExtTextOutW (GDI32.@)
1840 * Draws text using the currently selected font, background color, and text color.
1844 * x,y [I] coordinates of string
1846 * ETO_GRAYED - undocumented on MSDN
1847 * ETO_OPAQUE - use background color for fill the rectangle
1848 * ETO_CLIPPED - clipping text to the rectangle
1849 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1850 * than encoded characters. Implies ETO_IGNORELANGUAGE
1851 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1852 * Affects BiDi ordering
1853 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1854 * ETO_PDY - unimplemented
1855 * ETO_NUMERICSLATIN - unimplemented always assumed -
1856 * do not translate numbers into locale representations
1857 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1858 * lprect [I] dimensions for clipping or/and opaquing
1859 * str [I] text string
1860 * count [I] number of symbols in string
1861 * lpDx [I] optional parameter with distance between drawing characters
1867 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1868 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1871 LPWSTR reordered_str = (LPWSTR)str;
1872 WORD *glyphs = NULL;
1873 UINT align = GetTextAlign( hdc );
1874 DWORD layout = GetLayout( hdc );
1878 double cosEsc, sinEsc;
1882 BOOL done_extents = FALSE;
1883 POINT *deltas = NULL, width = {0, 0};
1885 DC * dc = get_dc_ptr( hdc );
1888 static int quietfixme = 0;
1890 if (!dc) return FALSE;
1892 breakRem = dc->breakRem;
1894 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1896 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1901 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1902 type = GetObjectType(hdc);
1903 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1905 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1906 release_dc_ptr( dc );
1911 flags &= ~ETO_CLIPPED;
1913 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1914 if (layout & LAYOUT_RTL)
1916 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1917 align ^= TA_RTLREADING;
1920 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1923 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1925 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1926 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1927 reordered_str, count, NULL, &glyphs, &cGlyphs);
1929 flags |= ETO_IGNORELANGUAGE;
1932 flags |= ETO_GLYPH_INDEX;
1933 if (cGlyphs != count)
1937 else if(flags & ETO_GLYPH_INDEX)
1938 glyphs = reordered_str;
1940 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1941 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1942 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1944 if(align & TA_UPDATECP)
1946 GetCurrentPositionEx( hdc, &pt );
1951 GetTextMetricsW(hdc, &tm);
1952 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1954 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1955 lf.lfEscapement = 0;
1957 if(lf.lfEscapement != 0)
1959 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1960 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1968 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1972 if(flags & ETO_GLYPH_INDEX)
1973 GetTextExtentPointI(hdc, glyphs, count, &sz);
1975 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1977 done_extents = TRUE;
1980 rc.right = x + sz.cx;
1981 rc.bottom = y + sz.cy;
1988 LPtoDP(hdc, (POINT*)&rc, 2);
1990 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1991 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1994 if (flags & ETO_OPAQUE)
1995 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2005 LPtoDP(hdc, &pt, 1);
2009 char_extra = GetTextCharacterExtra(hdc);
2010 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2014 POINT total = {0, 0}, desired[2];
2016 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2017 for(i = 0; i < count; i++)
2023 deltas[i].x = lpDx[i * 2] + char_extra;
2024 deltas[i].y = -lpDx[i * 2 + 1];
2028 deltas[i].x = lpDx[i] + char_extra;
2035 if(flags & ETO_GLYPH_INDEX)
2036 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2038 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2040 deltas[i].x = tmpsz.cx;
2044 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2046 deltas[i].x = deltas[i].x + dc->breakExtra;
2053 total.x += deltas[i].x;
2054 total.y += deltas[i].y;
2056 desired[0].x = desired[0].y = 0;
2058 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2059 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2061 LPtoDP(hdc, desired, 2);
2062 desired[1].x -= desired[0].x;
2063 desired[1].y -= desired[0].y;
2064 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2066 deltas[i].x = desired[1].x - width.x;
2067 deltas[i].y = desired[1].y - width.y;
2077 if(flags & ETO_GLYPH_INDEX)
2078 GetTextExtentPointI(hdc, glyphs, count, &sz);
2080 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2081 done_extents = TRUE;
2083 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2087 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2088 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2089 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2092 if (align & TA_UPDATECP)
2096 DPtoLP(hdc, &pt, 1);
2097 MoveToEx(hdc, pt.x, pt.y, NULL);
2109 if (align & TA_UPDATECP)
2113 DPtoLP(hdc, &pt, 1);
2114 MoveToEx(hdc, pt.x, pt.y, NULL);
2119 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2122 y += tm.tmAscent * cosEsc;
2123 x += tm.tmAscent * sinEsc;
2127 y -= tm.tmDescent * cosEsc;
2128 x -= tm.tmDescent * sinEsc;
2135 if (GetBkMode(hdc) != TRANSPARENT)
2137 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2139 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2140 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2144 rc.right = x + width.x;
2145 rc.top = y - tm.tmAscent;
2146 rc.bottom = y + tm.tmDescent;
2148 if(flags & ETO_CLIPPED)
2150 rc.left = max(lprect->left, rc.left);
2151 rc.right = min(lprect->right, rc.right);
2152 rc.top = max(lprect->top, rc.top);
2153 rc.bottom = min(lprect->bottom, rc.bottom);
2155 if(rc.left < rc.right && rc.top < rc.bottom)
2156 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2161 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2163 HFONT orig_font = dc->hFont, cur_font;
2166 POINT *offsets = NULL;
2169 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2170 for(i = 0; i < count; i++)
2172 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2173 if(cur_font != dc->hFont)
2178 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2179 offsets[0].x = offsets[0].y = 0;
2184 for(j = 1; j < count; j++)
2186 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2187 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2193 for(j = 1; j < count; j++)
2195 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2196 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2202 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2203 y + offsets[i - span].y,
2204 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2205 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2208 SelectObject(hdc, cur_font);
2210 glyphs[span++] = glyph;
2214 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2215 y + (offsets ? offsets[count - span].y : 0),
2216 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2217 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2218 SelectObject(hdc, orig_font);
2219 HeapFree(GetProcessHeap(), 0, offsets);
2225 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2227 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2228 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2229 flags |= ETO_GLYPH_INDEX;
2231 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2232 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2236 HeapFree(GetProcessHeap(), 0, deltas);
2237 if(glyphs != reordered_str)
2238 HeapFree(GetProcessHeap(), 0, glyphs);
2239 if(reordered_str != str)
2240 HeapFree(GetProcessHeap(), 0, reordered_str);
2242 release_dc_ptr( dc );
2244 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2246 int underlinePos, strikeoutPos;
2247 int underlineWidth, strikeoutWidth;
2248 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2249 OUTLINETEXTMETRICW* otm = NULL;
2251 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2252 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2254 hbrush = SelectObject(hdc, hbrush);
2259 underlineWidth = tm.tmAscent / 20 + 1;
2260 strikeoutPos = tm.tmAscent / 2;
2261 strikeoutWidth = underlineWidth;
2265 otm = HeapAlloc(GetProcessHeap(), 0, size);
2266 GetOutlineTextMetricsW(hdc, size, otm);
2267 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2268 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2269 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2270 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2271 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2272 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2273 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2274 HeapFree(GetProcessHeap(), 0, otm);
2280 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2281 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2282 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2283 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2284 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2285 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2286 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2287 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2288 pts[4].x = pts[0].x;
2289 pts[4].y = pts[0].y;
2290 DPtoLP(hdc, pts, 5);
2291 Polygon(hdc, pts, 5);
2296 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2297 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2298 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2299 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2300 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2301 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2302 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2303 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2304 pts[4].x = pts[0].x;
2305 pts[4].y = pts[0].y;
2306 DPtoLP(hdc, pts, 5);
2307 Polygon(hdc, pts, 5);
2310 SelectObject(hdc, hpen);
2311 hbrush = SelectObject(hdc, hbrush);
2312 DeleteObject(hbrush);
2319 /***********************************************************************
2320 * TextOutA (GDI32.@)
2322 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2324 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2328 /***********************************************************************
2329 * TextOutW (GDI32.@)
2331 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2333 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2337 /***********************************************************************
2338 * PolyTextOutA (GDI32.@)
2342 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2344 for (; cStrings>0; cStrings--, pptxt++)
2345 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2352 /***********************************************************************
2353 * PolyTextOutW (GDI32.@)
2355 * Draw several Strings
2361 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2363 for (; cStrings>0; cStrings--, pptxt++)
2364 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2370 /***********************************************************************
2371 * SetMapperFlags (GDI32.@)
2373 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2375 DC *dc = get_dc_ptr( hdc );
2376 DWORD ret = GDI_ERROR;
2380 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2381 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2382 if (flags != GDI_ERROR)
2384 ret = dc->mapperFlags;
2385 dc->mapperFlags = flags;
2387 release_dc_ptr( dc );
2392 /***********************************************************************
2393 * GetAspectRatioFilterEx (GDI32.@)
2395 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2397 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2402 /***********************************************************************
2403 * GetCharABCWidthsA (GDI32.@)
2405 * See GetCharABCWidthsW.
2407 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2415 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2419 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2422 HeapFree(GetProcessHeap(), 0, str);
2426 for(i = 0; i < wlen; i++)
2428 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2436 HeapFree(GetProcessHeap(), 0, str);
2437 HeapFree(GetProcessHeap(), 0, wstr);
2443 /******************************************************************************
2444 * GetCharABCWidthsW [GDI32.@]
2446 * Retrieves widths of characters in range.
2449 * hdc [I] Handle of device context
2450 * firstChar [I] First character in range to query
2451 * lastChar [I] Last character in range to query
2452 * abc [O] Address of character-width structure
2455 * Only works with TrueType fonts
2461 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2464 DC *dc = get_dc_ptr(hdc);
2469 if (!dc) return FALSE;
2473 release_dc_ptr( dc );
2477 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2478 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2481 /* convert device units to logical */
2482 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2483 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2484 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2485 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2489 release_dc_ptr( dc );
2494 /******************************************************************************
2495 * GetCharABCWidthsI [GDI32.@]
2497 * Retrieves widths of characters in range.
2500 * hdc [I] Handle of device context
2501 * firstChar [I] First glyphs in range to query
2502 * count [I] Last glyphs in range to query
2503 * pgi [i] Array of glyphs to query
2504 * abc [O] Address of character-width structure
2507 * Only works with TrueType fonts
2513 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2514 LPWORD pgi, LPABC abc)
2516 DC *dc = get_dc_ptr(hdc);
2521 if (!dc) return FALSE;
2525 release_dc_ptr( dc );
2529 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2530 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2533 /* convert device units to logical */
2534 for( i = 0; i < count; i++, abc++ ) {
2535 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2536 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2537 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2541 release_dc_ptr( dc );
2546 /***********************************************************************
2547 * GetGlyphOutlineA (GDI32.@)
2549 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2550 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2551 LPVOID lpBuffer, const MAT2 *lpmat2 )
2553 if (!lpmat2) return GDI_ERROR;
2555 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2560 cp = GdiGetCodePage(hdc);
2561 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2563 mbchs[0] = (uChar & 0xff00) >> 8;
2564 mbchs[1] = (uChar & 0xff);
2567 mbchs[0] = (uChar & 0xff);
2570 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2573 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2577 /***********************************************************************
2578 * GetGlyphOutlineW (GDI32.@)
2580 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2581 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2582 LPVOID lpBuffer, const MAT2 *lpmat2 )
2588 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2589 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2591 if (!lpmat2) return GDI_ERROR;
2593 dc = get_dc_ptr(hdc);
2594 if(!dc) return GDI_ERROR;
2596 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2597 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2598 release_dc_ptr( dc );
2603 /***********************************************************************
2604 * CreateScalableFontResourceA (GDI32.@)
2606 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2607 LPCSTR lpszResourceFile,
2608 LPCSTR lpszFontFile,
2609 LPCSTR lpszCurrentPath )
2611 LPWSTR lpszResourceFileW = NULL;
2612 LPWSTR lpszFontFileW = NULL;
2613 LPWSTR lpszCurrentPathW = NULL;
2617 if (lpszResourceFile)
2619 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2620 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2621 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2626 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2627 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2628 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2631 if (lpszCurrentPath)
2633 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2634 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2635 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2638 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2639 lpszFontFileW, lpszCurrentPathW);
2641 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2642 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2643 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2648 /***********************************************************************
2649 * CreateScalableFontResourceW (GDI32.@)
2651 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2652 LPCWSTR lpszResourceFile,
2653 LPCWSTR lpszFontFile,
2654 LPCWSTR lpszCurrentPath )
2657 FIXME("(%d,%s,%s,%s): stub\n",
2658 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2659 debugstr_w(lpszCurrentPath) );
2661 /* fHidden=1 - only visible for the calling app, read-only, not
2662 * enumerated with EnumFonts/EnumFontFamilies
2663 * lpszCurrentPath can be NULL
2666 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2667 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2669 SetLastError(ERROR_FILE_EXISTS);
2672 return FALSE; /* create failed */
2675 /*************************************************************************
2676 * GetKerningPairsA (GDI32.@)
2678 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2679 LPKERNINGPAIR kern_pairA )
2683 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2684 KERNINGPAIR *kern_pairW;
2686 if (!cPairs && kern_pairA)
2688 SetLastError(ERROR_INVALID_PARAMETER);
2692 cp = GdiGetCodePage(hDC);
2694 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2695 * to fail on an invalid character for CP_SYMBOL.
2697 cpi.DefaultChar[0] = 0;
2698 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2700 FIXME("Can't find codepage %u info\n", cp);
2704 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2705 if (!total_kern_pairs) return 0;
2707 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2708 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2710 for (i = 0; i < total_kern_pairs; i++)
2714 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2717 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2720 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2725 if (kern_pairs_copied >= cPairs) break;
2727 kern_pairA->wFirst = (BYTE)first;
2728 kern_pairA->wSecond = (BYTE)second;
2729 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2732 kern_pairs_copied++;
2735 HeapFree(GetProcessHeap(), 0, kern_pairW);
2737 return kern_pairs_copied;
2740 /*************************************************************************
2741 * GetKerningPairsW (GDI32.@)
2743 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2744 LPKERNINGPAIR lpKerningPairs )
2750 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2752 if (!cPairs && lpKerningPairs)
2754 SetLastError(ERROR_INVALID_PARAMETER);
2758 dc = get_dc_ptr(hDC);
2761 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2762 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2763 release_dc_ptr( dc );
2767 /*************************************************************************
2768 * TranslateCharsetInfo [GDI32.@]
2770 * Fills a CHARSETINFO structure for a character set, code page, or
2771 * font. This allows making the correspondence between different labels
2772 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2773 * of the same encoding.
2775 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2776 * only one codepage should be set in *lpSrc.
2779 * TRUE on success, FALSE on failure.
2782 BOOL WINAPI TranslateCharsetInfo(
2783 LPDWORD lpSrc, /* [in]
2784 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2785 if flags == TCI_SRCCHARSET: a character set value
2786 if flags == TCI_SRCCODEPAGE: a code page value
2788 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2789 DWORD flags /* [in] determines interpretation of lpSrc */)
2793 case TCI_SRCFONTSIG:
2794 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2796 case TCI_SRCCODEPAGE:
2797 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2799 case TCI_SRCCHARSET:
2800 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2805 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2806 *lpCs = FONT_tci[index];
2810 /*************************************************************************
2811 * GetFontLanguageInfo (GDI32.@)
2813 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2815 FONTSIGNATURE fontsig;
2816 static const DWORD GCP_DBCS_MASK=0x003F0000,
2817 GCP_DIACRITIC_MASK=0x00000000,
2818 FLI_GLYPHS_MASK=0x00000000,
2819 GCP_GLYPHSHAPE_MASK=0x00000040,
2820 GCP_KASHIDA_MASK=0x00000000,
2821 GCP_LIGATE_MASK=0x00000000,
2822 GCP_USEKERNING_MASK=0x00000000,
2823 GCP_REORDER_MASK=0x00000060;
2827 GetTextCharsetInfo( hdc, &fontsig, 0 );
2828 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2830 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2833 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2834 result|=GCP_DIACRITIC;
2836 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2839 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2840 result|=GCP_GLYPHSHAPE;
2842 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2843 result|=GCP_KASHIDA;
2845 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2848 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2849 result|=GCP_USEKERNING;
2851 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2852 if( GetTextAlign( hdc) & TA_RTLREADING )
2853 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2854 result|=GCP_REORDER;
2860 /*************************************************************************
2861 * GetFontData [GDI32.@]
2863 * Retrieve data for TrueType font.
2867 * success: Number of bytes returned
2868 * failure: GDI_ERROR
2872 * Calls SetLastError()
2875 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2876 LPVOID buffer, DWORD length)
2878 DC *dc = get_dc_ptr(hdc);
2882 if(!dc) return GDI_ERROR;
2884 dev = GET_DC_PHYSDEV( dc, pGetFontData );
2885 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
2886 release_dc_ptr( dc );
2890 /*************************************************************************
2891 * GetGlyphIndicesA [GDI32.@]
2893 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2894 LPWORD pgi, DWORD flags)
2900 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2901 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2903 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2904 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2905 HeapFree(GetProcessHeap(), 0, lpstrW);
2910 /*************************************************************************
2911 * GetGlyphIndicesW [GDI32.@]
2913 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2914 LPWORD pgi, DWORD flags)
2916 DC *dc = get_dc_ptr(hdc);
2920 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2921 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2923 if(!dc) return GDI_ERROR;
2925 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
2926 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
2927 release_dc_ptr( dc );
2931 /*************************************************************************
2932 * GetCharacterPlacementA [GDI32.@]
2934 * See GetCharacterPlacementW.
2937 * the web browser control of ie4 calls this with dwFlags=0
2940 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2941 INT nMaxExtent, GCP_RESULTSA *lpResults,
2946 GCP_RESULTSW resultsW;
2950 TRACE("%s, %d, %d, 0x%08x\n",
2951 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2953 /* both structs are equal in size */
2954 memcpy(&resultsW, lpResults, sizeof(resultsW));
2956 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2957 if(lpResults->lpOutString)
2958 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2960 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2962 lpResults->nGlyphs = resultsW.nGlyphs;
2963 lpResults->nMaxFit = resultsW.nMaxFit;
2965 if(lpResults->lpOutString) {
2966 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2967 lpResults->lpOutString, uCount, NULL, NULL );
2970 HeapFree(GetProcessHeap(), 0, lpStringW);
2971 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2976 /*************************************************************************
2977 * GetCharacterPlacementW [GDI32.@]
2979 * Retrieve information about a string. This includes the width, reordering,
2980 * Glyphing and so on.
2984 * The width and height of the string if successful, 0 if failed.
2988 * All flags except GCP_REORDER are not yet implemented.
2989 * Reordering is not 100% compliant to the Windows BiDi method.
2990 * Caret positioning is not yet implemented for BiDi.
2991 * Classes are not yet implemented.
2995 GetCharacterPlacementW(
2996 HDC hdc, /* [in] Device context for which the rendering is to be done */
2997 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2998 INT uCount, /* [in] Number of WORDS in string. */
2999 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3000 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3001 DWORD dwFlags /* [in] Flags specifying how to process the string */
3008 TRACE("%s, %d, %d, 0x%08x\n",
3009 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3011 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3012 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3013 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3014 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3015 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3017 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3018 if(lpResults->lpClass) FIXME("classes not implemented\n");
3019 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3020 FIXME("Caret positions for complex scripts not implemented\n");
3022 nSet = (UINT)uCount;
3023 if(nSet > lpResults->nGlyphs)
3024 nSet = lpResults->nGlyphs;
3026 /* return number of initialized fields */
3027 lpResults->nGlyphs = nSet;
3029 if((dwFlags&GCP_REORDER)==0 )
3031 /* Treat the case where no special handling was requested in a fastpath way */
3032 /* copy will do if the GCP_REORDER flag is not set */
3033 if(lpResults->lpOutString)
3034 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3036 if(lpResults->lpOrder)
3038 for(i = 0; i < nSet; i++)
3039 lpResults->lpOrder[i] = i;
3043 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3044 nSet, lpResults->lpOrder, NULL, NULL );
3047 /* FIXME: Will use the placement chars */
3048 if (lpResults->lpDx)
3051 for (i = 0; i < nSet; i++)
3053 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3054 lpResults->lpDx[i]= c;
3058 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3062 lpResults->lpCaretPos[0] = 0;
3063 for (i = 1; i < nSet; i++)
3064 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3065 lpResults->lpCaretPos[i] = (pos += size.cx);
3068 if(lpResults->lpGlyphs)
3069 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3071 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3072 ret = MAKELONG(size.cx, size.cy);
3077 /*************************************************************************
3078 * GetCharABCWidthsFloatA [GDI32.@]
3080 * See GetCharABCWidthsFloatW.
3082 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3089 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3093 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3095 for (i = 0; i < wlen; i++)
3097 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3105 HeapFree( GetProcessHeap(), 0, str );
3106 HeapFree( GetProcessHeap(), 0, wstr );
3111 /*************************************************************************
3112 * GetCharABCWidthsFloatW [GDI32.@]
3114 * Retrieves widths of a range of characters.
3117 * hdc [I] Handle to device context.
3118 * first [I] First character in range to query.
3119 * last [I] Last character in range to query.
3120 * abcf [O] Array of LPABCFLOAT structures.
3126 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3132 DC *dc = get_dc_ptr( hdc );
3134 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3136 if (!dc) return FALSE;
3138 if (!abcf) goto done;
3139 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3141 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3142 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3145 /* convert device units to logical */
3146 for (i = first; i <= last; i++, abcf++)
3148 abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
3149 abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
3150 abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
3153 HeapFree( GetProcessHeap(), 0, abc );
3156 release_dc_ptr( dc );
3160 /*************************************************************************
3161 * GetCharWidthFloatA [GDI32.@]
3163 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3164 UINT iLastChar, PFLOAT pxBuffer)
3166 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3170 /*************************************************************************
3171 * GetCharWidthFloatW [GDI32.@]
3173 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3174 UINT iLastChar, PFLOAT pxBuffer)
3176 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3181 /***********************************************************************
3183 * Font Resource API *
3185 ***********************************************************************/
3187 /***********************************************************************
3188 * AddFontResourceA (GDI32.@)
3190 INT WINAPI AddFontResourceA( LPCSTR str )
3192 return AddFontResourceExA( str, 0, NULL);
3195 /***********************************************************************
3196 * AddFontResourceW (GDI32.@)
3198 INT WINAPI AddFontResourceW( LPCWSTR str )
3200 return AddFontResourceExW(str, 0, NULL);
3204 /***********************************************************************
3205 * AddFontResourceExA (GDI32.@)
3207 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3209 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3210 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3213 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3214 ret = AddFontResourceExW(strW, fl, pdv);
3215 HeapFree(GetProcessHeap(), 0, strW);
3219 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3221 HRSRC rsrc = FindResourceW(hModule, name, type);
3222 HGLOBAL hMem = LoadResource(hModule, rsrc);
3223 LPVOID *pMem = LockResource(hMem);
3224 int *num_total = (int *)lParam;
3227 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3228 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3230 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3234 *num_total += num_in_res;
3238 /***********************************************************************
3239 * AddFontResourceExW (GDI32.@)
3241 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3243 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3246 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3247 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3248 if (hModule != NULL)
3250 int num_resources = 0;
3251 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3253 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3254 wine_dbgstr_w(str));
3255 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3256 ret = num_resources;
3257 FreeLibrary(hModule);
3263 /***********************************************************************
3264 * RemoveFontResourceA (GDI32.@)
3266 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3268 return RemoveFontResourceExA(str, 0, 0);
3271 /***********************************************************************
3272 * RemoveFontResourceW (GDI32.@)
3274 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3276 return RemoveFontResourceExW(str, 0, 0);
3279 /***********************************************************************
3280 * AddFontMemResourceEx (GDI32.@)
3282 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3287 if (!pbFont || !cbFont || !pcFonts)
3289 SetLastError(ERROR_INVALID_PARAMETER);
3293 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3298 *pcFonts = num_fonts;
3302 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3303 RemoveFontMemResourceEx(ret);
3311 /***********************************************************************
3312 * RemoveFontMemResourceEx (GDI32.@)
3314 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3316 FIXME("(%p) stub\n", fh);
3320 /***********************************************************************
3321 * RemoveFontResourceExA (GDI32.@)
3323 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3325 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3326 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3329 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3330 ret = RemoveFontResourceExW(strW, fl, pdv);
3331 HeapFree(GetProcessHeap(), 0, strW);
3335 /***********************************************************************
3336 * RemoveFontResourceExW (GDI32.@)
3338 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3340 return WineEngRemoveFontResourceEx(str, fl, pdv);
3343 /***********************************************************************
3344 * GetTextCharset (GDI32.@)
3346 UINT WINAPI GetTextCharset(HDC hdc)
3348 /* MSDN docs say this is equivalent */
3349 return GetTextCharsetInfo(hdc, NULL, 0);
3352 /***********************************************************************
3353 * GetTextCharsetInfo (GDI32.@)
3355 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3357 UINT ret = DEFAULT_CHARSET;
3358 DC *dc = get_dc_ptr(hdc);
3363 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3364 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3365 release_dc_ptr( dc );
3368 if (ret == DEFAULT_CHARSET && fs)
3369 memset(fs, 0, sizeof(FONTSIGNATURE));
3373 /***********************************************************************
3374 * GdiGetCharDimensions (GDI32.@)
3376 * Gets the average width of the characters in the English alphabet.
3379 * hdc [I] Handle to the device context to measure on.
3380 * lptm [O] Pointer to memory to store the text metrics into.
3381 * height [O] On exit, the maximum height of characters in the English alphabet.
3384 * The average width of characters in the English alphabet.
3387 * This function is used by the dialog manager to get the size of a dialog
3388 * unit. It should also be used by other pieces of code that need to know
3389 * the size of a dialog unit in logical units without having access to the
3390 * window handle of the dialog.
3391 * Windows caches the font metrics from this function, but we don't and
3392 * there doesn't appear to be an immediate advantage to do so.
3395 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3397 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3400 static const WCHAR alphabet[] = {
3401 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3402 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3403 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3405 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3407 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3409 if (height) *height = sz.cy;
3410 return (sz.cx / 26 + 1) / 2;
3413 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3415 FIXME("(%d): stub\n", fEnableEUDC);
3419 /***********************************************************************
3420 * GetCharWidthI (GDI32.@)
3422 * Retrieve widths of characters.
3425 * hdc [I] Handle to a device context.
3426 * first [I] First glyph in range to query.
3427 * count [I] Number of glyph indices to query.
3428 * glyphs [I] Array of glyphs to query.
3429 * buffer [O] Buffer to receive character widths.
3432 * Only works with TrueType fonts.
3438 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3443 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3445 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3448 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3450 HeapFree(GetProcessHeap(), 0, abc);
3454 for (i = 0; i < count; i++)
3455 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3457 HeapFree(GetProcessHeap(), 0, abc);
3461 /***********************************************************************
3462 * GetFontUnicodeRanges (GDI32.@)
3464 * Retrieve a list of supported Unicode characters in a font.
3467 * hdc [I] Handle to a device context.
3468 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3471 * Success: Number of bytes written to the buffer pointed to by lpgs.
3475 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3479 DC *dc = get_dc_ptr(hdc);
3481 TRACE("(%p, %p)\n", hdc, lpgs);
3485 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3486 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3492 /*************************************************************
3493 * FontIsLinked (GDI32.@)
3495 BOOL WINAPI FontIsLinked(HDC hdc)
3497 DC *dc = get_dc_ptr(hdc);
3501 if (!dc) return FALSE;
3502 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3503 ret = dev->funcs->pFontIsLinked( dev );
3505 TRACE("returning %d\n", ret);
3509 /*************************************************************
3510 * GdiRealizationInfo (GDI32.@)
3512 * Returns a structure that contains some font information.
3514 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3516 DC *dc = get_dc_ptr(hdc);
3520 if (!dc) return FALSE;
3521 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3522 ret = dev->funcs->pGdiRealizationInfo( dev, info );