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, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
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 UINT last_char = ptmW->tmLastChar;
216 if (last_char > 0xf000) last_char -= 0xf000;
217 ptmA->tmLastChar = min(last_char, 255);
220 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
221 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
222 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
223 ptmA->tmItalic = ptmW->tmItalic;
224 ptmA->tmUnderlined = ptmW->tmUnderlined;
225 ptmA->tmStruckOut = ptmW->tmStruckOut;
226 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
227 ptmA->tmCharSet = ptmW->tmCharSet;
231 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
233 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
234 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
235 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
236 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
237 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
238 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
242 /***********************************************************************
243 * GdiGetCodePage (GDI32.@)
245 DWORD WINAPI GdiGetCodePage( HDC hdc )
249 int charset = GetTextCharset(hdc);
251 /* Hmm, nicely designed api this one! */
252 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
259 case DEFAULT_CHARSET:
270 /* FIXME: These have no place here, but because x11drv
271 enumerates fonts with these (made up) charsets some apps
272 might use them and then the FIXME below would become
273 annoying. Now we could pick the intended codepage for
274 each of these, but since it's broken anyway we'll just
275 use CP_ACP and hope it'll go away...
281 FIXME("Can't find codepage for charset %d\n", charset);
286 TRACE("charset %d => cp %d\n", charset, cp);
290 /***********************************************************************
293 * Returns a Unicode translation of str using the charset of the
294 * currently selected font in hdc. If count is -1 then str is assumed
295 * to be '\0' terminated, otherwise it contains the number of bytes to
296 * convert. If plenW is non-NULL, on return it will point to the
297 * number of WCHARs that have been written. If pCP is non-NULL, on
298 * return it will point to the codepage used in the conversion. The
299 * caller should free the returned LPWSTR from the process heap
302 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
308 cp = GdiGetCodePage( hdc );
310 if(count == -1) count = strlen(str);
311 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
312 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
313 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
314 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
315 if(plenW) *plenW = lenW;
321 /***********************************************************************
322 * CreateFontIndirectA (GDI32.@)
324 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
330 FONT_LogFontAToW( plfA, &lfW );
331 return CreateFontIndirectW( &lfW );
334 /***********************************************************************
335 * CreateFontIndirectW (GDI32.@)
337 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
339 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
340 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
341 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
342 WCHAR *pFaceNameSuffix = NULL;
348 if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
349 &font_funcs ))) return 0;
351 fontPtr->logfont = *plf;
353 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
354 plf->lfHeight, plf->lfWidth,
355 plf->lfEscapement, plf->lfOrientation,
356 plf->lfPitchAndFamily,
357 plf->lfOutPrecision, plf->lfClipPrecision,
358 plf->lfQuality, plf->lfCharSet,
359 debugstr_w(plf->lfFaceName),
360 plf->lfWeight > 400 ? "Bold" : "",
361 plf->lfItalic ? "Italic" : "",
362 plf->lfUnderline ? "Underline" : "", hFont);
364 if (plf->lfEscapement != plf->lfOrientation)
366 /* this should really depend on whether GM_ADVANCED is set */
367 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
368 WARN("orientation angle %f set to "
369 "escapement angle %f for new font %p\n",
370 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
373 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
374 if (pFaceNameItalicSuffix)
376 fontPtr->logfont.lfItalic = TRUE;
377 pFaceNameSuffix = pFaceNameItalicSuffix;
380 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
381 if (pFaceNameBoldSuffix)
383 if (fontPtr->logfont.lfWeight < FW_BOLD)
384 fontPtr->logfont.lfWeight = FW_BOLD;
385 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
386 pFaceNameSuffix = pFaceNameBoldSuffix;
389 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
391 GDI_ReleaseObj( hFont );
395 /*************************************************************************
396 * CreateFontA (GDI32.@)
398 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
399 INT orient, INT weight, DWORD italic,
400 DWORD underline, DWORD strikeout, DWORD charset,
401 DWORD outpres, DWORD clippres, DWORD quality,
402 DWORD pitch, LPCSTR name )
406 logfont.lfHeight = height;
407 logfont.lfWidth = width;
408 logfont.lfEscapement = esc;
409 logfont.lfOrientation = orient;
410 logfont.lfWeight = weight;
411 logfont.lfItalic = italic;
412 logfont.lfUnderline = underline;
413 logfont.lfStrikeOut = strikeout;
414 logfont.lfCharSet = charset;
415 logfont.lfOutPrecision = outpres;
416 logfont.lfClipPrecision = clippres;
417 logfont.lfQuality = quality;
418 logfont.lfPitchAndFamily = pitch;
421 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
423 logfont.lfFaceName[0] = '\0';
425 return CreateFontIndirectA( &logfont );
428 /*************************************************************************
429 * CreateFontW (GDI32.@)
431 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
432 INT orient, INT weight, DWORD italic,
433 DWORD underline, DWORD strikeout, DWORD charset,
434 DWORD outpres, DWORD clippres, DWORD quality,
435 DWORD pitch, LPCWSTR name )
439 logfont.lfHeight = height;
440 logfont.lfWidth = width;
441 logfont.lfEscapement = esc;
442 logfont.lfOrientation = orient;
443 logfont.lfWeight = weight;
444 logfont.lfItalic = italic;
445 logfont.lfUnderline = underline;
446 logfont.lfStrikeOut = strikeout;
447 logfont.lfCharSet = charset;
448 logfont.lfOutPrecision = outpres;
449 logfont.lfClipPrecision = clippres;
450 logfont.lfQuality = quality;
451 logfont.lfPitchAndFamily = pitch;
454 lstrcpynW(logfont.lfFaceName, name,
455 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
457 logfont.lfFaceName[0] = '\0';
459 return CreateFontIndirectW( &logfont );
463 /***********************************************************************
466 * If the driver supports vector fonts we create a gdi font first and
467 * then call the driver to give it a chance to supply its own device
468 * font. If the driver wants to do this it returns TRUE and we can
469 * delete the gdi font, if the driver wants to use the gdi font it
470 * should return FALSE, to signal an error return GDI_ERROR. For
471 * drivers that don't support vector fonts they must supply their own
474 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
477 DC *dc = get_dc_ptr( hdc );
481 if (!GDI_inc_ref_count( handle ))
483 release_dc_ptr( dc );
487 if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
489 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
490 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
491 if (font) GDI_ReleaseObj( handle );
494 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
496 if (ret && dc->gdiFont) dc->gdiFont = 0;
498 if (ret == HGDI_ERROR)
500 GDI_dec_ref_count( handle );
501 ret = 0; /* SelectObject returns 0 on error */
507 GDI_dec_ref_count( ret );
509 release_dc_ptr( dc );
514 /***********************************************************************
517 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
524 FONT_LogFontWToA( &font->logfont, &lfA );
526 if (count > sizeof(lfA)) count = sizeof(lfA);
527 memcpy( buffer, &lfA, count );
531 /***********************************************************************
534 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
538 return sizeof(LOGFONTW);
539 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
540 memcpy( buffer, &font->logfont, count );
545 /***********************************************************************
548 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
550 WineEngDestroyFontInstance( handle );
551 return GDI_FreeObject( handle, obj );
555 /***********************************************************************
558 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
559 * We have to use other types because of the FONTENUMPROCW definition.
561 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
562 DWORD fType, LPARAM lp )
564 fontEnum32 *pfe = (fontEnum32*)lp;
567 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
568 if ((!pfe->lpLogFontParam ||
569 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
570 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
571 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
573 /* convert font metrics */
574 ENUMLOGFONTEXA logfont;
575 NEWTEXTMETRICEXA tmA;
577 pfe->dwFlags |= ENUM_CALLED;
578 if (!(pfe->dwFlags & ENUM_UNICODE))
580 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
581 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
582 plf = (LOGFONTW *)&logfont.elfLogFont;
583 ptm = (TEXTMETRICW *)&tmA;
586 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
591 /***********************************************************************
592 * FONT_EnumFontFamiliesEx
594 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
595 FONTENUMPROCW efproc,
596 LPARAM lParam, DWORD dwUnicode)
599 DC *dc = get_dc_ptr( hDC );
606 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
608 fe32.lpLogFontParam = plf;
609 fe32.lpEnumFunc = efproc;
610 fe32.lpData = lParam;
611 fe32.dwFlags = dwUnicode;
614 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
616 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
623 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
624 fe32.dwFlags &= ~ENUM_CALLED;
625 if (ret && dc->funcs->pEnumDeviceFonts) {
626 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
627 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
631 release_dc_ptr( dc );
635 /***********************************************************************
636 * EnumFontFamiliesExW (GDI32.@)
638 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
639 FONTENUMPROCW efproc,
640 LPARAM lParam, DWORD dwFlags )
642 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
645 /***********************************************************************
646 * EnumFontFamiliesExA (GDI32.@)
648 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
649 FONTENUMPROCA efproc,
650 LPARAM lParam, DWORD dwFlags)
656 FONT_LogFontAToW( plf, &lfW );
661 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
664 /***********************************************************************
665 * EnumFontFamiliesA (GDI32.@)
667 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
668 FONTENUMPROCA efproc, LPARAM lpData )
674 if (!*lpFamily) return 1;
675 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
676 lf.lfCharSet = DEFAULT_CHARSET;
677 lf.lfPitchAndFamily = 0;
682 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
685 /***********************************************************************
686 * EnumFontFamiliesW (GDI32.@)
688 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
689 FONTENUMPROCW efproc, LPARAM lpData )
695 if (!*lpFamily) return 1;
696 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
697 lf.lfCharSet = DEFAULT_CHARSET;
698 lf.lfPitchAndFamily = 0;
703 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
706 /***********************************************************************
707 * EnumFontsA (GDI32.@)
709 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
712 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
715 /***********************************************************************
716 * EnumFontsW (GDI32.@)
718 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
721 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
725 /***********************************************************************
726 * GetTextCharacterExtra (GDI32.@)
728 INT WINAPI GetTextCharacterExtra( HDC hdc )
731 DC *dc = get_dc_ptr( hdc );
732 if (!dc) return 0x80000000;
734 release_dc_ptr( dc );
739 /***********************************************************************
740 * SetTextCharacterExtra (GDI32.@)
742 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
745 DC * dc = get_dc_ptr( hdc );
746 if (!dc) return 0x80000000;
747 if (dc->funcs->pSetTextCharacterExtra)
748 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
751 prev = dc->charExtra;
752 dc->charExtra = extra;
754 release_dc_ptr( dc );
759 /***********************************************************************
760 * SetTextJustification (GDI32.@)
762 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
765 DC * dc = get_dc_ptr( hdc );
766 if (!dc) return FALSE;
767 if (dc->funcs->pSetTextJustification)
768 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
771 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
772 if (!extra) breaks = 0;
775 dc->breakExtra = extra / breaks;
776 dc->breakRem = extra - (breaks * dc->breakExtra);
784 release_dc_ptr( dc );
789 /***********************************************************************
790 * GetTextFaceA (GDI32.@)
792 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
794 INT res = GetTextFaceW(hdc, 0, NULL);
795 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
796 GetTextFaceW( hdc, res, nameW );
802 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
806 /* GetTextFaceA does NOT include the nul byte in the return count. */
813 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
814 HeapFree( GetProcessHeap(), 0, nameW );
818 /***********************************************************************
819 * GetTextFaceW (GDI32.@)
821 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
826 DC * dc = get_dc_ptr( hdc );
830 ret = WineEngGetTextFace(dc->gdiFont, count, name);
831 else if ((font = GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
833 INT n = strlenW(font->logfont.lfFaceName) + 1;
836 lstrcpynW( name, font->logfont.lfFaceName, count );
840 GDI_ReleaseObj( dc->hFont );
842 release_dc_ptr( dc );
847 /***********************************************************************
848 * GetTextExtentPoint32A (GDI32.@)
850 * See GetTextExtentPoint32W.
852 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
857 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
860 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
861 HeapFree( GetProcessHeap(), 0, p );
864 TRACE("(%p %s %d %p): returning %d x %d\n",
865 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
870 /***********************************************************************
871 * GetTextExtentPoint32W [GDI32.@]
873 * Computes width/height for a string.
875 * Computes width and height of the specified string.
881 BOOL WINAPI GetTextExtentPoint32W(
882 HDC hdc, /* [in] Handle of device context */
883 LPCWSTR str, /* [in] Address of text string */
884 INT count, /* [in] Number of characters in string */
885 LPSIZE size) /* [out] Address of structure for string size */
887 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
890 /***********************************************************************
891 * GetTextExtentExPointI [GDI32.@]
893 * Computes width and height of the array of glyph indices.
896 * hdc [I] Handle of device context.
897 * indices [I] Glyph index array.
898 * count [I] Number of glyphs in array.
899 * max_ext [I] Maximum width in glyphs.
900 * nfit [O] Maximum number of characters.
901 * dxs [O] Partial string widths.
902 * size [O] Returned string size.
908 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
909 LPINT nfit, LPINT dxs, LPSIZE size )
912 DC * dc = get_dc_ptr( hdc );
913 if (!dc) return FALSE;
916 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
917 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
918 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
919 size->cx += count * dc->charExtra;
921 else if(dc->funcs->pGetTextExtentExPoint) {
922 FIXME("calling GetTextExtentExPoint\n");
923 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
924 count, max_ext, nfit, dxs, size );
927 release_dc_ptr( dc );
929 TRACE("(%p %p %d %p): returning %d x %d\n",
930 hdc, indices, count, size, size->cx, size->cy );
934 /***********************************************************************
935 * GetTextExtentPointI [GDI32.@]
937 * Computes width and height of the array of glyph indices.
940 * hdc [I] Handle of device context.
941 * indices [I] Glyph index array.
942 * count [I] Number of glyphs in array.
943 * size [O] Returned string size.
949 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
951 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
955 /***********************************************************************
956 * GetTextExtentPointA (GDI32.@)
958 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
961 TRACE("not bug compatible.\n");
962 return GetTextExtentPoint32A( hdc, str, count, size );
965 /***********************************************************************
966 * GetTextExtentPointW (GDI32.@)
968 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
971 TRACE("not bug compatible.\n");
972 return GetTextExtentPoint32W( hdc, str, count, size );
976 /***********************************************************************
977 * GetTextExtentExPointA (GDI32.@)
979 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
980 INT maxExt, LPINT lpnFit,
981 LPINT alpDx, LPSIZE size )
989 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
992 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
993 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
996 INT n = lpnFit ? *lpnFit : wlen;
998 for(i = 0, j = 0; i < n; i++, j++)
1000 alpDx[j] = walpDx[i];
1001 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1004 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1005 HeapFree( GetProcessHeap(), 0, p );
1006 HeapFree( GetProcessHeap(), 0, walpDx );
1011 /***********************************************************************
1012 * GetTextExtentExPointW (GDI32.@)
1014 * Return the size of the string as it would be if it was output properly by
1017 * This should include
1018 * - Intercharacter spacing
1019 * - justification spacing (not yet done)
1020 * - kerning? see below
1022 * Kerning. Since kerning would be carried out by the rendering code it should
1023 * be done by the driver. However they don't support it yet. Also I am not
1024 * yet persuaded that (certainly under Win95) any kerning is actually done.
1026 * str: According to MSDN this should be null-terminated. That is not true; a
1027 * null will not terminate it early.
1028 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1029 * than count. I have seen it be either the size of the full string or
1030 * 1 less than the size of the full string. I have not seen it bear any
1031 * resemblance to the portion that would fit.
1032 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1033 * trailing intercharacter spacing and any trailing justification.
1036 * Currently we do this by measuring each character etc. We should do it by
1037 * passing the request to the driver, perhaps by extending the
1038 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1039 * thinking about kerning issues and rounding issues in the justification.
1042 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1043 INT maxExt, LPINT lpnFit,
1044 LPINT alpDx, LPSIZE size )
1052 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1054 dc = get_dc_ptr(hdc);
1058 GetTextMetricsW(hdc, &tm);
1060 /* If we need to calculate nFit, then we need the partial extents even if
1061 the user hasn't provided us with an array. */
1064 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1068 SetLastError(ERROR_OUTOFMEMORY);
1076 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1077 0, NULL, dxs, size);
1078 else if (dc->funcs->pGetTextExtentExPoint)
1079 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1080 0, NULL, dxs, size);
1082 /* Perform device size to world size transformations. */
1085 INT extra = dc->charExtra,
1086 breakExtra = dc->breakExtra,
1087 breakRem = dc->breakRem,
1092 for (i = 0; i < count; ++i)
1094 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1095 dxs[i] += (i+1) * extra;
1096 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1098 dxs[i] += breakExtra;
1105 if (dxs[i] <= maxExt)
1108 breakRem = dc->breakRem;
1110 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1111 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1113 if (!dxs && count > 1 && (breakExtra || breakRem))
1115 for (i = 0; i < count; i++)
1117 if (str[i] == tm.tmBreakChar)
1119 size->cx += breakExtra;
1134 HeapFree(GetProcessHeap(), 0, dxs);
1136 release_dc_ptr( dc );
1138 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1142 /***********************************************************************
1143 * GetTextMetricsA (GDI32.@)
1145 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1149 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1150 FONT_TextMetricWToA( &tm32, metrics );
1154 /***********************************************************************
1155 * GetTextMetricsW (GDI32.@)
1157 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1160 DC * dc = get_dc_ptr( hdc );
1161 if (!dc) return FALSE;
1164 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1165 else if (dc->funcs->pGetTextMetrics)
1166 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1170 /* device layer returns values in device units
1171 * therefore we have to convert them to logical */
1173 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1174 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1176 #define WDPTOLP(x) ((x<0)? \
1177 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1178 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1179 #define HDPTOLP(y) ((y<0)? \
1180 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1181 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1183 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1184 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1185 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1186 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1187 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1188 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1189 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1190 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1194 TRACE("text metrics:\n"
1195 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1196 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1197 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1198 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1199 " PitchAndFamily = %02x\n"
1200 " --------------------\n"
1201 " InternalLeading = %i\n"
1205 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1206 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1207 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1208 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1209 metrics->tmPitchAndFamily,
1210 metrics->tmInternalLeading,
1213 metrics->tmHeight );
1215 release_dc_ptr( dc );
1220 /***********************************************************************
1221 * GetOutlineTextMetricsA (GDI32.@)
1222 * Gets metrics for TrueType fonts.
1225 * If the supplied buffer isn't big enough Windows partially fills it up to
1226 * its given length and returns that length.
1229 * Success: Non-zero or size of required buffer
1232 UINT WINAPI GetOutlineTextMetricsA(
1233 HDC hdc, /* [in] Handle of device context */
1234 UINT cbData, /* [in] Size of metric data array */
1235 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1237 char buf[512], *ptr;
1239 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1240 OUTLINETEXTMETRICA *output = lpOTM;
1243 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1245 if(ret > sizeof(buf))
1246 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1247 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1249 needed = sizeof(OUTLINETEXTMETRICA);
1250 if(lpOTMW->otmpFamilyName)
1251 needed += WideCharToMultiByte(CP_ACP, 0,
1252 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1253 NULL, 0, NULL, NULL);
1254 if(lpOTMW->otmpFaceName)
1255 needed += WideCharToMultiByte(CP_ACP, 0,
1256 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1257 NULL, 0, NULL, NULL);
1258 if(lpOTMW->otmpStyleName)
1259 needed += WideCharToMultiByte(CP_ACP, 0,
1260 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1261 NULL, 0, NULL, NULL);
1262 if(lpOTMW->otmpFullName)
1263 needed += WideCharToMultiByte(CP_ACP, 0,
1264 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1265 NULL, 0, NULL, NULL);
1272 TRACE("needed = %d\n", needed);
1274 /* Since the supplied buffer isn't big enough, we'll alloc one
1275 that is and memcpy the first cbData bytes into the lpOTM at
1277 output = HeapAlloc(GetProcessHeap(), 0, needed);
1279 ret = output->otmSize = min(needed, cbData);
1280 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1281 output->otmFiller = 0;
1282 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1283 output->otmfsSelection = lpOTMW->otmfsSelection;
1284 output->otmfsType = lpOTMW->otmfsType;
1285 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1286 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1287 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1288 output->otmEMSquare = lpOTMW->otmEMSquare;
1289 output->otmAscent = lpOTMW->otmAscent;
1290 output->otmDescent = lpOTMW->otmDescent;
1291 output->otmLineGap = lpOTMW->otmLineGap;
1292 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1293 output->otmsXHeight = lpOTMW->otmsXHeight;
1294 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1295 output->otmMacAscent = lpOTMW->otmMacAscent;
1296 output->otmMacDescent = lpOTMW->otmMacDescent;
1297 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1298 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1299 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1300 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1301 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1302 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1303 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1304 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1305 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1306 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1309 ptr = (char*)(output + 1);
1310 left = needed - sizeof(*output);
1312 if(lpOTMW->otmpFamilyName) {
1313 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1314 len = WideCharToMultiByte(CP_ACP, 0,
1315 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1316 ptr, left, NULL, NULL);
1320 output->otmpFamilyName = 0;
1322 if(lpOTMW->otmpFaceName) {
1323 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1324 len = WideCharToMultiByte(CP_ACP, 0,
1325 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1326 ptr, left, NULL, NULL);
1330 output->otmpFaceName = 0;
1332 if(lpOTMW->otmpStyleName) {
1333 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1334 len = WideCharToMultiByte(CP_ACP, 0,
1335 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1336 ptr, left, NULL, NULL);
1340 output->otmpStyleName = 0;
1342 if(lpOTMW->otmpFullName) {
1343 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1344 len = WideCharToMultiByte(CP_ACP, 0,
1345 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1346 ptr, left, NULL, NULL);
1349 output->otmpFullName = 0;
1353 if(output != lpOTM) {
1354 memcpy(lpOTM, output, cbData);
1355 HeapFree(GetProcessHeap(), 0, output);
1357 /* check if the string offsets really fit into the provided size */
1358 /* FIXME: should we check string length as well? */
1359 /* make sure that we don't read/write beyond the provided buffer */
1360 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1362 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1363 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1366 /* make sure that we don't read/write beyond the provided buffer */
1367 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1369 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1370 lpOTM->otmpFaceName = 0; /* doesn't fit */
1373 /* make sure that we don't read/write beyond the provided buffer */
1374 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1376 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1377 lpOTM->otmpStyleName = 0; /* doesn't fit */
1380 /* make sure that we don't read/write beyond the provided buffer */
1381 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1383 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1384 lpOTM->otmpFullName = 0; /* doesn't fit */
1389 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1390 HeapFree(GetProcessHeap(), 0, lpOTMW);
1396 /***********************************************************************
1397 * GetOutlineTextMetricsW [GDI32.@]
1399 UINT WINAPI GetOutlineTextMetricsW(
1400 HDC hdc, /* [in] Handle of device context */
1401 UINT cbData, /* [in] Size of metric data array */
1402 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1404 DC *dc = get_dc_ptr( hdc );
1405 OUTLINETEXTMETRICW *output = lpOTM;
1408 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1412 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1415 output = HeapAlloc(GetProcessHeap(), 0, ret);
1416 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1419 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1420 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1422 #define WDPTOLP(x) ((x<0)? \
1423 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1424 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1425 #define HDPTOLP(y) ((y<0)? \
1426 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1427 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1429 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1430 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1431 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1432 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1433 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1434 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1435 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1436 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1437 output->otmAscent = HDPTOLP(output->otmAscent);
1438 output->otmDescent = HDPTOLP(output->otmDescent);
1439 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1440 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1441 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1442 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1443 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1444 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1445 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1446 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1447 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1448 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1449 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1450 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1451 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1452 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1453 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1454 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1455 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1456 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1457 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1458 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1459 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1460 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1463 if(output != lpOTM) {
1464 memcpy(lpOTM, output, cbData);
1465 HeapFree(GetProcessHeap(), 0, output);
1471 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1472 but really this should just be a return 0. */
1474 ret = sizeof(*lpOTM);
1479 memset(lpOTM, 0, ret);
1480 lpOTM->otmSize = sizeof(*lpOTM);
1481 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1483 Further fill of the structure not implemented,
1484 Needs real values for the structure members
1494 /***********************************************************************
1495 * GetCharWidthW (GDI32.@)
1496 * GetCharWidth32W (GDI32.@)
1498 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1503 DC * dc = get_dc_ptr( hdc );
1504 if (!dc) return FALSE;
1507 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1508 else if (dc->funcs->pGetCharWidth)
1509 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1513 /* convert device units to logical */
1514 for( i = firstChar; i <= lastChar; i++, buffer++ )
1515 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1518 release_dc_ptr( dc );
1523 /***********************************************************************
1524 * GetCharWidthA (GDI32.@)
1525 * GetCharWidth32A (GDI32.@)
1527 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1530 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1535 if(count <= 0) return FALSE;
1537 str = HeapAlloc(GetProcessHeap(), 0, count);
1538 for(i = 0; i < count; i++)
1539 str[i] = (BYTE)(firstChar + i);
1541 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1543 for(i = 0; i < wlen; i++)
1545 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1553 HeapFree(GetProcessHeap(), 0, str);
1554 HeapFree(GetProcessHeap(), 0, wstr);
1560 /***********************************************************************
1561 * ExtTextOutA (GDI32.@)
1565 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1566 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1574 if (flags & ETO_GLYPH_INDEX)
1575 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1577 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1580 unsigned int i = 0, j = 0;
1582 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1584 if(IsDBCSLeadByteEx(codepage, str[i])) {
1585 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1588 lpDxW[j++] = lpDx[i];
1594 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1596 HeapFree( GetProcessHeap(), 0, p );
1597 HeapFree( GetProcessHeap(), 0, lpDxW );
1602 /***********************************************************************
1603 * ExtTextOutW (GDI32.@)
1605 * Draws text using the currently selected font, background color, and text color.
1609 * x,y [I] coordinates of string
1611 * ETO_GRAYED - undocumented on MSDN
1612 * ETO_OPAQUE - use background color for fill the rectangle
1613 * ETO_CLIPPED - clipping text to the rectangle
1614 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1615 * than encoded characters. Implies ETO_IGNORELANGUAGE
1616 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1617 * Affects BiDi ordering
1618 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1619 * ETO_PDY - unimplemented
1620 * ETO_NUMERICSLATIN - unimplemented always assumed -
1621 * do not translate numbers into locale representations
1622 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1623 * lprect [I] dimensions for clipping or/and opaquing
1624 * str [I] text string
1625 * count [I] number of symbols in string
1626 * lpDx [I] optional parameter with distance between drawing characters
1632 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1633 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1636 LPWSTR reordered_str = (LPWSTR)str;
1637 WORD *glyphs = NULL;
1638 UINT align = GetTextAlign( hdc );
1642 double cosEsc, sinEsc;
1643 INT *deltas = NULL, char_extra;
1646 BOOL done_extents = FALSE;
1647 INT width = 0, xwidth = 0, ywidth = 0;
1649 DC * dc = get_dc_ptr( hdc );
1651 static int quietfixme = 0;
1653 if (!dc) return FALSE;
1655 breakRem = dc->breakRem;
1657 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1659 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1662 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1664 release_dc_ptr( dc );
1669 type = GetObjectType(hdc);
1670 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1672 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1673 release_dc_ptr( dc );
1678 flags &= ~ETO_CLIPPED;
1680 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1682 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1684 BIDI_Reorder( str, count, GCP_REORDER,
1685 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1686 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1687 reordered_str, count, NULL );
1689 flags |= ETO_IGNORELANGUAGE;
1692 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1693 lprect, debugstr_wn(str, count), count, lpDx);
1695 if(flags & ETO_GLYPH_INDEX)
1696 glyphs = reordered_str;
1699 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1701 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1703 if(align & TA_UPDATECP)
1705 GetCurrentPositionEx( hdc, &pt );
1710 GetTextMetricsW(hdc, &tm);
1711 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1713 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1714 lf.lfEscapement = 0;
1716 if(lf.lfEscapement != 0)
1718 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1719 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1727 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1731 if(flags & ETO_GLYPH_INDEX)
1732 GetTextExtentPointI(hdc, glyphs, count, &sz);
1734 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1736 done_extents = TRUE;
1739 rc.right = x + sz.cx;
1740 rc.bottom = y + sz.cy;
1747 LPtoDP(hdc, (POINT*)&rc, 2);
1749 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1750 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1753 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1754 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1764 LPtoDP(hdc, &pt, 1);
1768 char_extra = GetTextCharacterExtra(hdc);
1769 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1773 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1774 for(i = 0; i < count; i++)
1776 if(lpDx && (flags & ETO_PDY))
1777 deltas[i] = lpDx[i*2] + char_extra;
1779 deltas[i] = lpDx[i] + char_extra;
1782 if(flags & ETO_GLYPH_INDEX)
1783 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1785 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1787 deltas[i] = tmpsz.cx;
1790 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1792 deltas[i] = deltas[i] + dc->breakExtra;
1799 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1807 if(flags & ETO_GLYPH_INDEX)
1808 GetTextExtentPointI(hdc, glyphs, count, &sz);
1810 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1811 done_extents = TRUE;
1813 width = INTERNAL_XWSTODS(dc, sz.cx);
1815 xwidth = width * cosEsc;
1816 ywidth = width * sinEsc;
1818 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1819 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1820 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1823 if (align & TA_UPDATECP)
1827 DPtoLP(hdc, &pt, 1);
1828 MoveToEx(hdc, pt.x, pt.y, NULL);
1840 if (align & TA_UPDATECP)
1844 DPtoLP(hdc, &pt, 1);
1845 MoveToEx(hdc, pt.x, pt.y, NULL);
1850 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1853 y += tm.tmAscent * cosEsc;
1854 x += tm.tmAscent * sinEsc;
1858 y -= tm.tmDescent * cosEsc;
1859 x -= tm.tmDescent * sinEsc;
1866 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1868 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1870 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1871 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1875 rc.right = x + width;
1876 rc.top = y - tm.tmAscent;
1877 rc.bottom = y + tm.tmDescent;
1878 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1883 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1885 HFONT orig_font = dc->hFont, cur_font;
1887 INT span = 0, *offsets = NULL;
1890 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1891 for(i = 0; i < count; i++)
1893 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1894 if(cur_font != dc->hFont)
1899 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1904 for(j = 1; j < count; j++)
1906 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1907 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1912 for(j = 1; j < count; j++)
1913 offsets[j] = offsets[j-1] + deltas[j];
1918 if (PATH_IsPathOpen(dc->path))
1919 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1920 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1921 glyphs, span, deltas ? deltas + i - span : NULL);
1923 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1924 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1925 glyphs, span, deltas ? deltas + i - span : NULL);
1928 SelectObject(hdc, cur_font);
1930 glyphs[span++] = glyph;
1934 if (PATH_IsPathOpen(dc->path))
1935 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1936 y - (offsets ? offsets[count - span] * sinEsc : 0),
1937 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1938 glyphs, span, deltas ? deltas + count - span : NULL);
1940 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1941 y - (offsets ? offsets[count - span] * sinEsc : 0),
1942 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1943 glyphs, span, deltas ? deltas + count - span : NULL);
1944 SelectObject(hdc, orig_font);
1945 HeapFree(GetProcessHeap(), 0, offsets);
1951 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1953 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1954 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1955 flags |= ETO_GLYPH_INDEX;
1958 if (PATH_IsPathOpen(dc->path))
1959 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1960 glyphs ? glyphs : reordered_str, count, deltas);
1962 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1963 glyphs ? glyphs : reordered_str, count, deltas);
1967 HeapFree(GetProcessHeap(), 0, deltas);
1968 if(glyphs != reordered_str)
1969 HeapFree(GetProcessHeap(), 0, glyphs);
1970 if(reordered_str != str)
1971 HeapFree(GetProcessHeap(), 0, reordered_str);
1973 release_dc_ptr( dc );
1975 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
1977 int underlinePos, strikeoutPos;
1978 int underlineWidth, strikeoutWidth;
1979 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
1980 OUTLINETEXTMETRICW* otm = NULL;
1985 underlineWidth = tm.tmAscent / 20 + 1;
1986 strikeoutPos = tm.tmAscent / 2;
1987 strikeoutWidth = underlineWidth;
1991 otm = HeapAlloc(GetProcessHeap(), 0, size);
1992 GetOutlineTextMetricsW(hdc, size, otm);
1993 underlinePos = otm->otmsUnderscorePosition;
1994 underlineWidth = otm->otmsUnderscoreSize;
1995 strikeoutPos = otm->otmsStrikeoutPosition;
1996 strikeoutWidth = otm->otmsStrikeoutSize;
1997 HeapFree(GetProcessHeap(), 0, otm);
2000 if (PATH_IsPathOpen(dc->path))
2004 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2006 hbrush = SelectObject(hdc, hbrush);
2007 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2011 pts[0].x = x - underlinePos * sinEsc;
2012 pts[0].y = y - underlinePos * cosEsc;
2013 pts[1].x = x + xwidth - underlinePos * sinEsc;
2014 pts[1].y = y - ywidth - underlinePos * cosEsc;
2015 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2016 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2017 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2018 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2019 pts[4].x = pts[0].x;
2020 pts[4].y = pts[0].y;
2021 DPtoLP(hdc, pts, 5);
2022 Polygon(hdc, pts, 5);
2027 pts[0].x = x - strikeoutPos * sinEsc;
2028 pts[0].y = y - strikeoutPos * cosEsc;
2029 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2030 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2031 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2032 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2033 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2034 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2035 pts[4].x = pts[0].x;
2036 pts[4].y = pts[0].y;
2037 DPtoLP(hdc, pts, 5);
2038 Polygon(hdc, pts, 5);
2041 SelectObject(hdc, hpen);
2042 hbrush = SelectObject(hdc, hbrush);
2043 DeleteObject(hbrush);
2047 POINT pts[2], oldpt;
2052 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2053 hpen = SelectObject(hdc, hpen);
2056 pts[1].x = x + xwidth;
2057 pts[1].y = y - ywidth;
2058 DPtoLP(hdc, pts, 2);
2059 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2060 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2061 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2062 DeleteObject(SelectObject(hdc, hpen));
2067 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2068 hpen = SelectObject(hdc, hpen);
2071 pts[1].x = x + xwidth;
2072 pts[1].y = y - ywidth;
2073 DPtoLP(hdc, pts, 2);
2074 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2075 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2076 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2077 DeleteObject(SelectObject(hdc, hpen));
2086 /***********************************************************************
2087 * TextOutA (GDI32.@)
2089 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2091 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2095 /***********************************************************************
2096 * TextOutW (GDI32.@)
2098 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2100 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2104 /***********************************************************************
2105 * PolyTextOutA (GDI32.@)
2109 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2111 for (; cStrings>0; cStrings--, pptxt++)
2112 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2119 /***********************************************************************
2120 * PolyTextOutW (GDI32.@)
2122 * Draw several Strings
2128 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2130 for (; cStrings>0; cStrings--, pptxt++)
2131 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2137 /* FIXME: all following APIs ******************************************/
2140 /***********************************************************************
2141 * SetMapperFlags (GDI32.@)
2143 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2145 DC *dc = get_dc_ptr( hDC );
2148 if(dc->funcs->pSetMapperFlags)
2150 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2151 /* FIXME: ret is just a success flag, we should return a proper value */
2154 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2155 release_dc_ptr( dc );
2159 /***********************************************************************
2160 * GetAspectRatioFilterEx (GDI32.@)
2162 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2164 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2169 /***********************************************************************
2170 * GetCharABCWidthsA (GDI32.@)
2172 * See GetCharABCWidthsW.
2174 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2177 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2182 if(count <= 0) return FALSE;
2184 str = HeapAlloc(GetProcessHeap(), 0, count);
2185 for(i = 0; i < count; i++)
2186 str[i] = (BYTE)(firstChar + i);
2188 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2190 for(i = 0; i < wlen; i++)
2192 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2200 HeapFree(GetProcessHeap(), 0, str);
2201 HeapFree(GetProcessHeap(), 0, wstr);
2207 /******************************************************************************
2208 * GetCharABCWidthsW [GDI32.@]
2210 * Retrieves widths of characters in range.
2213 * hdc [I] Handle of device context
2214 * firstChar [I] First character in range to query
2215 * lastChar [I] Last character in range to query
2216 * abc [O] Address of character-width structure
2219 * Only works with TrueType fonts
2225 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2228 DC *dc = get_dc_ptr(hdc);
2232 if (!dc) return FALSE;
2236 release_dc_ptr( dc );
2241 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2247 /* convert device units to logical */
2248 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2249 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2250 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2251 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2256 release_dc_ptr( dc );
2261 /******************************************************************************
2262 * GetCharABCWidthsI [GDI32.@]
2264 * Retrieves widths of characters in range.
2267 * hdc [I] Handle of device context
2268 * firstChar [I] First glyphs in range to query
2269 * count [I] Last glyphs in range to query
2270 * pgi [i] Array of glyphs to query
2271 * abc [O] Address of character-width structure
2274 * Only works with TrueType fonts
2280 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2281 LPWORD pgi, LPABC abc)
2283 DC *dc = get_dc_ptr(hdc);
2287 if (!dc) return FALSE;
2291 release_dc_ptr( dc );
2296 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2302 /* convert device units to logical */
2303 for( i = 0; i < count; i++, abc++ ) {
2304 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2305 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2306 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2311 release_dc_ptr( dc );
2316 /***********************************************************************
2317 * GetGlyphOutlineA (GDI32.@)
2319 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2320 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2321 LPVOID lpBuffer, const MAT2 *lpmat2 )
2327 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2330 if(uChar > 0xff) { /* but, 2 bytes character only */
2332 mbchs[0] = (uChar & 0xff00) >> 8;
2333 mbchs[1] = (uChar & 0xff);
2336 mbchs[0] = (uChar & 0xff);
2338 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2342 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2344 HeapFree(GetProcessHeap(), 0, p);
2348 /***********************************************************************
2349 * GetGlyphOutlineW (GDI32.@)
2351 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2352 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2353 LPVOID lpBuffer, const MAT2 *lpmat2 )
2355 DC *dc = get_dc_ptr(hdc);
2358 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2359 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2361 if(!dc) return GDI_ERROR;
2364 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2365 cbBuffer, lpBuffer, lpmat2);
2369 release_dc_ptr( dc );
2374 /***********************************************************************
2375 * CreateScalableFontResourceA (GDI32.@)
2377 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2378 LPCSTR lpszResourceFile,
2379 LPCSTR lpszFontFile,
2380 LPCSTR lpszCurrentPath )
2382 LPWSTR lpszResourceFileW = NULL;
2383 LPWSTR lpszFontFileW = NULL;
2384 LPWSTR lpszCurrentPathW = NULL;
2388 if (lpszResourceFile)
2390 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2391 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2392 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2397 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2398 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2399 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2402 if (lpszCurrentPath)
2404 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2405 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2406 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2409 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2410 lpszFontFileW, lpszCurrentPathW);
2412 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2413 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2414 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2419 /***********************************************************************
2420 * CreateScalableFontResourceW (GDI32.@)
2422 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2423 LPCWSTR lpszResourceFile,
2424 LPCWSTR lpszFontFile,
2425 LPCWSTR lpszCurrentPath )
2428 FIXME("(%d,%s,%s,%s): stub\n",
2429 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2430 debugstr_w(lpszCurrentPath) );
2432 /* fHidden=1 - only visible for the calling app, read-only, not
2433 * enumerated with EnumFonts/EnumFontFamilies
2434 * lpszCurrentPath can be NULL
2437 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2438 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2440 SetLastError(ERROR_FILE_EXISTS);
2443 return FALSE; /* create failed */
2446 /*************************************************************************
2447 * GetKerningPairsA (GDI32.@)
2449 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2450 LPKERNINGPAIR kern_pairA )
2455 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2456 KERNINGPAIR *kern_pairW;
2458 if (!cPairs && kern_pairA)
2460 SetLastError(ERROR_INVALID_PARAMETER);
2464 charset = GetTextCharset(hDC);
2465 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2467 FIXME("Can't find codepage for charset %d\n", charset);
2470 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2471 * to fail on an invalid character for CP_SYMBOL.
2473 cpi.DefaultChar[0] = 0;
2474 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2476 FIXME("Can't find codepage %u info\n", csi.ciACP);
2479 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2481 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2482 if (!total_kern_pairs) return 0;
2484 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2485 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2487 for (i = 0; i < total_kern_pairs; i++)
2491 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2494 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2497 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2502 if (kern_pairs_copied >= cPairs) break;
2504 kern_pairA->wFirst = (BYTE)first;
2505 kern_pairA->wSecond = (BYTE)second;
2506 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2509 kern_pairs_copied++;
2512 HeapFree(GetProcessHeap(), 0, kern_pairW);
2514 return kern_pairs_copied;
2517 /*************************************************************************
2518 * GetKerningPairsW (GDI32.@)
2520 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2521 LPKERNINGPAIR lpKerningPairs )
2526 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2528 if (!cPairs && lpKerningPairs)
2530 SetLastError(ERROR_INVALID_PARAMETER);
2534 dc = get_dc_ptr(hDC);
2538 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2540 release_dc_ptr( dc );
2544 /*************************************************************************
2545 * TranslateCharsetInfo [GDI32.@]
2547 * Fills a CHARSETINFO structure for a character set, code page, or
2548 * font. This allows making the correspondence between different labels
2549 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2550 * of the same encoding.
2552 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2553 * only one codepage should be set in *lpSrc.
2556 * TRUE on success, FALSE on failure.
2559 BOOL WINAPI TranslateCharsetInfo(
2560 LPDWORD lpSrc, /* [in]
2561 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2562 if flags == TCI_SRCCHARSET: a character set value
2563 if flags == TCI_SRCCODEPAGE: a code page value
2565 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2566 DWORD flags /* [in] determines interpretation of lpSrc */)
2570 case TCI_SRCFONTSIG:
2571 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2573 case TCI_SRCCODEPAGE:
2574 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2576 case TCI_SRCCHARSET:
2577 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2582 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2583 *lpCs = FONT_tci[index];
2587 /*************************************************************************
2588 * GetFontLanguageInfo (GDI32.@)
2590 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2592 FONTSIGNATURE fontsig;
2593 static const DWORD GCP_DBCS_MASK=0x003F0000,
2594 GCP_DIACRITIC_MASK=0x00000000,
2595 FLI_GLYPHS_MASK=0x00000000,
2596 GCP_GLYPHSHAPE_MASK=0x00000040,
2597 GCP_KASHIDA_MASK=0x00000000,
2598 GCP_LIGATE_MASK=0x00000000,
2599 GCP_USEKERNING_MASK=0x00000000,
2600 GCP_REORDER_MASK=0x00000060;
2604 GetTextCharsetInfo( hdc, &fontsig, 0 );
2605 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2607 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2610 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2611 result|=GCP_DIACRITIC;
2613 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2616 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2617 result|=GCP_GLYPHSHAPE;
2619 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2620 result|=GCP_KASHIDA;
2622 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2625 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2626 result|=GCP_USEKERNING;
2628 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2629 if( GetTextAlign( hdc) & TA_RTLREADING )
2630 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2631 result|=GCP_REORDER;
2637 /*************************************************************************
2638 * GetFontData [GDI32.@]
2640 * Retrieve data for TrueType font.
2644 * success: Number of bytes returned
2645 * failure: GDI_ERROR
2649 * Calls SetLastError()
2652 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2653 LPVOID buffer, DWORD length)
2655 DC *dc = get_dc_ptr(hdc);
2656 DWORD ret = GDI_ERROR;
2658 if(!dc) return GDI_ERROR;
2661 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2663 release_dc_ptr( dc );
2667 /*************************************************************************
2668 * GetGlyphIndicesA [GDI32.@]
2670 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2671 LPWORD pgi, DWORD flags)
2677 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2678 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2680 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2681 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2682 HeapFree(GetProcessHeap(), 0, lpstrW);
2687 /*************************************************************************
2688 * GetGlyphIndicesW [GDI32.@]
2690 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2691 LPWORD pgi, DWORD flags)
2693 DC *dc = get_dc_ptr(hdc);
2694 DWORD ret = GDI_ERROR;
2696 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2697 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2699 if(!dc) return GDI_ERROR;
2702 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2704 release_dc_ptr( dc );
2708 /*************************************************************************
2709 * GetCharacterPlacementA [GDI32.@]
2711 * See GetCharacterPlacementW.
2714 * the web browser control of ie4 calls this with dwFlags=0
2717 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2718 INT nMaxExtent, GCP_RESULTSA *lpResults,
2723 GCP_RESULTSW resultsW;
2727 TRACE("%s, %d, %d, 0x%08x\n",
2728 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2730 /* both structs are equal in size */
2731 memcpy(&resultsW, lpResults, sizeof(resultsW));
2733 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2734 if(lpResults->lpOutString)
2735 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2737 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2739 lpResults->nGlyphs = resultsW.nGlyphs;
2740 lpResults->nMaxFit = resultsW.nMaxFit;
2742 if(lpResults->lpOutString) {
2743 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2744 lpResults->lpOutString, uCount, NULL, NULL );
2747 HeapFree(GetProcessHeap(), 0, lpStringW);
2748 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2753 /*************************************************************************
2754 * GetCharacterPlacementW [GDI32.@]
2756 * Retrieve information about a string. This includes the width, reordering,
2757 * Glyphing and so on.
2761 * The width and height of the string if successful, 0 if failed.
2765 * All flags except GCP_REORDER are not yet implemented.
2766 * Reordering is not 100% compliant to the Windows BiDi method.
2767 * Caret positioning is not yet implemented for BiDi.
2768 * Classes are not yet implemented.
2772 GetCharacterPlacementW(
2773 HDC hdc, /* [in] Device context for which the rendering is to be done */
2774 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2775 INT uCount, /* [in] Number of WORDS in string. */
2776 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2777 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2778 DWORD dwFlags /* [in] Flags specifying how to process the string */
2785 TRACE("%s, %d, %d, 0x%08x\n",
2786 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2788 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2789 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2790 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2791 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2792 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2794 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2795 if(lpResults->lpClass) FIXME("classes not implemented\n");
2796 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2797 FIXME("Caret positions for complex scripts not implemented\n");
2799 nSet = (UINT)uCount;
2800 if(nSet > lpResults->nGlyphs)
2801 nSet = lpResults->nGlyphs;
2803 /* return number of initialized fields */
2804 lpResults->nGlyphs = nSet;
2806 if((dwFlags&GCP_REORDER)==0 )
2808 /* Treat the case where no special handling was requested in a fastpath way */
2809 /* copy will do if the GCP_REORDER flag is not set */
2810 if(lpResults->lpOutString)
2811 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2813 if(lpResults->lpOrder)
2815 for(i = 0; i < nSet; i++)
2816 lpResults->lpOrder[i] = i;
2820 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2821 nSet, lpResults->lpOrder );
2824 /* FIXME: Will use the placement chars */
2825 if (lpResults->lpDx)
2828 for (i = 0; i < nSet; i++)
2830 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2831 lpResults->lpDx[i]= c;
2835 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2839 lpResults->lpCaretPos[0] = 0;
2840 for (i = 1; i < nSet; i++)
2841 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2842 lpResults->lpCaretPos[i] = (pos += size.cx);
2845 if(lpResults->lpGlyphs)
2846 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2848 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2849 ret = MAKELONG(size.cx, size.cy);
2854 /*************************************************************************
2855 * GetCharABCWidthsFloatA [GDI32.@]
2857 * See GetCharABCWidthsFloatW.
2859 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2861 INT i, wlen, count = (INT)(last - first + 1);
2866 if (count <= 0) return FALSE;
2868 str = HeapAlloc(GetProcessHeap(), 0, count);
2870 for(i = 0; i < count; i++)
2871 str[i] = (BYTE)(first + i);
2873 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2875 for (i = 0; i < wlen; i++)
2877 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2885 HeapFree( GetProcessHeap(), 0, str );
2886 HeapFree( GetProcessHeap(), 0, wstr );
2891 /*************************************************************************
2892 * GetCharABCWidthsFloatW [GDI32.@]
2894 * Retrieves widths of a range of characters.
2897 * hdc [I] Handle to device context.
2898 * first [I] First character in range to query.
2899 * last [I] Last character in range to query.
2900 * abcf [O] Array of LPABCFLOAT structures.
2907 * Only works with TrueType fonts. It also doesn't return real
2908 * floats but converted integers because it's implemented on
2909 * top of GetCharABCWidthsW.
2911 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2913 ABC *abc, *abc_base;
2914 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2917 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2919 abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2920 if (!abc) return FALSE;
2922 ret = GetCharABCWidthsW( hdc, first, last, abc );
2925 for (i = first; i <= last; i++, abc++, abcf++)
2927 abcf->abcfA = abc->abcA;
2928 abcf->abcfB = abc->abcB;
2929 abcf->abcfC = abc->abcC;
2932 HeapFree( GetProcessHeap(), 0, abc_base );
2936 /*************************************************************************
2937 * GetCharWidthFloatA [GDI32.@]
2939 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2940 UINT iLastChar, PFLOAT pxBuffer)
2942 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2946 /*************************************************************************
2947 * GetCharWidthFloatW [GDI32.@]
2949 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2950 UINT iLastChar, PFLOAT pxBuffer)
2952 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2957 /***********************************************************************
2959 * Font Resource API *
2961 ***********************************************************************/
2963 /***********************************************************************
2964 * AddFontResourceA (GDI32.@)
2966 INT WINAPI AddFontResourceA( LPCSTR str )
2968 return AddFontResourceExA( str, 0, NULL);
2971 /***********************************************************************
2972 * AddFontResourceW (GDI32.@)
2974 INT WINAPI AddFontResourceW( LPCWSTR str )
2976 return AddFontResourceExW(str, 0, NULL);
2980 /***********************************************************************
2981 * AddFontResourceExA (GDI32.@)
2983 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2985 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2986 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2989 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2990 ret = AddFontResourceExW(strW, fl, pdv);
2991 HeapFree(GetProcessHeap(), 0, strW);
2995 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
2997 HRSRC rsrc = FindResourceW(hModule, name, type);
2998 HGLOBAL hMem = LoadResource(hModule, rsrc);
2999 LPVOID *pMem = LockResource(hMem);
3000 int *num_total = (int *)lParam;
3003 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3004 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3006 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3010 *num_total += num_in_res;
3014 /***********************************************************************
3015 * AddFontResourceExW (GDI32.@)
3017 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3019 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3022 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3023 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3024 if (hModule != NULL)
3026 int num_resources = 0;
3027 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3029 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3030 wine_dbgstr_w(str));
3031 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3032 ret = num_resources;
3033 FreeLibrary(hModule);
3039 /***********************************************************************
3040 * RemoveFontResourceA (GDI32.@)
3042 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3044 return RemoveFontResourceExA(str, 0, 0);
3047 /***********************************************************************
3048 * RemoveFontResourceW (GDI32.@)
3050 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3052 return RemoveFontResourceExW(str, 0, 0);
3055 /***********************************************************************
3056 * AddFontMemResourceEx (GDI32.@)
3058 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3060 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3063 /***********************************************************************
3064 * RemoveFontMemResourceEx (GDI32.@)
3066 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3068 FIXME("(%p) stub\n", fh);
3072 /***********************************************************************
3073 * RemoveFontResourceExA (GDI32.@)
3075 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3077 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3078 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3081 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3082 ret = RemoveFontResourceExW(strW, fl, pdv);
3083 HeapFree(GetProcessHeap(), 0, strW);
3087 /***********************************************************************
3088 * RemoveFontResourceExW (GDI32.@)
3090 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3092 return WineEngRemoveFontResourceEx(str, fl, pdv);
3095 /***********************************************************************
3096 * GetTextCharset (GDI32.@)
3098 UINT WINAPI GetTextCharset(HDC hdc)
3100 /* MSDN docs say this is equivalent */
3101 return GetTextCharsetInfo(hdc, NULL, 0);
3104 /***********************************************************************
3105 * GetTextCharsetInfo (GDI32.@)
3107 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3109 UINT ret = DEFAULT_CHARSET;
3110 DC *dc = get_dc_ptr(hdc);
3115 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3117 release_dc_ptr( dc );
3120 if (ret == DEFAULT_CHARSET && fs)
3121 memset(fs, 0, sizeof(FONTSIGNATURE));
3125 /***********************************************************************
3126 * GdiGetCharDimensions (GDI32.@)
3128 * Gets the average width of the characters in the English alphabet.
3131 * hdc [I] Handle to the device context to measure on.
3132 * lptm [O] Pointer to memory to store the text metrics into.
3133 * height [O] On exit, the maximum height of characters in the English alphabet.
3136 * The average width of characters in the English alphabet.
3139 * This function is used by the dialog manager to get the size of a dialog
3140 * unit. It should also be used by other pieces of code that need to know
3141 * the size of a dialog unit in logical units without having access to the
3142 * window handle of the dialog.
3143 * Windows caches the font metrics from this function, but we don't and
3144 * there doesn't appear to be an immediate advantage to do so.
3147 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3149 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3152 static const WCHAR alphabet[] = {
3153 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3154 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3155 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3157 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3159 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3161 if (height) *height = sz.cy;
3162 return (sz.cx / 26 + 1) / 2;
3165 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3167 FIXME("(%d): stub\n", fEnableEUDC);
3171 /***********************************************************************
3172 * GetCharWidthI (GDI32.@)
3174 * Retrieve widths of characters.
3177 * hdc [I] Handle to a device context.
3178 * first [I] First glyph in range to query.
3179 * count [I] Number of glyph indices to query.
3180 * glyphs [I] Array of glyphs to query.
3181 * buffer [O] Buffer to receive character widths.
3184 * Only works with TrueType fonts.
3190 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3195 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3197 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3200 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3202 HeapFree(GetProcessHeap(), 0, abc);
3206 for (i = 0; i < count; i++)
3207 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3209 HeapFree(GetProcessHeap(), 0, abc);
3213 /***********************************************************************
3214 * GetFontUnicodeRanges (GDI32.@)
3216 * Retrieve a list of supported Unicode characters in a font.
3219 * hdc [I] Handle to a device context.
3220 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3223 * Success: Number of bytes written to the buffer pointed to by lpgs.
3227 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3230 DC *dc = get_dc_ptr(hdc);
3232 TRACE("(%p, %p)\n", hdc, lpgs);
3236 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3242 /*************************************************************
3243 * FontIsLinked (GDI32.@)
3245 BOOL WINAPI FontIsLinked(HDC hdc)
3247 DC *dc = get_dc_ptr(hdc);
3250 if (!dc) return FALSE;
3251 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3253 TRACE("returning %d\n", ret);
3257 /*************************************************************
3258 * GdiRealizationInfo (GDI32.@)
3260 * Returns a structure that contains some font information.
3262 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3264 DC *dc = get_dc_ptr(hdc);
3267 if (!dc) return FALSE;
3268 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);