4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 /* Perform operation with floating point */
51 floatWidth = (double)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 /* Perform operation with floating point */
64 floatHeight = (double)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 pt[0].x = pt[0].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 pt[0].x = pt[0].y = 0;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
111 LPLOGFONTW lpLogFontParam;
112 FONTENUMPROCW lpEnumFunc;
119 * For TranslateCharsetInfo
121 #define MAXTCIINDEX 32
122 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
124 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
125 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
126 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
127 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
128 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
129 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
130 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
131 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
132 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
133 /* reserved by ANSI */
134 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
135 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
136 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
143 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
144 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
145 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
146 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
147 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
148 /* reserved for alternate ANSI and OEM */
149 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
150 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
151 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 /* reserved for system */
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
162 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
164 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
165 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
167 fontW->lfFaceName[LF_FACESIZE-1] = 0;
170 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
172 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
173 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
174 LF_FACESIZE, NULL, NULL);
175 fontA->lfFaceName[LF_FACESIZE-1] = 0;
178 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
180 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
182 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
183 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
184 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
186 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
187 fontA->elfStyle[LF_FACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
189 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
190 fontA->elfScript[LF_FACESIZE-1] = '\0';
193 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
195 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
197 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
198 fontW->elfFullName, LF_FULLFACESIZE );
199 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
201 fontW->elfStyle, LF_FACESIZE );
202 fontW->elfStyle[LF_FACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
204 fontW->elfScript, LF_FACESIZE );
205 fontW->elfScript[LF_FACESIZE-1] = '\0';
208 /***********************************************************************
209 * TEXTMETRIC conversion functions.
211 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
213 ptmA->tmHeight = ptmW->tmHeight;
214 ptmA->tmAscent = ptmW->tmAscent;
215 ptmA->tmDescent = ptmW->tmDescent;
216 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
217 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
218 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
219 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
220 ptmA->tmWeight = ptmW->tmWeight;
221 ptmA->tmOverhang = ptmW->tmOverhang;
222 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
223 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
224 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
225 if (ptmW->tmCharSet == SYMBOL_CHARSET)
227 ptmA->tmFirstChar = 0x1e;
228 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
230 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
232 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
233 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
237 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
238 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
240 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
241 ptmA->tmBreakChar = ptmW->tmBreakChar;
242 ptmA->tmItalic = ptmW->tmItalic;
243 ptmA->tmUnderlined = ptmW->tmUnderlined;
244 ptmA->tmStruckOut = ptmW->tmStruckOut;
245 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
246 ptmA->tmCharSet = ptmW->tmCharSet;
250 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
252 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
253 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
254 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
255 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
256 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
257 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
261 /***********************************************************************
262 * GdiGetCodePage (GDI32.@)
264 DWORD WINAPI GdiGetCodePage( HDC hdc )
267 DC *dc = get_dc_ptr( hdc );
271 cp = dc->font_code_page;
272 release_dc_ptr( dc );
277 /***********************************************************************
280 * Returns a Unicode translation of str using the charset of the
281 * currently selected font in hdc. If count is -1 then str is assumed
282 * to be '\0' terminated, otherwise it contains the number of bytes to
283 * convert. If plenW is non-NULL, on return it will point to the
284 * number of WCHARs that have been written. If pCP is non-NULL, on
285 * return it will point to the codepage used in the conversion. The
286 * caller should free the returned LPWSTR from the process heap
289 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
295 cp = GdiGetCodePage( hdc );
297 if(count == -1) count = strlen(str);
298 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
299 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
300 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
301 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
302 if(plenW) *plenW = lenW;
307 /***********************************************************************
308 * CreateFontIndirectExA (GDI32.@)
310 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
312 ENUMLOGFONTEXDVW enumexW;
314 if (!penumexA) return 0;
316 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
317 enumexW.elfDesignVector = penumexA->elfDesignVector;
318 return CreateFontIndirectExW( &enumexW );
321 /***********************************************************************
322 * CreateFontIndirectExW (GDI32.@)
324 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
330 if (!penumex) return 0;
332 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
333 penumex->elfEnumLogfontEx.elfStyle[0] ||
334 penumex->elfEnumLogfontEx.elfScript[0])
336 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
337 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
338 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
339 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
342 plf = &penumex->elfEnumLogfontEx.elfLogFont;
343 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
345 fontPtr->logfont = *plf;
347 if (plf->lfEscapement != plf->lfOrientation)
349 /* this should really depend on whether GM_ADVANCED is set */
350 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
351 WARN("orientation angle %f set to "
352 "escapement angle %f for new font %p\n",
353 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
356 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
358 HeapFree( GetProcessHeap(), 0, fontPtr );
362 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
363 plf->lfHeight, plf->lfWidth,
364 plf->lfEscapement, plf->lfOrientation,
365 plf->lfPitchAndFamily,
366 plf->lfOutPrecision, plf->lfClipPrecision,
367 plf->lfQuality, plf->lfCharSet,
368 debugstr_w(plf->lfFaceName),
369 plf->lfWeight > 400 ? "Bold" : "",
370 plf->lfItalic ? "Italic" : "",
371 plf->lfUnderline ? "Underline" : "", hFont);
376 /***********************************************************************
377 * CreateFontIndirectA (GDI32.@)
379 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
385 FONT_LogFontAToW( plfA, &lfW );
386 return CreateFontIndirectW( &lfW );
389 /***********************************************************************
390 * CreateFontIndirectW (GDI32.@)
392 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
394 ENUMLOGFONTEXDVW exdv;
398 exdv.elfEnumLogfontEx.elfLogFont = *plf;
399 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
400 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
401 exdv.elfEnumLogfontEx.elfScript[0] = 0;
402 return CreateFontIndirectExW( &exdv );
405 /*************************************************************************
406 * CreateFontA (GDI32.@)
408 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
409 INT orient, INT weight, DWORD italic,
410 DWORD underline, DWORD strikeout, DWORD charset,
411 DWORD outpres, DWORD clippres, DWORD quality,
412 DWORD pitch, LPCSTR name )
416 logfont.lfHeight = height;
417 logfont.lfWidth = width;
418 logfont.lfEscapement = esc;
419 logfont.lfOrientation = orient;
420 logfont.lfWeight = weight;
421 logfont.lfItalic = italic;
422 logfont.lfUnderline = underline;
423 logfont.lfStrikeOut = strikeout;
424 logfont.lfCharSet = charset;
425 logfont.lfOutPrecision = outpres;
426 logfont.lfClipPrecision = clippres;
427 logfont.lfQuality = quality;
428 logfont.lfPitchAndFamily = pitch;
431 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
433 logfont.lfFaceName[0] = '\0';
435 return CreateFontIndirectA( &logfont );
438 /*************************************************************************
439 * CreateFontW (GDI32.@)
441 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
442 INT orient, INT weight, DWORD italic,
443 DWORD underline, DWORD strikeout, DWORD charset,
444 DWORD outpres, DWORD clippres, DWORD quality,
445 DWORD pitch, LPCWSTR name )
449 logfont.lfHeight = height;
450 logfont.lfWidth = width;
451 logfont.lfEscapement = esc;
452 logfont.lfOrientation = orient;
453 logfont.lfWeight = weight;
454 logfont.lfItalic = italic;
455 logfont.lfUnderline = underline;
456 logfont.lfStrikeOut = strikeout;
457 logfont.lfCharSet = charset;
458 logfont.lfOutPrecision = outpres;
459 logfont.lfClipPrecision = clippres;
460 logfont.lfQuality = quality;
461 logfont.lfPitchAndFamily = pitch;
464 lstrcpynW(logfont.lfFaceName, name,
465 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
467 logfont.lfFaceName[0] = '\0';
469 return CreateFontIndirectW( &logfont );
472 static void update_font_code_page( DC *dc )
475 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
477 /* Hmm, nicely designed api this one! */
478 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
479 dc->font_code_page = csi.ciACP;
483 dc->font_code_page = GetOEMCP();
485 case DEFAULT_CHARSET:
486 dc->font_code_page = GetACP();
496 /* FIXME: These have no place here, but because x11drv
497 enumerates fonts with these (made up) charsets some apps
498 might use them and then the FIXME below would become
499 annoying. Now we could pick the intended codepage for
500 each of these, but since it's broken anyway we'll just
501 use CP_ACP and hope it'll go away...
503 dc->font_code_page = CP_ACP;
507 FIXME("Can't find codepage for charset %d\n", charset);
508 dc->font_code_page = CP_ACP;
513 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
516 /***********************************************************************
519 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
522 DC *dc = get_dc_ptr( hdc );
527 if (!GDI_inc_ref_count( handle ))
529 release_dc_ptr( dc );
533 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
534 if (physdev->funcs->pSelectFont( physdev, handle ))
538 update_font_code_page( dc );
539 GDI_dec_ref_count( ret );
541 else GDI_dec_ref_count( handle );
543 release_dc_ptr( dc );
548 /***********************************************************************
551 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
553 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
559 FONT_LogFontWToA( &font->logfont, &lfA );
560 if (count > sizeof(lfA)) count = sizeof(lfA);
561 memcpy( buffer, &lfA, count );
563 else count = sizeof(lfA);
564 GDI_ReleaseObj( handle );
568 /***********************************************************************
571 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
573 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
578 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
579 memcpy( buffer, &font->logfont, count );
581 else count = sizeof(LOGFONTW);
582 GDI_ReleaseObj( handle );
587 /***********************************************************************
590 static BOOL FONT_DeleteObject( HGDIOBJ handle )
594 WineEngDestroyFontInstance( handle );
596 if (!(obj = free_gdi_handle( handle ))) return FALSE;
597 return HeapFree( GetProcessHeap(), 0, obj );
601 /***********************************************************************
604 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
605 * We have to use other types because of the FONTENUMPROCW definition.
607 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
608 DWORD fType, LPARAM lp )
610 struct font_enum *pfe = (struct font_enum *)lp;
613 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
614 if ((!pfe->lpLogFontParam ||
615 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
616 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
617 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
619 /* convert font metrics */
620 ENUMLOGFONTEXA logfont;
621 NEWTEXTMETRICEXA tmA;
625 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
626 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
627 plf = (LOGFONTW *)&logfont.elfLogFont;
628 ptm = (TEXTMETRICW *)&tmA;
630 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
635 /***********************************************************************
636 * FONT_EnumFontFamiliesEx
638 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
639 LPARAM lParam, BOOL unicode )
642 DC *dc = get_dc_ptr( hDC );
647 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
649 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
650 fe.lpLogFontParam = plf;
651 fe.lpEnumFunc = efproc;
653 fe.unicode = unicode;
655 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
656 release_dc_ptr( dc );
661 /***********************************************************************
662 * EnumFontFamiliesExW (GDI32.@)
664 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
665 FONTENUMPROCW efproc,
666 LPARAM lParam, DWORD dwFlags )
668 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
671 /***********************************************************************
672 * EnumFontFamiliesExA (GDI32.@)
674 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
675 FONTENUMPROCA efproc,
676 LPARAM lParam, DWORD dwFlags)
682 FONT_LogFontAToW( plf, &lfW );
687 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
690 /***********************************************************************
691 * EnumFontFamiliesA (GDI32.@)
693 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
694 FONTENUMPROCA efproc, LPARAM lpData )
700 if (!*lpFamily) return 1;
701 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
702 lf.lfCharSet = DEFAULT_CHARSET;
703 lf.lfPitchAndFamily = 0;
708 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
711 /***********************************************************************
712 * EnumFontFamiliesW (GDI32.@)
714 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
715 FONTENUMPROCW efproc, LPARAM lpData )
721 if (!*lpFamily) return 1;
722 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
723 lf.lfCharSet = DEFAULT_CHARSET;
724 lf.lfPitchAndFamily = 0;
729 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
732 /***********************************************************************
733 * EnumFontsA (GDI32.@)
735 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
738 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
741 /***********************************************************************
742 * EnumFontsW (GDI32.@)
744 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
747 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
751 /***********************************************************************
752 * GetTextCharacterExtra (GDI32.@)
754 INT WINAPI GetTextCharacterExtra( HDC hdc )
757 DC *dc = get_dc_ptr( hdc );
758 if (!dc) return 0x80000000;
760 release_dc_ptr( dc );
765 /***********************************************************************
766 * SetTextCharacterExtra (GDI32.@)
768 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
770 INT ret = 0x80000000;
771 DC * dc = get_dc_ptr( hdc );
775 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
776 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
777 if (extra != 0x80000000)
780 dc->charExtra = extra;
782 release_dc_ptr( dc );
788 /***********************************************************************
789 * SetTextJustification (GDI32.@)
791 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
795 DC * dc = get_dc_ptr( hdc );
797 if (!dc) return FALSE;
799 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
800 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
803 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
804 if (!extra) breaks = 0;
807 dc->breakExtra = extra / breaks;
808 dc->breakRem = extra - (breaks * dc->breakExtra);
816 release_dc_ptr( dc );
821 /***********************************************************************
822 * GetTextFaceA (GDI32.@)
824 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
826 INT res = GetTextFaceW(hdc, 0, NULL);
827 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
828 GetTextFaceW( hdc, res, nameW );
834 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
838 /* GetTextFaceA does NOT include the nul byte in the return count. */
845 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
846 HeapFree( GetProcessHeap(), 0, nameW );
850 /***********************************************************************
851 * GetTextFaceW (GDI32.@)
853 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
858 DC * dc = get_dc_ptr( hdc );
861 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
862 ret = dev->funcs->pGetTextFace( dev, count, name );
863 release_dc_ptr( dc );
868 /***********************************************************************
869 * GetTextExtentPoint32A (GDI32.@)
871 * See GetTextExtentPoint32W.
873 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
880 if (count < 0) return FALSE;
882 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
886 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
887 HeapFree( GetProcessHeap(), 0, p );
890 TRACE("(%p %s %d %p): returning %d x %d\n",
891 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
896 /***********************************************************************
897 * GetTextExtentPoint32W [GDI32.@]
899 * Computes width/height for a string.
901 * Computes width and height of the specified string.
907 BOOL WINAPI GetTextExtentPoint32W(
908 HDC hdc, /* [in] Handle of device context */
909 LPCWSTR str, /* [in] Address of text string */
910 INT count, /* [in] Number of characters in string */
911 LPSIZE size) /* [out] Address of structure for string size */
913 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
916 /***********************************************************************
917 * GetTextExtentExPointI [GDI32.@]
919 * Computes width and height of the array of glyph indices.
922 * hdc [I] Handle of device context.
923 * indices [I] Glyph index array.
924 * count [I] Number of glyphs in array.
925 * max_ext [I] Maximum width in glyphs.
926 * nfit [O] Maximum number of characters.
927 * dxs [O] Partial string widths.
928 * size [O] Returned string size.
934 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
935 LPINT nfit, LPINT dxs, LPSIZE size )
941 if (count < 0) return FALSE;
943 dc = get_dc_ptr( hdc );
944 if (!dc) return FALSE;
946 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
947 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
948 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
949 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
950 size->cx += count * dc->charExtra;
951 release_dc_ptr( dc );
953 TRACE("(%p %p %d %p): returning %d x %d\n",
954 hdc, indices, count, size, size->cx, size->cy );
958 /***********************************************************************
959 * GetTextExtentPointI [GDI32.@]
961 * Computes width and height of the array of glyph indices.
964 * hdc [I] Handle of device context.
965 * indices [I] Glyph index array.
966 * count [I] Number of glyphs in array.
967 * size [O] Returned string size.
973 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
975 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
979 /***********************************************************************
980 * GetTextExtentPointA (GDI32.@)
982 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
985 TRACE("not bug compatible.\n");
986 return GetTextExtentPoint32A( hdc, str, count, size );
989 /***********************************************************************
990 * GetTextExtentPointW (GDI32.@)
992 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
995 TRACE("not bug compatible.\n");
996 return GetTextExtentPoint32W( hdc, str, count, size );
1000 /***********************************************************************
1001 * GetTextExtentExPointA (GDI32.@)
1003 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1004 INT maxExt, LPINT lpnFit,
1005 LPINT alpDx, LPSIZE size )
1012 if (count < 0) return FALSE;
1016 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1017 if (!walpDx) return FALSE;
1020 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1021 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1024 INT n = lpnFit ? *lpnFit : wlen;
1026 for(i = 0, j = 0; i < n; i++, j++)
1028 alpDx[j] = walpDx[i];
1029 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1032 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1033 HeapFree( GetProcessHeap(), 0, p );
1034 HeapFree( GetProcessHeap(), 0, walpDx );
1039 /***********************************************************************
1040 * GetTextExtentExPointW (GDI32.@)
1042 * Return the size of the string as it would be if it was output properly by
1045 * This should include
1046 * - Intercharacter spacing
1047 * - justification spacing (not yet done)
1048 * - kerning? see below
1050 * Kerning. Since kerning would be carried out by the rendering code it should
1051 * be done by the driver. However they don't support it yet. Also I am not
1052 * yet persuaded that (certainly under Win95) any kerning is actually done.
1054 * str: According to MSDN this should be null-terminated. That is not true; a
1055 * null will not terminate it early.
1056 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1057 * than count. I have seen it be either the size of the full string or
1058 * 1 less than the size of the full string. I have not seen it bear any
1059 * resemblance to the portion that would fit.
1060 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1061 * trailing intercharacter spacing and any trailing justification.
1064 * Currently we do this by measuring each character etc. We should do it by
1065 * passing the request to the driver, perhaps by extending the
1066 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1067 * thinking about kerning issues and rounding issues in the justification.
1070 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1071 INT maxExt, LPINT lpnFit,
1072 LPINT alpDx, LPSIZE size )
1081 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1083 if (count < 0) return FALSE;
1085 dc = get_dc_ptr(hdc);
1086 if (!dc) return FALSE;
1088 GetTextMetricsW(hdc, &tm);
1090 /* If we need to calculate nFit, then we need the partial extents even if
1091 the user hasn't provided us with an array. */
1094 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1098 SetLastError(ERROR_OUTOFMEMORY);
1105 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1106 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1108 /* Perform device size to world size transformations. */
1111 INT extra = dc->charExtra,
1112 breakExtra = dc->breakExtra,
1113 breakRem = dc->breakRem,
1118 for (i = 0; i < count; ++i)
1120 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1121 dxs[i] += (i+1) * extra;
1122 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1124 dxs[i] += breakExtra;
1131 if (dxs[i] <= maxExt)
1134 breakRem = dc->breakRem;
1136 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1137 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1139 if (!dxs && count > 1 && (breakExtra || breakRem))
1141 for (i = 0; i < count; i++)
1143 if (str[i] == tm.tmBreakChar)
1145 size->cx += breakExtra;
1160 HeapFree(GetProcessHeap(), 0, dxs);
1162 release_dc_ptr( dc );
1164 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1168 /***********************************************************************
1169 * GetTextMetricsA (GDI32.@)
1171 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1175 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1176 FONT_TextMetricWToA( &tm32, metrics );
1180 /***********************************************************************
1181 * GetTextMetricsW (GDI32.@)
1183 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1187 DC * dc = get_dc_ptr( hdc );
1188 if (!dc) return FALSE;
1190 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1191 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1195 /* device layer returns values in device units
1196 * therefore we have to convert them to logical */
1198 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1199 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1201 #define WDPTOLP(x) ((x<0)? \
1202 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1203 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1204 #define HDPTOLP(y) ((y<0)? \
1205 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1206 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1208 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1209 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1210 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1211 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1212 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1213 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1214 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1215 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1219 TRACE("text metrics:\n"
1220 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1221 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1222 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1223 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1224 " PitchAndFamily = %02x\n"
1225 " --------------------\n"
1226 " InternalLeading = %i\n"
1230 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1231 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1232 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1233 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1234 metrics->tmPitchAndFamily,
1235 metrics->tmInternalLeading,
1238 metrics->tmHeight );
1240 release_dc_ptr( dc );
1245 /***********************************************************************
1246 * GetOutlineTextMetricsA (GDI32.@)
1247 * Gets metrics for TrueType fonts.
1250 * If the supplied buffer isn't big enough Windows partially fills it up to
1251 * its given length and returns that length.
1254 * Success: Non-zero or size of required buffer
1257 UINT WINAPI GetOutlineTextMetricsA(
1258 HDC hdc, /* [in] Handle of device context */
1259 UINT cbData, /* [in] Size of metric data array */
1260 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1262 char buf[512], *ptr;
1264 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1265 OUTLINETEXTMETRICA *output = lpOTM;
1268 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1270 if(ret > sizeof(buf))
1271 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1272 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1274 needed = sizeof(OUTLINETEXTMETRICA);
1275 if(lpOTMW->otmpFamilyName)
1276 needed += WideCharToMultiByte(CP_ACP, 0,
1277 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1278 NULL, 0, NULL, NULL);
1279 if(lpOTMW->otmpFaceName)
1280 needed += WideCharToMultiByte(CP_ACP, 0,
1281 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1282 NULL, 0, NULL, NULL);
1283 if(lpOTMW->otmpStyleName)
1284 needed += WideCharToMultiByte(CP_ACP, 0,
1285 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1286 NULL, 0, NULL, NULL);
1287 if(lpOTMW->otmpFullName)
1288 needed += WideCharToMultiByte(CP_ACP, 0,
1289 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1290 NULL, 0, NULL, NULL);
1297 TRACE("needed = %d\n", needed);
1299 /* Since the supplied buffer isn't big enough, we'll alloc one
1300 that is and memcpy the first cbData bytes into the lpOTM at
1302 output = HeapAlloc(GetProcessHeap(), 0, needed);
1304 ret = output->otmSize = min(needed, cbData);
1305 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1306 output->otmFiller = 0;
1307 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1308 output->otmfsSelection = lpOTMW->otmfsSelection;
1309 output->otmfsType = lpOTMW->otmfsType;
1310 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1311 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1312 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1313 output->otmEMSquare = lpOTMW->otmEMSquare;
1314 output->otmAscent = lpOTMW->otmAscent;
1315 output->otmDescent = lpOTMW->otmDescent;
1316 output->otmLineGap = lpOTMW->otmLineGap;
1317 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1318 output->otmsXHeight = lpOTMW->otmsXHeight;
1319 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1320 output->otmMacAscent = lpOTMW->otmMacAscent;
1321 output->otmMacDescent = lpOTMW->otmMacDescent;
1322 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1323 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1324 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1325 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1326 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1327 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1328 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1329 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1330 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1331 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1334 ptr = (char*)(output + 1);
1335 left = needed - sizeof(*output);
1337 if(lpOTMW->otmpFamilyName) {
1338 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1339 len = WideCharToMultiByte(CP_ACP, 0,
1340 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1341 ptr, left, NULL, NULL);
1345 output->otmpFamilyName = 0;
1347 if(lpOTMW->otmpFaceName) {
1348 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1349 len = WideCharToMultiByte(CP_ACP, 0,
1350 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1351 ptr, left, NULL, NULL);
1355 output->otmpFaceName = 0;
1357 if(lpOTMW->otmpStyleName) {
1358 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1359 len = WideCharToMultiByte(CP_ACP, 0,
1360 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1361 ptr, left, NULL, NULL);
1365 output->otmpStyleName = 0;
1367 if(lpOTMW->otmpFullName) {
1368 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1369 len = WideCharToMultiByte(CP_ACP, 0,
1370 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1371 ptr, left, NULL, NULL);
1374 output->otmpFullName = 0;
1378 if(output != lpOTM) {
1379 memcpy(lpOTM, output, cbData);
1380 HeapFree(GetProcessHeap(), 0, output);
1382 /* check if the string offsets really fit into the provided size */
1383 /* FIXME: should we check string length as well? */
1384 /* make sure that we don't read/write beyond the provided buffer */
1385 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1387 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1388 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1391 /* make sure that we don't read/write beyond the provided buffer */
1392 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1394 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1395 lpOTM->otmpFaceName = 0; /* doesn't fit */
1398 /* make sure that we don't read/write beyond the provided buffer */
1399 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1401 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1402 lpOTM->otmpStyleName = 0; /* doesn't fit */
1405 /* make sure that we don't read/write beyond the provided buffer */
1406 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1408 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1409 lpOTM->otmpFullName = 0; /* doesn't fit */
1414 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1415 HeapFree(GetProcessHeap(), 0, lpOTMW);
1421 /***********************************************************************
1422 * GetOutlineTextMetricsW [GDI32.@]
1424 UINT WINAPI GetOutlineTextMetricsW(
1425 HDC hdc, /* [in] Handle of device context */
1426 UINT cbData, /* [in] Size of metric data array */
1427 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1429 DC *dc = get_dc_ptr( hdc );
1430 OUTLINETEXTMETRICW *output = lpOTM;
1434 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1437 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1438 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1440 if (lpOTM && ret > cbData)
1442 output = HeapAlloc(GetProcessHeap(), 0, ret);
1443 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1448 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1449 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1451 #define WDPTOLP(x) ((x<0)? \
1452 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1453 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1454 #define HDPTOLP(y) ((y<0)? \
1455 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1456 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1458 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1459 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1460 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1461 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1462 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1463 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1464 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1465 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1466 output->otmAscent = HDPTOLP(output->otmAscent);
1467 output->otmDescent = HDPTOLP(output->otmDescent);
1468 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1469 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1470 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1471 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1472 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1473 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1474 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1475 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1476 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1477 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1478 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1479 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1480 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1481 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1482 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1483 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1484 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1485 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1486 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1487 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1488 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1489 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1494 memcpy(lpOTM, output, cbData);
1495 HeapFree(GetProcessHeap(), 0, output);
1503 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1505 INT i, count = lastChar - firstChar + 1;
1512 switch (GdiGetCodePage(hdc))
1519 if (lastChar > 0xffff)
1521 if ((firstChar ^ lastChar) > 0xff)
1525 if (lastChar > 0xff)
1530 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1534 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1537 str[i++] = (BYTE)(c >> 8);
1547 /***********************************************************************
1548 * GetCharWidthW (GDI32.@)
1549 * GetCharWidth32W (GDI32.@)
1551 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1557 DC * dc = get_dc_ptr( hdc );
1559 if (!dc) return FALSE;
1561 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1562 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1566 /* convert device units to logical */
1567 for( i = firstChar; i <= lastChar; i++, buffer++ )
1568 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1570 release_dc_ptr( dc );
1575 /***********************************************************************
1576 * GetCharWidthA (GDI32.@)
1577 * GetCharWidth32A (GDI32.@)
1579 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1587 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1591 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1593 for(i = 0; i < wlen; i++)
1595 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1603 HeapFree(GetProcessHeap(), 0, str);
1604 HeapFree(GetProcessHeap(), 0, wstr);
1610 /***********************************************************************
1611 * ExtTextOutA (GDI32.@)
1615 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1616 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1624 if (flags & ETO_GLYPH_INDEX)
1625 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1627 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1630 unsigned int i = 0, j = 0;
1632 /* allocate enough for a ETO_PDY */
1633 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1635 if(IsDBCSLeadByteEx(codepage, str[i]))
1639 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1640 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1643 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1650 lpDxW[j++] = lpDx[i * 2];
1651 lpDxW[j++] = lpDx[i * 2 + 1];
1654 lpDxW[j++] = lpDx[i];
1660 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1662 HeapFree( GetProcessHeap(), 0, p );
1663 HeapFree( GetProcessHeap(), 0, lpDxW );
1668 /***********************************************************************
1669 * ExtTextOutW (GDI32.@)
1671 * Draws text using the currently selected font, background color, and text color.
1675 * x,y [I] coordinates of string
1677 * ETO_GRAYED - undocumented on MSDN
1678 * ETO_OPAQUE - use background color for fill the rectangle
1679 * ETO_CLIPPED - clipping text to the rectangle
1680 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1681 * than encoded characters. Implies ETO_IGNORELANGUAGE
1682 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1683 * Affects BiDi ordering
1684 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1685 * ETO_PDY - unimplemented
1686 * ETO_NUMERICSLATIN - unimplemented always assumed -
1687 * do not translate numbers into locale representations
1688 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1689 * lprect [I] dimensions for clipping or/and opaquing
1690 * str [I] text string
1691 * count [I] number of symbols in string
1692 * lpDx [I] optional parameter with distance between drawing characters
1698 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1699 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1702 LPWSTR reordered_str = (LPWSTR)str;
1703 WORD *glyphs = NULL;
1704 UINT align = GetTextAlign( hdc );
1705 DWORD layout = GetLayout( hdc );
1709 double cosEsc, sinEsc;
1713 BOOL done_extents = FALSE;
1714 POINT *deltas = NULL, width = {0, 0};
1716 DC * dc = get_dc_ptr( hdc );
1719 static int quietfixme = 0;
1721 if (!dc) return FALSE;
1723 breakRem = dc->breakRem;
1725 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1727 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1732 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1733 type = GetObjectType(hdc);
1734 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1736 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1737 release_dc_ptr( dc );
1742 flags &= ~ETO_CLIPPED;
1744 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1745 if (layout & LAYOUT_RTL)
1747 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1748 align ^= TA_RTLREADING;
1751 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1754 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1756 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1757 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1758 reordered_str, count, NULL, &glyphs, &cGlyphs);
1760 flags |= ETO_IGNORELANGUAGE;
1763 flags |= ETO_GLYPH_INDEX;
1764 if (cGlyphs != count)
1768 else if(flags & ETO_GLYPH_INDEX)
1769 glyphs = reordered_str;
1771 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1772 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1773 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1775 if(align & TA_UPDATECP)
1777 GetCurrentPositionEx( hdc, &pt );
1782 GetTextMetricsW(hdc, &tm);
1783 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1785 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1786 lf.lfEscapement = 0;
1788 if(lf.lfEscapement != 0)
1790 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1791 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1799 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1803 if(flags & ETO_GLYPH_INDEX)
1804 GetTextExtentPointI(hdc, glyphs, count, &sz);
1806 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1808 done_extents = TRUE;
1811 rc.right = x + sz.cx;
1812 rc.bottom = y + sz.cy;
1819 LPtoDP(hdc, (POINT*)&rc, 2);
1821 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1822 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1825 if (flags & ETO_OPAQUE)
1826 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1836 LPtoDP(hdc, &pt, 1);
1840 char_extra = GetTextCharacterExtra(hdc);
1841 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1845 POINT total = {0, 0}, desired[2];
1847 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1848 for(i = 0; i < count; i++)
1854 deltas[i].x = lpDx[i * 2] + char_extra;
1855 deltas[i].y = -lpDx[i * 2 + 1];
1859 deltas[i].x = lpDx[i] + char_extra;
1866 if(flags & ETO_GLYPH_INDEX)
1867 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1869 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1871 deltas[i].x = tmpsz.cx;
1875 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1877 deltas[i].x = deltas[i].x + dc->breakExtra;
1884 total.x += deltas[i].x;
1885 total.y += deltas[i].y;
1887 desired[0].x = desired[0].y = 0;
1889 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1890 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1892 LPtoDP(hdc, desired, 2);
1893 desired[1].x -= desired[0].x;
1894 desired[1].y -= desired[0].y;
1895 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1897 deltas[i].x = desired[1].x - width.x;
1898 deltas[i].y = desired[1].y - width.y;
1908 if(flags & ETO_GLYPH_INDEX)
1909 GetTextExtentPointI(hdc, glyphs, count, &sz);
1911 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1912 done_extents = TRUE;
1914 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1918 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1919 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1920 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1923 if (align & TA_UPDATECP)
1927 DPtoLP(hdc, &pt, 1);
1928 MoveToEx(hdc, pt.x, pt.y, NULL);
1940 if (align & TA_UPDATECP)
1944 DPtoLP(hdc, &pt, 1);
1945 MoveToEx(hdc, pt.x, pt.y, NULL);
1950 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1953 y += tm.tmAscent * cosEsc;
1954 x += tm.tmAscent * sinEsc;
1958 y -= tm.tmDescent * cosEsc;
1959 x -= tm.tmDescent * sinEsc;
1966 if (GetBkMode(hdc) != TRANSPARENT)
1968 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1970 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
1971 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1975 rc.right = x + width.x;
1976 rc.top = y - tm.tmAscent;
1977 rc.bottom = y + tm.tmDescent;
1979 if(flags & ETO_CLIPPED)
1981 rc.left = max(lprect->left, rc.left);
1982 rc.right = min(lprect->right, rc.right);
1983 rc.top = max(lprect->top, rc.top);
1984 rc.bottom = min(lprect->bottom, rc.bottom);
1986 if(rc.left < rc.right && rc.top < rc.bottom)
1987 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1992 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1994 HFONT orig_font = dc->hFont, cur_font;
1997 POINT *offsets = NULL;
2000 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2001 for(i = 0; i < count; i++)
2003 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2004 if(cur_font != dc->hFont)
2009 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2010 offsets[0].x = offsets[0].y = 0;
2015 for(j = 1; j < count; j++)
2017 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2018 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2024 for(j = 1; j < count; j++)
2026 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2027 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2033 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2034 y + offsets[i - span].y,
2035 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2036 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2039 SelectObject(hdc, cur_font);
2041 glyphs[span++] = glyph;
2045 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2046 y + (offsets ? offsets[count - span].y : 0),
2047 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2048 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2049 SelectObject(hdc, orig_font);
2050 HeapFree(GetProcessHeap(), 0, offsets);
2056 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2058 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2059 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2060 flags |= ETO_GLYPH_INDEX;
2062 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2063 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2067 HeapFree(GetProcessHeap(), 0, deltas);
2068 if(glyphs != reordered_str)
2069 HeapFree(GetProcessHeap(), 0, glyphs);
2070 if(reordered_str != str)
2071 HeapFree(GetProcessHeap(), 0, reordered_str);
2073 release_dc_ptr( dc );
2075 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2077 int underlinePos, strikeoutPos;
2078 int underlineWidth, strikeoutWidth;
2079 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2080 OUTLINETEXTMETRICW* otm = NULL;
2082 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2083 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2085 hbrush = SelectObject(hdc, hbrush);
2090 underlineWidth = tm.tmAscent / 20 + 1;
2091 strikeoutPos = tm.tmAscent / 2;
2092 strikeoutWidth = underlineWidth;
2096 otm = HeapAlloc(GetProcessHeap(), 0, size);
2097 GetOutlineTextMetricsW(hdc, size, otm);
2098 underlinePos = otm->otmsUnderscorePosition;
2099 underlineWidth = otm->otmsUnderscoreSize;
2100 strikeoutPos = otm->otmsStrikeoutPosition;
2101 strikeoutWidth = otm->otmsStrikeoutSize;
2102 HeapFree(GetProcessHeap(), 0, otm);
2108 pts[0].x = x - underlinePos * sinEsc;
2109 pts[0].y = y - underlinePos * cosEsc;
2110 pts[1].x = x + width.x - underlinePos * sinEsc;
2111 pts[1].y = y + width.y - underlinePos * cosEsc;
2112 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2113 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2114 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2115 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2116 pts[4].x = pts[0].x;
2117 pts[4].y = pts[0].y;
2118 DPtoLP(hdc, pts, 5);
2119 Polygon(hdc, pts, 5);
2124 pts[0].x = x - strikeoutPos * sinEsc;
2125 pts[0].y = y - strikeoutPos * cosEsc;
2126 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2127 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2128 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2129 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2130 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2131 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2132 pts[4].x = pts[0].x;
2133 pts[4].y = pts[0].y;
2134 DPtoLP(hdc, pts, 5);
2135 Polygon(hdc, pts, 5);
2138 SelectObject(hdc, hpen);
2139 hbrush = SelectObject(hdc, hbrush);
2140 DeleteObject(hbrush);
2147 /***********************************************************************
2148 * TextOutA (GDI32.@)
2150 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2152 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2156 /***********************************************************************
2157 * TextOutW (GDI32.@)
2159 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2161 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2165 /***********************************************************************
2166 * PolyTextOutA (GDI32.@)
2170 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2172 for (; cStrings>0; cStrings--, pptxt++)
2173 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2180 /***********************************************************************
2181 * PolyTextOutW (GDI32.@)
2183 * Draw several Strings
2189 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2191 for (; cStrings>0; cStrings--, pptxt++)
2192 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2198 /***********************************************************************
2199 * SetMapperFlags (GDI32.@)
2201 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2203 DC *dc = get_dc_ptr( hdc );
2204 DWORD ret = GDI_ERROR;
2208 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2209 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2210 if (flags != GDI_ERROR)
2212 ret = dc->mapperFlags;
2213 dc->mapperFlags = flags;
2215 release_dc_ptr( dc );
2220 /***********************************************************************
2221 * GetAspectRatioFilterEx (GDI32.@)
2223 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2225 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2230 /***********************************************************************
2231 * GetCharABCWidthsA (GDI32.@)
2233 * See GetCharABCWidthsW.
2235 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2243 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2247 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2250 HeapFree(GetProcessHeap(), 0, str);
2254 for(i = 0; i < wlen; i++)
2256 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2264 HeapFree(GetProcessHeap(), 0, str);
2265 HeapFree(GetProcessHeap(), 0, wstr);
2271 /******************************************************************************
2272 * GetCharABCWidthsW [GDI32.@]
2274 * Retrieves widths of characters in range.
2277 * hdc [I] Handle of device context
2278 * firstChar [I] First character in range to query
2279 * lastChar [I] Last character in range to query
2280 * abc [O] Address of character-width structure
2283 * Only works with TrueType fonts
2289 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2292 DC *dc = get_dc_ptr(hdc);
2297 if (!dc) return FALSE;
2301 release_dc_ptr( dc );
2305 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2306 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2309 /* convert device units to logical */
2310 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2311 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2312 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2313 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2317 release_dc_ptr( dc );
2322 /******************************************************************************
2323 * GetCharABCWidthsI [GDI32.@]
2325 * Retrieves widths of characters in range.
2328 * hdc [I] Handle of device context
2329 * firstChar [I] First glyphs in range to query
2330 * count [I] Last glyphs in range to query
2331 * pgi [i] Array of glyphs to query
2332 * abc [O] Address of character-width structure
2335 * Only works with TrueType fonts
2341 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2342 LPWORD pgi, LPABC abc)
2344 DC *dc = get_dc_ptr(hdc);
2349 if (!dc) return FALSE;
2353 release_dc_ptr( dc );
2357 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2358 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2361 /* convert device units to logical */
2362 for( i = 0; i < count; i++, abc++ ) {
2363 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2364 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2365 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2369 release_dc_ptr( dc );
2374 /***********************************************************************
2375 * GetGlyphOutlineA (GDI32.@)
2377 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2378 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2379 LPVOID lpBuffer, const MAT2 *lpmat2 )
2381 if (!lpmat2) return GDI_ERROR;
2383 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2388 cp = GdiGetCodePage(hdc);
2389 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2391 mbchs[0] = (uChar & 0xff00) >> 8;
2392 mbchs[1] = (uChar & 0xff);
2395 mbchs[0] = (uChar & 0xff);
2398 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2401 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2405 /***********************************************************************
2406 * GetGlyphOutlineW (GDI32.@)
2408 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2409 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2410 LPVOID lpBuffer, const MAT2 *lpmat2 )
2416 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2417 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2419 if (!lpmat2) return GDI_ERROR;
2421 dc = get_dc_ptr(hdc);
2422 if(!dc) return GDI_ERROR;
2424 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2425 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2426 release_dc_ptr( dc );
2431 /***********************************************************************
2432 * CreateScalableFontResourceA (GDI32.@)
2434 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2435 LPCSTR lpszResourceFile,
2436 LPCSTR lpszFontFile,
2437 LPCSTR lpszCurrentPath )
2439 LPWSTR lpszResourceFileW = NULL;
2440 LPWSTR lpszFontFileW = NULL;
2441 LPWSTR lpszCurrentPathW = NULL;
2445 if (lpszResourceFile)
2447 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2448 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2449 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2454 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2455 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2456 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2459 if (lpszCurrentPath)
2461 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2462 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2463 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2466 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2467 lpszFontFileW, lpszCurrentPathW);
2469 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2470 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2471 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2476 /***********************************************************************
2477 * CreateScalableFontResourceW (GDI32.@)
2479 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2480 LPCWSTR lpszResourceFile,
2481 LPCWSTR lpszFontFile,
2482 LPCWSTR lpszCurrentPath )
2485 FIXME("(%d,%s,%s,%s): stub\n",
2486 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2487 debugstr_w(lpszCurrentPath) );
2489 /* fHidden=1 - only visible for the calling app, read-only, not
2490 * enumerated with EnumFonts/EnumFontFamilies
2491 * lpszCurrentPath can be NULL
2494 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2495 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2497 SetLastError(ERROR_FILE_EXISTS);
2500 return FALSE; /* create failed */
2503 /*************************************************************************
2504 * GetKerningPairsA (GDI32.@)
2506 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2507 LPKERNINGPAIR kern_pairA )
2511 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2512 KERNINGPAIR *kern_pairW;
2514 if (!cPairs && kern_pairA)
2516 SetLastError(ERROR_INVALID_PARAMETER);
2520 cp = GdiGetCodePage(hDC);
2522 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2523 * to fail on an invalid character for CP_SYMBOL.
2525 cpi.DefaultChar[0] = 0;
2526 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2528 FIXME("Can't find codepage %u info\n", cp);
2532 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2533 if (!total_kern_pairs) return 0;
2535 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2536 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2538 for (i = 0; i < total_kern_pairs; i++)
2542 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2545 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2548 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2553 if (kern_pairs_copied >= cPairs) break;
2555 kern_pairA->wFirst = (BYTE)first;
2556 kern_pairA->wSecond = (BYTE)second;
2557 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2560 kern_pairs_copied++;
2563 HeapFree(GetProcessHeap(), 0, kern_pairW);
2565 return kern_pairs_copied;
2568 /*************************************************************************
2569 * GetKerningPairsW (GDI32.@)
2571 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2572 LPKERNINGPAIR lpKerningPairs )
2578 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2580 if (!cPairs && lpKerningPairs)
2582 SetLastError(ERROR_INVALID_PARAMETER);
2586 dc = get_dc_ptr(hDC);
2589 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2590 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2591 release_dc_ptr( dc );
2595 /*************************************************************************
2596 * TranslateCharsetInfo [GDI32.@]
2598 * Fills a CHARSETINFO structure for a character set, code page, or
2599 * font. This allows making the correspondence between different labels
2600 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2601 * of the same encoding.
2603 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2604 * only one codepage should be set in *lpSrc.
2607 * TRUE on success, FALSE on failure.
2610 BOOL WINAPI TranslateCharsetInfo(
2611 LPDWORD lpSrc, /* [in]
2612 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2613 if flags == TCI_SRCCHARSET: a character set value
2614 if flags == TCI_SRCCODEPAGE: a code page value
2616 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2617 DWORD flags /* [in] determines interpretation of lpSrc */)
2621 case TCI_SRCFONTSIG:
2622 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2624 case TCI_SRCCODEPAGE:
2625 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2627 case TCI_SRCCHARSET:
2628 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2633 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2634 *lpCs = FONT_tci[index];
2638 /*************************************************************************
2639 * GetFontLanguageInfo (GDI32.@)
2641 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2643 FONTSIGNATURE fontsig;
2644 static const DWORD GCP_DBCS_MASK=0x003F0000,
2645 GCP_DIACRITIC_MASK=0x00000000,
2646 FLI_GLYPHS_MASK=0x00000000,
2647 GCP_GLYPHSHAPE_MASK=0x00000040,
2648 GCP_KASHIDA_MASK=0x00000000,
2649 GCP_LIGATE_MASK=0x00000000,
2650 GCP_USEKERNING_MASK=0x00000000,
2651 GCP_REORDER_MASK=0x00000060;
2655 GetTextCharsetInfo( hdc, &fontsig, 0 );
2656 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2658 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2661 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2662 result|=GCP_DIACRITIC;
2664 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2667 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2668 result|=GCP_GLYPHSHAPE;
2670 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2671 result|=GCP_KASHIDA;
2673 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2676 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2677 result|=GCP_USEKERNING;
2679 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2680 if( GetTextAlign( hdc) & TA_RTLREADING )
2681 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2682 result|=GCP_REORDER;
2688 /*************************************************************************
2689 * GetFontData [GDI32.@]
2691 * Retrieve data for TrueType font.
2695 * success: Number of bytes returned
2696 * failure: GDI_ERROR
2700 * Calls SetLastError()
2703 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2704 LPVOID buffer, DWORD length)
2706 DC *dc = get_dc_ptr(hdc);
2710 if(!dc) return GDI_ERROR;
2712 dev = GET_DC_PHYSDEV( dc, pGetFontData );
2713 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
2714 release_dc_ptr( dc );
2718 /*************************************************************************
2719 * GetGlyphIndicesA [GDI32.@]
2721 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2722 LPWORD pgi, DWORD flags)
2728 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2729 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2731 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2732 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2733 HeapFree(GetProcessHeap(), 0, lpstrW);
2738 /*************************************************************************
2739 * GetGlyphIndicesW [GDI32.@]
2741 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2742 LPWORD pgi, DWORD flags)
2744 DC *dc = get_dc_ptr(hdc);
2748 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2749 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2751 if(!dc) return GDI_ERROR;
2753 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
2754 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
2755 release_dc_ptr( dc );
2759 /*************************************************************************
2760 * GetCharacterPlacementA [GDI32.@]
2762 * See GetCharacterPlacementW.
2765 * the web browser control of ie4 calls this with dwFlags=0
2768 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2769 INT nMaxExtent, GCP_RESULTSA *lpResults,
2774 GCP_RESULTSW resultsW;
2778 TRACE("%s, %d, %d, 0x%08x\n",
2779 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2781 /* both structs are equal in size */
2782 memcpy(&resultsW, lpResults, sizeof(resultsW));
2784 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2785 if(lpResults->lpOutString)
2786 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2788 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2790 lpResults->nGlyphs = resultsW.nGlyphs;
2791 lpResults->nMaxFit = resultsW.nMaxFit;
2793 if(lpResults->lpOutString) {
2794 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2795 lpResults->lpOutString, uCount, NULL, NULL );
2798 HeapFree(GetProcessHeap(), 0, lpStringW);
2799 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2804 /*************************************************************************
2805 * GetCharacterPlacementW [GDI32.@]
2807 * Retrieve information about a string. This includes the width, reordering,
2808 * Glyphing and so on.
2812 * The width and height of the string if successful, 0 if failed.
2816 * All flags except GCP_REORDER are not yet implemented.
2817 * Reordering is not 100% compliant to the Windows BiDi method.
2818 * Caret positioning is not yet implemented for BiDi.
2819 * Classes are not yet implemented.
2823 GetCharacterPlacementW(
2824 HDC hdc, /* [in] Device context for which the rendering is to be done */
2825 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2826 INT uCount, /* [in] Number of WORDS in string. */
2827 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2828 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2829 DWORD dwFlags /* [in] Flags specifying how to process the string */
2836 TRACE("%s, %d, %d, 0x%08x\n",
2837 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2839 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2840 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2841 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2842 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2843 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2845 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2846 if(lpResults->lpClass) FIXME("classes not implemented\n");
2847 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2848 FIXME("Caret positions for complex scripts not implemented\n");
2850 nSet = (UINT)uCount;
2851 if(nSet > lpResults->nGlyphs)
2852 nSet = lpResults->nGlyphs;
2854 /* return number of initialized fields */
2855 lpResults->nGlyphs = nSet;
2857 if((dwFlags&GCP_REORDER)==0 )
2859 /* Treat the case where no special handling was requested in a fastpath way */
2860 /* copy will do if the GCP_REORDER flag is not set */
2861 if(lpResults->lpOutString)
2862 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2864 if(lpResults->lpOrder)
2866 for(i = 0; i < nSet; i++)
2867 lpResults->lpOrder[i] = i;
2871 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2872 nSet, lpResults->lpOrder, NULL, NULL );
2875 /* FIXME: Will use the placement chars */
2876 if (lpResults->lpDx)
2879 for (i = 0; i < nSet; i++)
2881 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2882 lpResults->lpDx[i]= c;
2886 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2890 lpResults->lpCaretPos[0] = 0;
2891 for (i = 1; i < nSet; i++)
2892 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2893 lpResults->lpCaretPos[i] = (pos += size.cx);
2896 if(lpResults->lpGlyphs)
2897 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2899 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2900 ret = MAKELONG(size.cx, size.cy);
2905 /*************************************************************************
2906 * GetCharABCWidthsFloatA [GDI32.@]
2908 * See GetCharABCWidthsFloatW.
2910 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2917 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
2921 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
2923 for (i = 0; i < wlen; i++)
2925 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2933 HeapFree( GetProcessHeap(), 0, str );
2934 HeapFree( GetProcessHeap(), 0, wstr );
2939 /*************************************************************************
2940 * GetCharABCWidthsFloatW [GDI32.@]
2942 * Retrieves widths of a range of characters.
2945 * hdc [I] Handle to device context.
2946 * first [I] First character in range to query.
2947 * last [I] Last character in range to query.
2948 * abcf [O] Array of LPABCFLOAT structures.
2954 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2960 DC *dc = get_dc_ptr( hdc );
2962 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
2964 if (!dc) return FALSE;
2966 if (!abcf) goto done;
2967 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
2969 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2970 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
2973 /* convert device units to logical */
2974 for (i = first; i <= last; i++, abcf++)
2976 abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
2977 abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
2978 abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
2981 HeapFree( GetProcessHeap(), 0, abc );
2984 release_dc_ptr( dc );
2988 /*************************************************************************
2989 * GetCharWidthFloatA [GDI32.@]
2991 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2992 UINT iLastChar, PFLOAT pxBuffer)
2994 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2998 /*************************************************************************
2999 * GetCharWidthFloatW [GDI32.@]
3001 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3002 UINT iLastChar, PFLOAT pxBuffer)
3004 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3009 /***********************************************************************
3011 * Font Resource API *
3013 ***********************************************************************/
3015 /***********************************************************************
3016 * AddFontResourceA (GDI32.@)
3018 INT WINAPI AddFontResourceA( LPCSTR str )
3020 return AddFontResourceExA( str, 0, NULL);
3023 /***********************************************************************
3024 * AddFontResourceW (GDI32.@)
3026 INT WINAPI AddFontResourceW( LPCWSTR str )
3028 return AddFontResourceExW(str, 0, NULL);
3032 /***********************************************************************
3033 * AddFontResourceExA (GDI32.@)
3035 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3037 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3038 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3041 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3042 ret = AddFontResourceExW(strW, fl, pdv);
3043 HeapFree(GetProcessHeap(), 0, strW);
3047 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3049 HRSRC rsrc = FindResourceW(hModule, name, type);
3050 HGLOBAL hMem = LoadResource(hModule, rsrc);
3051 LPVOID *pMem = LockResource(hMem);
3052 int *num_total = (int *)lParam;
3055 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3056 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3058 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3062 *num_total += num_in_res;
3066 /***********************************************************************
3067 * AddFontResourceExW (GDI32.@)
3069 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3071 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3074 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3075 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3076 if (hModule != NULL)
3078 int num_resources = 0;
3079 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3081 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3082 wine_dbgstr_w(str));
3083 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3084 ret = num_resources;
3085 FreeLibrary(hModule);
3091 /***********************************************************************
3092 * RemoveFontResourceA (GDI32.@)
3094 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3096 return RemoveFontResourceExA(str, 0, 0);
3099 /***********************************************************************
3100 * RemoveFontResourceW (GDI32.@)
3102 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3104 return RemoveFontResourceExW(str, 0, 0);
3107 /***********************************************************************
3108 * AddFontMemResourceEx (GDI32.@)
3110 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3115 if (!pbFont || !cbFont || !pcFonts)
3117 SetLastError(ERROR_INVALID_PARAMETER);
3121 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3126 *pcFonts = num_fonts;
3130 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3131 RemoveFontMemResourceEx(ret);
3139 /***********************************************************************
3140 * RemoveFontMemResourceEx (GDI32.@)
3142 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3144 FIXME("(%p) stub\n", fh);
3148 /***********************************************************************
3149 * RemoveFontResourceExA (GDI32.@)
3151 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3153 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3154 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3157 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3158 ret = RemoveFontResourceExW(strW, fl, pdv);
3159 HeapFree(GetProcessHeap(), 0, strW);
3163 /***********************************************************************
3164 * RemoveFontResourceExW (GDI32.@)
3166 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3168 return WineEngRemoveFontResourceEx(str, fl, pdv);
3171 /***********************************************************************
3172 * GetTextCharset (GDI32.@)
3174 UINT WINAPI GetTextCharset(HDC hdc)
3176 /* MSDN docs say this is equivalent */
3177 return GetTextCharsetInfo(hdc, NULL, 0);
3180 /***********************************************************************
3181 * GetTextCharsetInfo (GDI32.@)
3183 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3185 UINT ret = DEFAULT_CHARSET;
3186 DC *dc = get_dc_ptr(hdc);
3191 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3192 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3193 release_dc_ptr( dc );
3196 if (ret == DEFAULT_CHARSET && fs)
3197 memset(fs, 0, sizeof(FONTSIGNATURE));
3201 /***********************************************************************
3202 * GdiGetCharDimensions (GDI32.@)
3204 * Gets the average width of the characters in the English alphabet.
3207 * hdc [I] Handle to the device context to measure on.
3208 * lptm [O] Pointer to memory to store the text metrics into.
3209 * height [O] On exit, the maximum height of characters in the English alphabet.
3212 * The average width of characters in the English alphabet.
3215 * This function is used by the dialog manager to get the size of a dialog
3216 * unit. It should also be used by other pieces of code that need to know
3217 * the size of a dialog unit in logical units without having access to the
3218 * window handle of the dialog.
3219 * Windows caches the font metrics from this function, but we don't and
3220 * there doesn't appear to be an immediate advantage to do so.
3223 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3225 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3228 static const WCHAR alphabet[] = {
3229 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3230 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3231 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3233 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3235 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3237 if (height) *height = sz.cy;
3238 return (sz.cx / 26 + 1) / 2;
3241 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3243 FIXME("(%d): stub\n", fEnableEUDC);
3247 /***********************************************************************
3248 * GetCharWidthI (GDI32.@)
3250 * Retrieve widths of characters.
3253 * hdc [I] Handle to a device context.
3254 * first [I] First glyph in range to query.
3255 * count [I] Number of glyph indices to query.
3256 * glyphs [I] Array of glyphs to query.
3257 * buffer [O] Buffer to receive character widths.
3260 * Only works with TrueType fonts.
3266 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3271 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3273 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3276 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3278 HeapFree(GetProcessHeap(), 0, abc);
3282 for (i = 0; i < count; i++)
3283 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3285 HeapFree(GetProcessHeap(), 0, abc);
3289 /***********************************************************************
3290 * GetFontUnicodeRanges (GDI32.@)
3292 * Retrieve a list of supported Unicode characters in a font.
3295 * hdc [I] Handle to a device context.
3296 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3299 * Success: Number of bytes written to the buffer pointed to by lpgs.
3303 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3307 DC *dc = get_dc_ptr(hdc);
3309 TRACE("(%p, %p)\n", hdc, lpgs);
3313 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3314 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3320 /*************************************************************
3321 * FontIsLinked (GDI32.@)
3323 BOOL WINAPI FontIsLinked(HDC hdc)
3325 DC *dc = get_dc_ptr(hdc);
3329 if (!dc) return FALSE;
3330 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3331 ret = dev->funcs->pFontIsLinked( dev );
3333 TRACE("returning %d\n", ret);
3337 /*************************************************************
3338 * GdiRealizationInfo (GDI32.@)
3340 * Returns a structure that contains some font information.
3342 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3344 DC *dc = get_dc_ptr(hdc);
3348 if (!dc) return FALSE;
3349 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3350 ret = dev->funcs->pGdiRealizationInfo( dev, info );