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 */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
114 LPLOGFONTW lpLogFontParam;
115 FONTENUMPROCW lpEnumFunc;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
167 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
170 fontW->lfFaceName[LF_FACESIZE-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
175 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177 LF_FACESIZE, NULL, NULL);
178 fontA->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
183 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190 fontA->elfStyle[LF_FACESIZE-1] = '\0';
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193 fontA->elfScript[LF_FACESIZE-1] = '\0';
196 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
198 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
201 fontW->elfFullName, LF_FULLFACESIZE );
202 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
204 fontW->elfStyle, LF_FACESIZE );
205 fontW->elfStyle[LF_FACESIZE-1] = '\0';
206 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
207 fontW->elfScript, LF_FACESIZE );
208 fontW->elfScript[LF_FACESIZE-1] = '\0';
211 /***********************************************************************
212 * TEXTMETRIC conversion functions.
214 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
216 ptmA->tmHeight = ptmW->tmHeight;
217 ptmA->tmAscent = ptmW->tmAscent;
218 ptmA->tmDescent = ptmW->tmDescent;
219 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
220 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
221 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
222 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
223 ptmA->tmWeight = ptmW->tmWeight;
224 ptmA->tmOverhang = ptmW->tmOverhang;
225 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
226 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
227 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
228 if (ptmW->tmCharSet == SYMBOL_CHARSET)
230 ptmA->tmFirstChar = 0x1e;
231 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
235 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
236 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
238 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
239 ptmA->tmBreakChar = ptmW->tmBreakChar;
240 ptmA->tmItalic = ptmW->tmItalic;
241 ptmA->tmUnderlined = ptmW->tmUnderlined;
242 ptmA->tmStruckOut = ptmW->tmStruckOut;
243 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
244 ptmA->tmCharSet = ptmW->tmCharSet;
248 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
250 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
251 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
252 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
253 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
254 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
255 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
259 /***********************************************************************
260 * GdiGetCodePage (GDI32.@)
262 DWORD WINAPI GdiGetCodePage( HDC hdc )
265 DC *dc = get_dc_ptr( hdc );
269 cp = dc->font_code_page;
270 release_dc_ptr( dc );
275 /***********************************************************************
278 * Returns a Unicode translation of str using the charset of the
279 * currently selected font in hdc. If count is -1 then str is assumed
280 * to be '\0' terminated, otherwise it contains the number of bytes to
281 * convert. If plenW is non-NULL, on return it will point to the
282 * number of WCHARs that have been written. If pCP is non-NULL, on
283 * return it will point to the codepage used in the conversion. The
284 * caller should free the returned LPWSTR from the process heap
287 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
293 cp = GdiGetCodePage( hdc );
295 if(count == -1) count = strlen(str);
296 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
297 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
298 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
299 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
300 if(plenW) *plenW = lenW;
305 /***********************************************************************
306 * CreateFontIndirectExA (GDI32.@)
308 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
310 ENUMLOGFONTEXDVW enumexW;
312 if (!penumexA) return 0;
314 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
315 enumexW.elfDesignVector = penumexA->elfDesignVector;
316 return CreateFontIndirectExW( &enumexW );
319 /***********************************************************************
320 * CreateFontIndirectExW (GDI32.@)
322 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
328 if (!penumex) return 0;
330 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
331 penumex->elfEnumLogfontEx.elfStyle[0] ||
332 penumex->elfEnumLogfontEx.elfScript[0])
334 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
335 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
336 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
337 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
340 plf = &penumex->elfEnumLogfontEx.elfLogFont;
341 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
343 fontPtr->logfont = *plf;
345 if (plf->lfEscapement != plf->lfOrientation)
347 /* this should really depend on whether GM_ADVANCED is set */
348 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
349 WARN("orientation angle %f set to "
350 "escapement angle %f for new font %p\n",
351 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
354 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
356 HeapFree( GetProcessHeap(), 0, fontPtr );
360 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
361 plf->lfHeight, plf->lfWidth,
362 plf->lfEscapement, plf->lfOrientation,
363 plf->lfPitchAndFamily,
364 plf->lfOutPrecision, plf->lfClipPrecision,
365 plf->lfQuality, plf->lfCharSet,
366 debugstr_w(plf->lfFaceName),
367 plf->lfWeight > 400 ? "Bold" : "",
368 plf->lfItalic ? "Italic" : "",
369 plf->lfUnderline ? "Underline" : "", hFont);
374 /***********************************************************************
375 * CreateFontIndirectA (GDI32.@)
377 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
383 FONT_LogFontAToW( plfA, &lfW );
384 return CreateFontIndirectW( &lfW );
387 /***********************************************************************
388 * CreateFontIndirectW (GDI32.@)
390 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
392 ENUMLOGFONTEXDVW exdv;
396 exdv.elfEnumLogfontEx.elfLogFont = *plf;
397 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
398 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
399 exdv.elfEnumLogfontEx.elfScript[0] = 0;
400 return CreateFontIndirectExW( &exdv );
403 /*************************************************************************
404 * CreateFontA (GDI32.@)
406 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
407 INT orient, INT weight, DWORD italic,
408 DWORD underline, DWORD strikeout, DWORD charset,
409 DWORD outpres, DWORD clippres, DWORD quality,
410 DWORD pitch, LPCSTR name )
414 logfont.lfHeight = height;
415 logfont.lfWidth = width;
416 logfont.lfEscapement = esc;
417 logfont.lfOrientation = orient;
418 logfont.lfWeight = weight;
419 logfont.lfItalic = italic;
420 logfont.lfUnderline = underline;
421 logfont.lfStrikeOut = strikeout;
422 logfont.lfCharSet = charset;
423 logfont.lfOutPrecision = outpres;
424 logfont.lfClipPrecision = clippres;
425 logfont.lfQuality = quality;
426 logfont.lfPitchAndFamily = pitch;
429 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
431 logfont.lfFaceName[0] = '\0';
433 return CreateFontIndirectA( &logfont );
436 /*************************************************************************
437 * CreateFontW (GDI32.@)
439 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
440 INT orient, INT weight, DWORD italic,
441 DWORD underline, DWORD strikeout, DWORD charset,
442 DWORD outpres, DWORD clippres, DWORD quality,
443 DWORD pitch, LPCWSTR name )
447 logfont.lfHeight = height;
448 logfont.lfWidth = width;
449 logfont.lfEscapement = esc;
450 logfont.lfOrientation = orient;
451 logfont.lfWeight = weight;
452 logfont.lfItalic = italic;
453 logfont.lfUnderline = underline;
454 logfont.lfStrikeOut = strikeout;
455 logfont.lfCharSet = charset;
456 logfont.lfOutPrecision = outpres;
457 logfont.lfClipPrecision = clippres;
458 logfont.lfQuality = quality;
459 logfont.lfPitchAndFamily = pitch;
462 lstrcpynW(logfont.lfFaceName, name,
463 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
465 logfont.lfFaceName[0] = '\0';
467 return CreateFontIndirectW( &logfont );
470 static void update_font_code_page( DC *dc )
473 int charset = DEFAULT_CHARSET;
476 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
478 /* Hmm, nicely designed api this one! */
479 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
480 dc->font_code_page = csi.ciACP;
484 dc->font_code_page = GetOEMCP();
486 case DEFAULT_CHARSET:
487 dc->font_code_page = GetACP();
497 /* FIXME: These have no place here, but because x11drv
498 enumerates fonts with these (made up) charsets some apps
499 might use them and then the FIXME below would become
500 annoying. Now we could pick the intended codepage for
501 each of these, but since it's broken anyway we'll just
502 use CP_ACP and hope it'll go away...
504 dc->font_code_page = CP_ACP;
508 FIXME("Can't find codepage for charset %d\n", charset);
509 dc->font_code_page = CP_ACP;
514 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
517 /***********************************************************************
520 * If the driver supports vector fonts we create a gdi font first and
521 * then call the driver to give it a chance to supply its own device
522 * font. If the driver wants to do this it returns TRUE and we can
523 * delete the gdi font, if the driver wants to use the gdi font it
524 * should return FALSE, to signal an error return GDI_ERROR. For
525 * drivers that don't support vector fonts they must supply their own
528 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
531 DC *dc = get_dc_ptr( hdc );
536 if (!GDI_inc_ref_count( handle ))
538 release_dc_ptr( dc );
542 if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
543 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
545 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
546 ret = physdev->funcs->pSelectFont( physdev, handle, dc->gdiFont );
548 if (ret && dc->gdiFont) dc->gdiFont = 0;
550 if (ret == HGDI_ERROR)
552 GDI_dec_ref_count( handle );
553 ret = 0; /* SelectObject returns 0 on error */
559 update_font_code_page( dc );
560 GDI_dec_ref_count( ret );
562 release_dc_ptr( dc );
567 /***********************************************************************
570 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
572 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
578 FONT_LogFontWToA( &font->logfont, &lfA );
579 if (count > sizeof(lfA)) count = sizeof(lfA);
580 memcpy( buffer, &lfA, count );
582 else count = sizeof(lfA);
583 GDI_ReleaseObj( handle );
587 /***********************************************************************
590 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
592 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
597 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
598 memcpy( buffer, &font->logfont, count );
600 else count = sizeof(LOGFONTW);
601 GDI_ReleaseObj( handle );
606 /***********************************************************************
609 static BOOL FONT_DeleteObject( HGDIOBJ handle )
613 WineEngDestroyFontInstance( handle );
615 if (!(obj = free_gdi_handle( handle ))) return FALSE;
616 return HeapFree( GetProcessHeap(), 0, obj );
620 /***********************************************************************
623 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
624 * We have to use other types because of the FONTENUMPROCW definition.
626 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
627 DWORD fType, LPARAM lp )
629 fontEnum32 *pfe = (fontEnum32*)lp;
632 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
633 if ((!pfe->lpLogFontParam ||
634 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
635 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
636 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
638 /* convert font metrics */
639 ENUMLOGFONTEXA logfont;
640 NEWTEXTMETRICEXA tmA;
642 pfe->dwFlags |= ENUM_CALLED;
643 if (!(pfe->dwFlags & ENUM_UNICODE))
645 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
646 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
647 plf = (LOGFONTW *)&logfont.elfLogFont;
648 ptm = (TEXTMETRICW *)&tmA;
651 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
656 /***********************************************************************
657 * FONT_EnumFontFamiliesEx
659 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
660 FONTENUMPROCW efproc,
661 LPARAM lParam, DWORD dwUnicode)
664 DC *dc = get_dc_ptr( hDC );
671 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
673 fe32.lpLogFontParam = plf;
674 fe32.lpEnumFunc = efproc;
675 fe32.lpData = lParam;
676 fe32.dwFlags = dwUnicode;
679 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
682 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
683 fe32.dwFlags &= ~ENUM_CALLED;
686 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumDeviceFonts );
687 ret2 = physdev->funcs->pEnumDeviceFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
688 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
691 release_dc_ptr( dc );
695 /***********************************************************************
696 * EnumFontFamiliesExW (GDI32.@)
698 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
699 FONTENUMPROCW efproc,
700 LPARAM lParam, DWORD dwFlags )
702 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
705 /***********************************************************************
706 * EnumFontFamiliesExA (GDI32.@)
708 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
709 FONTENUMPROCA efproc,
710 LPARAM lParam, DWORD dwFlags)
716 FONT_LogFontAToW( plf, &lfW );
721 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
724 /***********************************************************************
725 * EnumFontFamiliesA (GDI32.@)
727 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
728 FONTENUMPROCA efproc, LPARAM lpData )
734 if (!*lpFamily) return 1;
735 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
736 lf.lfCharSet = DEFAULT_CHARSET;
737 lf.lfPitchAndFamily = 0;
742 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
745 /***********************************************************************
746 * EnumFontFamiliesW (GDI32.@)
748 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
749 FONTENUMPROCW efproc, LPARAM lpData )
755 if (!*lpFamily) return 1;
756 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
757 lf.lfCharSet = DEFAULT_CHARSET;
758 lf.lfPitchAndFamily = 0;
763 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
766 /***********************************************************************
767 * EnumFontsA (GDI32.@)
769 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
772 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
775 /***********************************************************************
776 * EnumFontsW (GDI32.@)
778 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
781 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
785 /***********************************************************************
786 * GetTextCharacterExtra (GDI32.@)
788 INT WINAPI GetTextCharacterExtra( HDC hdc )
791 DC *dc = get_dc_ptr( hdc );
792 if (!dc) return 0x80000000;
794 release_dc_ptr( dc );
799 /***********************************************************************
800 * SetTextCharacterExtra (GDI32.@)
802 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
804 INT ret = 0x80000000;
805 DC * dc = get_dc_ptr( hdc );
809 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
810 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
811 if (extra != 0x80000000)
814 dc->charExtra = extra;
816 release_dc_ptr( dc );
822 /***********************************************************************
823 * SetTextJustification (GDI32.@)
825 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
829 DC * dc = get_dc_ptr( hdc );
831 if (!dc) return FALSE;
833 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
834 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
837 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
838 if (!extra) breaks = 0;
841 dc->breakExtra = extra / breaks;
842 dc->breakRem = extra - (breaks * dc->breakExtra);
850 release_dc_ptr( dc );
855 /***********************************************************************
856 * GetTextFaceA (GDI32.@)
858 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
860 INT res = GetTextFaceW(hdc, 0, NULL);
861 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
862 GetTextFaceW( hdc, res, nameW );
868 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
872 /* GetTextFaceA does NOT include the nul byte in the return count. */
879 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
880 HeapFree( GetProcessHeap(), 0, nameW );
884 /***********************************************************************
885 * GetTextFaceW (GDI32.@)
887 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
892 DC * dc = get_dc_ptr( hdc );
896 ret = WineEngGetTextFace(dc->gdiFont, count, name);
897 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
899 INT n = strlenW(font->logfont.lfFaceName) + 1;
902 lstrcpynW( name, font->logfont.lfFaceName, count );
906 GDI_ReleaseObj( dc->hFont );
908 release_dc_ptr( dc );
913 /***********************************************************************
914 * GetTextExtentPoint32A (GDI32.@)
916 * See GetTextExtentPoint32W.
918 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
925 if (count < 0) return FALSE;
927 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
931 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
932 HeapFree( GetProcessHeap(), 0, p );
935 TRACE("(%p %s %d %p): returning %d x %d\n",
936 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
941 /***********************************************************************
942 * GetTextExtentPoint32W [GDI32.@]
944 * Computes width/height for a string.
946 * Computes width and height of the specified string.
952 BOOL WINAPI GetTextExtentPoint32W(
953 HDC hdc, /* [in] Handle of device context */
954 LPCWSTR str, /* [in] Address of text string */
955 INT count, /* [in] Number of characters in string */
956 LPSIZE size) /* [out] Address of structure for string size */
958 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
961 /***********************************************************************
962 * GetTextExtentExPointI [GDI32.@]
964 * Computes width and height of the array of glyph indices.
967 * hdc [I] Handle of device context.
968 * indices [I] Glyph index array.
969 * count [I] Number of glyphs in array.
970 * max_ext [I] Maximum width in glyphs.
971 * nfit [O] Maximum number of characters.
972 * dxs [O] Partial string widths.
973 * size [O] Returned string size.
979 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
980 LPINT nfit, LPINT dxs, LPSIZE size )
985 if (count < 0) return FALSE;
987 dc = get_dc_ptr( hdc );
988 if (!dc) return FALSE;
992 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
993 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
994 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
995 size->cx += count * dc->charExtra;
999 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1000 FIXME("calling GetTextExtentExPoint\n");
1001 ret = physdev->funcs->pGetTextExtentExPoint( physdev, indices, count, max_ext, nfit, dxs, size );
1004 release_dc_ptr( dc );
1006 TRACE("(%p %p %d %p): returning %d x %d\n",
1007 hdc, indices, count, size, size->cx, size->cy );
1011 /***********************************************************************
1012 * GetTextExtentPointI [GDI32.@]
1014 * Computes width and height of the array of glyph indices.
1017 * hdc [I] Handle of device context.
1018 * indices [I] Glyph index array.
1019 * count [I] Number of glyphs in array.
1020 * size [O] Returned string size.
1026 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1028 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1032 /***********************************************************************
1033 * GetTextExtentPointA (GDI32.@)
1035 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1038 TRACE("not bug compatible.\n");
1039 return GetTextExtentPoint32A( hdc, str, count, size );
1042 /***********************************************************************
1043 * GetTextExtentPointW (GDI32.@)
1045 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1048 TRACE("not bug compatible.\n");
1049 return GetTextExtentPoint32W( hdc, str, count, size );
1053 /***********************************************************************
1054 * GetTextExtentExPointA (GDI32.@)
1056 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1057 INT maxExt, LPINT lpnFit,
1058 LPINT alpDx, LPSIZE size )
1065 if (count < 0) return FALSE;
1069 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1070 if (!walpDx) return FALSE;
1073 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1074 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1077 INT n = lpnFit ? *lpnFit : wlen;
1079 for(i = 0, j = 0; i < n; i++, j++)
1081 alpDx[j] = walpDx[i];
1082 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1085 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1086 HeapFree( GetProcessHeap(), 0, p );
1087 HeapFree( GetProcessHeap(), 0, walpDx );
1092 /***********************************************************************
1093 * GetTextExtentExPointW (GDI32.@)
1095 * Return the size of the string as it would be if it was output properly by
1098 * This should include
1099 * - Intercharacter spacing
1100 * - justification spacing (not yet done)
1101 * - kerning? see below
1103 * Kerning. Since kerning would be carried out by the rendering code it should
1104 * be done by the driver. However they don't support it yet. Also I am not
1105 * yet persuaded that (certainly under Win95) any kerning is actually done.
1107 * str: According to MSDN this should be null-terminated. That is not true; a
1108 * null will not terminate it early.
1109 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1110 * than count. I have seen it be either the size of the full string or
1111 * 1 less than the size of the full string. I have not seen it bear any
1112 * resemblance to the portion that would fit.
1113 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1114 * trailing intercharacter spacing and any trailing justification.
1117 * Currently we do this by measuring each character etc. We should do it by
1118 * passing the request to the driver, perhaps by extending the
1119 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1120 * thinking about kerning issues and rounding issues in the justification.
1123 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1124 INT maxExt, LPINT lpnFit,
1125 LPINT alpDx, LPSIZE size )
1133 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1135 if (count < 0) return FALSE;
1137 dc = get_dc_ptr(hdc);
1138 if (!dc) return FALSE;
1140 GetTextMetricsW(hdc, &tm);
1142 /* If we need to calculate nFit, then we need the partial extents even if
1143 the user hasn't provided us with an array. */
1146 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1150 SetLastError(ERROR_OUTOFMEMORY);
1158 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1159 0, NULL, dxs, size);
1162 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1163 ret = physdev->funcs->pGetTextExtentExPoint(physdev, str, count, 0, NULL, dxs, size);
1166 /* Perform device size to world size transformations. */
1169 INT extra = dc->charExtra,
1170 breakExtra = dc->breakExtra,
1171 breakRem = dc->breakRem,
1176 for (i = 0; i < count; ++i)
1178 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1179 dxs[i] += (i+1) * extra;
1180 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1182 dxs[i] += breakExtra;
1189 if (dxs[i] <= maxExt)
1192 breakRem = dc->breakRem;
1194 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1195 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1197 if (!dxs && count > 1 && (breakExtra || breakRem))
1199 for (i = 0; i < count; i++)
1201 if (str[i] == tm.tmBreakChar)
1203 size->cx += breakExtra;
1218 HeapFree(GetProcessHeap(), 0, dxs);
1220 release_dc_ptr( dc );
1222 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1226 /***********************************************************************
1227 * GetTextMetricsA (GDI32.@)
1229 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1233 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1234 FONT_TextMetricWToA( &tm32, metrics );
1238 /***********************************************************************
1239 * GetTextMetricsW (GDI32.@)
1241 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1244 DC * dc = get_dc_ptr( hdc );
1245 if (!dc) return FALSE;
1248 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1251 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1252 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1257 /* device layer returns values in device units
1258 * therefore we have to convert them to logical */
1260 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1261 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1263 #define WDPTOLP(x) ((x<0)? \
1264 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1265 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1266 #define HDPTOLP(y) ((y<0)? \
1267 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1268 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1270 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1271 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1272 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1273 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1274 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1275 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1276 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1277 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1281 TRACE("text metrics:\n"
1282 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1283 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1284 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1285 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1286 " PitchAndFamily = %02x\n"
1287 " --------------------\n"
1288 " InternalLeading = %i\n"
1292 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1293 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1294 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1295 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1296 metrics->tmPitchAndFamily,
1297 metrics->tmInternalLeading,
1300 metrics->tmHeight );
1302 release_dc_ptr( dc );
1307 /***********************************************************************
1308 * GetOutlineTextMetricsA (GDI32.@)
1309 * Gets metrics for TrueType fonts.
1312 * If the supplied buffer isn't big enough Windows partially fills it up to
1313 * its given length and returns that length.
1316 * Success: Non-zero or size of required buffer
1319 UINT WINAPI GetOutlineTextMetricsA(
1320 HDC hdc, /* [in] Handle of device context */
1321 UINT cbData, /* [in] Size of metric data array */
1322 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1324 char buf[512], *ptr;
1326 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1327 OUTLINETEXTMETRICA *output = lpOTM;
1330 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1332 if(ret > sizeof(buf))
1333 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1334 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1336 needed = sizeof(OUTLINETEXTMETRICA);
1337 if(lpOTMW->otmpFamilyName)
1338 needed += WideCharToMultiByte(CP_ACP, 0,
1339 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1340 NULL, 0, NULL, NULL);
1341 if(lpOTMW->otmpFaceName)
1342 needed += WideCharToMultiByte(CP_ACP, 0,
1343 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1344 NULL, 0, NULL, NULL);
1345 if(lpOTMW->otmpStyleName)
1346 needed += WideCharToMultiByte(CP_ACP, 0,
1347 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1348 NULL, 0, NULL, NULL);
1349 if(lpOTMW->otmpFullName)
1350 needed += WideCharToMultiByte(CP_ACP, 0,
1351 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1352 NULL, 0, NULL, NULL);
1359 TRACE("needed = %d\n", needed);
1361 /* Since the supplied buffer isn't big enough, we'll alloc one
1362 that is and memcpy the first cbData bytes into the lpOTM at
1364 output = HeapAlloc(GetProcessHeap(), 0, needed);
1366 ret = output->otmSize = min(needed, cbData);
1367 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1368 output->otmFiller = 0;
1369 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1370 output->otmfsSelection = lpOTMW->otmfsSelection;
1371 output->otmfsType = lpOTMW->otmfsType;
1372 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1373 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1374 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1375 output->otmEMSquare = lpOTMW->otmEMSquare;
1376 output->otmAscent = lpOTMW->otmAscent;
1377 output->otmDescent = lpOTMW->otmDescent;
1378 output->otmLineGap = lpOTMW->otmLineGap;
1379 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1380 output->otmsXHeight = lpOTMW->otmsXHeight;
1381 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1382 output->otmMacAscent = lpOTMW->otmMacAscent;
1383 output->otmMacDescent = lpOTMW->otmMacDescent;
1384 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1385 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1386 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1387 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1388 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1389 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1390 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1391 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1392 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1393 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1396 ptr = (char*)(output + 1);
1397 left = needed - sizeof(*output);
1399 if(lpOTMW->otmpFamilyName) {
1400 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1401 len = WideCharToMultiByte(CP_ACP, 0,
1402 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1403 ptr, left, NULL, NULL);
1407 output->otmpFamilyName = 0;
1409 if(lpOTMW->otmpFaceName) {
1410 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1411 len = WideCharToMultiByte(CP_ACP, 0,
1412 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1413 ptr, left, NULL, NULL);
1417 output->otmpFaceName = 0;
1419 if(lpOTMW->otmpStyleName) {
1420 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1421 len = WideCharToMultiByte(CP_ACP, 0,
1422 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1423 ptr, left, NULL, NULL);
1427 output->otmpStyleName = 0;
1429 if(lpOTMW->otmpFullName) {
1430 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1431 len = WideCharToMultiByte(CP_ACP, 0,
1432 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1433 ptr, left, NULL, NULL);
1436 output->otmpFullName = 0;
1440 if(output != lpOTM) {
1441 memcpy(lpOTM, output, cbData);
1442 HeapFree(GetProcessHeap(), 0, output);
1444 /* check if the string offsets really fit into the provided size */
1445 /* FIXME: should we check string length as well? */
1446 /* make sure that we don't read/write beyond the provided buffer */
1447 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1449 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1450 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1453 /* make sure that we don't read/write beyond the provided buffer */
1454 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1456 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1457 lpOTM->otmpFaceName = 0; /* doesn't fit */
1460 /* make sure that we don't read/write beyond the provided buffer */
1461 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1463 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1464 lpOTM->otmpStyleName = 0; /* doesn't fit */
1467 /* make sure that we don't read/write beyond the provided buffer */
1468 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1470 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1471 lpOTM->otmpFullName = 0; /* doesn't fit */
1476 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1477 HeapFree(GetProcessHeap(), 0, lpOTMW);
1483 /***********************************************************************
1484 * GetOutlineTextMetricsW [GDI32.@]
1486 UINT WINAPI GetOutlineTextMetricsW(
1487 HDC hdc, /* [in] Handle of device context */
1488 UINT cbData, /* [in] Size of metric data array */
1489 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1491 DC *dc = get_dc_ptr( hdc );
1492 OUTLINETEXTMETRICW *output = lpOTM;
1495 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1499 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1502 output = HeapAlloc(GetProcessHeap(), 0, ret);
1503 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1506 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1507 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1509 #define WDPTOLP(x) ((x<0)? \
1510 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1511 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1512 #define HDPTOLP(y) ((y<0)? \
1513 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1514 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1516 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1517 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1518 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1519 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1520 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1521 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1522 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1523 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1524 output->otmAscent = HDPTOLP(output->otmAscent);
1525 output->otmDescent = HDPTOLP(output->otmDescent);
1526 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1527 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1528 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1529 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1530 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1531 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1532 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1533 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1534 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1535 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1536 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1537 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1538 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1539 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1540 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1541 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1542 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1543 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1544 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1545 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1546 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1547 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1550 if(output != lpOTM) {
1551 memcpy(lpOTM, output, cbData);
1552 HeapFree(GetProcessHeap(), 0, output);
1558 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1559 but really this should just be a return 0. */
1561 ret = sizeof(*lpOTM);
1566 memset(lpOTM, 0, ret);
1567 lpOTM->otmSize = sizeof(*lpOTM);
1568 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1570 Further fill of the structure not implemented,
1571 Needs real values for the structure members
1580 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1582 INT i, count = lastChar - firstChar + 1;
1589 switch (GdiGetCodePage(hdc))
1596 if (lastChar > 0xffff)
1598 if ((firstChar ^ lastChar) > 0xff)
1602 if (lastChar > 0xff)
1607 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1611 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1614 str[i++] = (BYTE)(c >> 8);
1624 /***********************************************************************
1625 * GetCharWidthW (GDI32.@)
1626 * GetCharWidth32W (GDI32.@)
1628 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1633 DC * dc = get_dc_ptr( hdc );
1634 if (!dc) return FALSE;
1637 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1640 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1641 ret = physdev->funcs->pGetCharWidth( physdev, firstChar, lastChar, buffer);
1646 /* convert device units to logical */
1647 for( i = firstChar; i <= lastChar; i++, buffer++ )
1648 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1651 release_dc_ptr( dc );
1656 /***********************************************************************
1657 * GetCharWidthA (GDI32.@)
1658 * GetCharWidth32A (GDI32.@)
1660 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1668 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1672 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1674 for(i = 0; i < wlen; i++)
1676 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1684 HeapFree(GetProcessHeap(), 0, str);
1685 HeapFree(GetProcessHeap(), 0, wstr);
1691 /***********************************************************************
1692 * ExtTextOutA (GDI32.@)
1696 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1697 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1705 if (flags & ETO_GLYPH_INDEX)
1706 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1708 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1711 unsigned int i = 0, j = 0;
1713 /* allocate enough for a ETO_PDY */
1714 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1716 if(IsDBCSLeadByteEx(codepage, str[i]))
1720 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1721 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1724 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1731 lpDxW[j++] = lpDx[i * 2];
1732 lpDxW[j++] = lpDx[i * 2 + 1];
1735 lpDxW[j++] = lpDx[i];
1741 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1743 HeapFree( GetProcessHeap(), 0, p );
1744 HeapFree( GetProcessHeap(), 0, lpDxW );
1749 /***********************************************************************
1750 * ExtTextOutW (GDI32.@)
1752 * Draws text using the currently selected font, background color, and text color.
1756 * x,y [I] coordinates of string
1758 * ETO_GRAYED - undocumented on MSDN
1759 * ETO_OPAQUE - use background color for fill the rectangle
1760 * ETO_CLIPPED - clipping text to the rectangle
1761 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1762 * than encoded characters. Implies ETO_IGNORELANGUAGE
1763 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1764 * Affects BiDi ordering
1765 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1766 * ETO_PDY - unimplemented
1767 * ETO_NUMERICSLATIN - unimplemented always assumed -
1768 * do not translate numbers into locale representations
1769 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1770 * lprect [I] dimensions for clipping or/and opaquing
1771 * str [I] text string
1772 * count [I] number of symbols in string
1773 * lpDx [I] optional parameter with distance between drawing characters
1779 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1780 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1783 LPWSTR reordered_str = (LPWSTR)str;
1784 WORD *glyphs = NULL;
1785 UINT align = GetTextAlign( hdc );
1786 DWORD layout = GetLayout( hdc );
1790 double cosEsc, sinEsc;
1794 BOOL done_extents = FALSE;
1795 POINT *deltas = NULL, width = {0, 0};
1797 DC * dc = get_dc_ptr( hdc );
1800 static int quietfixme = 0;
1802 if (!dc) return FALSE;
1804 breakRem = dc->breakRem;
1806 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1808 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1813 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1814 type = GetObjectType(hdc);
1815 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1817 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1818 release_dc_ptr( dc );
1823 flags &= ~ETO_CLIPPED;
1825 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1826 if (layout & LAYOUT_RTL)
1828 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1829 align ^= TA_RTLREADING;
1832 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1835 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1837 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1838 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1839 reordered_str, count, NULL, &glyphs, &cGlyphs);
1841 flags |= ETO_IGNORELANGUAGE;
1844 flags |= ETO_GLYPH_INDEX;
1845 if (cGlyphs != count)
1849 else if(flags & ETO_GLYPH_INDEX)
1850 glyphs = reordered_str;
1852 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1853 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1854 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1856 if(align & TA_UPDATECP)
1858 GetCurrentPositionEx( hdc, &pt );
1863 GetTextMetricsW(hdc, &tm);
1864 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1866 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1867 lf.lfEscapement = 0;
1869 if(lf.lfEscapement != 0)
1871 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1872 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1880 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1884 if(flags & ETO_GLYPH_INDEX)
1885 GetTextExtentPointI(hdc, glyphs, count, &sz);
1887 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1889 done_extents = TRUE;
1892 rc.right = x + sz.cx;
1893 rc.bottom = y + sz.cy;
1900 LPtoDP(hdc, (POINT*)&rc, 2);
1902 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1903 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1906 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1907 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1917 LPtoDP(hdc, &pt, 1);
1921 char_extra = GetTextCharacterExtra(hdc);
1922 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1926 POINT total = {0, 0}, desired[2];
1928 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1929 for(i = 0; i < count; i++)
1935 deltas[i].x = lpDx[i * 2] + char_extra;
1936 deltas[i].y = -lpDx[i * 2 + 1];
1940 deltas[i].x = lpDx[i] + char_extra;
1947 if(flags & ETO_GLYPH_INDEX)
1948 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1950 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1952 deltas[i].x = tmpsz.cx;
1956 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1958 deltas[i].x = deltas[i].x + dc->breakExtra;
1965 total.x += deltas[i].x;
1966 total.y += deltas[i].y;
1968 desired[0].x = desired[0].y = 0;
1970 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1971 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1973 LPtoDP(hdc, desired, 2);
1974 desired[1].x -= desired[0].x;
1975 desired[1].y -= desired[0].y;
1976 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1978 deltas[i].x = desired[1].x - width.x;
1979 deltas[i].y = desired[1].y - width.y;
1989 if(flags & ETO_GLYPH_INDEX)
1990 GetTextExtentPointI(hdc, glyphs, count, &sz);
1992 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1993 done_extents = TRUE;
1995 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1999 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2000 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2001 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2004 if (align & TA_UPDATECP)
2008 DPtoLP(hdc, &pt, 1);
2009 MoveToEx(hdc, pt.x, pt.y, NULL);
2021 if (align & TA_UPDATECP)
2025 DPtoLP(hdc, &pt, 1);
2026 MoveToEx(hdc, pt.x, pt.y, NULL);
2031 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2034 y += tm.tmAscent * cosEsc;
2035 x += tm.tmAscent * sinEsc;
2039 y -= tm.tmDescent * cosEsc;
2040 x -= tm.tmDescent * sinEsc;
2047 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2049 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2051 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2052 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2056 rc.right = x + width.x;
2057 rc.top = y - tm.tmAscent;
2058 rc.bottom = y + tm.tmDescent;
2060 if(flags & ETO_CLIPPED)
2062 rc.left = max(lprect->left, rc.left);
2063 rc.right = min(lprect->right, rc.right);
2064 rc.top = max(lprect->top, rc.top);
2065 rc.bottom = min(lprect->bottom, rc.bottom);
2067 if(rc.left < rc.right && rc.top < rc.bottom)
2068 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2073 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2075 HFONT orig_font = dc->hFont, cur_font;
2078 POINT *offsets = NULL;
2081 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2082 for(i = 0; i < count; i++)
2084 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2085 if(cur_font != dc->hFont)
2090 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2091 offsets[0].x = offsets[0].y = 0;
2096 for(j = 1; j < count; j++)
2098 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2099 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2105 for(j = 1; j < count; j++)
2107 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2108 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2114 if (PATH_IsPathOpen(dc->path))
2115 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2116 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2117 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2119 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2120 y + offsets[i - span].y,
2121 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2122 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2125 SelectObject(hdc, cur_font);
2127 glyphs[span++] = glyph;
2131 if (PATH_IsPathOpen(dc->path))
2132 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2133 y + (offsets ? offsets[count - span].y : 0),
2134 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2135 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2137 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2138 y + (offsets ? offsets[count - span].y : 0),
2139 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2140 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2141 SelectObject(hdc, orig_font);
2142 HeapFree(GetProcessHeap(), 0, offsets);
2148 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2150 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2151 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2152 flags |= ETO_GLYPH_INDEX;
2155 if (PATH_IsPathOpen(dc->path))
2156 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2157 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2159 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2160 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2164 HeapFree(GetProcessHeap(), 0, deltas);
2165 if(glyphs != reordered_str)
2166 HeapFree(GetProcessHeap(), 0, glyphs);
2167 if(reordered_str != str)
2168 HeapFree(GetProcessHeap(), 0, reordered_str);
2170 release_dc_ptr( dc );
2172 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2174 int underlinePos, strikeoutPos;
2175 int underlineWidth, strikeoutWidth;
2176 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2177 OUTLINETEXTMETRICW* otm = NULL;
2182 underlineWidth = tm.tmAscent / 20 + 1;
2183 strikeoutPos = tm.tmAscent / 2;
2184 strikeoutWidth = underlineWidth;
2188 otm = HeapAlloc(GetProcessHeap(), 0, size);
2189 GetOutlineTextMetricsW(hdc, size, otm);
2190 underlinePos = otm->otmsUnderscorePosition;
2191 underlineWidth = otm->otmsUnderscoreSize;
2192 strikeoutPos = otm->otmsStrikeoutPosition;
2193 strikeoutWidth = otm->otmsStrikeoutSize;
2194 HeapFree(GetProcessHeap(), 0, otm);
2197 if (PATH_IsPathOpen(dc->path))
2201 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2203 hbrush = SelectObject(hdc, hbrush);
2204 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2208 pts[0].x = x - underlinePos * sinEsc;
2209 pts[0].y = y - underlinePos * cosEsc;
2210 pts[1].x = x + width.x - underlinePos * sinEsc;
2211 pts[1].y = y + width.y - underlinePos * cosEsc;
2212 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2213 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2214 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2215 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2216 pts[4].x = pts[0].x;
2217 pts[4].y = pts[0].y;
2218 DPtoLP(hdc, pts, 5);
2219 Polygon(hdc, pts, 5);
2224 pts[0].x = x - strikeoutPos * sinEsc;
2225 pts[0].y = y - strikeoutPos * cosEsc;
2226 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2227 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2228 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2229 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2230 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2231 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2232 pts[4].x = pts[0].x;
2233 pts[4].y = pts[0].y;
2234 DPtoLP(hdc, pts, 5);
2235 Polygon(hdc, pts, 5);
2238 SelectObject(hdc, hpen);
2239 hbrush = SelectObject(hdc, hbrush);
2240 DeleteObject(hbrush);
2244 POINT pts[2], oldpt;
2249 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2250 hpen = SelectObject(hdc, hpen);
2253 pts[1].x = x + width.x;
2254 pts[1].y = y + width.y;
2255 DPtoLP(hdc, pts, 2);
2256 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2257 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2258 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2259 DeleteObject(SelectObject(hdc, hpen));
2264 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2265 hpen = SelectObject(hdc, hpen);
2268 pts[1].x = x + width.x;
2269 pts[1].y = y + width.y;
2270 DPtoLP(hdc, pts, 2);
2271 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2272 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2273 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2274 DeleteObject(SelectObject(hdc, hpen));
2283 /***********************************************************************
2284 * TextOutA (GDI32.@)
2286 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2288 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2292 /***********************************************************************
2293 * TextOutW (GDI32.@)
2295 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2297 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2301 /***********************************************************************
2302 * PolyTextOutA (GDI32.@)
2306 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2308 for (; cStrings>0; cStrings--, pptxt++)
2309 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2316 /***********************************************************************
2317 * PolyTextOutW (GDI32.@)
2319 * Draw several Strings
2325 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2327 for (; cStrings>0; cStrings--, pptxt++)
2328 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2334 /***********************************************************************
2335 * SetMapperFlags (GDI32.@)
2337 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2339 DC *dc = get_dc_ptr( hdc );
2340 DWORD ret = GDI_ERROR;
2344 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2345 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2346 if (flags != GDI_ERROR)
2348 ret = dc->mapperFlags;
2349 dc->mapperFlags = flags;
2351 release_dc_ptr( dc );
2356 /***********************************************************************
2357 * GetAspectRatioFilterEx (GDI32.@)
2359 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2361 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2366 /***********************************************************************
2367 * GetCharABCWidthsA (GDI32.@)
2369 * See GetCharABCWidthsW.
2371 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2379 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2383 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2386 HeapFree(GetProcessHeap(), 0, str);
2390 for(i = 0; i < wlen; i++)
2392 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2400 HeapFree(GetProcessHeap(), 0, str);
2401 HeapFree(GetProcessHeap(), 0, wstr);
2407 /******************************************************************************
2408 * GetCharABCWidthsW [GDI32.@]
2410 * Retrieves widths of characters in range.
2413 * hdc [I] Handle of device context
2414 * firstChar [I] First character in range to query
2415 * lastChar [I] Last character in range to query
2416 * abc [O] Address of character-width structure
2419 * Only works with TrueType fonts
2425 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2428 DC *dc = get_dc_ptr(hdc);
2432 if (!dc) return FALSE;
2436 release_dc_ptr( dc );
2441 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2447 /* convert device units to logical */
2448 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2449 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2450 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2451 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2456 release_dc_ptr( dc );
2461 /******************************************************************************
2462 * GetCharABCWidthsI [GDI32.@]
2464 * Retrieves widths of characters in range.
2467 * hdc [I] Handle of device context
2468 * firstChar [I] First glyphs in range to query
2469 * count [I] Last glyphs in range to query
2470 * pgi [i] Array of glyphs to query
2471 * abc [O] Address of character-width structure
2474 * Only works with TrueType fonts
2480 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2481 LPWORD pgi, LPABC abc)
2483 DC *dc = get_dc_ptr(hdc);
2487 if (!dc) return FALSE;
2491 release_dc_ptr( dc );
2496 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2502 /* convert device units to logical */
2503 for( i = 0; i < count; i++, abc++ ) {
2504 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2505 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2506 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2511 release_dc_ptr( dc );
2516 /***********************************************************************
2517 * GetGlyphOutlineA (GDI32.@)
2519 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2520 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2521 LPVOID lpBuffer, const MAT2 *lpmat2 )
2523 if (!lpmat2) return GDI_ERROR;
2525 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2530 cp = GdiGetCodePage(hdc);
2531 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2533 mbchs[0] = (uChar & 0xff00) >> 8;
2534 mbchs[1] = (uChar & 0xff);
2537 mbchs[0] = (uChar & 0xff);
2540 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2543 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2547 /***********************************************************************
2548 * GetGlyphOutlineW (GDI32.@)
2550 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2551 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2552 LPVOID lpBuffer, const MAT2 *lpmat2 )
2557 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2558 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2560 if (!lpmat2) return GDI_ERROR;
2562 dc = get_dc_ptr(hdc);
2563 if(!dc) return GDI_ERROR;
2566 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2567 cbBuffer, lpBuffer, lpmat2);
2571 release_dc_ptr( dc );
2576 /***********************************************************************
2577 * CreateScalableFontResourceA (GDI32.@)
2579 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2580 LPCSTR lpszResourceFile,
2581 LPCSTR lpszFontFile,
2582 LPCSTR lpszCurrentPath )
2584 LPWSTR lpszResourceFileW = NULL;
2585 LPWSTR lpszFontFileW = NULL;
2586 LPWSTR lpszCurrentPathW = NULL;
2590 if (lpszResourceFile)
2592 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2593 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2594 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2599 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2600 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2601 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2604 if (lpszCurrentPath)
2606 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2607 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2608 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2611 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2612 lpszFontFileW, lpszCurrentPathW);
2614 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2615 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2616 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2621 /***********************************************************************
2622 * CreateScalableFontResourceW (GDI32.@)
2624 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2625 LPCWSTR lpszResourceFile,
2626 LPCWSTR lpszFontFile,
2627 LPCWSTR lpszCurrentPath )
2630 FIXME("(%d,%s,%s,%s): stub\n",
2631 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2632 debugstr_w(lpszCurrentPath) );
2634 /* fHidden=1 - only visible for the calling app, read-only, not
2635 * enumerated with EnumFonts/EnumFontFamilies
2636 * lpszCurrentPath can be NULL
2639 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2640 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2642 SetLastError(ERROR_FILE_EXISTS);
2645 return FALSE; /* create failed */
2648 /*************************************************************************
2649 * GetKerningPairsA (GDI32.@)
2651 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2652 LPKERNINGPAIR kern_pairA )
2656 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2657 KERNINGPAIR *kern_pairW;
2659 if (!cPairs && kern_pairA)
2661 SetLastError(ERROR_INVALID_PARAMETER);
2665 cp = GdiGetCodePage(hDC);
2667 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2668 * to fail on an invalid character for CP_SYMBOL.
2670 cpi.DefaultChar[0] = 0;
2671 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2673 FIXME("Can't find codepage %u info\n", cp);
2677 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2678 if (!total_kern_pairs) return 0;
2680 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2681 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2683 for (i = 0; i < total_kern_pairs; i++)
2687 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2690 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2693 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2698 if (kern_pairs_copied >= cPairs) break;
2700 kern_pairA->wFirst = (BYTE)first;
2701 kern_pairA->wSecond = (BYTE)second;
2702 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2705 kern_pairs_copied++;
2708 HeapFree(GetProcessHeap(), 0, kern_pairW);
2710 return kern_pairs_copied;
2713 /*************************************************************************
2714 * GetKerningPairsW (GDI32.@)
2716 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2717 LPKERNINGPAIR lpKerningPairs )
2722 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2724 if (!cPairs && lpKerningPairs)
2726 SetLastError(ERROR_INVALID_PARAMETER);
2730 dc = get_dc_ptr(hDC);
2734 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2736 release_dc_ptr( dc );
2740 /*************************************************************************
2741 * TranslateCharsetInfo [GDI32.@]
2743 * Fills a CHARSETINFO structure for a character set, code page, or
2744 * font. This allows making the correspondence between different labels
2745 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2746 * of the same encoding.
2748 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2749 * only one codepage should be set in *lpSrc.
2752 * TRUE on success, FALSE on failure.
2755 BOOL WINAPI TranslateCharsetInfo(
2756 LPDWORD lpSrc, /* [in]
2757 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2758 if flags == TCI_SRCCHARSET: a character set value
2759 if flags == TCI_SRCCODEPAGE: a code page value
2761 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2762 DWORD flags /* [in] determines interpretation of lpSrc */)
2766 case TCI_SRCFONTSIG:
2767 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2769 case TCI_SRCCODEPAGE:
2770 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2772 case TCI_SRCCHARSET:
2773 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2778 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2779 *lpCs = FONT_tci[index];
2783 /*************************************************************************
2784 * GetFontLanguageInfo (GDI32.@)
2786 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2788 FONTSIGNATURE fontsig;
2789 static const DWORD GCP_DBCS_MASK=0x003F0000,
2790 GCP_DIACRITIC_MASK=0x00000000,
2791 FLI_GLYPHS_MASK=0x00000000,
2792 GCP_GLYPHSHAPE_MASK=0x00000040,
2793 GCP_KASHIDA_MASK=0x00000000,
2794 GCP_LIGATE_MASK=0x00000000,
2795 GCP_USEKERNING_MASK=0x00000000,
2796 GCP_REORDER_MASK=0x00000060;
2800 GetTextCharsetInfo( hdc, &fontsig, 0 );
2801 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2803 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2806 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2807 result|=GCP_DIACRITIC;
2809 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2812 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2813 result|=GCP_GLYPHSHAPE;
2815 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2816 result|=GCP_KASHIDA;
2818 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2821 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2822 result|=GCP_USEKERNING;
2824 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2825 if( GetTextAlign( hdc) & TA_RTLREADING )
2826 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2827 result|=GCP_REORDER;
2833 /*************************************************************************
2834 * GetFontData [GDI32.@]
2836 * Retrieve data for TrueType font.
2840 * success: Number of bytes returned
2841 * failure: GDI_ERROR
2845 * Calls SetLastError()
2848 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2849 LPVOID buffer, DWORD length)
2851 DC *dc = get_dc_ptr(hdc);
2852 DWORD ret = GDI_ERROR;
2854 if(!dc) return GDI_ERROR;
2857 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2859 release_dc_ptr( dc );
2863 /*************************************************************************
2864 * GetGlyphIndicesA [GDI32.@]
2866 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2867 LPWORD pgi, DWORD flags)
2873 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2874 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2876 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2877 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2878 HeapFree(GetProcessHeap(), 0, lpstrW);
2883 /*************************************************************************
2884 * GetGlyphIndicesW [GDI32.@]
2886 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2887 LPWORD pgi, DWORD flags)
2889 DC *dc = get_dc_ptr(hdc);
2890 DWORD ret = GDI_ERROR;
2892 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2893 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2895 if(!dc) return GDI_ERROR;
2898 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2900 release_dc_ptr( dc );
2904 /*************************************************************************
2905 * GetCharacterPlacementA [GDI32.@]
2907 * See GetCharacterPlacementW.
2910 * the web browser control of ie4 calls this with dwFlags=0
2913 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2914 INT nMaxExtent, GCP_RESULTSA *lpResults,
2919 GCP_RESULTSW resultsW;
2923 TRACE("%s, %d, %d, 0x%08x\n",
2924 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2926 /* both structs are equal in size */
2927 memcpy(&resultsW, lpResults, sizeof(resultsW));
2929 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2930 if(lpResults->lpOutString)
2931 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2933 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2935 lpResults->nGlyphs = resultsW.nGlyphs;
2936 lpResults->nMaxFit = resultsW.nMaxFit;
2938 if(lpResults->lpOutString) {
2939 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2940 lpResults->lpOutString, uCount, NULL, NULL );
2943 HeapFree(GetProcessHeap(), 0, lpStringW);
2944 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2949 /*************************************************************************
2950 * GetCharacterPlacementW [GDI32.@]
2952 * Retrieve information about a string. This includes the width, reordering,
2953 * Glyphing and so on.
2957 * The width and height of the string if successful, 0 if failed.
2961 * All flags except GCP_REORDER are not yet implemented.
2962 * Reordering is not 100% compliant to the Windows BiDi method.
2963 * Caret positioning is not yet implemented for BiDi.
2964 * Classes are not yet implemented.
2968 GetCharacterPlacementW(
2969 HDC hdc, /* [in] Device context for which the rendering is to be done */
2970 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2971 INT uCount, /* [in] Number of WORDS in string. */
2972 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2973 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2974 DWORD dwFlags /* [in] Flags specifying how to process the string */
2981 TRACE("%s, %d, %d, 0x%08x\n",
2982 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2984 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2985 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2986 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2987 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2988 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2990 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2991 if(lpResults->lpClass) FIXME("classes not implemented\n");
2992 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2993 FIXME("Caret positions for complex scripts not implemented\n");
2995 nSet = (UINT)uCount;
2996 if(nSet > lpResults->nGlyphs)
2997 nSet = lpResults->nGlyphs;
2999 /* return number of initialized fields */
3000 lpResults->nGlyphs = nSet;
3002 if((dwFlags&GCP_REORDER)==0 )
3004 /* Treat the case where no special handling was requested in a fastpath way */
3005 /* copy will do if the GCP_REORDER flag is not set */
3006 if(lpResults->lpOutString)
3007 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3009 if(lpResults->lpOrder)
3011 for(i = 0; i < nSet; i++)
3012 lpResults->lpOrder[i] = i;
3016 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3017 nSet, lpResults->lpOrder, NULL, NULL );
3020 /* FIXME: Will use the placement chars */
3021 if (lpResults->lpDx)
3024 for (i = 0; i < nSet; i++)
3026 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3027 lpResults->lpDx[i]= c;
3031 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3035 lpResults->lpCaretPos[0] = 0;
3036 for (i = 1; i < nSet; i++)
3037 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3038 lpResults->lpCaretPos[i] = (pos += size.cx);
3041 if(lpResults->lpGlyphs)
3042 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3044 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3045 ret = MAKELONG(size.cx, size.cy);
3050 /*************************************************************************
3051 * GetCharABCWidthsFloatA [GDI32.@]
3053 * See GetCharABCWidthsFloatW.
3055 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3062 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3066 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3068 for (i = 0; i < wlen; i++)
3070 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3078 HeapFree( GetProcessHeap(), 0, str );
3079 HeapFree( GetProcessHeap(), 0, wstr );
3084 /*************************************************************************
3085 * GetCharABCWidthsFloatW [GDI32.@]
3087 * Retrieves widths of a range of characters.
3090 * hdc [I] Handle to device context.
3091 * first [I] First character in range to query.
3092 * last [I] Last character in range to query.
3093 * abcf [O] Array of LPABCFLOAT structures.
3099 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3103 DC *dc = get_dc_ptr( hdc );
3105 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3107 if (!dc) return FALSE;
3111 release_dc_ptr( dc );
3116 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3122 /* convert device units to logical */
3123 for (i = first; i <= last; i++, abcf++)
3125 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3126 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3127 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3131 release_dc_ptr( dc );
3135 /*************************************************************************
3136 * GetCharWidthFloatA [GDI32.@]
3138 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3139 UINT iLastChar, PFLOAT pxBuffer)
3141 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3145 /*************************************************************************
3146 * GetCharWidthFloatW [GDI32.@]
3148 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3149 UINT iLastChar, PFLOAT pxBuffer)
3151 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3156 /***********************************************************************
3158 * Font Resource API *
3160 ***********************************************************************/
3162 /***********************************************************************
3163 * AddFontResourceA (GDI32.@)
3165 INT WINAPI AddFontResourceA( LPCSTR str )
3167 return AddFontResourceExA( str, 0, NULL);
3170 /***********************************************************************
3171 * AddFontResourceW (GDI32.@)
3173 INT WINAPI AddFontResourceW( LPCWSTR str )
3175 return AddFontResourceExW(str, 0, NULL);
3179 /***********************************************************************
3180 * AddFontResourceExA (GDI32.@)
3182 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3184 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3185 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3188 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3189 ret = AddFontResourceExW(strW, fl, pdv);
3190 HeapFree(GetProcessHeap(), 0, strW);
3194 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3196 HRSRC rsrc = FindResourceW(hModule, name, type);
3197 HGLOBAL hMem = LoadResource(hModule, rsrc);
3198 LPVOID *pMem = LockResource(hMem);
3199 int *num_total = (int *)lParam;
3202 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3203 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3205 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3209 *num_total += num_in_res;
3213 /***********************************************************************
3214 * AddFontResourceExW (GDI32.@)
3216 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3218 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3221 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3222 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3223 if (hModule != NULL)
3225 int num_resources = 0;
3226 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3228 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3229 wine_dbgstr_w(str));
3230 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3231 ret = num_resources;
3232 FreeLibrary(hModule);
3238 /***********************************************************************
3239 * RemoveFontResourceA (GDI32.@)
3241 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3243 return RemoveFontResourceExA(str, 0, 0);
3246 /***********************************************************************
3247 * RemoveFontResourceW (GDI32.@)
3249 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3251 return RemoveFontResourceExW(str, 0, 0);
3254 /***********************************************************************
3255 * AddFontMemResourceEx (GDI32.@)
3257 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3262 if (!pbFont || !cbFont || !pcFonts)
3264 SetLastError(ERROR_INVALID_PARAMETER);
3268 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3273 *pcFonts = num_fonts;
3277 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3278 RemoveFontMemResourceEx(ret);
3286 /***********************************************************************
3287 * RemoveFontMemResourceEx (GDI32.@)
3289 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3291 FIXME("(%p) stub\n", fh);
3295 /***********************************************************************
3296 * RemoveFontResourceExA (GDI32.@)
3298 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3300 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3301 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3304 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3305 ret = RemoveFontResourceExW(strW, fl, pdv);
3306 HeapFree(GetProcessHeap(), 0, strW);
3310 /***********************************************************************
3311 * RemoveFontResourceExW (GDI32.@)
3313 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3315 return WineEngRemoveFontResourceEx(str, fl, pdv);
3318 /***********************************************************************
3319 * GetTextCharset (GDI32.@)
3321 UINT WINAPI GetTextCharset(HDC hdc)
3323 /* MSDN docs say this is equivalent */
3324 return GetTextCharsetInfo(hdc, NULL, 0);
3327 /***********************************************************************
3328 * GetTextCharsetInfo (GDI32.@)
3330 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3332 UINT ret = DEFAULT_CHARSET;
3333 DC *dc = get_dc_ptr(hdc);
3338 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3340 release_dc_ptr( dc );
3343 if (ret == DEFAULT_CHARSET && fs)
3344 memset(fs, 0, sizeof(FONTSIGNATURE));
3348 /***********************************************************************
3349 * GdiGetCharDimensions (GDI32.@)
3351 * Gets the average width of the characters in the English alphabet.
3354 * hdc [I] Handle to the device context to measure on.
3355 * lptm [O] Pointer to memory to store the text metrics into.
3356 * height [O] On exit, the maximum height of characters in the English alphabet.
3359 * The average width of characters in the English alphabet.
3362 * This function is used by the dialog manager to get the size of a dialog
3363 * unit. It should also be used by other pieces of code that need to know
3364 * the size of a dialog unit in logical units without having access to the
3365 * window handle of the dialog.
3366 * Windows caches the font metrics from this function, but we don't and
3367 * there doesn't appear to be an immediate advantage to do so.
3370 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3372 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3375 static const WCHAR alphabet[] = {
3376 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3377 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3378 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3380 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3382 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3384 if (height) *height = sz.cy;
3385 return (sz.cx / 26 + 1) / 2;
3388 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3390 FIXME("(%d): stub\n", fEnableEUDC);
3394 /***********************************************************************
3395 * GetCharWidthI (GDI32.@)
3397 * Retrieve widths of characters.
3400 * hdc [I] Handle to a device context.
3401 * first [I] First glyph in range to query.
3402 * count [I] Number of glyph indices to query.
3403 * glyphs [I] Array of glyphs to query.
3404 * buffer [O] Buffer to receive character widths.
3407 * Only works with TrueType fonts.
3413 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3418 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3420 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3423 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3425 HeapFree(GetProcessHeap(), 0, abc);
3429 for (i = 0; i < count; i++)
3430 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3432 HeapFree(GetProcessHeap(), 0, abc);
3436 /***********************************************************************
3437 * GetFontUnicodeRanges (GDI32.@)
3439 * Retrieve a list of supported Unicode characters in a font.
3442 * hdc [I] Handle to a device context.
3443 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3446 * Success: Number of bytes written to the buffer pointed to by lpgs.
3450 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3453 DC *dc = get_dc_ptr(hdc);
3455 TRACE("(%p, %p)\n", hdc, lpgs);
3459 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3465 /*************************************************************
3466 * FontIsLinked (GDI32.@)
3468 BOOL WINAPI FontIsLinked(HDC hdc)
3470 DC *dc = get_dc_ptr(hdc);
3473 if (!dc) return FALSE;
3474 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3476 TRACE("returning %d\n", ret);
3480 /*************************************************************
3481 * GdiRealizationInfo (GDI32.@)
3483 * Returns a structure that contains some font information.
3485 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3487 DC *dc = get_dc_ptr(hdc);
3490 if (!dc) return FALSE;
3491 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);