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);
2388 if (!dc) return FALSE;
2392 release_dc_ptr( dc );
2397 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2403 /* convert device units to logical */
2404 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2405 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2406 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2407 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2412 release_dc_ptr( dc );
2417 /******************************************************************************
2418 * GetCharABCWidthsI [GDI32.@]
2420 * Retrieves widths of characters in range.
2423 * hdc [I] Handle of device context
2424 * firstChar [I] First glyphs in range to query
2425 * count [I] Last glyphs in range to query
2426 * pgi [i] Array of glyphs to query
2427 * abc [O] Address of character-width structure
2430 * Only works with TrueType fonts
2436 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2437 LPWORD pgi, LPABC abc)
2439 DC *dc = get_dc_ptr(hdc);
2443 if (!dc) return FALSE;
2447 release_dc_ptr( dc );
2452 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2458 /* convert device units to logical */
2459 for( i = 0; i < count; i++, abc++ ) {
2460 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2461 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2462 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2467 release_dc_ptr( dc );
2472 /***********************************************************************
2473 * GetGlyphOutlineA (GDI32.@)
2475 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2476 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2477 LPVOID lpBuffer, const MAT2 *lpmat2 )
2479 if (!lpmat2) return GDI_ERROR;
2481 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2486 cp = GdiGetCodePage(hdc);
2487 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2489 mbchs[0] = (uChar & 0xff00) >> 8;
2490 mbchs[1] = (uChar & 0xff);
2493 mbchs[0] = (uChar & 0xff);
2496 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2499 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2503 /***********************************************************************
2504 * GetGlyphOutlineW (GDI32.@)
2506 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2507 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2508 LPVOID lpBuffer, const MAT2 *lpmat2 )
2513 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2514 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2516 if (!lpmat2) return GDI_ERROR;
2518 dc = get_dc_ptr(hdc);
2519 if(!dc) return GDI_ERROR;
2522 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2523 cbBuffer, lpBuffer, lpmat2);
2527 release_dc_ptr( dc );
2532 /***********************************************************************
2533 * CreateScalableFontResourceA (GDI32.@)
2535 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2536 LPCSTR lpszResourceFile,
2537 LPCSTR lpszFontFile,
2538 LPCSTR lpszCurrentPath )
2540 LPWSTR lpszResourceFileW = NULL;
2541 LPWSTR lpszFontFileW = NULL;
2542 LPWSTR lpszCurrentPathW = NULL;
2546 if (lpszResourceFile)
2548 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2549 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2550 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2555 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2556 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2557 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2560 if (lpszCurrentPath)
2562 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2563 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2564 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2567 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2568 lpszFontFileW, lpszCurrentPathW);
2570 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2571 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2572 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2577 /***********************************************************************
2578 * CreateScalableFontResourceW (GDI32.@)
2580 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2581 LPCWSTR lpszResourceFile,
2582 LPCWSTR lpszFontFile,
2583 LPCWSTR lpszCurrentPath )
2586 FIXME("(%d,%s,%s,%s): stub\n",
2587 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2588 debugstr_w(lpszCurrentPath) );
2590 /* fHidden=1 - only visible for the calling app, read-only, not
2591 * enumerated with EnumFonts/EnumFontFamilies
2592 * lpszCurrentPath can be NULL
2595 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2596 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2598 SetLastError(ERROR_FILE_EXISTS);
2601 return FALSE; /* create failed */
2604 /*************************************************************************
2605 * GetKerningPairsA (GDI32.@)
2607 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2608 LPKERNINGPAIR kern_pairA )
2612 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2613 KERNINGPAIR *kern_pairW;
2615 if (!cPairs && kern_pairA)
2617 SetLastError(ERROR_INVALID_PARAMETER);
2621 cp = GdiGetCodePage(hDC);
2623 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2624 * to fail on an invalid character for CP_SYMBOL.
2626 cpi.DefaultChar[0] = 0;
2627 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2629 FIXME("Can't find codepage %u info\n", cp);
2633 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2634 if (!total_kern_pairs) return 0;
2636 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2637 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2639 for (i = 0; i < total_kern_pairs; i++)
2643 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2646 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2649 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2654 if (kern_pairs_copied >= cPairs) break;
2656 kern_pairA->wFirst = (BYTE)first;
2657 kern_pairA->wSecond = (BYTE)second;
2658 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2661 kern_pairs_copied++;
2664 HeapFree(GetProcessHeap(), 0, kern_pairW);
2666 return kern_pairs_copied;
2669 /*************************************************************************
2670 * GetKerningPairsW (GDI32.@)
2672 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2673 LPKERNINGPAIR lpKerningPairs )
2678 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2680 if (!cPairs && lpKerningPairs)
2682 SetLastError(ERROR_INVALID_PARAMETER);
2686 dc = get_dc_ptr(hDC);
2690 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2692 release_dc_ptr( dc );
2696 /*************************************************************************
2697 * TranslateCharsetInfo [GDI32.@]
2699 * Fills a CHARSETINFO structure for a character set, code page, or
2700 * font. This allows making the correspondence between different labels
2701 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2702 * of the same encoding.
2704 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2705 * only one codepage should be set in *lpSrc.
2708 * TRUE on success, FALSE on failure.
2711 BOOL WINAPI TranslateCharsetInfo(
2712 LPDWORD lpSrc, /* [in]
2713 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2714 if flags == TCI_SRCCHARSET: a character set value
2715 if flags == TCI_SRCCODEPAGE: a code page value
2717 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2718 DWORD flags /* [in] determines interpretation of lpSrc */)
2722 case TCI_SRCFONTSIG:
2723 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2725 case TCI_SRCCODEPAGE:
2726 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2728 case TCI_SRCCHARSET:
2729 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2734 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2735 *lpCs = FONT_tci[index];
2739 /*************************************************************************
2740 * GetFontLanguageInfo (GDI32.@)
2742 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2744 FONTSIGNATURE fontsig;
2745 static const DWORD GCP_DBCS_MASK=0x003F0000,
2746 GCP_DIACRITIC_MASK=0x00000000,
2747 FLI_GLYPHS_MASK=0x00000000,
2748 GCP_GLYPHSHAPE_MASK=0x00000040,
2749 GCP_KASHIDA_MASK=0x00000000,
2750 GCP_LIGATE_MASK=0x00000000,
2751 GCP_USEKERNING_MASK=0x00000000,
2752 GCP_REORDER_MASK=0x00000060;
2756 GetTextCharsetInfo( hdc, &fontsig, 0 );
2757 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2759 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2762 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2763 result|=GCP_DIACRITIC;
2765 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2768 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2769 result|=GCP_GLYPHSHAPE;
2771 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2772 result|=GCP_KASHIDA;
2774 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2777 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2778 result|=GCP_USEKERNING;
2780 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2781 if( GetTextAlign( hdc) & TA_RTLREADING )
2782 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2783 result|=GCP_REORDER;
2789 /*************************************************************************
2790 * GetFontData [GDI32.@]
2792 * Retrieve data for TrueType font.
2796 * success: Number of bytes returned
2797 * failure: GDI_ERROR
2801 * Calls SetLastError()
2804 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2805 LPVOID buffer, DWORD length)
2807 DC *dc = get_dc_ptr(hdc);
2808 DWORD ret = GDI_ERROR;
2810 if(!dc) return GDI_ERROR;
2813 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2815 release_dc_ptr( dc );
2819 /*************************************************************************
2820 * GetGlyphIndicesA [GDI32.@]
2822 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2823 LPWORD pgi, DWORD flags)
2829 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2830 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2832 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2833 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2834 HeapFree(GetProcessHeap(), 0, lpstrW);
2839 /*************************************************************************
2840 * GetGlyphIndicesW [GDI32.@]
2842 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2843 LPWORD pgi, DWORD flags)
2845 DC *dc = get_dc_ptr(hdc);
2846 DWORD ret = GDI_ERROR;
2848 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2849 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2851 if(!dc) return GDI_ERROR;
2854 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2856 release_dc_ptr( dc );
2860 /*************************************************************************
2861 * GetCharacterPlacementA [GDI32.@]
2863 * See GetCharacterPlacementW.
2866 * the web browser control of ie4 calls this with dwFlags=0
2869 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2870 INT nMaxExtent, GCP_RESULTSA *lpResults,
2875 GCP_RESULTSW resultsW;
2879 TRACE("%s, %d, %d, 0x%08x\n",
2880 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2882 /* both structs are equal in size */
2883 memcpy(&resultsW, lpResults, sizeof(resultsW));
2885 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2886 if(lpResults->lpOutString)
2887 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2889 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2891 lpResults->nGlyphs = resultsW.nGlyphs;
2892 lpResults->nMaxFit = resultsW.nMaxFit;
2894 if(lpResults->lpOutString) {
2895 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2896 lpResults->lpOutString, uCount, NULL, NULL );
2899 HeapFree(GetProcessHeap(), 0, lpStringW);
2900 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2905 /*************************************************************************
2906 * GetCharacterPlacementW [GDI32.@]
2908 * Retrieve information about a string. This includes the width, reordering,
2909 * Glyphing and so on.
2913 * The width and height of the string if successful, 0 if failed.
2917 * All flags except GCP_REORDER are not yet implemented.
2918 * Reordering is not 100% compliant to the Windows BiDi method.
2919 * Caret positioning is not yet implemented for BiDi.
2920 * Classes are not yet implemented.
2924 GetCharacterPlacementW(
2925 HDC hdc, /* [in] Device context for which the rendering is to be done */
2926 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2927 INT uCount, /* [in] Number of WORDS in string. */
2928 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2929 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2930 DWORD dwFlags /* [in] Flags specifying how to process the string */
2937 TRACE("%s, %d, %d, 0x%08x\n",
2938 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2940 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2941 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2942 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2943 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2944 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2946 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2947 if(lpResults->lpClass) FIXME("classes not implemented\n");
2948 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2949 FIXME("Caret positions for complex scripts not implemented\n");
2951 nSet = (UINT)uCount;
2952 if(nSet > lpResults->nGlyphs)
2953 nSet = lpResults->nGlyphs;
2955 /* return number of initialized fields */
2956 lpResults->nGlyphs = nSet;
2958 if((dwFlags&GCP_REORDER)==0 )
2960 /* Treat the case where no special handling was requested in a fastpath way */
2961 /* copy will do if the GCP_REORDER flag is not set */
2962 if(lpResults->lpOutString)
2963 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2965 if(lpResults->lpOrder)
2967 for(i = 0; i < nSet; i++)
2968 lpResults->lpOrder[i] = i;
2972 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2973 nSet, lpResults->lpOrder, NULL, NULL );
2976 /* FIXME: Will use the placement chars */
2977 if (lpResults->lpDx)
2980 for (i = 0; i < nSet; i++)
2982 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2983 lpResults->lpDx[i]= c;
2987 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2991 lpResults->lpCaretPos[0] = 0;
2992 for (i = 1; i < nSet; i++)
2993 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2994 lpResults->lpCaretPos[i] = (pos += size.cx);
2997 if(lpResults->lpGlyphs)
2998 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3000 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3001 ret = MAKELONG(size.cx, size.cy);
3006 /*************************************************************************
3007 * GetCharABCWidthsFloatA [GDI32.@]
3009 * See GetCharABCWidthsFloatW.
3011 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3018 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3022 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3024 for (i = 0; i < wlen; i++)
3026 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3034 HeapFree( GetProcessHeap(), 0, str );
3035 HeapFree( GetProcessHeap(), 0, wstr );
3040 /*************************************************************************
3041 * GetCharABCWidthsFloatW [GDI32.@]
3043 * Retrieves widths of a range of characters.
3046 * hdc [I] Handle to device context.
3047 * first [I] First character in range to query.
3048 * last [I] Last character in range to query.
3049 * abcf [O] Array of LPABCFLOAT structures.
3055 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3059 DC *dc = get_dc_ptr( hdc );
3061 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3063 if (!dc) return FALSE;
3067 release_dc_ptr( dc );
3072 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3078 /* convert device units to logical */
3079 for (i = first; i <= last; i++, abcf++)
3081 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3082 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3083 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3087 release_dc_ptr( dc );
3091 /*************************************************************************
3092 * GetCharWidthFloatA [GDI32.@]
3094 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3095 UINT iLastChar, PFLOAT pxBuffer)
3097 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3101 /*************************************************************************
3102 * GetCharWidthFloatW [GDI32.@]
3104 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3105 UINT iLastChar, PFLOAT pxBuffer)
3107 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3112 /***********************************************************************
3114 * Font Resource API *
3116 ***********************************************************************/
3118 /***********************************************************************
3119 * AddFontResourceA (GDI32.@)
3121 INT WINAPI AddFontResourceA( LPCSTR str )
3123 return AddFontResourceExA( str, 0, NULL);
3126 /***********************************************************************
3127 * AddFontResourceW (GDI32.@)
3129 INT WINAPI AddFontResourceW( LPCWSTR str )
3131 return AddFontResourceExW(str, 0, NULL);
3135 /***********************************************************************
3136 * AddFontResourceExA (GDI32.@)
3138 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3140 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3141 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3144 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3145 ret = AddFontResourceExW(strW, fl, pdv);
3146 HeapFree(GetProcessHeap(), 0, strW);
3150 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3152 HRSRC rsrc = FindResourceW(hModule, name, type);
3153 HGLOBAL hMem = LoadResource(hModule, rsrc);
3154 LPVOID *pMem = LockResource(hMem);
3155 int *num_total = (int *)lParam;
3158 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3159 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3161 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3165 *num_total += num_in_res;
3169 /***********************************************************************
3170 * AddFontResourceExW (GDI32.@)
3172 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3174 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3177 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3178 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3179 if (hModule != NULL)
3181 int num_resources = 0;
3182 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3184 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3185 wine_dbgstr_w(str));
3186 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3187 ret = num_resources;
3188 FreeLibrary(hModule);
3194 /***********************************************************************
3195 * RemoveFontResourceA (GDI32.@)
3197 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3199 return RemoveFontResourceExA(str, 0, 0);
3202 /***********************************************************************
3203 * RemoveFontResourceW (GDI32.@)
3205 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3207 return RemoveFontResourceExW(str, 0, 0);
3210 /***********************************************************************
3211 * AddFontMemResourceEx (GDI32.@)
3213 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3218 if (!pbFont || !cbFont || !pcFonts)
3220 SetLastError(ERROR_INVALID_PARAMETER);
3224 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3229 *pcFonts = num_fonts;
3233 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3234 RemoveFontMemResourceEx(ret);
3242 /***********************************************************************
3243 * RemoveFontMemResourceEx (GDI32.@)
3245 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3247 FIXME("(%p) stub\n", fh);
3251 /***********************************************************************
3252 * RemoveFontResourceExA (GDI32.@)
3254 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3256 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3257 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3260 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3261 ret = RemoveFontResourceExW(strW, fl, pdv);
3262 HeapFree(GetProcessHeap(), 0, strW);
3266 /***********************************************************************
3267 * RemoveFontResourceExW (GDI32.@)
3269 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3271 return WineEngRemoveFontResourceEx(str, fl, pdv);
3274 /***********************************************************************
3275 * GetTextCharset (GDI32.@)
3277 UINT WINAPI GetTextCharset(HDC hdc)
3279 /* MSDN docs say this is equivalent */
3280 return GetTextCharsetInfo(hdc, NULL, 0);
3283 /***********************************************************************
3284 * GetTextCharsetInfo (GDI32.@)
3286 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3288 UINT ret = DEFAULT_CHARSET;
3289 DC *dc = get_dc_ptr(hdc);
3294 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3296 release_dc_ptr( dc );
3299 if (ret == DEFAULT_CHARSET && fs)
3300 memset(fs, 0, sizeof(FONTSIGNATURE));
3304 /***********************************************************************
3305 * GdiGetCharDimensions (GDI32.@)
3307 * Gets the average width of the characters in the English alphabet.
3310 * hdc [I] Handle to the device context to measure on.
3311 * lptm [O] Pointer to memory to store the text metrics into.
3312 * height [O] On exit, the maximum height of characters in the English alphabet.
3315 * The average width of characters in the English alphabet.
3318 * This function is used by the dialog manager to get the size of a dialog
3319 * unit. It should also be used by other pieces of code that need to know
3320 * the size of a dialog unit in logical units without having access to the
3321 * window handle of the dialog.
3322 * Windows caches the font metrics from this function, but we don't and
3323 * there doesn't appear to be an immediate advantage to do so.
3326 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3328 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3331 static const WCHAR alphabet[] = {
3332 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3333 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3334 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3336 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3338 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3340 if (height) *height = sz.cy;
3341 return (sz.cx / 26 + 1) / 2;
3344 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3346 FIXME("(%d): stub\n", fEnableEUDC);
3350 /***********************************************************************
3351 * GetCharWidthI (GDI32.@)
3353 * Retrieve widths of characters.
3356 * hdc [I] Handle to a device context.
3357 * first [I] First glyph in range to query.
3358 * count [I] Number of glyph indices to query.
3359 * glyphs [I] Array of glyphs to query.
3360 * buffer [O] Buffer to receive character widths.
3363 * Only works with TrueType fonts.
3369 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3374 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3376 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3379 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3381 HeapFree(GetProcessHeap(), 0, abc);
3385 for (i = 0; i < count; i++)
3386 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3388 HeapFree(GetProcessHeap(), 0, abc);
3392 /***********************************************************************
3393 * GetFontUnicodeRanges (GDI32.@)
3395 * Retrieve a list of supported Unicode characters in a font.
3398 * hdc [I] Handle to a device context.
3399 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3402 * Success: Number of bytes written to the buffer pointed to by lpgs.
3406 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3409 DC *dc = get_dc_ptr(hdc);
3411 TRACE("(%p, %p)\n", hdc, lpgs);
3415 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3421 /*************************************************************
3422 * FontIsLinked (GDI32.@)
3424 BOOL WINAPI FontIsLinked(HDC hdc)
3426 DC *dc = get_dc_ptr(hdc);
3429 if (!dc) return FALSE;
3430 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3432 TRACE("returning %d\n", ret);
3436 /*************************************************************
3437 * GdiRealizationInfo (GDI32.@)
3439 * Returns a structure that contains some font information.
3441 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3443 DC *dc = get_dc_ptr(hdc);
3446 if (!dc) return FALSE;
3447 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);