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 /***********************************************************************
262 * GdiGetCodePage (GDI32.@)
264 DWORD WINAPI GdiGetCodePage( HDC hdc )
267 DC *dc = get_dc_ptr( hdc );
271 cp = dc->font_code_page;
272 release_dc_ptr( dc );
277 /***********************************************************************
280 * Returns a Unicode translation of str using the charset of the
281 * currently selected font in hdc. If count is -1 then str is assumed
282 * to be '\0' terminated, otherwise it contains the number of bytes to
283 * convert. If plenW is non-NULL, on return it will point to the
284 * number of WCHARs that have been written. If pCP is non-NULL, on
285 * return it will point to the codepage used in the conversion. The
286 * caller should free the returned LPWSTR from the process heap
289 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
295 cp = GdiGetCodePage( hdc );
297 if(count == -1) count = strlen(str);
298 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
299 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
300 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
301 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
302 if(plenW) *plenW = lenW;
307 /***********************************************************************
308 * CreateFontIndirectExA (GDI32.@)
310 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
312 ENUMLOGFONTEXDVW enumexW;
314 if (!penumexA) return 0;
316 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
317 enumexW.elfDesignVector = penumexA->elfDesignVector;
318 return CreateFontIndirectExW( &enumexW );
321 /***********************************************************************
322 * CreateFontIndirectExW (GDI32.@)
324 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
330 if (!penumex) return 0;
332 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
333 penumex->elfEnumLogfontEx.elfStyle[0] ||
334 penumex->elfEnumLogfontEx.elfScript[0])
336 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
337 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
338 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
339 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
342 plf = &penumex->elfEnumLogfontEx.elfLogFont;
343 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
345 fontPtr->logfont = *plf;
347 if (plf->lfEscapement != plf->lfOrientation)
349 /* this should really depend on whether GM_ADVANCED is set */
350 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
351 WARN("orientation angle %f set to "
352 "escapement angle %f for new font %p\n",
353 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
356 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
358 HeapFree( GetProcessHeap(), 0, fontPtr );
362 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
363 plf->lfHeight, plf->lfWidth,
364 plf->lfEscapement, plf->lfOrientation,
365 plf->lfPitchAndFamily,
366 plf->lfOutPrecision, plf->lfClipPrecision,
367 plf->lfQuality, plf->lfCharSet,
368 debugstr_w(plf->lfFaceName),
369 plf->lfWeight > 400 ? "Bold" : "",
370 plf->lfItalic ? "Italic" : "",
371 plf->lfUnderline ? "Underline" : "", hFont);
376 /***********************************************************************
377 * CreateFontIndirectA (GDI32.@)
379 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
385 FONT_LogFontAToW( plfA, &lfW );
386 return CreateFontIndirectW( &lfW );
389 /***********************************************************************
390 * CreateFontIndirectW (GDI32.@)
392 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
394 ENUMLOGFONTEXDVW exdv;
398 exdv.elfEnumLogfontEx.elfLogFont = *plf;
399 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
400 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
401 exdv.elfEnumLogfontEx.elfScript[0] = 0;
402 return CreateFontIndirectExW( &exdv );
405 /*************************************************************************
406 * CreateFontA (GDI32.@)
408 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
409 INT orient, INT weight, DWORD italic,
410 DWORD underline, DWORD strikeout, DWORD charset,
411 DWORD outpres, DWORD clippres, DWORD quality,
412 DWORD pitch, LPCSTR name )
416 logfont.lfHeight = height;
417 logfont.lfWidth = width;
418 logfont.lfEscapement = esc;
419 logfont.lfOrientation = orient;
420 logfont.lfWeight = weight;
421 logfont.lfItalic = italic;
422 logfont.lfUnderline = underline;
423 logfont.lfStrikeOut = strikeout;
424 logfont.lfCharSet = charset;
425 logfont.lfOutPrecision = outpres;
426 logfont.lfClipPrecision = clippres;
427 logfont.lfQuality = quality;
428 logfont.lfPitchAndFamily = pitch;
431 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
433 logfont.lfFaceName[0] = '\0';
435 return CreateFontIndirectA( &logfont );
438 /*************************************************************************
439 * CreateFontW (GDI32.@)
441 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
442 INT orient, INT weight, DWORD italic,
443 DWORD underline, DWORD strikeout, DWORD charset,
444 DWORD outpres, DWORD clippres, DWORD quality,
445 DWORD pitch, LPCWSTR name )
449 logfont.lfHeight = height;
450 logfont.lfWidth = width;
451 logfont.lfEscapement = esc;
452 logfont.lfOrientation = orient;
453 logfont.lfWeight = weight;
454 logfont.lfItalic = italic;
455 logfont.lfUnderline = underline;
456 logfont.lfStrikeOut = strikeout;
457 logfont.lfCharSet = charset;
458 logfont.lfOutPrecision = outpres;
459 logfont.lfClipPrecision = clippres;
460 logfont.lfQuality = quality;
461 logfont.lfPitchAndFamily = pitch;
464 lstrcpynW(logfont.lfFaceName, name,
465 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
467 logfont.lfFaceName[0] = '\0';
469 return CreateFontIndirectW( &logfont );
472 static void update_font_code_page( DC *dc )
475 int charset = DEFAULT_CHARSET;
478 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
480 /* Hmm, nicely designed api this one! */
481 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
482 dc->font_code_page = csi.ciACP;
486 dc->font_code_page = GetOEMCP();
488 case DEFAULT_CHARSET:
489 dc->font_code_page = GetACP();
499 /* FIXME: These have no place here, but because x11drv
500 enumerates fonts with these (made up) charsets some apps
501 might use them and then the FIXME below would become
502 annoying. Now we could pick the intended codepage for
503 each of these, but since it's broken anyway we'll just
504 use CP_ACP and hope it'll go away...
506 dc->font_code_page = CP_ACP;
510 FIXME("Can't find codepage for charset %d\n", charset);
511 dc->font_code_page = CP_ACP;
516 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
519 /***********************************************************************
522 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
525 DC *dc = get_dc_ptr( hdc );
530 if (!GDI_inc_ref_count( handle ))
532 release_dc_ptr( dc );
536 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
537 if (physdev->funcs->pSelectFont( physdev, handle ))
541 update_font_code_page( dc );
542 GDI_dec_ref_count( ret );
544 else GDI_dec_ref_count( handle );
546 release_dc_ptr( dc );
551 /***********************************************************************
554 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
556 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
562 FONT_LogFontWToA( &font->logfont, &lfA );
563 if (count > sizeof(lfA)) count = sizeof(lfA);
564 memcpy( buffer, &lfA, count );
566 else count = sizeof(lfA);
567 GDI_ReleaseObj( handle );
571 /***********************************************************************
574 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
576 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
581 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
582 memcpy( buffer, &font->logfont, count );
584 else count = sizeof(LOGFONTW);
585 GDI_ReleaseObj( handle );
590 /***********************************************************************
593 static BOOL FONT_DeleteObject( HGDIOBJ handle )
597 WineEngDestroyFontInstance( handle );
599 if (!(obj = free_gdi_handle( handle ))) return FALSE;
600 return HeapFree( GetProcessHeap(), 0, obj );
604 /***********************************************************************
607 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
608 * We have to use other types because of the FONTENUMPROCW definition.
610 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
611 DWORD fType, LPARAM lp )
613 struct font_enum *pfe = (struct font_enum *)lp;
616 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
617 if ((!pfe->lpLogFontParam ||
618 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
619 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
620 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
622 /* convert font metrics */
623 ENUMLOGFONTEXA logfont;
624 NEWTEXTMETRICEXA tmA;
628 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
629 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
630 plf = (LOGFONTW *)&logfont.elfLogFont;
631 ptm = (TEXTMETRICW *)&tmA;
633 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
638 /***********************************************************************
639 * FONT_EnumFontFamiliesEx
641 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
642 LPARAM lParam, BOOL unicode )
645 DC *dc = get_dc_ptr( hDC );
650 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
652 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
653 fe.lpLogFontParam = plf;
654 fe.lpEnumFunc = efproc;
656 fe.unicode = unicode;
658 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
660 release_dc_ptr( dc );
664 /***********************************************************************
665 * EnumFontFamiliesExW (GDI32.@)
667 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
668 FONTENUMPROCW efproc,
669 LPARAM lParam, DWORD dwFlags )
671 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
674 /***********************************************************************
675 * EnumFontFamiliesExA (GDI32.@)
677 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
678 FONTENUMPROCA efproc,
679 LPARAM lParam, DWORD dwFlags)
685 FONT_LogFontAToW( plf, &lfW );
690 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
693 /***********************************************************************
694 * EnumFontFamiliesA (GDI32.@)
696 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
697 FONTENUMPROCA efproc, LPARAM lpData )
703 if (!*lpFamily) return 1;
704 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
705 lf.lfCharSet = DEFAULT_CHARSET;
706 lf.lfPitchAndFamily = 0;
711 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
714 /***********************************************************************
715 * EnumFontFamiliesW (GDI32.@)
717 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
718 FONTENUMPROCW efproc, LPARAM lpData )
724 if (!*lpFamily) return 1;
725 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
726 lf.lfCharSet = DEFAULT_CHARSET;
727 lf.lfPitchAndFamily = 0;
732 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
735 /***********************************************************************
736 * EnumFontsA (GDI32.@)
738 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
741 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
744 /***********************************************************************
745 * EnumFontsW (GDI32.@)
747 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
750 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
754 /***********************************************************************
755 * GetTextCharacterExtra (GDI32.@)
757 INT WINAPI GetTextCharacterExtra( HDC hdc )
760 DC *dc = get_dc_ptr( hdc );
761 if (!dc) return 0x80000000;
763 release_dc_ptr( dc );
768 /***********************************************************************
769 * SetTextCharacterExtra (GDI32.@)
771 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
773 INT ret = 0x80000000;
774 DC * dc = get_dc_ptr( hdc );
778 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
779 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
780 if (extra != 0x80000000)
783 dc->charExtra = extra;
785 release_dc_ptr( dc );
791 /***********************************************************************
792 * SetTextJustification (GDI32.@)
794 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
798 DC * dc = get_dc_ptr( hdc );
800 if (!dc) return FALSE;
802 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
803 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
806 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
807 if (!extra) breaks = 0;
810 dc->breakExtra = extra / breaks;
811 dc->breakRem = extra - (breaks * dc->breakExtra);
819 release_dc_ptr( dc );
824 /***********************************************************************
825 * GetTextFaceA (GDI32.@)
827 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
829 INT res = GetTextFaceW(hdc, 0, NULL);
830 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
831 GetTextFaceW( hdc, res, nameW );
837 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
841 /* GetTextFaceA does NOT include the nul byte in the return count. */
848 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
849 HeapFree( GetProcessHeap(), 0, nameW );
853 /***********************************************************************
854 * GetTextFaceW (GDI32.@)
856 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
861 DC * dc = get_dc_ptr( hdc );
865 ret = WineEngGetTextFace(dc->gdiFont, count, name);
866 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
868 INT n = strlenW(font->logfont.lfFaceName) + 1;
871 lstrcpynW( name, font->logfont.lfFaceName, count );
875 GDI_ReleaseObj( dc->hFont );
877 release_dc_ptr( dc );
882 /***********************************************************************
883 * GetTextExtentPoint32A (GDI32.@)
885 * See GetTextExtentPoint32W.
887 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
894 if (count < 0) return FALSE;
896 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
900 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
901 HeapFree( GetProcessHeap(), 0, p );
904 TRACE("(%p %s %d %p): returning %d x %d\n",
905 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
910 /***********************************************************************
911 * GetTextExtentPoint32W [GDI32.@]
913 * Computes width/height for a string.
915 * Computes width and height of the specified string.
921 BOOL WINAPI GetTextExtentPoint32W(
922 HDC hdc, /* [in] Handle of device context */
923 LPCWSTR str, /* [in] Address of text string */
924 INT count, /* [in] Number of characters in string */
925 LPSIZE size) /* [out] Address of structure for string size */
927 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
930 /***********************************************************************
931 * GetTextExtentExPointI [GDI32.@]
933 * Computes width and height of the array of glyph indices.
936 * hdc [I] Handle of device context.
937 * indices [I] Glyph index array.
938 * count [I] Number of glyphs in array.
939 * max_ext [I] Maximum width in glyphs.
940 * nfit [O] Maximum number of characters.
941 * dxs [O] Partial string widths.
942 * size [O] Returned string size.
948 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
949 LPINT nfit, LPINT dxs, LPSIZE size )
954 if (count < 0) return FALSE;
956 dc = get_dc_ptr( hdc );
957 if (!dc) return FALSE;
961 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
962 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
963 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
964 size->cx += count * dc->charExtra;
968 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
969 FIXME("calling GetTextExtentExPoint\n");
970 ret = physdev->funcs->pGetTextExtentExPoint( physdev, indices, count, max_ext, nfit, dxs, size );
973 release_dc_ptr( dc );
975 TRACE("(%p %p %d %p): returning %d x %d\n",
976 hdc, indices, count, size, size->cx, size->cy );
980 /***********************************************************************
981 * GetTextExtentPointI [GDI32.@]
983 * Computes width and height of the array of glyph indices.
986 * hdc [I] Handle of device context.
987 * indices [I] Glyph index array.
988 * count [I] Number of glyphs in array.
989 * size [O] Returned string size.
995 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
997 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1001 /***********************************************************************
1002 * GetTextExtentPointA (GDI32.@)
1004 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1007 TRACE("not bug compatible.\n");
1008 return GetTextExtentPoint32A( hdc, str, count, size );
1011 /***********************************************************************
1012 * GetTextExtentPointW (GDI32.@)
1014 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1017 TRACE("not bug compatible.\n");
1018 return GetTextExtentPoint32W( hdc, str, count, size );
1022 /***********************************************************************
1023 * GetTextExtentExPointA (GDI32.@)
1025 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1026 INT maxExt, LPINT lpnFit,
1027 LPINT alpDx, LPSIZE size )
1034 if (count < 0) return FALSE;
1038 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1039 if (!walpDx) return FALSE;
1042 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1043 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1046 INT n = lpnFit ? *lpnFit : wlen;
1048 for(i = 0, j = 0; i < n; i++, j++)
1050 alpDx[j] = walpDx[i];
1051 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1054 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1055 HeapFree( GetProcessHeap(), 0, p );
1056 HeapFree( GetProcessHeap(), 0, walpDx );
1061 /***********************************************************************
1062 * GetTextExtentExPointW (GDI32.@)
1064 * Return the size of the string as it would be if it was output properly by
1067 * This should include
1068 * - Intercharacter spacing
1069 * - justification spacing (not yet done)
1070 * - kerning? see below
1072 * Kerning. Since kerning would be carried out by the rendering code it should
1073 * be done by the driver. However they don't support it yet. Also I am not
1074 * yet persuaded that (certainly under Win95) any kerning is actually done.
1076 * str: According to MSDN this should be null-terminated. That is not true; a
1077 * null will not terminate it early.
1078 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1079 * than count. I have seen it be either the size of the full string or
1080 * 1 less than the size of the full string. I have not seen it bear any
1081 * resemblance to the portion that would fit.
1082 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1083 * trailing intercharacter spacing and any trailing justification.
1086 * Currently we do this by measuring each character etc. We should do it by
1087 * passing the request to the driver, perhaps by extending the
1088 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1089 * thinking about kerning issues and rounding issues in the justification.
1092 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1093 INT maxExt, LPINT lpnFit,
1094 LPINT alpDx, LPSIZE size )
1103 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1105 if (count < 0) return FALSE;
1107 dc = get_dc_ptr(hdc);
1108 if (!dc) return FALSE;
1110 GetTextMetricsW(hdc, &tm);
1112 /* If we need to calculate nFit, then we need the partial extents even if
1113 the user hasn't provided us with an array. */
1116 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1120 SetLastError(ERROR_OUTOFMEMORY);
1127 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1128 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1130 /* Perform device size to world size transformations. */
1133 INT extra = dc->charExtra,
1134 breakExtra = dc->breakExtra,
1135 breakRem = dc->breakRem,
1140 for (i = 0; i < count; ++i)
1142 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1143 dxs[i] += (i+1) * extra;
1144 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1146 dxs[i] += breakExtra;
1153 if (dxs[i] <= maxExt)
1156 breakRem = dc->breakRem;
1158 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1159 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1161 if (!dxs && count > 1 && (breakExtra || breakRem))
1163 for (i = 0; i < count; i++)
1165 if (str[i] == tm.tmBreakChar)
1167 size->cx += breakExtra;
1182 HeapFree(GetProcessHeap(), 0, dxs);
1184 release_dc_ptr( dc );
1186 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1190 /***********************************************************************
1191 * GetTextMetricsA (GDI32.@)
1193 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1197 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1198 FONT_TextMetricWToA( &tm32, metrics );
1202 /***********************************************************************
1203 * GetTextMetricsW (GDI32.@)
1205 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1209 DC * dc = get_dc_ptr( hdc );
1210 if (!dc) return FALSE;
1212 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1213 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1217 /* device layer returns values in device units
1218 * therefore we have to convert them to logical */
1220 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1221 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1223 #define WDPTOLP(x) ((x<0)? \
1224 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1225 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1226 #define HDPTOLP(y) ((y<0)? \
1227 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1228 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1230 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1231 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1232 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1233 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1234 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1235 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1236 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1237 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1241 TRACE("text metrics:\n"
1242 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1243 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1244 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1245 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1246 " PitchAndFamily = %02x\n"
1247 " --------------------\n"
1248 " InternalLeading = %i\n"
1252 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1253 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1254 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1255 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1256 metrics->tmPitchAndFamily,
1257 metrics->tmInternalLeading,
1260 metrics->tmHeight );
1262 release_dc_ptr( dc );
1267 /***********************************************************************
1268 * GetOutlineTextMetricsA (GDI32.@)
1269 * Gets metrics for TrueType fonts.
1272 * If the supplied buffer isn't big enough Windows partially fills it up to
1273 * its given length and returns that length.
1276 * Success: Non-zero or size of required buffer
1279 UINT WINAPI GetOutlineTextMetricsA(
1280 HDC hdc, /* [in] Handle of device context */
1281 UINT cbData, /* [in] Size of metric data array */
1282 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1284 char buf[512], *ptr;
1286 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1287 OUTLINETEXTMETRICA *output = lpOTM;
1290 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1292 if(ret > sizeof(buf))
1293 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1294 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1296 needed = sizeof(OUTLINETEXTMETRICA);
1297 if(lpOTMW->otmpFamilyName)
1298 needed += WideCharToMultiByte(CP_ACP, 0,
1299 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1300 NULL, 0, NULL, NULL);
1301 if(lpOTMW->otmpFaceName)
1302 needed += WideCharToMultiByte(CP_ACP, 0,
1303 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1304 NULL, 0, NULL, NULL);
1305 if(lpOTMW->otmpStyleName)
1306 needed += WideCharToMultiByte(CP_ACP, 0,
1307 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1308 NULL, 0, NULL, NULL);
1309 if(lpOTMW->otmpFullName)
1310 needed += WideCharToMultiByte(CP_ACP, 0,
1311 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1312 NULL, 0, NULL, NULL);
1319 TRACE("needed = %d\n", needed);
1321 /* Since the supplied buffer isn't big enough, we'll alloc one
1322 that is and memcpy the first cbData bytes into the lpOTM at
1324 output = HeapAlloc(GetProcessHeap(), 0, needed);
1326 ret = output->otmSize = min(needed, cbData);
1327 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1328 output->otmFiller = 0;
1329 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1330 output->otmfsSelection = lpOTMW->otmfsSelection;
1331 output->otmfsType = lpOTMW->otmfsType;
1332 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1333 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1334 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1335 output->otmEMSquare = lpOTMW->otmEMSquare;
1336 output->otmAscent = lpOTMW->otmAscent;
1337 output->otmDescent = lpOTMW->otmDescent;
1338 output->otmLineGap = lpOTMW->otmLineGap;
1339 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1340 output->otmsXHeight = lpOTMW->otmsXHeight;
1341 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1342 output->otmMacAscent = lpOTMW->otmMacAscent;
1343 output->otmMacDescent = lpOTMW->otmMacDescent;
1344 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1345 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1346 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1347 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1348 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1349 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1350 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1351 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1352 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1353 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1356 ptr = (char*)(output + 1);
1357 left = needed - sizeof(*output);
1359 if(lpOTMW->otmpFamilyName) {
1360 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1361 len = WideCharToMultiByte(CP_ACP, 0,
1362 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1363 ptr, left, NULL, NULL);
1367 output->otmpFamilyName = 0;
1369 if(lpOTMW->otmpFaceName) {
1370 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1371 len = WideCharToMultiByte(CP_ACP, 0,
1372 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1373 ptr, left, NULL, NULL);
1377 output->otmpFaceName = 0;
1379 if(lpOTMW->otmpStyleName) {
1380 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1381 len = WideCharToMultiByte(CP_ACP, 0,
1382 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1383 ptr, left, NULL, NULL);
1387 output->otmpStyleName = 0;
1389 if(lpOTMW->otmpFullName) {
1390 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1391 len = WideCharToMultiByte(CP_ACP, 0,
1392 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1393 ptr, left, NULL, NULL);
1396 output->otmpFullName = 0;
1400 if(output != lpOTM) {
1401 memcpy(lpOTM, output, cbData);
1402 HeapFree(GetProcessHeap(), 0, output);
1404 /* check if the string offsets really fit into the provided size */
1405 /* FIXME: should we check string length as well? */
1406 /* make sure that we don't read/write beyond the provided buffer */
1407 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1409 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1410 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1413 /* make sure that we don't read/write beyond the provided buffer */
1414 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1416 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1417 lpOTM->otmpFaceName = 0; /* doesn't fit */
1420 /* make sure that we don't read/write beyond the provided buffer */
1421 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1423 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1424 lpOTM->otmpStyleName = 0; /* doesn't fit */
1427 /* make sure that we don't read/write beyond the provided buffer */
1428 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1430 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1431 lpOTM->otmpFullName = 0; /* doesn't fit */
1436 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1437 HeapFree(GetProcessHeap(), 0, lpOTMW);
1443 /***********************************************************************
1444 * GetOutlineTextMetricsW [GDI32.@]
1446 UINT WINAPI GetOutlineTextMetricsW(
1447 HDC hdc, /* [in] Handle of device context */
1448 UINT cbData, /* [in] Size of metric data array */
1449 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1451 DC *dc = get_dc_ptr( hdc );
1452 OUTLINETEXTMETRICW *output = lpOTM;
1455 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1459 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1462 output = HeapAlloc(GetProcessHeap(), 0, ret);
1463 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1466 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1467 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1469 #define WDPTOLP(x) ((x<0)? \
1470 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1471 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1472 #define HDPTOLP(y) ((y<0)? \
1473 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1474 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1476 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1477 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1478 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1479 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1480 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1481 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1482 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1483 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1484 output->otmAscent = HDPTOLP(output->otmAscent);
1485 output->otmDescent = HDPTOLP(output->otmDescent);
1486 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1487 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1488 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1489 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1490 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1491 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1492 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1493 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1494 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1495 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1496 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1497 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1498 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1499 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1500 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1501 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1502 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1503 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1504 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1505 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1506 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1507 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1510 if(output != lpOTM) {
1511 memcpy(lpOTM, output, cbData);
1512 HeapFree(GetProcessHeap(), 0, output);
1518 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1519 but really this should just be a return 0. */
1521 ret = sizeof(*lpOTM);
1526 memset(lpOTM, 0, ret);
1527 lpOTM->otmSize = sizeof(*lpOTM);
1528 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1530 Further fill of the structure not implemented,
1531 Needs real values for the structure members
1540 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1542 INT i, count = lastChar - firstChar + 1;
1549 switch (GdiGetCodePage(hdc))
1556 if (lastChar > 0xffff)
1558 if ((firstChar ^ lastChar) > 0xff)
1562 if (lastChar > 0xff)
1567 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1571 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1574 str[i++] = (BYTE)(c >> 8);
1584 /***********************************************************************
1585 * GetCharWidthW (GDI32.@)
1586 * GetCharWidth32W (GDI32.@)
1588 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1594 DC * dc = get_dc_ptr( hdc );
1596 if (!dc) return FALSE;
1598 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1599 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1603 /* convert device units to logical */
1604 for( i = firstChar; i <= lastChar; i++, buffer++ )
1605 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1607 release_dc_ptr( dc );
1612 /***********************************************************************
1613 * GetCharWidthA (GDI32.@)
1614 * GetCharWidth32A (GDI32.@)
1616 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1624 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1628 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1630 for(i = 0; i < wlen; i++)
1632 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1640 HeapFree(GetProcessHeap(), 0, str);
1641 HeapFree(GetProcessHeap(), 0, wstr);
1647 /***********************************************************************
1648 * ExtTextOutA (GDI32.@)
1652 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1653 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1661 if (flags & ETO_GLYPH_INDEX)
1662 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1664 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1667 unsigned int i = 0, j = 0;
1669 /* allocate enough for a ETO_PDY */
1670 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1672 if(IsDBCSLeadByteEx(codepage, str[i]))
1676 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1677 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1680 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1687 lpDxW[j++] = lpDx[i * 2];
1688 lpDxW[j++] = lpDx[i * 2 + 1];
1691 lpDxW[j++] = lpDx[i];
1697 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1699 HeapFree( GetProcessHeap(), 0, p );
1700 HeapFree( GetProcessHeap(), 0, lpDxW );
1705 /***********************************************************************
1706 * ExtTextOutW (GDI32.@)
1708 * Draws text using the currently selected font, background color, and text color.
1712 * x,y [I] coordinates of string
1714 * ETO_GRAYED - undocumented on MSDN
1715 * ETO_OPAQUE - use background color for fill the rectangle
1716 * ETO_CLIPPED - clipping text to the rectangle
1717 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1718 * than encoded characters. Implies ETO_IGNORELANGUAGE
1719 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1720 * Affects BiDi ordering
1721 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1722 * ETO_PDY - unimplemented
1723 * ETO_NUMERICSLATIN - unimplemented always assumed -
1724 * do not translate numbers into locale representations
1725 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1726 * lprect [I] dimensions for clipping or/and opaquing
1727 * str [I] text string
1728 * count [I] number of symbols in string
1729 * lpDx [I] optional parameter with distance between drawing characters
1735 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1736 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1739 LPWSTR reordered_str = (LPWSTR)str;
1740 WORD *glyphs = NULL;
1741 UINT align = GetTextAlign( hdc );
1742 DWORD layout = GetLayout( hdc );
1746 double cosEsc, sinEsc;
1750 BOOL done_extents = FALSE;
1751 POINT *deltas = NULL, width = {0, 0};
1753 DC * dc = get_dc_ptr( hdc );
1756 static int quietfixme = 0;
1758 if (!dc) return FALSE;
1760 breakRem = dc->breakRem;
1762 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1764 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1769 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1770 type = GetObjectType(hdc);
1771 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1773 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1774 release_dc_ptr( dc );
1779 flags &= ~ETO_CLIPPED;
1781 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1782 if (layout & LAYOUT_RTL)
1784 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1785 align ^= TA_RTLREADING;
1788 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1791 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1793 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1794 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1795 reordered_str, count, NULL, &glyphs, &cGlyphs);
1797 flags |= ETO_IGNORELANGUAGE;
1800 flags |= ETO_GLYPH_INDEX;
1801 if (cGlyphs != count)
1805 else if(flags & ETO_GLYPH_INDEX)
1806 glyphs = reordered_str;
1808 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1809 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1810 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1812 if(align & TA_UPDATECP)
1814 GetCurrentPositionEx( hdc, &pt );
1819 GetTextMetricsW(hdc, &tm);
1820 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1822 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1823 lf.lfEscapement = 0;
1825 if(lf.lfEscapement != 0)
1827 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1828 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1836 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1840 if(flags & ETO_GLYPH_INDEX)
1841 GetTextExtentPointI(hdc, glyphs, count, &sz);
1843 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1845 done_extents = TRUE;
1848 rc.right = x + sz.cx;
1849 rc.bottom = y + sz.cy;
1856 LPtoDP(hdc, (POINT*)&rc, 2);
1858 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1859 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1862 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1863 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1873 LPtoDP(hdc, &pt, 1);
1877 char_extra = GetTextCharacterExtra(hdc);
1878 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1882 POINT total = {0, 0}, desired[2];
1884 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1885 for(i = 0; i < count; i++)
1891 deltas[i].x = lpDx[i * 2] + char_extra;
1892 deltas[i].y = -lpDx[i * 2 + 1];
1896 deltas[i].x = lpDx[i] + char_extra;
1903 if(flags & ETO_GLYPH_INDEX)
1904 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1906 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1908 deltas[i].x = tmpsz.cx;
1912 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1914 deltas[i].x = deltas[i].x + dc->breakExtra;
1921 total.x += deltas[i].x;
1922 total.y += deltas[i].y;
1924 desired[0].x = desired[0].y = 0;
1926 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1927 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1929 LPtoDP(hdc, desired, 2);
1930 desired[1].x -= desired[0].x;
1931 desired[1].y -= desired[0].y;
1932 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1934 deltas[i].x = desired[1].x - width.x;
1935 deltas[i].y = desired[1].y - width.y;
1945 if(flags & ETO_GLYPH_INDEX)
1946 GetTextExtentPointI(hdc, glyphs, count, &sz);
1948 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1949 done_extents = TRUE;
1951 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1955 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1956 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1957 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1960 if (align & TA_UPDATECP)
1964 DPtoLP(hdc, &pt, 1);
1965 MoveToEx(hdc, pt.x, pt.y, NULL);
1977 if (align & TA_UPDATECP)
1981 DPtoLP(hdc, &pt, 1);
1982 MoveToEx(hdc, pt.x, pt.y, NULL);
1987 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1990 y += tm.tmAscent * cosEsc;
1991 x += tm.tmAscent * sinEsc;
1995 y -= tm.tmDescent * cosEsc;
1996 x -= tm.tmDescent * sinEsc;
2003 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2005 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2007 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2008 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2012 rc.right = x + width.x;
2013 rc.top = y - tm.tmAscent;
2014 rc.bottom = y + tm.tmDescent;
2016 if(flags & ETO_CLIPPED)
2018 rc.left = max(lprect->left, rc.left);
2019 rc.right = min(lprect->right, rc.right);
2020 rc.top = max(lprect->top, rc.top);
2021 rc.bottom = min(lprect->bottom, rc.bottom);
2023 if(rc.left < rc.right && rc.top < rc.bottom)
2024 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2029 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2031 HFONT orig_font = dc->hFont, cur_font;
2034 POINT *offsets = NULL;
2037 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2038 for(i = 0; i < count; i++)
2040 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2041 if(cur_font != dc->hFont)
2046 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2047 offsets[0].x = offsets[0].y = 0;
2052 for(j = 1; j < count; j++)
2054 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2055 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2061 for(j = 1; j < count; j++)
2063 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2064 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2070 if (PATH_IsPathOpen(dc->path))
2071 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2072 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2073 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2075 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2076 y + offsets[i - span].y,
2077 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2078 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2081 SelectObject(hdc, cur_font);
2083 glyphs[span++] = glyph;
2087 if (PATH_IsPathOpen(dc->path))
2088 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2089 y + (offsets ? offsets[count - span].y : 0),
2090 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2091 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2093 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2094 y + (offsets ? offsets[count - span].y : 0),
2095 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2096 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2097 SelectObject(hdc, orig_font);
2098 HeapFree(GetProcessHeap(), 0, offsets);
2104 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2106 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2107 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2108 flags |= ETO_GLYPH_INDEX;
2111 if (PATH_IsPathOpen(dc->path))
2112 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2113 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2115 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2116 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2120 HeapFree(GetProcessHeap(), 0, deltas);
2121 if(glyphs != reordered_str)
2122 HeapFree(GetProcessHeap(), 0, glyphs);
2123 if(reordered_str != str)
2124 HeapFree(GetProcessHeap(), 0, reordered_str);
2126 release_dc_ptr( dc );
2128 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2130 int underlinePos, strikeoutPos;
2131 int underlineWidth, strikeoutWidth;
2132 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2133 OUTLINETEXTMETRICW* otm = NULL;
2138 underlineWidth = tm.tmAscent / 20 + 1;
2139 strikeoutPos = tm.tmAscent / 2;
2140 strikeoutWidth = underlineWidth;
2144 otm = HeapAlloc(GetProcessHeap(), 0, size);
2145 GetOutlineTextMetricsW(hdc, size, otm);
2146 underlinePos = otm->otmsUnderscorePosition;
2147 underlineWidth = otm->otmsUnderscoreSize;
2148 strikeoutPos = otm->otmsStrikeoutPosition;
2149 strikeoutWidth = otm->otmsStrikeoutSize;
2150 HeapFree(GetProcessHeap(), 0, otm);
2153 if (PATH_IsPathOpen(dc->path))
2157 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2159 hbrush = SelectObject(hdc, hbrush);
2160 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2164 pts[0].x = x - underlinePos * sinEsc;
2165 pts[0].y = y - underlinePos * cosEsc;
2166 pts[1].x = x + width.x - underlinePos * sinEsc;
2167 pts[1].y = y + width.y - underlinePos * cosEsc;
2168 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2169 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2170 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2171 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2172 pts[4].x = pts[0].x;
2173 pts[4].y = pts[0].y;
2174 DPtoLP(hdc, pts, 5);
2175 Polygon(hdc, pts, 5);
2180 pts[0].x = x - strikeoutPos * sinEsc;
2181 pts[0].y = y - strikeoutPos * cosEsc;
2182 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2183 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2184 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2185 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2186 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2187 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2188 pts[4].x = pts[0].x;
2189 pts[4].y = pts[0].y;
2190 DPtoLP(hdc, pts, 5);
2191 Polygon(hdc, pts, 5);
2194 SelectObject(hdc, hpen);
2195 hbrush = SelectObject(hdc, hbrush);
2196 DeleteObject(hbrush);
2200 POINT pts[2], oldpt;
2205 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2206 hpen = SelectObject(hdc, hpen);
2209 pts[1].x = x + width.x;
2210 pts[1].y = y + width.y;
2211 DPtoLP(hdc, pts, 2);
2212 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2213 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2214 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2215 DeleteObject(SelectObject(hdc, hpen));
2220 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2221 hpen = SelectObject(hdc, hpen);
2224 pts[1].x = x + width.x;
2225 pts[1].y = y + width.y;
2226 DPtoLP(hdc, pts, 2);
2227 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2228 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2229 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2230 DeleteObject(SelectObject(hdc, hpen));
2239 /***********************************************************************
2240 * TextOutA (GDI32.@)
2242 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2244 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2248 /***********************************************************************
2249 * TextOutW (GDI32.@)
2251 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2253 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2257 /***********************************************************************
2258 * PolyTextOutA (GDI32.@)
2262 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2264 for (; cStrings>0; cStrings--, pptxt++)
2265 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2272 /***********************************************************************
2273 * PolyTextOutW (GDI32.@)
2275 * Draw several Strings
2281 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2283 for (; cStrings>0; cStrings--, pptxt++)
2284 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2290 /***********************************************************************
2291 * SetMapperFlags (GDI32.@)
2293 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2295 DC *dc = get_dc_ptr( hdc );
2296 DWORD ret = GDI_ERROR;
2300 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2301 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2302 if (flags != GDI_ERROR)
2304 ret = dc->mapperFlags;
2305 dc->mapperFlags = flags;
2307 release_dc_ptr( dc );
2312 /***********************************************************************
2313 * GetAspectRatioFilterEx (GDI32.@)
2315 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2317 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2322 /***********************************************************************
2323 * GetCharABCWidthsA (GDI32.@)
2325 * See GetCharABCWidthsW.
2327 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2335 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2339 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2342 HeapFree(GetProcessHeap(), 0, str);
2346 for(i = 0; i < wlen; i++)
2348 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2356 HeapFree(GetProcessHeap(), 0, str);
2357 HeapFree(GetProcessHeap(), 0, wstr);
2363 /******************************************************************************
2364 * GetCharABCWidthsW [GDI32.@]
2366 * Retrieves widths of characters in range.
2369 * hdc [I] Handle of device context
2370 * firstChar [I] First character in range to query
2371 * lastChar [I] Last character in range to query
2372 * abc [O] Address of character-width structure
2375 * Only works with TrueType fonts
2381 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2384 DC *dc = get_dc_ptr(hdc);
2389 if (!dc) return FALSE;
2393 release_dc_ptr( dc );
2397 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2398 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2401 /* convert device units to logical */
2402 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2403 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2404 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2405 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2409 release_dc_ptr( dc );
2414 /******************************************************************************
2415 * GetCharABCWidthsI [GDI32.@]
2417 * Retrieves widths of characters in range.
2420 * hdc [I] Handle of device context
2421 * firstChar [I] First glyphs in range to query
2422 * count [I] Last glyphs in range to query
2423 * pgi [i] Array of glyphs to query
2424 * abc [O] Address of character-width structure
2427 * Only works with TrueType fonts
2433 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2434 LPWORD pgi, LPABC abc)
2436 DC *dc = get_dc_ptr(hdc);
2441 if (!dc) return FALSE;
2445 release_dc_ptr( dc );
2449 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2450 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2453 /* convert device units to logical */
2454 for( i = 0; i < count; i++, abc++ ) {
2455 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2456 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2457 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2461 release_dc_ptr( dc );
2466 /***********************************************************************
2467 * GetGlyphOutlineA (GDI32.@)
2469 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2470 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2471 LPVOID lpBuffer, const MAT2 *lpmat2 )
2473 if (!lpmat2) return GDI_ERROR;
2475 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2480 cp = GdiGetCodePage(hdc);
2481 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2483 mbchs[0] = (uChar & 0xff00) >> 8;
2484 mbchs[1] = (uChar & 0xff);
2487 mbchs[0] = (uChar & 0xff);
2490 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2493 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2497 /***********************************************************************
2498 * GetGlyphOutlineW (GDI32.@)
2500 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2501 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2502 LPVOID lpBuffer, const MAT2 *lpmat2 )
2507 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2508 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2510 if (!lpmat2) return GDI_ERROR;
2512 dc = get_dc_ptr(hdc);
2513 if(!dc) return GDI_ERROR;
2516 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2517 cbBuffer, lpBuffer, lpmat2);
2521 release_dc_ptr( dc );
2526 /***********************************************************************
2527 * CreateScalableFontResourceA (GDI32.@)
2529 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2530 LPCSTR lpszResourceFile,
2531 LPCSTR lpszFontFile,
2532 LPCSTR lpszCurrentPath )
2534 LPWSTR lpszResourceFileW = NULL;
2535 LPWSTR lpszFontFileW = NULL;
2536 LPWSTR lpszCurrentPathW = NULL;
2540 if (lpszResourceFile)
2542 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2543 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2544 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2549 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2550 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2551 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2554 if (lpszCurrentPath)
2556 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2557 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2558 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2561 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2562 lpszFontFileW, lpszCurrentPathW);
2564 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2565 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2566 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2571 /***********************************************************************
2572 * CreateScalableFontResourceW (GDI32.@)
2574 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2575 LPCWSTR lpszResourceFile,
2576 LPCWSTR lpszFontFile,
2577 LPCWSTR lpszCurrentPath )
2580 FIXME("(%d,%s,%s,%s): stub\n",
2581 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2582 debugstr_w(lpszCurrentPath) );
2584 /* fHidden=1 - only visible for the calling app, read-only, not
2585 * enumerated with EnumFonts/EnumFontFamilies
2586 * lpszCurrentPath can be NULL
2589 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2590 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2592 SetLastError(ERROR_FILE_EXISTS);
2595 return FALSE; /* create failed */
2598 /*************************************************************************
2599 * GetKerningPairsA (GDI32.@)
2601 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2602 LPKERNINGPAIR kern_pairA )
2606 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2607 KERNINGPAIR *kern_pairW;
2609 if (!cPairs && kern_pairA)
2611 SetLastError(ERROR_INVALID_PARAMETER);
2615 cp = GdiGetCodePage(hDC);
2617 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2618 * to fail on an invalid character for CP_SYMBOL.
2620 cpi.DefaultChar[0] = 0;
2621 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2623 FIXME("Can't find codepage %u info\n", cp);
2627 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2628 if (!total_kern_pairs) return 0;
2630 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2631 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2633 for (i = 0; i < total_kern_pairs; i++)
2637 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2640 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2643 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2648 if (kern_pairs_copied >= cPairs) break;
2650 kern_pairA->wFirst = (BYTE)first;
2651 kern_pairA->wSecond = (BYTE)second;
2652 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2655 kern_pairs_copied++;
2658 HeapFree(GetProcessHeap(), 0, kern_pairW);
2660 return kern_pairs_copied;
2663 /*************************************************************************
2664 * GetKerningPairsW (GDI32.@)
2666 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2667 LPKERNINGPAIR lpKerningPairs )
2672 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2674 if (!cPairs && lpKerningPairs)
2676 SetLastError(ERROR_INVALID_PARAMETER);
2680 dc = get_dc_ptr(hDC);
2684 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2686 release_dc_ptr( dc );
2690 /*************************************************************************
2691 * TranslateCharsetInfo [GDI32.@]
2693 * Fills a CHARSETINFO structure for a character set, code page, or
2694 * font. This allows making the correspondence between different labels
2695 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2696 * of the same encoding.
2698 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2699 * only one codepage should be set in *lpSrc.
2702 * TRUE on success, FALSE on failure.
2705 BOOL WINAPI TranslateCharsetInfo(
2706 LPDWORD lpSrc, /* [in]
2707 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2708 if flags == TCI_SRCCHARSET: a character set value
2709 if flags == TCI_SRCCODEPAGE: a code page value
2711 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2712 DWORD flags /* [in] determines interpretation of lpSrc */)
2716 case TCI_SRCFONTSIG:
2717 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2719 case TCI_SRCCODEPAGE:
2720 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2722 case TCI_SRCCHARSET:
2723 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2728 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2729 *lpCs = FONT_tci[index];
2733 /*************************************************************************
2734 * GetFontLanguageInfo (GDI32.@)
2736 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2738 FONTSIGNATURE fontsig;
2739 static const DWORD GCP_DBCS_MASK=0x003F0000,
2740 GCP_DIACRITIC_MASK=0x00000000,
2741 FLI_GLYPHS_MASK=0x00000000,
2742 GCP_GLYPHSHAPE_MASK=0x00000040,
2743 GCP_KASHIDA_MASK=0x00000000,
2744 GCP_LIGATE_MASK=0x00000000,
2745 GCP_USEKERNING_MASK=0x00000000,
2746 GCP_REORDER_MASK=0x00000060;
2750 GetTextCharsetInfo( hdc, &fontsig, 0 );
2751 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2753 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2756 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2757 result|=GCP_DIACRITIC;
2759 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2762 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2763 result|=GCP_GLYPHSHAPE;
2765 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2766 result|=GCP_KASHIDA;
2768 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2771 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2772 result|=GCP_USEKERNING;
2774 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2775 if( GetTextAlign( hdc) & TA_RTLREADING )
2776 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2777 result|=GCP_REORDER;
2783 /*************************************************************************
2784 * GetFontData [GDI32.@]
2786 * Retrieve data for TrueType font.
2790 * success: Number of bytes returned
2791 * failure: GDI_ERROR
2795 * Calls SetLastError()
2798 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2799 LPVOID buffer, DWORD length)
2801 DC *dc = get_dc_ptr(hdc);
2802 DWORD ret = GDI_ERROR;
2804 if(!dc) return GDI_ERROR;
2807 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2809 release_dc_ptr( dc );
2813 /*************************************************************************
2814 * GetGlyphIndicesA [GDI32.@]
2816 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2817 LPWORD pgi, DWORD flags)
2823 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2824 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2826 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2827 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2828 HeapFree(GetProcessHeap(), 0, lpstrW);
2833 /*************************************************************************
2834 * GetGlyphIndicesW [GDI32.@]
2836 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2837 LPWORD pgi, DWORD flags)
2839 DC *dc = get_dc_ptr(hdc);
2840 DWORD ret = GDI_ERROR;
2842 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2843 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2845 if(!dc) return GDI_ERROR;
2848 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2850 release_dc_ptr( dc );
2854 /*************************************************************************
2855 * GetCharacterPlacementA [GDI32.@]
2857 * See GetCharacterPlacementW.
2860 * the web browser control of ie4 calls this with dwFlags=0
2863 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2864 INT nMaxExtent, GCP_RESULTSA *lpResults,
2869 GCP_RESULTSW resultsW;
2873 TRACE("%s, %d, %d, 0x%08x\n",
2874 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2876 /* both structs are equal in size */
2877 memcpy(&resultsW, lpResults, sizeof(resultsW));
2879 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2880 if(lpResults->lpOutString)
2881 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2883 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2885 lpResults->nGlyphs = resultsW.nGlyphs;
2886 lpResults->nMaxFit = resultsW.nMaxFit;
2888 if(lpResults->lpOutString) {
2889 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2890 lpResults->lpOutString, uCount, NULL, NULL );
2893 HeapFree(GetProcessHeap(), 0, lpStringW);
2894 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2899 /*************************************************************************
2900 * GetCharacterPlacementW [GDI32.@]
2902 * Retrieve information about a string. This includes the width, reordering,
2903 * Glyphing and so on.
2907 * The width and height of the string if successful, 0 if failed.
2911 * All flags except GCP_REORDER are not yet implemented.
2912 * Reordering is not 100% compliant to the Windows BiDi method.
2913 * Caret positioning is not yet implemented for BiDi.
2914 * Classes are not yet implemented.
2918 GetCharacterPlacementW(
2919 HDC hdc, /* [in] Device context for which the rendering is to be done */
2920 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2921 INT uCount, /* [in] Number of WORDS in string. */
2922 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2923 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2924 DWORD dwFlags /* [in] Flags specifying how to process the string */
2931 TRACE("%s, %d, %d, 0x%08x\n",
2932 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2934 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2935 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2936 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2937 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2938 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2940 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2941 if(lpResults->lpClass) FIXME("classes not implemented\n");
2942 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2943 FIXME("Caret positions for complex scripts not implemented\n");
2945 nSet = (UINT)uCount;
2946 if(nSet > lpResults->nGlyphs)
2947 nSet = lpResults->nGlyphs;
2949 /* return number of initialized fields */
2950 lpResults->nGlyphs = nSet;
2952 if((dwFlags&GCP_REORDER)==0 )
2954 /* Treat the case where no special handling was requested in a fastpath way */
2955 /* copy will do if the GCP_REORDER flag is not set */
2956 if(lpResults->lpOutString)
2957 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2959 if(lpResults->lpOrder)
2961 for(i = 0; i < nSet; i++)
2962 lpResults->lpOrder[i] = i;
2966 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2967 nSet, lpResults->lpOrder, NULL, NULL );
2970 /* FIXME: Will use the placement chars */
2971 if (lpResults->lpDx)
2974 for (i = 0; i < nSet; i++)
2976 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2977 lpResults->lpDx[i]= c;
2981 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2985 lpResults->lpCaretPos[0] = 0;
2986 for (i = 1; i < nSet; i++)
2987 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2988 lpResults->lpCaretPos[i] = (pos += size.cx);
2991 if(lpResults->lpGlyphs)
2992 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2994 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2995 ret = MAKELONG(size.cx, size.cy);
3000 /*************************************************************************
3001 * GetCharABCWidthsFloatA [GDI32.@]
3003 * See GetCharABCWidthsFloatW.
3005 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3012 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3016 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3018 for (i = 0; i < wlen; i++)
3020 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3028 HeapFree( GetProcessHeap(), 0, str );
3029 HeapFree( GetProcessHeap(), 0, wstr );
3034 /*************************************************************************
3035 * GetCharABCWidthsFloatW [GDI32.@]
3037 * Retrieves widths of a range of characters.
3040 * hdc [I] Handle to device context.
3041 * first [I] First character in range to query.
3042 * last [I] Last character in range to query.
3043 * abcf [O] Array of LPABCFLOAT structures.
3049 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3055 DC *dc = get_dc_ptr( hdc );
3057 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3059 if (!dc) return FALSE;
3061 if (!abcf) goto done;
3062 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3064 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3065 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3068 /* convert device units to logical */
3069 for (i = first; i <= last; i++, abcf++)
3071 abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
3072 abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
3073 abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
3076 HeapFree( GetProcessHeap(), 0, abc );
3079 release_dc_ptr( dc );
3083 /*************************************************************************
3084 * GetCharWidthFloatA [GDI32.@]
3086 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3087 UINT iLastChar, PFLOAT pxBuffer)
3089 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3093 /*************************************************************************
3094 * GetCharWidthFloatW [GDI32.@]
3096 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3097 UINT iLastChar, PFLOAT pxBuffer)
3099 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3104 /***********************************************************************
3106 * Font Resource API *
3108 ***********************************************************************/
3110 /***********************************************************************
3111 * AddFontResourceA (GDI32.@)
3113 INT WINAPI AddFontResourceA( LPCSTR str )
3115 return AddFontResourceExA( str, 0, NULL);
3118 /***********************************************************************
3119 * AddFontResourceW (GDI32.@)
3121 INT WINAPI AddFontResourceW( LPCWSTR str )
3123 return AddFontResourceExW(str, 0, NULL);
3127 /***********************************************************************
3128 * AddFontResourceExA (GDI32.@)
3130 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3132 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3133 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3136 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3137 ret = AddFontResourceExW(strW, fl, pdv);
3138 HeapFree(GetProcessHeap(), 0, strW);
3142 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3144 HRSRC rsrc = FindResourceW(hModule, name, type);
3145 HGLOBAL hMem = LoadResource(hModule, rsrc);
3146 LPVOID *pMem = LockResource(hMem);
3147 int *num_total = (int *)lParam;
3150 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3151 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3153 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3157 *num_total += num_in_res;
3161 /***********************************************************************
3162 * AddFontResourceExW (GDI32.@)
3164 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3166 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3169 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3170 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3171 if (hModule != NULL)
3173 int num_resources = 0;
3174 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3176 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3177 wine_dbgstr_w(str));
3178 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3179 ret = num_resources;
3180 FreeLibrary(hModule);
3186 /***********************************************************************
3187 * RemoveFontResourceA (GDI32.@)
3189 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3191 return RemoveFontResourceExA(str, 0, 0);
3194 /***********************************************************************
3195 * RemoveFontResourceW (GDI32.@)
3197 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3199 return RemoveFontResourceExW(str, 0, 0);
3202 /***********************************************************************
3203 * AddFontMemResourceEx (GDI32.@)
3205 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3210 if (!pbFont || !cbFont || !pcFonts)
3212 SetLastError(ERROR_INVALID_PARAMETER);
3216 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3221 *pcFonts = num_fonts;
3225 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3226 RemoveFontMemResourceEx(ret);
3234 /***********************************************************************
3235 * RemoveFontMemResourceEx (GDI32.@)
3237 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3239 FIXME("(%p) stub\n", fh);
3243 /***********************************************************************
3244 * RemoveFontResourceExA (GDI32.@)
3246 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3248 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3249 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3252 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3253 ret = RemoveFontResourceExW(strW, fl, pdv);
3254 HeapFree(GetProcessHeap(), 0, strW);
3258 /***********************************************************************
3259 * RemoveFontResourceExW (GDI32.@)
3261 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3263 return WineEngRemoveFontResourceEx(str, fl, pdv);
3266 /***********************************************************************
3267 * GetTextCharset (GDI32.@)
3269 UINT WINAPI GetTextCharset(HDC hdc)
3271 /* MSDN docs say this is equivalent */
3272 return GetTextCharsetInfo(hdc, NULL, 0);
3275 /***********************************************************************
3276 * GetTextCharsetInfo (GDI32.@)
3278 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3280 UINT ret = DEFAULT_CHARSET;
3281 DC *dc = get_dc_ptr(hdc);
3286 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3288 release_dc_ptr( dc );
3291 if (ret == DEFAULT_CHARSET && fs)
3292 memset(fs, 0, sizeof(FONTSIGNATURE));
3296 /***********************************************************************
3297 * GdiGetCharDimensions (GDI32.@)
3299 * Gets the average width of the characters in the English alphabet.
3302 * hdc [I] Handle to the device context to measure on.
3303 * lptm [O] Pointer to memory to store the text metrics into.
3304 * height [O] On exit, the maximum height of characters in the English alphabet.
3307 * The average width of characters in the English alphabet.
3310 * This function is used by the dialog manager to get the size of a dialog
3311 * unit. It should also be used by other pieces of code that need to know
3312 * the size of a dialog unit in logical units without having access to the
3313 * window handle of the dialog.
3314 * Windows caches the font metrics from this function, but we don't and
3315 * there doesn't appear to be an immediate advantage to do so.
3318 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3320 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3323 static const WCHAR alphabet[] = {
3324 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3325 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3326 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3328 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3330 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3332 if (height) *height = sz.cy;
3333 return (sz.cx / 26 + 1) / 2;
3336 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3338 FIXME("(%d): stub\n", fEnableEUDC);
3342 /***********************************************************************
3343 * GetCharWidthI (GDI32.@)
3345 * Retrieve widths of characters.
3348 * hdc [I] Handle to a device context.
3349 * first [I] First glyph in range to query.
3350 * count [I] Number of glyph indices to query.
3351 * glyphs [I] Array of glyphs to query.
3352 * buffer [O] Buffer to receive character widths.
3355 * Only works with TrueType fonts.
3361 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3366 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3368 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3371 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3373 HeapFree(GetProcessHeap(), 0, abc);
3377 for (i = 0; i < count; i++)
3378 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3380 HeapFree(GetProcessHeap(), 0, abc);
3384 /***********************************************************************
3385 * GetFontUnicodeRanges (GDI32.@)
3387 * Retrieve a list of supported Unicode characters in a font.
3390 * hdc [I] Handle to a device context.
3391 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3394 * Success: Number of bytes written to the buffer pointed to by lpgs.
3398 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3402 DC *dc = get_dc_ptr(hdc);
3404 TRACE("(%p, %p)\n", hdc, lpgs);
3408 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3409 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3415 /*************************************************************
3416 * FontIsLinked (GDI32.@)
3418 BOOL WINAPI FontIsLinked(HDC hdc)
3420 DC *dc = get_dc_ptr(hdc);
3423 if (!dc) return FALSE;
3424 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3426 TRACE("returning %d\n", ret);
3430 /*************************************************************
3431 * GdiRealizationInfo (GDI32.@)
3433 * Returns a structure that contains some font information.
3435 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3437 DC *dc = get_dc_ptr(hdc);
3440 if (!dc) return FALSE;
3441 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);