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"
35 #include "gdi_private.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( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
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 /***********************************************************************
197 * TEXTMETRIC conversion functions.
199 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
201 ptmA->tmHeight = ptmW->tmHeight;
202 ptmA->tmAscent = ptmW->tmAscent;
203 ptmA->tmDescent = ptmW->tmDescent;
204 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
205 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
206 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
207 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
208 ptmA->tmWeight = ptmW->tmWeight;
209 ptmA->tmOverhang = ptmW->tmOverhang;
210 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
211 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
212 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
213 if (ptmW->tmCharSet == SYMBOL_CHARSET)
215 ptmA->tmFirstChar = 0x1e;
216 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
220 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
221 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
223 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
224 ptmA->tmBreakChar = ptmW->tmBreakChar;
225 ptmA->tmItalic = ptmW->tmItalic;
226 ptmA->tmUnderlined = ptmW->tmUnderlined;
227 ptmA->tmStruckOut = ptmW->tmStruckOut;
228 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
229 ptmA->tmCharSet = ptmW->tmCharSet;
233 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
235 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
236 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
237 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
238 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
239 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
240 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
244 /***********************************************************************
245 * GdiGetCodePage (GDI32.@)
247 DWORD WINAPI GdiGetCodePage( HDC hdc )
250 DC *dc = get_dc_ptr( hdc );
254 cp = dc->font_code_page;
255 release_dc_ptr( dc );
260 /***********************************************************************
263 * Returns a Unicode translation of str using the charset of the
264 * currently selected font in hdc. If count is -1 then str is assumed
265 * to be '\0' terminated, otherwise it contains the number of bytes to
266 * convert. If plenW is non-NULL, on return it will point to the
267 * number of WCHARs that have been written. If pCP is non-NULL, on
268 * return it will point to the codepage used in the conversion. The
269 * caller should free the returned LPWSTR from the process heap
272 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
278 cp = GdiGetCodePage( hdc );
280 if(count == -1) count = strlen(str);
281 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
282 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
283 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
284 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
285 if(plenW) *plenW = lenW;
291 /***********************************************************************
292 * CreateFontIndirectA (GDI32.@)
294 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
300 FONT_LogFontAToW( plfA, &lfW );
301 return CreateFontIndirectW( &lfW );
304 /***********************************************************************
305 * CreateFontIndirectW (GDI32.@)
307 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
309 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
310 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
311 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
312 WCHAR *pFaceNameSuffix = NULL;
318 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
320 fontPtr->logfont = *plf;
322 if (plf->lfEscapement != plf->lfOrientation)
324 /* this should really depend on whether GM_ADVANCED is set */
325 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
326 WARN("orientation angle %f set to "
327 "escapement angle %f for new font %p\n",
328 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
331 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
332 if (pFaceNameItalicSuffix)
334 fontPtr->logfont.lfItalic = TRUE;
335 pFaceNameSuffix = pFaceNameItalicSuffix;
338 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
339 if (pFaceNameBoldSuffix)
341 if (fontPtr->logfont.lfWeight < FW_BOLD)
342 fontPtr->logfont.lfWeight = FW_BOLD;
343 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
344 pFaceNameSuffix = pFaceNameBoldSuffix;
347 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
349 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
351 HeapFree( GetProcessHeap(), 0, fontPtr );
355 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
356 plf->lfHeight, plf->lfWidth,
357 plf->lfEscapement, plf->lfOrientation,
358 plf->lfPitchAndFamily,
359 plf->lfOutPrecision, plf->lfClipPrecision,
360 plf->lfQuality, plf->lfCharSet,
361 debugstr_w(plf->lfFaceName),
362 plf->lfWeight > 400 ? "Bold" : "",
363 plf->lfItalic ? "Italic" : "",
364 plf->lfUnderline ? "Underline" : "", hFont);
369 /*************************************************************************
370 * CreateFontA (GDI32.@)
372 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
373 INT orient, INT weight, DWORD italic,
374 DWORD underline, DWORD strikeout, DWORD charset,
375 DWORD outpres, DWORD clippres, DWORD quality,
376 DWORD pitch, LPCSTR name )
380 logfont.lfHeight = height;
381 logfont.lfWidth = width;
382 logfont.lfEscapement = esc;
383 logfont.lfOrientation = orient;
384 logfont.lfWeight = weight;
385 logfont.lfItalic = italic;
386 logfont.lfUnderline = underline;
387 logfont.lfStrikeOut = strikeout;
388 logfont.lfCharSet = charset;
389 logfont.lfOutPrecision = outpres;
390 logfont.lfClipPrecision = clippres;
391 logfont.lfQuality = quality;
392 logfont.lfPitchAndFamily = pitch;
395 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
397 logfont.lfFaceName[0] = '\0';
399 return CreateFontIndirectA( &logfont );
402 /*************************************************************************
403 * CreateFontW (GDI32.@)
405 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
406 INT orient, INT weight, DWORD italic,
407 DWORD underline, DWORD strikeout, DWORD charset,
408 DWORD outpres, DWORD clippres, DWORD quality,
409 DWORD pitch, LPCWSTR name )
413 logfont.lfHeight = height;
414 logfont.lfWidth = width;
415 logfont.lfEscapement = esc;
416 logfont.lfOrientation = orient;
417 logfont.lfWeight = weight;
418 logfont.lfItalic = italic;
419 logfont.lfUnderline = underline;
420 logfont.lfStrikeOut = strikeout;
421 logfont.lfCharSet = charset;
422 logfont.lfOutPrecision = outpres;
423 logfont.lfClipPrecision = clippres;
424 logfont.lfQuality = quality;
425 logfont.lfPitchAndFamily = pitch;
428 lstrcpynW(logfont.lfFaceName, name,
429 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
431 logfont.lfFaceName[0] = '\0';
433 return CreateFontIndirectW( &logfont );
436 static void update_font_code_page( DC *dc )
439 int charset = DEFAULT_CHARSET;
442 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
444 /* Hmm, nicely designed api this one! */
445 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
446 dc->font_code_page = csi.ciACP;
450 dc->font_code_page = GetOEMCP();
452 case DEFAULT_CHARSET:
453 dc->font_code_page = GetACP();
463 /* FIXME: These have no place here, but because x11drv
464 enumerates fonts with these (made up) charsets some apps
465 might use them and then the FIXME below would become
466 annoying. Now we could pick the intended codepage for
467 each of these, but since it's broken anyway we'll just
468 use CP_ACP and hope it'll go away...
470 dc->font_code_page = CP_ACP;
474 FIXME("Can't find codepage for charset %d\n", charset);
475 dc->font_code_page = CP_ACP;
480 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
483 /***********************************************************************
486 * If the driver supports vector fonts we create a gdi font first and
487 * then call the driver to give it a chance to supply its own device
488 * font. If the driver wants to do this it returns TRUE and we can
489 * delete the gdi font, if the driver wants to use the gdi font it
490 * should return FALSE, to signal an error return GDI_ERROR. For
491 * drivers that don't support vector fonts they must supply their own
494 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
497 DC *dc = get_dc_ptr( hdc );
501 if (!GDI_inc_ref_count( handle ))
503 release_dc_ptr( dc );
507 if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
508 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
510 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
512 if (ret && dc->gdiFont) dc->gdiFont = 0;
514 if (ret == HGDI_ERROR)
516 GDI_dec_ref_count( handle );
517 ret = 0; /* SelectObject returns 0 on error */
523 update_font_code_page( dc );
524 GDI_dec_ref_count( ret );
526 release_dc_ptr( dc );
531 /***********************************************************************
534 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
536 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
542 FONT_LogFontWToA( &font->logfont, &lfA );
543 if (count > sizeof(lfA)) count = sizeof(lfA);
544 memcpy( buffer, &lfA, count );
546 else count = sizeof(lfA);
547 GDI_ReleaseObj( handle );
551 /***********************************************************************
554 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
556 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
561 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
562 memcpy( buffer, &font->logfont, count );
564 else count = sizeof(LOGFONTW);
565 GDI_ReleaseObj( handle );
570 /***********************************************************************
573 static BOOL FONT_DeleteObject( HGDIOBJ handle )
577 WineEngDestroyFontInstance( handle );
579 if (!(obj = free_gdi_handle( handle ))) return FALSE;
580 return HeapFree( GetProcessHeap(), 0, obj );
584 /***********************************************************************
587 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
588 * We have to use other types because of the FONTENUMPROCW definition.
590 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
591 DWORD fType, LPARAM lp )
593 fontEnum32 *pfe = (fontEnum32*)lp;
596 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
597 if ((!pfe->lpLogFontParam ||
598 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
599 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
600 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
602 /* convert font metrics */
603 ENUMLOGFONTEXA logfont;
604 NEWTEXTMETRICEXA tmA;
606 pfe->dwFlags |= ENUM_CALLED;
607 if (!(pfe->dwFlags & ENUM_UNICODE))
609 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
610 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
611 plf = (LOGFONTW *)&logfont.elfLogFont;
612 ptm = (TEXTMETRICW *)&tmA;
615 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
620 /***********************************************************************
621 * FONT_EnumFontFamiliesEx
623 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
624 FONTENUMPROCW efproc,
625 LPARAM lParam, DWORD dwUnicode)
628 DC *dc = get_dc_ptr( hDC );
635 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
637 fe32.lpLogFontParam = plf;
638 fe32.lpEnumFunc = efproc;
639 fe32.lpData = lParam;
640 fe32.dwFlags = dwUnicode;
643 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
645 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
652 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
653 fe32.dwFlags &= ~ENUM_CALLED;
654 if (ret && dc->funcs->pEnumDeviceFonts) {
655 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
656 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
660 release_dc_ptr( dc );
664 /***********************************************************************
665 * EnumFontFamiliesExW (GDI32.@)
667 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
668 FONTENUMPROCW efproc,
669 LPARAM lParam, DWORD dwFlags )
671 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
674 /***********************************************************************
675 * EnumFontFamiliesExA (GDI32.@)
677 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
678 FONTENUMPROCA efproc,
679 LPARAM lParam, DWORD dwFlags)
685 FONT_LogFontAToW( plf, &lfW );
690 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
693 /***********************************************************************
694 * EnumFontFamiliesA (GDI32.@)
696 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
697 FONTENUMPROCA efproc, LPARAM lpData )
703 if (!*lpFamily) return 1;
704 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
705 lf.lfCharSet = DEFAULT_CHARSET;
706 lf.lfPitchAndFamily = 0;
711 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
714 /***********************************************************************
715 * EnumFontFamiliesW (GDI32.@)
717 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
718 FONTENUMPROCW efproc, LPARAM lpData )
724 if (!*lpFamily) return 1;
725 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
726 lf.lfCharSet = DEFAULT_CHARSET;
727 lf.lfPitchAndFamily = 0;
732 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
735 /***********************************************************************
736 * EnumFontsA (GDI32.@)
738 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
741 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
744 /***********************************************************************
745 * EnumFontsW (GDI32.@)
747 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
750 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
754 /***********************************************************************
755 * GetTextCharacterExtra (GDI32.@)
757 INT WINAPI GetTextCharacterExtra( HDC hdc )
760 DC *dc = get_dc_ptr( hdc );
761 if (!dc) return 0x80000000;
763 release_dc_ptr( dc );
768 /***********************************************************************
769 * SetTextCharacterExtra (GDI32.@)
771 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
774 DC * dc = get_dc_ptr( hdc );
775 if (!dc) return 0x80000000;
776 if (dc->funcs->pSetTextCharacterExtra)
777 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
780 prev = dc->charExtra;
781 dc->charExtra = extra;
783 release_dc_ptr( dc );
788 /***********************************************************************
789 * SetTextJustification (GDI32.@)
791 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
794 DC * dc = get_dc_ptr( hdc );
795 if (!dc) return FALSE;
796 if (dc->funcs->pSetTextJustification)
797 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
800 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
801 if (!extra) breaks = 0;
804 dc->breakExtra = extra / breaks;
805 dc->breakRem = extra - (breaks * dc->breakExtra);
813 release_dc_ptr( dc );
818 /***********************************************************************
819 * GetTextFaceA (GDI32.@)
821 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
823 INT res = GetTextFaceW(hdc, 0, NULL);
824 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
825 GetTextFaceW( hdc, res, nameW );
831 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
835 /* GetTextFaceA does NOT include the nul byte in the return count. */
842 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
843 HeapFree( GetProcessHeap(), 0, nameW );
847 /***********************************************************************
848 * GetTextFaceW (GDI32.@)
850 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
855 DC * dc = get_dc_ptr( hdc );
859 ret = WineEngGetTextFace(dc->gdiFont, count, name);
860 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
862 INT n = strlenW(font->logfont.lfFaceName) + 1;
865 lstrcpynW( name, font->logfont.lfFaceName, count );
869 GDI_ReleaseObj( dc->hFont );
871 release_dc_ptr( dc );
876 /***********************************************************************
877 * GetTextExtentPoint32A (GDI32.@)
879 * See GetTextExtentPoint32W.
881 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
886 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
889 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
890 HeapFree( GetProcessHeap(), 0, p );
893 TRACE("(%p %s %d %p): returning %d x %d\n",
894 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
899 /***********************************************************************
900 * GetTextExtentPoint32W [GDI32.@]
902 * Computes width/height for a string.
904 * Computes width and height of the specified string.
910 BOOL WINAPI GetTextExtentPoint32W(
911 HDC hdc, /* [in] Handle of device context */
912 LPCWSTR str, /* [in] Address of text string */
913 INT count, /* [in] Number of characters in string */
914 LPSIZE size) /* [out] Address of structure for string size */
916 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
919 /***********************************************************************
920 * GetTextExtentExPointI [GDI32.@]
922 * Computes width and height of the array of glyph indices.
925 * hdc [I] Handle of device context.
926 * indices [I] Glyph index array.
927 * count [I] Number of glyphs in array.
928 * max_ext [I] Maximum width in glyphs.
929 * nfit [O] Maximum number of characters.
930 * dxs [O] Partial string widths.
931 * size [O] Returned string size.
937 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
938 LPINT nfit, LPINT dxs, LPSIZE size )
941 DC * dc = get_dc_ptr( hdc );
942 if (!dc) return FALSE;
945 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
946 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
947 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
948 size->cx += count * dc->charExtra;
950 else if(dc->funcs->pGetTextExtentExPoint) {
951 FIXME("calling GetTextExtentExPoint\n");
952 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, indices, count,
953 max_ext, nfit, dxs, size );
956 release_dc_ptr( dc );
958 TRACE("(%p %p %d %p): returning %d x %d\n",
959 hdc, indices, count, size, size->cx, size->cy );
963 /***********************************************************************
964 * GetTextExtentPointI [GDI32.@]
966 * Computes width and height of the array of glyph indices.
969 * hdc [I] Handle of device context.
970 * indices [I] Glyph index array.
971 * count [I] Number of glyphs in array.
972 * size [O] Returned string size.
978 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
980 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
984 /***********************************************************************
985 * GetTextExtentPointA (GDI32.@)
987 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
990 TRACE("not bug compatible.\n");
991 return GetTextExtentPoint32A( hdc, str, count, size );
994 /***********************************************************************
995 * GetTextExtentPointW (GDI32.@)
997 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1000 TRACE("not bug compatible.\n");
1001 return GetTextExtentPoint32W( hdc, str, count, size );
1005 /***********************************************************************
1006 * GetTextExtentExPointA (GDI32.@)
1008 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1009 INT maxExt, LPINT lpnFit,
1010 LPINT alpDx, LPSIZE size )
1018 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1021 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1022 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1025 INT n = lpnFit ? *lpnFit : wlen;
1027 for(i = 0, j = 0; i < n; i++, j++)
1029 alpDx[j] = walpDx[i];
1030 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1033 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1034 HeapFree( GetProcessHeap(), 0, p );
1035 HeapFree( GetProcessHeap(), 0, walpDx );
1040 /***********************************************************************
1041 * GetTextExtentExPointW (GDI32.@)
1043 * Return the size of the string as it would be if it was output properly by
1046 * This should include
1047 * - Intercharacter spacing
1048 * - justification spacing (not yet done)
1049 * - kerning? see below
1051 * Kerning. Since kerning would be carried out by the rendering code it should
1052 * be done by the driver. However they don't support it yet. Also I am not
1053 * yet persuaded that (certainly under Win95) any kerning is actually done.
1055 * str: According to MSDN this should be null-terminated. That is not true; a
1056 * null will not terminate it early.
1057 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1058 * than count. I have seen it be either the size of the full string or
1059 * 1 less than the size of the full string. I have not seen it bear any
1060 * resemblance to the portion that would fit.
1061 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1062 * trailing intercharacter spacing and any trailing justification.
1065 * Currently we do this by measuring each character etc. We should do it by
1066 * passing the request to the driver, perhaps by extending the
1067 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1068 * thinking about kerning issues and rounding issues in the justification.
1071 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1072 INT maxExt, LPINT lpnFit,
1073 LPINT alpDx, LPSIZE size )
1081 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1083 dc = get_dc_ptr(hdc);
1087 GetTextMetricsW(hdc, &tm);
1089 /* If we need to calculate nFit, then we need the partial extents even if
1090 the user hasn't provided us with an array. */
1093 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1097 SetLastError(ERROR_OUTOFMEMORY);
1105 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1106 0, NULL, dxs, size);
1107 else if (dc->funcs->pGetTextExtentExPoint)
1108 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1109 0, NULL, dxs, size);
1111 /* Perform device size to world size transformations. */
1114 INT extra = dc->charExtra,
1115 breakExtra = dc->breakExtra,
1116 breakRem = dc->breakRem,
1121 for (i = 0; i < count; ++i)
1123 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1124 dxs[i] += (i+1) * extra;
1125 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1127 dxs[i] += breakExtra;
1134 if (dxs[i] <= maxExt)
1137 breakRem = dc->breakRem;
1139 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1140 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1142 if (!dxs && count > 1 && (breakExtra || breakRem))
1144 for (i = 0; i < count; i++)
1146 if (str[i] == tm.tmBreakChar)
1148 size->cx += breakExtra;
1163 HeapFree(GetProcessHeap(), 0, dxs);
1165 release_dc_ptr( dc );
1167 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1171 /***********************************************************************
1172 * GetTextMetricsA (GDI32.@)
1174 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1178 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1179 FONT_TextMetricWToA( &tm32, metrics );
1183 /***********************************************************************
1184 * GetTextMetricsW (GDI32.@)
1186 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1189 DC * dc = get_dc_ptr( hdc );
1190 if (!dc) return FALSE;
1193 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1194 else if (dc->funcs->pGetTextMetrics)
1195 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1199 /* device layer returns values in device units
1200 * therefore we have to convert them to logical */
1202 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1203 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1205 #define WDPTOLP(x) ((x<0)? \
1206 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1207 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1208 #define HDPTOLP(y) ((y<0)? \
1209 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1210 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1212 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1213 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1214 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1215 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1216 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1217 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1218 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1219 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1223 TRACE("text metrics:\n"
1224 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1225 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1226 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1227 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1228 " PitchAndFamily = %02x\n"
1229 " --------------------\n"
1230 " InternalLeading = %i\n"
1234 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1235 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1236 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1237 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1238 metrics->tmPitchAndFamily,
1239 metrics->tmInternalLeading,
1242 metrics->tmHeight );
1244 release_dc_ptr( dc );
1249 /***********************************************************************
1250 * GetOutlineTextMetricsA (GDI32.@)
1251 * Gets metrics for TrueType fonts.
1254 * If the supplied buffer isn't big enough Windows partially fills it up to
1255 * its given length and returns that length.
1258 * Success: Non-zero or size of required buffer
1261 UINT WINAPI GetOutlineTextMetricsA(
1262 HDC hdc, /* [in] Handle of device context */
1263 UINT cbData, /* [in] Size of metric data array */
1264 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1266 char buf[512], *ptr;
1268 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1269 OUTLINETEXTMETRICA *output = lpOTM;
1272 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1274 if(ret > sizeof(buf))
1275 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1276 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1278 needed = sizeof(OUTLINETEXTMETRICA);
1279 if(lpOTMW->otmpFamilyName)
1280 needed += WideCharToMultiByte(CP_ACP, 0,
1281 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1282 NULL, 0, NULL, NULL);
1283 if(lpOTMW->otmpFaceName)
1284 needed += WideCharToMultiByte(CP_ACP, 0,
1285 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1286 NULL, 0, NULL, NULL);
1287 if(lpOTMW->otmpStyleName)
1288 needed += WideCharToMultiByte(CP_ACP, 0,
1289 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1290 NULL, 0, NULL, NULL);
1291 if(lpOTMW->otmpFullName)
1292 needed += WideCharToMultiByte(CP_ACP, 0,
1293 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1294 NULL, 0, NULL, NULL);
1301 TRACE("needed = %d\n", needed);
1303 /* Since the supplied buffer isn't big enough, we'll alloc one
1304 that is and memcpy the first cbData bytes into the lpOTM at
1306 output = HeapAlloc(GetProcessHeap(), 0, needed);
1308 ret = output->otmSize = min(needed, cbData);
1309 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1310 output->otmFiller = 0;
1311 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1312 output->otmfsSelection = lpOTMW->otmfsSelection;
1313 output->otmfsType = lpOTMW->otmfsType;
1314 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1315 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1316 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1317 output->otmEMSquare = lpOTMW->otmEMSquare;
1318 output->otmAscent = lpOTMW->otmAscent;
1319 output->otmDescent = lpOTMW->otmDescent;
1320 output->otmLineGap = lpOTMW->otmLineGap;
1321 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1322 output->otmsXHeight = lpOTMW->otmsXHeight;
1323 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1324 output->otmMacAscent = lpOTMW->otmMacAscent;
1325 output->otmMacDescent = lpOTMW->otmMacDescent;
1326 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1327 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1328 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1329 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1330 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1331 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1332 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1333 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1334 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1335 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1338 ptr = (char*)(output + 1);
1339 left = needed - sizeof(*output);
1341 if(lpOTMW->otmpFamilyName) {
1342 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1343 len = WideCharToMultiByte(CP_ACP, 0,
1344 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1345 ptr, left, NULL, NULL);
1349 output->otmpFamilyName = 0;
1351 if(lpOTMW->otmpFaceName) {
1352 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1353 len = WideCharToMultiByte(CP_ACP, 0,
1354 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1355 ptr, left, NULL, NULL);
1359 output->otmpFaceName = 0;
1361 if(lpOTMW->otmpStyleName) {
1362 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1363 len = WideCharToMultiByte(CP_ACP, 0,
1364 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1365 ptr, left, NULL, NULL);
1369 output->otmpStyleName = 0;
1371 if(lpOTMW->otmpFullName) {
1372 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1373 len = WideCharToMultiByte(CP_ACP, 0,
1374 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1375 ptr, left, NULL, NULL);
1378 output->otmpFullName = 0;
1382 if(output != lpOTM) {
1383 memcpy(lpOTM, output, cbData);
1384 HeapFree(GetProcessHeap(), 0, output);
1386 /* check if the string offsets really fit into the provided size */
1387 /* FIXME: should we check string length as well? */
1388 /* make sure that we don't read/write beyond the provided buffer */
1389 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1391 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1392 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1395 /* make sure that we don't read/write beyond the provided buffer */
1396 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1398 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1399 lpOTM->otmpFaceName = 0; /* doesn't fit */
1402 /* make sure that we don't read/write beyond the provided buffer */
1403 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1405 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1406 lpOTM->otmpStyleName = 0; /* doesn't fit */
1409 /* make sure that we don't read/write beyond the provided buffer */
1410 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1412 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1413 lpOTM->otmpFullName = 0; /* doesn't fit */
1418 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1419 HeapFree(GetProcessHeap(), 0, lpOTMW);
1425 /***********************************************************************
1426 * GetOutlineTextMetricsW [GDI32.@]
1428 UINT WINAPI GetOutlineTextMetricsW(
1429 HDC hdc, /* [in] Handle of device context */
1430 UINT cbData, /* [in] Size of metric data array */
1431 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1433 DC *dc = get_dc_ptr( hdc );
1434 OUTLINETEXTMETRICW *output = lpOTM;
1437 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1441 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1444 output = HeapAlloc(GetProcessHeap(), 0, ret);
1445 WineEngGetOutlineTextMetrics(dc->gdiFont, 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);
1492 if(output != lpOTM) {
1493 memcpy(lpOTM, output, cbData);
1494 HeapFree(GetProcessHeap(), 0, output);
1500 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1501 but really this should just be a return 0. */
1503 ret = sizeof(*lpOTM);
1508 memset(lpOTM, 0, ret);
1509 lpOTM->otmSize = sizeof(*lpOTM);
1510 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1512 Further fill of the structure not implemented,
1513 Needs real values for the structure members
1523 /***********************************************************************
1524 * GetCharWidthW (GDI32.@)
1525 * GetCharWidth32W (GDI32.@)
1527 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1532 DC * dc = get_dc_ptr( hdc );
1533 if (!dc) return FALSE;
1536 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1537 else if (dc->funcs->pGetCharWidth)
1538 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1542 /* convert device units to logical */
1543 for( i = firstChar; i <= lastChar; i++, buffer++ )
1544 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1547 release_dc_ptr( dc );
1552 /***********************************************************************
1553 * GetCharWidthA (GDI32.@)
1554 * GetCharWidth32A (GDI32.@)
1556 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1559 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1564 if(count <= 0) return FALSE;
1566 str = HeapAlloc(GetProcessHeap(), 0, count);
1567 for(i = 0; i < count; i++)
1568 str[i] = (BYTE)(firstChar + i);
1570 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1572 for(i = 0; i < wlen; i++)
1574 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1582 HeapFree(GetProcessHeap(), 0, str);
1583 HeapFree(GetProcessHeap(), 0, wstr);
1589 /***********************************************************************
1590 * ExtTextOutA (GDI32.@)
1594 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1595 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1603 if (flags & ETO_GLYPH_INDEX)
1604 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1606 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1609 unsigned int i = 0, j = 0;
1611 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1613 if(IsDBCSLeadByteEx(codepage, str[i])) {
1614 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1617 lpDxW[j++] = lpDx[i];
1623 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1625 HeapFree( GetProcessHeap(), 0, p );
1626 HeapFree( GetProcessHeap(), 0, lpDxW );
1631 /***********************************************************************
1632 * ExtTextOutW (GDI32.@)
1634 * Draws text using the currently selected font, background color, and text color.
1638 * x,y [I] coordinates of string
1640 * ETO_GRAYED - undocumented on MSDN
1641 * ETO_OPAQUE - use background color for fill the rectangle
1642 * ETO_CLIPPED - clipping text to the rectangle
1643 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1644 * than encoded characters. Implies ETO_IGNORELANGUAGE
1645 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1646 * Affects BiDi ordering
1647 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1648 * ETO_PDY - unimplemented
1649 * ETO_NUMERICSLATIN - unimplemented always assumed -
1650 * do not translate numbers into locale representations
1651 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1652 * lprect [I] dimensions for clipping or/and opaquing
1653 * str [I] text string
1654 * count [I] number of symbols in string
1655 * lpDx [I] optional parameter with distance between drawing characters
1661 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1662 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1665 LPWSTR reordered_str = (LPWSTR)str;
1666 WORD *glyphs = NULL;
1667 UINT align = GetTextAlign( hdc );
1671 double cosEsc, sinEsc;
1672 INT *deltas = NULL, char_extra;
1675 BOOL done_extents = FALSE;
1676 INT width = 0, xwidth = 0, ywidth = 0;
1678 DC * dc = get_dc_ptr( hdc );
1680 static int quietfixme = 0;
1682 if (!dc) return FALSE;
1684 breakRem = dc->breakRem;
1686 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1688 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1691 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1693 release_dc_ptr( dc );
1698 type = GetObjectType(hdc);
1699 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1701 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1702 release_dc_ptr( dc );
1707 flags &= ~ETO_CLIPPED;
1709 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1711 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1713 BIDI_Reorder( str, count, GCP_REORDER,
1714 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1715 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1716 reordered_str, count, NULL );
1718 flags |= ETO_IGNORELANGUAGE;
1721 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1722 lprect, debugstr_wn(str, count), count, lpDx);
1724 if(flags & ETO_GLYPH_INDEX)
1725 glyphs = reordered_str;
1728 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1730 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1732 if(align & TA_UPDATECP)
1734 GetCurrentPositionEx( hdc, &pt );
1739 GetTextMetricsW(hdc, &tm);
1740 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1742 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1743 lf.lfEscapement = 0;
1745 if(lf.lfEscapement != 0)
1747 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1748 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1756 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1760 if(flags & ETO_GLYPH_INDEX)
1761 GetTextExtentPointI(hdc, glyphs, count, &sz);
1763 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1765 done_extents = TRUE;
1768 rc.right = x + sz.cx;
1769 rc.bottom = y + sz.cy;
1776 LPtoDP(hdc, (POINT*)&rc, 2);
1778 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1779 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1782 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1783 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1793 LPtoDP(hdc, &pt, 1);
1797 char_extra = GetTextCharacterExtra(hdc);
1798 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1802 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1803 for(i = 0; i < count; i++)
1805 if(lpDx && (flags & ETO_PDY))
1806 deltas[i] = lpDx[i*2] + char_extra;
1808 deltas[i] = lpDx[i] + char_extra;
1811 if(flags & ETO_GLYPH_INDEX)
1812 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1814 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1816 deltas[i] = tmpsz.cx;
1819 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1821 deltas[i] = deltas[i] + dc->breakExtra;
1828 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1836 if(flags & ETO_GLYPH_INDEX)
1837 GetTextExtentPointI(hdc, glyphs, count, &sz);
1839 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1840 done_extents = TRUE;
1842 width = INTERNAL_XWSTODS(dc, sz.cx);
1844 xwidth = width * cosEsc;
1845 ywidth = width * sinEsc;
1847 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1848 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1849 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1852 if (align & TA_UPDATECP)
1856 DPtoLP(hdc, &pt, 1);
1857 MoveToEx(hdc, pt.x, pt.y, NULL);
1869 if (align & TA_UPDATECP)
1873 DPtoLP(hdc, &pt, 1);
1874 MoveToEx(hdc, pt.x, pt.y, NULL);
1879 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1882 y += tm.tmAscent * cosEsc;
1883 x += tm.tmAscent * sinEsc;
1887 y -= tm.tmDescent * cosEsc;
1888 x -= tm.tmDescent * sinEsc;
1895 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1897 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1899 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1900 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1904 rc.right = x + width;
1905 rc.top = y - tm.tmAscent;
1906 rc.bottom = y + tm.tmDescent;
1907 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1912 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1914 HFONT orig_font = dc->hFont, cur_font;
1916 INT span = 0, *offsets = NULL;
1919 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1920 for(i = 0; i < count; i++)
1922 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1923 if(cur_font != dc->hFont)
1928 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1933 for(j = 1; j < count; j++)
1935 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1936 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1941 for(j = 1; j < count; j++)
1942 offsets[j] = offsets[j-1] + deltas[j];
1947 if (PATH_IsPathOpen(dc->path))
1948 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1949 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1950 glyphs, span, deltas ? deltas + i - span : NULL);
1952 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1953 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1954 glyphs, span, deltas ? deltas + i - span : NULL);
1957 SelectObject(hdc, cur_font);
1959 glyphs[span++] = glyph;
1963 if (PATH_IsPathOpen(dc->path))
1964 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1965 y - (offsets ? offsets[count - span] * sinEsc : 0),
1966 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1967 glyphs, span, deltas ? deltas + count - span : NULL);
1969 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1970 y - (offsets ? offsets[count - span] * sinEsc : 0),
1971 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1972 glyphs, span, deltas ? deltas + count - span : NULL);
1973 SelectObject(hdc, orig_font);
1974 HeapFree(GetProcessHeap(), 0, offsets);
1980 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1982 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1983 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1984 flags |= ETO_GLYPH_INDEX;
1987 if (PATH_IsPathOpen(dc->path))
1988 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1989 glyphs ? glyphs : reordered_str, count, deltas);
1991 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1992 glyphs ? glyphs : reordered_str, count, deltas);
1996 HeapFree(GetProcessHeap(), 0, deltas);
1997 if(glyphs != reordered_str)
1998 HeapFree(GetProcessHeap(), 0, glyphs);
1999 if(reordered_str != str)
2000 HeapFree(GetProcessHeap(), 0, reordered_str);
2002 release_dc_ptr( dc );
2004 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2006 int underlinePos, strikeoutPos;
2007 int underlineWidth, strikeoutWidth;
2008 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2009 OUTLINETEXTMETRICW* otm = NULL;
2014 underlineWidth = tm.tmAscent / 20 + 1;
2015 strikeoutPos = tm.tmAscent / 2;
2016 strikeoutWidth = underlineWidth;
2020 otm = HeapAlloc(GetProcessHeap(), 0, size);
2021 GetOutlineTextMetricsW(hdc, size, otm);
2022 underlinePos = otm->otmsUnderscorePosition;
2023 underlineWidth = otm->otmsUnderscoreSize;
2024 strikeoutPos = otm->otmsStrikeoutPosition;
2025 strikeoutWidth = otm->otmsStrikeoutSize;
2026 HeapFree(GetProcessHeap(), 0, otm);
2029 if (PATH_IsPathOpen(dc->path))
2033 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2035 hbrush = SelectObject(hdc, hbrush);
2036 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2040 pts[0].x = x - underlinePos * sinEsc;
2041 pts[0].y = y - underlinePos * cosEsc;
2042 pts[1].x = x + xwidth - underlinePos * sinEsc;
2043 pts[1].y = y - ywidth - underlinePos * cosEsc;
2044 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2045 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2046 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2047 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2048 pts[4].x = pts[0].x;
2049 pts[4].y = pts[0].y;
2050 DPtoLP(hdc, pts, 5);
2051 Polygon(hdc, pts, 5);
2056 pts[0].x = x - strikeoutPos * sinEsc;
2057 pts[0].y = y - strikeoutPos * cosEsc;
2058 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2059 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2060 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2061 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2062 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2063 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2064 pts[4].x = pts[0].x;
2065 pts[4].y = pts[0].y;
2066 DPtoLP(hdc, pts, 5);
2067 Polygon(hdc, pts, 5);
2070 SelectObject(hdc, hpen);
2071 hbrush = SelectObject(hdc, hbrush);
2072 DeleteObject(hbrush);
2076 POINT pts[2], oldpt;
2081 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2082 hpen = SelectObject(hdc, hpen);
2085 pts[1].x = x + xwidth;
2086 pts[1].y = y - ywidth;
2087 DPtoLP(hdc, pts, 2);
2088 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2089 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2090 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2091 DeleteObject(SelectObject(hdc, hpen));
2096 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2097 hpen = SelectObject(hdc, hpen);
2100 pts[1].x = x + xwidth;
2101 pts[1].y = y - ywidth;
2102 DPtoLP(hdc, pts, 2);
2103 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2104 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2105 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2106 DeleteObject(SelectObject(hdc, hpen));
2115 /***********************************************************************
2116 * TextOutA (GDI32.@)
2118 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2120 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2124 /***********************************************************************
2125 * TextOutW (GDI32.@)
2127 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2129 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2133 /***********************************************************************
2134 * PolyTextOutA (GDI32.@)
2138 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2140 for (; cStrings>0; cStrings--, pptxt++)
2141 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2148 /***********************************************************************
2149 * PolyTextOutW (GDI32.@)
2151 * Draw several Strings
2157 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2159 for (; cStrings>0; cStrings--, pptxt++)
2160 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2166 /* FIXME: all following APIs ******************************************/
2169 /***********************************************************************
2170 * SetMapperFlags (GDI32.@)
2172 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2174 DC *dc = get_dc_ptr( hDC );
2177 if(dc->funcs->pSetMapperFlags)
2179 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2180 /* FIXME: ret is just a success flag, we should return a proper value */
2183 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2184 release_dc_ptr( dc );
2188 /***********************************************************************
2189 * GetAspectRatioFilterEx (GDI32.@)
2191 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2193 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2198 /***********************************************************************
2199 * GetCharABCWidthsA (GDI32.@)
2201 * See GetCharABCWidthsW.
2203 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2206 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2211 if(count <= 0) return FALSE;
2213 str = HeapAlloc(GetProcessHeap(), 0, count);
2214 for(i = 0; i < count; i++)
2215 str[i] = (BYTE)(firstChar + i);
2217 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2219 for(i = 0; i < wlen; i++)
2221 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2229 HeapFree(GetProcessHeap(), 0, str);
2230 HeapFree(GetProcessHeap(), 0, wstr);
2236 /******************************************************************************
2237 * GetCharABCWidthsW [GDI32.@]
2239 * Retrieves widths of characters in range.
2242 * hdc [I] Handle of device context
2243 * firstChar [I] First character in range to query
2244 * lastChar [I] Last character in range to query
2245 * abc [O] Address of character-width structure
2248 * Only works with TrueType fonts
2254 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2257 DC *dc = get_dc_ptr(hdc);
2261 if (!dc) return FALSE;
2265 release_dc_ptr( dc );
2270 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2276 /* convert device units to logical */
2277 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2278 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2279 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2280 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2285 release_dc_ptr( dc );
2290 /******************************************************************************
2291 * GetCharABCWidthsI [GDI32.@]
2293 * Retrieves widths of characters in range.
2296 * hdc [I] Handle of device context
2297 * firstChar [I] First glyphs in range to query
2298 * count [I] Last glyphs in range to query
2299 * pgi [i] Array of glyphs to query
2300 * abc [O] Address of character-width structure
2303 * Only works with TrueType fonts
2309 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2310 LPWORD pgi, LPABC abc)
2312 DC *dc = get_dc_ptr(hdc);
2316 if (!dc) return FALSE;
2320 release_dc_ptr( dc );
2325 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2331 /* convert device units to logical */
2332 for( i = 0; i < count; i++, abc++ ) {
2333 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2334 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2335 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2340 release_dc_ptr( dc );
2345 /***********************************************************************
2346 * GetGlyphOutlineA (GDI32.@)
2348 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2349 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2350 LPVOID lpBuffer, const MAT2 *lpmat2 )
2356 if (!lpmat2) return GDI_ERROR;
2358 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2361 if(uChar > 0xff) { /* but, 2 bytes character only */
2363 mbchs[0] = (uChar & 0xff00) >> 8;
2364 mbchs[1] = (uChar & 0xff);
2367 mbchs[0] = (uChar & 0xff);
2369 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2373 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2375 HeapFree(GetProcessHeap(), 0, p);
2379 /***********************************************************************
2380 * GetGlyphOutlineW (GDI32.@)
2382 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2383 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2384 LPVOID lpBuffer, const MAT2 *lpmat2 )
2389 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2390 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2392 if (!lpmat2) return GDI_ERROR;
2394 dc = get_dc_ptr(hdc);
2395 if(!dc) return GDI_ERROR;
2398 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2399 cbBuffer, lpBuffer, lpmat2);
2403 release_dc_ptr( dc );
2408 /***********************************************************************
2409 * CreateScalableFontResourceA (GDI32.@)
2411 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2412 LPCSTR lpszResourceFile,
2413 LPCSTR lpszFontFile,
2414 LPCSTR lpszCurrentPath )
2416 LPWSTR lpszResourceFileW = NULL;
2417 LPWSTR lpszFontFileW = NULL;
2418 LPWSTR lpszCurrentPathW = NULL;
2422 if (lpszResourceFile)
2424 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2425 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2426 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2431 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2432 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2433 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2436 if (lpszCurrentPath)
2438 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2439 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2440 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2443 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2444 lpszFontFileW, lpszCurrentPathW);
2446 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2447 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2448 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2453 /***********************************************************************
2454 * CreateScalableFontResourceW (GDI32.@)
2456 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2457 LPCWSTR lpszResourceFile,
2458 LPCWSTR lpszFontFile,
2459 LPCWSTR lpszCurrentPath )
2462 FIXME("(%d,%s,%s,%s): stub\n",
2463 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2464 debugstr_w(lpszCurrentPath) );
2466 /* fHidden=1 - only visible for the calling app, read-only, not
2467 * enumerated with EnumFonts/EnumFontFamilies
2468 * lpszCurrentPath can be NULL
2471 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2472 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2474 SetLastError(ERROR_FILE_EXISTS);
2477 return FALSE; /* create failed */
2480 /*************************************************************************
2481 * GetKerningPairsA (GDI32.@)
2483 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2484 LPKERNINGPAIR kern_pairA )
2488 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2489 KERNINGPAIR *kern_pairW;
2491 if (!cPairs && kern_pairA)
2493 SetLastError(ERROR_INVALID_PARAMETER);
2497 cp = GdiGetCodePage(hDC);
2499 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2500 * to fail on an invalid character for CP_SYMBOL.
2502 cpi.DefaultChar[0] = 0;
2503 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2505 FIXME("Can't find codepage %u info\n", cp);
2509 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2510 if (!total_kern_pairs) return 0;
2512 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2513 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2515 for (i = 0; i < total_kern_pairs; i++)
2519 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2522 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2525 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2530 if (kern_pairs_copied >= cPairs) break;
2532 kern_pairA->wFirst = (BYTE)first;
2533 kern_pairA->wSecond = (BYTE)second;
2534 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2537 kern_pairs_copied++;
2540 HeapFree(GetProcessHeap(), 0, kern_pairW);
2542 return kern_pairs_copied;
2545 /*************************************************************************
2546 * GetKerningPairsW (GDI32.@)
2548 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2549 LPKERNINGPAIR lpKerningPairs )
2554 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2556 if (!cPairs && lpKerningPairs)
2558 SetLastError(ERROR_INVALID_PARAMETER);
2562 dc = get_dc_ptr(hDC);
2566 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2568 release_dc_ptr( dc );
2572 /*************************************************************************
2573 * TranslateCharsetInfo [GDI32.@]
2575 * Fills a CHARSETINFO structure for a character set, code page, or
2576 * font. This allows making the correspondence between different labels
2577 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2578 * of the same encoding.
2580 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2581 * only one codepage should be set in *lpSrc.
2584 * TRUE on success, FALSE on failure.
2587 BOOL WINAPI TranslateCharsetInfo(
2588 LPDWORD lpSrc, /* [in]
2589 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2590 if flags == TCI_SRCCHARSET: a character set value
2591 if flags == TCI_SRCCODEPAGE: a code page value
2593 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2594 DWORD flags /* [in] determines interpretation of lpSrc */)
2598 case TCI_SRCFONTSIG:
2599 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2601 case TCI_SRCCODEPAGE:
2602 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2604 case TCI_SRCCHARSET:
2605 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2610 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2611 *lpCs = FONT_tci[index];
2615 /*************************************************************************
2616 * GetFontLanguageInfo (GDI32.@)
2618 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2620 FONTSIGNATURE fontsig;
2621 static const DWORD GCP_DBCS_MASK=0x003F0000,
2622 GCP_DIACRITIC_MASK=0x00000000,
2623 FLI_GLYPHS_MASK=0x00000000,
2624 GCP_GLYPHSHAPE_MASK=0x00000040,
2625 GCP_KASHIDA_MASK=0x00000000,
2626 GCP_LIGATE_MASK=0x00000000,
2627 GCP_USEKERNING_MASK=0x00000000,
2628 GCP_REORDER_MASK=0x00000060;
2632 GetTextCharsetInfo( hdc, &fontsig, 0 );
2633 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2635 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2638 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2639 result|=GCP_DIACRITIC;
2641 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2644 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2645 result|=GCP_GLYPHSHAPE;
2647 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2648 result|=GCP_KASHIDA;
2650 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2653 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2654 result|=GCP_USEKERNING;
2656 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2657 if( GetTextAlign( hdc) & TA_RTLREADING )
2658 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2659 result|=GCP_REORDER;
2665 /*************************************************************************
2666 * GetFontData [GDI32.@]
2668 * Retrieve data for TrueType font.
2672 * success: Number of bytes returned
2673 * failure: GDI_ERROR
2677 * Calls SetLastError()
2680 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2681 LPVOID buffer, DWORD length)
2683 DC *dc = get_dc_ptr(hdc);
2684 DWORD ret = GDI_ERROR;
2686 if(!dc) return GDI_ERROR;
2689 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2691 release_dc_ptr( dc );
2695 /*************************************************************************
2696 * GetGlyphIndicesA [GDI32.@]
2698 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2699 LPWORD pgi, DWORD flags)
2705 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2706 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2708 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2709 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2710 HeapFree(GetProcessHeap(), 0, lpstrW);
2715 /*************************************************************************
2716 * GetGlyphIndicesW [GDI32.@]
2718 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2719 LPWORD pgi, DWORD flags)
2721 DC *dc = get_dc_ptr(hdc);
2722 DWORD ret = GDI_ERROR;
2724 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2725 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2727 if(!dc) return GDI_ERROR;
2730 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2732 release_dc_ptr( dc );
2736 /*************************************************************************
2737 * GetCharacterPlacementA [GDI32.@]
2739 * See GetCharacterPlacementW.
2742 * the web browser control of ie4 calls this with dwFlags=0
2745 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2746 INT nMaxExtent, GCP_RESULTSA *lpResults,
2751 GCP_RESULTSW resultsW;
2755 TRACE("%s, %d, %d, 0x%08x\n",
2756 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2758 /* both structs are equal in size */
2759 memcpy(&resultsW, lpResults, sizeof(resultsW));
2761 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2762 if(lpResults->lpOutString)
2763 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2765 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2767 lpResults->nGlyphs = resultsW.nGlyphs;
2768 lpResults->nMaxFit = resultsW.nMaxFit;
2770 if(lpResults->lpOutString) {
2771 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2772 lpResults->lpOutString, uCount, NULL, NULL );
2775 HeapFree(GetProcessHeap(), 0, lpStringW);
2776 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2781 /*************************************************************************
2782 * GetCharacterPlacementW [GDI32.@]
2784 * Retrieve information about a string. This includes the width, reordering,
2785 * Glyphing and so on.
2789 * The width and height of the string if successful, 0 if failed.
2793 * All flags except GCP_REORDER are not yet implemented.
2794 * Reordering is not 100% compliant to the Windows BiDi method.
2795 * Caret positioning is not yet implemented for BiDi.
2796 * Classes are not yet implemented.
2800 GetCharacterPlacementW(
2801 HDC hdc, /* [in] Device context for which the rendering is to be done */
2802 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2803 INT uCount, /* [in] Number of WORDS in string. */
2804 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2805 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2806 DWORD dwFlags /* [in] Flags specifying how to process the string */
2813 TRACE("%s, %d, %d, 0x%08x\n",
2814 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2816 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2817 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2818 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2819 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2820 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2822 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2823 if(lpResults->lpClass) FIXME("classes not implemented\n");
2824 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2825 FIXME("Caret positions for complex scripts not implemented\n");
2827 nSet = (UINT)uCount;
2828 if(nSet > lpResults->nGlyphs)
2829 nSet = lpResults->nGlyphs;
2831 /* return number of initialized fields */
2832 lpResults->nGlyphs = nSet;
2834 if((dwFlags&GCP_REORDER)==0 )
2836 /* Treat the case where no special handling was requested in a fastpath way */
2837 /* copy will do if the GCP_REORDER flag is not set */
2838 if(lpResults->lpOutString)
2839 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2841 if(lpResults->lpOrder)
2843 for(i = 0; i < nSet; i++)
2844 lpResults->lpOrder[i] = i;
2848 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2849 nSet, lpResults->lpOrder );
2852 /* FIXME: Will use the placement chars */
2853 if (lpResults->lpDx)
2856 for (i = 0; i < nSet; i++)
2858 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2859 lpResults->lpDx[i]= c;
2863 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2867 lpResults->lpCaretPos[0] = 0;
2868 for (i = 1; i < nSet; i++)
2869 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2870 lpResults->lpCaretPos[i] = (pos += size.cx);
2873 if(lpResults->lpGlyphs)
2874 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2876 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2877 ret = MAKELONG(size.cx, size.cy);
2882 /*************************************************************************
2883 * GetCharABCWidthsFloatA [GDI32.@]
2885 * See GetCharABCWidthsFloatW.
2887 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2889 INT i, wlen, count = (INT)(last - first + 1);
2894 if (count <= 0) return FALSE;
2896 str = HeapAlloc(GetProcessHeap(), 0, count);
2898 for(i = 0; i < count; i++)
2899 str[i] = (BYTE)(first + i);
2901 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2903 for (i = 0; i < wlen; i++)
2905 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2913 HeapFree( GetProcessHeap(), 0, str );
2914 HeapFree( GetProcessHeap(), 0, wstr );
2919 /*************************************************************************
2920 * GetCharABCWidthsFloatW [GDI32.@]
2922 * Retrieves widths of a range of characters.
2925 * hdc [I] Handle to device context.
2926 * first [I] First character in range to query.
2927 * last [I] Last character in range to query.
2928 * abcf [O] Array of LPABCFLOAT structures.
2935 * Only works with TrueType fonts. It also doesn't return real
2936 * floats but converted integers because it's implemented on
2937 * top of GetCharABCWidthsW.
2939 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2941 ABC *abc, *abc_base;
2942 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2945 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2947 abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2948 if (!abc) return FALSE;
2950 ret = GetCharABCWidthsW( hdc, first, last, abc );
2953 for (i = first; i <= last; i++, abc++, abcf++)
2955 abcf->abcfA = abc->abcA;
2956 abcf->abcfB = abc->abcB;
2957 abcf->abcfC = abc->abcC;
2960 HeapFree( GetProcessHeap(), 0, abc_base );
2964 /*************************************************************************
2965 * GetCharWidthFloatA [GDI32.@]
2967 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2968 UINT iLastChar, PFLOAT pxBuffer)
2970 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2974 /*************************************************************************
2975 * GetCharWidthFloatW [GDI32.@]
2977 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2978 UINT iLastChar, PFLOAT pxBuffer)
2980 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2985 /***********************************************************************
2987 * Font Resource API *
2989 ***********************************************************************/
2991 /***********************************************************************
2992 * AddFontResourceA (GDI32.@)
2994 INT WINAPI AddFontResourceA( LPCSTR str )
2996 return AddFontResourceExA( str, 0, NULL);
2999 /***********************************************************************
3000 * AddFontResourceW (GDI32.@)
3002 INT WINAPI AddFontResourceW( LPCWSTR str )
3004 return AddFontResourceExW(str, 0, NULL);
3008 /***********************************************************************
3009 * AddFontResourceExA (GDI32.@)
3011 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3013 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3014 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3017 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3018 ret = AddFontResourceExW(strW, fl, pdv);
3019 HeapFree(GetProcessHeap(), 0, strW);
3023 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3025 HRSRC rsrc = FindResourceW(hModule, name, type);
3026 HGLOBAL hMem = LoadResource(hModule, rsrc);
3027 LPVOID *pMem = LockResource(hMem);
3028 int *num_total = (int *)lParam;
3031 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3032 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3034 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3038 *num_total += num_in_res;
3042 /***********************************************************************
3043 * AddFontResourceExW (GDI32.@)
3045 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3047 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3050 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3051 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3052 if (hModule != NULL)
3054 int num_resources = 0;
3055 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3057 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3058 wine_dbgstr_w(str));
3059 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3060 ret = num_resources;
3061 FreeLibrary(hModule);
3067 /***********************************************************************
3068 * RemoveFontResourceA (GDI32.@)
3070 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3072 return RemoveFontResourceExA(str, 0, 0);
3075 /***********************************************************************
3076 * RemoveFontResourceW (GDI32.@)
3078 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3080 return RemoveFontResourceExW(str, 0, 0);
3083 /***********************************************************************
3084 * AddFontMemResourceEx (GDI32.@)
3086 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3088 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3091 /***********************************************************************
3092 * RemoveFontMemResourceEx (GDI32.@)
3094 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3096 FIXME("(%p) stub\n", fh);
3100 /***********************************************************************
3101 * RemoveFontResourceExA (GDI32.@)
3103 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3105 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3106 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3109 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3110 ret = RemoveFontResourceExW(strW, fl, pdv);
3111 HeapFree(GetProcessHeap(), 0, strW);
3115 /***********************************************************************
3116 * RemoveFontResourceExW (GDI32.@)
3118 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3120 return WineEngRemoveFontResourceEx(str, fl, pdv);
3123 /***********************************************************************
3124 * GetTextCharset (GDI32.@)
3126 UINT WINAPI GetTextCharset(HDC hdc)
3128 /* MSDN docs say this is equivalent */
3129 return GetTextCharsetInfo(hdc, NULL, 0);
3132 /***********************************************************************
3133 * GetTextCharsetInfo (GDI32.@)
3135 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3137 UINT ret = DEFAULT_CHARSET;
3138 DC *dc = get_dc_ptr(hdc);
3143 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3145 release_dc_ptr( dc );
3148 if (ret == DEFAULT_CHARSET && fs)
3149 memset(fs, 0, sizeof(FONTSIGNATURE));
3153 /***********************************************************************
3154 * GdiGetCharDimensions (GDI32.@)
3156 * Gets the average width of the characters in the English alphabet.
3159 * hdc [I] Handle to the device context to measure on.
3160 * lptm [O] Pointer to memory to store the text metrics into.
3161 * height [O] On exit, the maximum height of characters in the English alphabet.
3164 * The average width of characters in the English alphabet.
3167 * This function is used by the dialog manager to get the size of a dialog
3168 * unit. It should also be used by other pieces of code that need to know
3169 * the size of a dialog unit in logical units without having access to the
3170 * window handle of the dialog.
3171 * Windows caches the font metrics from this function, but we don't and
3172 * there doesn't appear to be an immediate advantage to do so.
3175 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3177 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3180 static const WCHAR alphabet[] = {
3181 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3182 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3183 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3185 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3187 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3189 if (height) *height = sz.cy;
3190 return (sz.cx / 26 + 1) / 2;
3193 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3195 FIXME("(%d): stub\n", fEnableEUDC);
3199 /***********************************************************************
3200 * GetCharWidthI (GDI32.@)
3202 * Retrieve widths of characters.
3205 * hdc [I] Handle to a device context.
3206 * first [I] First glyph in range to query.
3207 * count [I] Number of glyph indices to query.
3208 * glyphs [I] Array of glyphs to query.
3209 * buffer [O] Buffer to receive character widths.
3212 * Only works with TrueType fonts.
3218 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3223 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3225 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3228 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3230 HeapFree(GetProcessHeap(), 0, abc);
3234 for (i = 0; i < count; i++)
3235 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3237 HeapFree(GetProcessHeap(), 0, abc);
3241 /***********************************************************************
3242 * GetFontUnicodeRanges (GDI32.@)
3244 * Retrieve a list of supported Unicode characters in a font.
3247 * hdc [I] Handle to a device context.
3248 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3251 * Success: Number of bytes written to the buffer pointed to by lpgs.
3255 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3258 DC *dc = get_dc_ptr(hdc);
3260 TRACE("(%p, %p)\n", hdc, lpgs);
3264 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3270 /*************************************************************
3271 * FontIsLinked (GDI32.@)
3273 BOOL WINAPI FontIsLinked(HDC hdc)
3275 DC *dc = get_dc_ptr(hdc);
3278 if (!dc) return FALSE;
3279 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3281 TRACE("returning %d\n", ret);
3285 /*************************************************************
3286 * GdiRealizationInfo (GDI32.@)
3288 * Returns a structure that contains some font information.
3290 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3292 DC *dc = get_dc_ptr(hdc);
3295 if (!dc) return FALSE;
3296 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);