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 )
251 int charset = GetTextCharset(hdc);
253 /* Hmm, nicely designed api this one! */
254 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
261 case DEFAULT_CHARSET:
272 /* FIXME: These have no place here, but because x11drv
273 enumerates fonts with these (made up) charsets some apps
274 might use them and then the FIXME below would become
275 annoying. Now we could pick the intended codepage for
276 each of these, but since it's broken anyway we'll just
277 use CP_ACP and hope it'll go away...
283 FIXME("Can't find codepage for charset %d\n", charset);
288 TRACE("charset %d => cp %d\n", charset, cp);
292 /***********************************************************************
295 * Returns a Unicode translation of str using the charset of the
296 * currently selected font in hdc. If count is -1 then str is assumed
297 * to be '\0' terminated, otherwise it contains the number of bytes to
298 * convert. If plenW is non-NULL, on return it will point to the
299 * number of WCHARs that have been written. If pCP is non-NULL, on
300 * return it will point to the codepage used in the conversion. The
301 * caller should free the returned LPWSTR from the process heap
304 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
310 cp = GdiGetCodePage( hdc );
312 if(count == -1) count = strlen(str);
313 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
314 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
315 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
316 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
317 if(plenW) *plenW = lenW;
323 /***********************************************************************
324 * CreateFontIndirectA (GDI32.@)
326 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
332 FONT_LogFontAToW( plfA, &lfW );
333 return CreateFontIndirectW( &lfW );
336 /***********************************************************************
337 * CreateFontIndirectW (GDI32.@)
339 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
341 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
342 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
343 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
344 WCHAR *pFaceNameSuffix = NULL;
350 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
352 fontPtr->logfont = *plf;
354 if (plf->lfEscapement != plf->lfOrientation)
356 /* this should really depend on whether GM_ADVANCED is set */
357 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
358 WARN("orientation angle %f set to "
359 "escapement angle %f for new font %p\n",
360 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
363 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
364 if (pFaceNameItalicSuffix)
366 fontPtr->logfont.lfItalic = TRUE;
367 pFaceNameSuffix = pFaceNameItalicSuffix;
370 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
371 if (pFaceNameBoldSuffix)
373 if (fontPtr->logfont.lfWeight < FW_BOLD)
374 fontPtr->logfont.lfWeight = FW_BOLD;
375 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
376 pFaceNameSuffix = pFaceNameBoldSuffix;
379 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
381 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
383 HeapFree( GetProcessHeap(), 0, fontPtr );
387 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
388 plf->lfHeight, plf->lfWidth,
389 plf->lfEscapement, plf->lfOrientation,
390 plf->lfPitchAndFamily,
391 plf->lfOutPrecision, plf->lfClipPrecision,
392 plf->lfQuality, plf->lfCharSet,
393 debugstr_w(plf->lfFaceName),
394 plf->lfWeight > 400 ? "Bold" : "",
395 plf->lfItalic ? "Italic" : "",
396 plf->lfUnderline ? "Underline" : "", hFont);
401 /*************************************************************************
402 * CreateFontA (GDI32.@)
404 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
405 INT orient, INT weight, DWORD italic,
406 DWORD underline, DWORD strikeout, DWORD charset,
407 DWORD outpres, DWORD clippres, DWORD quality,
408 DWORD pitch, LPCSTR name )
412 logfont.lfHeight = height;
413 logfont.lfWidth = width;
414 logfont.lfEscapement = esc;
415 logfont.lfOrientation = orient;
416 logfont.lfWeight = weight;
417 logfont.lfItalic = italic;
418 logfont.lfUnderline = underline;
419 logfont.lfStrikeOut = strikeout;
420 logfont.lfCharSet = charset;
421 logfont.lfOutPrecision = outpres;
422 logfont.lfClipPrecision = clippres;
423 logfont.lfQuality = quality;
424 logfont.lfPitchAndFamily = pitch;
427 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
429 logfont.lfFaceName[0] = '\0';
431 return CreateFontIndirectA( &logfont );
434 /*************************************************************************
435 * CreateFontW (GDI32.@)
437 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
438 INT orient, INT weight, DWORD italic,
439 DWORD underline, DWORD strikeout, DWORD charset,
440 DWORD outpres, DWORD clippres, DWORD quality,
441 DWORD pitch, LPCWSTR name )
445 logfont.lfHeight = height;
446 logfont.lfWidth = width;
447 logfont.lfEscapement = esc;
448 logfont.lfOrientation = orient;
449 logfont.lfWeight = weight;
450 logfont.lfItalic = italic;
451 logfont.lfUnderline = underline;
452 logfont.lfStrikeOut = strikeout;
453 logfont.lfCharSet = charset;
454 logfont.lfOutPrecision = outpres;
455 logfont.lfClipPrecision = clippres;
456 logfont.lfQuality = quality;
457 logfont.lfPitchAndFamily = pitch;
460 lstrcpynW(logfont.lfFaceName, name,
461 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
463 logfont.lfFaceName[0] = '\0';
465 return CreateFontIndirectW( &logfont );
469 /***********************************************************************
472 * If the driver supports vector fonts we create a gdi font first and
473 * then call the driver to give it a chance to supply its own device
474 * font. If the driver wants to do this it returns TRUE and we can
475 * delete the gdi font, if the driver wants to use the gdi font it
476 * should return FALSE, to signal an error return GDI_ERROR. For
477 * drivers that don't support vector fonts they must supply their own
480 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
483 DC *dc = get_dc_ptr( hdc );
487 if (!GDI_inc_ref_count( handle ))
489 release_dc_ptr( dc );
493 if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
494 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
496 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
498 if (ret && dc->gdiFont) dc->gdiFont = 0;
500 if (ret == HGDI_ERROR)
502 GDI_dec_ref_count( handle );
503 ret = 0; /* SelectObject returns 0 on error */
509 GDI_dec_ref_count( ret );
511 release_dc_ptr( dc );
516 /***********************************************************************
519 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
521 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
527 FONT_LogFontWToA( &font->logfont, &lfA );
528 if (count > sizeof(lfA)) count = sizeof(lfA);
529 memcpy( buffer, &lfA, count );
531 else count = sizeof(lfA);
532 GDI_ReleaseObj( handle );
536 /***********************************************************************
539 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
541 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
546 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
547 memcpy( buffer, &font->logfont, count );
549 else count = sizeof(LOGFONTW);
550 GDI_ReleaseObj( handle );
555 /***********************************************************************
558 static BOOL FONT_DeleteObject( HGDIOBJ handle )
562 WineEngDestroyFontInstance( handle );
564 if (!(obj = free_gdi_handle( handle ))) return FALSE;
565 return HeapFree( GetProcessHeap(), 0, obj );
569 /***********************************************************************
572 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
573 * We have to use other types because of the FONTENUMPROCW definition.
575 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
576 DWORD fType, LPARAM lp )
578 fontEnum32 *pfe = (fontEnum32*)lp;
581 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
582 if ((!pfe->lpLogFontParam ||
583 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
584 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
585 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
587 /* convert font metrics */
588 ENUMLOGFONTEXA logfont;
589 NEWTEXTMETRICEXA tmA;
591 pfe->dwFlags |= ENUM_CALLED;
592 if (!(pfe->dwFlags & ENUM_UNICODE))
594 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
595 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
596 plf = (LOGFONTW *)&logfont.elfLogFont;
597 ptm = (TEXTMETRICW *)&tmA;
600 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
605 /***********************************************************************
606 * FONT_EnumFontFamiliesEx
608 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
609 FONTENUMPROCW efproc,
610 LPARAM lParam, DWORD dwUnicode)
613 DC *dc = get_dc_ptr( hDC );
620 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
622 fe32.lpLogFontParam = plf;
623 fe32.lpEnumFunc = efproc;
624 fe32.lpData = lParam;
625 fe32.dwFlags = dwUnicode;
628 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
630 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
637 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
638 fe32.dwFlags &= ~ENUM_CALLED;
639 if (ret && dc->funcs->pEnumDeviceFonts) {
640 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
641 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
645 release_dc_ptr( dc );
649 /***********************************************************************
650 * EnumFontFamiliesExW (GDI32.@)
652 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
653 FONTENUMPROCW efproc,
654 LPARAM lParam, DWORD dwFlags )
656 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
659 /***********************************************************************
660 * EnumFontFamiliesExA (GDI32.@)
662 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
663 FONTENUMPROCA efproc,
664 LPARAM lParam, DWORD dwFlags)
670 FONT_LogFontAToW( plf, &lfW );
675 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
678 /***********************************************************************
679 * EnumFontFamiliesA (GDI32.@)
681 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
682 FONTENUMPROCA efproc, LPARAM lpData )
688 if (!*lpFamily) return 1;
689 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
690 lf.lfCharSet = DEFAULT_CHARSET;
691 lf.lfPitchAndFamily = 0;
696 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
699 /***********************************************************************
700 * EnumFontFamiliesW (GDI32.@)
702 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
703 FONTENUMPROCW efproc, LPARAM lpData )
709 if (!*lpFamily) return 1;
710 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
711 lf.lfCharSet = DEFAULT_CHARSET;
712 lf.lfPitchAndFamily = 0;
717 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
720 /***********************************************************************
721 * EnumFontsA (GDI32.@)
723 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
726 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
729 /***********************************************************************
730 * EnumFontsW (GDI32.@)
732 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
735 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
739 /***********************************************************************
740 * GetTextCharacterExtra (GDI32.@)
742 INT WINAPI GetTextCharacterExtra( HDC hdc )
745 DC *dc = get_dc_ptr( hdc );
746 if (!dc) return 0x80000000;
748 release_dc_ptr( dc );
753 /***********************************************************************
754 * SetTextCharacterExtra (GDI32.@)
756 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
759 DC * dc = get_dc_ptr( hdc );
760 if (!dc) return 0x80000000;
761 if (dc->funcs->pSetTextCharacterExtra)
762 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
765 prev = dc->charExtra;
766 dc->charExtra = extra;
768 release_dc_ptr( dc );
773 /***********************************************************************
774 * SetTextJustification (GDI32.@)
776 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
779 DC * dc = get_dc_ptr( hdc );
780 if (!dc) return FALSE;
781 if (dc->funcs->pSetTextJustification)
782 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
785 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
786 if (!extra) breaks = 0;
789 dc->breakExtra = extra / breaks;
790 dc->breakRem = extra - (breaks * dc->breakExtra);
798 release_dc_ptr( dc );
803 /***********************************************************************
804 * GetTextFaceA (GDI32.@)
806 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
808 INT res = GetTextFaceW(hdc, 0, NULL);
809 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
810 GetTextFaceW( hdc, res, nameW );
816 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
820 /* GetTextFaceA does NOT include the nul byte in the return count. */
827 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
828 HeapFree( GetProcessHeap(), 0, nameW );
832 /***********************************************************************
833 * GetTextFaceW (GDI32.@)
835 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
840 DC * dc = get_dc_ptr( hdc );
844 ret = WineEngGetTextFace(dc->gdiFont, count, name);
845 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
847 INT n = strlenW(font->logfont.lfFaceName) + 1;
850 lstrcpynW( name, font->logfont.lfFaceName, count );
854 GDI_ReleaseObj( dc->hFont );
856 release_dc_ptr( dc );
861 /***********************************************************************
862 * GetTextExtentPoint32A (GDI32.@)
864 * See GetTextExtentPoint32W.
866 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
871 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
874 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
875 HeapFree( GetProcessHeap(), 0, p );
878 TRACE("(%p %s %d %p): returning %d x %d\n",
879 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
884 /***********************************************************************
885 * GetTextExtentPoint32W [GDI32.@]
887 * Computes width/height for a string.
889 * Computes width and height of the specified string.
895 BOOL WINAPI GetTextExtentPoint32W(
896 HDC hdc, /* [in] Handle of device context */
897 LPCWSTR str, /* [in] Address of text string */
898 INT count, /* [in] Number of characters in string */
899 LPSIZE size) /* [out] Address of structure for string size */
901 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
904 /***********************************************************************
905 * GetTextExtentExPointI [GDI32.@]
907 * Computes width and height of the array of glyph indices.
910 * hdc [I] Handle of device context.
911 * indices [I] Glyph index array.
912 * count [I] Number of glyphs in array.
913 * max_ext [I] Maximum width in glyphs.
914 * nfit [O] Maximum number of characters.
915 * dxs [O] Partial string widths.
916 * size [O] Returned string size.
922 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
923 LPINT nfit, LPINT dxs, LPSIZE size )
926 DC * dc = get_dc_ptr( hdc );
927 if (!dc) return FALSE;
930 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
931 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
932 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
933 size->cx += count * dc->charExtra;
935 else if(dc->funcs->pGetTextExtentExPoint) {
936 FIXME("calling GetTextExtentExPoint\n");
937 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, indices, count,
938 max_ext, nfit, dxs, size );
941 release_dc_ptr( dc );
943 TRACE("(%p %p %d %p): returning %d x %d\n",
944 hdc, indices, count, size, size->cx, size->cy );
948 /***********************************************************************
949 * GetTextExtentPointI [GDI32.@]
951 * Computes width and height of the array of glyph indices.
954 * hdc [I] Handle of device context.
955 * indices [I] Glyph index array.
956 * count [I] Number of glyphs in array.
957 * size [O] Returned string size.
963 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
965 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
969 /***********************************************************************
970 * GetTextExtentPointA (GDI32.@)
972 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
975 TRACE("not bug compatible.\n");
976 return GetTextExtentPoint32A( hdc, str, count, size );
979 /***********************************************************************
980 * GetTextExtentPointW (GDI32.@)
982 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
985 TRACE("not bug compatible.\n");
986 return GetTextExtentPoint32W( hdc, str, count, size );
990 /***********************************************************************
991 * GetTextExtentExPointA (GDI32.@)
993 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
994 INT maxExt, LPINT lpnFit,
995 LPINT alpDx, LPSIZE size )
1003 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1006 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1007 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1010 INT n = lpnFit ? *lpnFit : wlen;
1012 for(i = 0, j = 0; i < n; i++, j++)
1014 alpDx[j] = walpDx[i];
1015 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1018 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1019 HeapFree( GetProcessHeap(), 0, p );
1020 HeapFree( GetProcessHeap(), 0, walpDx );
1025 /***********************************************************************
1026 * GetTextExtentExPointW (GDI32.@)
1028 * Return the size of the string as it would be if it was output properly by
1031 * This should include
1032 * - Intercharacter spacing
1033 * - justification spacing (not yet done)
1034 * - kerning? see below
1036 * Kerning. Since kerning would be carried out by the rendering code it should
1037 * be done by the driver. However they don't support it yet. Also I am not
1038 * yet persuaded that (certainly under Win95) any kerning is actually done.
1040 * str: According to MSDN this should be null-terminated. That is not true; a
1041 * null will not terminate it early.
1042 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1043 * than count. I have seen it be either the size of the full string or
1044 * 1 less than the size of the full string. I have not seen it bear any
1045 * resemblance to the portion that would fit.
1046 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1047 * trailing intercharacter spacing and any trailing justification.
1050 * Currently we do this by measuring each character etc. We should do it by
1051 * passing the request to the driver, perhaps by extending the
1052 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1053 * thinking about kerning issues and rounding issues in the justification.
1056 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1057 INT maxExt, LPINT lpnFit,
1058 LPINT alpDx, LPSIZE size )
1066 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1068 dc = get_dc_ptr(hdc);
1072 GetTextMetricsW(hdc, &tm);
1074 /* If we need to calculate nFit, then we need the partial extents even if
1075 the user hasn't provided us with an array. */
1078 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1082 SetLastError(ERROR_OUTOFMEMORY);
1090 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1091 0, NULL, dxs, size);
1092 else if (dc->funcs->pGetTextExtentExPoint)
1093 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1094 0, NULL, dxs, size);
1096 /* Perform device size to world size transformations. */
1099 INT extra = dc->charExtra,
1100 breakExtra = dc->breakExtra,
1101 breakRem = dc->breakRem,
1106 for (i = 0; i < count; ++i)
1108 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1109 dxs[i] += (i+1) * extra;
1110 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1112 dxs[i] += breakExtra;
1119 if (dxs[i] <= maxExt)
1122 breakRem = dc->breakRem;
1124 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1125 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1127 if (!dxs && count > 1 && (breakExtra || breakRem))
1129 for (i = 0; i < count; i++)
1131 if (str[i] == tm.tmBreakChar)
1133 size->cx += breakExtra;
1148 HeapFree(GetProcessHeap(), 0, dxs);
1150 release_dc_ptr( dc );
1152 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1156 /***********************************************************************
1157 * GetTextMetricsA (GDI32.@)
1159 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1163 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1164 FONT_TextMetricWToA( &tm32, metrics );
1168 /***********************************************************************
1169 * GetTextMetricsW (GDI32.@)
1171 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1174 DC * dc = get_dc_ptr( hdc );
1175 if (!dc) return FALSE;
1178 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1179 else if (dc->funcs->pGetTextMetrics)
1180 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1184 /* device layer returns values in device units
1185 * therefore we have to convert them to logical */
1187 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1188 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1190 #define WDPTOLP(x) ((x<0)? \
1191 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1192 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1193 #define HDPTOLP(y) ((y<0)? \
1194 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1195 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1197 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1198 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1199 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1200 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1201 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1202 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1203 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1204 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1208 TRACE("text metrics:\n"
1209 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1210 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1211 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1212 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1213 " PitchAndFamily = %02x\n"
1214 " --------------------\n"
1215 " InternalLeading = %i\n"
1219 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1220 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1221 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1222 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1223 metrics->tmPitchAndFamily,
1224 metrics->tmInternalLeading,
1227 metrics->tmHeight );
1229 release_dc_ptr( dc );
1234 /***********************************************************************
1235 * GetOutlineTextMetricsA (GDI32.@)
1236 * Gets metrics for TrueType fonts.
1239 * If the supplied buffer isn't big enough Windows partially fills it up to
1240 * its given length and returns that length.
1243 * Success: Non-zero or size of required buffer
1246 UINT WINAPI GetOutlineTextMetricsA(
1247 HDC hdc, /* [in] Handle of device context */
1248 UINT cbData, /* [in] Size of metric data array */
1249 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1251 char buf[512], *ptr;
1253 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1254 OUTLINETEXTMETRICA *output = lpOTM;
1257 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1259 if(ret > sizeof(buf))
1260 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1261 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1263 needed = sizeof(OUTLINETEXTMETRICA);
1264 if(lpOTMW->otmpFamilyName)
1265 needed += WideCharToMultiByte(CP_ACP, 0,
1266 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1267 NULL, 0, NULL, NULL);
1268 if(lpOTMW->otmpFaceName)
1269 needed += WideCharToMultiByte(CP_ACP, 0,
1270 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1271 NULL, 0, NULL, NULL);
1272 if(lpOTMW->otmpStyleName)
1273 needed += WideCharToMultiByte(CP_ACP, 0,
1274 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1275 NULL, 0, NULL, NULL);
1276 if(lpOTMW->otmpFullName)
1277 needed += WideCharToMultiByte(CP_ACP, 0,
1278 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1279 NULL, 0, NULL, NULL);
1286 TRACE("needed = %d\n", needed);
1288 /* Since the supplied buffer isn't big enough, we'll alloc one
1289 that is and memcpy the first cbData bytes into the lpOTM at
1291 output = HeapAlloc(GetProcessHeap(), 0, needed);
1293 ret = output->otmSize = min(needed, cbData);
1294 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1295 output->otmFiller = 0;
1296 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1297 output->otmfsSelection = lpOTMW->otmfsSelection;
1298 output->otmfsType = lpOTMW->otmfsType;
1299 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1300 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1301 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1302 output->otmEMSquare = lpOTMW->otmEMSquare;
1303 output->otmAscent = lpOTMW->otmAscent;
1304 output->otmDescent = lpOTMW->otmDescent;
1305 output->otmLineGap = lpOTMW->otmLineGap;
1306 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1307 output->otmsXHeight = lpOTMW->otmsXHeight;
1308 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1309 output->otmMacAscent = lpOTMW->otmMacAscent;
1310 output->otmMacDescent = lpOTMW->otmMacDescent;
1311 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1312 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1313 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1314 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1315 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1316 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1317 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1318 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1319 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1320 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1323 ptr = (char*)(output + 1);
1324 left = needed - sizeof(*output);
1326 if(lpOTMW->otmpFamilyName) {
1327 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1328 len = WideCharToMultiByte(CP_ACP, 0,
1329 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1330 ptr, left, NULL, NULL);
1334 output->otmpFamilyName = 0;
1336 if(lpOTMW->otmpFaceName) {
1337 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1338 len = WideCharToMultiByte(CP_ACP, 0,
1339 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1340 ptr, left, NULL, NULL);
1344 output->otmpFaceName = 0;
1346 if(lpOTMW->otmpStyleName) {
1347 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1348 len = WideCharToMultiByte(CP_ACP, 0,
1349 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1350 ptr, left, NULL, NULL);
1354 output->otmpStyleName = 0;
1356 if(lpOTMW->otmpFullName) {
1357 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1358 len = WideCharToMultiByte(CP_ACP, 0,
1359 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1360 ptr, left, NULL, NULL);
1363 output->otmpFullName = 0;
1367 if(output != lpOTM) {
1368 memcpy(lpOTM, output, cbData);
1369 HeapFree(GetProcessHeap(), 0, output);
1371 /* check if the string offsets really fit into the provided size */
1372 /* FIXME: should we check string length as well? */
1373 /* make sure that we don't read/write beyond the provided buffer */
1374 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1376 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1377 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1380 /* make sure that we don't read/write beyond the provided buffer */
1381 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1383 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1384 lpOTM->otmpFaceName = 0; /* doesn't fit */
1387 /* make sure that we don't read/write beyond the provided buffer */
1388 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1390 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1391 lpOTM->otmpStyleName = 0; /* doesn't fit */
1394 /* make sure that we don't read/write beyond the provided buffer */
1395 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1397 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1398 lpOTM->otmpFullName = 0; /* doesn't fit */
1403 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1404 HeapFree(GetProcessHeap(), 0, lpOTMW);
1410 /***********************************************************************
1411 * GetOutlineTextMetricsW [GDI32.@]
1413 UINT WINAPI GetOutlineTextMetricsW(
1414 HDC hdc, /* [in] Handle of device context */
1415 UINT cbData, /* [in] Size of metric data array */
1416 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1418 DC *dc = get_dc_ptr( hdc );
1419 OUTLINETEXTMETRICW *output = lpOTM;
1422 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1426 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1429 output = HeapAlloc(GetProcessHeap(), 0, ret);
1430 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1433 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1434 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1436 #define WDPTOLP(x) ((x<0)? \
1437 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1438 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1439 #define HDPTOLP(y) ((y<0)? \
1440 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1441 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1443 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1444 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1445 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1446 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1447 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1448 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1449 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1450 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1451 output->otmAscent = HDPTOLP(output->otmAscent);
1452 output->otmDescent = HDPTOLP(output->otmDescent);
1453 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1454 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1455 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1456 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1457 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1458 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1459 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1460 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1461 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1462 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1463 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1464 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1465 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1466 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1467 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1468 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1469 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1470 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1471 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1472 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1473 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1474 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1477 if(output != lpOTM) {
1478 memcpy(lpOTM, output, cbData);
1479 HeapFree(GetProcessHeap(), 0, output);
1485 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1486 but really this should just be a return 0. */
1488 ret = sizeof(*lpOTM);
1493 memset(lpOTM, 0, ret);
1494 lpOTM->otmSize = sizeof(*lpOTM);
1495 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1497 Further fill of the structure not implemented,
1498 Needs real values for the structure members
1508 /***********************************************************************
1509 * GetCharWidthW (GDI32.@)
1510 * GetCharWidth32W (GDI32.@)
1512 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1517 DC * dc = get_dc_ptr( hdc );
1518 if (!dc) return FALSE;
1521 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1522 else if (dc->funcs->pGetCharWidth)
1523 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1527 /* convert device units to logical */
1528 for( i = firstChar; i <= lastChar; i++, buffer++ )
1529 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1532 release_dc_ptr( dc );
1537 /***********************************************************************
1538 * GetCharWidthA (GDI32.@)
1539 * GetCharWidth32A (GDI32.@)
1541 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1544 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1549 if(count <= 0) return FALSE;
1551 str = HeapAlloc(GetProcessHeap(), 0, count);
1552 for(i = 0; i < count; i++)
1553 str[i] = (BYTE)(firstChar + i);
1555 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1557 for(i = 0; i < wlen; i++)
1559 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1567 HeapFree(GetProcessHeap(), 0, str);
1568 HeapFree(GetProcessHeap(), 0, wstr);
1574 /***********************************************************************
1575 * ExtTextOutA (GDI32.@)
1579 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1580 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1588 if (flags & ETO_GLYPH_INDEX)
1589 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1591 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1594 unsigned int i = 0, j = 0;
1596 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1598 if(IsDBCSLeadByteEx(codepage, str[i])) {
1599 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1602 lpDxW[j++] = lpDx[i];
1608 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1610 HeapFree( GetProcessHeap(), 0, p );
1611 HeapFree( GetProcessHeap(), 0, lpDxW );
1616 /***********************************************************************
1617 * ExtTextOutW (GDI32.@)
1619 * Draws text using the currently selected font, background color, and text color.
1623 * x,y [I] coordinates of string
1625 * ETO_GRAYED - undocumented on MSDN
1626 * ETO_OPAQUE - use background color for fill the rectangle
1627 * ETO_CLIPPED - clipping text to the rectangle
1628 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1629 * than encoded characters. Implies ETO_IGNORELANGUAGE
1630 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1631 * Affects BiDi ordering
1632 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1633 * ETO_PDY - unimplemented
1634 * ETO_NUMERICSLATIN - unimplemented always assumed -
1635 * do not translate numbers into locale representations
1636 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1637 * lprect [I] dimensions for clipping or/and opaquing
1638 * str [I] text string
1639 * count [I] number of symbols in string
1640 * lpDx [I] optional parameter with distance between drawing characters
1646 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1647 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1650 LPWSTR reordered_str = (LPWSTR)str;
1651 WORD *glyphs = NULL;
1652 UINT align = GetTextAlign( hdc );
1656 double cosEsc, sinEsc;
1657 INT *deltas = NULL, char_extra;
1660 BOOL done_extents = FALSE;
1661 INT width = 0, xwidth = 0, ywidth = 0;
1663 DC * dc = get_dc_ptr( hdc );
1665 static int quietfixme = 0;
1667 if (!dc) return FALSE;
1669 breakRem = dc->breakRem;
1671 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1673 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1676 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1678 release_dc_ptr( dc );
1683 type = GetObjectType(hdc);
1684 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1686 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1687 release_dc_ptr( dc );
1692 flags &= ~ETO_CLIPPED;
1694 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1696 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1698 BIDI_Reorder( str, count, GCP_REORDER,
1699 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1700 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1701 reordered_str, count, NULL );
1703 flags |= ETO_IGNORELANGUAGE;
1706 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1707 lprect, debugstr_wn(str, count), count, lpDx);
1709 if(flags & ETO_GLYPH_INDEX)
1710 glyphs = reordered_str;
1713 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1715 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1717 if(align & TA_UPDATECP)
1719 GetCurrentPositionEx( hdc, &pt );
1724 GetTextMetricsW(hdc, &tm);
1725 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1727 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1728 lf.lfEscapement = 0;
1730 if(lf.lfEscapement != 0)
1732 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1733 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1741 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1745 if(flags & ETO_GLYPH_INDEX)
1746 GetTextExtentPointI(hdc, glyphs, count, &sz);
1748 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1750 done_extents = TRUE;
1753 rc.right = x + sz.cx;
1754 rc.bottom = y + sz.cy;
1761 LPtoDP(hdc, (POINT*)&rc, 2);
1763 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1764 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1767 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1768 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1778 LPtoDP(hdc, &pt, 1);
1782 char_extra = GetTextCharacterExtra(hdc);
1783 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1787 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1788 for(i = 0; i < count; i++)
1790 if(lpDx && (flags & ETO_PDY))
1791 deltas[i] = lpDx[i*2] + char_extra;
1793 deltas[i] = lpDx[i] + char_extra;
1796 if(flags & ETO_GLYPH_INDEX)
1797 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1799 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1801 deltas[i] = tmpsz.cx;
1804 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1806 deltas[i] = deltas[i] + dc->breakExtra;
1813 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1821 if(flags & ETO_GLYPH_INDEX)
1822 GetTextExtentPointI(hdc, glyphs, count, &sz);
1824 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1825 done_extents = TRUE;
1827 width = INTERNAL_XWSTODS(dc, sz.cx);
1829 xwidth = width * cosEsc;
1830 ywidth = width * sinEsc;
1832 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1833 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1834 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1837 if (align & TA_UPDATECP)
1841 DPtoLP(hdc, &pt, 1);
1842 MoveToEx(hdc, pt.x, pt.y, NULL);
1854 if (align & TA_UPDATECP)
1858 DPtoLP(hdc, &pt, 1);
1859 MoveToEx(hdc, pt.x, pt.y, NULL);
1864 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1867 y += tm.tmAscent * cosEsc;
1868 x += tm.tmAscent * sinEsc;
1872 y -= tm.tmDescent * cosEsc;
1873 x -= tm.tmDescent * sinEsc;
1880 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1882 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1884 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1885 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1889 rc.right = x + width;
1890 rc.top = y - tm.tmAscent;
1891 rc.bottom = y + tm.tmDescent;
1892 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1897 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1899 HFONT orig_font = dc->hFont, cur_font;
1901 INT span = 0, *offsets = NULL;
1904 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1905 for(i = 0; i < count; i++)
1907 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1908 if(cur_font != dc->hFont)
1913 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1918 for(j = 1; j < count; j++)
1920 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1921 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1926 for(j = 1; j < count; j++)
1927 offsets[j] = offsets[j-1] + deltas[j];
1932 if (PATH_IsPathOpen(dc->path))
1933 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1934 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1935 glyphs, span, deltas ? deltas + i - span : NULL);
1937 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1938 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1939 glyphs, span, deltas ? deltas + i - span : NULL);
1942 SelectObject(hdc, cur_font);
1944 glyphs[span++] = glyph;
1948 if (PATH_IsPathOpen(dc->path))
1949 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1950 y - (offsets ? offsets[count - span] * sinEsc : 0),
1951 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1952 glyphs, span, deltas ? deltas + count - span : NULL);
1954 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1955 y - (offsets ? offsets[count - span] * sinEsc : 0),
1956 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1957 glyphs, span, deltas ? deltas + count - span : NULL);
1958 SelectObject(hdc, orig_font);
1959 HeapFree(GetProcessHeap(), 0, offsets);
1965 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1967 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1968 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1969 flags |= ETO_GLYPH_INDEX;
1972 if (PATH_IsPathOpen(dc->path))
1973 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1974 glyphs ? glyphs : reordered_str, count, deltas);
1976 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1977 glyphs ? glyphs : reordered_str, count, deltas);
1981 HeapFree(GetProcessHeap(), 0, deltas);
1982 if(glyphs != reordered_str)
1983 HeapFree(GetProcessHeap(), 0, glyphs);
1984 if(reordered_str != str)
1985 HeapFree(GetProcessHeap(), 0, reordered_str);
1987 release_dc_ptr( dc );
1989 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
1991 int underlinePos, strikeoutPos;
1992 int underlineWidth, strikeoutWidth;
1993 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
1994 OUTLINETEXTMETRICW* otm = NULL;
1999 underlineWidth = tm.tmAscent / 20 + 1;
2000 strikeoutPos = tm.tmAscent / 2;
2001 strikeoutWidth = underlineWidth;
2005 otm = HeapAlloc(GetProcessHeap(), 0, size);
2006 GetOutlineTextMetricsW(hdc, size, otm);
2007 underlinePos = otm->otmsUnderscorePosition;
2008 underlineWidth = otm->otmsUnderscoreSize;
2009 strikeoutPos = otm->otmsStrikeoutPosition;
2010 strikeoutWidth = otm->otmsStrikeoutSize;
2011 HeapFree(GetProcessHeap(), 0, otm);
2014 if (PATH_IsPathOpen(dc->path))
2018 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2020 hbrush = SelectObject(hdc, hbrush);
2021 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2025 pts[0].x = x - underlinePos * sinEsc;
2026 pts[0].y = y - underlinePos * cosEsc;
2027 pts[1].x = x + xwidth - underlinePos * sinEsc;
2028 pts[1].y = y - ywidth - underlinePos * cosEsc;
2029 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2030 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2031 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2032 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2033 pts[4].x = pts[0].x;
2034 pts[4].y = pts[0].y;
2035 DPtoLP(hdc, pts, 5);
2036 Polygon(hdc, pts, 5);
2041 pts[0].x = x - strikeoutPos * sinEsc;
2042 pts[0].y = y - strikeoutPos * cosEsc;
2043 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2044 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2045 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2046 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2047 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2048 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2049 pts[4].x = pts[0].x;
2050 pts[4].y = pts[0].y;
2051 DPtoLP(hdc, pts, 5);
2052 Polygon(hdc, pts, 5);
2055 SelectObject(hdc, hpen);
2056 hbrush = SelectObject(hdc, hbrush);
2057 DeleteObject(hbrush);
2061 POINT pts[2], oldpt;
2066 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2067 hpen = SelectObject(hdc, hpen);
2070 pts[1].x = x + xwidth;
2071 pts[1].y = y - ywidth;
2072 DPtoLP(hdc, pts, 2);
2073 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2074 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2075 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2076 DeleteObject(SelectObject(hdc, hpen));
2081 hpen = CreatePen(PS_SOLID, strikeoutWidth, 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 - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2089 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2090 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2091 DeleteObject(SelectObject(hdc, hpen));
2100 /***********************************************************************
2101 * TextOutA (GDI32.@)
2103 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2105 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2109 /***********************************************************************
2110 * TextOutW (GDI32.@)
2112 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2114 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2118 /***********************************************************************
2119 * PolyTextOutA (GDI32.@)
2123 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2125 for (; cStrings>0; cStrings--, pptxt++)
2126 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2133 /***********************************************************************
2134 * PolyTextOutW (GDI32.@)
2136 * Draw several Strings
2142 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2144 for (; cStrings>0; cStrings--, pptxt++)
2145 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2151 /* FIXME: all following APIs ******************************************/
2154 /***********************************************************************
2155 * SetMapperFlags (GDI32.@)
2157 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2159 DC *dc = get_dc_ptr( hDC );
2162 if(dc->funcs->pSetMapperFlags)
2164 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2165 /* FIXME: ret is just a success flag, we should return a proper value */
2168 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2169 release_dc_ptr( dc );
2173 /***********************************************************************
2174 * GetAspectRatioFilterEx (GDI32.@)
2176 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2178 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2183 /***********************************************************************
2184 * GetCharABCWidthsA (GDI32.@)
2186 * See GetCharABCWidthsW.
2188 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2191 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2196 if(count <= 0) return FALSE;
2198 str = HeapAlloc(GetProcessHeap(), 0, count);
2199 for(i = 0; i < count; i++)
2200 str[i] = (BYTE)(firstChar + i);
2202 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2204 for(i = 0; i < wlen; i++)
2206 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2214 HeapFree(GetProcessHeap(), 0, str);
2215 HeapFree(GetProcessHeap(), 0, wstr);
2221 /******************************************************************************
2222 * GetCharABCWidthsW [GDI32.@]
2224 * Retrieves widths of characters in range.
2227 * hdc [I] Handle of device context
2228 * firstChar [I] First character in range to query
2229 * lastChar [I] Last character in range to query
2230 * abc [O] Address of character-width structure
2233 * Only works with TrueType fonts
2239 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2242 DC *dc = get_dc_ptr(hdc);
2246 if (!dc) return FALSE;
2250 release_dc_ptr( dc );
2255 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2261 /* convert device units to logical */
2262 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2263 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2264 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2265 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2270 release_dc_ptr( dc );
2275 /******************************************************************************
2276 * GetCharABCWidthsI [GDI32.@]
2278 * Retrieves widths of characters in range.
2281 * hdc [I] Handle of device context
2282 * firstChar [I] First glyphs in range to query
2283 * count [I] Last glyphs in range to query
2284 * pgi [i] Array of glyphs to query
2285 * abc [O] Address of character-width structure
2288 * Only works with TrueType fonts
2294 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2295 LPWORD pgi, LPABC abc)
2297 DC *dc = get_dc_ptr(hdc);
2301 if (!dc) return FALSE;
2305 release_dc_ptr( dc );
2310 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2316 /* convert device units to logical */
2317 for( i = 0; i < count; i++, abc++ ) {
2318 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2319 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2320 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2325 release_dc_ptr( dc );
2330 /***********************************************************************
2331 * GetGlyphOutlineA (GDI32.@)
2333 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2334 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2335 LPVOID lpBuffer, const MAT2 *lpmat2 )
2341 if (!lpmat2) return GDI_ERROR;
2343 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2346 if(uChar > 0xff) { /* but, 2 bytes character only */
2348 mbchs[0] = (uChar & 0xff00) >> 8;
2349 mbchs[1] = (uChar & 0xff);
2352 mbchs[0] = (uChar & 0xff);
2354 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2358 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2360 HeapFree(GetProcessHeap(), 0, p);
2364 /***********************************************************************
2365 * GetGlyphOutlineW (GDI32.@)
2367 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2368 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2369 LPVOID lpBuffer, const MAT2 *lpmat2 )
2374 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2375 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2377 if (!lpmat2) return GDI_ERROR;
2379 dc = get_dc_ptr(hdc);
2380 if(!dc) return GDI_ERROR;
2383 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2384 cbBuffer, lpBuffer, lpmat2);
2388 release_dc_ptr( dc );
2393 /***********************************************************************
2394 * CreateScalableFontResourceA (GDI32.@)
2396 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2397 LPCSTR lpszResourceFile,
2398 LPCSTR lpszFontFile,
2399 LPCSTR lpszCurrentPath )
2401 LPWSTR lpszResourceFileW = NULL;
2402 LPWSTR lpszFontFileW = NULL;
2403 LPWSTR lpszCurrentPathW = NULL;
2407 if (lpszResourceFile)
2409 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2410 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2411 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2416 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2417 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2418 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2421 if (lpszCurrentPath)
2423 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2424 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2425 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2428 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2429 lpszFontFileW, lpszCurrentPathW);
2431 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2432 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2433 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2438 /***********************************************************************
2439 * CreateScalableFontResourceW (GDI32.@)
2441 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2442 LPCWSTR lpszResourceFile,
2443 LPCWSTR lpszFontFile,
2444 LPCWSTR lpszCurrentPath )
2447 FIXME("(%d,%s,%s,%s): stub\n",
2448 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2449 debugstr_w(lpszCurrentPath) );
2451 /* fHidden=1 - only visible for the calling app, read-only, not
2452 * enumerated with EnumFonts/EnumFontFamilies
2453 * lpszCurrentPath can be NULL
2456 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2457 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2459 SetLastError(ERROR_FILE_EXISTS);
2462 return FALSE; /* create failed */
2465 /*************************************************************************
2466 * GetKerningPairsA (GDI32.@)
2468 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2469 LPKERNINGPAIR kern_pairA )
2474 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2475 KERNINGPAIR *kern_pairW;
2477 if (!cPairs && kern_pairA)
2479 SetLastError(ERROR_INVALID_PARAMETER);
2483 charset = GetTextCharset(hDC);
2484 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2486 FIXME("Can't find codepage for charset %d\n", charset);
2489 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2490 * to fail on an invalid character for CP_SYMBOL.
2492 cpi.DefaultChar[0] = 0;
2493 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2495 FIXME("Can't find codepage %u info\n", csi.ciACP);
2498 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2500 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2501 if (!total_kern_pairs) return 0;
2503 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2504 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2506 for (i = 0; i < total_kern_pairs; i++)
2510 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2513 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2516 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2521 if (kern_pairs_copied >= cPairs) break;
2523 kern_pairA->wFirst = (BYTE)first;
2524 kern_pairA->wSecond = (BYTE)second;
2525 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2528 kern_pairs_copied++;
2531 HeapFree(GetProcessHeap(), 0, kern_pairW);
2533 return kern_pairs_copied;
2536 /*************************************************************************
2537 * GetKerningPairsW (GDI32.@)
2539 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2540 LPKERNINGPAIR lpKerningPairs )
2545 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2547 if (!cPairs && lpKerningPairs)
2549 SetLastError(ERROR_INVALID_PARAMETER);
2553 dc = get_dc_ptr(hDC);
2557 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2559 release_dc_ptr( dc );
2563 /*************************************************************************
2564 * TranslateCharsetInfo [GDI32.@]
2566 * Fills a CHARSETINFO structure for a character set, code page, or
2567 * font. This allows making the correspondence between different labels
2568 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2569 * of the same encoding.
2571 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2572 * only one codepage should be set in *lpSrc.
2575 * TRUE on success, FALSE on failure.
2578 BOOL WINAPI TranslateCharsetInfo(
2579 LPDWORD lpSrc, /* [in]
2580 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2581 if flags == TCI_SRCCHARSET: a character set value
2582 if flags == TCI_SRCCODEPAGE: a code page value
2584 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2585 DWORD flags /* [in] determines interpretation of lpSrc */)
2589 case TCI_SRCFONTSIG:
2590 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2592 case TCI_SRCCODEPAGE:
2593 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2595 case TCI_SRCCHARSET:
2596 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2601 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2602 *lpCs = FONT_tci[index];
2606 /*************************************************************************
2607 * GetFontLanguageInfo (GDI32.@)
2609 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2611 FONTSIGNATURE fontsig;
2612 static const DWORD GCP_DBCS_MASK=0x003F0000,
2613 GCP_DIACRITIC_MASK=0x00000000,
2614 FLI_GLYPHS_MASK=0x00000000,
2615 GCP_GLYPHSHAPE_MASK=0x00000040,
2616 GCP_KASHIDA_MASK=0x00000000,
2617 GCP_LIGATE_MASK=0x00000000,
2618 GCP_USEKERNING_MASK=0x00000000,
2619 GCP_REORDER_MASK=0x00000060;
2623 GetTextCharsetInfo( hdc, &fontsig, 0 );
2624 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2626 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2629 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2630 result|=GCP_DIACRITIC;
2632 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2635 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2636 result|=GCP_GLYPHSHAPE;
2638 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2639 result|=GCP_KASHIDA;
2641 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2644 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2645 result|=GCP_USEKERNING;
2647 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2648 if( GetTextAlign( hdc) & TA_RTLREADING )
2649 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2650 result|=GCP_REORDER;
2656 /*************************************************************************
2657 * GetFontData [GDI32.@]
2659 * Retrieve data for TrueType font.
2663 * success: Number of bytes returned
2664 * failure: GDI_ERROR
2668 * Calls SetLastError()
2671 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2672 LPVOID buffer, DWORD length)
2674 DC *dc = get_dc_ptr(hdc);
2675 DWORD ret = GDI_ERROR;
2677 if(!dc) return GDI_ERROR;
2680 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2682 release_dc_ptr( dc );
2686 /*************************************************************************
2687 * GetGlyphIndicesA [GDI32.@]
2689 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2690 LPWORD pgi, DWORD flags)
2696 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2697 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2699 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2700 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2701 HeapFree(GetProcessHeap(), 0, lpstrW);
2706 /*************************************************************************
2707 * GetGlyphIndicesW [GDI32.@]
2709 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2710 LPWORD pgi, DWORD flags)
2712 DC *dc = get_dc_ptr(hdc);
2713 DWORD ret = GDI_ERROR;
2715 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2716 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2718 if(!dc) return GDI_ERROR;
2721 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2723 release_dc_ptr( dc );
2727 /*************************************************************************
2728 * GetCharacterPlacementA [GDI32.@]
2730 * See GetCharacterPlacementW.
2733 * the web browser control of ie4 calls this with dwFlags=0
2736 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2737 INT nMaxExtent, GCP_RESULTSA *lpResults,
2742 GCP_RESULTSW resultsW;
2746 TRACE("%s, %d, %d, 0x%08x\n",
2747 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2749 /* both structs are equal in size */
2750 memcpy(&resultsW, lpResults, sizeof(resultsW));
2752 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2753 if(lpResults->lpOutString)
2754 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2756 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2758 lpResults->nGlyphs = resultsW.nGlyphs;
2759 lpResults->nMaxFit = resultsW.nMaxFit;
2761 if(lpResults->lpOutString) {
2762 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2763 lpResults->lpOutString, uCount, NULL, NULL );
2766 HeapFree(GetProcessHeap(), 0, lpStringW);
2767 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2772 /*************************************************************************
2773 * GetCharacterPlacementW [GDI32.@]
2775 * Retrieve information about a string. This includes the width, reordering,
2776 * Glyphing and so on.
2780 * The width and height of the string if successful, 0 if failed.
2784 * All flags except GCP_REORDER are not yet implemented.
2785 * Reordering is not 100% compliant to the Windows BiDi method.
2786 * Caret positioning is not yet implemented for BiDi.
2787 * Classes are not yet implemented.
2791 GetCharacterPlacementW(
2792 HDC hdc, /* [in] Device context for which the rendering is to be done */
2793 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2794 INT uCount, /* [in] Number of WORDS in string. */
2795 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2796 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2797 DWORD dwFlags /* [in] Flags specifying how to process the string */
2804 TRACE("%s, %d, %d, 0x%08x\n",
2805 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2807 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2808 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2809 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2810 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2811 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2813 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2814 if(lpResults->lpClass) FIXME("classes not implemented\n");
2815 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2816 FIXME("Caret positions for complex scripts not implemented\n");
2818 nSet = (UINT)uCount;
2819 if(nSet > lpResults->nGlyphs)
2820 nSet = lpResults->nGlyphs;
2822 /* return number of initialized fields */
2823 lpResults->nGlyphs = nSet;
2825 if((dwFlags&GCP_REORDER)==0 )
2827 /* Treat the case where no special handling was requested in a fastpath way */
2828 /* copy will do if the GCP_REORDER flag is not set */
2829 if(lpResults->lpOutString)
2830 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2832 if(lpResults->lpOrder)
2834 for(i = 0; i < nSet; i++)
2835 lpResults->lpOrder[i] = i;
2839 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2840 nSet, lpResults->lpOrder );
2843 /* FIXME: Will use the placement chars */
2844 if (lpResults->lpDx)
2847 for (i = 0; i < nSet; i++)
2849 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2850 lpResults->lpDx[i]= c;
2854 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2858 lpResults->lpCaretPos[0] = 0;
2859 for (i = 1; i < nSet; i++)
2860 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2861 lpResults->lpCaretPos[i] = (pos += size.cx);
2864 if(lpResults->lpGlyphs)
2865 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2867 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2868 ret = MAKELONG(size.cx, size.cy);
2873 /*************************************************************************
2874 * GetCharABCWidthsFloatA [GDI32.@]
2876 * See GetCharABCWidthsFloatW.
2878 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2880 INT i, wlen, count = (INT)(last - first + 1);
2885 if (count <= 0) return FALSE;
2887 str = HeapAlloc(GetProcessHeap(), 0, count);
2889 for(i = 0; i < count; i++)
2890 str[i] = (BYTE)(first + i);
2892 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2894 for (i = 0; i < wlen; i++)
2896 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2904 HeapFree( GetProcessHeap(), 0, str );
2905 HeapFree( GetProcessHeap(), 0, wstr );
2910 /*************************************************************************
2911 * GetCharABCWidthsFloatW [GDI32.@]
2913 * Retrieves widths of a range of characters.
2916 * hdc [I] Handle to device context.
2917 * first [I] First character in range to query.
2918 * last [I] Last character in range to query.
2919 * abcf [O] Array of LPABCFLOAT structures.
2926 * Only works with TrueType fonts. It also doesn't return real
2927 * floats but converted integers because it's implemented on
2928 * top of GetCharABCWidthsW.
2930 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2932 ABC *abc, *abc_base;
2933 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2936 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2938 abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2939 if (!abc) return FALSE;
2941 ret = GetCharABCWidthsW( hdc, first, last, abc );
2944 for (i = first; i <= last; i++, abc++, abcf++)
2946 abcf->abcfA = abc->abcA;
2947 abcf->abcfB = abc->abcB;
2948 abcf->abcfC = abc->abcC;
2951 HeapFree( GetProcessHeap(), 0, abc_base );
2955 /*************************************************************************
2956 * GetCharWidthFloatA [GDI32.@]
2958 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2959 UINT iLastChar, PFLOAT pxBuffer)
2961 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2965 /*************************************************************************
2966 * GetCharWidthFloatW [GDI32.@]
2968 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2969 UINT iLastChar, PFLOAT pxBuffer)
2971 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2976 /***********************************************************************
2978 * Font Resource API *
2980 ***********************************************************************/
2982 /***********************************************************************
2983 * AddFontResourceA (GDI32.@)
2985 INT WINAPI AddFontResourceA( LPCSTR str )
2987 return AddFontResourceExA( str, 0, NULL);
2990 /***********************************************************************
2991 * AddFontResourceW (GDI32.@)
2993 INT WINAPI AddFontResourceW( LPCWSTR str )
2995 return AddFontResourceExW(str, 0, NULL);
2999 /***********************************************************************
3000 * AddFontResourceExA (GDI32.@)
3002 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3004 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3005 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3008 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3009 ret = AddFontResourceExW(strW, fl, pdv);
3010 HeapFree(GetProcessHeap(), 0, strW);
3014 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3016 HRSRC rsrc = FindResourceW(hModule, name, type);
3017 HGLOBAL hMem = LoadResource(hModule, rsrc);
3018 LPVOID *pMem = LockResource(hMem);
3019 int *num_total = (int *)lParam;
3022 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3023 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3025 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3029 *num_total += num_in_res;
3033 /***********************************************************************
3034 * AddFontResourceExW (GDI32.@)
3036 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3038 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3041 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3042 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3043 if (hModule != NULL)
3045 int num_resources = 0;
3046 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3048 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3049 wine_dbgstr_w(str));
3050 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3051 ret = num_resources;
3052 FreeLibrary(hModule);
3058 /***********************************************************************
3059 * RemoveFontResourceA (GDI32.@)
3061 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3063 return RemoveFontResourceExA(str, 0, 0);
3066 /***********************************************************************
3067 * RemoveFontResourceW (GDI32.@)
3069 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3071 return RemoveFontResourceExW(str, 0, 0);
3074 /***********************************************************************
3075 * AddFontMemResourceEx (GDI32.@)
3077 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3079 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3082 /***********************************************************************
3083 * RemoveFontMemResourceEx (GDI32.@)
3085 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3087 FIXME("(%p) stub\n", fh);
3091 /***********************************************************************
3092 * RemoveFontResourceExA (GDI32.@)
3094 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3096 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3097 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3100 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3101 ret = RemoveFontResourceExW(strW, fl, pdv);
3102 HeapFree(GetProcessHeap(), 0, strW);
3106 /***********************************************************************
3107 * RemoveFontResourceExW (GDI32.@)
3109 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3111 return WineEngRemoveFontResourceEx(str, fl, pdv);
3114 /***********************************************************************
3115 * GetTextCharset (GDI32.@)
3117 UINT WINAPI GetTextCharset(HDC hdc)
3119 /* MSDN docs say this is equivalent */
3120 return GetTextCharsetInfo(hdc, NULL, 0);
3123 /***********************************************************************
3124 * GetTextCharsetInfo (GDI32.@)
3126 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3128 UINT ret = DEFAULT_CHARSET;
3129 DC *dc = get_dc_ptr(hdc);
3134 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3136 release_dc_ptr( dc );
3139 if (ret == DEFAULT_CHARSET && fs)
3140 memset(fs, 0, sizeof(FONTSIGNATURE));
3144 /***********************************************************************
3145 * GdiGetCharDimensions (GDI32.@)
3147 * Gets the average width of the characters in the English alphabet.
3150 * hdc [I] Handle to the device context to measure on.
3151 * lptm [O] Pointer to memory to store the text metrics into.
3152 * height [O] On exit, the maximum height of characters in the English alphabet.
3155 * The average width of characters in the English alphabet.
3158 * This function is used by the dialog manager to get the size of a dialog
3159 * unit. It should also be used by other pieces of code that need to know
3160 * the size of a dialog unit in logical units without having access to the
3161 * window handle of the dialog.
3162 * Windows caches the font metrics from this function, but we don't and
3163 * there doesn't appear to be an immediate advantage to do so.
3166 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3168 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3171 static const WCHAR alphabet[] = {
3172 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3173 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3174 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3176 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3178 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3180 if (height) *height = sz.cy;
3181 return (sz.cx / 26 + 1) / 2;
3184 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3186 FIXME("(%d): stub\n", fEnableEUDC);
3190 /***********************************************************************
3191 * GetCharWidthI (GDI32.@)
3193 * Retrieve widths of characters.
3196 * hdc [I] Handle to a device context.
3197 * first [I] First glyph in range to query.
3198 * count [I] Number of glyph indices to query.
3199 * glyphs [I] Array of glyphs to query.
3200 * buffer [O] Buffer to receive character widths.
3203 * Only works with TrueType fonts.
3209 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3214 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3216 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3219 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3221 HeapFree(GetProcessHeap(), 0, abc);
3225 for (i = 0; i < count; i++)
3226 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3228 HeapFree(GetProcessHeap(), 0, abc);
3232 /***********************************************************************
3233 * GetFontUnicodeRanges (GDI32.@)
3235 * Retrieve a list of supported Unicode characters in a font.
3238 * hdc [I] Handle to a device context.
3239 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3242 * Success: Number of bytes written to the buffer pointed to by lpgs.
3246 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3249 DC *dc = get_dc_ptr(hdc);
3251 TRACE("(%p, %p)\n", hdc, lpgs);
3255 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3261 /*************************************************************
3262 * FontIsLinked (GDI32.@)
3264 BOOL WINAPI FontIsLinked(HDC hdc)
3266 DC *dc = get_dc_ptr(hdc);
3269 if (!dc) return FALSE;
3270 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3272 TRACE("returning %d\n", ret);
3276 /*************************************************************
3277 * GdiRealizationInfo (GDI32.@)
3279 * Returns a structure that contains some font information.
3281 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3283 DC *dc = get_dc_ptr(hdc);
3286 if (!dc) return FALSE;
3287 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);