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;
681 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
688 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
689 fe32.dwFlags &= ~ENUM_CALLED;
690 if (ret && dc->funcs->pEnumDeviceFonts) {
691 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
692 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
696 release_dc_ptr( dc );
700 /***********************************************************************
701 * EnumFontFamiliesExW (GDI32.@)
703 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
704 FONTENUMPROCW efproc,
705 LPARAM lParam, DWORD dwFlags )
707 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
710 /***********************************************************************
711 * EnumFontFamiliesExA (GDI32.@)
713 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
714 FONTENUMPROCA efproc,
715 LPARAM lParam, DWORD dwFlags)
721 FONT_LogFontAToW( plf, &lfW );
726 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
729 /***********************************************************************
730 * EnumFontFamiliesA (GDI32.@)
732 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
733 FONTENUMPROCA efproc, LPARAM lpData )
739 if (!*lpFamily) return 1;
740 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
741 lf.lfCharSet = DEFAULT_CHARSET;
742 lf.lfPitchAndFamily = 0;
747 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
750 /***********************************************************************
751 * EnumFontFamiliesW (GDI32.@)
753 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
754 FONTENUMPROCW efproc, LPARAM lpData )
760 if (!*lpFamily) return 1;
761 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
762 lf.lfCharSet = DEFAULT_CHARSET;
763 lf.lfPitchAndFamily = 0;
768 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
771 /***********************************************************************
772 * EnumFontsA (GDI32.@)
774 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
777 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
780 /***********************************************************************
781 * EnumFontsW (GDI32.@)
783 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
786 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
790 /***********************************************************************
791 * GetTextCharacterExtra (GDI32.@)
793 INT WINAPI GetTextCharacterExtra( HDC hdc )
796 DC *dc = get_dc_ptr( hdc );
797 if (!dc) return 0x80000000;
799 release_dc_ptr( dc );
804 /***********************************************************************
805 * SetTextCharacterExtra (GDI32.@)
807 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
809 INT ret = 0x80000000;
810 DC * dc = get_dc_ptr( hdc );
814 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
815 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
816 if (extra != 0x80000000)
819 dc->charExtra = extra;
821 release_dc_ptr( dc );
827 /***********************************************************************
828 * SetTextJustification (GDI32.@)
830 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
834 DC * dc = get_dc_ptr( hdc );
836 if (!dc) return FALSE;
838 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
839 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
842 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
843 if (!extra) breaks = 0;
846 dc->breakExtra = extra / breaks;
847 dc->breakRem = extra - (breaks * dc->breakExtra);
855 release_dc_ptr( dc );
860 /***********************************************************************
861 * GetTextFaceA (GDI32.@)
863 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
865 INT res = GetTextFaceW(hdc, 0, NULL);
866 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
867 GetTextFaceW( hdc, res, nameW );
873 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
877 /* GetTextFaceA does NOT include the nul byte in the return count. */
884 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
885 HeapFree( GetProcessHeap(), 0, nameW );
889 /***********************************************************************
890 * GetTextFaceW (GDI32.@)
892 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
897 DC * dc = get_dc_ptr( hdc );
901 ret = WineEngGetTextFace(dc->gdiFont, count, name);
902 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
904 INT n = strlenW(font->logfont.lfFaceName) + 1;
907 lstrcpynW( name, font->logfont.lfFaceName, count );
911 GDI_ReleaseObj( dc->hFont );
913 release_dc_ptr( dc );
918 /***********************************************************************
919 * GetTextExtentPoint32A (GDI32.@)
921 * See GetTextExtentPoint32W.
923 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
928 LPWSTR 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 )
983 DC * dc = get_dc_ptr( hdc );
984 if (!dc) return FALSE;
987 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
988 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
989 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
990 size->cx += count * dc->charExtra;
992 else if(dc->funcs->pGetTextExtentExPoint) {
993 FIXME("calling GetTextExtentExPoint\n");
994 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, indices, count,
995 max_ext, nfit, dxs, size );
998 release_dc_ptr( dc );
1000 TRACE("(%p %p %d %p): returning %d x %d\n",
1001 hdc, indices, count, size, size->cx, size->cy );
1005 /***********************************************************************
1006 * GetTextExtentPointI [GDI32.@]
1008 * Computes width and height of the array of glyph indices.
1011 * hdc [I] Handle of device context.
1012 * indices [I] Glyph index array.
1013 * count [I] Number of glyphs in array.
1014 * size [O] Returned string size.
1020 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1022 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1026 /***********************************************************************
1027 * GetTextExtentPointA (GDI32.@)
1029 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1032 TRACE("not bug compatible.\n");
1033 return GetTextExtentPoint32A( hdc, str, count, size );
1036 /***********************************************************************
1037 * GetTextExtentPointW (GDI32.@)
1039 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1042 TRACE("not bug compatible.\n");
1043 return GetTextExtentPoint32W( hdc, str, count, size );
1047 /***********************************************************************
1048 * GetTextExtentExPointA (GDI32.@)
1050 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1051 INT maxExt, LPINT lpnFit,
1052 LPINT alpDx, LPSIZE size )
1060 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1063 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1064 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1067 INT n = lpnFit ? *lpnFit : wlen;
1069 for(i = 0, j = 0; i < n; i++, j++)
1071 alpDx[j] = walpDx[i];
1072 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1075 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1076 HeapFree( GetProcessHeap(), 0, p );
1077 HeapFree( GetProcessHeap(), 0, walpDx );
1082 /***********************************************************************
1083 * GetTextExtentExPointW (GDI32.@)
1085 * Return the size of the string as it would be if it was output properly by
1088 * This should include
1089 * - Intercharacter spacing
1090 * - justification spacing (not yet done)
1091 * - kerning? see below
1093 * Kerning. Since kerning would be carried out by the rendering code it should
1094 * be done by the driver. However they don't support it yet. Also I am not
1095 * yet persuaded that (certainly under Win95) any kerning is actually done.
1097 * str: According to MSDN this should be null-terminated. That is not true; a
1098 * null will not terminate it early.
1099 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1100 * than count. I have seen it be either the size of the full string or
1101 * 1 less than the size of the full string. I have not seen it bear any
1102 * resemblance to the portion that would fit.
1103 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1104 * trailing intercharacter spacing and any trailing justification.
1107 * Currently we do this by measuring each character etc. We should do it by
1108 * passing the request to the driver, perhaps by extending the
1109 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1110 * thinking about kerning issues and rounding issues in the justification.
1113 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1114 INT maxExt, LPINT lpnFit,
1115 LPINT alpDx, LPSIZE size )
1123 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1125 dc = get_dc_ptr(hdc);
1129 GetTextMetricsW(hdc, &tm);
1131 /* If we need to calculate nFit, then we need the partial extents even if
1132 the user hasn't provided us with an array. */
1135 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1139 SetLastError(ERROR_OUTOFMEMORY);
1147 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1148 0, NULL, dxs, size);
1149 else if (dc->funcs->pGetTextExtentExPoint)
1150 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1151 0, NULL, dxs, size);
1153 /* Perform device size to world size transformations. */
1156 INT extra = dc->charExtra,
1157 breakExtra = dc->breakExtra,
1158 breakRem = dc->breakRem,
1163 for (i = 0; i < count; ++i)
1165 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1166 dxs[i] += (i+1) * extra;
1167 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1169 dxs[i] += breakExtra;
1176 if (dxs[i] <= maxExt)
1179 breakRem = dc->breakRem;
1181 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1182 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1184 if (!dxs && count > 1 && (breakExtra || breakRem))
1186 for (i = 0; i < count; i++)
1188 if (str[i] == tm.tmBreakChar)
1190 size->cx += breakExtra;
1205 HeapFree(GetProcessHeap(), 0, dxs);
1207 release_dc_ptr( dc );
1209 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1213 /***********************************************************************
1214 * GetTextMetricsA (GDI32.@)
1216 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1220 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1221 FONT_TextMetricWToA( &tm32, metrics );
1225 /***********************************************************************
1226 * GetTextMetricsW (GDI32.@)
1228 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1231 DC * dc = get_dc_ptr( hdc );
1232 if (!dc) return FALSE;
1235 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1236 else if (dc->funcs->pGetTextMetrics)
1237 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1241 /* device layer returns values in device units
1242 * therefore we have to convert them to logical */
1244 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1245 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1247 #define WDPTOLP(x) ((x<0)? \
1248 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1249 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1250 #define HDPTOLP(y) ((y<0)? \
1251 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1252 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1254 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1255 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1256 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1257 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1258 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1259 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1260 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1261 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1265 TRACE("text metrics:\n"
1266 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1267 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1268 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1269 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1270 " PitchAndFamily = %02x\n"
1271 " --------------------\n"
1272 " InternalLeading = %i\n"
1276 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1277 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1278 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1279 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1280 metrics->tmPitchAndFamily,
1281 metrics->tmInternalLeading,
1284 metrics->tmHeight );
1286 release_dc_ptr( dc );
1291 /***********************************************************************
1292 * GetOutlineTextMetricsA (GDI32.@)
1293 * Gets metrics for TrueType fonts.
1296 * If the supplied buffer isn't big enough Windows partially fills it up to
1297 * its given length and returns that length.
1300 * Success: Non-zero or size of required buffer
1303 UINT WINAPI GetOutlineTextMetricsA(
1304 HDC hdc, /* [in] Handle of device context */
1305 UINT cbData, /* [in] Size of metric data array */
1306 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1308 char buf[512], *ptr;
1310 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1311 OUTLINETEXTMETRICA *output = lpOTM;
1314 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1316 if(ret > sizeof(buf))
1317 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1318 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1320 needed = sizeof(OUTLINETEXTMETRICA);
1321 if(lpOTMW->otmpFamilyName)
1322 needed += WideCharToMultiByte(CP_ACP, 0,
1323 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1324 NULL, 0, NULL, NULL);
1325 if(lpOTMW->otmpFaceName)
1326 needed += WideCharToMultiByte(CP_ACP, 0,
1327 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1328 NULL, 0, NULL, NULL);
1329 if(lpOTMW->otmpStyleName)
1330 needed += WideCharToMultiByte(CP_ACP, 0,
1331 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1332 NULL, 0, NULL, NULL);
1333 if(lpOTMW->otmpFullName)
1334 needed += WideCharToMultiByte(CP_ACP, 0,
1335 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1336 NULL, 0, NULL, NULL);
1343 TRACE("needed = %d\n", needed);
1345 /* Since the supplied buffer isn't big enough, we'll alloc one
1346 that is and memcpy the first cbData bytes into the lpOTM at
1348 output = HeapAlloc(GetProcessHeap(), 0, needed);
1350 ret = output->otmSize = min(needed, cbData);
1351 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1352 output->otmFiller = 0;
1353 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1354 output->otmfsSelection = lpOTMW->otmfsSelection;
1355 output->otmfsType = lpOTMW->otmfsType;
1356 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1357 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1358 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1359 output->otmEMSquare = lpOTMW->otmEMSquare;
1360 output->otmAscent = lpOTMW->otmAscent;
1361 output->otmDescent = lpOTMW->otmDescent;
1362 output->otmLineGap = lpOTMW->otmLineGap;
1363 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1364 output->otmsXHeight = lpOTMW->otmsXHeight;
1365 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1366 output->otmMacAscent = lpOTMW->otmMacAscent;
1367 output->otmMacDescent = lpOTMW->otmMacDescent;
1368 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1369 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1370 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1371 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1372 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1373 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1374 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1375 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1376 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1377 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1380 ptr = (char*)(output + 1);
1381 left = needed - sizeof(*output);
1383 if(lpOTMW->otmpFamilyName) {
1384 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1385 len = WideCharToMultiByte(CP_ACP, 0,
1386 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1387 ptr, left, NULL, NULL);
1391 output->otmpFamilyName = 0;
1393 if(lpOTMW->otmpFaceName) {
1394 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1395 len = WideCharToMultiByte(CP_ACP, 0,
1396 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1397 ptr, left, NULL, NULL);
1401 output->otmpFaceName = 0;
1403 if(lpOTMW->otmpStyleName) {
1404 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1405 len = WideCharToMultiByte(CP_ACP, 0,
1406 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1407 ptr, left, NULL, NULL);
1411 output->otmpStyleName = 0;
1413 if(lpOTMW->otmpFullName) {
1414 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1415 len = WideCharToMultiByte(CP_ACP, 0,
1416 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1417 ptr, left, NULL, NULL);
1420 output->otmpFullName = 0;
1424 if(output != lpOTM) {
1425 memcpy(lpOTM, output, cbData);
1426 HeapFree(GetProcessHeap(), 0, output);
1428 /* check if the string offsets really fit into the provided size */
1429 /* FIXME: should we check string length as well? */
1430 /* make sure that we don't read/write beyond the provided buffer */
1431 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1433 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1434 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1437 /* make sure that we don't read/write beyond the provided buffer */
1438 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1440 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1441 lpOTM->otmpFaceName = 0; /* doesn't fit */
1444 /* make sure that we don't read/write beyond the provided buffer */
1445 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1447 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1448 lpOTM->otmpStyleName = 0; /* doesn't fit */
1451 /* make sure that we don't read/write beyond the provided buffer */
1452 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1454 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1455 lpOTM->otmpFullName = 0; /* doesn't fit */
1460 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1461 HeapFree(GetProcessHeap(), 0, lpOTMW);
1467 /***********************************************************************
1468 * GetOutlineTextMetricsW [GDI32.@]
1470 UINT WINAPI GetOutlineTextMetricsW(
1471 HDC hdc, /* [in] Handle of device context */
1472 UINT cbData, /* [in] Size of metric data array */
1473 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1475 DC *dc = get_dc_ptr( hdc );
1476 OUTLINETEXTMETRICW *output = lpOTM;
1479 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1483 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1486 output = HeapAlloc(GetProcessHeap(), 0, ret);
1487 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1490 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1491 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1493 #define WDPTOLP(x) ((x<0)? \
1494 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1495 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1496 #define HDPTOLP(y) ((y<0)? \
1497 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1498 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1500 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1501 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1502 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1503 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1504 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1505 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1506 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1507 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1508 output->otmAscent = HDPTOLP(output->otmAscent);
1509 output->otmDescent = HDPTOLP(output->otmDescent);
1510 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1511 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1512 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1513 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1514 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1515 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1516 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1517 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1518 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1519 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1520 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1521 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1522 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1523 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1524 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1525 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1526 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1527 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1528 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1529 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1530 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1531 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1534 if(output != lpOTM) {
1535 memcpy(lpOTM, output, cbData);
1536 HeapFree(GetProcessHeap(), 0, output);
1542 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1543 but really this should just be a return 0. */
1545 ret = sizeof(*lpOTM);
1550 memset(lpOTM, 0, ret);
1551 lpOTM->otmSize = sizeof(*lpOTM);
1552 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1554 Further fill of the structure not implemented,
1555 Needs real values for the structure members
1564 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1566 INT i, count = lastChar - firstChar + 1;
1573 switch (GdiGetCodePage(hdc))
1580 if (lastChar > 0xffff)
1582 if ((firstChar ^ lastChar) > 0xff)
1586 if (lastChar > 0xff)
1591 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1595 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1598 str[i++] = (BYTE)(c >> 8);
1608 /***********************************************************************
1609 * GetCharWidthW (GDI32.@)
1610 * GetCharWidth32W (GDI32.@)
1612 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1617 DC * dc = get_dc_ptr( hdc );
1618 if (!dc) return FALSE;
1621 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1622 else if (dc->funcs->pGetCharWidth)
1623 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1627 /* convert device units to logical */
1628 for( i = firstChar; i <= lastChar; i++, buffer++ )
1629 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1632 release_dc_ptr( dc );
1637 /***********************************************************************
1638 * GetCharWidthA (GDI32.@)
1639 * GetCharWidth32A (GDI32.@)
1641 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1649 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1653 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1655 for(i = 0; i < wlen; i++)
1657 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1665 HeapFree(GetProcessHeap(), 0, str);
1666 HeapFree(GetProcessHeap(), 0, wstr);
1672 /***********************************************************************
1673 * ExtTextOutA (GDI32.@)
1677 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1678 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1686 if (flags & ETO_GLYPH_INDEX)
1687 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1689 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1692 unsigned int i = 0, j = 0;
1694 /* allocate enough for a ETO_PDY */
1695 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1697 if(IsDBCSLeadByteEx(codepage, str[i]))
1701 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1702 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1705 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1712 lpDxW[j++] = lpDx[i * 2];
1713 lpDxW[j++] = lpDx[i * 2 + 1];
1716 lpDxW[j++] = lpDx[i];
1722 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1724 HeapFree( GetProcessHeap(), 0, p );
1725 HeapFree( GetProcessHeap(), 0, lpDxW );
1730 /***********************************************************************
1731 * ExtTextOutW (GDI32.@)
1733 * Draws text using the currently selected font, background color, and text color.
1737 * x,y [I] coordinates of string
1739 * ETO_GRAYED - undocumented on MSDN
1740 * ETO_OPAQUE - use background color for fill the rectangle
1741 * ETO_CLIPPED - clipping text to the rectangle
1742 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1743 * than encoded characters. Implies ETO_IGNORELANGUAGE
1744 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1745 * Affects BiDi ordering
1746 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1747 * ETO_PDY - unimplemented
1748 * ETO_NUMERICSLATIN - unimplemented always assumed -
1749 * do not translate numbers into locale representations
1750 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1751 * lprect [I] dimensions for clipping or/and opaquing
1752 * str [I] text string
1753 * count [I] number of symbols in string
1754 * lpDx [I] optional parameter with distance between drawing characters
1760 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1761 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1764 LPWSTR reordered_str = (LPWSTR)str;
1765 WORD *glyphs = NULL;
1766 UINT align = GetTextAlign( hdc );
1767 DWORD layout = GetLayout( hdc );
1771 double cosEsc, sinEsc;
1775 BOOL done_extents = FALSE;
1776 POINT *deltas = NULL, width = {0, 0};
1778 DC * dc = get_dc_ptr( hdc );
1780 static int quietfixme = 0;
1782 if (!dc) return FALSE;
1784 breakRem = dc->breakRem;
1786 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1788 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1791 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1793 release_dc_ptr( dc );
1798 type = GetObjectType(hdc);
1799 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1801 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1802 release_dc_ptr( dc );
1807 flags &= ~ETO_CLIPPED;
1809 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1810 if (layout & LAYOUT_RTL)
1812 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1813 align ^= TA_RTLREADING;
1816 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1819 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1821 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1822 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1823 reordered_str, count, NULL, &glyphs, &cGlyphs);
1825 flags |= ETO_IGNORELANGUAGE;
1828 flags |= ETO_GLYPH_INDEX;
1829 if (cGlyphs != count)
1833 else if(flags & ETO_GLYPH_INDEX)
1834 glyphs = reordered_str;
1836 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1837 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1838 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1840 if(align & TA_UPDATECP)
1842 GetCurrentPositionEx( hdc, &pt );
1847 GetTextMetricsW(hdc, &tm);
1848 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1850 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1851 lf.lfEscapement = 0;
1853 if(lf.lfEscapement != 0)
1855 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1856 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1864 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1868 if(flags & ETO_GLYPH_INDEX)
1869 GetTextExtentPointI(hdc, glyphs, count, &sz);
1871 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1873 done_extents = TRUE;
1876 rc.right = x + sz.cx;
1877 rc.bottom = y + sz.cy;
1884 LPtoDP(hdc, (POINT*)&rc, 2);
1886 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1887 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1890 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1891 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1901 LPtoDP(hdc, &pt, 1);
1905 char_extra = GetTextCharacterExtra(hdc);
1906 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1910 POINT total = {0, 0}, desired[2];
1912 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1913 for(i = 0; i < count; i++)
1919 deltas[i].x = lpDx[i * 2] + char_extra;
1920 deltas[i].y = -lpDx[i * 2 + 1];
1924 deltas[i].x = lpDx[i] + char_extra;
1931 if(flags & ETO_GLYPH_INDEX)
1932 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1934 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1936 deltas[i].x = tmpsz.cx;
1940 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1942 deltas[i].x = deltas[i].x + dc->breakExtra;
1949 total.x += deltas[i].x;
1950 total.y += deltas[i].y;
1952 desired[0].x = desired[0].y = 0;
1954 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1955 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1957 LPtoDP(hdc, desired, 2);
1958 desired[1].x -= desired[0].x;
1959 desired[1].y -= desired[0].y;
1960 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1962 deltas[i].x = desired[1].x - width.x;
1963 deltas[i].y = desired[1].y - width.y;
1973 if(flags & ETO_GLYPH_INDEX)
1974 GetTextExtentPointI(hdc, glyphs, count, &sz);
1976 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1977 done_extents = TRUE;
1979 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1983 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1984 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1985 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1988 if (align & TA_UPDATECP)
1992 DPtoLP(hdc, &pt, 1);
1993 MoveToEx(hdc, pt.x, pt.y, NULL);
2005 if (align & TA_UPDATECP)
2009 DPtoLP(hdc, &pt, 1);
2010 MoveToEx(hdc, pt.x, pt.y, NULL);
2015 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2018 y += tm.tmAscent * cosEsc;
2019 x += tm.tmAscent * sinEsc;
2023 y -= tm.tmDescent * cosEsc;
2024 x -= tm.tmDescent * sinEsc;
2031 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2033 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2035 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2036 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2040 rc.right = x + width.x;
2041 rc.top = y - tm.tmAscent;
2042 rc.bottom = y + tm.tmDescent;
2044 if(flags & ETO_CLIPPED)
2046 rc.left = max(lprect->left, rc.left);
2047 rc.right = min(lprect->right, rc.right);
2048 rc.top = max(lprect->top, rc.top);
2049 rc.bottom = min(lprect->bottom, rc.bottom);
2051 if(rc.left < rc.right && rc.top < rc.bottom)
2052 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2057 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2059 HFONT orig_font = dc->hFont, cur_font;
2062 POINT *offsets = NULL;
2065 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2066 for(i = 0; i < count; i++)
2068 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2069 if(cur_font != dc->hFont)
2074 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2075 offsets[0].x = offsets[0].y = 0;
2080 for(j = 1; j < count; j++)
2082 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2083 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2089 for(j = 1; j < count; j++)
2091 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2092 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2098 if (PATH_IsPathOpen(dc->path))
2099 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2100 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2101 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2103 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span].x, y + offsets[i - span].y,
2104 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2105 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2108 SelectObject(hdc, cur_font);
2110 glyphs[span++] = glyph;
2114 if (PATH_IsPathOpen(dc->path))
2115 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2116 y + (offsets ? offsets[count - span].y : 0),
2117 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2118 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2120 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span].x : 0),
2121 y + (offsets ? offsets[count - span].y : 0),
2122 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2123 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2124 SelectObject(hdc, orig_font);
2125 HeapFree(GetProcessHeap(), 0, offsets);
2131 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2133 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2134 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2135 flags |= ETO_GLYPH_INDEX;
2138 if (PATH_IsPathOpen(dc->path))
2139 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2140 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2142 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2143 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2147 HeapFree(GetProcessHeap(), 0, deltas);
2148 if(glyphs != reordered_str)
2149 HeapFree(GetProcessHeap(), 0, glyphs);
2150 if(reordered_str != str)
2151 HeapFree(GetProcessHeap(), 0, reordered_str);
2153 release_dc_ptr( dc );
2155 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2157 int underlinePos, strikeoutPos;
2158 int underlineWidth, strikeoutWidth;
2159 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2160 OUTLINETEXTMETRICW* otm = NULL;
2165 underlineWidth = tm.tmAscent / 20 + 1;
2166 strikeoutPos = tm.tmAscent / 2;
2167 strikeoutWidth = underlineWidth;
2171 otm = HeapAlloc(GetProcessHeap(), 0, size);
2172 GetOutlineTextMetricsW(hdc, size, otm);
2173 underlinePos = otm->otmsUnderscorePosition;
2174 underlineWidth = otm->otmsUnderscoreSize;
2175 strikeoutPos = otm->otmsStrikeoutPosition;
2176 strikeoutWidth = otm->otmsStrikeoutSize;
2177 HeapFree(GetProcessHeap(), 0, otm);
2180 if (PATH_IsPathOpen(dc->path))
2184 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2186 hbrush = SelectObject(hdc, hbrush);
2187 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2191 pts[0].x = x - underlinePos * sinEsc;
2192 pts[0].y = y - underlinePos * cosEsc;
2193 pts[1].x = x + width.x - underlinePos * sinEsc;
2194 pts[1].y = y + width.y - underlinePos * cosEsc;
2195 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2196 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2197 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2198 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2199 pts[4].x = pts[0].x;
2200 pts[4].y = pts[0].y;
2201 DPtoLP(hdc, pts, 5);
2202 Polygon(hdc, pts, 5);
2207 pts[0].x = x - strikeoutPos * sinEsc;
2208 pts[0].y = y - strikeoutPos * cosEsc;
2209 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2210 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2211 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2212 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2213 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2214 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2215 pts[4].x = pts[0].x;
2216 pts[4].y = pts[0].y;
2217 DPtoLP(hdc, pts, 5);
2218 Polygon(hdc, pts, 5);
2221 SelectObject(hdc, hpen);
2222 hbrush = SelectObject(hdc, hbrush);
2223 DeleteObject(hbrush);
2227 POINT pts[2], oldpt;
2232 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2233 hpen = SelectObject(hdc, hpen);
2236 pts[1].x = x + width.x;
2237 pts[1].y = y + width.y;
2238 DPtoLP(hdc, pts, 2);
2239 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2240 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2241 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2242 DeleteObject(SelectObject(hdc, hpen));
2247 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2248 hpen = SelectObject(hdc, hpen);
2251 pts[1].x = x + width.x;
2252 pts[1].y = y + width.y;
2253 DPtoLP(hdc, pts, 2);
2254 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2255 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2256 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2257 DeleteObject(SelectObject(hdc, hpen));
2266 /***********************************************************************
2267 * TextOutA (GDI32.@)
2269 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2271 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2275 /***********************************************************************
2276 * TextOutW (GDI32.@)
2278 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2280 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2284 /***********************************************************************
2285 * PolyTextOutA (GDI32.@)
2289 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2291 for (; cStrings>0; cStrings--, pptxt++)
2292 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2299 /***********************************************************************
2300 * PolyTextOutW (GDI32.@)
2302 * Draw several Strings
2308 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2310 for (; cStrings>0; cStrings--, pptxt++)
2311 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2317 /* FIXME: all following APIs ******************************************/
2320 /***********************************************************************
2321 * SetMapperFlags (GDI32.@)
2323 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2325 DC *dc = get_dc_ptr( hdc );
2326 DWORD ret = GDI_ERROR;
2330 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2331 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2332 if (flags != GDI_ERROR)
2334 ret = dc->mapperFlags;
2335 dc->mapperFlags = flags;
2337 release_dc_ptr( dc );
2342 /***********************************************************************
2343 * GetAspectRatioFilterEx (GDI32.@)
2345 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2347 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2352 /***********************************************************************
2353 * GetCharABCWidthsA (GDI32.@)
2355 * See GetCharABCWidthsW.
2357 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2365 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2369 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2372 HeapFree(GetProcessHeap(), 0, str);
2376 for(i = 0; i < wlen; i++)
2378 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2386 HeapFree(GetProcessHeap(), 0, str);
2387 HeapFree(GetProcessHeap(), 0, wstr);
2393 /******************************************************************************
2394 * GetCharABCWidthsW [GDI32.@]
2396 * Retrieves widths of characters in range.
2399 * hdc [I] Handle of device context
2400 * firstChar [I] First character in range to query
2401 * lastChar [I] Last character in range to query
2402 * abc [O] Address of character-width structure
2405 * Only works with TrueType fonts
2411 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2414 DC *dc = get_dc_ptr(hdc);
2418 if (!dc) return FALSE;
2422 release_dc_ptr( dc );
2427 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2433 /* convert device units to logical */
2434 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2435 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2436 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2437 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2442 release_dc_ptr( dc );
2447 /******************************************************************************
2448 * GetCharABCWidthsI [GDI32.@]
2450 * Retrieves widths of characters in range.
2453 * hdc [I] Handle of device context
2454 * firstChar [I] First glyphs in range to query
2455 * count [I] Last glyphs in range to query
2456 * pgi [i] Array of glyphs to query
2457 * abc [O] Address of character-width structure
2460 * Only works with TrueType fonts
2466 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2467 LPWORD pgi, LPABC abc)
2469 DC *dc = get_dc_ptr(hdc);
2473 if (!dc) return FALSE;
2477 release_dc_ptr( dc );
2482 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2488 /* convert device units to logical */
2489 for( i = 0; i < count; i++, abc++ ) {
2490 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2491 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2492 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2497 release_dc_ptr( dc );
2502 /***********************************************************************
2503 * GetGlyphOutlineA (GDI32.@)
2505 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2506 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2507 LPVOID lpBuffer, const MAT2 *lpmat2 )
2509 if (!lpmat2) return GDI_ERROR;
2511 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2516 cp = GdiGetCodePage(hdc);
2517 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2519 mbchs[0] = (uChar & 0xff00) >> 8;
2520 mbchs[1] = (uChar & 0xff);
2523 mbchs[0] = (uChar & 0xff);
2525 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2528 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2532 /***********************************************************************
2533 * GetGlyphOutlineW (GDI32.@)
2535 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2536 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2537 LPVOID lpBuffer, const MAT2 *lpmat2 )
2542 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2543 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2545 if (!lpmat2) return GDI_ERROR;
2547 dc = get_dc_ptr(hdc);
2548 if(!dc) return GDI_ERROR;
2551 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2552 cbBuffer, lpBuffer, lpmat2);
2556 release_dc_ptr( dc );
2561 /***********************************************************************
2562 * CreateScalableFontResourceA (GDI32.@)
2564 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2565 LPCSTR lpszResourceFile,
2566 LPCSTR lpszFontFile,
2567 LPCSTR lpszCurrentPath )
2569 LPWSTR lpszResourceFileW = NULL;
2570 LPWSTR lpszFontFileW = NULL;
2571 LPWSTR lpszCurrentPathW = NULL;
2575 if (lpszResourceFile)
2577 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2578 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2579 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2584 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2585 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2586 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2589 if (lpszCurrentPath)
2591 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2592 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2593 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2596 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2597 lpszFontFileW, lpszCurrentPathW);
2599 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2600 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2601 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2606 /***********************************************************************
2607 * CreateScalableFontResourceW (GDI32.@)
2609 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2610 LPCWSTR lpszResourceFile,
2611 LPCWSTR lpszFontFile,
2612 LPCWSTR lpszCurrentPath )
2615 FIXME("(%d,%s,%s,%s): stub\n",
2616 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2617 debugstr_w(lpszCurrentPath) );
2619 /* fHidden=1 - only visible for the calling app, read-only, not
2620 * enumerated with EnumFonts/EnumFontFamilies
2621 * lpszCurrentPath can be NULL
2624 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2625 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2627 SetLastError(ERROR_FILE_EXISTS);
2630 return FALSE; /* create failed */
2633 /*************************************************************************
2634 * GetKerningPairsA (GDI32.@)
2636 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2637 LPKERNINGPAIR kern_pairA )
2641 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2642 KERNINGPAIR *kern_pairW;
2644 if (!cPairs && kern_pairA)
2646 SetLastError(ERROR_INVALID_PARAMETER);
2650 cp = GdiGetCodePage(hDC);
2652 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2653 * to fail on an invalid character for CP_SYMBOL.
2655 cpi.DefaultChar[0] = 0;
2656 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2658 FIXME("Can't find codepage %u info\n", cp);
2662 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2663 if (!total_kern_pairs) return 0;
2665 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2666 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2668 for (i = 0; i < total_kern_pairs; i++)
2672 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2675 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2678 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2683 if (kern_pairs_copied >= cPairs) break;
2685 kern_pairA->wFirst = (BYTE)first;
2686 kern_pairA->wSecond = (BYTE)second;
2687 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2690 kern_pairs_copied++;
2693 HeapFree(GetProcessHeap(), 0, kern_pairW);
2695 return kern_pairs_copied;
2698 /*************************************************************************
2699 * GetKerningPairsW (GDI32.@)
2701 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2702 LPKERNINGPAIR lpKerningPairs )
2707 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2709 if (!cPairs && lpKerningPairs)
2711 SetLastError(ERROR_INVALID_PARAMETER);
2715 dc = get_dc_ptr(hDC);
2719 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2721 release_dc_ptr( dc );
2725 /*************************************************************************
2726 * TranslateCharsetInfo [GDI32.@]
2728 * Fills a CHARSETINFO structure for a character set, code page, or
2729 * font. This allows making the correspondence between different labels
2730 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2731 * of the same encoding.
2733 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2734 * only one codepage should be set in *lpSrc.
2737 * TRUE on success, FALSE on failure.
2740 BOOL WINAPI TranslateCharsetInfo(
2741 LPDWORD lpSrc, /* [in]
2742 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2743 if flags == TCI_SRCCHARSET: a character set value
2744 if flags == TCI_SRCCODEPAGE: a code page value
2746 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2747 DWORD flags /* [in] determines interpretation of lpSrc */)
2751 case TCI_SRCFONTSIG:
2752 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2754 case TCI_SRCCODEPAGE:
2755 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2757 case TCI_SRCCHARSET:
2758 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2763 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2764 *lpCs = FONT_tci[index];
2768 /*************************************************************************
2769 * GetFontLanguageInfo (GDI32.@)
2771 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2773 FONTSIGNATURE fontsig;
2774 static const DWORD GCP_DBCS_MASK=0x003F0000,
2775 GCP_DIACRITIC_MASK=0x00000000,
2776 FLI_GLYPHS_MASK=0x00000000,
2777 GCP_GLYPHSHAPE_MASK=0x00000040,
2778 GCP_KASHIDA_MASK=0x00000000,
2779 GCP_LIGATE_MASK=0x00000000,
2780 GCP_USEKERNING_MASK=0x00000000,
2781 GCP_REORDER_MASK=0x00000060;
2785 GetTextCharsetInfo( hdc, &fontsig, 0 );
2786 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2788 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2791 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2792 result|=GCP_DIACRITIC;
2794 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2797 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2798 result|=GCP_GLYPHSHAPE;
2800 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2801 result|=GCP_KASHIDA;
2803 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2806 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2807 result|=GCP_USEKERNING;
2809 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2810 if( GetTextAlign( hdc) & TA_RTLREADING )
2811 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2812 result|=GCP_REORDER;
2818 /*************************************************************************
2819 * GetFontData [GDI32.@]
2821 * Retrieve data for TrueType font.
2825 * success: Number of bytes returned
2826 * failure: GDI_ERROR
2830 * Calls SetLastError()
2833 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2834 LPVOID buffer, DWORD length)
2836 DC *dc = get_dc_ptr(hdc);
2837 DWORD ret = GDI_ERROR;
2839 if(!dc) return GDI_ERROR;
2842 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2844 release_dc_ptr( dc );
2848 /*************************************************************************
2849 * GetGlyphIndicesA [GDI32.@]
2851 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2852 LPWORD pgi, DWORD flags)
2858 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2859 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2861 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2862 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2863 HeapFree(GetProcessHeap(), 0, lpstrW);
2868 /*************************************************************************
2869 * GetGlyphIndicesW [GDI32.@]
2871 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2872 LPWORD pgi, DWORD flags)
2874 DC *dc = get_dc_ptr(hdc);
2875 DWORD ret = GDI_ERROR;
2877 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2878 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2880 if(!dc) return GDI_ERROR;
2883 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2885 release_dc_ptr( dc );
2889 /*************************************************************************
2890 * GetCharacterPlacementA [GDI32.@]
2892 * See GetCharacterPlacementW.
2895 * the web browser control of ie4 calls this with dwFlags=0
2898 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2899 INT nMaxExtent, GCP_RESULTSA *lpResults,
2904 GCP_RESULTSW resultsW;
2908 TRACE("%s, %d, %d, 0x%08x\n",
2909 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2911 /* both structs are equal in size */
2912 memcpy(&resultsW, lpResults, sizeof(resultsW));
2914 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2915 if(lpResults->lpOutString)
2916 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2918 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2920 lpResults->nGlyphs = resultsW.nGlyphs;
2921 lpResults->nMaxFit = resultsW.nMaxFit;
2923 if(lpResults->lpOutString) {
2924 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2925 lpResults->lpOutString, uCount, NULL, NULL );
2928 HeapFree(GetProcessHeap(), 0, lpStringW);
2929 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2934 /*************************************************************************
2935 * GetCharacterPlacementW [GDI32.@]
2937 * Retrieve information about a string. This includes the width, reordering,
2938 * Glyphing and so on.
2942 * The width and height of the string if successful, 0 if failed.
2946 * All flags except GCP_REORDER are not yet implemented.
2947 * Reordering is not 100% compliant to the Windows BiDi method.
2948 * Caret positioning is not yet implemented for BiDi.
2949 * Classes are not yet implemented.
2953 GetCharacterPlacementW(
2954 HDC hdc, /* [in] Device context for which the rendering is to be done */
2955 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2956 INT uCount, /* [in] Number of WORDS in string. */
2957 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2958 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2959 DWORD dwFlags /* [in] Flags specifying how to process the string */
2966 TRACE("%s, %d, %d, 0x%08x\n",
2967 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2969 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2970 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2971 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2972 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2973 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2975 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2976 if(lpResults->lpClass) FIXME("classes not implemented\n");
2977 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2978 FIXME("Caret positions for complex scripts not implemented\n");
2980 nSet = (UINT)uCount;
2981 if(nSet > lpResults->nGlyphs)
2982 nSet = lpResults->nGlyphs;
2984 /* return number of initialized fields */
2985 lpResults->nGlyphs = nSet;
2987 if((dwFlags&GCP_REORDER)==0 )
2989 /* Treat the case where no special handling was requested in a fastpath way */
2990 /* copy will do if the GCP_REORDER flag is not set */
2991 if(lpResults->lpOutString)
2992 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2994 if(lpResults->lpOrder)
2996 for(i = 0; i < nSet; i++)
2997 lpResults->lpOrder[i] = i;
3001 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3002 nSet, lpResults->lpOrder, NULL, NULL );
3005 /* FIXME: Will use the placement chars */
3006 if (lpResults->lpDx)
3009 for (i = 0; i < nSet; i++)
3011 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3012 lpResults->lpDx[i]= c;
3016 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3020 lpResults->lpCaretPos[0] = 0;
3021 for (i = 1; i < nSet; i++)
3022 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3023 lpResults->lpCaretPos[i] = (pos += size.cx);
3026 if(lpResults->lpGlyphs)
3027 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3029 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3030 ret = MAKELONG(size.cx, size.cy);
3035 /*************************************************************************
3036 * GetCharABCWidthsFloatA [GDI32.@]
3038 * See GetCharABCWidthsFloatW.
3040 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3047 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3051 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3053 for (i = 0; i < wlen; i++)
3055 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3063 HeapFree( GetProcessHeap(), 0, str );
3064 HeapFree( GetProcessHeap(), 0, wstr );
3069 /*************************************************************************
3070 * GetCharABCWidthsFloatW [GDI32.@]
3072 * Retrieves widths of a range of characters.
3075 * hdc [I] Handle to device context.
3076 * first [I] First character in range to query.
3077 * last [I] Last character in range to query.
3078 * abcf [O] Array of LPABCFLOAT structures.
3084 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3088 DC *dc = get_dc_ptr( hdc );
3090 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3092 if (!dc) return FALSE;
3096 release_dc_ptr( dc );
3101 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3107 /* convert device units to logical */
3108 for (i = first; i <= last; i++, abcf++)
3110 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3111 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3112 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3116 release_dc_ptr( dc );
3120 /*************************************************************************
3121 * GetCharWidthFloatA [GDI32.@]
3123 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3124 UINT iLastChar, PFLOAT pxBuffer)
3126 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3130 /*************************************************************************
3131 * GetCharWidthFloatW [GDI32.@]
3133 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3134 UINT iLastChar, PFLOAT pxBuffer)
3136 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3141 /***********************************************************************
3143 * Font Resource API *
3145 ***********************************************************************/
3147 /***********************************************************************
3148 * AddFontResourceA (GDI32.@)
3150 INT WINAPI AddFontResourceA( LPCSTR str )
3152 return AddFontResourceExA( str, 0, NULL);
3155 /***********************************************************************
3156 * AddFontResourceW (GDI32.@)
3158 INT WINAPI AddFontResourceW( LPCWSTR str )
3160 return AddFontResourceExW(str, 0, NULL);
3164 /***********************************************************************
3165 * AddFontResourceExA (GDI32.@)
3167 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3169 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3170 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3173 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3174 ret = AddFontResourceExW(strW, fl, pdv);
3175 HeapFree(GetProcessHeap(), 0, strW);
3179 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3181 HRSRC rsrc = FindResourceW(hModule, name, type);
3182 HGLOBAL hMem = LoadResource(hModule, rsrc);
3183 LPVOID *pMem = LockResource(hMem);
3184 int *num_total = (int *)lParam;
3187 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3188 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3190 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3194 *num_total += num_in_res;
3198 /***********************************************************************
3199 * AddFontResourceExW (GDI32.@)
3201 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3203 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3206 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3207 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3208 if (hModule != NULL)
3210 int num_resources = 0;
3211 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3213 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3214 wine_dbgstr_w(str));
3215 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3216 ret = num_resources;
3217 FreeLibrary(hModule);
3223 /***********************************************************************
3224 * RemoveFontResourceA (GDI32.@)
3226 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3228 return RemoveFontResourceExA(str, 0, 0);
3231 /***********************************************************************
3232 * RemoveFontResourceW (GDI32.@)
3234 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3236 return RemoveFontResourceExW(str, 0, 0);
3239 /***********************************************************************
3240 * AddFontMemResourceEx (GDI32.@)
3242 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3247 if (!pbFont || !cbFont || !pcFonts)
3249 SetLastError(ERROR_INVALID_PARAMETER);
3253 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3258 *pcFonts = num_fonts;
3262 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3263 RemoveFontMemResourceEx(ret);
3271 /***********************************************************************
3272 * RemoveFontMemResourceEx (GDI32.@)
3274 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3276 FIXME("(%p) stub\n", fh);
3280 /***********************************************************************
3281 * RemoveFontResourceExA (GDI32.@)
3283 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3285 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3286 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3289 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3290 ret = RemoveFontResourceExW(strW, fl, pdv);
3291 HeapFree(GetProcessHeap(), 0, strW);
3295 /***********************************************************************
3296 * RemoveFontResourceExW (GDI32.@)
3298 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3300 return WineEngRemoveFontResourceEx(str, fl, pdv);
3303 /***********************************************************************
3304 * GetTextCharset (GDI32.@)
3306 UINT WINAPI GetTextCharset(HDC hdc)
3308 /* MSDN docs say this is equivalent */
3309 return GetTextCharsetInfo(hdc, NULL, 0);
3312 /***********************************************************************
3313 * GetTextCharsetInfo (GDI32.@)
3315 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3317 UINT ret = DEFAULT_CHARSET;
3318 DC *dc = get_dc_ptr(hdc);
3323 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3325 release_dc_ptr( dc );
3328 if (ret == DEFAULT_CHARSET && fs)
3329 memset(fs, 0, sizeof(FONTSIGNATURE));
3333 /***********************************************************************
3334 * GdiGetCharDimensions (GDI32.@)
3336 * Gets the average width of the characters in the English alphabet.
3339 * hdc [I] Handle to the device context to measure on.
3340 * lptm [O] Pointer to memory to store the text metrics into.
3341 * height [O] On exit, the maximum height of characters in the English alphabet.
3344 * The average width of characters in the English alphabet.
3347 * This function is used by the dialog manager to get the size of a dialog
3348 * unit. It should also be used by other pieces of code that need to know
3349 * the size of a dialog unit in logical units without having access to the
3350 * window handle of the dialog.
3351 * Windows caches the font metrics from this function, but we don't and
3352 * there doesn't appear to be an immediate advantage to do so.
3355 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3357 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3360 static const WCHAR alphabet[] = {
3361 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3362 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3363 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3365 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3367 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3369 if (height) *height = sz.cy;
3370 return (sz.cx / 26 + 1) / 2;
3373 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3375 FIXME("(%d): stub\n", fEnableEUDC);
3379 /***********************************************************************
3380 * GetCharWidthI (GDI32.@)
3382 * Retrieve widths of characters.
3385 * hdc [I] Handle to a device context.
3386 * first [I] First glyph in range to query.
3387 * count [I] Number of glyph indices to query.
3388 * glyphs [I] Array of glyphs to query.
3389 * buffer [O] Buffer to receive character widths.
3392 * Only works with TrueType fonts.
3398 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3403 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3405 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3408 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3410 HeapFree(GetProcessHeap(), 0, abc);
3414 for (i = 0; i < count; i++)
3415 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3417 HeapFree(GetProcessHeap(), 0, abc);
3421 /***********************************************************************
3422 * GetFontUnicodeRanges (GDI32.@)
3424 * Retrieve a list of supported Unicode characters in a font.
3427 * hdc [I] Handle to a device context.
3428 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3431 * Success: Number of bytes written to the buffer pointed to by lpgs.
3435 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3438 DC *dc = get_dc_ptr(hdc);
3440 TRACE("(%p, %p)\n", hdc, lpgs);
3444 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3450 /*************************************************************
3451 * FontIsLinked (GDI32.@)
3453 BOOL WINAPI FontIsLinked(HDC hdc)
3455 DC *dc = get_dc_ptr(hdc);
3458 if (!dc) return FALSE;
3459 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3461 TRACE("returning %d\n", ret);
3465 /*************************************************************
3466 * GdiRealizationInfo (GDI32.@)
3468 * Returns a structure that contains some font information.
3470 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3472 DC *dc = get_dc_ptr(hdc);
3475 if (!dc) return FALSE;
3476 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);